New upstream version 7.0.2

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
This commit is contained in:
nyanmisaka
2024-08-03 18:31:39 +08:00
parent bc8d6d51bf
commit 8b6e13f596
3232 changed files with 222247 additions and 99227 deletions
+411 -179
View File
@@ -1,185 +1,417 @@
Entries are sorted chronologically from oldest to youngest within each release, Entries are sorted chronologically from oldest to youngest within each release,
releases are sorted from youngest to oldest. releases are sorted from youngest to oldest.
version 6.0.1: version 7.0.2:
avcodec/4xm: Check for cfrm exhaustion avcodec/snow: Fix off by 1 error in run_buffer
avformat/mov: Disallow FTYP after streams avcodec/utils: apply the same alignment to YUV410 as we do to YUV420 for snow
doc/html: fix styling issue with Texinfo 7.0 avformat/iamf_parse: Check for 0 samples
doc/html: support texinfo 7.0 swscale: [loongarch] Fix checkasm-sw_yuv2rgb failure.
Changelog: update avcodec/aacps_tablegen_template: don't redefine CONFIG_HARDCODED_TABLES
avformat/lafdec: Check for 0 parameters avutil/hwcontext_vaapi: use the correct type for VASurfaceAttribExternalBuffers.buffers
avformat/lafdec: Check for 0 parameters avcodec/pcm-bluray/dvd: Use correct pointer types on BE
avfilter/buffersink: fix order of operation with = and <0 avcodec/pngenc: fix sBIT writing for indexed-color PNGs
avfilter/framesync: fix order of operation with = and <0 avcodec/pngdec: use 8-bit sBIT cap for indexed PNGs per spec
tools/target_dec_fuzzer: Adjust threshold for CSCD avformat/mov: check that child boxes of trak are only present inside it
avcodec/dovi_rpu: Use 64 bit in get_us/se_coeff() avformat/mov: check that sample and chunk count is 1 for HEIF
avformat/mov: Check that is_still_picture_avif has no trak based streams avcodec/videotoolboxenc: Fix bitrate doesn't work as expected
avformat/matroskadec: Fix declaration-after-statement warnings avdevice/dshow: Don't skip audio devices if no video device is present
Update for FFmpeg 6.0.1 avcodec/hdrenc: Allocate more space
fftools/ffmpeg_mux_init: Restrict disabling automatic copying of metadata avcodec/cfhdenc: Height of 16 is not supported
avformat/rtsp: Use rtsp_st->stream_index avcodec/cfhdenc: Allocate more space
avformat/rtsp: Use rtsp_st->stream_index avcodec/osq: fix integer overflow when applying factor
avutil/tx_template: fix integer ovberflwo in fft3() avcodec/osq: avoid using too large numbers for shifts and integers in update_residue_parameter()
avcodec/jpeg2000dec: Check image offset avcodec/vaapi_encode: Check hwctx
avformat/mxfdec: Check klv offset avcodec/proresdec: Consider negative bits left
libavutil/ppc/cpu.c: check that AT_HWCAP2 is defined avcodec/alsdec: Clear shift_value
avcodec/h2645_parse: Avoid EAGAIN avcodec/hevc/hevcdec: Do not allow slices to depend on failed slices
avcodec/xvididct: Make c* unsigned to avoid undefined overflows avformat/mov: add an EOF check in IPRP
avcodec/bonk: Fix undefined overflow in predictor_calc_error() avfilter/vf_xfade: Check ff_inlink_consume_frame() for failure
avformat/tmv: Check video chunk size avutil/slicethread: Check pthread_*_init() for failure
avcodec/h264_parser: saturate dts a bit avutil/frame: Check log2_crop_align
avformat/asfdec_f: Saturate presentation time in marker avutil/buffer: Check ff_mutex_init() for failure
avformat/xwma: sanity check bits_per_coded_sample avformat/xmv: Check this_packet_size
avformat/matroskadec: Check prebuffered_ns for overflow avformat/webpenc: Check filesize in trailer
avformat/wavdec: Check left avio_tell for overflow avformat/ty: rec_size seems to only need 32bit
avformat/tta: Better totalframes check avformat/tty: Check avio_size()
avformat/rpl: Check for number_of_chunks overflow avformat/siff: Basic pkt_size check
avformat/mov: compute absolute dts difference without overflow in mov_find_next_sample() avformat/sauce: Check avio_size() for failure
avformat/jacosubdec: Check timeres avformat/sapdec: Check ffurl_get_file_handle() for error
avformat/jacosubdec: avoid signed integer overflows in get_shift() avformat/nsvdec: Check asize for PCM
avformat/jacosubdec: Factorize code in get_shift() a bit avformat/mp3dec: Check header_filesize
avformat/sbgdec: Check for negative duration or un-representable end pts avformat/mp3dec; Check for avio_size() failure
avcodec/escape124: Do not return random numbers avformat/mov: Use 64bit for str_size
avcodec/apedec: Fix an integer overflow in predictor_update_filter() avformat/mm: Check length
tools/target_dec_fuzzer: Adjust wmapro threshold avformat/hnm: Check *chunk_size
avcodec/wavarc: Allocate AV_INPUT_BUFFER_PADDING_SIZE avformat/hlsenc: Check ret
avcodec/wavarc: Fix integer overflwo in do_stereo() avformat/bintext: Check avio_size() return
avutil/tx_template: Fix some signed integer overflows in DECL_FFT5() avformat/asfdec_o: Check size of index object
avcodec/aacdec_template: Better avoidance of signed integer overflow in imdct_and_windowing_eld() avfilter/vf_scale: Check ff_scale_adjust_dimensions() for failure
tools/target_dec_fuzzer: Adjust threshold for MVHA avfilter/scale_eval: Use 64bit, check values in ff_scale_adjust_dimensions()
avformat/avs: Check if return code is representable avfilter/vf_lut3d: Check av_scanf()
avcodec/flacdec: Fix integer overflow in "33bit" DECODER_SUBFRAME_FIXED_WIDE() avfilter/vf_elbg: Use unsigned for shifting into the top bit
avcodec/flacdec: Fix overflow in "33bit" decorrelate avfilter/vf_premultiply: Use AV_PIX_MAX_PLANES
avcodec/lcldec: Make PNG filter addressing match the code afterwards avfilter/vf_deshake_opencl: Ensure that the first iteration initializes the best variables
avformat/westwood_vqa: Check chunk size avformat/iamf_parse: Check for negative sample sizes
avformat/sbgdec: Check for period overflow swscale/output: Fix integer overflows in yuv2rgba64_X_c_template
avformat/concatdec: Check in/outpoint for overflow avformat/mxfdec: Reorder elements of expression in bisect loop
avformat/mov: Check avif_info avutil/timecode: Use a 64bit framenum internally
avformat/mxfdec: Remove this_partition avcodec/pnmdec: Use 64bit for input size check
avcodec/xvididct: Fix integer overflow in idct_row() avformat/mov: Check extradata in mov_read_iacb()
avcodec/celp_math: avoid overflow in shift avcodec/mpeg12enc: Use av_rescale() in vbv_buffer_size computation
tools/target_dec_fuzzer: Adjust threshold for rtv1 avcodec/utvideoenc: Use unsigned shift to build flags
avformat/hls: reduce default max reload to 3 avcodec/j2kenc: Merge dwt_norm into lambda
avformat/format: Stop reading data at EOF during probing avcodec/vc2enc: Fix overflows with storing large values
avcodec/bonk: Fix integer overflow in predictor_calc_error() avcodec/mpegvideo_enc: Do not duplicate pictures on shifting
avcodec/jpeg2000dec: jpeg2000 has its own lowres option avdevice/dshow_capture: Fix error handling in ff_dshow_##prefix##_Create()
avcodec/huffyuvdec: avoid undefined behavior with get_vlc2() failure avcodec/tiff: Check value on positive signed targets
avcodec/cscd: Fix "CamStudio Lossless Codec 1.0" gzip files avfilter/vf_convolution_opencl: Assert that the filter name is one of the filters
avcodec/cscd: Check for CamStudio Lossless Codec 1.0 behavior in end check of LZO files avfilter/vf_bm3d: Dont round MSE2SSE to an integer
avcodec/mpeg4videodec: consider lowres in dest_pcm[] avdevice/dshow: Remove NULL check on pin
avcodec/hevcdec: Fix undefined memcpy() avdevice/dshow: check ff_dshow_pin_ConnectionMediaType() for failure
avcodec/mpeg4videodec: more unsigned in amv computation avdevice/dshow: Check device_filter_unique_name before use
avcodec/tta: fix signed overflow in decorrelate avdevice/dshow: Cleanup also on av_log case
avcodec/apedec: remove unused variable avdevice/dshow_filter: Use wcscpy_s()
avcodec/apedec: Fix 48khz 24bit below insane level avcodec/flac_parser: Assert that we do not overrun the link_penalty array
avcodec/apedec: Fix CRC for 24bps and bigendian avcodec/osq: avoid signed overflow in downsample path
avcodec/wavarc: Check that nb_samples is not negative avcodec/pixlet: Simplify pfx computation
avcodec/wavarc: Check shift avcodec/motion_est: Fix score squaring overflow
avcodec/xvididct: Fix integer overflow in idct_row() avcodec/mlpenc: Use 64 for ml, mr
avformat/avr: Check sample rate avcodec/loco: Check loco_get_rice() for failure
avformat/imf_cpl: Replace NULL content_title_utf8 by "" avcodec/loco: check get_ur_golomb_jpegls() for failure
avformat/imf_cpl: xmlNodeListGetString() can return NULL avcodec/leaddec: Check init_get_bits8() for failure
avcodec/aacdec_template: Fix undefined signed interger operations avcodec/imm4: check cbphi for error
avcodec/wavarc: Fix k limit avcodec/iff: Use signed count
avcodec/rka: Fix integer overflow in decode_filter() avcodec/golomb: Assert that k is in the supported range for get_ur/sr_golomb()
avformat/rka: bps < 8 is invalid avcodec/golomb: Document return for get_ur_golomb_jpegls() and get_sr_golomb_flac()
avcodec/pcm: allow Changing parameters avcodec/dxv: Fix type in get_opcodes()
avutil/tx_template: extend to 2M avcodec/cri: Check length
avcodec/jpeg2000dec: Check for reduction factor and image offset avcodec/xsubdec: Check parse_timecode()
avutil/softfloat: Basic documentation for av_sincos_sf() avutil/imgutils: av_image_check_size2() ensure width and height fit in 32bit
avutil/softfloat: fix av_sincos_sf() avfilter/vf_tiltandshift: Free dst on error
tools/target_dec_fuzzer: Adjust threshold for speex doc/examples/mux: remove nop
avcodec/utils: fix 2 integer overflows in get_audio_frame_duration() avcodec/proresenc_kostya: use unsigned alpha for rotation
avcodec/hevcdec: Avoid null pointer dereferences in MC avformat/rtpenc_rfc4175: Use 64bit in computation if copy_offset
avcodec/takdsp: Fix integer overflows avformat/rtmpproto: Use AV_DICT_MATCH_CASE instead of litteral number
avcodec/mpegvideo_dec: consider interlaced lowres 4:2:0 chroma in edge emulation check better avformat/rtmppkt: Simplify and deobfuscate amf_tag_skip() slightly
avcodec/rka: use unsigned for buf0 additions avformat/rmdec: use 64bit for audio_framesize checks
avcodec/rka: Avoid undefined left shift avutil/wchar_filename: Correct sizeof
avcodec: Ignoring errors is only possible before the input end avutil/hwcontext_d3d11va: correct sizeof IDirect3DSurface9
avformat/jpegxl_probe: Forward error codes avutil/hwcontext_d3d11va: Free AVD3D11FrameDescriptor on error
avformat/jpegxl_probe: check length instead of blindly reading avutil/hwcontext_d3d11va: correct sizeof AVD3D11FrameDescriptor
avformat/jpegxl_probe: Remove intermediate macro obfuscation around get_bits*() avcodec/vvc/refs: Use unsigned mask
avcodec/noise_bsf: Check for wrapped frames doc/examples/vaapi_encode: Try to check fwrite() for failure
avformat/oggparsetheora: clip duration within 64bit avformat/usmdec: Initialize value
avcodec/rka: avoid undefined multiply in cmode==0 avformat/tls_schannel: Initialize ret
avcodec/rka: use 64bit for srate_pad computation avformat/subfile: Assert that whence is a known case
avcodec/bonk: Avoid undefined integer overflow in predictor_calc_error() avformat/subfile: Merge if into switch()
avformat/wavdec: Check that smv block fits in available space avformat/rtsp: Check that lower transport is handled in one of the if()
avcodec/adpcm: Fix integer overflow in intermediate in ADPCM_XMD avformat/rtsp: initialize reply1
avcodec/dpcm: fix undefined interger overflow in wady avformat/rtsp: use < 0 for error check
avcodec/tiff: add a zero DNG_LINEARIZATION_TABLE check avformat/rtpenc_vc2hq: Check sizes
avcodec/tak: Check remaining bits in ff_tak_decode_frame_header() avfilter/af_aderivative: Free out on error
avcodec/sonic: Fix two undefined integer overflows swscale/swscale: Use ptrdiff_t for linesize computations
avcodec/utils: the IFF_ILBM implementation assumes that there are a multiple of 16 allocated avfilter/af_amerge: Cleanup on av_channel_layout_copy() failure
avcodec/flacdec: Fix signed integre overflow avfilter/af_afir: Assert format
avcodec/exr: Cleanup befor return avfilter/af_afftdn: Assert format
avcodec/pngdec: Do not pass AVFrame into global header decode avfilter/af_pan: check nb_output_channels before use
avcodec/pngdec: remove AVFrame argument from decode_iccp_chunk() cbs_av1: Reject thirty-two zero bits in uvlc code
avcodec/wavarc: Check order before using it to write the list avfilter/af_mcompand: compute half frequency in double
avcodec/bonk: decode multiple passes in intlist_read() at once avfilter/af_channelsplit: Assert that av_channel_layout_channel_from_index() succeeds
avcodec/vorbisdec: Check codebook float values to be finite avfilter/af_aresample: Cleanup on av_channel_layout_copy() failure
avcodec/g2meet: Replace fake allocation avoidance for framebuf tools/coverity: Phase 1 study of anti-halicogenic for coverity av_rescale()
avutil/tx_priv: Use unsigned in BF() to avoid signed overflows avfilter/vf_avgblur: Check plane instead of AVFrame
avcodec/lcldec: More space for rgb24 avfilter/drawutils: Fix depthb computation
avcodec/lcldec: Support 4:1:1 and 4:2:2 with odd width avfilter/avf_showcwt: Check av_parse_video_rate() for failure
libavcodec/lcldec: width and height should not be unsigned avformat/rdt: Check pkt_len
avformat/imf: fix invalid resource handling avformat/mpeg: Check len in mpegps_probe()
avcodec/escape124: Check that blocks are allocated before use avformat/mxfenc: resurrects the error print
avcodec/rka: Fix signed integer overflow in decode_filter() avdevice/dshow: Check ICaptureGraphBuilder2_SetFiltergraph() for failure
avcodec/huffyuvdec: Fix undefined behavior with shift avcodec/mfenc: check IMFSample_ConvertToContiguousBuffer() for failure
avcodec/j2kenc: Replace RGB24 special case by generic test avcodec/vc1_loopfilter: Factor duplicate code in vc1_b_h_intfi_loop_filter()
avcodec/j2kenc: Replace BGR48 / GRAY16 test by test for number of bits avcodec/vvc/ctu: Remove dead ret check
avcodec/j2kenc: simplify pixel format setup avcodec/vvc/dec: Remove constant eos_at_start
avcodec/j2kenc: Fix funky bpno errors on decoding avformat/img2dec: assert no pipe on ts_from_file
avcodec/j2kenc: remove misleading pred value avcodec/cbs_jpeg: Try to move the read entity to one side in a test
avcodec/j2kenc: fix 5/3 DWT identifer fftools/ffplay: Check vulkan_params
avcodec/vp3: Check width to avoid assertion failure fftools/ffmpeg_enc: Initialize Decoder
avcodec/g729postfilter: Limit shift in long term filter fftools/ffmpeg_enc: Initialize fd
avcodec/wavarc: Fix several integer overflows fftools/ffmpeg_enc: simplify opaque_ref check
avcodec/tests/snowenc: Fix 2nd test avformat/mov: Check edit list for overflow
avcodec/tests/snowenc: return a failure if DWT/IDWT mismatches fftools/ffmpeg: Check read() for failure
avcodec/snowenc: Fix visual weight calculation avcodec/vvc/dec: Check ff_init_cabac_decoder() for failure
avcodec/tests/snowenc: unbreak DWT tests MAINTAINERS: Add Timo Rothenpieler to server admins
avcodec/mpeg12dec: Check input size swscale/output: Avoid undefined overflow in yuv2rgb_write_full()
avcodec/escape124: Fix some return codes swscale/output: alpha can become negative after scaling, use multiply
avcodec/escape124: fix signdness of end of input check avcodec/targaenc: Allocate space for the palette
Use https for repository links avcodec/r210enc: Use av_rescale for bitrate
avcodec/nvdec_hevc: fail to initialize on unsupported profiles avcodec/jfdctint_template: Fewer integer anomalies
fftools/ffmpeg_enc: apply -top to individual encoded frames avcodec/snowenc: MV limits due to mv_penalty table size
avcodec/on2avc: use correct fft sizes tools/target_dec_fuzzer: Adjust threshold for MV30
avcodec/on2avc: use the matching AVTX context for the 512 sized iMDCT tools/target_dec_fuzzer: Adjust threshold for jpeg2000
examples: fix build of mux and resample_audio avformat/mxfdec: Check container_ul->desc before use
avcodec/nvenc: stop using deprecated rc modes with SDK 12.1 avcodec/libvpxenc: Cleanup on error
configure: use non-deprecated nvenc GUID for conftest MAINTAINERS: Update the entries for the release maintainer for FFmpeg
avcodec/x86/mathops: clip constants used with shift instructions within inline assembly doc/developer: Provide information about git send-email and gmail
avfilter/vsrc_ddagrab: calculate pointer position on rotated screens avfilter/vf_rotate: Check ff_draw_init2() return value
avfilter/vsrc_ddagrab: account for mouse-only frames during probing avformat/mov: Use int64_t in intermediate for corrected_dts
avcodec/aac_ac3_parser: add preprocessor checks for codec specific code avformat/mov: Use 64bit in intermediate for current_dts
avcodec/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE avformat/matroskadec: Assert that num_levels is non negative
Revert "lavc/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE" avformat/libzmq: Check av_strstart()
Revert "avcodec/nvenc: fix b-frame DTS behavior with fractional framerates" avformat/img2dec: Little JFIF / Exif cleanup
avcodec/vdpau_mpeg4: fix order of quant matrix coefficients avformat/img2dec: Move DQT after unrelated if()
avcodec/vdpau_mpeg12: fix order of quant matrix coefficients avformat/imfdec: Simplify get_next_track_with_minimum_timestamp()
avcodec/nvdec_mpeg4: fix order of quant matrix coefficients avdevice/xcbgrab: Check sscanf() return
avcodec/nvdec_mpeg2: fix order of quant matrix coefficients fftools/cmdutils: Add protective () to FLAGS
fftools/ffmpeg_filter: fix leak of AVIOContext in read_binary() avformat/sdp: Check before appending ","
fftools/ffmpeg: avoid possible invalid reads with short -tag values avcodec/libx264: Check init_get_bits8() return code
avcodec/mp_cmp: reject invalid comparison function values avcodec/ilbcdec: Remove dead code
avcodec/aacpsy: clip global_quality within the psy_vbr_map array boundaries avcodec/vp8: Check cond init
avutil/wchar_filename: propagate MultiByteToWideChar() and WideCharToMultiByte() failures avcodec/vp8: Check mutex init
avformat/concatf: check if any nodes were allocated avcodec/proresenc_anatoliy: Assert that AV_PROFILE_UNKNOWN is replaced
avcodec/nvenc: fix b-frame DTS behavior with fractional framerates avcodec/pcm-dvdenc: 64bit pkt-size
avcodec/vorbisdec: export skip_samples instead of dropping frames avcodec/notchlc: Check init_get_bits8() for failure
fftools/ffmpeg_mux_init: avoid invalid reads in forced keyframe parsing avcodec/tests/dct: Use 64bit in intermediate for error computation
lavfi/vf_vpp_qsv: set the right timestamp for AVERROR_EOF avcodec/scpr3: Check add_dec() for failure
avfilter/vf_untile: swap the chroma shift values used for plane offsets avcodec/rv34: assert that size is not 0 in rv34_gen_vlc_ext()
lavc/decode: stop mangling last_pkt_props->opaque avcodec/wavpackenc: Use unsigned for potential 31bit shift
avcodec/nvenc: avoid failing b_ref_mode check when unset avcodec/vvc/mvs: Initialize mvf
lavu/vulkan: fix handle type for 32-bit targets avcodec/tests/jpeg2000dwt: Use 64bit in comparission
vulkan: Fix win/i386 calling convention avcodec/tests/jpeg2000dwt: Use 64bit in err2 computation
avfilter/graphparser: fix filter instance name when an id is provided avformat/fwse: Remove always false expression
avcodec/aacps_tablegen: fix build error after avutil bump avcodec/sga: Make it clear that the return is intentionally not checked
avcodec/nvenc: fix potential NULL pointer dereference avformat/asfdec_f: Use 64bit for preroll computation
avformat/argo_asf: Use 64bit in offset intermediate
avformat/ape: Use 64bit for final frame size
avformat/ac4dec: Check remaining space in ac4_probe()
avdevice/pulse_audio_enc: Use av_rescale() to avoid integer overflow
avcodec/vlc: Cleanup on multi table alloc failure in ff_vlc_init_multi_from_lengths()
avcodec/tiff: Assert init_get_bits8() success in unpack_gray()
avcodec/tiff: Assert init_get_bits8() success in horizontal_fill()
tools/decode_simple: Check avcodec_send_packet() for errors on flushing
swscale/yuv2rgb: Use 64bit for brightness computation
swscale/x86/swscale: use a clearer name for INPUT_PLANER_RGB_A_FUNC_CASE
avutil/tests/opt: Check av_set_options_string() for failure
avutil/tests/dict: Check av_dict_set() before get for failure
avdevice/dshow: fix badly indented line
avformat/demux: resurrect dead stores
avcodec/tests/bitstream_template: Assert bits_init8() return
tools/enc_recon_frame_test: Assert that av_image_get_linesize() succeeds
avformat/iamf_writer: disallow Opus extradata with mapping family other than 0
avformat/iamf_parse: sanitize audio_roll_distance values
avformat/iamf: byteswap values in OpusHeader
avformat/iamf: rename Codec Config seek_preroll to audio_roll_distance
avformat/iamf_writer: fix coded audio_roll_distance values
avformat/iamf_writer: fix PCM endian-ness flag
avformat/movenc: fix channel count and samplerate fields for IAMF tracks
avformat/iamf_parse: keep substream count consistent
avformat/iamf_parse: add missing padding to AAC extradata
avformat/iamf_parse: 0 layers are not allowed
avformat/iamf_parse: consider nb_substreams when accessing substreams array
avformat/iamf_parse: Remove dead case
avcodec/png: more informative error message for invalid sBIT size
avcodec/pngdec: avoid erroring with sBIT on indexed-color images
avfilter/vf_tiltandshift: fix buffer offset for yuv422p input
avutil/timestamp: avoid possible FPE when 0 is passed to av_ts_make_time_string2()
avformat/mov: add more checks for infe atom size
avformat/mov: check for EOF inside the infe list parsing loop
avformat/mov: check extent_offset calculation for overflow
avformat/mov: check that iloc offset values fit on an int64_t
avcodec/pngenc: fix mDCv typo
avcodec/pngdec: fix mDCv typo
avcodec/nvenc: fix segfault in intra-only mode
avdevice/avfoundation: add external video devices
aarch64: Add OpenBSD runtime detection of dotprod and i8mm using sysctl
fftools/ffplay_renderer: use correct NULL value for Vulkan type
qsv: Initialize impl_value
avutil/hwcontext_qsv: fix GCC 14.1 warnings
avcodec/mediacodecenc: workaround the alignment requirement for H.265
avcodec/mediacodecenc: workaround the alignment requirement only for H.264
lavc/lpc: fix off-by-one in R-V V compute_autocorr
lavc/vp9: reset segmentation fields when segmentation isn't enabled
configure: enable ffnvcodec, nvenc, nvdec for FreeBSD
lavc/sbrdsp: fix potential overflow in noise table
version 7.0.1:
lavc/flacdsp: do not assume maximum R-V VL
avformat/flacdec: Reorder allocations to avoid leak on error
avcodec/adts_parser: Don't presume buffer to be padded
avformat/movenc: Check av_malloc()
avcodec/vp8: Return error on error
avformat/mov: store sample_sizes as unsigned ints
avformat/vvc: fix parsing sps_subpic_id
avformat/vvc: initialize some ptl flags
avcodec/mscc & mwsc: Check loop counts before use
avcodec/mpegvideo_enc: Fix potential overflow in RD
avcodec/mpeg4videodec: assert impossible wrap points
avcodec/mpeg12dec: Use 64bit in bit computation
avcodec/vqcdec: Check init_get_bits8() for failure
avcodec/vvc/dec: Check init_get_bits8() for failure
avcodec/vble: Check av_image_get_buffer_size() for failure
avcodec/vp3: Replace check by assert
avcodec/vp8: Forward return of ff_vpx_init_range_decoder()
avcodec/jpeg2000dec: remove ST=3 case
avcodec/qsvdec: Check av_image_get_buffer_size() for failure
avcodec/exr: Fix preview overflow
avcodec/decode: decode_simple_internal() only implements audio and video
avcodec/fmvc: remove dead assignment
avcodec/h2645_sei: Remove dead checks
avcodec/h264_slice: Remove dead sps check
avcodec/lpc: copy levenson coeffs only when they have been computed
avutil/tests/base64: Check with too short output array
libavutil/base64: Try not to write over the array end
avcodec/cbs_av1: Avoid shift overflow
fftools/ffplay: Check return of swr_alloc_set_opts2()
tools/opt_common: Check for malloc failure
doc/examples/demux_decode: Simplify loop
avformat/concatdec: Check file
avcodec/mpegvideo_enc: Fix 1 line and one column images
avcodec/amrwbdec: assert mode to be valid in decode_fixed_vector()
avcodec/wavarc: fix integer overflow in decode_5elp() block type 2
swscale/output: Fix integer overflow in yuv2rgba64_full_1_c_template()
swscale/output: Fix integer overflow in yuv2rgba64_1_c_template
avcodec/av1dec: Change bit_depth to int
avcodec/av1dec: bit_depth cannot be another values than 8,10,12
avcodec/avs3_parser: assert the return value of init_get_bits()
avcodec/avs2_parser: Assert init_get_bits8() success with const size 15
avfilter/avfiltergraph: return value of ff_request_frame() is unused
avformat/mxfdec: Check body_offset
avformat/kvag: Check sample_rate
avcodec/atrac9dec: Check init_get_bits8() for failure
avcodec/ac3_parser: Check init_get_bits8() for failure
avcodec/pngdec: Check last AVFrame before deref
avcodec/hevcdec: Check ref frame
doc/examples/qsv_transcode: Initialize pointer before free
doc/examples/qsv_transcode: Simplify str_to_dict() loop
doc/examples/vaapi_transcode: Simplify loop
doc/examples/qsv_transcode: Simplify loop
avcodec/cbs_h2645: Check NAL space
avfilter/vf_thumbnail_cuda: Set ret before checking it
avfilter/signature_lookup: Dont copy uninitialized stuff around
avfilter/signature_lookup: Fix 2 differences to the refernce SW
avcodec/x86/vp3dsp_init: Set correct function pointer, fix crash
avformat/mp3dec: change bogus error message if read_header encounters EOF
avformat/mp3dec: simplify inner frame size check in mp3_read_header
avformat/mp3dec: only call ffio_ensure_seekback once
avcodec/cbs_h266: read vps_ptl_max_tid before using it
avcodec/cbs_h266: fix sh_collocated_from_l0_flag and sh_collocated_ref_idx infer
avformat/vvc: fix parsing some early VPS bitstream values
avformat/vvc: fix writing general_constraint_info bytes
avutil/ppc/cpu: Also use the machdep.altivec sysctl on NetBSD
lavd/v4l2: Use proper field type for second parameter of ioctl() with BSD's
vulkan_av1: Fix force_integer_mv value
vaapi_av1: Fix force_integer_mv value
av1dec: Add force_integer_mv derived field for decoder use
avutil/iamf: fix offsets for mix_gain options
avformat/iamfdec: check nb_streams in header read
avformat/mov: free the infe allocated item data on failure
avformat/iamf_writer: reject duplicated stream ids in a stream group
avformat/mov: don't read key_size bytes twice in the keys atom
avformat/mov: take into account the first eight bytes in the keys atom
avformat/mov: fix the check for the heif item parsing loop
avutil/iamf: fix mix_gain_class name
av1dec: Fix RefFrameSignBias calculation
avcodec/codec_par: always clear extradata_size in avcodec_parameters_to_context()
avcodec/mediacodecenc: Fix return empty packet when bsf is used
avcodec/hevcdec: Fix precedence, bogus film grain warning
avcodec/hevcdec: fix segfault on invalid film grain metadata
lavc/vvc: Skip enhancement layer NAL units
avformat/mov: ignore old infe box versions
vulkan_av1: add workaround for NVIDIA drivers tested on broken CTS
lavc/vulkan_av1: Use av1dec reference order hint information
lavc/av1: Record reference ordering information for each frame
doc/encoders: add missing libxvid option
doc/encoders: remove non-existent flag
fate/ffmpeg: Avoid dependency on samples
avcodec/wavpack: Remove always-false check
avcodec/wavpack: Fix leak and segfault on reallocation error
avcodec/lossless_videoencdsp: Don't presume alignment in diff_bytes
avcodec/ppc/h264dsp: Fix left shifts of negative numbers
version 7.0:
- DXV DXT1 encoder
- LEAD MCMP decoder
- EVC decoding using external library libxevd
- EVC encoding using external library libxeve
- QOA decoder and demuxer
- aap filter
- demuxing, decoding, filtering, encoding, and muxing in the
ffmpeg CLI now all run in parallel
- enable gdigrab device to grab a window using the hwnd=HANDLER syntax
- IAMF raw demuxer and muxer
- D3D12VA hardware accelerated H264, HEVC, VP9, AV1, MPEG-2 and VC1 decoding
- tiltandshift filter
- qrencode filter and qrencodesrc source
- quirc filter
- lavu/eval: introduce randomi() function in expressions
- VVC decoder (experimental)
- fsync filter
- Raw Captions with Time (RCWT) closed caption muxer
- ffmpeg CLI -bsf option may now be used for input as well as output
- ffmpeg CLI options may now be used as -/opt <path>, which is equivalent
to -opt <contents of file <path>>
- showinfo bitstream filter
- a C11-compliant compiler is now required; note that this requirement
will be bumped to C17 in the near future, so consider updating your
build environment if it lacks C17 support
- Change the default bitrate control method from VBR to CQP for QSV encoders.
- removed deprecated ffmpeg CLI options -psnr and -map_channel
- DVD-Video demuxer, powered by libdvdnav and libdvdread
- ffprobe -show_stream_groups option
- ffprobe (with -export_side_data film_grain) now prints film grain metadata
- AEA muxer
- ffmpeg CLI loopback decoders
- Support PacketTypeMetadata of PacketType in enhanced flv format
- ffplay with hwaccel decoding support (depends on vulkan renderer via libplacebo)
- dnn filter libtorch backend
- Android content URIs protocol
- AOMedia Film Grain Synthesis 1 (AFGS1)
- RISC-V optimizations for AAC, FLAC, JPEG-2000, LPC, RV4.0, SVQ, VC1, VP8, and more
- Loongarch optimizations for HEVC decoding
- Important AArch64 optimizations for HEVC
- IAMF support inside MP4/ISOBMFF
- Support for HEIF/AVIF still images and tiled still images
- Dolby Vision profile 10 support in AV1
- Support for Ambient Viewing Environment metadata in MP4/ISOBMFF
- HDR10 metadata passthrough when encoding with libx264, libx265, and libsvtav1
version 6.1:
- libaribcaption decoder
- Playdate video decoder and demuxer
- Extend VAAPI support for libva-win32 on Windows
- afireqsrc audio source filter
- arls filter
- ffmpeg CLI new option: -readrate_initial_burst
- zoneplate video source filter
- command support in the setpts and asetpts filters
- Vulkan decode hwaccel, supporting H264, HEVC and AV1
- color_vulkan filter
- bwdif_vulkan filter
- nlmeans_vulkan filter
- RivaTuner video decoder
- xfade_vulkan filter
- vMix video decoder
- Essential Video Coding parser, muxer and demuxer
- Essential Video Coding frame merge bsf
- bwdif_cuda filter
- Microsoft RLE video encoder
- Raw AC-4 muxer and demuxer
- Raw VVC bitstream parser, muxer and demuxer
- Bitstream filter for editing metadata in VVC streams
- Bitstream filter for converting VVC from MP4 to Annex B
- scale_vt filter for videotoolbox
- transpose_vt filter for videotoolbox
- support for the P_SKIP hinting to speed up libx264 encoding
- Support HEVC,VP9,AV1 codec in enhanced flv format
- apsnr and asisdr audio filters
- OSQ demuxer and decoder
- Support HEVC,VP9,AV1 codec fourcclist in enhanced rtmp protocol
- CRI USM demuxer
- ffmpeg CLI '-top' option deprecated in favor of the setfield filter
- VAAPI AV1 encoder
- ffprobe XML output schema changed to account for multiple
variable-fields elements within the same parent element
- ffprobe -output_format option added as an alias of -of
version 6.0: version 6.0:
+21 -67
View File
@@ -34,8 +34,8 @@ Miscellaneous Areas
=================== ===================
documentation Stefano Sabatini, Mike Melanson, Timothy Gu, Gyan Doshi documentation Stefano Sabatini, Mike Melanson, Timothy Gu, Gyan Doshi
project server day to day operations Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov project server day to day operations Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
project server emergencies Árpád Gereöffy, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov project server emergencies Árpád Gereöffy, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
presets Robert Swain presets Robert Swain
metadata subsystem Aurelien Jacobs metadata subsystem Aurelien Jacobs
release management Michael Niedermayer release management Michael Niedermayer
@@ -144,7 +144,6 @@ Codecs:
bgmc.c, bgmc.h Thilo Borgmann bgmc.c, bgmc.h Thilo Borgmann
binkaudio.c Peter Ross binkaudio.c Peter Ross
cavs* Stefan Gehrer cavs* Stefan Gehrer
cdxl.c Paul B Mahol
celp_filters.* Vitor Sessak celp_filters.* Vitor Sessak
cinepak.c Roberto Togni cinepak.c Roberto Togni
cinepakenc.c Rl / Aetey G.T. AB cinepakenc.c Rl / Aetey G.T. AB
@@ -163,7 +162,6 @@ Codecs:
dv.c Roman Shaposhnik dv.c Roman Shaposhnik
dvbsubdec.c Anshul Maheshwari dvbsubdec.c Anshul Maheshwari
eacmv*, eaidct*, eat* Peter Ross eacmv*, eaidct*, eat* Peter Ross
evrc* Paul B Mahol
exif.c, exif.h Thilo Borgmann exif.c, exif.h Thilo Borgmann
ffv1* Michael Niedermayer ffv1* Michael Niedermayer
ffwavesynth.c Nicolas George ffwavesynth.c Nicolas George
@@ -181,6 +179,7 @@ Codecs:
interplayvideo.c Mike Melanson interplayvideo.c Mike Melanson
jni*, ffjni* Matthieu Bouron jni*, ffjni* Matthieu Bouron
jpeg2000* Nicolas Bertrand jpeg2000* Nicolas Bertrand
jpegxl* Leo Izen
jvdec.c Peter Ross jvdec.c Peter Ross
lcl*.c Roberto Togni, Reimar Doeffinger lcl*.c Roberto Togni, Reimar Doeffinger
libcelt_dec.c Nicolas George libcelt_dec.c Nicolas George
@@ -210,12 +209,12 @@ Codecs:
mqc* Nicolas Bertrand mqc* Nicolas Bertrand
msmpeg4.c, msmpeg4data.h Michael Niedermayer msmpeg4.c, msmpeg4data.h Michael Niedermayer
msrle.c Mike Melanson msrle.c Mike Melanson
msrleenc.c Tomas Härdin
msvideo1.c Mike Melanson msvideo1.c Mike Melanson
nuv.c Reimar Doeffinger nuv.c Reimar Doeffinger
nvdec*, nvenc* Timo Rothenpieler nvdec*, nvenc* Timo Rothenpieler
omx.c Martin Storsjo, Aman Gupta omx.c Martin Storsjo, Aman Gupta
opus* Rostislav Pehlivanov opus* Rostislav Pehlivanov
paf.* Paul B Mahol
pcx.c Ivo van Poorten pcx.c Ivo van Poorten
pgssubdec.c Reimar Doeffinger pgssubdec.c Reimar Doeffinger
ptx.c Ivo van Poorten ptx.c Ivo van Poorten
@@ -229,7 +228,6 @@ Codecs:
rpza.c Roberto Togni rpza.c Roberto Togni
rtjpeg.c, rtjpeg.h Reimar Doeffinger rtjpeg.c, rtjpeg.h Reimar Doeffinger
rv10.c Michael Niedermayer rv10.c Michael Niedermayer
s3tc* Ivo van Poorten
smc.c Mike Melanson smc.c Mike Melanson
snow* Michael Niedermayer, Loren Merritt snow* Michael Niedermayer, Loren Merritt
sonic.c Alex Beregszaszi sonic.c Alex Beregszaszi
@@ -237,16 +235,13 @@ Codecs:
srt* Aurelien Jacobs srt* Aurelien Jacobs
sunrast.c Ivo van Poorten sunrast.c Ivo van Poorten
svq3.c Michael Niedermayer svq3.c Michael Niedermayer
tak* Paul B Mahol
truemotion1* Mike Melanson truemotion1* Mike Melanson
tta.c Alex Beregszaszi, Jaikrishnan Menon tta.c Alex Beregszaszi, Jaikrishnan Menon
ttaenc.c Paul B Mahol
txd.c Ivo van Poorten txd.c Ivo van Poorten
v4l2_* Jorge Ramirez-Ortiz v4l2_* Jorge Ramirez-Ortiz
vc2* Rostislav Pehlivanov vc2* Rostislav Pehlivanov
vcr1.c Michael Niedermayer vcr1.c Michael Niedermayer
videotoolboxenc.c Rick Kern, Aman Gupta videotoolboxenc.c Rick Kern, Aman Gupta
vima.c Paul B Mahol
vorbisdec.c Denes Balatoni, David Conrad vorbisdec.c Denes Balatoni, David Conrad
vorbisenc.c Oded Shimon vorbisenc.c Oded Shimon
vp3* Mike Melanson vp3* Mike Melanson
@@ -255,22 +250,21 @@ Codecs:
vp8 David Conrad, Ronald Bultje vp8 David Conrad, Ronald Bultje
vp9 Ronald Bultje vp9 Ronald Bultje
vqavideo.c Mike Melanson vqavideo.c Mike Melanson
vvc Nuo Mi
wmaprodec.c Sascha Sommer wmaprodec.c Sascha Sommer
wmavoice.c Ronald S. Bultje wmavoice.c Ronald S. Bultje
wmv2.c Michael Niedermayer wmv2.c Michael Niedermayer
xan.c Mike Melanson xan.c Mike Melanson
xbm* Paul B Mahol
xface Stefano Sabatini xface Stefano Sabatini
xwd* Paul B Mahol
Hardware acceleration: Hardware acceleration:
dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme
d3d11va* Steve Lhomme d3d11va* Steve Lhomme
mediacodec* Matthieu Bouron, Aman Gupta mediacodec* Matthieu Bouron, Aman Gupta, Zhao Zhili
vaapi* Haihao Xiang vaapi* Haihao Xiang
vaapi_encode* Mark Thompson, Haihao Xiang vaapi_encode* Mark Thompson, Haihao Xiang
vdpau* Philip Langdale, Carl Eugen Hoyos vdpau* Philip Langdale, Carl Eugen Hoyos
videotoolbox* Rick Kern, Aman Gupta videotoolbox* Rick Kern, Aman Gupta, Zhao Zhili
libavdevice libavdevice
@@ -305,64 +299,34 @@ Generic parts:
motion_estimation.c Davinder Singh motion_estimation.c Davinder Singh
Filters: Filters:
f_drawgraph.c Paul B Mahol
af_adelay.c Paul B Mahol
af_aecho.c Paul B Mahol
af_afade.c Paul B Mahol
af_amerge.c Nicolas George af_amerge.c Nicolas George
af_aphaser.c Paul B Mahol
af_aresample.c Michael Niedermayer af_aresample.c Michael Niedermayer
af_astats.c Paul B Mahol
af_atempo.c Pavel Koshevoy af_atempo.c Pavel Koshevoy
af_biquads.c Paul B Mahol
af_chorus.c Paul B Mahol
af_compand.c Paul B Mahol
af_firequalizer.c Muhammad Faiz af_firequalizer.c Muhammad Faiz
af_hdcd.c Burt P. af_hdcd.c Burt P.
af_ladspa.c Paul B Mahol
af_loudnorm.c Kyle Swanson af_loudnorm.c Kyle Swanson
af_pan.c Nicolas George af_pan.c Nicolas George
af_sidechaincompress.c Paul B Mahol
af_silenceremove.c Paul B Mahol
avf_aphasemeter.c Paul B Mahol
avf_avectorscope.c Paul B Mahol
avf_showcqt.c Muhammad Faiz avf_showcqt.c Muhammad Faiz
vf_blend.c Paul B Mahol
vf_bwdif Thomas Mundt (CC <thomas.mundt@hr.de>) vf_bwdif Thomas Mundt (CC <thomas.mundt@hr.de>)
vf_chromakey.c Timo Rothenpieler vf_chromakey.c Timo Rothenpieler
vf_colorchannelmixer.c Paul B Mahol
vf_colorconstancy.c Mina Sami (CC <minas.gorgy@gmail.com>) vf_colorconstancy.c Mina Sami (CC <minas.gorgy@gmail.com>)
vf_colorbalance.c Paul B Mahol
vf_colorkey.c Timo Rothenpieler vf_colorkey.c Timo Rothenpieler
vf_colorlevels.c Paul B Mahol
vf_coreimage.m Thilo Borgmann vf_coreimage.m Thilo Borgmann
vf_deband.c Paul B Mahol
vf_dejudder.c Nicholas Robbins vf_dejudder.c Nicholas Robbins
vf_delogo.c Jean Delvare (CC <jdelvare@suse.com>) vf_delogo.c Jean Delvare (CC <jdelvare@suse.com>)
vf_drawbox.c/drawgrid Andrey Utkin vf_drawbox.c/drawgrid Andrey Utkin
vf_extractplanes.c Paul B Mahol vf_fsync.c Thilo Borgmann
vf_histogram.c Paul B Mahol
vf_hqx.c Clément Bœsch vf_hqx.c Clément Bœsch
vf_idet.c Pascal Massimino vf_idet.c Pascal Massimino
vf_il.c Paul B Mahol
vf_(t)interlace Thomas Mundt (CC <thomas.mundt@hr.de>) vf_(t)interlace Thomas Mundt (CC <thomas.mundt@hr.de>)
vf_lenscorrection.c Daniel Oberhoff vf_lenscorrection.c Daniel Oberhoff
vf_libplacebo.c Niklas Haas vf_libplacebo.c Niklas Haas
vf_mergeplanes.c Paul B Mahol
vf_mestimate.c Davinder Singh vf_mestimate.c Davinder Singh
vf_minterpolate.c Davinder Singh vf_minterpolate.c Davinder Singh
vf_neighbor.c Paul B Mahol
vf_psnr.c Paul B Mahol
vf_random.c Paul B Mahol
vf_readvitc.c Tobias Rapp (CC t.rapp at noa-archive dot com) vf_readvitc.c Tobias Rapp (CC t.rapp at noa-archive dot com)
vf_scale.c Michael Niedermayer vf_scale.c Michael Niedermayer
vf_separatefields.c Paul B Mahol
vf_ssim.c Paul B Mahol
vf_stereo3d.c Paul B Mahol
vf_telecine.c Paul B Mahol
vf_tonemap_opencl.c Ruiling Song vf_tonemap_opencl.c Ruiling Song
vf_yadif.c Michael Niedermayer vf_yadif.c Michael Niedermayer
vf_zoompan.c Paul B Mahol
Sources: Sources:
vsrc_mandelbrot.c Michael Niedermayer vsrc_mandelbrot.c Michael Niedermayer
@@ -384,7 +348,6 @@ Muxers/Demuxers:
4xm.c Mike Melanson 4xm.c Mike Melanson
aadec.c Vesselin Bontchev (vesselin.bontchev at yandex dot com) aadec.c Vesselin Bontchev (vesselin.bontchev at yandex dot com)
adtsenc.c Robert Swain adtsenc.c Robert Swain
afc.c Paul B Mahol
aiffdec.c Baptiste Coudurier, Matthieu Bouron aiffdec.c Baptiste Coudurier, Matthieu Bouron
aiffenc.c Baptiste Coudurier, Matthieu Bouron aiffenc.c Baptiste Coudurier, Matthieu Bouron
alp.c Zane van Iperen alp.c Zane van Iperen
@@ -395,16 +358,12 @@ Muxers/Demuxers:
argo_brp.c Zane van Iperen argo_brp.c Zane van Iperen
argo_cvg.c Zane van Iperen argo_cvg.c Zane van Iperen
ass* Aurelien Jacobs ass* Aurelien Jacobs
astdec.c Paul B Mahol
astenc.c James Almer astenc.c James Almer
avi* Michael Niedermayer avi* Michael Niedermayer
avisynth.c Stephen Hutchinson avisynth.c Stephen Hutchinson
avr.c Paul B Mahol
bink.c Peter Ross bink.c Peter Ross
boadec.c Michael Niedermayer boadec.c Michael Niedermayer
brstm.c Paul B Mahol
caf* Peter Ross caf* Peter Ross
cdxl.c Paul B Mahol
codec2.c Tomas Härdin codec2.c Tomas Härdin
crc.c Michael Niedermayer crc.c Michael Niedermayer
dashdec.c Steven Liu dashdec.c Steven Liu
@@ -413,10 +372,10 @@ Muxers/Demuxers:
dfpwmdec.c Jack Bruienne dfpwmdec.c Jack Bruienne
dss.c Oleksij Rempel dss.c Oleksij Rempel
dtsdec.c foo86 dtsdec.c foo86
dtshddec.c Paul B Mahol
dv.c Roman Shaposhnik dv.c Roman Shaposhnik
dvdvideodec.c Marth64
electronicarts.c Peter Ross electronicarts.c Peter Ross
epafdec.c Paul B Mahol evc* Samsung (Dawid Kozinski)
ffm* Baptiste Coudurier ffm* Baptiste Coudurier
flic.c Mike Melanson flic.c Mike Melanson
flvdec.c Michael Niedermayer flvdec.c Michael Niedermayer
@@ -430,22 +389,19 @@ Muxers/Demuxers:
imf* Pierre-Anthony Lemieux imf* Pierre-Anthony Lemieux
img2*.c Michael Niedermayer img2*.c Michael Niedermayer
ipmovie.c Mike Melanson ipmovie.c Mike Melanson
ircam* Paul B Mahol
iss.c Stefan Gehrer iss.c Stefan Gehrer
jpegxl_probe.* Leo Izen jpegxl* Leo Izen
jvdec.c Peter Ross jvdec.c Peter Ross
kvag.c Zane van Iperen kvag.c Zane van Iperen
libmodplug.c Clément Bœsch libmodplug.c Clément Bœsch
libopenmpt.c Josh de Kock libopenmpt.c Josh de Kock
lmlm4.c Ivo van Poorten lmlm4.c Ivo van Poorten
lvfdec.c Paul B Mahol
lxfdec.c Tomas Härdin lxfdec.c Tomas Härdin
matroska.c Aurelien Jacobs, Andreas Rheinhardt matroska.c Aurelien Jacobs, Andreas Rheinhardt
matroskadec.c Aurelien Jacobs, Andreas Rheinhardt matroskadec.c Aurelien Jacobs, Andreas Rheinhardt
matroskaenc.c David Conrad, Andreas Rheinhardt matroskaenc.c David Conrad, Andreas Rheinhardt
matroska subtitles (matroskaenc.c) John Peebles matroska subtitles (matroskaenc.c) John Peebles
metadata* Aurelien Jacobs metadata* Aurelien Jacobs
mgsts.c Paul B Mahol
microdvd* Aurelien Jacobs microdvd* Aurelien Jacobs
mm.c Peter Ross mm.c Peter Ross
mov.c Baptiste Coudurier mov.c Baptiste Coudurier
@@ -458,7 +414,6 @@ Muxers/Demuxers:
msnwc_tcp.c Ramiro Polla msnwc_tcp.c Ramiro Polla
mtv.c Reynaldo H. Verdejo Pinochet mtv.c Reynaldo H. Verdejo Pinochet
mxf* Baptiste Coudurier, Tomas Härdin mxf* Baptiste Coudurier, Tomas Härdin
nistspheredec.c Paul B Mahol
nsvdec.c Francois Revol nsvdec.c Francois Revol
nut* Michael Niedermayer nut* Michael Niedermayer
nuv.c Reimar Doeffinger nuv.c Reimar Doeffinger
@@ -466,13 +421,12 @@ Muxers/Demuxers:
oggenc.c Baptiste Coudurier oggenc.c Baptiste Coudurier
oggparse*.c David Conrad oggparse*.c David Conrad
oma.c Maxim Poliakovski oma.c Maxim Poliakovski
paf.c Paul B Mahol
pp_bnk.c Zane van Iperen pp_bnk.c Zane van Iperen
psxstr.c Mike Melanson psxstr.c Mike Melanson
pva.c Ivo van Poorten pva.c Ivo van Poorten
pvfdec.c Paul B Mahol
r3d.c Baptiste Coudurier r3d.c Baptiste Coudurier
raw.c Michael Niedermayer raw.c Michael Niedermayer
rcwtenc.c Marth64
rdt.c Ronald S. Bultje rdt.c Ronald S. Bultje
rl2.c Sascha Sommer rl2.c Sascha Sommer
rmdec.c, rmenc.c Ronald S. Bultje rmdec.c, rmenc.c Ronald S. Bultje
@@ -491,11 +445,9 @@ Muxers/Demuxers:
sdp.c Martin Storsjo sdp.c Martin Storsjo
segafilm.c Mike Melanson segafilm.c Mike Melanson
segment.c Stefano Sabatini segment.c Stefano Sabatini
smjpeg* Paul B Mahol
spdif* Anssi Hannula spdif* Anssi Hannula
srtdec.c Aurelien Jacobs srtdec.c Aurelien Jacobs
swf.c Baptiste Coudurier swf.c Baptiste Coudurier
takdec.c Paul B Mahol
tta.c Alex Beregszaszi tta.c Alex Beregszaszi
txd.c Ivo van Poorten txd.c Ivo van Poorten
voc.c Aurelien Jacobs voc.c Aurelien Jacobs
@@ -505,7 +457,6 @@ Muxers/Demuxers:
webvtt* Matthew J Heaney webvtt* Matthew J Heaney
westwood.c Mike Melanson westwood.c Mike Melanson
wtv.c Peter Ross wtv.c Peter Ross
wvenc.c Paul B Mahol
Protocols: Protocols:
async.c Zhang Rui async.c Zhang Rui
@@ -543,10 +494,10 @@ LoongArch Shiyou Yin
Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier
Amiga / PowerPC Colin Ward Amiga / PowerPC Colin Ward
Linux / PowerPC Lauri Kasanen Linux / PowerPC Lauri Kasanen
RISC-V Rémi Denis-Courmont
Windows MinGW Alex Beregszaszi, Ramiro Polla Windows MinGW Alex Beregszaszi, Ramiro Polla
Windows Cygwin Victor Paesa Windows Cygwin Victor Paesa
Windows MSVC Matthew Oliver, Hendrik Leppkes Windows MSVC Hendrik Leppkes
Windows ICL Matthew Oliver
ADI/Blackfin DSP Marc Hoffman ADI/Blackfin DSP Marc Hoffman
Sparc Roman Shaposhnik Sparc Roman Shaposhnik
OS/2 KO Myung-Hun OS/2 KO Myung-Hun
@@ -584,10 +535,12 @@ wm4
Releases Releases
======== ========
7.0 Michael Niedermayer
6.1 Michael Niedermayer
5.1 Michael Niedermayer
4.4 Michael Niedermayer
3.4 Michael Niedermayer
2.8 Michael Niedermayer 2.8 Michael Niedermayer
2.7 Michael Niedermayer
2.6 Michael Niedermayer
2.5 Michael Niedermayer
If you want to maintain an older release, please contact us If you want to maintain an older release, please contact us
@@ -614,7 +567,8 @@ Haihao Xiang (haihao) 1F0C 31E8 B4FE F7A4 4DC1 DC99 E0F5 76D4 76FC 437F
Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368 Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368
James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0 James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0
Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A
Leo Izen (thebombzen) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A Leo Izen (Traneptora) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A
Leo Izen (Traneptora) 1D83 0A0B CE46 709E 203B 26FC 764E 48EA 4822 1833
Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE
Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464 Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464
Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB
+15 -5
View File
@@ -47,7 +47,7 @@ FF_DEP_LIBS := $(DEP_LIBS)
FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS) FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS)
$(TOOLS): %$(EXESUF): %.o $(TOOLS): %$(EXESUF): %.o
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter-out $(FF_DEP_LIBS), $^) $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS)
target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS) target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS)
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
@@ -64,9 +64,14 @@ tools/target_dem_fuzzer$(EXESUF): tools/target_dem_fuzzer.o $(FF_DEP_LIBS)
tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS) 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) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_sws_fuzzer$(EXESUF): tools/target_sws_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): ELIBS = $(FF_EXTRALIBS)
tools/enum_options$(EXESUF): $(FF_DEP_LIBS) tools/enum_options$(EXESUF): $(FF_DEP_LIBS)
tools/enc_recon_frame_test$(EXESUF): $(FF_DEP_LIBS)
tools/enc_recon_frame_test$(EXESUF): ELIBS = $(FF_EXTRALIBS)
tools/scale_slice_test$(EXESUF): $(FF_DEP_LIBS) tools/scale_slice_test$(EXESUF): $(FF_DEP_LIBS)
tools/scale_slice_test$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/scale_slice_test$(EXESUF): ELIBS = $(FF_EXTRALIBS)
tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS)
@@ -91,10 +96,10 @@ ffbuild/.config: $(CONFIGURABLE_COMPONENTS)
SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \
HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \ HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \
ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \
ALTIVEC-OBJS VSX-OBJS RVV-OBJS MMX-OBJS X86ASM-OBJS \ ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \
MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \
MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \ MMI-OBJS LSX-OBJS LASX-OBJS RV-OBJS RVV-OBJS \
STLIBOBJS HOSTOBJS TESTOBJS OBJS SLIBOBJS SHLIBOBJS STLIBOBJS HOSTOBJS TESTOBJS
define RESET define RESET
$(1) := $(1) :=
@@ -131,13 +136,18 @@ endif
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS)
VERSION_SH = $(SRC_PATH)/ffbuild/version.sh VERSION_SH = $(SRC_PATH)/ffbuild/version.sh
ifeq ($(VERSION_TRACKING),yes)
GIT_LOG = $(SRC_PATH)/.git/logs/HEAD GIT_LOG = $(SRC_PATH)/.git/logs/HEAD
endif
.version: $(wildcard $(GIT_LOG)) $(VERSION_SH) ffbuild/config.mak .version: $(wildcard $(GIT_LOG)) $(VERSION_SH) ffbuild/config.mak
.version: M=@ .version: M=@
ifneq ($(VERSION_TRACKING),yes)
libavutil/ffversion.h .version: REVISION=unknown
endif
libavutil/ffversion.h .version: libavutil/ffversion.h .version:
$(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION) $(M)revision=$(REVISION) $(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION)
$(Q)touch .version $(Q)touch .version
# force version.sh to run whenever version might have changed # force version.sh to run whenever version might have changed
+1 -1
View File
@@ -1 +1 @@
6.0.1 7.0.2
+5 -5
View File
@@ -1,10 +1,10 @@
┌──────────────────────────────────────────── ┌─────────────────────────────────────────┐
│ RELEASE NOTES for FFmpeg 6.0 "Von Neumann" │ │ RELEASE NOTES for FFmpeg 7.0 "Dijkstra" │
└──────────────────────────────────────────── └─────────────────────────────────────────┘
The FFmpeg Project proudly presents FFmpeg 6.0 "Von Neumann", about 6 The FFmpeg Project proudly presents FFmpeg 7.0 "Dijkstra", about 6
months after the release of FFmpeg 5.1. months after the release of FFmpeg 6.1.
A complete Changelog is available at the root of the project, and the A complete Changelog is available at the root of the project, and the
complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git
+1 -1
View File
@@ -1 +1 @@
6.0.1 7.0.2
-1
View File
@@ -19,7 +19,6 @@
#ifndef COMPAT_ATOMICS_WIN32_STDATOMIC_H #ifndef COMPAT_ATOMICS_WIN32_STDATOMIC_H
#define COMPAT_ATOMICS_WIN32_STDATOMIC_H #define COMPAT_ATOMICS_WIN32_STDATOMIC_H
#define WIN32_LEAN_AND_MEAN
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <windows.h> #include <windows.h>
+8 -2
View File
@@ -35,7 +35,6 @@
* As most functions here are used without checking return values, * As most functions here are used without checking return values,
* only implement return values as necessary. */ * only implement return values as necessary. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#include <time.h> #include <time.h>
@@ -66,7 +65,14 @@ typedef CONDITION_VARIABLE pthread_cond_t;
#define PTHREAD_CANCEL_ENABLE 1 #define PTHREAD_CANCEL_ENABLE 1
#define PTHREAD_CANCEL_DISABLE 0 #define PTHREAD_CANCEL_DISABLE 0
static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg) #if HAVE_WINRT
#define THREADFUNC_RETTYPE DWORD
#else
#define THREADFUNC_RETTYPE unsigned
#endif
static av_unused THREADFUNC_RETTYPE
__stdcall attribute_align_arg win32thread_worker(void *arg)
{ {
pthread_t *h = (pthread_t*)arg; pthread_t *h = (pthread_t*)arg;
h->ret = h->func(h->arg); h->ret = h->func(h->arg);
Vendored
+460 -163
View File
File diff suppressed because it is too large Load Diff
+302 -1
View File
@@ -1,7 +1,308 @@
The last version increases of all libraries were on 2023-02-09 The last version increases of all libraries were on 2024-03-07
API changes, most recent first: API changes, most recent first:
-------- 8< --------- FFmpeg 7.0 was cut here -------- 8< ---------
2024-03-25 - 5df901ffa56 - lavu 59.7.100 - timestamp.h
Add av_ts_make_time_string2() for better timestamp precision, the new
function accepts AVRational as time base instead of *AVRational, and is not
an inline function like its predecessor.
2024-03-23 - a9023377b22 - lavu 59.6.100 - film_grain_params.h
Add av_film_grain_params_select().
2024-03-23 - 35d2960dcd0 - lavu 59.5.100 - film_grain_params.h
Add AVFilmGrainParams.color_range, color_primaries, color_trc, color_space,
width, height, subsampling_x, subsampling_y, bit_depth_luma and
bit_depth_chroma. Deprecate the corresponding fields from
AVFilmGrainH274Params.
2024-03-23 - f17e18d2922 - lavc 61.3.100 - jni.h
Add av_jni_set_android_app_ctx() and av_jni_get_android_app_ctx().
2024-03-22 - 26398da8f30 - lavu 59.4.100 - frame.h
Constified the first-level pointee of av_frame_side_data_get()
and renamed it to av_frame_side_data_get_c(). From now on,
av_frame_side_data_get() is a wrapper around av_frame_side_data_get_c()
that accepts AVFrameSideData * const *sd.
2024-03-20 - 0d36844ddf9 - lavc 61.2.100 - avcodec.h
Add AVCodecContext.[nb_]decoded_side_data.
2024-03-20 - d9ade14c5c5 - lavu 59.3.100 - frame.h
Add av_frame_side_data_free(), av_frame_side_data_new(),
av_frame_side_data_clone(), av_frame_side_data_get() as well
as AV_FRAME_SIDE_DATA_FLAG_UNIQUE.
2024-03-16 - ed6207274e6 - lavu 59.2.100 - channel_layout.h
Add AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL.
2024-03-08 - 68a8eca7523 - lavc 61.1.100 - avcodec.h
Add AVCodecContext.[nb_]side_data_prefer_packet.
2024-03-08 - efe44787781 - lavu 59.1.100 - opt.h
Add AV_OPT_TYPE_FLAG_ARRAY and AVOptionArrayDef.
2024-03-08 - c9f5cea9cca - lavc 61.0.100 - vdpau.h
Deprecate av_vdpau_alloc_context(), av_alloc_vdpaucontext(),
av_vdpau_hwaccel_get_render2() and av_vdpau_hwaccel_set_render2().
The former are superseded by av_vdpau_bind_context(), the latter
are unneeded as the relevant field is public and can be accessed directly.
2024-03-06 - 49707b05900 - lavf 60.25.100 - avformat.h
Deprecate av_fmt_ctx_get_duration_estimation_method().
The relevant field is public and needs no getter to access.
2024-03-05 - ab15c04dee5 - lavf 60.24.100 - avformat.h
Add avformat_stream_group_name().
2024-02-28 - b295aafb082 - swr 4.14.100 - swresample.h
swr_convert() now accepts arrays of const pointers (to input and output).
2024-02-28 - 58e3ef7f546 - lavu 58.40.100 - timestamp.h
av_ts_make_time_string() now accepts a pointer to const AVRational.
2024-02-28 - dfb9d8a5a2f - lavf 60.23.100 - avio.h
avio_print_string_array() now accepts an array of const pointers.
2024-02-26 - 41e349c24a7 - lavf 60.22.101 - avformat.h
AV_DISPOSITION_DEPENDENT may now also be used for video streams
intended to be merged with other video streams for presentation.
2024-02-26 - 25a10677d12 - lavf 60.22.100 - avformat.h
Add AVStreamGroupTileGrid
Add AV_STREAM_GROUP_PARAMS_TILE_GRID
Add AVStreamGroup.params.tile_grid
2024-02-21 - 1d66a122df9 - lavc 60.40.100 - avcodec.h
Deprecate AV_INPUT_BUFFER_MIN_SIZE without replacement.
2024-02-16 - eea9bd88a5f - lavu 58.39.100 - pixfmt.h
Add AV_VIDEO_MAX_PLANES
2024-02-13 - ec2036454bc - lavf 60.21.100 - avformat.h
Add AVStreamGroup.disposition.
2024-02-12 - 66386bf2a2a - lavu 58.38.100 - channel_layout.h
Add av_channel_layout_retype().
2024-02-12 - 4569b861322 - lavu 58.37.100 - channel_layout.h
Add av_channel_layout_custom_init().
2024-02-04 - 45697e6a512 - lavc 60.39.100 - packet.h
Add AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT.
2023-11-xx - xxxxxxxxxx - lavfi 9.16.100 - buffersink.h buffersrc.h
Add av_buffersink_get_colorspace and av_buffersink_get_color_range.
Add AVBufferSrcParameters.color_space and AVBufferSrcParameters.color_range.
2023-11-xx - xxxxxxxxxx - lavfi 9.15.100 - avfilter.h
Add AVFilterLink.colorspace, AVFilterLink.color_range
2023-12-21 - 142f727b9ca - lavu 58.36.100 - pixfmt.h hwcontext.h hwcontext_d3d12va.h
Add AV_HWDEVICE_TYPE_D3D12VA and AV_PIX_FMT_D3D12.
Add AVD3D12VADeviceContext, AVD3D12VASyncContext, AVD3D12VAFrame and
AVD3D12VAFramesContext.
2023-12-18 - 74279227dd2 - lavc 60.36.100 - packet.h
Add AV_PKT_DATA_IAMF_MIX_GAIN_PARAM, AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM
and AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM.
2023-12-18 - 556b596d1d9 - lavc 60.19.100 - avformat.h
Add AVStreamGroup struct.
Add AVFormatContext.stream_groups and AVFormatContext.nb_stream_groups
Add avformat_stream_group_create(), avformat_stream_group_add_stream(),
and av_stream_group_get_class().
Add enum AVStreamGroupParamsType with values AV_STREAM_GROUP_PARAMS_NONE,
AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT and
AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION.
2023-12-18 - d2af93bbefc - lavu 58.35.100 - iamf.h
Add a new API to support Immersive Audio Model and Formats.
2023-12-13 - 5475f665f60 - lavu 58.33.100 - imgutils.h
Add av_image_fill_color().
2023-11-08 - b82957a66a7 - lavu 58.32.100 - channel_layout.h
Add AV_CH_LAYOUT_7POINT2POINT3 and AV_CHANNEL_LAYOUT_7POINT2POINT3.
Add AV_CH_LAYOUT_9POINT1POINT4_BACK and AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK.
2023-10-31 - 57c16323f26 - lavu 58.31.100 - pixdesc.h
Add AV_PIX_FMT_FLAG_XYZ.
-------- 8< --------- FFmpeg 6.1 was cut here -------- 8< ---------
2023-10-27 - 52a97642604 - lavu 58.28.100 - channel_layout.h
Add AV_CH_LAYOUT_3POINT1POINT2 and AV_CHANNEL_LAYOUT_3POINT1POINT2.
Add AV_CH_LAYOUT_5POINT1POINT2_BACK and AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK.
Add AV_CH_LAYOUT_5POINT1POINT4_BACK and AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK.
Add AV_CH_LAYOUT_7POINT1POINT2 and AV_CHANNEL_LAYOUT_7POINT1POINT2.
Add AV_CH_LAYOUT_7POINT1POINT4_BACK and AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK.
2023-10-06 - 804be7f9e3c - lavc 60.30.101 - avcodec.h
AVCodecContext.coded_side_data may now be used during decoding, to be set
by user before calling avcodec_open2() for initialization.
2023-10-06 - 5432d2aacad - lavc 60.15.100 - avformat.h
Deprecate AVFormatContext.{nb_,}side_data, av_stream_add_side_data(),
av_stream_new_side_data(), and av_stream_get_side_data(). Side data fields
from AVFormatContext.codecpar should be used from now on.
2023-10-06 - 21d7cc6fa9a - lavc 60.30.100 - codec_par.h
Added {nb_,}coded_side_data to AVCodecParameters.
The AVCodecParameters helpers will copy it to and from its AVCodecContext
namesake.
2023-10-06 - 74279227dd2 - lavc 60.29.100 - packet.h
Added av_packet_side_data_new(), av_packet_side_data_add(),
av_packet_side_data_get(), av_packet_side_data_remove, and
av_packet_side_data_free().
2023-10-03 - ea14e8bc302 - lavc 60.28.100 - codec_par.h defs.h
Move the definition of enum AVFieldOrder from codec_par.h to defs.h.
2023-10-03 - dd48e49d547 - lavf 60.14.100 - avformat.h
Deprecate AVFMT_ALLOW_FLUSH without replacement. Users can always
flush any muxer by sending a NULL packet.
2023-09-28 - 8e1ef7c38f6 - lavu 58.27.100 - pixfmt.h
Add AV_PIX_FMT_GBRAP14BE, AV_PIX_FMT_GBRAP14LE pixel formats.
2023-09-28 - 05f8b2ca0f7 - lavu 58.26.100 - hwcontext_cuda.h
Add AV_CUDA_USE_CURRENT_CONTEXT.
2023-09-19 - ba9cd06c763 - lavu 58.25.100 - avutil.h
Make AV_TIME_BASE_Q compatible with C++.
2023-09-18 - 85e075587dc - lavf 60 - avformat.h
Deprecate AVFMT_FLAG_SHORTEST without replacement.
2023-09-07 - 423b6a7e493 - lavu 58.24.100 - imgutils.h
Add av_image_copy2(), a wrapper around the av_image_copy()
to overcome limitations of automatic conversions.
2023-09-07 - 5094d1f429e - lavu 58.23.100 - fifo.h
Constify the AVFifo pointees in av_fifo_peek() and av_fifo_peek_to_cb().
2023-09-07 - fa4bf5793a0 - lavu 58.22.100 - audio_fifo.h
Constify some pointees in av_audio_fifo_write(), av_audio_fifo_read(),
av_audio_fifo_peek() and av_audio_fifo_peek_at().
2023-09-07 - 9bf31f60960 - lavu 58.21.100 - samplefmt.h
Constify some pointees in av_samples_copy() and av_samples_set_silence().
2023-09-07 - 41285890e03 - lavu 58.20.100 - imgutils.h
Constify some pointees in av_image_copy(), av_image_copy_uc_from() and
av_image_fill_black().
2023-09-07 - 2a68d945cd7 - lavf 60.12.100 - avio.h
Constify the buffer pointees in the write_packet and write_data_type
callbacks of AVIOContext on the next major bump.
2023-09-07 - 8238bc0b5e3 - lavc 60.26.100 - defs.h
Add AV_PROFILE_* and AV_LEVEL_* replacements in defs.h for the
defines from avcodec.h. The latter are deprecated.
2023-09-06 - b6627a57f41 - lavc 60.25.101 - avcodec.h
AVCodecContext.rc_buffer_size may now be set by decoders.
2023-09-02 - 25ecc94d58f - lavu 58.19.100 - executor.h
Add AVExecutor API
2023-09-01 - 139e54911c8 - lavc 60.25.100 - avfft.h
The entire header will be deprecated and removed in two major bumps.
For a replacement to av_dct, av_rdft, av_fft and av_mdct, use
the new API from libavutil/tx.h.
2023-09-01 - 11e22730e1e - lavu 58.18.100 - tx.h
Add AV_TX_REAL_TO_REAL and AV_TX_REAL_TO_IMAGINARY
2023-08-18 - ff094f5ebbd - lavu 58.17.100 - channel_layout.h
All AV_CHANNEL_LAYOUT_* macros are now compatible with C++ 17 and older.
2023-08-08 - 5012b4ab4ca - lavu 58.15.100 - video_hint.h
Add AVVideoHint API.
2023-08-08 - 5012b4ab4ca - lavc 60 - avcodec.h
Deprecate AV_CODEC_FLAG_DROPCHANGED without replacement.
2023-07-05 - d694c25b44c - lavu 58.14.100 - random_seed.h
Add av_random_bytes()
2023-05-29 - 637afea88ed - lavc 60.16.100 - avcodec.h codec_id.h
Add AV_CODEC_ID_EVC, FF_PROFILE_EVC_BASELINE, and FF_PROFILE_EVC_MAIN.
2023-05-29 - 75918016ab1 - lavu 58.12.100 - mathematics.h
Add av_bessel_i0()
2023-05-29 - f3795e18574 - lavc 60.15.100 - avcodec.h
Add AVHWAccel.update_thread_context, AVHWAccel.free_frame_priv,
AVHWAccel.flush.
2023-05-29 - db1d0227812 - lavu 58.11.100 - hwcontext_vulkan.h
Add AVVulkanDeviceContext.lock_queue, AVVulkanDeviceContext.unlock_queue,
AVVulkanFramesContext.format, AVVulkanFramesContext.lock_frame,
AVVulkanFramesContext.unlock_frame, AVVkFrame.queue_family.
Deprecate AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY (use multiplane images instead).
2023-05-29 - bef86ba86cc - lavu 58.10.100 - pixfmt.h
Add AV_PIX_FMT_P212BE, AV_PIX_FMT_P212LE, AV_PIX_FMT_P412BE,
AV_PIX_FMT_P412LE.
2023-05-18 - 01d444c077e - lavu 58.8.100 - frame.h
Add av_frame_replace().
2023-05-18 - 63767b79a57 - lavu 58 - frame.h
Deprecate AVFrame.palette_has_changed without replacement.
2023-05-15 - 7d1d61cc5f5 - lavc 60 - avcodec.h
Depreate AVCodecContext.ticks_per_frame in favor of
AVCodecContext.framerate (encoding) and
AV_CODEC_PROP_FIELDS (decoding).
2023-05-15 - 70433abf7fb - lavc 60.12.100 - codec_desc.h
Add AV_CODEC_PROP_FIELDS.
2023-05-15 - 8b20d0dcb5c - lavc 60 - codec.h
Depreate AV_CODEC_CAP_SUBFRAMES without replacement.
2023-05-07 - c2ae8e30b7f - lavc 60.11.100 - codec_par.h
Add AVCodecParameters.framerate.
2023-05-04 - 0fc9c1f6828 - lavu 58.7.100 - frame.h
Deprecate AVFrame.interlaced_frame, AVFrame.top_field_first, and
AVFrame.key_frame.
Add AV_FRAME_FLAG_INTERLACED, AV_FRAME_FLAG_TOP_FIELD_FIRST, and
AV_FRAME_FLAG_KEY flags as replacement.
2023-04-10 - 4eaaa38d3df - lavu 58.6.100 - frame.h
av_frame_get_plane_buffer() now accepts const AVFrame*.
2023-04-04 - 61b27b15fc9 - lavu 58.6.100 - hdr_dynamic_metadata.h
Add AV_HDR_PLUS_MAX_PAYLOAD_SIZE.
av_dynamic_hdr_plus_create_side_data() now accepts a user provided
buffer.
2023-03-24 - 632c3499319 - lavfi 9.5.100 - avfilter.h
Add AVFILTER_FLAG_HWDEVICE.
2023-03-21 - 0a3ce5f7384 - lavu 58.5.100 - hdr_dynamic_metadata.h
Add av_dynamic_hdr_plus_from_t35() and av_dynamic_hdr_plus_to_t35()
functions to convert between raw T.35 payloads containing dynamic
HDR10+ metadata and their parsed representations as AVDynamicHDRPlus.
2023-03-17 - 3be46ee7672 - lavu 58.4.100 - hdr_dynamic_vivid_metadata.h
Add two group of three spline params.
Deprecate previous define which only supports one group of params.
2023-03-02 - 373ef1c4fae - lavc 60.6.100 - avcodec.h
Add FF_PROFILE_EAC3_DDP_ATMOS, FF_PROFILE_TRUEHD_ATMOS,
FF_PROFILE_DTS_HD_MA_X and FF_PROFILE_DTS_HD_MA_X_IMAX.
2023-02-25 - f4593775436 - lavc 60.5.100 - avcodec.h
Add FF_PROFILE_HEVC_SCC.
-------- 8< --------- FFmpeg 6.0 was cut here -------- 8< --------- -------- 8< --------- FFmpeg 6.0 was cut here -------- 8< ---------
2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h 2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 6.0.1 PROJECT_NUMBER = 7.0.2
# Using the PROJECT_BRIEF tag one can provide an optional one line description # 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 # for a project that appears at the top of each page and should give viewer a
+1
View File
@@ -19,6 +19,7 @@ MANPAGES3 = $(LIBRARIES-yes:%=doc/%.3)
MANPAGES = $(MANPAGES1) $(MANPAGES3) MANPAGES = $(MANPAGES1) $(MANPAGES3)
PODPAGES = $(AVPROGS-yes:%=doc/%.pod) $(AVPROGS-yes:%=doc/%-all.pod) $(COMPONENTS-yes:%=doc/%.pod) $(LIBRARIES-yes:%=doc/%.pod) PODPAGES = $(AVPROGS-yes:%=doc/%.pod) $(AVPROGS-yes:%=doc/%-all.pod) $(COMPONENTS-yes:%=doc/%.pod) $(LIBRARIES-yes:%=doc/%.pod)
HTMLPAGES = $(AVPROGS-yes:%=doc/%.html) $(AVPROGS-yes:%=doc/%-all.html) $(COMPONENTS-yes:%=doc/%.html) $(LIBRARIES-yes:%=doc/%.html) \ HTMLPAGES = $(AVPROGS-yes:%=doc/%.html) $(AVPROGS-yes:%=doc/%-all.html) $(COMPONENTS-yes:%=doc/%.html) $(LIBRARIES-yes:%=doc/%.html) \
doc/community.html \
doc/developer.html \ doc/developer.html \
doc/faq.html \ doc/faq.html \
doc/fate.html \ doc/fate.html \
+31 -4
View File
@@ -199,6 +199,13 @@ Identical to @option{pass_types}, except the units in the given set
removed and all others passed through. removed and all others passed through.
@end table @end table
The types used by pass_types and remove_types correspond to NAL unit types
(nal_unit_type) in H.264, HEVC and H.266 (see Table 7-1 in the H.264
and HEVC specifications or Table 5 in the H.266 specification), to
marker values for JPEG (without 0xFF prefix) and to start codes without
start code prefix (i.e. the byte following the 0x000001) for MPEG-2.
For VP8 and VP9, every unit has type zero.
Extradata is unchanged by this transformation, but note that if the stream Extradata is unchanged by this transformation, but note that if the stream
contains inline parameter sets then the output may be unusable if they are contains inline parameter sets then the output may be unusable if they are
removed. removed.
@@ -213,6 +220,21 @@ To remove all AUDs, SEI and filler from an H.265 stream:
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=35|38-40' OUTPUT ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=35|38-40' OUTPUT
@end example @end example
To remove all user data from a MPEG-2 stream, including Closed Captions:
@example
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=178' OUTPUT
@end example
To remove all SEI from a H264 stream, including Closed Captions:
@example
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=6' OUTPUT
@end example
To remove all prefix and suffix SEI from a HEVC stream, including Closed Captions and dynamic HDR:
@example
ffmpeg -i INPUT -c:v copy -bsf:v 'filter_units=remove_types=39|40' OUTPUT
@end example
@section hapqa_extract @section hapqa_extract
Extract Rgb or Alpha part of an HAPQA file, without recompression, in order to create an HAPQ or an HAPAlphaOnly file. Extract Rgb or Alpha part of an HAPQA file, without recompression, in order to create an HAPQ or an HAPAlphaOnly file.
@@ -528,10 +550,6 @@ metadata header from each subtitle packet.
See also the @ref{text2movsub} filter. See also the @ref{text2movsub} filter.
@section mp3decomp
Decompress non-standard compressed MP3 audio headers.
@section mpeg2_metadata @section mpeg2_metadata
Modify metadata embedded in an MPEG-2 stream. Modify metadata embedded in an MPEG-2 stream.
@@ -882,6 +900,15 @@ The sample rate of stream packet belongs.
The AV_NOPTS_VALUE constant. The AV_NOPTS_VALUE constant.
@end table @end table
For example, to set PTS equal to DTS (not recommended if B-frames are involved):
@example
ffmpeg -i INPUT -c:a copy -bsf:a setts=pts=DTS out.mkv
@end example
@section showinfo
Log basic packet information. Mainly useful for testing, debugging,
and development.
@anchor{text2movsub} @anchor{text2movsub}
@section text2movsub @section text2movsub
+9 -11
View File
@@ -3,7 +3,7 @@
@c man begin CODEC OPTIONS @c man begin CODEC OPTIONS
libavcodec provides some generic global options, which can be set on libavcodec provides some generic global options, which can be set on
all the encoders and decoders. In addition each codec may support all the encoders and decoders. In addition, each codec may support
so-called private options, which are specific for a given codec. so-called private options, which are specific for a given codec.
Sometimes, a global option may only affect a specific kind of codec, Sometimes, a global option may only affect a specific kind of codec,
@@ -697,10 +697,13 @@ profiles are documented in the relevant encoder documentation.
@item level @var{integer} (@emph{encoding,audio,video}) @item level @var{integer} (@emph{encoding,audio,video})
Set the encoder level. This level depends on the specific codec, and
might correspond to the profile level. It is set by default to
@samp{unknown}.
Possible values: Possible values:
@table @samp @table @samp
@item unknown @item unknown
@end table @end table
@item lowres @var{integer} (@emph{decoding,audio,video}) @item lowres @var{integer} (@emph{decoding,audio,video})
@@ -764,18 +767,11 @@ Set rate-distortion optimal quantization.
@item compression_level @var{integer} (@emph{encoding,audio,video}) @item compression_level @var{integer} (@emph{encoding,audio,video})
@item bits_per_raw_sample @var{integer} @item bits_per_raw_sample @var{integer}
@item channel_layout @var{integer} (@emph{decoding/encoding,audio}) @item channel_layout @var{integer} (@emph{decoding/encoding,audio})
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
for the required syntax.
Possible values:
@table @samp
@end table
@item request_channel_layout @var{integer} (@emph{decoding,audio})
Possible values:
@table @samp
@end table
@item rc_max_vbv_use @var{float} (@emph{encoding,video}) @item rc_max_vbv_use @var{float} (@emph{encoding,video})
@item rc_min_vbv_use @var{float} (@emph{encoding,video}) @item rc_min_vbv_use @var{float} (@emph{encoding,video})
@item ticks_per_frame @var{integer} (@emph{decoding/encoding,audio,video})
@item color_primaries @var{integer} (@emph{decoding/encoding,video}) @item color_primaries @var{integer} (@emph{decoding/encoding,video})
Possible values: Possible values:
@@ -890,9 +886,11 @@ Possible values:
@table @samp @table @samp
@item tv @item tv
@item mpeg @item mpeg
@item limited
MPEG (219*2^(n-8)) MPEG (219*2^(n-8))
@item pc @item pc
@item jpeg @item jpeg
@item full
JPEG (2^n-1) JPEG (2^n-1)
@end table @end table
+177
View File
@@ -0,0 +1,177 @@
\input texinfo @c -*- texinfo -*-
@documentencoding UTF-8
@settitle Community
@titlepage
@center @titlefont{Community}
@end titlepage
@top
@contents
@anchor{Organisation}
@chapter 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.
@anchor{General Assembly}
@chapter 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 authored more than 20 patches in the last 36 months in the main FFmpeg repository, or if they have been voted in by the GA.
The list of active contributors is updated twice each year, on 1st January and 1st July, 0:00 UTC.
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.
A script to generate the current members of the general assembly (minus members voted in) can be found in `tools/general_assembly.pl`.
@anchor{Voting}
@chapter 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.
@anchor{Technical Committee}
@chapter 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 document.
The TC can be contacted at <tc@@ffmpeg>.
@anchor{Resolution Process}
@section Resolution Process
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.
@subsection 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.
@subsection 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.
@subsection 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.
@subsection Within TC
In the internal case, the TC has 96 hours to give its final decision. Exceptionally, the TC can request an extra delay.
@subsection 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.
@anchor{Community Committee}
@chapter 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.
The CC can be contacted at <cc@@ffmpeg>.
@anchor{Code of Conduct}
@chapter Code of Conduct
Be friendly and respectful towards others and third parties.
Treat others the way you yourself want to be treated.
Be considerate. Not everyone shares the same viewpoint and priorities as you do.
Different opinions and interpretations help the project.
Looking at issues from a different perspective assists development.
Do not assume malice for things that can be attributed to incompetence. Even if
it is malice, it's rarely good to start with that as initial assumption.
Stay friendly even if someone acts contrarily. Everyone has a bad day
once in a while.
If you yourself have a bad day or are angry then try to take a break and reply
once you are calm and without anger if you have to.
Try to help other team members and cooperate if you can.
The goal of software development is to create technical excellence, not for any
individual to be better and "win" against the others. Large software projects
are only possible and successful through teamwork.
If someone struggles do not put them down. Give them a helping hand
instead and point them in the right direction.
Finally, keep in mind the immortal words of Bill and Ted,
"Be excellent to each other."
@bye
+187
View File
@@ -130,6 +130,30 @@ Set amount of frame threads to use during decoding. The default value is 0 (auto
@end table @end table
@section libxevd
eXtra-fast Essential Video Decoder (XEVD) MPEG-5 EVC decoder wrapper.
This decoder requires the presence of the libxevd headers and library
during configuration. You need to explicitly configure the build with
@option{--enable-libxevd}.
The xevd project website is at @url{https://github.com/mpeg5/xevd}.
@subsection Options
The following options are supported by the libxevd wrapper.
The xevd-equivalent options or values are listed in parentheses for easy migration.
To get a more accurate and extensive documentation of the libxevd options,
invoke the command @code{xevd_app --help} or consult the libxevd documentation.
@table @option
@item threads (@emph{threads})
Force to use a specific number of threads
@end table
@section QSV Decoders @section QSV Decoders
The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC, The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC,
@@ -353,6 +377,169 @@ Enabled by default.
@end table @end table
@section libaribcaption
Yet another ARIB STD-B24 caption decoder using external @dfn{libaribcaption}
library.
Implements profiles A and C of the Japanse ARIB STD-B24 standard,
Brazilian ABNT NBR 15606-1, and Philippines version of ISDB-T.
Requires the presence of the libaribcaption headers and library
(@url{https://github.com/xqq/libaribcaption}) during configuration.
You need to explicitly configure the build with @code{--enable-libaribcaption}.
If both @dfn{libaribb24} and @dfn{libaribcaption} are enabled, @dfn{libaribcaption}
decoder precedes.
@subsection libaribcaption Decoder Options
@table @option
@item -sub_type @var{subtitle_type}
Specifies the format of the decoded subtitles.
@table @samp
@item bitmap
Graphical image.
@item ass
ASS formatted text.
@item text
Simple text based output without formatting.
@end table
The default is @dfn{ass} as same as @dfn{libaribb24} decoder.
Some present players (e.g., @dfn{mpv}) expect ASS format for ARIB caption.
@item -caption_encoding @var{encoding_scheme}
Specifies the encoding scheme of input subtitle text.
@table @samp
@item auto
Automatically detect text encoding (default).
@item jis
8bit-char JIS encoding defined in ARIB STD B24.
This encoding used in Japan for ISDB captions.
@item utf8
UTF-8 encoding defined in ARIB STD B24.
This encoding is used in Philippines for ISDB-T captions.
@item latin
Latin character encoding defined in ABNT NBR 15606-1.
This encoding is used in South America for SBTVD / ISDB-Tb captions.
@end table
@item -font @var{font_name[,font_name2,...]}
Specify comma-separated list of font family names to be used for @dfn{bitmap}
or @dfn{ass} type subtitle rendering.
Only first font name is used for @dfn{ass} type subtitle.
If not specified, use internaly defined default font family.
@item -ass_single_rect @var{boolean}
ARIB STD-B24 specifies that some captions may be displayed at different
positions at a time (multi-rectangle subtitle).
Since some players (e.g., old @dfn{mpv}) can't handle multiple ASS rectangles
in a single AVSubtitle, or multiple ASS rectangles of indeterminate duration
with the same start timestamp, this option can change the behavior so that
all the texts are displayed in a single ASS rectangle.
The default is @var{false}.
If your player cannot handle AVSubtitles with multiple ASS rectangles properly,
set this option to @var{true} or define @env{ASS_SINGLE_RECT=1} to change
default behavior at compilation.
@item -force_outline_text @var{boolean}
Specify whether always render outline text for all characters regardless of
the indication by charactor style.
The default is @var{false}.
@item -outline_width @var{number} (0.0 - 3.0)
Specify width for outline text, in dots (relative).
The default is @var{1.5}.
@item -ignore_background @var{boolean}
Specify whether to ignore background color rendering.
The default is @var{false}.
@item -ignore_ruby @var{boolean}
Specify whether to ignore rendering for ruby-like (furigana) characters.
The default is @var{false}.
@item -replace_drcs @var{boolean}
Specify whether to render replaced DRCS characters as Unicode characters.
The default is @var{true}.
@item -replace_msz_ascii @var{boolean}
Specify whether to replace MSZ (Middle Size; half width) fullwidth
alphanumerics with halfwidth alphanumerics.
The default is @var{true}.
@item -replace_msz_japanese @var{boolean}
Specify whether to replace some MSZ (Middle Size; half width) fullwidth
japanese special characters with halfwidth ones.
The default is @var{true}.
@item -replace_msz_glyph @var{boolean}
Specify whether to replace MSZ (Middle Size; half width) characters
with halfwidth glyphs if the fonts supports it.
This option works under FreeType or DirectWrite renderer
with Adobe-Japan1 compliant fonts.
e.g., IBM Plex Sans JP, Morisawa BIZ UDGothic, Morisawa BIZ UDMincho,
Yu Gothic, Yu Mincho, and Meiryo.
The default is @var{true}.
@item -canvas_size @var{image_size}
Specify the resolution of the canvas to render subtitles to; usually, this
should be frame size of input video.
This only applies when @code{-subtitle_type} is set to @var{bitmap}.
The libaribcaption decoder assumes input frame size for bitmap rendering as below:
@enumerate
@item
PROFILE_A : 1440 x 1080 with SAR (PAR) 4:3
@item
PROFILE_C : 320 x 180 with SAR (PAR) 1:1
@end enumerate
If actual frame size of input video does not match above assumption,
the rendered captions may be distorted.
To make the captions undistorted, add @code{-canvas_size} option to specify
actual input video size.
Note that the @code{-canvas_size} option is not required for video with
different size but same aspect ratio.
In such cases, the caption will be stretched or shrunk to actual video size
if @code{-canvas_size} option is not specified.
If @code{-canvas_size} option is specified with different size,
the caption will be stretched or shrunk as specified size with calculated SAR.
@end table
@subsection libaribcaption decoder usage examples
Display MPEG-TS file with ARIB subtitle by @code{ffplay} tool:
@example
ffplay -sub_type bitmap MPEG.TS
@end example
Display MPEG-TS file with input frame size 1920x1080 by @code{ffplay} tool:
@example
ffplay -sub_type bitmap -canvas_size 1920x1080 MPEG.TS
@end example
Embed ARIB subtitle in transcoded video:
@example
ffmpeg -sub_type bitmap -i src.m2t -filter_complex "[0:v][0:s]overlay" -vcodec h264 dest.mp4
@end example
@section dvbsub @section dvbsub
@subsection Options @subsection Options
+202 -2
View File
@@ -285,6 +285,168 @@ This demuxer accepts the following option:
@end table @end table
@section dvdvideo
DVD-Video demuxer, powered by libdvdnav and libdvdread.
Can directly ingest DVD titles, specifically sequential PGCs, into
a conversion pipeline. Menu assets, such as background video or audio,
can also be demuxed given the menu's coordinates (at best effort).
Seeking is not supported at this time.
Block devices (DVD drives), ISO files, and directory structures are accepted.
Activate with @code{-f dvdvideo} in front of one of these inputs.
This demuxer does NOT have decryption code of any kind. You are on your own
working with encrypted DVDs, and should not expect support on the matter.
Underlying playback is handled by libdvdnav, and structure parsing by libdvdread.
FFmpeg must be built with GPL library support available as well as the
configure switches @code{--enable-libdvdnav} and @code{--enable-libdvdread}.
You will need to provide either the desired "title number" or exact PGC/PG coordinates.
Many open-source DVD players and tools can aid in providing this information.
If not specified, the demuxer will default to title 1 which works for many discs.
However, due to the flexibility of the format, it is recommended to check manually.
There are many discs that are authored strangely or with invalid headers.
If the input is a real DVD drive, please note that there are some drives which may
silently fail on reading bad sectors from the disc, returning random bits instead
which is effectively corrupt data. This is especially prominent on aging or rotting discs.
A second pass and integrity checks would be needed to detect the corruption.
This is not an FFmpeg issue.
@subsection Background
DVD-Video is not a directly accessible, linear container format in the
traditional sense. Instead, it allows for complex and programmatic playback of
carefully muxed MPEG-PS streams that are stored in headerless VOB files.
To the end-user, these streams are known simply as "titles", but the actual
logical playback sequence is defined by one or more "PGCs", or Program Group Chains,
within the title. The PGC is in turn comprised of multiple "PGs", or Programs",
which are the actual video segments (and for a typical video feature, sequentially
ordered). The PGC structure, along with stream layout and metadata, are stored in
IFO files that need to be parsed. PGCs can be thought of as playlists in easier terms.
An actual DVD player relies on user GUI interaction via menus and an internal VM
to drive the direction of demuxing. Generally, the user would either navigate (via menus)
or automatically be redirected to the PGC of their choice. During this process and
the subsequent playback, the DVD player's internal VM also maintains a state and
executes instructions that can create jumps to different sectors during playback.
This is why libdvdnav is involved, as a linear read of the MPEG-PS blobs on the
disc (VOBs) is not enough to produce the right sequence in many cases.
There are many other DVD structures (a long subject) that will not be discussed here.
NAV packets, in particular, are handled by this demuxer to build accurate timing
but not emitted as a stream. For a good high-level understanding, refer to:
@url{https://code.videolan.org/videolan/libdvdnav/-/blob/master/doc/dvd_structures}
@subsection Options
This demuxer accepts the following options:
@table @option
@item title @var{int}
The title number to play. Must be set if @option{pgc} and @option{pg} are not set.
Not applicable to menus.
Default is 0 (auto), which currently only selects the first available title (title 1)
and notifies the user about the implications.
@item chapter_start @var{int}
The chapter, or PTT (part-of-title), number to start at. Not applicable to menus.
Default is 1.
@item chapter_end @var{int}
The chapter, or PTT (part-of-title), number to end at. Not applicable to menus.
Default is 0, which is a special value to signal end at the last possible chapter.
@item angle @var{int}
The video angle number, referring to what is essentially an additional
video stream that is composed from alternate frames interleaved in the VOBs.
Not applicable to menus.
Default is 1.
@item region @var{int}
The region code to use for playback. Some discs may use this to default playback
at a particular angle in different regions. This option will not affect the region code
of a real DVD drive, if used as an input. Not applicable to menus.
Default is 0, "world".
@item menu @var{bool}
Demux menu assets instead of navigating a title. Requires exact coordinates
of the menu (@option{menu_lu}, @option{menu_vts}, @option{pgc}, @option{pg}).
Default is false.
@item menu_lu @var{int}
The menu language to demux. In DVD, menus are grouped by language.
Default is 0, the first language unit.
@item menu_vts @var{int}
The VTS where the menu lives, or 0 if it is a VMG menu (root-level).
Default is 0, VMG menu.
@item pgc @var{int}
The entry PGC to start playback, in conjunction with @option{pg}.
Alternative to setting @option{title}.
Chapter markers are not supported at this time.
Must be explicitly set for menus.
Default is 0, automatically resolve from value of @option{title}.
@item pg @var{int}
The entry PG to start playback, in conjunction with @option{pgc}.
Alternative to setting @option{title}.
Chapter markers are not supported at this time.
Default is 0, automatically resolve from value of @option{title}, or
start from the beginning (PG 1) of the menu.
@item preindex @var{bool}
Enable this to have accurate chapter (PTT) markers and duration measurement,
which requires a slow second pass read in order to index the chapter marker
timestamps from NAV packets. This is non-ideal extra work for real optical drives.
It is recommended and faster to use this option with a backup of the DVD structure
stored on a hard drive. Not compatible with @option{pgc} and @option{pg}.
Not applicable to menus.
Default is 0, false.
@item trim @var{bool}
Skip padding cells (i.e. cells shorter than 1 second) from the beginning.
There exist many discs with filler segments at the beginning of the PGC,
often with junk data intended for controlling a real DVD player's
buffering speed and with no other material data value.
Not applicable to menus.
Default is 1, true.
@end table
@subsection Examples
@itemize
@item
Open title 3 from a given DVD structure:
@example
ffmpeg -f dvdvideo -title 3 -i <path to DVD> ...
@end example
@item
Open chapters 3-6 from title 1 from a given DVD structure:
@example
ffmpeg -f dvdvideo -chapter_start 3 -chapter_end 6 -title 1 -i <path to DVD> ...
@end example
@item
Open only chapter 5 from title 1 from a given DVD structure:
@example
ffmpeg -f dvdvideo -chapter_start 5 -chapter_end 5 -title 1 -i <path to DVD> ...
@end example
@item
Demux menu with language 1 from VTS 1, PGC 1, starting at PG 1:
@example
ffmpeg -f dvdvideo -menu 1 -menu_lu 1 -menu_vts 1 -pgc 1 -pg 1 -i <path to DVD> ...
@end example
@end itemize
@section ea @section ea
Electronic Arts Multimedia format demuxer. Electronic Arts Multimedia format demuxer.
@@ -307,7 +469,15 @@ stream which contains the alpha channel in addition to the ordinary video.
Interoperable Master Format demuxer. Interoperable Master Format demuxer.
This demuxer presents audio and video streams found in an IMF Composition. This demuxer presents audio and video streams found in an IMF Composition, as
specified in @url{https://doi.org/10.5594/SMPTE.ST2067-2.2020, SMPTE ST 2067-2}.
@example
ffmpeg [-assetmaps <path of ASSETMAP1>,<path of ASSETMAP2>,...] -i <path of CPL> ...
@end example
If @code{-assetmaps} is not specified, the demuxer looks for a file called
@file{ASSETMAP.xml} in the same directory as the CPL.
@section flv, live_flv, kux @section flv, live_flv, kux
@@ -769,8 +939,15 @@ error or used to store a negative value for dts correction when treated as signe
the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when
cast to int32 are used to adjust onward dts. cast to int32 are used to adjust onward dts.
Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows up to
a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range. a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range.
@item interleaved_read
Interleave packets from multiple tracks at demuxer level. For badly interleaved files, this prevents playback issues
caused by large gaps between packets in different tracks, as MOV/MP4 do not have packet placement requirements.
However, this can cause excessive seeking on very badly interleaved files, due to seeking between tracks, so disabling
it may prevent I/O issues, at the expense of playback.
@end table @end table
@subsection Audible AAX @subsection Audible AAX
@@ -928,4 +1105,27 @@ which in turn, acts as a ceiling for the size of scripts that can be read.
Default is 1 MiB. Default is 1 MiB.
@end table @end table
@section w64
Sony Wave64 Audio demuxer.
This demuxer accepts the following options:
@table @option
@item max_size
See the same option for the @ref{wav} demuxer.
@end table
@anchor{wav}
@section wav
RIFF Wave Audio demuxer.
This demuxer accepts the following options:
@table @option
@item max_size
Specify the maximum packet size in bytes for the demuxed packets. By default
this is set to 0, which means that a sensible value is chosen based on the
input format.
@end table
@c man end DEMUXERS @c man end DEMUXERS
-82
View File
@@ -1,82 +0,0 @@
# 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.
A script to generate the current members of the general assembly (minus members
voted in) can be found in `tools/general_assembly.pl`.
## 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.
-91
View File
@@ -1,91 +0,0 @@
# 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.
+258 -105
View File
@@ -24,6 +24,10 @@ generated from the headers
the examples under @file{doc/examples} the examples under @file{doc/examples}
@end itemize @end itemize
For more detailed legal information about the use of FFmpeg in
external programs read the @file{LICENSE} file in the source tree and
consult @url{https://ffmpeg.org/legal.html}.
If you modify FFmpeg code for your own use case, you are highly encouraged to If you modify FFmpeg code for your own use case, you are highly encouraged to
@emph{submit your changes back to us}, using this document as a guide. There are @emph{submit your changes back to us}, using this document as a guide. There are
both pragmatic and ideological reasons to do so: both pragmatic and ideological reasons to do so:
@@ -40,12 +44,6 @@ By supporting the project you find useful you ensure it continues to be
maintained and developed. maintained and developed.
@end itemize @end itemize
For more detailed legal information about the use of FFmpeg in
external programs read the @file{LICENSE} file in the source tree and
consult @url{https://ffmpeg.org/legal.html}.
@section Contributing code
All proposed code changes should be submitted for review to All proposed code changes should be submitted for review to
@url{mailto:ffmpeg-devel@@ffmpeg.org, the development mailing list}, as @url{mailto:ffmpeg-devel@@ffmpeg.org, the development mailing list}, as
described in more detail in the @ref{Submitting patches} chapter. The code described in more detail in the @ref{Submitting patches} chapter. The code
@@ -56,16 +54,10 @@ and should try to fix issues their commit causes.
@anchor{Coding Rules} @anchor{Coding Rules}
@chapter Coding Rules @chapter Coding Rules
@section C language features @section Language
FFmpeg is programmed in the ISO C99 language, extended with: FFmpeg is mainly programmed in the ISO C11 language, except for the public
@itemize @bullet headers which must stay C99 compatible.
@item
Atomic operations from C11 @file{stdatomic.h}. They are emulated on
architectures/compilers that do not support them, so all FFmpeg-internal code
may use atomics without any extra checks. However, @file{stdatomic.h} must not
be included in public headers, so they stay C99-compatible.
@end itemize
Compiler-specific extensions may be used with good reason, but must not be Compiler-specific extensions may be used with good reason, but must not be
depended on, i.e. the code must still compile and work with compilers lacking depended on, i.e. the code must still compile and work with compilers lacking
@@ -83,6 +75,44 @@ complex numbers;
mixed statements and declarations. mixed statements and declarations.
@end itemize @end itemize
@subsection SIMD/DSP
@anchor{SIMD/DSP}
As modern compilers are unable to generate efficient SIMD or other
performance-critical DSP code from plain C, handwritten assembly is used.
Usually such code is isolated in a separate function. Then the standard approach
is writing multiple versions of this function a plain C one that works
everywhere and may also be useful for debugging, and potentially multiple
architecture-specific optimized implementations. Initialization code then
chooses the best available version at runtime and loads it into a function
pointer; the function in question is then always called through this pointer.
The specific syntax used for writing assembly is:
@itemize @bullet
@item
NASM on x86;
@item
GAS on ARM and RISC-V.
@end itemize
A unit testing framework for assembly called @code{checkasm} lives under
@file{tests/checkasm}. All new assembly should come with @code{checkasm} tests;
adding tests for existing assembly that lacks them is also strongly encouraged.
@subsection Other languages
Other languages than C may be used in special cases:
@itemize @bullet
@item
Compiler intrinsics or inline assembly when the code in question cannot be
written in the standard way described in the @ref{SIMD/DSP} section. This
typically applies to code that needs to be inlined.
@item
Objective-C where required for interacting with macOS-specific interfaces.
@end itemize
@section Code formatting conventions @section Code formatting conventions
There are the following guidelines regarding the indentation in files: There are the following guidelines regarding the indentation in files:
@@ -179,6 +209,7 @@ int myfunc(int my_parameter)
... ...
@end example @end example
@anchor{Naming conventions}
@section Naming conventions @section Naming conventions
Names of functions, variables, and struct members must be lowercase, using Names of functions, variables, and struct members must be lowercase, using
@@ -237,10 +268,6 @@ symbols. If in doubt, just avoid names starting with @code{_} altogether.
@section Miscellaneous conventions @section Miscellaneous conventions
@itemize @bullet @itemize @bullet
@item
fprintf and printf are forbidden in libavformat and libavcodec,
please use av_log() instead.
@item @item
Casts should be used only when necessary. Unneeded parentheses Casts should be used only when necessary. Unneeded parentheses
should also be avoided if they don't make the code easier to understand. should also be avoided if they don't make the code easier to understand.
@@ -249,6 +276,42 @@ should also be avoided if they don't make the code easier to understand.
@anchor{Development Policy} @anchor{Development Policy}
@chapter Development Policy @chapter Development Policy
@section Code behaviour
@subheading Correctness
The code must be valid. It must not crash, abort, access invalid pointers, leak
memory, cause data races or signed integer overflow, or otherwise cause
undefined behaviour. Error codes should be checked and, when applicable,
forwarded to the caller.
@subheading Thread- and library-safety
Our libraries may be called by multiple independent callers in the same process.
These calls may happen from any number of threads and the different call sites
may not be aware of each other - e.g. a user program may be calling our
libraries directly, and use one or more libraries that also call our libraries.
The code must behave correctly under such conditions.
@subheading Robustness
The code must treat as untrusted any bytestream received from a caller or read
from a file, network, etc. It must not misbehave when arbitrary data is sent to
it - typically it should print an error message and return
@code{AVERROR_INVALIDDATA} on encountering invalid input data.
@subheading Memory allocation
The code must use the @code{av_malloc()} family of functions from
@file{libavutil/mem.h} to perform all memory allocation, except in special cases
(e.g. when interacting with an external library that requires a specific
allocator to be used).
All allocations should be checked and @code{AVERROR(ENOMEM)} returned on
failure. A common mistake is that error paths leak memory - make sure that does
not happen.
@subheading stdio
Our libraries must not access the stdio streams stdin/stdout/stderr directly
(e.g. via @code{printf()} family of functions), as that is not library-safe. For
logging, use @code{av_log()}.
@section Patches/Committing @section Patches/Committing
@subheading Licenses for patches must be compatible with FFmpeg. @subheading Licenses for patches must be compatible with FFmpeg.
Contributions should be licensed under the Contributions should be licensed under the
@@ -271,13 +334,24 @@ missing samples or an implementation with a small subset of features.
Always check the mailing list for any reviewers with issues and test Always check the mailing list for any reviewers with issues and test
FATE before you push. FATE before you push.
@subheading Keep the main commit message short with an extended description below. @subheading Commit messages
The commit message should have a short first line in the form of Commit messages are highly important tools for informing other developers on
a @samp{topic: short description} as a header, separated by a newline what a given change does and why. Every commit must always have a properly
from the body consisting of an explanation of why the change is necessary. filled out commit message with the following format:
If the commit fixes a known bug on the bug tracker, the commit message @example
should include its bug ID. Referring to the issue on the bug tracker does area changed: short 1 line description
not exempt you from writing an excerpt of the bug in the commit message.
details describing what and why and giving references.
@end example
If the commit addresses a known bug on our bug tracker or other external issue
(e.g. CVE), the commit message should include the relevant bug ID(s) or other
external identifiers. Note that this should be done in addition to a proper
explanation and not instead of it. Comments such as "fixed!" or "Changed it."
are not acceptable.
When applying patches that have been discussed at length on the mailing list,
reference the thread in the commit message.
@subheading Testing must be adequate but not excessive. @subheading Testing must be adequate but not excessive.
If it works for you, others, and passes FATE then it should be OK to commit If it works for you, others, and passes FATE then it should be OK to commit
@@ -296,15 +370,6 @@ later on.
Also if you have doubts about splitting or not splitting, do not hesitate to Also if you have doubts about splitting or not splitting, do not hesitate to
ask/discuss it on the developer mailing list. ask/discuss it on the developer mailing list.
@subheading Ask before you change the build system (configure, etc).
Do not commit changes to the build system (Makefiles, configure script)
which change behavior, defaults etc, without asking first. The same
applies to compiler warning fixes, trivial looking fixes and to code
maintained by other developers. We usually have a reason for doing things
the way we do. Send your changes as patches to the ffmpeg-devel mailing
list, and if the code maintainers say OK, you may commit. This does not
apply to files you wrote and/or maintain.
@subheading Cosmetic changes should be kept in separate patches. @subheading Cosmetic changes should be kept in separate patches.
We refuse source indentation and other cosmetic changes if they are mixed We refuse source indentation and other cosmetic changes if they are mixed
with functional changes, such commits will be rejected and removed. Every with functional changes, such commits will be rejected and removed. Every
@@ -319,27 +384,15 @@ NOTE: If you had to put if()@{ .. @} over a large (> 5 lines) chunk of code,
then either do NOT change the indentation of the inner part within (do not then either do NOT change the indentation of the inner part within (do not
move it to the right)! or do so in a separate commit move it to the right)! or do so in a separate commit
@subheading Commit messages should always be filled out properly.
Always fill out the commit log message. Describe in a few lines what you
changed and why. You can refer to mailing list postings if you fix a
particular bug. Comments such as "fixed!" or "Changed it." are unacceptable.
Recommended format:
@example
area changed: Short 1 line description
details describing what and why and giving references.
@end example
@subheading Credit the author of the patch. @subheading Credit the author of the patch.
Make sure the author of the commit is set correctly. (see git commit --author) Make sure the author of the commit is set correctly. (see git commit --author)
If you apply a patch, send an If you apply a patch, send an
answer to ffmpeg-devel (or wherever you got the patch from) saying that answer to ffmpeg-devel (or wherever you got the patch from) saying that
you applied the patch. you applied the patch.
@subheading Complex patches should refer to discussion surrounding them. @subheading Credit any researchers
When applying patches that have been discussed (at length) on the mailing If a commit/patch fixes an issues found by some researcher, always credit the
list, reference the thread in the log message. researcher in the commit message for finding/reporting the issue.
@subheading Always wait long enough before pushing changes @subheading Always wait long enough before pushing changes
Do NOT commit to code actively maintained by others without permission. Do NOT commit to code actively maintained by others without permission.
@@ -349,22 +402,6 @@ time-frame (12h for build failures and security fixes, 3 days small changes,
Also note, the maintainer can simply ask for more time to review! Also note, the maintainer can simply ask for more time to review!
@section Code @section Code
@subheading API/ABI changes should be discussed before they are made.
Do not change behavior of the programs (renaming options etc) or public
API or ABI without first discussing it on the ffmpeg-devel mailing list.
Do not remove widely used functionality or features (redundant code can be removed).
@subheading Remember to check if you need to bump versions for libav*.
Depending on the change, you may need to change the version integer.
Incrementing the first component means no backward compatibility to
previous versions (e.g. removal of a function from the public API).
Incrementing the second component means backward compatible change
(e.g. addition of a function to the public API or extension of an
existing data structure).
Incrementing the third component means a noteworthy binary compatible
change (e.g. encoder bug fix that matters for the decoder). The third
component always starts at 100 to distinguish FFmpeg from Libav.
@subheading Warnings for correct code may be disabled if there is no other option. @subheading Warnings for correct code may be disabled if there is no other option.
Compiler warnings indicate potential bugs or code with bad style. If a type of Compiler warnings indicate potential bugs or code with bad style. If a type of
warning always points to correct and clean code, that warning should warning always points to correct and clean code, that warning should
@@ -374,10 +411,150 @@ If it is a bug, the bug has to be fixed. If it is not, the code should
be changed to not generate a warning unless that causes a slowdown be changed to not generate a warning unless that causes a slowdown
or obfuscates the code. or obfuscates the code.
@subheading Check untrusted input properly. @section Library public interfaces
Never write to unallocated memory, never write over the end of arrays, Every library in FFmpeg provides a set of public APIs in its installed headers,
always check values read from some untrusted source before using them which are those listed in the variable @code{HEADERS} in that library's
as array index or other risky things. @file{Makefile}. All identifiers defined in those headers (except for those
explicitly documented otherwise), and corresponding symbols exported from
compiled shared or static libraries are considered public interfaces and must
comply with the API and ABI compatibility rules described in this section.
Public APIs must be backward compatible within a given major version. I.e. any
valid user code that compiles and works with a given library version must still
compile and work with any later version, as long as the major version number is
unchanged. "Valid user code" here means code that is calling our APIs in a
documented and/or intended manner and is not relying on any undefined behavior.
Incrementing the major version may break backward compatibility, but only to the
extent described in @ref{Major version bumps}.
We also guarantee backward ABI compatibility for shared and static libraries.
I.e. it should be possible to replace a shared or static build of our library
with a build of any later version (re-linking the user binary in the static
case) without breaking any valid user binaries, as long as the major version
number remains unchanged.
@subsection Adding new interfaces
Any new public identifiers in installed headers are considered new API - this
includes new functions, structs, macros, enum values, typedefs, new fields in
existing structs, new installed headers, etc. Consider the following
guidelines when adding new APIs.
@subsubheading Motivation
While new APIs can be added relatively easily, changing or removing them is much
harder due to abovementioned compatibility requirements. You should then
consider carefully whether the functionality you are adding really needs to be
exposed to our callers as new public API.
Your new API should have at least one well-established use case outside of the
library that cannot be easily achieved with existing APIs. Every library in
FFmpeg also has a defined scope - your new API must fit within it.
@subsubheading Replacing existing APIs
If your new API is replacing an existing one, it should be strictly superior to
it, so that the advantages of using the new API outweight the cost to the
callers of changing their code. After adding the new API you should then
deprecate the old one and schedule it for removal, as described in
@ref{Removing interfaces}.
If you deem an existing API deficient and want to fix it, the preferred approach
in most cases is to add a differently-named replacement and deprecate the
existing API rather than modify it. It is important to make the changes visible
to our callers (e.g. through compile- or run-time deprecation warnings) and make
it clear how to transition to the new API (e.g. in the Doxygen documentation or
on the wiki).
@subsubheading API design
The FFmpeg libraries are used by a variety of callers to perform a wide range of
multimedia-related processing tasks. You should therefore - within reason - try
to design your new API for the broadest feasible set of use cases and avoid
unnecessarily limiting it to a specific type of callers (e.g. just media
playback or just transcoding).
@subsubheading Consistency
Check whether similar APIs already exist in FFmpeg. If they do, try to model
your new addition on them to achieve better overall consistency.
The naming of your new identifiers should follow the @ref{Naming conventions}
and be aligned with other similar APIs, if applicable.
@subsubheading Extensibility
You should also consider how your API might be extended in the future in a
backward-compatible way. If you are adding a new struct @code{AVFoo}, the
standard approach is requiring the caller to always allocate it through a
constructor function, typically named @code{av_foo_alloc()}. This way new fields
may be added to the end of the struct without breaking ABI compatibility.
Typically you will also want a destructor - @code{av_foo_free(AVFoo**)} that
frees the indirectly supplied object (and its contents, if applicable) and
writes @code{NULL} to the supplied pointer, thus eliminating the potential
dangling pointer in the caller's memory.
If you are adding new functions, consider whether it might be desirable to tweak
their behavior in the future - you may want to add a flags argument, even though
it would be unused initially.
@subsubheading Documentation
All new APIs must be documented as Doxygen-formatted comments above the
identifiers you add to the public headers. You should also briefly mention the
change in @file{doc/APIchanges}.
@subsubheading Bump the version
Backward-incompatible API or ABI changes require incrementing (bumping) the
major version number, as described in @ref{Major version bumps}. Major
bumps are significant events that happen on a schedule - so if your change
strictly requires one you should add it under @code{#if} preprocesor guards that
disable it until the next major bump happens.
New APIs that can be added without breaking API or ABI compatibility require
bumping the minor version number.
Incrementing the third (micro) version component means a noteworthy binary
compatible change (e.g. encoder bug fix that matters for the decoder). The third
component always starts at 100 to distinguish FFmpeg from Libav.
@anchor{Removing interfaces}
@subsection Removing interfaces
Due to abovementioned compatibility guarantees, removing APIs is an involved
process that should only be undertaken with good reason. Typically a deficient,
restrictive, or otherwise inadequate API is replaced by a superior one, though
it does at times happen that we remove an API without any replacement (e.g. when
the feature it provides is deemed not worth the maintenance effort, out of scope
of the project, fundamentally flawed, etc.).
The removal has two steps - first the API is deprecated and scheduled for
removal, but remains present and functional. The second step is actually
removing the API - this is described in @ref{Major version bumps}.
To deprecate an API you should signal to our users that they should stop using
it. E.g. if you intend to remove struct members or functions, you should mark
them with @code{attribute_deprecated}. When this cannot be done, it may be
possible to detect the use of the deprecated API at runtime and print a warning
(though take care not to print it too often). You should also document the
deprecation (and the replacement, if applicable) in the relevant Doxygen
documentation block.
Finally, you should define a deprecation guard along the lines of
@code{#define FF_API_<FOO> (LIBAVBAR_VERSION_MAJOR < XX)} (where XX is the major
version in which the API will be removed) in @file{libavbar/version_major.h}
(@file{version.h} in case of @code{libavutil}). Then wrap all uses of the
deprecated API in @code{#if FF_API_<FOO> .... #endif}, so that the code will
automatically get disabled once the major version reaches XX. You can also use
@code{FF_DISABLE_DEPRECATION_WARNINGS} and @code{FF_ENABLE_DEPRECATION_WARNINGS}
to suppress compiler deprecation warnings inside these guards. You should test
that the code compiles and works with the guard macro evaluating to both true
and false.
@anchor{Major version bumps}
@subsection Major version bumps
A major version bump signifies an API and/or ABI compatibility break. To reduce
the negative effects on our callers, who are required to adapt their code,
backward-incompatible changes during a major bump should be limited to:
@itemize @bullet
@item
Removing previously deprecated APIs.
@item
Performing ABI- but not API-breaking changes, like reordering struct contents.
@end itemize
@section Documentation/Other @section Documentation/Other
@subheading Subscribe to the ffmpeg-devel mailing list. @subheading Subscribe to the ffmpeg-devel mailing list.
@@ -421,35 +598,6 @@ finding a new maintainer and also don't forget to update the @file{MAINTAINERS}
We think our rules are not too hard. If you have comments, contact us. We think our rules are not too hard. If you have comments, contact us.
@chapter Code of conduct
Be friendly and respectful towards others and third parties.
Treat others the way you yourself want to be treated.
Be considerate. Not everyone shares the same viewpoint and priorities as you do.
Different opinions and interpretations help the project.
Looking at issues from a different perspective assists development.
Do not assume malice for things that can be attributed to incompetence. Even if
it is malice, it's rarely good to start with that as initial assumption.
Stay friendly even if someone acts contrarily. Everyone has a bad day
once in a while.
If you yourself have a bad day or are angry then try to take a break and reply
once you are calm and without anger if you have to.
Try to help other team members and cooperate if you can.
The goal of software development is to create technical excellence, not for any
individual to be better and "win" against the others. Large software projects
are only possible and successful through teamwork.
If someone struggles do not put them down. Give them a helping hand
instead and point them in the right direction.
Finally, keep in mind the immortal words of Bill and Ted,
"Be excellent to each other."
@anchor{Submitting patches} @anchor{Submitting patches}
@chapter Submitting patches @chapter Submitting patches
@@ -490,6 +638,11 @@ patch is inline or attached per mail.
You can check @url{https://patchwork.ffmpeg.org}, if your patch does not show up, its mime type You can check @url{https://patchwork.ffmpeg.org}, if your patch does not show up, its mime type
likely was wrong. likely was wrong.
@subheading How to setup git send-email?
Please see @url{https://git-send-email.io/}.
For gmail additionally see @url{https://shallowsky.com/blog/tech/email/gmail-app-passwds.html}.
@subheading Sending patches from email clients @subheading Sending patches from email clients
Using @code{git send-email} might not be desirable for everyone. The Using @code{git send-email} might not be desirable for everyone. The
following trick allows to send patches via email clients in a safe following trick allows to send patches via email clients in a safe
@@ -666,16 +819,14 @@ Lines with similar content should be aligned vertically when doing so
improves readability. improves readability.
@item @item
Consider adding a regression test for your code. Consider adding a regression test for your code. All new modules
should be covered by tests. That includes demuxers, muxers, decoders, encoders
filters, bitstream filters, parsers. If its not possible to do that, add
an explanation why to your patchset, its ok to not test if theres a reason.
@item @item
If you added YASM code please check that things still work with --disable-yasm. If you added YASM code please check that things still work with --disable-yasm.
@item
Make sure you check the return values of function and return appropriate
error codes. Especially memory allocation functions like @code{av_malloc()}
are notoriously left unchecked, which is a serious problem.
@item @item
Test your code with valgrind and or Address Sanitizer to ensure it's free Test your code with valgrind and or Address Sanitizer to ensure it's free
of leaks, out of array accesses, etc. of leaks, out of array accesses, etc.
@@ -725,6 +876,8 @@ accordingly].
@section Adding files to the fate-suite dataset @section Adding files to the fate-suite dataset
If you need a sample uploaded send a mail to samples-request.
When there is no muxer or encoder available to generate test media for a When there is no muxer or encoder available to generate test media for a
specific test then the media has to be included in the fate-suite. specific test then the media has to be included in the fate-suite.
First please make sure that the sample file is as small as possible to test the First please make sure that the sample file is as small as possible to test the
+201 -52
View File
@@ -615,7 +615,7 @@ and slightly improves compression.
Opus encoder. Opus encoder.
This is a native FFmpeg encoder for the Opus format. Currently its in development and This is a native FFmpeg encoder for the Opus format. Currently, it's in development and
only implements the CELT part of the codec. Its quality is usually worse and at best only implements the CELT part of the codec. Its quality is usually worse and at best
is equal to the libopus encoder. is equal to the libopus encoder.
@@ -789,6 +789,11 @@ about 80-96 kbps/channel
@end table @end table
Default value is 0. Default value is 0.
@item frame_length
Set the audio frame length in samples. Default value is the internal
default of the library. Refer to the library's documentation for information
about supported values.
@end table @end table
@subsection Examples @subsection Examples
@@ -859,6 +864,13 @@ Enable the encoder to use ABR when set to 1. The @command{lame}
@option{--abr} sets the target bitrate, while this options only @option{--abr} sets the target bitrate, while this options only
tells FFmpeg to use ABR still relies on @option{b} to set bitrate. tells FFmpeg to use ABR still relies on @option{b} to set bitrate.
@item copyright (@emph{-c})
Set MPEG audio copyright flag when set to 1. The default value is 0
(disabled).
@item original (@emph{-o})
Set MPEG audio original flag when set to 1. The default value is 1
(enabled).
@end table @end table
@section libopencore-amrnb @section libopencore-amrnb
@@ -965,14 +977,17 @@ Favor improved speech intelligibility.
@item audio @item audio
Favor faithfulness to the input (the default). Favor faithfulness to the input (the default).
@item lowdelay @item lowdelay
Restrict to only the lowest delay modes. Restrict to only the lowest delay modes by disabling voice-optimized
modes.
@end table @end table
@item cutoff (N.A.) @item cutoff (N.A.)
Set cutoff bandwidth in Hz. The argument must be exactly one of the Set cutoff bandwidth in Hz. The argument must be exactly one of the
following: 4000, 6000, 8000, 12000, or 20000, corresponding to following: 4000, 6000, 8000, 12000, or 20000, corresponding to
narrowband, mediumband, wideband, super wideband, and fullband narrowband, mediumband, wideband, super wideband, and fullband
respectively. The default is 0 (cutoff disabled). respectively. The default is 0 (cutoff disabled). Note that libopus
forces a wideband cutoff for bitrates < 15 kbps, unless CELT-only
(@option{application} set to @samp{lowdelay}) mode is used.
@item mapping_family (@emph{mapping_family}) @item mapping_family (@emph{mapping_family})
Set channel mapping family to be used by the encoder. The default value of -1 Set channel mapping family to be used by the encoder. The default value of -1
@@ -2222,6 +2237,12 @@ the two temporal layer 2 frames within the temporal period.
@end table @end table
@end table @end table
@item VP8-specific options
@table @option
@item screen-content-mode
Screen content mode, one of: 0 (off), 1 (screen), 2 (screen with more aggressive rate control).
@end table
@item VP9-specific options @item VP9-specific options
@table @option @table @option
@item lossless @item lossless
@@ -2406,6 +2427,10 @@ To get a more accurate and extensive documentation of the libx264
options, invoke the command @command{x264 --fullhelp} or consult options, invoke the command @command{x264 --fullhelp} or consult
the libx264 documentation. the libx264 documentation.
In the list below, note that the @command{x264} option name is shown
in parentheses after the libavcodec corresponding name, in case there
is a direct mapping.
@table @option @table @option
@item b (@emph{bitrate}) @item b (@emph{bitrate})
Set bitrate in bits/s. Note that FFmpeg's @option{b} option is Set bitrate in bits/s. Note that FFmpeg's @option{b} option is
@@ -2413,17 +2438,19 @@ expressed in bits/s, while @command{x264}'s @option{bitrate} is in
kilobits/s. kilobits/s.
@item bf (@emph{bframes}) @item bf (@emph{bframes})
Number of B-frames between I and P-frames
@item g (@emph{keyint}) @item g (@emph{keyint})
Maximum GOP size
@item qmin (@emph{qpmin}) @item qmin (@emph{qpmin})
Minimum quantizer scale. Minimum quantizer scale
@item qmax (@emph{qpmax}) @item qmax (@emph{qpmax})
Maximum quantizer scale. Maximum quantizer scale
@item qdiff (@emph{qpstep}) @item qdiff (@emph{qpstep})
Maximum difference between quantizer scales. Maximum difference between quantizer scales
@item qblur (@emph{qblur}) @item qblur (@emph{qblur})
Quantizer curve blur Quantizer curve blur
@@ -2432,7 +2459,21 @@ Quantizer curve blur
Quantizer curve compression factor Quantizer curve compression factor
@item refs (@emph{ref}) @item refs (@emph{ref})
Number of reference frames each P-frame can use. The range is from @var{0-16}. Number of reference frames each P-frame can use. The range is @var{0-16}.
@item level (@emph{level})
Set the @code{x264_param_t.i_level_idc} value in case the value is
positive, it is ignored otherwise.
This value can be set using the @code{AVCodecContext} API (e.g. by
setting the @code{AVCodecContext} value directly), and is specified as
an integer mapped on a corresponding level (e.g. the value 31 maps
to H.264 level IDC "3.1", as defined in the @code{x264_levels}
table). It is ignored when set to a non positive value.
Alternatively it can be set as a private option, overriding the value
set in @code{AVCodecContext}, and in this case must be specified as
the level IDC identifier (e.g. "3.1"), as defined by H.264 Annex A.
@item sc_threshold (@emph{scenecut}) @item sc_threshold (@emph{scenecut})
Sets the threshold for the scene change detection. Sets the threshold for the scene change detection.
@@ -2440,7 +2481,8 @@ Sets the threshold for the scene change detection.
@item trellis (@emph{trellis}) @item trellis (@emph{trellis})
Performs Trellis quantization to increase efficiency. Enabled by default. Performs Trellis quantization to increase efficiency. Enabled by default.
@item nr (@emph{nr}) @item nr (@emph{nr})
Noise reduction
@item me_range (@emph{merange}) @item me_range (@emph{merange})
Maximum range of the motion search in pixels. Maximum range of the motion search in pixels.
@@ -2521,6 +2563,7 @@ open GOP by setting it to @code{-cgop}. The result is similar to
the behavior of @command{x264}'s @option{--open-gop} option. the behavior of @command{x264}'s @option{--open-gop} option.
@item rc_init_occupancy (@emph{vbv-init}) @item rc_init_occupancy (@emph{vbv-init})
Initial VBV buffer occupancy
@item preset (@emph{preset}) @item preset (@emph{preset})
Set the encoding preset. Set the encoding preset.
@@ -2566,7 +2609,7 @@ Set AQ strength, reduce blocking and blurring in flat and textured areas.
Use psychovisual optimizations when set to 1. When set to 0, it has the Use psychovisual optimizations when set to 1. When set to 0, it has the
same effect as @command{x264}'s @option{--no-psy} option. same effect as @command{x264}'s @option{--no-psy} option.
@item psy-rd (@emph{psy-rd}) @item psy-rd (@emph{psy-rd})
Set strength of psychovisual optimization, in Set strength of psychovisual optimization, in
@var{psy-rd}:@var{psy-trellis} format. @var{psy-rd}:@var{psy-trellis} format.
@@ -2598,7 +2641,7 @@ to 1.
@item avcintra-class (@emph{class}) @item avcintra-class (@emph{class})
Configure the encoder to generate AVC-Intra. Configure the encoder to generate AVC-Intra.
Valid values are 50,100 and 200 Valid values are 50, 100 and 200
@item bluray-compat (@emph{bluray-compat}) @item bluray-compat (@emph{bluray-compat})
Configure the encoder to be compatible with the bluray standard. Configure the encoder to be compatible with the bluray standard.
@@ -2649,8 +2692,8 @@ Set loop filter parameters, in @var{alpha}:@var{beta} form.
Set fluctuations reduction in QP (before curve compression). Set fluctuations reduction in QP (before curve compression).
@item partitions (@emph{partitions}) @item partitions (@emph{partitions})
Set partitions to consider as a comma-separated list of. Possible Set partitions to consider as a comma-separated list of values.
values in the list: Possible values in the list:
@table @samp @table @samp
@item p8x8 @item p8x8
@@ -2706,19 +2749,32 @@ Variable bit rate.
Constant bit rate (not allowed in MP4 container). Constant bit rate (not allowed in MP4 container).
@end table @end table
@item x264opts (N.A.) @item x264opts @var{opts}
Set any x264 option, see @command{x264 --fullhelp} for a list. @item x264-params @var{opts}
Override the x264 configuration using a :-separated list of key=value
options.
Argument is a list of @var{key}=@var{value} couples separated by The argument for both options is a list of @var{key}=@var{value}
":". In @var{filter} and @var{psy-rd} options that use ":" as a separator couples separated by ":". With @option{x264opts} the value can be
themselves, use "," instead. They accept it as well since long ago but this omitted, and the value @code{1} is assumed in that case.
is kept undocumented for some reason.
For @var{filter} and @var{psy-rd} options values that use ":" as a
separator themselves, use "," instead. They accept it as well since
long ago but this is kept undocumented for some reason.
For example, the options might be provided as:
@example
level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subq=6:8x8dct=0:trellis=0
@end example
For example to specify libx264 encoding options with @command{ffmpeg}: For example to specify libx264 encoding options with @command{ffmpeg}:
@example @example
ffmpeg -i foo.mpg -c:v libx264 -x264opts keyint=123:min-keyint=20 -an out.mkv ffmpeg -i foo.mpg -c:v libx264 -x264opts keyint=123:min-keyint=20 -an out.mkv
@end example @end example
To get the complete list of the libx264 options, invoke the command
@command{x264 --fullhelp} or consult the libx264 documentation.
@item a53cc @var{boolean} @item a53cc @var{boolean}
Import closed captions (which must be ATSC compatible format) into output. Import closed captions (which must be ATSC compatible format) into output.
Only the mpeg2 and h264 decoders provide these. Default is 1 (on). Only the mpeg2 and h264 decoders provide these. Default is 1 (on).
@@ -2726,19 +2782,9 @@ Only the mpeg2 and h264 decoders provide these. Default is 1 (on).
@item udu_sei @var{boolean} @item udu_sei @var{boolean}
Import user data unregistered SEI if available into output. Default is 0 (off). Import user data unregistered SEI if available into output. Default is 0 (off).
@item x264-params (N.A.) @item mb_info @var{boolean}
Override the x264 configuration using a :-separated list of key=value Set mb_info data through AVFrameSideData, only useful when used from the
parameters. API. Default is 0 (off).
This option is functionally the same as the @option{x264opts}, but is
duplicated for compatibility with the Libav fork.
For example to specify libx264 encoding options with @command{ffmpeg}:
@example
ffmpeg -i INPUT -c:v libx264 -x264-params level=30:bframes=0:weightp=0:\
cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:\
no-fast-pskip=1:subq=6:8x8dct=0:trellis=0 OUTPUT
@end example
@end table @end table
Encoding ffpresets for common usages are provided so they can be used with the Encoding ffpresets for common usages are provided so they can be used with the
@@ -2878,6 +2924,75 @@ ffmpeg -i input -c:v libxavs2 -xavs2-params RdoqLevel=0 output.avs2
@end example @end example
@end table @end table
@section libxeve
eXtra-fast Essential Video Encoder (XEVE) MPEG-5 EVC encoder wrapper.
The xeve-equivalent options or values are listed in parentheses for easy migration.
This encoder requires the presence of the libxeve headers and library
during configuration. You need to explicitly configure the build with
@option{--enable-libxeve}.
@float NOTE
Many libxeve encoder options are mapped to FFmpeg global codec options,
while unique encoder options are provided through private options.
Additionally the xeve-params private options allows one to pass a list
of key=value tuples as accepted by the libxeve @code{parse_xeve_params} function.
@end float
The xeve project website is at @url{https://github.com/mpeg5/xeve}.
@subsection Options
The following options are supported by the libxeve wrapper.
The xeve-equivalent options or values are listed in parentheses for easy migration.
@float NOTE
To reduce the duplication of documentation, only the private options
and some others requiring special attention are documented here. For
the documentation of the undocumented generic options, see
@ref{codec-options,,the Codec Options chapter}.
@end float
@float NOTE
To get a more accurate and extensive documentation of the libxeve options,
invoke the command @code{xeve_app --help} or consult the libxeve documentation.
@end float
@table @option
@item b (@emph{bitrate})
Set target video bitrate in bits/s.
Note that FFmpeg's b option is expressed in bits/s, while xeve's bitrate is in kilobits/s.
@item bf (@emph{bframes})
Set the maximum number of B frames (1,3,7,15).
@item g (@emph{keyint})
Set the GOP size (I-picture period).
@item preset (@emph{preset})
Set the xeve preset.
Set the encoder preset value to determine encoding speed [fast, medium, slow, placebo]
@item tune (@emph{tune})
Set the encoder tune parameter [psnr, zerolatency]
@item profile (@emph{profile})
Set the encoder profile [0: baseline; 1: main]
@item crf (@emph{crf})
Set the quality for constant quality mode.
Constant rate factor <10..49> [default: 32]
@item qp (@emph{qp})
Set constant quantization rate control method parameter.
Quantization parameter qp <0..51> [default: 32]
@item threads (@emph{threads})
Force to use a specific number of threads
@end table
@section libxvid @section libxvid
Xvid MPEG-4 Part 2 encoder wrapper. Xvid MPEG-4 Part 2 encoder wrapper.
@@ -2930,9 +3045,6 @@ Enable high quality AC prediction.
@item gray @item gray
Only encode grayscale. Only encode grayscale.
@item gmc
Enable the use of global motion compensation (GMC).
@item qpel @item qpel
Enable quarter-pixel motion compensation. Enable quarter-pixel motion compensation.
@@ -2944,29 +3056,28 @@ Place global headers in extradata instead of every keyframe.
@end table @end table
@item trellis @item gmc
Enable the use of global motion compensation (GMC). Default is 0
(disabled).
@item me_method @item me_quality
Set motion estimation method. Possible values in decreasing order of Set motion estimation quality level. Possible values in decreasing order of
speed and increasing order of quality: speed and increasing order of quality:
@table @samp @table @samp
@item zero @item 0
Use no motion estimation (default). Use no motion estimation (default).
@item phods @item 1, 2
@item x1
@item log
Enable advanced diamond zonal search for 16x16 blocks and half-pixel Enable advanced diamond zonal search for 16x16 blocks and half-pixel
refinement for 16x16 blocks. @samp{x1} and @samp{log} are aliases for refinement for 16x16 blocks.
@samp{phods}.
@item epzs @item 3, 4
Enable all of the things described above, plus advanced diamond zonal Enable all of the things described above, plus advanced diamond zonal
search for 8x8 blocks, half-pixel refinement for 8x8 blocks, and motion search for 8x8 blocks and half-pixel refinement for 8x8 blocks, also
estimation on chroma planes. enable motion estimation on chroma planes for P and B-frames.
@item full @item 5, 6
Enable all of the things described above, plus extended 16x16 and 8x8 Enable all of the things described above, plus extended 16x16 and 8x8
blocks search. blocks search.
@end table @end table
@@ -3002,6 +3113,9 @@ be better than any of the two specified individually. In other
words, the resulting quality will be the worse one of the two words, the resulting quality will be the worse one of the two
effects. effects.
@item trellis
Set rate-distortion optimal quantization.
@item ssim @item ssim
Set structural similarity (SSIM) displaying method. Possible values: Set structural similarity (SSIM) displaying method. Possible values:
@@ -3049,6 +3163,20 @@ Video encoders can take input in either of nv12 or yuv420p form
(some encoders support both, some support only either - in practice, (some encoders support both, some support only either - in practice,
nv12 is the safer choice, especially among HW encoders). nv12 is the safer choice, especially among HW encoders).
@section Microsoft RLE
Microsoft RLE aka MSRLE encoder.
Only 8-bit palette mode supported.
Compatible with Windows 3.1 and Windows 95.
@subsection Options
@table @option
@item g @var{integer}
Keyframe interval.
A keyframe is inserted at least every @code{-g} frames, sometimes sooner.
@end table
@section mpeg2 @section mpeg2
MPEG-2 video encoder. MPEG-2 video encoder.
@@ -3188,8 +3316,8 @@ recommended value) and do not set a size constraint.
@section QSV Encoders @section QSV Encoders
The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG,
and VP9) VP9, AV1)
@subsection Ratecontrol Method @subsection Ratecontrol Method
The ratecontrol method is selected as follows: The ratecontrol method is selected as follows:
@@ -3212,8 +3340,8 @@ quality range is 1 to 51, with 1 being the best quality.
@end itemize @end itemize
@item @item
Otherwise, a bitrate-based mode is used. For all of those, you should specify at Otherwise when the desired average bitrate is specified with the @option{b}
least the desired average bitrate with the @option{b} option. option, a bitrate-based mode is used.
@itemize @minus @itemize @minus
@item @item
@var{LA} - VBR with lookahead, when the @option{look_ahead} option is specified. @var{LA} - VBR with lookahead, when the @option{look_ahead} option is specified.
@@ -3234,6 +3362,9 @@ than the average bitrate.
@option{avbr_accuracy} and @option{avbr_convergence} are set to non-zero. This @option{avbr_accuracy} and @option{avbr_convergence} are set to non-zero. This
mode is available for H264 and HEVC on Windows. mode is available for H264 and HEVC on Windows.
@end itemize @end itemize
@item
Otherwise the default ratecontrol method @var{CQP} is used.
@end itemize @end itemize
Note that depending on your system, a different mode than the one you specified Note that depending on your system, a different mode than the one you specified
@@ -3344,7 +3475,7 @@ Supported in h264_qsv.
Change these value to reset qsv codec's max/min qp configuration. Change these value to reset qsv codec's max/min qp configuration.
@item @var{low_delay_brc} @item @var{low_delay_brc}
Supported in h264_qsv and hevc_qsv. Supported in h264_qsv, hevc_qsv and av1_qsv.
Change this value to reset qsv codec's low_delay_brc configuration. Change this value to reset qsv codec's low_delay_brc configuration.
@item @var{framerate} @item @var{framerate}
@@ -3960,11 +4091,29 @@ Quality-defined variable-bitrate.
Average variable bitrate. Average variable bitrate.
@end table @end table
@item blbrc
Enable block level rate control, which assigns different bitrate block by block.
Invalid for CQP mode.
@end table @end table
Each encoder also has its own specific options: Each encoder also has its own specific options:
@table @option @table @option
@item av1_vaapi
@option{profile} sets the value of @emph{seq_profile}.
@option{tier} sets the value of @emph{seq_tier}.
@option{level} sets the value of @emph{seq_level_idx}.
@table @option
@item tiles
Set the number of tiles to encode the input video with, as columns x rows.
(default is auto, which means use minimal tile column/row number).
@item tile_groups
Set tile groups number. All the tiles will be distributed as evenly as possible to
each tile group. (default is 1).
@end table
@item h264_vaapi @item h264_vaapi
@option{profile} sets the value of @emph{profile_idc} and the @emph{constraint_set*_flag}s. @option{profile} sets the value of @emph{profile_idc} and the @emph{constraint_set*_flag}s.
@option{level} sets the value of @emph{level_idc}. @option{level} sets the value of @emph{level_idc}.
+4 -6
View File
@@ -78,9 +78,9 @@ static int output_video_frame(AVFrame *frame)
/* copy decoded frame to destination buffer: /* copy decoded frame to destination buffer:
* this is required since rawvideo expects non aligned data */ * this is required since rawvideo expects non aligned data */
av_image_copy(video_dst_data, video_dst_linesize, av_image_copy2(video_dst_data, video_dst_linesize,
(const uint8_t **)(frame->data), frame->linesize, frame->data, frame->linesize,
pix_fmt, width, height); pix_fmt, width, height);
/* write to rawvideo file */ /* write to rawvideo file */
fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file);
@@ -138,11 +138,9 @@ static int decode_packet(AVCodecContext *dec, const AVPacket *pkt)
ret = output_audio_frame(frame); ret = output_audio_frame(frame);
av_frame_unref(frame); av_frame_unref(frame);
if (ret < 0)
return ret;
} }
return 0; return ret;
} }
static int open_codec_context(int *stream_idx, static int open_codec_context(int *stream_idx,
+13 -14
View File
@@ -347,8 +347,7 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
if (frame) { if (frame) {
/* convert samples from native format to destination codec format, using the resampler */ /* convert samples from native format to destination codec format, using the resampler */
/* compute destination number of samples */ /* compute destination number of samples */
dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples, dst_nb_samples = 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); av_assert0(dst_nb_samples == frame->nb_samples);
/* when we pass a frame to the encoder, it may keep a reference to it /* when we pass a frame to the encoder, it may keep a reference to it
@@ -379,27 +378,27 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
/**************************************************************/ /**************************************************************/
/* video output */ /* video output */
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height) static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height)
{ {
AVFrame *picture; AVFrame *frame;
int ret; int ret;
picture = av_frame_alloc(); frame = av_frame_alloc();
if (!picture) if (!frame)
return NULL; return NULL;
picture->format = pix_fmt; frame->format = pix_fmt;
picture->width = width; frame->width = width;
picture->height = height; frame->height = height;
/* allocate the buffers for the frame data */ /* allocate the buffers for the frame data */
ret = av_frame_get_buffer(picture, 0); ret = av_frame_get_buffer(frame, 0);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Could not allocate frame data.\n"); fprintf(stderr, "Could not allocate frame data.\n");
exit(1); exit(1);
} }
return picture; return frame;
} }
static void open_video(AVFormatContext *oc, const AVCodec *codec, static void open_video(AVFormatContext *oc, const AVCodec *codec,
@@ -420,7 +419,7 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec,
} }
/* allocate and init a re-usable frame */ /* allocate and init a re-usable frame */
ost->frame = alloc_picture(c->pix_fmt, c->width, c->height); ost->frame = alloc_frame(c->pix_fmt, c->width, c->height);
if (!ost->frame) { if (!ost->frame) {
fprintf(stderr, "Could not allocate video frame\n"); fprintf(stderr, "Could not allocate video frame\n");
exit(1); exit(1);
@@ -431,9 +430,9 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec,
* output format. */ * output format. */
ost->tmp_frame = NULL; ost->tmp_frame = NULL;
if (c->pix_fmt != AV_PIX_FMT_YUV420P) { if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height); ost->tmp_frame = alloc_frame(AV_PIX_FMT_YUV420P, c->width, c->height);
if (!ost->tmp_frame) { if (!ost->tmp_frame) {
fprintf(stderr, "Could not allocate temporary picture\n"); fprintf(stderr, "Could not allocate temporary video frame\n");
exit(1); exit(1);
} }
} }
-2
View File
@@ -28,8 +28,6 @@
* GPU video surfaces, write the decoded frames to an output file. * GPU video surfaces, write the decoded frames to an output file.
*/ */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include "libavformat/avformat.h" #include "libavformat/avformat.h"
+8 -11
View File
@@ -62,10 +62,10 @@ static int str_to_dict(char* optstr, AVDictionary **opt)
return 0; return 0;
key = strtok(optstr, " "); key = strtok(optstr, " ");
if (key == NULL) if (key == NULL)
return AVERROR(ENAVAIL); return AVERROR(EINVAL);
value = strtok(NULL, " "); value = strtok(NULL, " ");
if (value == NULL) if (value == NULL)
return AVERROR(ENAVAIL); return AVERROR(EINVAL);
av_dict_set(opt, key, value, 0); av_dict_set(opt, key, value, 0);
do { do {
key = strtok(NULL, " "); key = strtok(NULL, " ");
@@ -73,10 +73,9 @@ static int str_to_dict(char* optstr, AVDictionary **opt)
return 0; return 0;
value = strtok(NULL, " "); value = strtok(NULL, " ");
if (value == NULL) if (value == NULL)
return AVERROR(ENAVAIL); return AVERROR(EINVAL);
av_dict_set(opt, key, value, 0); av_dict_set(opt, key, value, 0);
} while(key != NULL); } while(1);
return 0;
} }
static int dynamic_set_parameter(AVCodecContext *avctx) static int dynamic_set_parameter(AVCodecContext *avctx)
@@ -88,7 +87,7 @@ static int dynamic_set_parameter(AVCodecContext *avctx)
if (current_setting_number < setting_number && if (current_setting_number < setting_number &&
frame_number == dynamic_setting[current_setting_number].frame_number) { frame_number == dynamic_setting[current_setting_number].frame_number) {
AVDictionaryEntry *e = NULL; AVDictionaryEntry *e = NULL;
ret = str_to_dict(dynamic_setting[current_setting_number].optstr, &opts); ret = str_to_dict(dynamic_setting[current_setting_number++].optstr, &opts);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "The dynamic parameter is wrong\n"); fprintf(stderr, "The dynamic parameter is wrong\n");
goto fail; goto fail;
@@ -181,7 +180,7 @@ static int open_input_file(char *filename)
break; break;
default: default:
fprintf(stderr, "Codec is not supportted by qsv\n"); fprintf(stderr, "Codec is not supportted by qsv\n");
return AVERROR(ENAVAIL); return AVERROR(EINVAL);
} }
if (!(decoder_ctx = avcodec_alloc_context3(decoder))) if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
@@ -334,17 +333,15 @@ static int dec_enc(AVPacket *pkt, const AVCodec *enc_codec, char *optstr)
fail: fail:
av_frame_free(&frame); av_frame_free(&frame);
if (ret < 0)
return ret;
} }
return 0; return ret;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const AVCodec *enc_codec; const AVCodec *enc_codec;
int ret = 0; int ret = 0;
AVPacket *dec_pkt; AVPacket *dec_pkt = NULL;
if (argc < 5 || (argc - 5) % 2) { if (argc < 5 || (argc - 5) % 2) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file> <encoder> <output file>" av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file> <encoder> <output file>"
+42 -8
View File
@@ -97,6 +97,11 @@ static int open_input_file(const char *filename)
"for stream #%u\n", i); "for stream #%u\n", i);
return ret; return ret;
} }
/* Inform the decoder about the timebase for the packet timestamps.
* This is highly recommended, but not mandatory. */
codec_ctx->pkt_timebase = stream->time_base;
/* Reencode video & audio and remux subtitles etc. */ /* Reencode video & audio and remux subtitles etc. */
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
|| codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -191,7 +196,7 @@ static int open_output_file(const char *filename)
/* Third parameter can be used to pass settings to encoder */ /* Third parameter can be used to pass settings to encoder */
ret = avcodec_open2(enc_ctx, encoder, NULL); ret = avcodec_open2(enc_ctx, encoder, NULL);
if (ret < 0) { if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i); av_log(NULL, AV_LOG_ERROR, "Cannot open %s encoder for stream #%u\n", encoder->name, i);
return ret; return ret;
} }
ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx); ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
@@ -266,7 +271,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
snprintf(args, sizeof(args), snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->pkt_timebase.num, dec_ctx->pkt_timebase.den,
dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.num,
dec_ctx->sample_aspect_ratio.den); dec_ctx->sample_aspect_ratio.den);
@@ -306,7 +311,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf)); av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf));
snprintf(args, sizeof(args), snprintf(args, sizeof(args),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s", "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s",
dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, dec_ctx->pkt_timebase.num, dec_ctx->pkt_timebase.den, dec_ctx->sample_rate,
av_get_sample_fmt_name(dec_ctx->sample_fmt), av_get_sample_fmt_name(dec_ctx->sample_fmt),
buf); buf);
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
@@ -436,6 +441,10 @@ static int encode_write_frame(unsigned int stream_index, int flush)
/* encode filtered frame */ /* encode filtered frame */
av_packet_unref(enc_pkt); av_packet_unref(enc_pkt);
if (filt_frame && filt_frame->pts != AV_NOPTS_VALUE)
filt_frame->pts = av_rescale_q(filt_frame->pts, filt_frame->time_base,
stream->enc_ctx->time_base);
ret = avcodec_send_frame(stream->enc_ctx, filt_frame); ret = avcodec_send_frame(stream->enc_ctx, filt_frame);
if (ret < 0) if (ret < 0)
@@ -490,6 +499,7 @@ static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
break; break;
} }
filter->filtered_frame->time_base = av_buffersink_get_time_base(filter->buffersink_ctx);;
filter->filtered_frame->pict_type = AV_PICTURE_TYPE_NONE; filter->filtered_frame->pict_type = AV_PICTURE_TYPE_NONE;
ret = encode_write_frame(stream_index, 0); ret = encode_write_frame(stream_index, 0);
av_frame_unref(filter->filtered_frame); av_frame_unref(filter->filtered_frame);
@@ -544,9 +554,6 @@ int main(int argc, char **argv)
av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n"); av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
av_packet_rescale_ts(packet,
ifmt_ctx->streams[stream_index]->time_base,
stream->dec_ctx->time_base);
ret = avcodec_send_packet(stream->dec_ctx, packet); ret = avcodec_send_packet(stream->dec_ctx, packet);
if (ret < 0) { if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Decoding failed\n"); av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
@@ -578,11 +585,38 @@ int main(int argc, char **argv)
av_packet_unref(packet); av_packet_unref(packet);
} }
/* flush filters and encoders */ /* flush decoders, filters and encoders */
for (i = 0; i < ifmt_ctx->nb_streams; i++) { for (i = 0; i < ifmt_ctx->nb_streams; i++) {
/* flush filter */ StreamContext *stream;
if (!filter_ctx[i].filter_graph) if (!filter_ctx[i].filter_graph)
continue; continue;
stream = &stream_ctx[i];
av_log(NULL, AV_LOG_INFO, "Flushing stream %u decoder\n", i);
/* flush decoder */
ret = avcodec_send_packet(stream->dec_ctx, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Flushing decoding failed\n");
goto end;
}
while (ret >= 0) {
ret = avcodec_receive_frame(stream->dec_ctx, stream->dec_frame);
if (ret == AVERROR_EOF)
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, i);
if (ret < 0)
goto end;
}
/* flush filter */
ret = filter_encode_write_frame(NULL, i); ret = filter_encode_write_frame(NULL, i);
if (ret < 0) { if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n"); av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
+5 -15
View File
@@ -447,26 +447,17 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
int error; int error;
/* Allocate as many pointers as there are audio channels. /* Allocate as many pointers as there are audio channels.
* Each pointer will later point to the audio samples of the corresponding * Each pointer will point to the audio samples of the corresponding
* channels (although it may be NULL for interleaved formats). * channels (although it may be NULL for interleaved formats).
*/ * Allocate memory for the samples of all channels in one consecutive
if (!(*converted_input_samples = calloc(output_codec_context->ch_layout.nb_channels,
sizeof(**converted_input_samples)))) {
fprintf(stderr, "Could not allocate converted input sample pointers\n");
return AVERROR(ENOMEM);
}
/* Allocate memory for the samples of all channels in one consecutive
* block for convenience. */ * block for convenience. */
if ((error = av_samples_alloc(*converted_input_samples, NULL, if ((error = av_samples_alloc_array_and_samples(converted_input_samples, NULL,
output_codec_context->ch_layout.nb_channels, output_codec_context->ch_layout.nb_channels,
frame_size, frame_size,
output_codec_context->sample_fmt, 0)) < 0) { output_codec_context->sample_fmt, 0)) < 0) {
fprintf(stderr, fprintf(stderr,
"Could not allocate converted input samples (error '%s')\n", "Could not allocate converted input samples (error '%s')\n",
av_err2str(error)); av_err2str(error));
av_freep(&(*converted_input_samples)[0]);
free(*converted_input_samples);
return error; return error;
} }
return 0; return 0;
@@ -598,10 +589,9 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo,
ret = 0; ret = 0;
cleanup: cleanup:
if (converted_input_samples) { if (converted_input_samples)
av_freep(&converted_input_samples[0]); av_freep(&converted_input_samples[0]);
free(converted_input_samples); av_freep(&converted_input_samples);
}
av_frame_free(&input_frame); av_frame_free(&input_frame);
return ret; return ret;
+4
View File
@@ -88,6 +88,10 @@ static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout)
enc_pkt->stream_index = 0; enc_pkt->stream_index = 0;
ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout); ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout);
av_packet_unref(enc_pkt); av_packet_unref(enc_pkt);
if (ret != enc_pkt->size) {
ret = AVERROR(errno);
break;
}
} }
end: end:
+1 -3
View File
@@ -215,10 +215,8 @@ static int dec_enc(AVPacket *pkt, const AVCodec *enc_codec)
fail: fail:
av_frame_free(&frame); av_frame_free(&frame);
if (ret < 0)
return ret;
} }
return 0; return ret;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
+2 -2
View File
@@ -450,7 +450,7 @@ work with streams that were detected during the initial scan; streams that
are detected later are ignored. are detected later are ignored.
The size of the initial scan is controlled by two options: @code{probesize} The size of the initial scan is controlled by two options: @code{probesize}
(default ~5 Mo) and @code{analyzeduration} (default 5,000,000 µs = 5 s). For (default ~5@tie{}Mo) and @code{analyzeduration} (default 5,000,000@tie{}µs = 5@tie{}s). For
the subtitle stream to be detected, both values must be large enough. the subtitle stream to be detected, both values must be large enough.
@section Why was the @command{ffmpeg} @option{-sameq} option removed? What to use instead? @section Why was the @command{ffmpeg} @option{-sameq} option removed? What to use instead?
@@ -467,7 +467,7 @@ point acceptable for your tastes. The most common options to do that are
@option{-qscale} and @option{-qmax}, but you should peruse the documentation @option{-qscale} and @option{-qmax}, but you should peruse the documentation
of the encoder you chose. of the encoder you chose.
@section I have a stretched video, why does scaling does not fix it? @section I have a stretched video, why does scaling not fix it?
A lot of video codecs and formats can store the @emph{aspect ratio} of the A lot of video codecs and formats can store the @emph{aspect ratio} of the
video: this is the ratio between the width and the height of either the full video: this is the ratio between the width and the height of either the full
+16
View File
@@ -79,6 +79,14 @@ Do not put a '~' character in the samples path to indicate a home
directory. Because of shell nuances, this will cause FATE to fail. directory. Because of shell nuances, this will cause FATE to fail.
@end float @end float
Beware that some assertions are disabled by default, so mind setting
@option{--assert-level=<level>} at configuration time, e.g. when seeking
the highest possible test coverage:
@example
./configure --assert-level=2
@end example
Note that raising the assert level could have a performance impact.
To get the complete list of tests, run the command: To get the complete list of tests, run the command:
@example @example
make fate-list make fate-list
@@ -223,6 +231,14 @@ meaning only while running the regression tests.
Specify how many threads to use while running regression tests, it is Specify how many threads to use while running regression tests, it is
quite useful to detect thread-related regressions. quite useful to detect thread-related regressions.
This variable may be set to the string "random", optionally followed by a
number, like "random99", This will cause each test to use a random number of
threads. If a number is specified, it is used as a maximum number of threads,
otherwise 16 is the maximum.
In case a test fails, the thread count used for it will be written into the
errfile.
@item THREAD_TYPE @item THREAD_TYPE
Specify which threading strategy test, either @samp{slice} or @samp{frame}, Specify which threading strategy test, either @samp{slice} or @samp{frame},
by default @samp{slice+frame} by default @samp{slice+frame}
+22
View File
@@ -31,3 +31,25 @@ makeopts= # extra options passed to 'make'
# defaulting to makeopts above if this is not set # defaulting to makeopts above if this is not set
#tar= # command to create a tar archive from its arguments on stdout, #tar= # command to create a tar archive from its arguments on stdout,
# defaults to 'tar c' # defaults to 'tar c'
#fate_targets= # targets to make when running fate; defaults to "fate",
# can be set to run a subset of tests, e.g. "fate-checkasm".
#fate_environments= # a list of names of configurations to run tests for;
# each round is run with variables from ${${name}_env} set.
# One example of using fate_environments:
# target_exec="qemu-aarch64-static"
# fate_targets="fate-checkasm fate-cpu"
# fate_environments="sve128 sve256"
# sve128_env="QEMU_CPU=max,sve128=on"
# sve256_env="QEMU_CPU=max,sve256=on"
# The variables set by fate_environments can also be used explicitly
# by target_exec, e.g. like this:
# target_exec="qemu-aarch64-static -cpu \$(MY_CPU)"
# fate_targets="fate-checkasm fate-cpu"
# fate_environments="sve128 sve256"
# sve128_env="MY_CPU=max,sve128=on"
# sve256_env="MY_CPU=max,sve256=on"
+496 -176
View File
@@ -17,9 +17,9 @@ ffmpeg [@var{global_options}] @{[@var{input_file_options}] -i @file{input_url}@}
@chapter Description @chapter Description
@c man begin DESCRIPTION @c man begin DESCRIPTION
@command{ffmpeg} is a very fast video and audio converter that can also grab from @command{ffmpeg} is a universal media converter. It can read a wide variety of
a live audio/video source. It can also convert between arbitrary sample inputs - including live grabbing/recording devices - filter, and transcode them
rates and resize video on the fly with a high quality polyphase filter. into a plethora of output formats.
@command{ffmpeg} reads from an arbitrary number of input "files" (which can be regular @command{ffmpeg} reads from an arbitrary number of input "files" (which can be regular
files, pipes, network streams, grabbing devices, etc.), specified by the files, pipes, network streams, grabbing devices, etc.), specified by the
@@ -49,24 +49,32 @@ Do not mix input and output files -- first specify all input files, then all
output files. Also do not mix options which belong to different files. All output files. Also do not mix options which belong to different files. All
options apply ONLY to the next input or output file and are reset between files. options apply ONLY to the next input or output file and are reset between files.
Some simple examples follow.
@itemize @itemize
@item @item
To set the video bitrate of the output file to 64 kbit/s: Convert an input media file to a different format, by re-encoding media streams:
@example @example
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi ffmpeg -i input.avi output.mp4
@end example @end example
@item @item
To force the frame rate of the output file to 24 fps: Set the video bitrate of the output file to 64 kbit/s:
@example @example
ffmpeg -i input.avi -r 24 output.avi ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4
@end example @end example
@item @item
To force the frame rate of the input file (valid for raw formats only) Force the frame rate of the output file to 24 fps:
to 1 fps and the frame rate of the output file to 24 fps:
@example @example
ffmpeg -r 1 -i input.m2v -r 24 output.avi ffmpeg -i input.avi -r 24 output.mp4
@end example
@item
Force the frame rate of the input file (valid for raw formats only) to 1 fps and
the frame rate of the output file to 24 fps:
@example
ffmpeg -r 1 -i input.m2v -r 24 output.mp4
@end example @end example
@end itemize @end itemize
@@ -110,7 +118,7 @@ Encoded packets are then passed to the decoder (unless streamcopy is selected
for the stream, see further for a description). The decoder produces for the stream, see further for a description). The decoder produces
uncompressed frames (raw video/PCM audio/...) which can be processed further by uncompressed frames (raw video/PCM audio/...) which can be processed further by
filtering (see next section). After filtering, the frames are passed to the filtering (see next section). After filtering, the frames are passed to the
encoder, which encodes them and outputs encoded packets. Finally those are encoder, which encodes them and outputs encoded packets. Finally, those are
passed to the muxer, which writes the encoded packets to the output file. passed to the muxer, which writes the encoded packets to the output file.
@section Filtering @section Filtering
@@ -211,6 +219,40 @@ Since there is no decoding or encoding, it is very fast and there is no quality
loss. However, it might not work in some cases because of many factors. Applying loss. However, it might not work in some cases because of many factors. Applying
filters is obviously also impossible, since filters work on uncompressed data. filters is obviously also impossible, since filters work on uncompressed data.
@section Loopback decoders
While decoders are normally associated with demuxer streams, it is also possible
to create "loopback" decoders that decode the output from some encoder and allow
it to be fed back to complex filtergraphs. This is done with the @code{-dec}
directive, which takes as a parameter the index of the output stream that should
be decoded. Every such directive creates a new loopback decoder, indexed with
successive integers starting at zero. These indices should then be used to refer
to loopback decoders in complex filtergraph link labels, as described in the
documentation for @option{-filter_complex}.
E.g. the following example:
@example
ffmpeg -i INPUT \
-map 0:v:0 -c:v libx264 -crf 45 -f null - \
-dec 0:0 -filter_complex '[0:v][dec:0]hstack[stack]' \
-map '[stack]' -c:v ffv1 OUTPUT
@end example
reads an input video and
@itemize
@item
(line 2) encodes it with @code{libx264} at low quality;
@item
(line 3) decodes this encoded stream and places it side by side with the
original input video;
@item
(line 4) combined video is then losslessly encoded and written into
@file{OUTPUT}.
@end itemize
@c man end DETAILED DESCRIPTION @c man end DETAILED DESCRIPTION
@chapter Stream selection @chapter Stream selection
@@ -615,6 +657,206 @@ Not all muxers support embedded thumbnails, and those who do, only support a few
Creates a program with the specified @var{title}, @var{program_num} and adds the specified Creates a program with the specified @var{title}, @var{program_num} and adds the specified
@var{stream}(s) to it. @var{stream}(s) to it.
@item -stream_group type=@var{type}:st=@var{stream}[:st=@var{stream}][:stg=@var{stream_group}][:id=@var{stream_group_id}...] (@emph{output})
Creates a stream group of the specified @var{type}, @var{stream_group_id} and adds the specified
@var{stream}(s) and/or previously defined @var{stream_group}(s) to it.
@var{type} can be one of the following:
@table @option
@item iamf_audio_element
Groups @var{stream}s that belong to the same IAMF Audio Element
For this group @var{type}, the following options are available
@table @option
@item audio_element_type
The Audio Element type. The following values are supported:
@table @option
@item channel
Scalable channel audio representation
@item scene
Ambisonics representation
@end table
@item demixing
Demixing information used to reconstruct a scalable channel audio representation.
This option must be separated from the rest with a ',', and takes the following
key=value options
@table @option
@item parameter_id
An identifier parameters blocks in frames may refer to
@item dmixp_mode
A pre-defined combination of demixing parameters
@end table
@item recon_gain
Recon gain information used to reconstruct a scalable channel audio representation.
This option must be separated from the rest with a ',', and takes the following
key=value options
@table @option
@item parameter_id
An identifier parameters blocks in frames may refer to
@end table
@item layer
A layer defining a Channel Layout in the Audio Element.
This option must be separated from the rest with a ','. Several ',' separated entries
can be defined, and at least one must be set.
It takes the following ":"-separated key=value options
@table @option
@item ch_layout
The layer's channel layout
@item flags
The following flags are available:
@table @option
@item recon_gain
Wether to signal if recon_gain is present as metadata in parameter blocks within frames
@end table
@item output_gain
@item output_gain_flags
Which channels output_gain applies to. The following flags are available:
@table @option
@item FL
@item FR
@item BL
@item BR
@item TFL
@item TFR
@end table
@item ambisonics_mode
The ambisonics mode. This has no effect if audio_element_type is set to channel.
The following values are supported:
@table @option
@item mono
Each ambisonics channel is coded as an individual mono stream in the group
@end table
@end table
@item default_w
Default weight value
@end table
@item iamf_mix_presentation
Groups @var{stream}s that belong to all IAMF Audio Element the same
IAMF Mix Presentation references
For this group @var{type}, the following options are available
@table @option
@item submix
A sub-mix within the Mix Presentation.
This option must be separated from the rest with a ','. Several ',' separated entries
can be defined, and at least one must be set.
It takes the following ":"-separated key=value options
@table @option
@item parameter_id
An identifier parameters blocks in frames may refer to, for post-processing the mixed
audio signal to generate the audio signal for playback
@item parameter_rate
The sample rate duration fields in parameters blocks in frames that refer to this
@var{parameter_id} are expressed as
@item default_mix_gain
Default mix gain value to apply when there are no parameter blocks sharing the same
@var{parameter_id} for a given frame
@item element
References an Audio Element used in this Mix Presentation to generate the final output
audio signal for playback.
This option must be separated from the rest with a '|'. Several '|' separated entries
can be defined, and at least one must be set.
It takes the following ":"-separated key=value options:
@table @option
@item stg
The @var{stream_group_id} for an Audio Element which this sub-mix refers to
@item parameter_id
An identifier parameters blocks in frames may refer to, for applying any processing to
the referenced and rendered Audio Element before being summed with other processed Audio
Elements
@item parameter_rate
The sample rate duration fields in parameters blocks in frames that refer to this
@var{parameter_id} are expressed as
@item default_mix_gain
Default mix gain value to apply when there are no parameter blocks sharing the same
@var{parameter_id} for a given frame
@item annotations
A key=value string describing the sub-mix element where "key" is a string conforming to
BCP-47 that specifies the language for the "value" string. "key" must be the same as the
one in the mix's @var{annotations}
@item headphones_rendering_mode
Indicates whether the input channel-based Audio Element is rendered to stereo loudspeakers
or spatialized with a binaural renderer when played back on headphones.
This has no effect if the referenced Audio Element's @var{audio_element_type} is set to
channel.
The following values are supported:
@table @option
@item stereo
@item binaural
@end table
@end table
@item layout
Specifies the layouts for this sub-mix on which the loudness information was measured.
This option must be separated from the rest with a '|'. Several '|' separated entries
can be defined, and at least one must be set.
It takes the following ":"-separated key=value options:
@table @option
@item layout_type
@table @option
@item loudspeakers
The layout follows the loudspeaker sound system convention of ITU-2051-3.
@item binaural
The layout is binaural.
@end table
@item sound_system
Channel layout matching one of Sound Systems A to J of ITU-2051-3, plus 7.1.2 and 3.1.2
This has no effect if @var{layout_type} is set to binaural.
@item integrated_loudness
The program integrated loudness information, as defined in ITU-1770-4.
@item digital_peak
The digital (sampled) peak value of the audio signal, as defined in ITU-1770-4.
@item true_peak
The true peak of the audio signal, as defined in ITU-1770-4.
@item dialog_anchored_loudness
The Dialogue loudness information, as defined in ITU-1770-4.
@item album_anchored_loudness
The Album loudness information, as defined in ITU-1770-4.
@end table
@end table
@item annotations
A key=value string string describing the mix where "key" is a string conforming to BCP-47
that specifies the language for the "value" string. "key" must be the same as the ones in
all sub-mix element's @var{annotations}s
@end table
@end table
@item -target @var{type} (@emph{output}) @item -target @var{type} (@emph{output})
Specify target file type (@code{vcd}, @code{svcd}, @code{dvd}, @code{dv}, Specify target file type (@code{vcd}, @code{svcd}, @code{dvd}, @code{dv},
@code{dv50}). @var{type} may be prefixed with @code{pal-}, @code{ntsc-} or @code{dv50}). @var{type} may be prefixed with @code{pal-}, @code{ntsc-} or
@@ -769,11 +1011,6 @@ syntax.
See the @ref{filter_complex_option,,-filter_complex option} if you See the @ref{filter_complex_option,,-filter_complex option} if you
want to create filtergraphs with multiple inputs and/or outputs. want to create filtergraphs with multiple inputs and/or outputs.
@item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream})
This option is similar to @option{-filter}, the only difference is that its
argument is the name of the file from which a filtergraph description is to be
read.
@item -reinit_filter[:@var{stream_specifier}] @var{integer} (@emph{input,per-stream}) @item -reinit_filter[:@var{stream_specifier}] @var{integer} (@emph{input,per-stream})
This boolean option determines if the filtergraph(s) to which this stream is fed gets This boolean option determines if the filtergraph(s) to which this stream is fed gets
reinitialized when input frame parameters change mid-stream. This option is enabled by reinitialized when input frame parameters change mid-stream. This option is enabled by
@@ -821,7 +1058,7 @@ be achieved with @code{ffmpeg ... < /dev/null} but it requires a
shell. shell.
@item -debug_ts (@emph{global}) @item -debug_ts (@emph{global})
Print timestamp information. It is off by default. This option is Print timestamp/latency information. It is off by default. This option is
mostly useful for testing and debugging purposes, and the output mostly useful for testing and debugging purposes, and the output
format may change from one version to another, so it should not be format may change from one version to another, so it should not be
employed by portable scripts. employed by portable scripts.
@@ -1014,7 +1251,12 @@ If @var{pix_fmt} is a single @code{+}, ffmpeg selects the same pixel format
as the input (or graph output) and automatic conversions are disabled. as the input (or graph output) and automatic conversions are disabled.
@item -sws_flags @var{flags} (@emph{input/output}) @item -sws_flags @var{flags} (@emph{input/output})
Set SwScaler flags. Set default flags for the libswscale library. These flags are used by
automatically inserted @code{scale} filters and those within simple
filtergraphs, if not overridden within the filtergraph definition.
See the @ref{scaler_options,,ffmpeg-scaler manual,ffmpeg-scaler} for a list
of scaler options.
@item -rc_override[:@var{stream_specifier}] @var{override} (@emph{output,per-stream}) @item -rc_override[:@var{stream_specifier}] @var{override} (@emph{output,per-stream})
Rate control override for specific intervals, formatted as "int,int,int" Rate control override for specific intervals, formatted as "int,int,int"
@@ -1022,36 +1264,24 @@ list separated with slashes. Two first values are the beginning and
end frame numbers, last one is quantizer to use if positive, or quality end frame numbers, last one is quantizer to use if positive, or quality
factor if negative. factor if negative.
@item -psnr
Calculate PSNR of compressed frames. This option is deprecated, pass the
PSNR flag to the encoder instead, using @code{-flags +psnr}.
@item -vstats @item -vstats
Dump video coding statistics to @file{vstats_HHMMSS.log}. Dump video coding statistics to @file{vstats_HHMMSS.log}. See the
@ref{vstats_file_format,,vstats file format} section for the format description.
@item -vstats_file @var{file} @item -vstats_file @var{file}
Dump video coding statistics to @var{file}. Dump video coding statistics to @var{file}. See the
@ref{vstats_file_format,,vstats file format} section for the format description.
@item -vstats_version @var{file} @item -vstats_version @var{file}
Specifies which version of the vstats format to use. Default is 2. Specify which version of the vstats format to use. Default is @code{2}. See the
@ref{vstats_file_format,,vstats file format} section for the format description.
version = 1 :
@code{frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s}
version > 1:
@code{out= %2d st= %2d frame= %5d q= %2.1f PSNR= %6.2f f_size= %6d s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s}
@item -top[:@var{stream_specifier}] @var{n} (@emph{output,per-stream})
top=1/bottom=0/auto=-1 field first
@item -vtag @var{fourcc/tag} (@emph{output}) @item -vtag @var{fourcc/tag} (@emph{output})
Force video tag/fourcc. This is an alias for @code{-tag:v}. Force video tag/fourcc. This is an alias for @code{-tag:v}.
@item -qphist (@emph{global})
Show QP histogram
@item -vbsf @var{bitstream_filter}
Deprecated see -bsf
@item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...] (@emph{output,per-stream}) @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}) @item -force_key_frames[:@var{stream_specifier}] expr:@var{expr} (@emph{output,per-stream})
@item -force_key_frames[:@var{stream_specifier}] source (@emph{output,per-stream}) @item -force_key_frames[:@var{stream_specifier}] source (@emph{output,per-stream})
@item -force_key_frames[:@var{stream_specifier}] source_no_drop (@emph{output,per-stream})
@var{force_key_frames} can take arguments of the following form: @var{force_key_frames} can take arguments of the following form:
@@ -1112,10 +1342,6 @@ starting from second 13:
@item source @item source
If the argument is @code{source}, ffmpeg will force a key frame if 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. the current frame being encoded is marked as a key frame in its source.
@item source_no_drop
If the argument is @code{source_no_drop}, ffmpeg will force a key frame if
the current frame being encoded is marked as a key frame in its source.
In cases where this particular source frame has to be dropped, In cases where this particular source frame has to be dropped,
enforce the next available frame to become a key frame instead. enforce the next available frame to become a key frame instead.
@@ -1161,11 +1387,50 @@ Choose the first device and use the primary device context.
@item d3d11va @item d3d11va
@var{device} is the number of the Direct3D 11 display adapter. @var{device} is the number of the Direct3D 11 display adapter.
If not specified, it will attempt to use the default Direct3D 11 display adapter
or the first Direct3D 11 display adapter whose hardware VendorId is specified
by @samp{vendor_id}.
Examples:
@table @emph
@item -init_hw_device d3d11va
Create a d3d11va device on the default Direct3D 11 display adapter.
@item -init_hw_device d3d11va:1
Create a d3d11va device on the Direct3D 11 display adapter specified by index 1.
@item -init_hw_device d3d11va:,vendor_id=0x8086
Create a d3d11va device on the first Direct3D 11 display adapter whose hardware VendorId is 0x8086.
@end table
@item vaapi @item vaapi
@var{device} is either an X11 display name or a DRM render node. @var{device} is either an X11 display name, a DRM render node or a DirectX adapter index.
If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY}) If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY})
and then the first DRM render node (@emph{/dev/dri/renderD128}). and then the first DRM render node (@emph{/dev/dri/renderD128}), or the default
DirectX adapter on Windows.
The following options are recognized:
@table @option
@item kernel_driver
When @var{device} is not specified, use this option to specify the name of the kernel
driver associated with the desired device. This option is available only when
the hardware acceleration method @emph{drm} and @emph{vaapi} are enabled.
@end table
Examples:
@table @emph
@item -init_hw_device vaapi
Create a vaapi device on the default device.
@item -init_hw_device vaapi:/dev/dri/renderD129
Create a vaapi device on DRM render node @file{/dev/dri/renderD129}.
@item -init_hw_device vaapi:1
Create a vaapi device on DirectX adapter 1.
@item -init_hw_device vaapi:,kernel_driver=i915
Create a vaapi device on a device associated with kernel driver @samp{i915}.
@end table
@item vdpau @item vdpau
@var{device} is an X11 display name. @var{device} is an X11 display name.
@@ -1188,16 +1453,38 @@ If not specified, @samp{auto_any} is used.
platform-appropriate subdevice (@samp{dxva2} or @samp{d3d11va} or @samp{vaapi}) and then deriving a platform-appropriate subdevice (@samp{dxva2} or @samp{d3d11va} or @samp{vaapi}) and then deriving a
QSV device from that.) QSV device from that.)
Alternatively, @samp{child_device_type} helps to choose platform-appropriate subdevice type. The following options are recognized:
On Windows @samp{d3d11va} is used as default subdevice type. @table @option
@item child_device
Specify a DRM render node on Linux or DirectX adapter on Windows.
@item child_device_type
Choose platform-appropriate subdevice type. On Windows @samp{d3d11va} is used
as default subdevice type when @code{--enable-libvpl} is specified at configuration time,
@samp{dxva2} is used as default subdevice type when @code{--enable-libmfx} is specified at
configuration time. On Linux user can use @samp{vaapi} only as subdevice type.
@end table
Examples: Examples:
@table @emph @table @emph
@item -init_hw_device qsv:hw,child_device=/dev/dri/renderD129
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DRM render node @file{/dev/dri/renderD129}.
@item -init_hw_device qsv:hw,child_device=1
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DirectX adapter 1.
@item -init_hw_device qsv:hw,child_device_type=d3d11va @item -init_hw_device qsv:hw,child_device_type=d3d11va
Choose the GPU subdevice with type @samp{d3d11va} and create QSV device with @samp{MFX_IMPL_HARDWARE}. Choose the GPU subdevice with type @samp{d3d11va} and create QSV device with @samp{MFX_IMPL_HARDWARE}.
@item -init_hw_device qsv:hw,child_device_type=dxva2 @item -init_hw_device qsv:hw,child_device_type=dxva2
Choose the GPU subdevice with type @samp{dxva2} and create QSV device with @samp{MFX_IMPL_HARDWARE}. Choose the GPU subdevice with type @samp{dxva2} and create QSV device with @samp{MFX_IMPL_HARDWARE}.
@item -init_hw_device qsv:hw,child_device=1,child_device_type=d3d11va
Create a QSV device with @samp{MFX_IMPL_HARDWARE} on DirectX adapter 1 with subdevice type @samp{d3d11va}.
@item -init_hw_device vaapi=va:/dev/dri/renderD129 -init_hw_device qsv=hw1@@@var{va}
Create a VAAPI device called @samp{va} on @file{/dev/dri/renderD129}, then derive a QSV device called @samp{hw1}
from device @samp{va}.
@end table @end table
@item opencl @item opencl
@@ -1404,8 +1691,6 @@ This is an alias for @code{-filter:a}, see the @ref{filter_option,,-filter optio
@table @option @table @option
@item -atag @var{fourcc/tag} (@emph{output}) @item -atag @var{fourcc/tag} (@emph{output})
Force audio tag/fourcc. This is an alias for @code{-tag:a}. Force audio tag/fourcc. This is an alias for @code{-tag:a}.
@item -absf @var{bitstream_filter}
Deprecated, see -bsf
@item -guess_layout_max @var{channels} (@emph{input,per-stream}) @item -guess_layout_max @var{channels} (@emph{input,per-stream})
If some input channel layout is not known, try to guess only if it If some input channel layout is not known, try to guess only if it
corresponds to at most the specified number of channels. For example, 2 corresponds to at most the specified number of channels. For example, 2
@@ -1427,8 +1712,6 @@ option to disable streams individually.
As an output option, disables subtitle recording i.e. automatic selection or As an output option, disables subtitle recording i.e. automatic selection or
mapping of any subtitle stream. For full manual control see the @code{-map} mapping of any subtitle stream. For full manual control see the @code{-map}
option. option.
@item -sbsf @var{bitstream_filter}
Deprecated, see -bsf
@end table @end table
@section Advanced Subtitle options @section Advanced Subtitle options
@@ -1461,8 +1744,7 @@ Set the size of the canvas used to render subtitles.
Create one or more streams in the output file. This option has two forms for Create one or more streams in the output file. This option has two forms for
specifying the data source(s): the first selects one or more streams from some specifying the data source(s): the first selects one or more streams from some
input file (specified with @code{-i}), the second takes an output from some input file (specified with @code{-i}), the second takes an output from some
complex filtergraph (specified with @code{-filter_complex} or complex filtergraph (specified with @code{-filter_complex}).
@code{-filter_complex_script}).
In the first form, an output stream is created for every stream from the input In the first form, an output stream is created for every stream from the input
file with the index @var{input_file_id}. If @var{stream_specifier} is given, file with the index @var{input_file_id}. If @var{stream_specifier} is given,
@@ -1554,77 +1836,6 @@ such streams is attempted.
Allow input streams with unknown type to be copied instead of failing if copying Allow input streams with unknown type to be copied instead of failing if copying
such streams is attempted. such streams is attempted.
@item -map_channel [@var{input_file_id}.@var{stream_specifier}.@var{channel_id}|-1][?][:@var{output_file_id}.@var{stream_specifier}]
This option is deprecated and will be removed. It can be replaced by the
@var{pan} filter. In some cases it may be easier to use some combination of the
@var{channelsplit}, @var{channelmap}, or @var{amerge} filters.
Map an audio channel from a given input to an output. If
@var{output_file_id}.@var{stream_specifier} is not set, the audio channel will
be mapped on all the audio streams.
Using "-1" instead of
@var{input_file_id}.@var{stream_specifier}.@var{channel_id} will map a muted
channel.
A trailing @code{?} will allow the map_channel to be
optional: if the map_channel matches no channel the map_channel will be ignored instead
of failing.
For example, assuming @var{INPUT} is a stereo audio file, you can switch the
two audio channels with the following command:
@example
ffmpeg -i INPUT -map_channel 0.0.1 -map_channel 0.0.0 OUTPUT
@end example
If you want to mute the first channel and keep the second:
@example
ffmpeg -i INPUT -map_channel -1 -map_channel 0.0.1 OUTPUT
@end example
The order of the "-map_channel" option specifies the order of the channels in
the output stream. The output channel layout is guessed from the number of
channels mapped (mono if one "-map_channel", stereo if two, etc.). Using "-ac"
in combination of "-map_channel" makes the channel gain levels to be updated if
input and output channel layouts don't match (for instance two "-map_channel"
options and "-ac 6").
You can also extract each channel of an input to specific outputs; the following
command extracts two channels of the @var{INPUT} audio stream (file 0, stream 0)
to the respective @var{OUTPUT_CH0} and @var{OUTPUT_CH1} outputs:
@example
ffmpeg -i INPUT -map_channel 0.0.0 OUTPUT_CH0 -map_channel 0.0.1 OUTPUT_CH1
@end example
The following example splits the channels of a stereo input into two separate
streams, which are put into the same output file:
@example
ffmpeg -i stereo.wav -map 0:0 -map 0:0 -map_channel 0.0.0:0.0 -map_channel 0.0.1:0.1 -y out.ogg
@end example
Note that currently each output stream can only contain channels from a single
input stream; you can't for example use "-map_channel" to pick multiple input
audio channels contained in different streams (from the same or different files)
and merge them into a single output stream. It is therefore not currently
possible, for example, to turn two separate mono streams into a single stereo
stream. However splitting a stereo stream into two single channel mono streams
is possible.
If you need this feature, a possible workaround is to use the @emph{amerge}
filter. For example, if you need to merge a media (here @file{input.mkv}) with 2
mono audio streams into one single stereo channel audio stream (and keep the
video stream), you can use the following command:
@example
ffmpeg -i input.mkv -filter_complex "[0:1] [0:2] amerge" -c:a pcm_s16le -c:v copy output.mkv
@end example
To map the first two audio channels from the first input, and using the
trailing @code{?}, ignore the audio channel mapping if the first input is
mono instead of stereo:
@example
ffmpeg -i INPUT -map_channel 0.0.0 -map_channel 0.0.1? OUTPUT
@end example
@item -map_metadata[:@var{metadata_spec_out}] @var{infile}[:@var{metadata_spec_in}] (@emph{output,per-metadata}) @item -map_metadata[:@var{metadata_spec_out}] @var{infile}[:@var{metadata_spec_in}] (@emph{output,per-metadata})
Set metadata information of the next output file from @var{infile}. Note that Set metadata information of the next output file from @var{infile}. Note that
those are file indices (zero-based), not filenames. those are file indices (zero-based), not filenames.
@@ -1701,6 +1912,9 @@ it may cause packet loss.
It is useful for when flow speed of output packets is important, such as live streaming. It is useful for when flow speed of output packets is important, such as live streaming.
@item -re (@emph{input}) @item -re (@emph{input})
Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. Read input at native frame rate. This is equivalent to setting @code{-readrate 1}.
@item -readrate_initial_burst @var{seconds}
Set an initial read burst time, in seconds, after which @option{-re/-readrate}
will be enforced.
@item -vsync @var{parameter} (@emph{global}) @item -vsync @var{parameter} (@emph{global})
@itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream}) @itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream})
Set video sync method / framerate mode. vsync is applied to all output video streams Set video sync method / framerate mode. vsync is applied to all output video streams
@@ -1719,9 +1933,6 @@ constant frame rate.
@item vfr (2) @item vfr (2)
Frames are passed through with their timestamp or dropped so as to Frames are passed through with their timestamp or dropped so as to
prevent 2 frames from having the same timestamp. prevent 2 frames from having the same timestamp.
@item drop
As passthrough but destroys all timestamps, making the muxer generate
fresh timestamps based on frame-rate.
@item auto (-1) @item auto (-1)
Chooses between cfr and vfr depending on muxer capabilities. This is the Chooses between cfr and vfr depending on muxer capabilities. This is the
default method. default method.
@@ -1742,12 +1953,6 @@ The default is -1.1. One possible usecase is to avoid framedrops in case
of noisy timestamps or to increase frame drop precision in case of exact of noisy timestamps or to increase frame drop precision in case of exact
timestamps. timestamps.
@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}) @item -apad @var{parameters} (@emph{output,per-stream})
Pad the output audio stream(s). This is the same as applying @code{-af apad}. 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. Argument is a string of filter parameters composed the same as with the @code{apad} filter.
@@ -1794,8 +1999,7 @@ Try to make the choice automatically, in order to generate a sane output.
Default value is -1. Default value is -1.
@item -enc_time_base[:@var{stream_specifier}] @var{timebase} (@emph{output,per-stream}) @item -enc_time_base[:@var{stream_specifier}] @var{timebase} (@emph{output,per-stream})
Set the encoder timebase. @var{timebase} is a floating point number, Set the encoder timebase. @var{timebase} can assume one of the following values:
and can assume one of the following values:
@table @option @table @option
@item 0 @item 0
@@ -1803,16 +2007,17 @@ Assign a default value according to the media type.
For video - use 1/framerate, for audio - use 1/samplerate. For video - use 1/framerate, for audio - use 1/samplerate.
@item -1 @item demux
Use the input stream timebase when possible. Use the timebase from the demuxer.
If an input stream is not available, the default timebase will be used. @item filter
Use the timebase from the filtergraph.
@item >0 @item a positive number
Use the provided number as the timebase. Use the provided number as the timebase.
This field can be provided as a ratio of two integers (e.g. 1:24, 1:48000) This field can be provided as a ratio of two integers (e.g. 1:24, 1:48000)
or as a floating point number (e.g. 0.04166, 2.0833e-5) or as a decimal number (e.g. 0.04166, 2.0833e-5)
@end table @end table
Default value is 0. Default value is 0.
@@ -1837,12 +2042,38 @@ results, but increase memory use and latency.
The default value is 10 seconds. The default value is 10 seconds.
@item -dts_delta_threshold @item -dts_delta_threshold @var{threshold}
Timestamp discontinuity delta threshold. Timestamp discontinuity delta threshold, expressed as a decimal number
@item -dts_error_threshold @var{seconds} of 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 The timestamp discontinuity correction enabled by this option is only
conservative. applied to input formats accepting timestamp discontinuity (for which
the @code{AVFMT_TS_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and
is automatically disabled when employing the @code{-copyts} option
(unless wrapping is detected).
If a timestamp discontinuity is detected whose absolute value is
greater than @var{threshold}, ffmpeg will remove the discontinuity by
decreasing/increasing the current DTS and PTS by the corresponding
delta value.
The default value is 10.
@item -dts_error_threshold @var{threshold}
Timestamp error delta threshold, expressed as a decimal number of
seconds.
The timestamp correction enabled by this option is only applied to
input formats not accepting timestamp discontinuity (for which the
@code{AVFMT_TS_DISCONT} flag is not enabled).
If a timestamp discontinuity is detected whose absolute value is
greater than @var{threshold}, ffmpeg will drop the PTS/DTS timestamp
value.
The default value is @code{3600*30} (30 hours), which is arbitrarily
picked and quite conservative.
@item -muxdelay @var{seconds} (@emph{output}) @item -muxdelay @var{seconds} (@emph{output})
Set the maximum demux-decode delay. Set the maximum demux-decode delay.
@item -muxpreload @var{seconds} (@emph{output}) @item -muxpreload @var{seconds} (@emph{output})
@@ -1859,16 +2090,36 @@ an output mpegts file:
ffmpeg -i inurl -streamid 0:33 -streamid 1:36 out.ts ffmpeg -i inurl -streamid 0:33 -streamid 1:36 out.ts
@end example @end example
@item -bsf[:@var{stream_specifier}] @var{bitstream_filters} (@emph{output,per-stream}) @item -bsf[:@var{stream_specifier}] @var{bitstream_filters} (@emph{input/output,per-stream})
Set bitstream filters for matching streams. @var{bitstream_filters} is Apply bitstream filters to matching streams. The filters are applied to each
a comma-separated list of bitstream filters. Use the @code{-bsfs} option packet as it is received from the demuxer (when used as an input option) or
to get the list of bitstream filters. before it is sent to the muxer (when used as an output option).
@var{bitstream_filters} is a comma-separated list of bitstream filter
specifications, each of the form
@example @example
ffmpeg -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264 @var{filter}[=@var{optname0}=@var{optval0}:@var{optname1}=@var{optval1}:...]
@end example @end example
Any of the ',=:' characters that are to be a part of an option value need to be
escaped with a backslash.
Use the @code{-bsfs} option to get the list of bitstream filters.
E.g.
@example
ffmpeg -bsf:v h264_mp4toannexb -i h264.mp4 -c:v copy -an out.h264
@end example
applies the @code{h264_mp4toannexb} bitstream filter (which converts
MP4-encapsulated H.264 stream to Annex B) to the @emph{input} video stream.
On the other hand,
@example @example
ffmpeg -i file.mov -an -vn -bsf:s mov2textsub -c:s copy -f rawvideo sub.txt ffmpeg -i file.mov -an -vn -bsf:s mov2textsub -c:s copy -f rawvideo sub.txt
@end example @end example
applies the @code{mov2textsub} bitstream filter (which extracts text from MOV
subtitles) to the @emph{output} subtitle stream. Note, however, that since both
examples use @code{-c copy}, it matters little whether the filters are applied
on input or output - that would change if transcoding was happening.
@item -tag[:@var{stream_specifier}] @var{codec_tag} (@emph{input/output,per-stream}) @item -tag[:@var{stream_specifier}] @var{codec_tag} (@emph{input/output,per-stream})
Force a tag/fourcc for matching streams. Force a tag/fourcc for matching streams.
@@ -1888,11 +2139,16 @@ type -- see the @option{-filter} options. @var{filtergraph} is a description of
the filtergraph, as described in the ``Filtergraph syntax'' section of the the filtergraph, as described in the ``Filtergraph syntax'' section of the
ffmpeg-filters manual. ffmpeg-filters manual.
Input link labels must refer to input streams using the Input link labels must refer to either input streams or loopback decoders. For
@code{[file_index:stream_specifier]} syntax (i.e. the same as @option{-map} input streams, use the @code{[file_index:stream_specifier]} syntax (i.e. the
uses). If @var{stream_specifier} matches multiple streams, the first one will be same as @option{-map} uses). If @var{stream_specifier} matches multiple streams,
used. An unlabeled input will be connected to the first unused input stream of the first one will be used.
the matching type.
For decoders, the link label must be [dec:@var{dec_idx}], where @var{dec_idx} is
the index of the loopback decoder to be connected to given input.
An unlabeled input will be connected to the first unused input stream of the
matching type.
Output link labels are referred to with @option{-map}. Unlabeled outputs are Output link labels are referred to with @option{-map}. Unlabeled outputs are
added to the first output file. added to the first output file.
@@ -1953,11 +2209,6 @@ The default is the number of available CPUs.
Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or
outputs. Equivalent to @option{-filter_complex}. outputs. Equivalent to @option{-filter_complex}.
@item -filter_complex_script @var{filename} (@emph{global})
This option is similar to @option{-filter_complex}, the only difference is that
its argument is the name of the file from which a complex filtergraph
description is to be read.
@item -accurate_seek (@emph{input}) @item -accurate_seek (@emph{input})
This option enables or disables accurate seeking in input files with the This option enables or disables accurate seeking in input files with the
@option{-ss} option. It is enabled by default, so seeking is accurate when @option{-ss} option. It is enabled by default, so seeking is accurate when
@@ -2061,6 +2312,7 @@ encoder/muxer, it does not change the stream to conform to this value. Setting
values that do not match the stream properties may result in encoding failures values that do not match the stream properties may result in encoding failures
or invalid output files. or invalid output files.
@anchor{stats_enc_options}
@item -stats_enc_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_enc_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
@item -stats_enc_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_enc_post[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
@item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream}) @item -stats_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
@@ -2108,8 +2360,8 @@ Input frame number. Index of the input frame (i.e. output by a decoder) that
corresponds to this output frame or packet. -1 if unavailable. corresponds to this output frame or packet. -1 if unavailable.
@item tb @item tb
Encoder timebase, as a rational number @var{num/den}. Note that this may be Timebase in which this frame/packet's timestamps are expressed, as a rational
different from the timebase used by the muxer. number @var{num/den}. Note that encoder and muxer may use different timebases.
@item tbi @item tbi
Timebase for @var{ptsi}, as a rational number @var{num/den}. Available when Timebase for @var{ptsi}, as a rational number @var{num/den}. Available when
@@ -2132,31 +2384,42 @@ Presentation time of the frame or packet, as a decimal number. Equal to
Presentation time of the input frame (see @var{ni}), as a decimal number. Equal Presentation time of the input frame (see @var{ni}), as a decimal number. Equal
to @var{ptsi} multiplied by @var{tbi}. Printed as inf when not available. to @var{ptsi} multiplied by @var{tbi}. Printed as inf when not available.
@item dts @item dts (@emph{packet})
Decoding timestamp of the packet, as an integer. Should be multiplied by the Decoding timestamp of the packet, as an integer. Should be multiplied by the
timebase to compute presentation time. Post-encoding only. timebase to compute presentation time.
@item dt @item dt (@emph{packet})
Decoding time of the frame or packet, as a decimal number. Equal to Decoding time of the frame or packet, as a decimal number. Equal to
@var{dts} multiplied by @var{tb}. @var{dts} multiplied by @var{tb}.
@item sn @item sn (@emph{frame,audio})
Number of audio samples sent to the encoder so far. Audio and pre-encoding only. Number of audio samples sent to the encoder so far.
@item samp @item samp (@emph{frame,audio})
Number of audio samples in the frame. Audio and pre-encoding only. Number of audio samples in the frame.
@item size @item size (@emph{packet})
Size of the encoded packet in bytes. Post-encoding only. Size of the encoded packet in bytes.
@item br @item br (@emph{packet})
Current bitrate in bits per second. Post-encoding only. Current bitrate in bits per second.
@item abr @item abr (@emph{packet})
Average bitrate for the whole stream so far, in bits per second, -1 if it cannot Average bitrate for the whole stream so far, in bits per second, -1 if it cannot
be determined at this point. Post-encoding only. be determined at this point.
@item key (@emph{packet})
Character 'K' if the packet contains a keyframe, character 'N' otherwise.
@end table @end table
Directives tagged with @emph{packet} may only be used with
@option{-stats_enc_post_fmt} and @option{-stats_mux_pre_fmt}.
Directives tagged with @emph{frame} may only be used with
@option{-stats_enc_pre_fmt}.
Directives tagged with @emph{audio} may only be used with audio streams.
The default format strings are: The default format strings are:
@table @option @table @option
@item pre-encoding @item pre-encoding
@@ -2228,6 +2491,63 @@ search for the file @file{libvpx-1080p.avpreset}.
If no such file is found, then ffmpeg will search for a file named If no such file is found, then ffmpeg will search for a file named
@var{arg}.avpreset in the same directories. @var{arg}.avpreset in the same directories.
@anchor{vstats_file_format}
@section vstats file format
The @code{-vstats} and @code{-vstats_file} options enable generation of a file
containing statistics about the generated video outputs.
The @code{-vstats_version} option controls the format version of the generated
file.
With version @code{1} the format is:
@example
frame= @var{FRAME} q= @var{FRAME_QUALITY} PSNR= @var{PSNR} f_size= @var{FRAME_SIZE} s_size= @var{STREAM_SIZE}kB time= @var{TIMESTAMP} br= @var{BITRATE}kbits/s avg_br= @var{AVERAGE_BITRATE}kbits/s
@end example
With version @code{2} the format is:
@example
out= @var{OUT_FILE_INDEX} st= @var{OUT_FILE_STREAM_INDEX} frame= @var{FRAME_NUMBER} q= @var{FRAME_QUALITY}f PSNR= @var{PSNR} f_size= @var{FRAME_SIZE} s_size= @var{STREAM_SIZE}kB time= @var{TIMESTAMP} br= @var{BITRATE}kbits/s avg_br= @var{AVERAGE_BITRATE}kbits/s
@end example
The value corresponding to each key is described below:
@table @option
@item avg_br
average bitrate expressed in Kbits/s
@item br
bitrate expressed in Kbits/s
@item frame
number of encoded frame
@item out
out file index
@item PSNR
Peak Signal to Noise Ratio
@item q
quality of the frame
@item f_size
encoded packet size expressed as number of bytes
@item s_size
stream size expressed in KiB
@item st
out file stream index
@item time
time of the packet
@item type
picture type
@end table
See also the @ref{stats_enc_options,,-stats_enc options} for an alternative way
to show encoding statistics.
@c man end OPTIONS @c man end OPTIONS
@chapter Examples @chapter Examples
@@ -2491,7 +2811,7 @@ ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
@ignore @ignore
@setfilename ffmpeg @setfilename ffmpeg
@settitle ffmpeg video converter @settitle ffmpeg media converter
@end ignore @end ignore
+12
View File
@@ -196,6 +196,18 @@ will produce a thread pool with this many threads available for parallel
processing. The default is 0 which means that the thread count will be processing. The default is 0 which means that the thread count will be
determined by the number of available CPUs. determined by the number of available CPUs.
@item -enable_vulkan
Use vulkan renderer rather than SDL builtin renderer. Depends on libplacebo.
@item -vulkan_params
Vulkan configuration using a list of @var{key}=@var{value} pairs separated by
":".
@item -hwaccel
Use HW accelerated decoding. Enable this option will enable vulkan renderer
automatically.
@end table @end table
@section While playing @section While playing
+15 -7
View File
@@ -41,15 +41,15 @@ ffprobe will show it.
ffprobe output is designed to be easily parsable by a textual filter, ffprobe output is designed to be easily parsable by a textual filter,
and consists of one or more sections of a form defined by the selected and consists of one or more sections of a form defined by the selected
writer, which is specified by the @option{print_format} option. writer, which is specified by the @option{output_format} option.
Sections may contain other nested sections, and are identified by a Sections may contain other nested sections, and are identified by a
name (which may be shared by other sections), and an unique name (which may be shared by other sections), and an unique
name. See the output of @option{sections}. name. See the output of @option{sections}.
Metadata tags stored in the container or in the streams are recognized Metadata tags stored in the container or in the streams are recognized
and printed in the corresponding "FORMAT", "STREAM" or "PROGRAM_STREAM" and printed in the corresponding "FORMAT", "STREAM", "STREAM_GROUP_STREAM"
section. or "PROGRAM_STREAM" section.
@c man end @c man end
@@ -83,7 +83,7 @@ Use sexagesimal format HH:MM:SS.MICROSECONDS for time values.
Prettify the format of the displayed values, it corresponds to the Prettify the format of the displayed values, it corresponds to the
options "-unit -prefix -byte_binary_prefix -sexagesimal". options "-unit -prefix -byte_binary_prefix -sexagesimal".
@item -of, -print_format @var{writer_name}[=@var{writer_options}] @item -output_format, -of, -print_format @var{writer_name}[=@var{writer_options}]
Set the output printing format. Set the output printing format.
@var{writer_name} specifies the name of the writer, and @var{writer_name} specifies the name of the writer, and
@@ -91,7 +91,7 @@ Set the output printing format.
For example for printing the output in JSON format, specify: For example for printing the output in JSON format, specify:
@example @example
-print_format json -output_format json
@end example @end example
For more details on the available output printing formats, see the For more details on the available output printing formats, see the
@@ -232,6 +232,13 @@ multimedia stream.
Each media stream information is printed within a dedicated section Each media stream information is printed within a dedicated section
with name "PROGRAM_STREAM". with name "PROGRAM_STREAM".
@item -show_stream_groups
Show information about stream groups and their streams contained in the
input multimedia stream.
Each media stream information is printed within a dedicated section
with name "STREAM_GROUP_STREAM".
@item -show_chapters @item -show_chapters
Show information about chapters stored in the format. Show information about chapters stored in the format.
@@ -415,8 +422,9 @@ keyN=valN
[/SECTION] [/SECTION]
@end example @end example
Metadata tags are printed as a line in the corresponding FORMAT, STREAM or Metadata tags are printed as a line in the corresponding FORMAT, STREAM,
PROGRAM_STREAM section, and are prefixed by the string "TAG:". STREAM_GROUP_STREAM or PROGRAM_STREAM section, and are prefixed by the
string "TAG:".
A description of the accepted options follows. A description of the accepted options follows.
+479 -341
View File
@@ -1,389 +1,527 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ffmpeg.org/schema/ffprobe" targetNamespace="http://www.ffmpeg.org/schema/ffprobe"
xmlns:ffprobe="http://www.ffmpeg.org/schema/ffprobe"> xmlns:ffprobe="http://www.ffmpeg.org/schema/ffprobe">
<xsd:element name="ffprobe" type="ffprobe:ffprobeType"/> <xsd:element name="ffprobe" type="ffprobe:ffprobeType"/>
<xsd:complexType name="ffprobeType"> <xsd:complexType name="ffprobeType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="program_version" type="ffprobe:programVersionType" minOccurs="0" maxOccurs="1" /> <xsd:element name="program_version" type="ffprobe:programVersionType" minOccurs="0" maxOccurs="1" />
<xsd:element name="library_versions" type="ffprobe:libraryVersionsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="library_versions" type="ffprobe:libraryVersionsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="pixel_formats" type="ffprobe:pixelFormatsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="pixel_formats" type="ffprobe:pixelFormatsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="packets" type="ffprobe:packetsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="packets" type="ffprobe:packetsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="frames" type="ffprobe:framesType" minOccurs="0" maxOccurs="1" /> <xsd:element name="frames" type="ffprobe:framesType" minOccurs="0" maxOccurs="1" />
<xsd:element name="packets_and_frames" type="ffprobe:packetsAndFramesType" minOccurs="0" maxOccurs="1" /> <xsd:element name="packets_and_frames" type="ffprobe:packetsAndFramesType" minOccurs="0" maxOccurs="1" />
<xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="stream_groups" type="ffprobe:StreamGroupsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" /> <xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" />
<xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" /> <xsd:element name="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
<xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" /> <xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
</xsd:sequence> <xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" />
</xsd:complexType> </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="packetsType"> <xsd:complexType name="packetsType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="packet" type="ffprobe:packetType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="packet" type="ffprobe:packetType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:sequence>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="framesType"> <xsd:complexType name="framesType">
<xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="frame" type="ffprobe:frameType"/> <xsd:element name="frame" type="ffprobe:frameType"/>
<xsd:element name="subtitle" type="ffprobe:subtitleType"/> <xsd:element name="subtitle" type="ffprobe:subtitleType"/>
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="packetsAndFramesType"> <xsd:complexType name="packetsAndFramesType">
<xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="packet" type="ffprobe:packetType"/> <xsd:element name="packet" type="ffprobe:packetType"/>
<xsd:element name="frame" type="ffprobe:frameType"/> <xsd:element name="frame" type="ffprobe:frameType"/>
<xsd:element name="subtitle" type="ffprobe:subtitleType"/> <xsd:element name="subtitle" type="ffprobe:subtitleType"/>
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="packetType"> <xsd:complexType name="tagsType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="side_data_list" type="ffprobe:packetSideDataListType" minOccurs="0" maxOccurs="1" /> </xsd:sequence>
</xsd:sequence> </xsd:complexType>
<xsd:attribute name="codec_type" type="xsd:string" use="required" /> <xsd:complexType name="packetType">
<xsd:attribute name="stream_index" type="xsd:int" use="required" /> <xsd:sequence>
<xsd:attribute name="pts" type="xsd:long" /> <xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="pts_time" type="xsd:float" /> <xsd:element name="side_data_list" type="ffprobe:packetSideDataListType" minOccurs="0" maxOccurs="1" />
<xsd:attribute name="dts" type="xsd:long" /> </xsd:sequence>
<xsd:attribute name="dts_time" type="xsd:float" />
<xsd:attribute name="duration" type="xsd:long" />
<xsd:attribute name="duration_time" type="xsd:float" />
<xsd:attribute name="size" type="xsd:long" use="required" />
<xsd:attribute name="pos" type="xsd:long" />
<xsd:attribute name="flags" type="xsd:string" use="required" />
<xsd:attribute name="data" type="xsd:string" />
<xsd:attribute name="data_hash" type="xsd:string" />
</xsd:complexType>
<xsd:complexType name="packetSideDataListType"> <xsd:attribute name="codec_type" type="xsd:string" use="required" />
<xsd:sequence> <xsd:attribute name="stream_index" type="xsd:int" use="required" />
<xsd:element name="side_data" type="ffprobe:packetSideDataType" minOccurs="1" maxOccurs="unbounded"/> <xsd:attribute name="pts" type="xsd:long" />
</xsd:sequence> <xsd:attribute name="pts_time" type="xsd:float" />
</xsd:complexType> <xsd:attribute name="dts" type="xsd:long" />
<xsd:complexType name="packetSideDataType"> <xsd:attribute name="dts_time" type="xsd:float" />
<xsd:attribute name="side_data_type" type="xsd:string"/> <xsd:attribute name="duration" type="xsd:long" />
<xsd:attribute name="side_data_size" type="xsd:int" /> <xsd:attribute name="duration_time" type="xsd:float" />
</xsd:complexType> <xsd:attribute name="size" type="xsd:long" use="required" />
<xsd:attribute name="pos" type="xsd:long" />
<xsd:attribute name="flags" type="xsd:string" use="required" />
<xsd:attribute name="data" type="xsd:string" />
<xsd:attribute name="data_hash" type="xsd:string" />
</xsd:complexType>
<xsd:complexType name="frameType"> <xsd:complexType name="packetSideDataListType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="side_data" type="ffprobe:packetSideDataType" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="logs" type="ffprobe:logsType" minOccurs="0" maxOccurs="1"/> </xsd:sequence>
<xsd:element name="side_data_list" type="ffprobe:frameSideDataListType" minOccurs="0" maxOccurs="1" /> </xsd:complexType>
</xsd:sequence>
<xsd:attribute name="media_type" type="xsd:string" use="required"/> <xsd:complexType name="packetSideDataType">
<xsd:attribute name="stream_index" type="xsd:int" /> <xsd:sequence>
<xsd:attribute name="key_frame" type="xsd:int" use="required"/> <xsd:element name="side_datum" type="ffprobe:packetSideDatumType" minOccurs="1" maxOccurs="unbounded"/>
<xsd:attribute name="pts" type="xsd:long" /> </xsd:sequence>
<xsd:attribute name="pts_time" type="xsd:float"/>
<xsd:attribute name="pkt_dts" type="xsd:long" />
<xsd:attribute name="pkt_dts_time" type="xsd:float"/>
<xsd:attribute name="best_effort_timestamp" type="xsd:long" />
<xsd:attribute name="best_effort_timestamp_time" type="xsd:float" />
<xsd:attribute name="pkt_duration" type="xsd:long" />
<xsd:attribute name="pkt_duration_time" type="xsd:float"/>
<xsd:attribute name="duration" type="xsd:long" />
<xsd:attribute name="duration_time" type="xsd:float"/>
<xsd:attribute name="pkt_pos" type="xsd:long" />
<xsd:attribute name="pkt_size" type="xsd:int" />
<!-- audio attributes --> <xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="sample_fmt" type="xsd:string"/> </xsd:complexType>
<xsd:attribute name="nb_samples" type="xsd:long" />
<xsd:attribute name="channels" type="xsd:int" />
<xsd:attribute name="channel_layout" type="xsd:string"/>
<!-- video attributes --> <xsd:complexType name="packetSideDatumType">
<xsd:attribute name="width" type="xsd:long" /> <xsd:attribute name="key" type="xsd:string"/>
<xsd:attribute name="height" type="xsd:long" /> <xsd:attribute name="value" type="xsd:string"/>
<xsd:attribute name="pix_fmt" type="xsd:string"/> </xsd:complexType>
<xsd:attribute name="sample_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="pict_type" type="xsd:string"/>
<xsd:attribute name="coded_picture_number" type="xsd:long" />
<xsd:attribute name="display_picture_number" type="xsd:long" />
<xsd:attribute name="interlaced_frame" type="xsd:int" />
<xsd:attribute name="top_field_first" type="xsd:int" />
<xsd:attribute name="repeat_pict" type="xsd:int" />
<xsd:attribute name="color_range" type="xsd:string"/>
<xsd:attribute name="color_space" type="xsd:string"/>
<xsd:attribute name="color_primaries" type="xsd:string"/>
<xsd:attribute name="color_transfer" type="xsd:string"/>
<xsd:attribute name="chroma_location" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="logsType"> <xsd:complexType name="frameType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="log" type="ffprobe:logType" minOccurs="1" maxOccurs="unbounded"/> <xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence> <xsd:element name="logs" type="ffprobe:logsType" minOccurs="0" maxOccurs="1"/>
</xsd:complexType> <xsd:element name="side_data_list" type="ffprobe:frameSideDataListType" minOccurs="0" maxOccurs="1" />
<xsd:complexType name="logType"> </xsd:sequence>
<xsd:attribute name="context" type="xsd:string"/>
<xsd:attribute name="level" type="xsd:int" />
<xsd:attribute name="category" type="xsd:int" />
<xsd:attribute name="parent_context" type="xsd:string"/>
<xsd:attribute name="parent_category" type="xsd:int" />
<xsd:attribute name="message" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="frameSideDataListType"> <xsd:attribute name="media_type" type="xsd:string" use="required"/>
<xsd:sequence> <xsd:attribute name="stream_index" type="xsd:int" />
<xsd:element name="side_data" type="ffprobe:frameSideDataType" minOccurs="1" maxOccurs="unbounded"/> <xsd:attribute name="key_frame" type="xsd:int" use="required"/>
</xsd:sequence> <xsd:attribute name="pts" type="xsd:long" />
</xsd:complexType> <xsd:attribute name="pts_time" type="xsd:float"/>
<xsd:complexType name="frameSideDataType"> <xsd:attribute name="pkt_dts" type="xsd:long" />
<xsd:sequence> <xsd:attribute name="pkt_dts_time" type="xsd:float"/>
<xsd:element name="timecodes" type="ffprobe:frameSideDataTimecodeList" minOccurs="0" maxOccurs="1"/> <xsd:attribute name="best_effort_timestamp" type="xsd:long" />
</xsd:sequence> <xsd:attribute name="best_effort_timestamp_time" type="xsd:float" />
<xsd:attribute name="duration" type="xsd:long" />
<xsd:attribute name="duration_time" type="xsd:float"/>
<xsd:attribute name="pkt_pos" type="xsd:long" />
<xsd:attribute name="pkt_size" type="xsd:int" />
<xsd:attribute name="side_data_type" type="xsd:string"/> <!-- audio attributes -->
<xsd:attribute name="side_data_size" type="xsd:int" /> <xsd:attribute name="sample_fmt" type="xsd:string"/>
<xsd:attribute name="timecode" type="xsd:string"/> <xsd:attribute name="nb_samples" type="xsd:long" />
</xsd:complexType> <xsd:attribute name="channels" type="xsd:int" />
<xsd:attribute name="channel_layout" type="xsd:string"/>
<xsd:complexType name="frameSideDataTimecodeList"> <!-- video attributes -->
<xsd:sequence> <xsd:attribute name="width" type="xsd:long" />
<xsd:element name="timecode" type="ffprobe:frameSideDataTimecodeType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="height" type="xsd:long" />
</xsd:sequence> <xsd:attribute name="crop_top" type="xsd:long" />
</xsd:complexType> <xsd:attribute name="crop_bottom" type="xsd:long" />
<xsd:attribute name="crop_left" type="xsd:long" />
<xsd:attribute name="crop_right" type="xsd:long" />
<xsd:attribute name="pix_fmt" type="xsd:string"/>
<xsd:attribute name="sample_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="pict_type" type="xsd:string"/>
<xsd:attribute name="interlaced_frame" type="xsd:int" />
<xsd:attribute name="top_field_first" type="xsd:int" />
<xsd:attribute name="repeat_pict" type="xsd:int" />
<xsd:attribute name="color_range" type="xsd:string"/>
<xsd:attribute name="color_space" type="xsd:string"/>
<xsd:attribute name="color_primaries" type="xsd:string"/>
<xsd:attribute name="color_transfer" type="xsd:string"/>
<xsd:attribute name="chroma_location" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="frameSideDataTimecodeType"> <xsd:complexType name="logsType">
<xsd:attribute name="value" type="xsd:string"/> <xsd:sequence>
</xsd:complexType> <xsd:element name="log" type="ffprobe:logType" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="logType">
<xsd:attribute name="context" type="xsd:string"/>
<xsd:attribute name="level" type="xsd:int" />
<xsd:attribute name="category" type="xsd:int" />
<xsd:attribute name="parent_context" type="xsd:string"/>
<xsd:attribute name="parent_category" type="xsd:int" />
<xsd:attribute name="message" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="subtitleType"> <xsd:complexType name="frameSideDataListType">
<xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/> <xsd:sequence>
<xsd:attribute name="pts" type="xsd:long" /> <xsd:element name="side_data" type="ffprobe:frameSideDataType" minOccurs="1" maxOccurs="unbounded"/>
<xsd:attribute name="pts_time" type="xsd:float"/> </xsd:sequence>
<xsd:attribute name="format" type="xsd:int" /> </xsd:complexType>
<xsd:attribute name="start_display_time" type="xsd:int" /> <xsd:complexType name="frameSideDataType">
<xsd:attribute name="end_display_time" type="xsd:int" /> <xsd:sequence>
<xsd:attribute name="num_rects" type="xsd:int" /> <xsd:element name="timecodes" type="ffprobe:frameSideDataTimecodeList" minOccurs="0" maxOccurs="1"/>
</xsd:complexType> <xsd:element name="components" type="ffprobe:frameSideDataComponentList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:complexType name="streamsType"> <xsd:attribute name="side_data_type" type="xsd:string"/>
<xsd:sequence> <xsd:attribute name="side_data_size" type="xsd:int" />
<xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="timecode" type="xsd:string"/>
</xsd:sequence> </xsd:complexType>
</xsd:complexType>
<xsd:complexType name="programsType"> <xsd:complexType name="frameSideDatumType">
<xsd:sequence> <xsd:attribute name="key" type="xsd:string"/>
<xsd:element name="program" type="ffprobe:programType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="value" type="xsd:string"/>
</xsd:sequence> </xsd:complexType>
</xsd:complexType>
<xsd:complexType name="streamDispositionType"> <xsd:complexType name="frameSideDataTimecodeList">
<xsd:attribute name="default" type="xsd:int" use="required" /> <xsd:sequence>
<xsd:attribute name="dub" type="xsd:int" use="required" /> <xsd:element name="timecode" type="ffprobe:frameSideDataTimecodeType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="original" type="xsd:int" use="required" /> </xsd:sequence>
<xsd:attribute name="comment" type="xsd:int" use="required" /> </xsd:complexType>
<xsd:attribute name="lyrics" type="xsd:int" use="required" />
<xsd:attribute name="karaoke" type="xsd:int" use="required" />
<xsd:attribute name="forced" type="xsd:int" use="required" />
<xsd:attribute name="hearing_impaired" type="xsd:int" use="required" />
<xsd:attribute name="visual_impaired" type="xsd:int" use="required" />
<xsd:attribute name="clean_effects" type="xsd:int" use="required" />
<xsd:attribute name="attached_pic" type="xsd:int" use="required" />
<xsd:attribute name="timed_thumbnails" type="xsd:int" use="required" />
<xsd:attribute name="captions" type="xsd:int" use="required" />
<xsd:attribute name="descriptions" type="xsd:int" use="required" />
<xsd:attribute name="metadata" type="xsd:int" use="required" />
<xsd:attribute name="dependent" type="xsd:int" use="required" />
<xsd:attribute name="still_image" type="xsd:int" use="required" />
</xsd:complexType>
<xsd:complexType name="streamType"> <xsd:complexType name="frameSideDataTimecodeType">
<xsd:sequence> <xsd:attribute name="value" type="xsd:string"/>
<xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/> </xsd:complexType>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="side_data_list" type="ffprobe:packetSideDataListType" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="index" type="xsd:int" use="required"/> <xsd:complexType name="frameSideDataComponentList">
<xsd:attribute name="codec_name" type="xsd:string" /> <xsd:sequence>
<xsd:attribute name="codec_long_name" type="xsd:string" /> <xsd:element name="component" type="ffprobe:frameSideDataComponentType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="profile" type="xsd:string" /> </xsd:sequence>
<xsd:attribute name="codec_type" type="xsd:string" /> </xsd:complexType>
<xsd:attribute name="codec_tag" type="xsd:string" use="required"/>
<xsd:attribute name="codec_tag_string" type="xsd:string" use="required"/>
<xsd:attribute name="extradata" type="xsd:string" />
<xsd:attribute name="extradata_size" type="xsd:int" />
<xsd:attribute name="extradata_hash" type="xsd:string" />
<!-- video attributes --> <xsd:complexType name="frameSideDataComponentType">
<xsd:attribute name="width" type="xsd:int"/> <xsd:sequence>
<xsd:attribute name="height" type="xsd:int"/> <xsd:element name="pieces" type="ffprobe:frameSideDataPieceList" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="coded_width" type="xsd:int"/> <xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="coded_height" type="xsd:int"/> </xsd:sequence>
<xsd:attribute name="closed_captions" type="xsd:boolean"/> </xsd:complexType>
<xsd:attribute name="film_grain" type="xsd:boolean"/>
<xsd:attribute name="has_b_frames" type="xsd:int"/>
<xsd:attribute name="sample_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="display_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="pix_fmt" type="xsd:string"/>
<xsd:attribute name="level" type="xsd:int"/>
<xsd:attribute name="color_range" type="xsd:string"/>
<xsd:attribute name="color_space" type="xsd:string"/>
<xsd:attribute name="color_transfer" type="xsd:string"/>
<xsd:attribute name="color_primaries" type="xsd:string"/>
<xsd:attribute name="chroma_location" type="xsd:string"/>
<xsd:attribute name="field_order" type="xsd:string"/>
<xsd:attribute name="refs" type="xsd:int"/>
<!-- audio attributes --> <xsd:complexType name="frameSideDataPieceList">
<xsd:attribute name="sample_fmt" type="xsd:string"/> <xsd:sequence>
<xsd:attribute name="sample_rate" type="xsd:int"/> <xsd:element name="piece" type="ffprobe:frameSideDataPieceType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="channels" type="xsd:int"/> </xsd:sequence>
<xsd:attribute name="channel_layout" type="xsd:string"/> </xsd:complexType>
<xsd:attribute name="bits_per_sample" type="xsd:int"/>
<xsd:attribute name="initial_padding" type="xsd:int"/>
<xsd:attribute name="id" type="xsd:string"/> <xsd:complexType name="frameSideDataPieceType">
<xsd:attribute name="r_frame_rate" type="xsd:string" use="required"/> <xsd:sequence>
<xsd:attribute name="avg_frame_rate" type="xsd:string" use="required"/> <xsd:element name="side_datum" type="ffprobe:frameSideDatumType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="time_base" type="xsd:string" use="required"/> </xsd:sequence>
<xsd:attribute name="start_pts" type="xsd:long"/> </xsd:complexType>
<xsd:attribute name="start_time" type="xsd:float"/>
<xsd:attribute name="duration_ts" type="xsd:long"/>
<xsd:attribute name="duration" type="xsd:float"/>
<xsd:attribute name="bit_rate" type="xsd:int"/>
<xsd:attribute name="max_bit_rate" type="xsd:int"/>
<xsd:attribute name="bits_per_raw_sample" type="xsd:int"/>
<xsd:attribute name="nb_frames" type="xsd:int"/>
<xsd:attribute name="nb_read_frames" type="xsd:int"/>
<xsd:attribute name="nb_read_packets" type="xsd:int"/>
</xsd:complexType>
<xsd:complexType name="programType"> <xsd:complexType name="subtitleType">
<xsd:sequence> <xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="pts" type="xsd:long" />
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/> <xsd:attribute name="pts_time" type="xsd:float"/>
</xsd:sequence> <xsd:attribute name="format" type="xsd:int" />
<xsd:attribute name="start_display_time" type="xsd:int" />
<xsd:attribute name="end_display_time" type="xsd:int" />
<xsd:attribute name="num_rects" type="xsd:int" />
</xsd:complexType>
<xsd:attribute name="program_id" type="xsd:int" use="required"/> <xsd:complexType name="streamsType">
<xsd:attribute name="program_num" type="xsd:int" use="required"/> <xsd:sequence>
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/> <xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="pmt_pid" type="xsd:int" use="required"/> </xsd:sequence>
<xsd:attribute name="pcr_pid" type="xsd:int" use="required"/> </xsd:complexType>
</xsd:complexType>
<xsd:complexType name="formatType"> <xsd:complexType name="programsType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="program" type="ffprobe:programType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:sequence>
</xsd:complexType>
<xsd:attribute name="filename" type="xsd:string" use="required"/> <xsd:complexType name="StreamGroupsType">
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/> <xsd:sequence>
<xsd:attribute name="nb_programs" type="xsd:int" use="required"/> <xsd:element name="stream_group" type="ffprobe:streamGroupType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="format_name" type="xsd:string" use="required"/> </xsd:sequence>
<xsd:attribute name="format_long_name" type="xsd:string"/> </xsd:complexType>
<xsd:attribute name="start_time" type="xsd:float"/>
<xsd:attribute name="duration" type="xsd:float"/>
<xsd:attribute name="size" type="xsd:long"/>
<xsd:attribute name="bit_rate" type="xsd:long"/>
<xsd:attribute name="probe_score" type="xsd:int"/>
</xsd:complexType>
<xsd:complexType name="tagType"> <xsd:complexType name="streamDispositionType">
<xsd:attribute name="key" type="xsd:string" use="required"/> <xsd:attribute name="default" type="xsd:int" use="required" />
<xsd:attribute name="value" type="xsd:string" use="required"/> <xsd:attribute name="dub" type="xsd:int" use="required" />
</xsd:complexType> <xsd:attribute name="original" type="xsd:int" use="required" />
<xsd:attribute name="comment" type="xsd:int" use="required" />
<xsd:attribute name="lyrics" type="xsd:int" use="required" />
<xsd:attribute name="karaoke" type="xsd:int" use="required" />
<xsd:attribute name="forced" type="xsd:int" use="required" />
<xsd:attribute name="hearing_impaired" type="xsd:int" use="required" />
<xsd:attribute name="visual_impaired" type="xsd:int" use="required" />
<xsd:attribute name="clean_effects" type="xsd:int" use="required" />
<xsd:attribute name="attached_pic" type="xsd:int" use="required" />
<xsd:attribute name="timed_thumbnails" type="xsd:int" use="required" />
<xsd:attribute name="non_diegetic" type="xsd:int" use="required" />
<xsd:attribute name="captions" type="xsd:int" use="required" />
<xsd:attribute name="descriptions" type="xsd:int" use="required" />
<xsd:attribute name="metadata" type="xsd:int" use="required" />
<xsd:attribute name="dependent" type="xsd:int" use="required" />
<xsd:attribute name="still_image" type="xsd:int" use="required" />
</xsd:complexType>
<xsd:complexType name="errorType"> <xsd:complexType name="streamType">
<xsd:attribute name="code" type="xsd:int" use="required"/> <xsd:sequence>
<xsd:attribute name="string" type="xsd:string" use="required"/> <xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/>
</xsd:complexType> <xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="side_data_list" type="ffprobe:packetSideDataListType" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:complexType name="programVersionType"> <xsd:attribute name="index" type="xsd:int" use="required"/>
<xsd:attribute name="version" type="xsd:string" use="required"/> <xsd:attribute name="codec_name" type="xsd:string" />
<xsd:attribute name="copyright" type="xsd:string" use="required"/> <xsd:attribute name="codec_long_name" type="xsd:string" />
<xsd:attribute name="build_date" type="xsd:string"/> <xsd:attribute name="profile" type="xsd:string" />
<xsd:attribute name="build_time" type="xsd:string"/> <xsd:attribute name="codec_type" type="xsd:string" />
<xsd:attribute name="compiler_ident" type="xsd:string" use="required"/> <xsd:attribute name="codec_tag" type="xsd:string" use="required"/>
<xsd:attribute name="configuration" type="xsd:string" use="required"/> <xsd:attribute name="codec_tag_string" type="xsd:string" use="required"/>
</xsd:complexType> <xsd:attribute name="extradata" type="xsd:string" />
<xsd:attribute name="extradata_size" type="xsd:int" />
<xsd:attribute name="extradata_hash" type="xsd:string" />
<xsd:complexType name="chaptersType"> <!-- video attributes -->
<xsd:sequence> <xsd:attribute name="width" type="xsd:int"/>
<xsd:element name="chapter" type="ffprobe:chapterType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="height" type="xsd:int"/>
</xsd:sequence> <xsd:attribute name="coded_width" type="xsd:int"/>
</xsd:complexType> <xsd:attribute name="coded_height" type="xsd:int"/>
<xsd:attribute name="closed_captions" type="xsd:boolean"/>
<xsd:attribute name="film_grain" type="xsd:boolean"/>
<xsd:attribute name="has_b_frames" type="xsd:int"/>
<xsd:attribute name="sample_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="display_aspect_ratio" type="xsd:string"/>
<xsd:attribute name="pix_fmt" type="xsd:string"/>
<xsd:attribute name="level" type="xsd:int"/>
<xsd:attribute name="color_range" type="xsd:string"/>
<xsd:attribute name="color_space" type="xsd:string"/>
<xsd:attribute name="color_transfer" type="xsd:string"/>
<xsd:attribute name="color_primaries" type="xsd:string"/>
<xsd:attribute name="chroma_location" type="xsd:string"/>
<xsd:attribute name="field_order" type="xsd:string"/>
<xsd:attribute name="refs" type="xsd:int"/>
<xsd:complexType name="chapterType"> <!-- audio attributes -->
<xsd:sequence> <xsd:attribute name="sample_fmt" type="xsd:string"/>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="sample_rate" type="xsd:int"/>
</xsd:sequence> <xsd:attribute name="channels" type="xsd:int"/>
<xsd:attribute name="channel_layout" type="xsd:string"/>
<xsd:attribute name="bits_per_sample" type="xsd:int"/>
<xsd:attribute name="initial_padding" type="xsd:int"/>
<xsd:attribute name="id" type="xsd:int" use="required"/> <xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="time_base" type="xsd:string" use="required"/> <xsd:attribute name="r_frame_rate" type="xsd:string" use="required"/>
<xsd:attribute name="start" type="xsd:int" use="required"/> <xsd:attribute name="avg_frame_rate" type="xsd:string" use="required"/>
<xsd:attribute name="start_time" type="xsd:float"/> <xsd:attribute name="time_base" type="xsd:string" use="required"/>
<xsd:attribute name="end" type="xsd:int" use="required"/> <xsd:attribute name="start_pts" type="xsd:long"/>
<xsd:attribute name="end_time" type="xsd:float" use="required"/> <xsd:attribute name="start_time" type="xsd:float"/>
</xsd:complexType> <xsd:attribute name="duration_ts" type="xsd:long"/>
<xsd:attribute name="duration" type="xsd:float"/>
<xsd:attribute name="bit_rate" type="xsd:int"/>
<xsd:attribute name="max_bit_rate" type="xsd:int"/>
<xsd:attribute name="bits_per_raw_sample" type="xsd:int"/>
<xsd:attribute name="nb_frames" type="xsd:int"/>
<xsd:attribute name="nb_read_frames" type="xsd:int"/>
<xsd:attribute name="nb_read_packets" type="xsd:int"/>
</xsd:complexType>
<xsd:complexType name="libraryVersionType"> <xsd:complexType name="programType">
<xsd:attribute name="name" type="xsd:string" use="required"/> <xsd:sequence>
<xsd:attribute name="major" type="xsd:int" use="required"/> <xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="minor" type="xsd:int" use="required"/> <xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="micro" type="xsd:int" use="required"/> </xsd:sequence>
<xsd:attribute name="version" type="xsd:int" use="required"/>
<xsd:attribute name="ident" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="libraryVersionsType"> <xsd:attribute name="program_id" type="xsd:int" use="required"/>
<xsd:sequence> <xsd:attribute name="program_num" type="xsd:int" use="required"/>
<xsd:element name="library_version" type="ffprobe:libraryVersionType" minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
</xsd:sequence> <xsd:attribute name="pmt_pid" type="xsd:int" use="required"/>
</xsd:complexType> <xsd:attribute name="pcr_pid" type="xsd:int" use="required"/>
</xsd:complexType>
<xsd:complexType name="pixelFormatFlagsType"> <xsd:complexType name="streamGroupType">
<xsd:attribute name="big_endian" type="xsd:int" use="required"/> <xsd:sequence>
<xsd:attribute name="palette" type="xsd:int" use="required"/> <xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="bitstream" type="xsd:int" use="required"/> <xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="hwaccel" type="xsd:int" use="required"/> <xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="planar" type="xsd:int" use="required"/> <xsd:element name="components" type="ffprobe:streamGroupComponentList" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="rgb" type="xsd:int" use="required"/> </xsd:sequence>
<xsd:attribute name="alpha" type="xsd:int" use="required"/>
</xsd:complexType>
<xsd:complexType name="pixelFormatComponentType"> <xsd:attribute name="index" type="xsd:int" use="required"/>
<xsd:attribute name="index" type="xsd:int" use="required"/> <xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
<xsd:attribute name="bit_depth" type="xsd:int" use="required"/> <xsd:attribute name="type" type="xsd:string" use="required"/>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="pixelFormatComponentsType"> <xsd:complexType name="streamGroupComponentList">
<xsd:sequence> <xsd:sequence>
<xsd:element name="component" type="ffprobe:pixelFormatComponentType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="component" type="ffprobe:streamGroupComponentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:sequence>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="pixelFormatType"> <xsd:complexType name="streamGroupComponentType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="flags" type="ffprobe:pixelFormatFlagsType" minOccurs="0" maxOccurs="1"/> <xsd:element name="subcomponents" type="ffprobe:streamGroupSubComponentList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="components" type="ffprobe:pixelFormatComponentsType" minOccurs="0" maxOccurs="1"/> <xsd:element name="component_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:sequence>
</xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required"/> <xsd:complexType name="streamGroupSubComponentList">
<xsd:attribute name="nb_components" type="xsd:int" use="required"/> <xsd:sequence>
<xsd:attribute name="log2_chroma_w" type="xsd:int"/> <xsd:element name="subcomponent" type="ffprobe:streamGroupSubComponentType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:attribute name="log2_chroma_h" type="xsd:int"/> </xsd:sequence>
<xsd:attribute name="bits_per_pixel" type="xsd:int"/> </xsd:complexType>
</xsd:complexType>
<xsd:complexType name="pixelFormatsType"> <xsd:complexType name="streamGroupSubComponentType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="pixel_format" type="ffprobe:pixelFormatType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="pieces" type="ffprobe:streamGroupPieceList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence> <xsd:element name="subcomponent_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:complexType> </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupPieceList">
<xsd:sequence>
<xsd:element name="piece" type="ffprobe:streamGroupPieceType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupPieceType">
<xsd:sequence>
<xsd:element name="subpieces" type="ffprobe:streamGroupSubPieceList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="piece_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupSubPieceList">
<xsd:sequence>
<xsd:element name="subpiece" type="ffprobe:streamGroupSubPieceType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupSubPieceType">
<xsd:sequence>
<xsd:element name="blocks" type="ffprobe:streamGroupBlockList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="subpiece_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupBlockList">
<xsd:sequence>
<xsd:element name="block" type="ffprobe:streamGroupBlockType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupBlockType">
<xsd:sequence>
<xsd:element name="block_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="streamGroupEntryType">
<xsd:attribute name="key" type="xsd:string"/>
<xsd:attribute name="value" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="formatType">
<xsd:sequence>
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="filename" type="xsd:string" use="required"/>
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
<xsd:attribute name="nb_programs" type="xsd:int" use="required"/>
<xsd:attribute name="nb_stream_groups" type="xsd:int" use="required"/>
<xsd:attribute name="format_name" type="xsd:string" use="required"/>
<xsd:attribute name="format_long_name" type="xsd:string"/>
<xsd:attribute name="start_time" type="xsd:float"/>
<xsd:attribute name="duration" type="xsd:float"/>
<xsd:attribute name="size" type="xsd:long"/>
<xsd:attribute name="bit_rate" type="xsd:long"/>
<xsd:attribute name="probe_score" type="xsd:int"/>
</xsd:complexType>
<xsd:complexType name="tagType">
<xsd:attribute name="key" type="xsd:string" use="required"/>
<xsd:attribute name="value" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="errorType">
<xsd:attribute name="code" type="xsd:int" use="required"/>
<xsd:attribute name="string" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="programVersionType">
<xsd:attribute name="version" type="xsd:string" use="required"/>
<xsd:attribute name="copyright" type="xsd:string" use="required"/>
<xsd:attribute name="build_date" type="xsd:string"/>
<xsd:attribute name="build_time" type="xsd:string"/>
<xsd:attribute name="compiler_ident" type="xsd:string" use="required"/>
<xsd:attribute name="configuration" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="chaptersType">
<xsd:sequence>
<xsd:element name="chapter" type="ffprobe:chapterType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="chapterType">
<xsd:sequence>
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:int" use="required"/>
<xsd:attribute name="time_base" type="xsd:string" use="required"/>
<xsd:attribute name="start" type="xsd:int" use="required"/>
<xsd:attribute name="start_time" type="xsd:float"/>
<xsd:attribute name="end" type="xsd:int" use="required"/>
<xsd:attribute name="end_time" type="xsd:float" use="required"/>
</xsd:complexType>
<xsd:complexType name="libraryVersionType">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="major" type="xsd:int" use="required"/>
<xsd:attribute name="minor" type="xsd:int" use="required"/>
<xsd:attribute name="micro" type="xsd:int" use="required"/>
<xsd:attribute name="version" type="xsd:int" use="required"/>
<xsd:attribute name="ident" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="libraryVersionsType">
<xsd:sequence>
<xsd:element name="library_version" type="ffprobe:libraryVersionType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="pixelFormatFlagsType">
<xsd:attribute name="big_endian" type="xsd:int" use="required"/>
<xsd:attribute name="palette" type="xsd:int" use="required"/>
<xsd:attribute name="bitstream" type="xsd:int" use="required"/>
<xsd:attribute name="hwaccel" type="xsd:int" use="required"/>
<xsd:attribute name="planar" type="xsd:int" use="required"/>
<xsd:attribute name="rgb" type="xsd:int" use="required"/>
<xsd:attribute name="alpha" type="xsd:int" use="required"/>
</xsd:complexType>
<xsd:complexType name="pixelFormatComponentType">
<xsd:attribute name="index" type="xsd:int" use="required"/>
<xsd:attribute name="bit_depth" type="xsd:int" use="required"/>
</xsd:complexType>
<xsd:complexType name="pixelFormatComponentsType">
<xsd:sequence>
<xsd:element name="component" type="ffprobe:pixelFormatComponentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="pixelFormatType">
<xsd:sequence>
<xsd:element name="flags" type="ffprobe:pixelFormatFlagsType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="components" type="ffprobe:pixelFormatComponentsType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="nb_components" type="xsd:int" use="required"/>
<xsd:attribute name="log2_chroma_w" type="xsd:int"/>
<xsd:attribute name="log2_chroma_h" type="xsd:int"/>
<xsd:attribute name="bits_per_pixel" type="xsd:int"/>
</xsd:complexType>
<xsd:complexType name="pixelFormatsType">
<xsd:sequence>
<xsd:element name="pixel_format" type="ffprobe:pixelFormatType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema> </xsd:schema>
+23 -3
View File
@@ -13,6 +13,15 @@ corresponding value to true. They can be set to false by prefixing
the option name with "no". For example using "-nofoo" the option name with "no". For example using "-nofoo"
will set the boolean option with name "foo" to false. will set the boolean option with name "foo" to false.
Options that take arguments support a special syntax where the argument given on
the command line is interpreted as a path to the file from which the actual
argument value is loaded. To use this feature, add a forward slash '/'
immediately before the option name (after the leading dash). E.g.
@example
ffmpeg -i INPUT -/filter:v filter.script OUTPUT
@end example
will load a filtergraph description from the file named @file{filter.script}.
@anchor{Stream specifiers} @anchor{Stream specifiers}
@section Stream specifiers @section Stream specifiers
Some options are applied per-stream, e.g. bitrate or codec. Stream specifiers Some options are applied per-stream, e.g. bitrate or codec. Stream specifiers
@@ -37,9 +46,9 @@ Matches the stream with this index. E.g. @code{-threads:1 4} would set the
thread count for the second stream to 4. If @var{stream_index} is used as an thread count for the second stream to 4. If @var{stream_index} is used as an
additional stream specifier (see below), then it selects stream number additional stream specifier (see below), then it selects stream number
@var{stream_index} from the matching streams. Stream numbering is based on the @var{stream_index} from the matching streams. Stream numbering is based on the
order of the streams as detected by libavformat except when a program ID is order of the streams as detected by libavformat except when a stream group
also specified. In this case it is based on the ordering of the streams in the specifier or program ID is also specified. In this case it is based on the
program. ordering of the streams in the group or program.
@item @var{stream_type}[:@var{additional_stream_specifier}] @item @var{stream_type}[:@var{additional_stream_specifier}]
@var{stream_type} is one of following: 'v' or 'V' for video, 'a' for audio, 's' @var{stream_type} is one of following: 'v' or 'V' for video, 'a' for audio, 's'
for subtitle, 'd' for data, and 't' for attachments. 'v' matches all video for subtitle, 'd' for data, and 't' for attachments. 'v' matches all video
@@ -48,6 +57,17 @@ thumbnails or cover arts. If @var{additional_stream_specifier} is used, then
it matches streams which both have this type and match the it matches streams which both have this type and match the
@var{additional_stream_specifier}. Otherwise, it matches all streams of the @var{additional_stream_specifier}. Otherwise, it matches all streams of the
specified type. specified type.
@item g:@var{group_specifier}[:@var{additional_stream_specifier}]
Matches streams which are in the group with the specifier @var{group_specifier}.
if @var{additional_stream_specifier} is used, then it matches streams which both
are part of the group and match the @var{additional_stream_specifier}.
@var{group_specifier} may be one of the following:
@table @option
@item @var{group_index}
Match the stream with this group index.
@item #@var{group_id} or i:@var{group_id}
Match the stream with this group id.
@end table
@item p:@var{program_id}[:@var{additional_stream_specifier}] @item p:@var{program_id}[:@var{additional_stream_specifier}]
Matches streams which are in the program with the id @var{program_id}. If Matches streams which are in the program with the id @var{program_id}. If
@var{additional_stream_specifier} is used, then it matches streams which both @var{additional_stream_specifier} is used, then it matches streams which both
+2203 -340
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -46,7 +46,8 @@ Enable fast, but inaccurate seeks for some formats.
@item genpts @item genpts
Generate missing PTS if DTS is present. Generate missing PTS if DTS is present.
@item igndts @item igndts
Ignore DTS if PTS is set. Inert when nofillin is set. Ignore DTS if PTS is also set. In case the PTS is set, the DTS value
is set to NOPTS. This is ignored when the @code{nofillin} flag is set.
@item ignidx @item ignidx
Ignore index. Ignore index.
@item nobuffer @item nobuffer
+29 -2
View File
@@ -343,6 +343,22 @@ libxavs2 is under the GNU Public License Version 2 or later
details), you must upgrade FFmpeg's license to GPL in order to use it. details), you must upgrade FFmpeg's license to GPL in order to use it.
@end float @end float
@section eXtra-fast Essential Video Encoder (XEVE)
FFmpeg can make use of the XEVE library for EVC video encoding.
Go to @url{https://github.com/mpeg5/xeve} and follow the instructions for
installing the XEVE library. Then pass @code{--enable-libxeve} to configure to
enable it.
@section eXtra-fast Essential Video Decoder (XEVD)
FFmpeg can make use of the XEVD library for EVC video decoding.
Go to @url{https://github.com/mpeg5/xevd} and follow the instructions for
installing the XEVD library. Then pass @code{--enable-libxevd} to configure to
enable it.
@section ZVBI @section ZVBI
ZVBI is a VBI decoding library which can be used by FFmpeg to decode DVB ZVBI is a VBI decoding library which can be used by FFmpeg to decode DVB
@@ -598,6 +614,7 @@ library:
@item raw DTS @tab X @tab X @item raw DTS @tab X @tab X
@item raw DTS-HD @tab @tab X @item raw DTS-HD @tab @tab X
@item raw E-AC-3 @tab X @tab X @item raw E-AC-3 @tab X @tab X
@item raw EVC @tab X @tab X
@item raw FLAC @tab X @tab X @item raw FLAC @tab X @tab X
@item raw GSM @tab @tab X @item raw GSM @tab @tab X
@item raw H.261 @tab X @tab X @item raw H.261 @tab X @tab X
@@ -615,6 +632,7 @@ library:
@item raw video @tab X @tab X @item raw video @tab X @tab X
@item raw id RoQ @tab X @tab @item raw id RoQ @tab X @tab
@item raw OBU @tab X @tab X @item raw OBU @tab X @tab X
@item raw OSQ @tab @tab X
@item raw SBC @tab X @tab X @item raw SBC @tab X @tab X
@item raw Shorten @tab @tab X @item raw Shorten @tab @tab X
@item raw TAK @tab @tab X @item raw TAK @tab @tab X
@@ -652,7 +670,8 @@ library:
@item Redirector @tab @tab X @item Redirector @tab @tab X
@item RedSpark @tab @tab X @item RedSpark @tab @tab X
@item Renderware TeXture Dictionary @tab @tab X @item Renderware TeXture Dictionary @tab @tab X
@item Resolume DXV @tab @tab X @item Resolume DXV @tab X @tab X
@tab Encoding is only supported for the DXT1 (Normal Quality, No Alpha) texture format.
@item RF64 @tab @tab X @item RF64 @tab @tab X
@item RL2 @tab @tab X @item RL2 @tab @tab X
@tab Audio and video format used in some games by Entertainment Software Partners. @tab Audio and video format used in some games by Entertainment Software Partners.
@@ -943,6 +962,8 @@ following image formats are supported:
@item Electronic Arts TQI video @tab @tab X @item Electronic Arts TQI video @tab @tab X
@item Escape 124 @tab @tab X @item Escape 124 @tab @tab X
@item Escape 130 @tab @tab X @item Escape 130 @tab @tab X
@item EVC / MPEG-5 Part 1 @tab E @tab E
@tab encoding and decoding supported through external libraries libxeve and libxevd
@item FFmpeg video codec #1 @tab X @tab X @item FFmpeg video codec #1 @tab X @tab X
@tab lossless codec (fourcc: FFV1) @tab lossless codec (fourcc: FFV1)
@item Flash Screen Video v1 @tab X @tab X @item Flash Screen Video v1 @tab X @tab X
@@ -996,6 +1017,7 @@ following image formats are supported:
@item Lagarith @tab @tab X @item Lagarith @tab @tab X
@item LCL (LossLess Codec Library) MSZH @tab @tab X @item LCL (LossLess Codec Library) MSZH @tab @tab X
@item LCL (LossLess Codec Library) ZLIB @tab E @tab E @item LCL (LossLess Codec Library) ZLIB @tab E @tab E
@item LEAD MCMP @tab @tab X
@item LOCO @tab @tab X @item LOCO @tab @tab X
@item LucasArts SANM/Smush @tab @tab X @item LucasArts SANM/Smush @tab @tab X
@tab Used in LucasArts games / SMUSH animations. @tab Used in LucasArts games / SMUSH animations.
@@ -1006,7 +1028,7 @@ following image formats are supported:
@tab Also known as Microsoft Screen 3. @tab Also known as Microsoft Screen 3.
@item Microsoft Expression Encoder Screen @tab @tab X @item Microsoft Expression Encoder Screen @tab @tab X
@tab Also known as Microsoft Titanium Screen 2. @tab Also known as Microsoft Titanium Screen 2.
@item Microsoft RLE @tab @tab X @item Microsoft RLE @tab X @tab X
@item Microsoft Screen 1 @tab @tab X @item Microsoft Screen 1 @tab @tab X
@tab Also known as Windows Media Video V7 Screen. @tab Also known as Windows Media Video V7 Screen.
@item Microsoft Screen 2 @tab @tab X @item Microsoft Screen 2 @tab @tab X
@@ -1066,6 +1088,8 @@ following image formats are supported:
@item RealVideo 4.0 @tab @tab X @item RealVideo 4.0 @tab @tab X
@item Renderware TXD (TeXture Dictionary) @tab @tab X @item Renderware TXD (TeXture Dictionary) @tab @tab X
@tab Texture dictionaries used by the Renderware Engine. @tab Texture dictionaries used by the Renderware Engine.
@item RivaTuner Video @tab @tab X
@tab fourcc: 'RTV1'
@item RL2 video @tab @tab X @item RL2 video @tab @tab X
@tab used in some games by Entertainment Software Partners @tab used in some games by Entertainment Software Partners
@item ScreenPressor @tab @tab X @item ScreenPressor @tab @tab X
@@ -1102,6 +1126,8 @@ following image formats are supported:
@item v408 QuickTime uncompressed 4: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 v410 QuickTime uncompressed 4:4:4 10-bit @tab X @tab X
@item VBLE Lossless Codec @tab @tab X @item VBLE Lossless Codec @tab @tab X
@item vMix Video @tab @tab X
@tab fourcc: 'VMX1'
@item VMware Screen Codec / VMware Video @tab @tab X @item VMware Screen Codec / VMware Video @tab @tab X
@tab Codec used in videos captured by VMware. @tab Codec used in videos captured by VMware.
@item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X @item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X
@@ -1294,6 +1320,7 @@ following image formats are supported:
@item On2 AVC (Audio for Video Codec) @tab @tab X @item On2 AVC (Audio for Video Codec) @tab @tab X
@item Opus @tab E @tab X @item Opus @tab E @tab X
@tab encoding supported through external library libopus @tab encoding supported through external library libopus
@item OSQ (Original Sound Quality) @tab @tab X
@item PCM A-law @tab X @tab X @item PCM A-law @tab X @tab X
@item PCM mu-law @tab X @tab X @item PCM mu-law @tab X @tab X
@item PCM Archimedes VIDC @tab X @tab X @item PCM Archimedes VIDC @tab X @tab X
+1 -1
View File
@@ -66,7 +66,7 @@ This will put the FFmpeg sources into the directory @var{<target>} and let
you push back your changes to the remote repository. you push back your changes to the remote repository.
@example @example
git clone gil@@ffmpeg.org:ffmpeg-web <target> git clone git@@ffmpeg.org:ffmpeg-web <target>
@end example @end example
This will put the source of the FFmpeg website into the directory This will put the source of the FFmpeg website into the directory
+10 -6
View File
@@ -222,7 +222,8 @@ $ ffmpeg -f avfoundation -capture_raw_data true -i "zr100:none" out.dv
@section bktr @section bktr
BSD video input device. BSD video input device. Deprecated and will be removed - please contact
the developers if you are interested in maintaining it.
@subsection Options @subsection Options
@@ -722,7 +723,7 @@ Win32 GDI-based screen capture device.
This device allows you to capture a region of the display on Windows. This device allows you to capture a region of the display on Windows.
There are two options for the input filename: Amongst options for the imput filenames are such elements as:
@example @example
desktop desktop
@end example @end example
@@ -730,9 +731,13 @@ or
@example @example
title=@var{window_title} title=@var{window_title}
@end example @end example
or
@example
hwnd=@var{window_hwnd}
@end example
The first option will capture the entire desktop, or a fixed region of the The first option will capture the entire desktop, or a fixed region of the
desktop. The second option will instead capture the contents of a single desktop. The second and third options will instead capture the contents of a single
window, regardless of its position on the screen. window, regardless of its position on the screen.
For example, to grab the entire desktop using @command{ffmpeg}: For example, to grab the entire desktop using @command{ffmpeg}:
@@ -991,9 +996,8 @@ This input device reads data from the open output pads of a libavfilter
filtergraph. filtergraph.
For each filtergraph open output, the input device will create a For each filtergraph open output, the input device will create a
corresponding stream which is mapped to the generated output. Currently corresponding stream which is mapped to the generated output.
only video data is supported. The filtergraph is specified through the The filtergraph is specified through the option @option{graph}.
option @option{graph}.
@subsection Options @subsection Options
+94
View File
@@ -0,0 +1,94 @@
FFmpeg Infrastructure:
======================
Servers:
~~~~~~~~
Main Server:
------------
Our Main server is hosted at telepoint.bg
for more details see: https://www.ffmpeg.org/#thanks_sponsor_0001
Nothing runs on our main server directly, instead several VMs run on it.
ffmpeg.org VM:
--------------
Web, mail, and public facing git, also website git
fftrac VM:
----------
trac.ffmpeg.org Issue tracking
ffaux VM:
---------
patchwork.ffmpeg.org Patch tracking
vote.ffmpeg.org Condorcet voting
fate:
-----
fate.ffmpeg.org FFmpeg automated testing environment
coverage:
---------
coverage.ffmpeg.org Fate code coverage
The main and fate server as well as VMs currently run ubuntu
Cronjobs:
~~~~~~~~~
Part of the docs is in the main ffmpeg repository as texi files, this part is build by a cronjob. So is the
doxygen stuff as well as the FFmpeg git snapshot.
These 3 scripts are under the ffcron user
Git:
~~~~
Public facing git is provided by our infra, (https://git.ffmpeg.org/gitweb)
main developer ffmpeg git repository for historic reasons is provided by (git@source.ffmpeg.org:ffmpeg)
Other developer git repositories are provided via git@git.ffmpeg.org:<NAME_OF_REPOSITORY>
git mirrors are available on https://github.com/FFmpeg
(there are some exceptions where primary repositories are on github or elsewhere instead of the mirrors)
Github mirrors are redundantly synced by multiple people
You need a new git repository related to FFmpeg ? contact root at ffmpeg.org
Fate:
~~~~~
fatesamples are provided via rsync. Every FFmpeg developer who has a shell account in ffmpeg.org
should be in the samples group and be able to upload samples.
See https://www.ffmpeg.org/fate.html#Uploading-new-samples-to-the-fate-suite
Accounts:
~~~~~~~~~
You need an account for some FFmpeg work? Send mail to root at ffmpeg.org
VMs:
~~~~
You need a VM, docker container for FFmpeg? contact root at ffmpeg.org
(for docker, CC Andriy)
IRC:
~~~~
irc channels are at https://libera.chat/
irc channel archives are at https://libera.irclog.whitequark.org
+1 -1
View File
@@ -344,7 +344,7 @@ recommended.
Avoid sending the same message to multiple mailing lists. Avoid sending the same message to multiple mailing lists.
@item @item
Please follow our @url{https://ffmpeg.org/developer.html#Code-of-conduct, Code of Conduct}. Please follow our @url{https://ffmpeg.org/community.html#Code-of-conduct, Code of Conduct}.
@end itemize @end itemize
@chapter Help @chapter Help
+1
View File
@@ -1,3 +1,4 @@
@anchor{metadata}
@chapter Metadata @chapter Metadata
@c man begin METADATA @c man begin METADATA
-8
View File
@@ -48,11 +48,6 @@ Files that have MIPS copyright notice in them:
float_dsp_mips.c float_dsp_mips.c
libm_mips.h libm_mips.h
softfloat_tables.h softfloat_tables.h
* libavcodec/
fft_fixed_32.c
fft_init_table.c
fft_table.h
mdct_fixed_32.c
* libavcodec/mips/ * libavcodec/mips/
aacdec_fixed.c aacdec_fixed.c
aacsbr_fixed.c aacsbr_fixed.c
@@ -70,9 +65,6 @@ Files that have MIPS copyright notice in them:
compute_antialias_float.h compute_antialias_float.h
lsp_mips.h lsp_mips.h
dsputil_mips.c dsputil_mips.c
fft_mips.c
fft_table.h
fft_init_table.c
fmtconvert_mips.c fmtconvert_mips.c
iirfilter_mips.c iirfilter_mips.c
mpegaudiodsp_mips_fixed.c mpegaudiodsp_mips_fixed.c
+1 -2
View File
@@ -55,8 +55,7 @@ speed gain at this point but it should work.
If there are inter-frame dependencies, so the codec calls If there are inter-frame dependencies, so the codec calls
ff_thread_report/await_progress(), set FF_CODEC_CAP_ALLOCATE_PROGRESS in 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 FFCodec.caps_internal and use ff_thread_get_buffer() to allocate frames.
frames must then be freed with ff_thread_release_buffer().
Otherwise 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. Call ff_thread_report_progress() after some part of the current picture has decoded.
+1448 -612
View File
File diff suppressed because it is too large Load Diff
+28 -17
View File
@@ -235,6 +235,11 @@ Enable SMPTE Level A mode on the used output.
Must be @samp{unset}, @samp{true} or @samp{false}. Must be @samp{unset}, @samp{true} or @samp{false}.
Defaults to @option{unset}. Defaults to @option{unset}.
@item vanc_queue_size
Sets maximum output buffer size in bytes for VANC data. If the buffering reaches this value,
outgoing VANC data will be dropped.
Defaults to @samp{1048576}.
@end table @end table
@subsection Examples @subsection Examples
@@ -297,7 +302,7 @@ ffmpeg -re -i INPUT -c:v rawvideo -pix_fmt bgra -f fbdev /dev/fb0
See also @url{http://linux-fbdev.sourceforge.net/}, and fbset(1). See also @url{http://linux-fbdev.sourceforge.net/}, and fbset(1).
@section opengl @section opengl
OpenGL output device. OpenGL output device. Deprecated and will be removed.
To enable this output device you need to configure FFmpeg with @code{--enable-opengl}. To enable this output device you need to configure FFmpeg with @code{--enable-opengl}.
@@ -403,7 +408,13 @@ ffmpeg -i INPUT -f pulse "stream name"
@section sdl @section sdl
SDL (Simple DirectMedia Layer) output device. SDL (Simple DirectMedia Layer) output device. Deprecated and will be removed.
For monitoring purposes in FFmpeg, pipes and a video player such as ffplay can be used:
@example
ffmpeg -i INPUT -f nut -c:v rawvideo - | ffplay -
@end example
"sdl2" can be used as alias for "sdl". "sdl2" can be used as alias for "sdl".
@@ -421,13 +432,18 @@ For more information about SDL, check:
@table @option @table @option
@item window_title @item window_borderless
Set the SDL window title, if not specified default to the filename Set SDL window border off.
specified for the output device. Default value is 0 (enable window border).
@item icon_title @item window_enable_quit
Set the name of the iconified SDL window, if not specified it is set Enable quit action (using window button or keyboard key)
to the same value of @var{window_title}. when non-zero value is provided.
Default value is 1 (enable quit action).
@item window_fullscreen
Set fullscreen mode when non-zero value is provided.
Default value is zero.
@item window_size @item window_size
Set the SDL window size, can be a string of the form Set the SDL window size, can be a string of the form
@@ -435,18 +451,13 @@ Set the SDL window size, can be a string of the form
If not specified it defaults to the size of the input video, If not specified it defaults to the size of the input video,
downscaled according to the aspect ratio. downscaled according to the aspect ratio.
@item window_title
Set the SDL window title, if not specified default to the filename
specified for the output device.
@item window_x @item window_x
@item window_y @item window_y
Set the position of the window on the screen. Set the position of the window on the screen.
@item window_fullscreen
Set fullscreen mode when non-zero value is provided.
Default value is zero.
@item window_enable_quit
Enable quit action (using window button or keyboard key)
when non-zero value is provided.
Default value is 1 (enable quit action)
@end table @end table
@subsection Interactive commands @subsection Interactive commands
-3
View File
@@ -92,9 +92,6 @@ For information about compiling FFmpeg on OS/2 see
@chapter Windows @chapter Windows
To get help and instructions for building FFmpeg under Windows, check out
the FFmpeg Windows Help Forum at @url{http://ffmpeg.zeranoe.com/forum/}.
@section Native Windows compilation using MinGW or MinGW-w64 @section Native Windows compilation using MinGW or MinGW-w64
FFmpeg can be built to run natively on Windows using the MinGW-w64 FFmpeg can be built to run natively on Windows using the MinGW-w64
+13
View File
@@ -896,6 +896,13 @@ be named, by prefixing the type with 'N' and specifying the name before
the value (i.e. @code{NB:myFlag:1}). This option may be used multiple the value (i.e. @code{NB:myFlag:1}). This option may be used multiple
times to construct arbitrary AMF sequences. times to construct arbitrary AMF sequences.
@item rtmp_enhanced_codecs
Specify the list of codecs the client advertises to support in an
enhanced RTMP stream. This option should be set to a comma separated
list of fourcc values, like @code{hvc1,av01,vp09} for multiple codecs
or @code{hvc1} for only one codec. The specified list will be presented
in the "fourCcLive" property of the Connect Command Message.
@item rtmp_flashver @item rtmp_flashver
Version of the Flash plugin used to run the SWF player. The default Version of the Flash plugin used to run the SWF player. The default
is LNX 9,0,124,2. (When publishing, the default is FMLE/3.0 (compatible; is LNX 9,0,124,2. (When publishing, the default is FMLE/3.0 (compatible;
@@ -1882,6 +1889,12 @@ The list of supported options follows.
Listen for an incoming connection. 0 disables listen, 1 enables listen in 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. single client mode, 2 enables listen in multi-client mode. Default value is 0.
@item local_addr=@var{addr}
Local IP address of a network interface used for tcp socket connect.
@item local_port=@var{port}
Local port used for tcp socket connect.
@item timeout=@var{microseconds} @item timeout=@var{microseconds}
Set raise error timeout, expressed in microseconds. Set raise error timeout, expressed in microseconds.
+23 -5
View File
@@ -695,6 +695,8 @@ FL+FR+FC+LFE+SL+SR
FL+FR+FC+BC+SL+SR FL+FR+FC+BC+SL+SR
@item 6.0(front) @item 6.0(front)
FL+FR+FLC+FRC+SL+SR FL+FR+FLC+FRC+SL+SR
@item 3.1.2
FL+FR+FC+LFE+TFL+TFR
@item hexagonal @item hexagonal
FL+FR+FC+BL+BR+BC FL+FR+FC+BL+BR+BC
@item 6.1 @item 6.1
@@ -713,12 +715,22 @@ FL+FR+FC+LFE+BL+BR+SL+SR
FL+FR+FC+LFE+BL+BR+FLC+FRC FL+FR+FC+LFE+BL+BR+FLC+FRC
@item 7.1(wide-side) @item 7.1(wide-side)
FL+FR+FC+LFE+FLC+FRC+SL+SR FL+FR+FC+LFE+FLC+FRC+SL+SR
@item 7.1(top) @item 5.1.2
FL+FR+FC+LFE+BL+BR+TFL+TFR FL+FR+FC+LFE+BL+BR+TFL+TFR
@item octagonal @item octagonal
FL+FR+FC+BL+BR+BC+SL+SR FL+FR+FC+BL+BR+BC+SL+SR
@item cube @item cube
FL+FR+BL+BR+TFL+TFR+TBL+TBR FL+FR+BL+BR+TFL+TFR+TBL+TBR
@item 5.1.4
FL+FR+FC+LFE+BL+BR+TFL+TFR+TBL+TBR
@item 7.1.2
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR
@item 7.1.4
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR+TBL+TBR
@item 7.2.3
FL+FR+FC+LFE+BL+BR+SL+SR+TFL+TFR+TBC+LFE2
@item 9.1.4
FL+FR+FC+LFE+BL+BR+FLC+FRC+SL+SR+TFL+TFR+TBL+TBR
@item hexadecagonal @item hexadecagonal
FL+FR+FC+BL+BR+BC+SL+SR+WL+WR+TBL+TBR+TBC+TFC+TFL+TFR FL+FR+FC+BL+BR+BC+SL+SR+WL+WR+TBL+TBR+TBC+TFC+TFL+TFR
@item downmix @item downmix
@@ -803,7 +815,7 @@ Compute arcsine of @var{x}.
@item atan(x) @item atan(x)
Compute arctangent of @var{x}. Compute arctangent of @var{x}.
@item atan2(x, y) @item atan2(y, x)
Compute principal value of the arc tangent of @var{y}/@var{x}. Compute principal value of the arc tangent of @var{y}/@var{x}.
@item between(x, min, max) @item between(x, min, max)
@@ -927,9 +939,15 @@ Returns the value of the expression printed.
Prints t with loglevel l Prints t with loglevel l
@item random(x) @item random(idx)
Return a pseudo random value between 0.0 and 1.0. @var{x} is the index of the Return a pseudo random value between 0.0 and 1.0. @var{idx} is the
internal variable which will be used to save the seed/state. index of the internal variable which will be used to save the
seed/state.
@item randomi(idx, min, max)
Return a pseudo random value in the interval between @var{min} and
@var{max}. @var{idx} is the index of the internal variable which will
be used to save the seed/state.
@item root(expr, max) @item root(expr, max)
Find an input value for which the function represented by @var{expr} Find an input value for which the function represented by @var{expr}
+1
View File
@@ -15,6 +15,7 @@ OBJS-$(HAVE_LASX) += $(LASX-OBJS) $(LASX-OBJS-yes)
OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes) OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes)
OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes) OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes)
OBJS-$(HAVE_RV) += $(RV-OBJS) $(RV-OBJS-yes)
OBJS-$(HAVE_RVV) += $(RVV-OBJS) $(RVV-OBJS-yes) OBJS-$(HAVE_RVV) += $(RVV-OBJS) $(RVV-OBJS-yes)
OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes) OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes)
+2 -2
View File
@@ -130,7 +130,7 @@ $(BIN2CEXE): ffbuild/bin2c_host.o
ifdef CONFIG_PTX_COMPRESSION ifdef CONFIG_PTX_COMPRESSION
%.ptx.gz: TAG = GZIP %.ptx.gz: TAG = GZIP
%.ptx.gz: %.ptx %.ptx.gz: %.ptx
$(M)gzip -c9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@ $(M)gzip -nc9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
%.ptx.c: %.ptx.gz $(BIN2CEXE) %.ptx.c: %.ptx.gz $(BIN2CEXE)
$(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@))) $(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
@@ -140,7 +140,7 @@ else
endif endif
clean:: clean::
$(RM) $(BIN2CEXE) $(RM) $(BIN2CEXE) $(CLEANSUFFIXES:%=ffbuild/%)
%.c %.h %.pc %.ver %.version: TAG = GEN %.c %.h %.pc %.ver %.version: TAG = GEN
+5
View File
@@ -10,16 +10,21 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
OBJS-ffmpeg += \ OBJS-ffmpeg += \
fftools/ffmpeg_dec.o \
fftools/ffmpeg_demux.o \ fftools/ffmpeg_demux.o \
fftools/ffmpeg_enc.o \
fftools/ffmpeg_filter.o \ fftools/ffmpeg_filter.o \
fftools/ffmpeg_hw.o \ fftools/ffmpeg_hw.o \
fftools/ffmpeg_mux.o \ fftools/ffmpeg_mux.o \
fftools/ffmpeg_mux_init.o \ fftools/ffmpeg_mux_init.o \
fftools/ffmpeg_opt.o \ fftools/ffmpeg_opt.o \
fftools/ffmpeg_sched.o \
fftools/objpool.o \ fftools/objpool.o \
fftools/sync_queue.o \ fftools/sync_queue.o \
fftools/thread_queue.o \ fftools/thread_queue.o \
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes) OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
ifdef HAVE_GNU_WINDRES ifdef HAVE_GNU_WINDRES
+298 -155
View File
@@ -37,6 +37,7 @@
#include "libswresample/swresample.h" #include "libswresample/swresample.h"
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h" #include "libavutil/channel_layout.h"
#include "libavutil/display.h" #include "libavutil/display.h"
#include "libavutil/getenv_utf8.h" #include "libavutil/getenv_utf8.h"
@@ -83,29 +84,8 @@ void init_dynload(void)
#endif #endif
} }
static void (*program_exit)(int ret); int parse_number(const char *context, const char *numstr, enum OptionType type,
double min, double max, double *dst)
void register_exit(void (*cb)(int ret))
{
program_exit = cb;
}
void report_and_exit(int ret)
{
av_log(NULL, AV_LOG_FATAL, "%s\n", av_err2str(ret));
exit_program(AVUNERROR(ret));
}
void exit_program(int ret)
{
if (program_exit)
program_exit(ret);
exit(ret);
}
double parse_number_or_die(const char *context, const char *numstr, int type,
double min, double max)
{ {
char *tail; char *tail;
const char *error; const char *error;
@@ -114,31 +94,21 @@ double parse_number_or_die(const char *context, const char *numstr, int type,
error = "Expected number for %s but found: %s\n"; error = "Expected number for %s but found: %s\n";
else if (d < min || d > max) else if (d < min || d > max)
error = "The value for %s was %s which is not within %f - %f\n"; error = "The value for %s was %s which is not within %f - %f\n";
else if (type == OPT_INT64 && (int64_t)d != d) else if (type == OPT_TYPE_INT64 && (int64_t)d != d)
error = "Expected int64 for %s but found %s\n"; error = "Expected int64 for %s but found %s\n";
else if (type == OPT_INT && (int)d != d) else if (type == OPT_TYPE_INT && (int)d != d)
error = "Expected int for %s but found %s\n"; error = "Expected int for %s but found %s\n";
else else {
return d; *dst = d;
av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); return 0;
exit_program(1);
return 0;
}
int64_t parse_time_or_die(const char *context, const char *timestr,
int is_duration)
{
int64_t us;
if (av_parse_time(&us, timestr, is_duration) < 0) {
av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n",
is_duration ? "duration" : "date", context, timestr);
exit_program(1);
} }
return us;
av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
return AVERROR(EINVAL);
} }
void show_help_options(const OptionDef *options, const char *msg, int req_flags, void show_help_options(const OptionDef *options, const char *msg, int req_flags,
int rej_flags, int alt_flags) int rej_flags)
{ {
const OptionDef *po; const OptionDef *po;
int first; int first;
@@ -148,7 +118,6 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
char buf[128]; char buf[128];
if (((po->flags & req_flags) != req_flags) || if (((po->flags & req_flags) != req_flags) ||
(alt_flags && !(po->flags & alt_flags)) ||
(po->flags & rej_flags)) (po->flags & rej_flags))
continue; continue;
@@ -157,10 +126,15 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
first = 0; first = 0;
} }
av_strlcpy(buf, po->name, sizeof(buf)); av_strlcpy(buf, po->name, sizeof(buf));
if (po->argname) {
av_strlcat(buf, " ", sizeof(buf)); if (po->flags & OPT_FLAG_PERSTREAM)
av_strlcat(buf, po->argname, sizeof(buf)); av_strlcat(buf, "[:<stream_spec>]", sizeof(buf));
} else if (po->flags & OPT_FLAG_SPEC)
av_strlcat(buf, "[:<spec>]", sizeof(buf));
if (po->argname)
av_strlcatf(buf, sizeof(buf), " <%s>", po->argname);
printf("-%-17s %s\n", buf, po->help); printf("-%-17s %s\n", buf, po->help);
} }
printf("\n"); printf("\n");
@@ -181,6 +155,9 @@ void show_help_children(const AVClass *class, int flags)
static const OptionDef *find_option(const OptionDef *po, const char *name) static const OptionDef *find_option(const OptionDef *po, const char *name)
{ {
if (*name == '/')
name++;
while (po->name) { while (po->name) {
const char *end; const char *end;
if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) if (av_strstart(name, po->name, &end) && (!*end || *end == ':'))
@@ -254,59 +231,138 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
} }
#endif /* HAVE_COMMANDLINETOARGVW */ #endif /* HAVE_COMMANDLINETOARGVW */
static int opt_has_arg(const OptionDef *o)
{
if (o->type == OPT_TYPE_BOOL)
return 0;
if (o->type == OPT_TYPE_FUNC)
return !!(o->flags & OPT_FUNC_ARG);
return 1;
}
static int write_option(void *optctx, const OptionDef *po, const char *opt, static int write_option(void *optctx, const OptionDef *po, const char *opt,
const char *arg) const char *arg, const OptionDef *defs)
{ {
/* new-style options contain an offset into optctx, old-style address of /* new-style options contain an offset into optctx, old-style address of
* a global var*/ * a global var*/
void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? void *dst = po->flags & OPT_FLAG_OFFSET ?
(uint8_t *)optctx + po->u.off : po->u.dst_ptr; (uint8_t *)optctx + po->u.off : po->u.dst_ptr;
int *dstcount; char *arg_allocated = NULL;
if (po->flags & OPT_SPEC) { SpecifierOptList *sol = NULL;
SpecifierOpt **so = dst; double num;
int ret = 0;
if (*opt == '/') {
opt++;
if (po->type == OPT_TYPE_BOOL) {
av_log(NULL, AV_LOG_FATAL,
"Requested to load an argument from file for a bool option '%s'\n",
po->name);
return AVERROR(EINVAL);
}
arg_allocated = file_read(arg);
if (!arg_allocated) {
av_log(NULL, AV_LOG_FATAL,
"Error reading the value for option '%s' from file: %s\n",
opt, arg);
return AVERROR(EINVAL);
}
arg = arg_allocated;
}
if (po->flags & OPT_FLAG_SPEC) {
char *p = strchr(opt, ':'); char *p = strchr(opt, ':');
char *str; char *str;
dstcount = (int *)(so + 1); sol = dst;
*so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1); ret = GROW_ARRAY(sol->opt, sol->nb_opt);
if (ret < 0)
goto finish;
str = av_strdup(p ? p + 1 : ""); str = av_strdup(p ? p + 1 : "");
if (!str) if (!str) {
return AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
(*so)[*dstcount - 1].specifier = str; goto finish;
dst = &(*so)[*dstcount - 1].u; }
sol->opt[sol->nb_opt - 1].specifier = str;
dst = &sol->opt[sol->nb_opt - 1].u;
} }
if (po->flags & OPT_STRING) { if (po->type == OPT_TYPE_STRING) {
char *str; char *str;
str = av_strdup(arg); if (arg_allocated) {
str = arg_allocated;
arg_allocated = NULL;
} else
str = av_strdup(arg);
av_freep(dst); av_freep(dst);
if (!str)
return AVERROR(ENOMEM); if (!str) {
ret = AVERROR(ENOMEM);
goto finish;
}
*(char **)dst = str; *(char **)dst = str;
} else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { } else if (po->type == OPT_TYPE_BOOL || po->type == OPT_TYPE_INT) {
*(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); ret = parse_number(opt, arg, OPT_TYPE_INT64, INT_MIN, INT_MAX, &num);
} else if (po->flags & OPT_INT64) { if (ret < 0)
*(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); goto finish;
} else if (po->flags & OPT_TIME) {
*(int64_t *)dst = parse_time_or_die(opt, arg, 1); *(int *)dst = num;
} else if (po->flags & OPT_FLOAT) { } else if (po->type == OPT_TYPE_INT64) {
*(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY); ret = parse_number(opt, arg, OPT_TYPE_INT64, INT64_MIN, INT64_MAX, &num);
} else if (po->flags & OPT_DOUBLE) { if (ret < 0)
*(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); goto finish;
} else if (po->u.func_arg) {
int ret = po->u.func_arg(optctx, opt, arg); *(int64_t *)dst = num;
} else if (po->type == OPT_TYPE_TIME) {
ret = av_parse_time(dst, arg, 1);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Invalid duration for option %s: %s\n",
opt, arg);
goto finish;
}
} else if (po->type == OPT_TYPE_FLOAT) {
ret = parse_number(opt, arg, OPT_TYPE_FLOAT, -INFINITY, INFINITY, &num);
if (ret < 0)
goto finish;
*(float *)dst = num;
} else if (po->type == OPT_TYPE_DOUBLE) {
ret = parse_number(opt, arg, OPT_TYPE_DOUBLE, -INFINITY, INFINITY, &num);
if (ret < 0)
goto finish;
*(double *)dst = num;
} else {
av_assert0(po->type == OPT_TYPE_FUNC && po->u.func_arg);
ret = po->u.func_arg(optctx, opt, arg);
if (ret < 0) { if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, av_log(NULL, AV_LOG_ERROR,
"Failed to set value '%s' for option '%s': %s\n", "Failed to set value '%s' for option '%s': %s\n",
arg, opt, av_err2str(ret)); arg, opt, av_err2str(ret));
return ret; goto finish;
} }
} }
if (po->flags & OPT_EXIT) if (po->flags & OPT_EXIT) {
exit_program(0); ret = AVERROR_EXIT;
goto finish;
}
return 0; if (sol) {
sol->type = po->type;
sol->opt_canon = (po->flags & OPT_HAS_CANON) ?
find_option(defs, po->u1.name_canon) : po;
}
finish:
av_freep(&arg_allocated);
return ret;
} }
int parse_option(void *optctx, const char *opt, const char *arg, int parse_option(void *optctx, const char *opt, const char *arg,
@@ -314,7 +370,8 @@ int parse_option(void *optctx, const char *opt, const char *arg,
{ {
static const OptionDef opt_avoptions = { static const OptionDef opt_avoptions = {
.name = "AVOption passthrough", .name = "AVOption passthrough",
.flags = HAS_ARG, .type = OPT_TYPE_FUNC,
.flags = OPT_FUNC_ARG,
.u.func_arg = opt_default, .u.func_arg = opt_default,
}; };
@@ -325,9 +382,9 @@ int parse_option(void *optctx, const char *opt, const char *arg,
if (!po->name && opt[0] == 'n' && opt[1] == 'o') { if (!po->name && opt[0] == 'n' && opt[1] == 'o') {
/* handle 'no' bool option */ /* handle 'no' bool option */
po = find_option(options, opt + 2); po = find_option(options, opt + 2);
if ((po->name && (po->flags & OPT_BOOL))) if ((po->name && po->type == OPT_TYPE_BOOL))
arg = "0"; arg = "0";
} else if (po->flags & OPT_BOOL) } else if (po->type == OPT_TYPE_BOOL)
arg = "1"; arg = "1";
if (!po->name) if (!po->name)
@@ -336,20 +393,20 @@ int parse_option(void *optctx, const char *opt, const char *arg,
av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt);
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (po->flags & HAS_ARG && !arg) { if (opt_has_arg(po) && !arg) {
av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt);
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
ret = write_option(optctx, po, opt, arg); ret = write_option(optctx, po, opt, arg, options);
if (ret < 0) if (ret < 0)
return ret; return ret;
return !!(po->flags & HAS_ARG); return opt_has_arg(po);
} }
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
void (*parse_arg_function)(void *, const char*)) int (*parse_arg_function)(void *, const char*))
{ {
const char *opt; const char *opt;
int optindex, handleoptions = 1, ret; int optindex, handleoptions = 1, ret;
@@ -370,16 +427,21 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options
opt++; opt++;
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
exit_program(1); return ret;
optindex += ret; optindex += ret;
} else { } else {
if (parse_arg_function) if (parse_arg_function) {
parse_arg_function(optctx, opt); ret = parse_arg_function(optctx, opt);
if (ret < 0)
return ret;
}
} }
} }
return 0;
} }
int parse_optgroup(void *optctx, OptionGroup *g) int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs)
{ {
int i, ret; int i, ret;
@@ -402,7 +464,7 @@ int parse_optgroup(void *optctx, OptionGroup *g)
av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n",
o->key, o->opt->help, o->val); o->key, o->opt->help, o->val);
ret = write_option(optctx, o->opt, o->key, o->val); ret = write_option(optctx, o->opt, o->key, o->val, defs);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@@ -432,7 +494,7 @@ int locate_option(int argc, char **argv, const OptionDef *options,
(po->name && !strcmp(optname, po->name))) (po->name && !strcmp(optname, po->name)))
return i; return i;
if (!po->name || po->flags & HAS_ARG) if (!po->name || opt_has_arg(po))
i++; i++;
} }
return 0; return 0;
@@ -466,7 +528,14 @@ static void check_options(const OptionDef *po)
{ {
while (po->name) { while (po->name) {
if (po->flags & OPT_PERFILE) if (po->flags & OPT_PERFILE)
av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT)); av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT | OPT_DECODER));
if (po->type == OPT_TYPE_FUNC)
av_assert0(!(po->flags & (OPT_FLAG_OFFSET | OPT_FLAG_SPEC)));
// OPT_FUNC_ARG can only be ser for OPT_TYPE_FUNC
av_assert0((po->type == OPT_TYPE_FUNC) || !(po->flags & OPT_FUNC_ARG));
po++; po++;
} }
} }
@@ -512,7 +581,7 @@ static const AVOption *opt_find(void *obj, const char *name, const char *unit,
return o; return o;
} }
#define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0 #define FLAGS ((o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0)
int opt_default(void *optctx, const char *opt, const char *arg) int opt_default(void *optctx, const char *opt, const char *arg)
{ {
const AVOption *o; const AVOption *o;
@@ -605,13 +674,17 @@ static int match_group_separator(const OptionGroupDef *groups, int nb_groups,
* @param group_idx which group definition should this group belong to * @param group_idx which group definition should this group belong to
* @param arg argument of the group delimiting option * @param arg argument of the group delimiting option
*/ */
static void finish_group(OptionParseContext *octx, int group_idx, static int finish_group(OptionParseContext *octx, int group_idx,
const char *arg) const char *arg)
{ {
OptionGroupList *l = &octx->groups[group_idx]; OptionGroupList *l = &octx->groups[group_idx];
OptionGroup *g; OptionGroup *g;
int ret;
ret = GROW_ARRAY(l->groups, l->nb_groups);
if (ret < 0)
return ret;
GROW_ARRAY(l->groups, l->nb_groups);
g = &l->groups[l->nb_groups - 1]; g = &l->groups[l->nb_groups - 1];
*g = octx->cur_group; *g = octx->cur_group;
@@ -628,41 +701,51 @@ static void finish_group(OptionParseContext *octx, int group_idx,
swr_opts = NULL; swr_opts = NULL;
memset(&octx->cur_group, 0, sizeof(octx->cur_group)); memset(&octx->cur_group, 0, sizeof(octx->cur_group));
return ret;
} }
/* /*
* Add an option instance to currently parsed group. * Add an option instance to currently parsed group.
*/ */
static void add_opt(OptionParseContext *octx, const OptionDef *opt, static int add_opt(OptionParseContext *octx, const OptionDef *opt,
const char *key, const char *val) const char *key, const char *val)
{ {
int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); int global = !(opt->flags & OPT_PERFILE);
OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; OptionGroup *g = global ? &octx->global_opts : &octx->cur_group;
int ret;
ret = GROW_ARRAY(g->opts, g->nb_opts);
if (ret < 0)
return ret;
GROW_ARRAY(g->opts, g->nb_opts);
g->opts[g->nb_opts - 1].opt = opt; g->opts[g->nb_opts - 1].opt = opt;
g->opts[g->nb_opts - 1].key = key; g->opts[g->nb_opts - 1].key = key;
g->opts[g->nb_opts - 1].val = val; g->opts[g->nb_opts - 1].val = val;
return 0;
} }
static void init_parse_context(OptionParseContext *octx, static int init_parse_context(OptionParseContext *octx,
const OptionGroupDef *groups, int nb_groups) const OptionGroupDef *groups, int nb_groups)
{ {
static const OptionGroupDef global_group = { "global" }; static const OptionGroupDef global_group = { "global" };
int i; int i;
memset(octx, 0, sizeof(*octx)); memset(octx, 0, sizeof(*octx));
octx->nb_groups = nb_groups; octx->groups = av_calloc(nb_groups, sizeof(*octx->groups));
octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups));
if (!octx->groups) if (!octx->groups)
report_and_exit(AVERROR(ENOMEM)); return AVERROR(ENOMEM);
octx->nb_groups = nb_groups;
for (i = 0; i < octx->nb_groups; i++) for (i = 0; i < octx->nb_groups; i++)
octx->groups[i].group_def = &groups[i]; octx->groups[i].group_def = &groups[i];
octx->global_opts.group_def = &global_group; octx->global_opts.group_def = &global_group;
octx->global_opts.arg = ""; octx->global_opts.arg = "";
return 0;
} }
void uninit_parse_context(OptionParseContext *octx) void uninit_parse_context(OptionParseContext *octx)
@@ -694,19 +777,23 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[],
const OptionDef *options, const OptionDef *options,
const OptionGroupDef *groups, int nb_groups) const OptionGroupDef *groups, int nb_groups)
{ {
int ret;
int optindex = 1; int optindex = 1;
int dashdash = -2; int dashdash = -2;
/* perform system-dependent conversions for arguments list */ /* perform system-dependent conversions for arguments list */
prepare_app_arguments(&argc, &argv); prepare_app_arguments(&argc, &argv);
init_parse_context(octx, groups, nb_groups); ret = init_parse_context(octx, groups, nb_groups);
if (ret < 0)
return ret;
av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");
while (optindex < argc) { while (optindex < argc) {
const char *opt = argv[optindex++], *arg; const char *opt = argv[optindex++], *arg;
const OptionDef *po; const OptionDef *po;
int ret; int ret, group_idx;
av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt);
@@ -716,7 +803,10 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[],
} }
/* unnamed group separators, e.g. output filename */ /* unnamed group separators, e.g. output filename */
if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) { if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) {
finish_group(octx, 0, opt); ret = finish_group(octx, 0, opt);
if (ret < 0)
return ret;
av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name);
continue; continue;
} }
@@ -732,11 +822,15 @@ do { \
} while (0) } while (0)
/* named group separators, e.g. -i */ /* named group separators, e.g. -i */
if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { group_idx = match_group_separator(groups, nb_groups, opt);
if (group_idx >= 0) {
GET_ARG(arg); GET_ARG(arg);
finish_group(octx, ret, arg); ret = finish_group(octx, group_idx, arg);
if (ret < 0)
return ret;
av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
groups[ret].name, arg); groups[group_idx].name, arg);
continue; continue;
} }
@@ -746,13 +840,16 @@ do { \
if (po->flags & OPT_EXIT) { if (po->flags & OPT_EXIT) {
/* optional argument, e.g. -h */ /* optional argument, e.g. -h */
arg = argv[optindex++]; arg = argv[optindex++];
} else if (po->flags & HAS_ARG) { } else if (opt_has_arg(po)) {
GET_ARG(arg); GET_ARG(arg);
} else { } else {
arg = "1"; arg = "1";
} }
add_opt(octx, po, opt, arg); ret = add_opt(octx, po, opt, arg);
if (ret < 0)
return ret;
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
"argument '%s'.\n", po->name, po->help, arg); "argument '%s'.\n", po->name, po->help, arg);
continue; continue;
@@ -776,8 +873,11 @@ do { \
/* boolean -nofoo options */ /* boolean -nofoo options */
if (opt[0] == 'n' && opt[1] == 'o' && if (opt[0] == 'n' && opt[1] == 'o' &&
(po = find_option(options, opt + 2)) && (po = find_option(options, opt + 2)) &&
po->name && po->flags & OPT_BOOL) { po->name && po->type == OPT_TYPE_BOOL) {
add_opt(octx, po, opt, "0"); ret = add_opt(octx, po, opt, "0");
if (ret < 0)
return ret;
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
"argument 0.\n", po->name, po->help); "argument 0.\n", po->name, po->help);
continue; continue;
@@ -796,11 +896,6 @@ do { \
return 0; return 0;
} }
void print_error(const char *filename, int err)
{
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err));
}
int read_yesno(void) int read_yesno(void)
{ {
int c = getchar(); int c = getchar();
@@ -892,8 +987,9 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
return ret; return ret;
} }
AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
AVFormatContext *s, AVStream *st, const AVCodec *codec) AVFormatContext *s, AVStream *st, const AVCodec *codec,
AVDictionary **dst)
{ {
AVDictionary *ret = NULL; AVDictionary *ret = NULL;
const AVDictionaryEntry *t = NULL; const AVDictionaryEntry *t = NULL;
@@ -926,12 +1022,16 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
char *p = strchr(t->key, ':'); char *p = strchr(t->key, ':');
/* check stream specification in opt name */ /* check stream specification in opt name */
if (p) if (p) {
switch (check_stream_specifier(s, st, p + 1)) { int err = check_stream_specifier(s, st, p + 1);
case 1: *p = 0; break; if (err < 0) {
case 0: continue; av_dict_free(&ret);
default: exit_program(1); return err;
} } else if (!err)
continue;
*p = 0;
}
if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
!codec || !codec ||
@@ -947,41 +1047,58 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
if (p) if (p)
*p = ':'; *p = ':';
} }
*dst = ret;
return 0;
}
int setup_find_stream_info_opts(AVFormatContext *s,
AVDictionary *codec_opts,
AVDictionary ***dst)
{
int ret;
AVDictionary **opts;
*dst = NULL;
if (!s->nb_streams)
return 0;
opts = av_calloc(s->nb_streams, sizeof(*opts));
if (!opts)
return AVERROR(ENOMEM);
for (int i = 0; i < s->nb_streams; i++) {
ret = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
s, s->streams[i], NULL, &opts[i]);
if (ret < 0)
goto fail;
}
*dst = opts;
return 0;
fail:
for (int i = 0; i < s->nb_streams; i++)
av_dict_free(&opts[i]);
av_freep(&opts);
return ret; return ret;
} }
AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, int grow_array(void **array, int elem_size, int *size, int new_size)
AVDictionary *codec_opts)
{
int i;
AVDictionary **opts;
if (!s->nb_streams)
return NULL;
opts = av_calloc(s->nb_streams, sizeof(*opts));
if (!opts)
report_and_exit(AVERROR(ENOMEM));
for (i = 0; i < s->nb_streams; i++)
opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
s, s->streams[i], NULL);
return opts;
}
void *grow_array(void *array, int elem_size, int *size, int new_size)
{ {
if (new_size >= INT_MAX / elem_size) { if (new_size >= INT_MAX / elem_size) {
av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
exit_program(1); return AVERROR(ERANGE);
} }
if (*size < new_size) { if (*size < new_size) {
uint8_t *tmp = av_realloc_array(array, new_size, elem_size); uint8_t *tmp = av_realloc_array(*array, new_size, elem_size);
if (!tmp) if (!tmp)
report_and_exit(AVERROR(ENOMEM)); return AVERROR(ENOMEM);
memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
*size = new_size; *size = new_size;
return tmp; *array = tmp;
return 0;
} }
return array; return 0;
} }
void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems)
@@ -990,15 +1107,15 @@ void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems)
if (!(new_elem = av_mallocz(elem_size)) || if (!(new_elem = av_mallocz(elem_size)) ||
av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0)
report_and_exit(AVERROR(ENOMEM)); return NULL;
return new_elem; return new_elem;
} }
double get_rotation(int32_t *displaymatrix) double get_rotation(const int32_t *displaymatrix)
{ {
double theta = 0; double theta = 0;
if (displaymatrix) if (displaymatrix)
theta = -round(av_display_rotation_get((int32_t*) displaymatrix)); theta = -round(av_display_rotation_get(displaymatrix));
theta -= 360*floor(theta/360 + 0.9/360); theta -= 360*floor(theta/360 + 0.9/360);
@@ -1010,3 +1127,29 @@ double get_rotation(int32_t *displaymatrix)
return theta; return theta;
} }
/* read file contents into a string */
char *file_read(const char *filename)
{
AVIOContext *pb = NULL;
int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
AVBPrint bprint;
char *str;
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
return NULL;
}
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX);
avio_closep(&pb);
if (ret < 0) {
av_bprint_finalize(&bprint, NULL);
return NULL;
}
ret = av_bprint_finalize(&bprint, &str);
if (ret < 0)
return NULL;
return str;
}
+109 -89
View File
@@ -49,27 +49,6 @@ extern AVDictionary *swr_opts;
extern AVDictionary *format_opts, *codec_opts; extern AVDictionary *format_opts, *codec_opts;
extern int hide_banner; extern int hide_banner;
/**
* Register a program-specific cleanup routine.
*/
void register_exit(void (*cb)(int ret));
/**
* Reports an error corresponding to the provided
* AVERROR code and calls exit_program() with the
* corresponding POSIX error code.
* @note ret must be an AVERROR-value of a POSIX error code
* (i.e. AVERROR(EFOO) and not AVERROR_FOO).
* library functions can return both, so call this only
* with AVERROR(EFOO) of your own.
*/
void report_and_exit(int ret) av_noreturn;
/**
* Wraps exit with a program-specific cleanup routine.
*/
void exit_program(int ret) av_noreturn;
/** /**
* Initialize dynamic library loading * Initialize dynamic library loading
*/ */
@@ -98,10 +77,19 @@ int opt_default(void *optctx, const char *opt, const char *arg);
*/ */
int opt_timelimit(void *optctx, const char *opt, const char *arg); int opt_timelimit(void *optctx, const char *opt, const char *arg);
enum OptionType {
OPT_TYPE_FUNC,
OPT_TYPE_BOOL,
OPT_TYPE_STRING,
OPT_TYPE_INT,
OPT_TYPE_INT64,
OPT_TYPE_FLOAT,
OPT_TYPE_DOUBLE,
OPT_TYPE_TIME,
};
/** /**
* Parse a string and return its corresponding value as a double. * Parse a string and return its corresponding value as a double.
* Exit from the application if the string cannot be correctly
* parsed or the corresponding value is invalid.
* *
* @param context the context of the value to be set (e.g. the * @param context the context of the value to be set (e.g. the
* corresponding command line option name) * corresponding command line option name)
@@ -111,25 +99,8 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg);
* @param min the minimum valid accepted value * @param min the minimum valid accepted value
* @param max the maximum valid accepted value * @param max the maximum valid accepted value
*/ */
double parse_number_or_die(const char *context, const char *numstr, int type, int parse_number(const char *context, const char *numstr, enum OptionType type,
double min, double max); double min, double max, double *dst);
/**
* Parse a string specifying a time and return its corresponding
* value as a number of microseconds. Exit from the application if
* the string cannot be correctly parsed.
*
* @param context the context of the value to be set (e.g. the
* corresponding command line option name)
* @param timestr the string to be parsed
* @param is_duration a flag which tells how to interpret timestr, if
* not zero timestr is interpreted as a duration, otherwise as a
* date
*
* @see av_parse_time()
*/
int64_t parse_time_or_die(const char *context, const char *timestr,
int is_duration);
typedef struct SpecifierOpt { typedef struct SpecifierOpt {
char *specifier; /**< stream/chapter/program/... specifier */ char *specifier; /**< stream/chapter/program/... specifier */
@@ -143,31 +114,70 @@ typedef struct SpecifierOpt {
} u; } u;
} SpecifierOpt; } SpecifierOpt;
typedef struct SpecifierOptList {
SpecifierOpt *opt;
int nb_opt;
/* Canonical option definition that was parsed into this list. */
const struct OptionDef *opt_canon;
enum OptionType type;
} SpecifierOptList;
typedef struct OptionDef { typedef struct OptionDef {
const char *name; const char *name;
enum OptionType type;
int flags; int flags;
#define HAS_ARG 0x0001
#define OPT_BOOL 0x0002 /* The OPT_TYPE_FUNC option takes an argument.
#define OPT_EXPERT 0x0004 * Must not be used with other option types, as for those it holds:
#define OPT_STRING 0x0008 * - OPT_TYPE_BOOL do not take an argument
#define OPT_VIDEO 0x0010 * - all other types do
#define OPT_AUDIO 0x0020 */
#define OPT_INT 0x0080 #define OPT_FUNC_ARG (1 << 0)
#define OPT_FLOAT 0x0100 /* Program will immediately exit after processing this option */
#define OPT_SUBTITLE 0x0200 #define OPT_EXIT (1 << 1)
#define OPT_INT64 0x0400 /* Option is intended for advanced users. Only affects
#define OPT_EXIT 0x0800 * help output.
#define OPT_DATA 0x1000 */
#define OPT_PERFILE 0x2000 /* the option is per-file (currently ffmpeg-only). #define OPT_EXPERT (1 << 2)
implied by OPT_OFFSET or OPT_SPEC */ #define OPT_VIDEO (1 << 3)
#define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */ #define OPT_AUDIO (1 << 4)
#define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt. #define OPT_SUBTITLE (1 << 5)
Implies OPT_OFFSET. Next element after the offset is #define OPT_DATA (1 << 6)
an int containing element count in the array. */ /* The option is per-file (currently ffmpeg-only). At least one of OPT_INPUT,
#define OPT_TIME 0x10000 * OPT_OUTPUT, OPT_DECODER must be set when this flag is in use.
#define OPT_DOUBLE 0x20000 */
#define OPT_INPUT 0x40000 #define OPT_PERFILE (1 << 7)
#define OPT_OUTPUT 0x80000
/* Option is specified as an offset in a passed optctx.
* Always use as OPT_OFFSET in option definitions. */
#define OPT_FLAG_OFFSET (1 << 8)
#define OPT_OFFSET (OPT_FLAG_OFFSET | OPT_PERFILE)
/* Option is to be stored in a SpecifierOptList.
Always use as OPT_SPEC in option definitions. */
#define OPT_FLAG_SPEC (1 << 9)
#define OPT_SPEC (OPT_FLAG_SPEC | OPT_OFFSET)
/* Option applies per-stream (implies OPT_SPEC). */
#define OPT_FLAG_PERSTREAM (1 << 10)
#define OPT_PERSTREAM (OPT_FLAG_PERSTREAM | OPT_SPEC)
/* ffmpeg-only - specifies whether an OPT_PERFILE option applies to input,
* output, or both. */
#define OPT_INPUT (1 << 11)
#define OPT_OUTPUT (1 << 12)
/* This option is a "canonical" form, to which one or more alternatives
* exist. These alternatives are listed in u1.names_alt. */
#define OPT_HAS_ALT (1 << 13)
/* This option is an alternative form of some other option, whose
* name is stored in u1.name_canon */
#define OPT_HAS_CANON (1 << 14)
/* ffmpeg-only - OPT_PERFILE may apply to standalone decoders */
#define OPT_DECODER (1 << 15)
union { union {
void *dst_ptr; void *dst_ptr;
int (*func_arg)(void *, const char *, const char *); int (*func_arg)(void *, const char *, const char *);
@@ -175,6 +185,15 @@ typedef struct OptionDef {
} u; } u;
const char *help; const char *help;
const char *argname; const char *argname;
union {
/* Name of the canonical form of this option.
* Is valid when OPT_HAS_CANON is set. */
const char *name_canon;
/* A NULL-terminated list of alternate forms of this option.
* Is valid when OPT_HAS_ALT is set. */
const char * const *names_alt;
} u1;
} OptionDef; } OptionDef;
/** /**
@@ -184,10 +203,9 @@ typedef struct OptionDef {
* @param msg title of this group. Only printed if at least one option matches. * @param msg title of this group. Only printed if at least one option matches.
* @param req_flags print only options which have all those flags set. * @param req_flags print only options which have all those flags set.
* @param rej_flags don't print options which have any of those flags set. * @param rej_flags don't print options which have any of those flags set.
* @param alt_flags print only options that have at least one of those flags set
*/ */
void show_help_options(const OptionDef *options, const char *msg, int req_flags, void show_help_options(const OptionDef *options, const char *msg, int req_flags,
int rej_flags, int alt_flags); int rej_flags);
/** /**
* Show help for all options with given flags in class and all its * Show help for all options with given flags in class and all its
@@ -213,8 +231,8 @@ void show_help_default(const char *opt, const char *arg);
* argument without a leading option name flag. NULL if such arguments do * argument without a leading option name flag. NULL if such arguments do
* not have to be processed. * not have to be processed.
*/ */
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(void *optctx, const char*)); int (* parse_arg_function)(void *optctx, const char*));
/** /**
* Parse one given option. * Parse one given option.
@@ -289,7 +307,7 @@ typedef struct OptionParseContext {
* *
* @param optctx an app-specific options context. NULL for global options group * @param optctx an app-specific options context. NULL for global options group
*/ */
int parse_optgroup(void *optctx, OptionGroup *g); int parse_optgroup(void *optctx, OptionGroup *g, const OptionDef *defs);
/** /**
* Split the commandline into an intermediate form convenient for further * Split the commandline into an intermediate form convenient for further
@@ -352,10 +370,12 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec);
* @param st A stream from s for which the options should be filtered. * @param st A stream from s for which the options should be filtered.
* @param codec The particular codec for which the options should be filtered. * @param codec The particular codec for which the options should be filtered.
* If null, the default one is looked up according to the codec id. * If null, the default one is looked up according to the codec id.
* @return a pointer to the created dictionary * @param dst a pointer to the created dictionary
* @return a non-negative number on success, a negative error code on failure
*/ */
AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
AVFormatContext *s, AVStream *st, const AVCodec *codec); AVFormatContext *s, AVStream *st, const AVCodec *codec,
AVDictionary **dst);
/** /**
* Setup AVCodecContext options for avformat_find_stream_info(). * Setup AVCodecContext options for avformat_find_stream_info().
@@ -364,12 +384,10 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
* contained in s. * contained in s.
* Each dictionary will contain the options from codec_opts which can * Each dictionary will contain the options from codec_opts which can
* be applied to the corresponding stream codec context. * be applied to the corresponding stream codec context.
*
* @return pointer to the created array of dictionaries.
* Calls exit() on failure.
*/ */
AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, int setup_find_stream_info_opts(AVFormatContext *s,
AVDictionary *codec_opts); AVDictionary *codec_opts,
AVDictionary ***dst);
/** /**
* Print an error message to stderr, indicating filename and a human * Print an error message to stderr, indicating filename and a human
@@ -380,7 +398,10 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
* *
* @see av_strerror() * @see av_strerror()
*/ */
void print_error(const char *filename, int err); static inline void print_error(const char *filename, int err)
{
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err));
}
/** /**
* Print the program banner to stderr. The banner contents depend on the * Print the program banner to stderr. The banner contents depend on the
@@ -418,35 +439,31 @@ FILE *get_preset_file(char *filename, size_t filename_size,
/** /**
* Realloc array to hold new_size elements of elem_size. * Realloc array to hold new_size elements of elem_size.
* Calls exit() on failure.
* *
* @param array array to reallocate * @param array pointer to the array to reallocate, will be updated
* with a new pointer on success
* @param elem_size size in bytes of each element * @param elem_size size in bytes of each element
* @param size new element count will be written here * @param size new element count will be written here
* @param new_size number of elements to place in reallocated array * @param new_size number of elements to place in reallocated array
* @return reallocated array * @return a non-negative number on success, a negative error code on failure
*/ */
void *grow_array(void *array, int elem_size, int *size, int new_size); int grow_array(void **array, int elem_size, int *size, int new_size);
/** /**
* Atomically add a new element to an array of pointers, i.e. allocate * Atomically add a new element to an array of pointers, i.e. allocate
* a new entry, reallocate the array of pointers and make the new last * a new entry, reallocate the array of pointers and make the new last
* member of this array point to the newly allocated buffer. * member of this array point to the newly allocated buffer.
* Calls exit() on failure.
* *
* @param array array of pointers to reallocate * @param array array of pointers to reallocate
* @param elem_size size of the new element to allocate * @param elem_size size of the new element to allocate
* @param nb_elems pointer to the number of elements of the array array; * @param nb_elems pointer to the number of elements of the array array;
* *nb_elems will be incremented by one by this function. * *nb_elems will be incremented by one by this function.
* @return pointer to the newly allocated entry * @return pointer to the newly allocated entry or NULL on failure
*/ */
void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
#define GROW_ARRAY(array, nb_elems)\ #define GROW_ARRAY(array, nb_elems)\
array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1)
#define ALLOC_ARRAY_ELEM(array, nb_elems)\
allocate_array_elem(&array, sizeof(*array[0]), &nb_elems)
#define GET_PIX_FMT_NAME(pix_fmt)\ #define GET_PIX_FMT_NAME(pix_fmt)\
const char *name = av_get_pix_fmt_name(pix_fmt); const char *name = av_get_pix_fmt_name(pix_fmt);
@@ -461,6 +478,9 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
char name[16];\ char name[16];\
snprintf(name, sizeof(name), "%d", rate); snprintf(name, sizeof(name), "%d", rate);
double get_rotation(int32_t *displaymatrix); double get_rotation(const int32_t *displaymatrix);
/* read file contents into a string */
char *file_read(const char *filename);
#endif /* FFTOOLS_CMDUTILS_H */ #endif /* FFTOOLS_CMDUTILS_H */
+238 -3437
View File
File diff suppressed because it is too large Load Diff
+397 -449
View File
File diff suppressed because it is too large Load Diff
+1361
View File
File diff suppressed because it is too large Load Diff
+1336 -609
View File
File diff suppressed because it is too large Load Diff
+966
View File
@@ -0,0 +1,966 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <math.h>
#include <stdint.h>
#include "ffmpeg.h"
#include "ffmpeg_utils.h"
#include "thread_queue.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/avutil.h"
#include "libavutil/dict.h"
#include "libavutil/display.h"
#include "libavutil/eval.h"
#include "libavutil/frame.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/pixdesc.h"
#include "libavutil/rational.h"
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
struct Encoder {
// combined size of all the packets received from the encoder
uint64_t data_size;
// number of packets received from the encoder
uint64_t packets_encoded;
int opened;
int attach_par;
Scheduler *sch;
unsigned sch_idx;
};
// data that is local to the decoder thread and not visible outside of it
typedef struct EncoderThread {
AVFrame *frame;
AVPacket *pkt;
} EncoderThread;
void enc_free(Encoder **penc)
{
Encoder *enc = *penc;
if (!enc)
return;
av_freep(penc);
}
int enc_alloc(Encoder **penc, const AVCodec *codec,
Scheduler *sch, unsigned sch_idx)
{
Encoder *enc;
*penc = NULL;
enc = av_mallocz(sizeof(*enc));
if (!enc)
return AVERROR(ENOMEM);
enc->sch = sch;
enc->sch_idx = sch_idx;
*penc = enc;
return 0;
}
static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref)
{
const AVCodecHWConfig *config;
HWDevice *dev = NULL;
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 (int i = 0;; i++) {
config = avcodec_get_hw_config(ost->enc_ctx->codec, 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_ctx->codec->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);
}
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_ctx->codec->name);
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
if (!ost->enc_ctx->hw_device_ctx)
return AVERROR(ENOMEM);
} else {
// No device required, or no device available.
}
return 0;
}
static int set_encoder_id(OutputFile *of, OutputStream *ost)
{
const char *cname = ost->enc_ctx->codec->name;
uint8_t *encoder_string;
int encoder_string_len;
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
return 0;
encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(cname) + 2;
encoder_string = av_mallocz(encoder_string_len);
if (!encoder_string)
return AVERROR(ENOMEM);
if (!of->bitexact && !ost->bitexact)
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
else
av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
av_strlcat(encoder_string, cname, encoder_string_len);
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
return 0;
}
int enc_open(void *opaque, const AVFrame *frame)
{
OutputStream *ost = opaque;
InputStream *ist = ost->ist;
Encoder *e = ost->enc;
AVCodecContext *enc_ctx = ost->enc_ctx;
Decoder *dec = NULL;
const AVCodec *enc = enc_ctx->codec;
OutputFile *of = ost->file;
FrameData *fd;
int frame_samples = 0;
int ret;
if (e->opened)
return 0;
// frame is always non-NULL for audio and video
av_assert0(frame || (enc->type != AVMEDIA_TYPE_VIDEO && enc->type != AVMEDIA_TYPE_AUDIO));
if (frame) {
av_assert0(frame->opaque_ref);
fd = (FrameData*)frame->opaque_ref->data;
}
ret = set_encoder_id(of, ost);
if (ret < 0)
return ret;
if (ist)
dec = ist->decoder;
// the timebase is chosen by filtering code
if (ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO) {
enc_ctx->time_base = frame->time_base;
enc_ctx->framerate = fd->frame_rate_filter;
ost->st->avg_frame_rate = fd->frame_rate_filter;
}
switch (enc_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
av_assert0(frame->format != AV_SAMPLE_FMT_NONE &&
frame->sample_rate > 0 &&
frame->ch_layout.nb_channels > 0);
enc_ctx->sample_fmt = frame->format;
enc_ctx->sample_rate = frame->sample_rate;
ret = av_channel_layout_copy(&enc_ctx->ch_layout, &frame->ch_layout);
if (ret < 0)
return ret;
if (ost->bits_per_raw_sample)
enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample;
else
enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample,
av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3);
break;
case AVMEDIA_TYPE_VIDEO: {
av_assert0(frame->format != AV_PIX_FMT_NONE &&
frame->width > 0 &&
frame->height > 0);
enc_ctx->width = frame->width;
enc_ctx->height = frame->height;
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option
av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) :
frame->sample_aspect_ratio;
enc_ctx->pix_fmt = frame->format;
if (ost->bits_per_raw_sample)
enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample;
else
enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample,
av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth);
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;
for (int i = 0; i < frame->nb_side_data; i++) {
ret = av_frame_side_data_clone(
&enc_ctx->decoded_side_data, &enc_ctx->nb_decoded_side_data,
frame->side_data[i], AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
if (ret < 0) {
av_frame_side_data_free(
&enc_ctx->decoded_side_data,
&enc_ctx->nb_decoded_side_data);
av_log(NULL, AV_LOG_ERROR,
"failed to configure video encoder: %s!\n",
av_err2str(ret));
return ret;
}
}
if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) ||
(frame->flags & AV_FRAME_FLAG_INTERLACED)
#if FFMPEG_OPT_TOP
|| ost->top_field_first >= 0
#endif
) {
int top_field_first =
#if FFMPEG_OPT_TOP
ost->top_field_first >= 0 ?
ost->top_field_first :
#endif
!!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST);
if (enc->id == AV_CODEC_ID_MJPEG)
enc_ctx->field_order = top_field_first ? AV_FIELD_TT : AV_FIELD_BB;
else
enc_ctx->field_order = top_field_first ? AV_FIELD_TB : AV_FIELD_BT;
} else
enc_ctx->field_order = AV_FIELD_PROGRESSIVE;
break;
}
case AVMEDIA_TYPE_SUBTITLE:
if (ost->enc_timebase.num)
av_log(ost, AV_LOG_WARNING,
"-enc_time_base not supported for subtitles, ignoring\n");
enc_ctx->time_base = AV_TIME_BASE_Q;
if (!enc_ctx->width) {
enc_ctx->width = ost->ist->par->width;
enc_ctx->height = ost->ist->par->height;
}
av_assert0(dec);
if (dec->subtitle_header) {
/* ASS code assumes this buffer is null terminated so add extra byte. */
enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1);
if (!enc_ctx->subtitle_header)
return AVERROR(ENOMEM);
memcpy(enc_ctx->subtitle_header, dec->subtitle_header,
dec->subtitle_header_size);
enc_ctx->subtitle_header_size = dec->subtitle_header_size;
}
break;
default:
av_assert0(0);
break;
}
if (ost->bitexact)
enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) {
ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
if (ret < 0)
return ret;
}
av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY);
ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR,
"Encoding hardware device setup failed: %s\n", av_err2str(ret));
return ret;
}
if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) {
if (ret != AVERROR_EXPERIMENTAL)
av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe "
"incorrect parameters such as bit_rate, rate, width or height.\n");
return ret;
}
e->opened = 1;
if (ost->enc_ctx->frame_size)
frame_samples = ost->enc_ctx->frame_size;
ret = check_avoptions(ost->encoder_opts);
if (ret < 0)
return ret;
if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 &&
ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low."
" It takes bits/s as argument, not kbits/s\n");
ret = avcodec_parameters_from_context(ost->par_in, ost->enc_ctx);
if (ret < 0) {
av_log(ost, AV_LOG_FATAL,
"Error initializing the output stream codec context.\n");
return ret;
}
/*
* Add global input side data. For now this is naive, and copies it
* from the input stream's global side data. All side data should
* really be funneled over AVFrame and libavfilter, then added back to
* packet side data, and then potentially using the first packet for
* global side data.
*/
if (ist) {
for (int i = 0; i < ist->st->codecpar->nb_coded_side_data; i++) {
AVPacketSideData *sd_src = &ist->st->codecpar->coded_side_data[i];
if (sd_src->type != AV_PKT_DATA_CPB_PROPERTIES) {
AVPacketSideData *sd_dst = av_packet_side_data_new(&ost->par_in->coded_side_data,
&ost->par_in->nb_coded_side_data,
sd_src->type, sd_src->size, 0);
if (!sd_dst)
return AVERROR(ENOMEM);
memcpy(sd_dst->data, sd_src->data, sd_src->size);
if (ist->autorotate && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX)
av_display_rotation_set((int32_t *)sd_dst->data, 0);
}
}
}
// copy timebase while removing common factors
if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0)
ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
ret = of_stream_init(of, ost);
if (ret < 0)
return ret;
return frame_samples;
}
static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb)
{
OutputFile *of = ost->file;
if (of->recording_time != INT64_MAX &&
av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) {
return 0;
}
return 1;
}
static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *sub,
AVPacket *pkt)
{
Encoder *e = ost->enc;
int subtitle_out_max_size = 1024 * 1024;
int subtitle_out_size, nb, i, ret;
AVCodecContext *enc;
int64_t pts;
if (sub->pts == AV_NOPTS_VALUE) {
av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
return exit_on_error ? AVERROR(EINVAL) : 0;
}
if ((of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
return 0;
enc = ost->enc_ctx;
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
nb = 2;
else if (enc->codec_id == AV_CODEC_ID_ASS)
nb = FFMAX(sub->num_rects, 1);
else
nb = 1;
/* shift timestamp to honor -ss and make check_recording_time() work with -t */
pts = sub->pts;
if (of->start_time != AV_NOPTS_VALUE)
pts -= of->start_time;
for (i = 0; i < nb; i++) {
AVSubtitle local_sub = *sub;
if (!check_recording_time(ost, pts, AV_TIME_BASE_Q))
return AVERROR_EOF;
ret = av_new_packet(pkt, subtitle_out_max_size);
if (ret < 0)
return AVERROR(ENOMEM);
local_sub.pts = pts;
// start_display_time is required to be 0
local_sub.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q);
local_sub.end_display_time -= sub->start_display_time;
local_sub.start_display_time = 0;
if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE && i == 1)
local_sub.num_rects = 0;
else if (enc->codec_id == AV_CODEC_ID_ASS && sub->num_rects > 0) {
local_sub.num_rects = 1;
local_sub.rects += i;
}
ost->frames_encoded++;
subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub);
if (subtitle_out_size < 0) {
av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n");
return subtitle_out_size;
}
av_shrink_packet(pkt, subtitle_out_size);
pkt->time_base = AV_TIME_BASE_Q;
pkt->pts = sub->pts;
pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base);
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 }, pkt->time_base);
else
pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, pkt->time_base);
}
pkt->dts = pkt->pts;
ret = sch_enc_send(e->sch, e->sch_idx, pkt);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
}
}
return 0;
}
void enc_stats_write(OutputStream *ost, EncStats *es,
const AVFrame *frame, const AVPacket *pkt,
uint64_t frame_num)
{
Encoder *e = ost->enc;
AVIOContext *io = es->io;
AVRational tb = frame ? frame->time_base : pkt->time_base;
int64_t pts = frame ? frame->pts : pkt->pts;
AVRational tbi = (AVRational){ 0, 1};
int64_t ptsi = INT64_MAX;
const FrameData *fd = NULL;
if (frame ? frame->opaque_ref : pkt->opaque_ref) {
fd = (const FrameData*)(frame ? frame->opaque_ref->data : pkt->opaque_ref->data);
tbi = fd->dec.tb;
ptsi = fd->dec.pts;
}
pthread_mutex_lock(&es->lock);
for (size_t i = 0; i < es->nb_components; i++) {
const EncStatsComponent *c = &es->components[i];
switch (c->type) {
case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue;
case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file->index); continue;
case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue;
case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue;
case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue;
case ENC_STATS_PTS: avio_printf(io, "%"PRId64, pts); continue;
case ENC_STATS_PTS_IN: avio_printf(io, "%"PRId64, ptsi); continue;
case ENC_STATS_PTS_TIME: avio_printf(io, "%g", pts * av_q2d(tb)); continue;
case ENC_STATS_PTS_TIME_IN: avio_printf(io, "%g", ptsi == INT64_MAX ?
INFINITY : ptsi * av_q2d(tbi)); continue;
case ENC_STATS_FRAME_NUM: avio_printf(io, "%"PRIu64, frame_num); continue;
case ENC_STATS_FRAME_NUM_IN: avio_printf(io, "%"PRIu64, fd ? fd->dec.frame_num : -1); continue;
}
if (frame) {
switch (c->type) {
case ENC_STATS_SAMPLE_NUM: avio_printf(io, "%"PRIu64, ost->samples_encoded); continue;
case ENC_STATS_NB_SAMPLES: avio_printf(io, "%d", frame->nb_samples); continue;
default: av_assert0(0);
}
} else {
switch (c->type) {
case ENC_STATS_DTS: avio_printf(io, "%"PRId64, pkt->dts); continue;
case ENC_STATS_DTS_TIME: avio_printf(io, "%g", pkt->dts * av_q2d(tb)); continue;
case ENC_STATS_PKT_SIZE: avio_printf(io, "%d", pkt->size); continue;
case ENC_STATS_KEYFRAME: avio_write(io, (pkt->flags & AV_PKT_FLAG_KEY) ?
"K" : "N", 1); continue;
case ENC_STATS_BITRATE: {
double duration = FFMAX(pkt->duration, 1) * av_q2d(tb);
avio_printf(io, "%g", 8.0 * pkt->size / duration);
continue;
}
case ENC_STATS_AVG_BITRATE: {
double duration = pkt->dts * av_q2d(tb);
avio_printf(io, "%g", duration > 0 ? 8.0 * e->data_size / duration : -1.);
continue;
}
default: av_assert0(0);
}
}
}
avio_w8(io, '\n');
avio_flush(io);
pthread_mutex_unlock(&es->lock);
}
static inline double psnr(double d)
{
return -10.0 * log10(d);
}
static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
{
Encoder *e = ost->enc;
const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
NULL);
AVCodecContext *enc = ost->enc_ctx;
enum AVPictureType pict_type;
int64_t frame_number;
double ti1, bitrate, avg_bitrate;
double psnr_val = -1;
int quality;
quality = sd ? AV_RL32(sd) : -1;
pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
atomic_store(&ost->quality, quality);
if ((enc->flags & AV_CODEC_FLAG_PSNR) && sd && sd[5]) {
// FIXME the scaling assumes 8bit
double error = AV_RL64(sd + 8) / (enc->width * enc->height * 255.0 * 255.0);
if (error >= 0 && error <= 1)
psnr_val = psnr(error);
}
if (!write_vstats)
return 0;
/* this is executed just the first time update_video_stats is called */
if (!vstats_file) {
vstats_file = fopen(vstats_filename, "w");
if (!vstats_file) {
perror("fopen");
return AVERROR(errno);
}
}
frame_number = e->packets_encoded;
if (vstats_version <= 1) {
fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number,
quality / (float)FF_QP2LAMBDA);
} else {
fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ",
ost->file->index, ost->index, frame_number,
quality / (float)FF_QP2LAMBDA);
}
if (psnr_val >= 0)
fprintf(vstats_file, "PSNR= %6.2f ", psnr_val);
fprintf(vstats_file,"f_size= %6d ", pkt->size);
/* compute pts value */
ti1 = pkt->dts * av_q2d(pkt->time_base);
if (ti1 < 0.01)
ti1 = 0.01;
bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0;
avg_bitrate = (double)(e->data_size * 8) / ti1 / 1000.0;
fprintf(vstats_file, "s_size= %8.0fKiB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)e->data_size / 1024, ti1, bitrate, avg_bitrate);
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(pict_type));
return 0;
}
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
AVPacket *pkt)
{
Encoder *e = ost->enc;
AVCodecContext *enc = ost->enc_ctx;
const char *type_desc = av_get_media_type_string(enc->codec_type);
const char *action = frame ? "encode" : "flush";
int ret;
if (frame) {
FrameData *fd = frame_data(frame);
if (!fd)
return AVERROR(ENOMEM);
fd->wallclock[LATENCY_PROBE_ENC_PRE] = av_gettime_relative();
if (ost->enc_stats_pre.io)
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
ost->frames_encoded);
ost->frames_encoded++;
ost->samples_encoded += frame->nb_samples;
if (debug_ts) {
av_log(ost, AV_LOG_INFO, "encoder <- type:%s "
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
type_desc,
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
enc->time_base.num, enc->time_base.den);
}
if (frame->sample_aspect_ratio.num && !ost->frame_aspect_ratio.num)
enc->sample_aspect_ratio = frame->sample_aspect_ratio;
}
update_benchmark(NULL);
ret = avcodec_send_frame(enc, frame);
if (ret < 0 && !(ret == AVERROR_EOF && !frame)) {
av_log(ost, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n",
type_desc);
return ret;
}
while (1) {
FrameData *fd;
av_packet_unref(pkt);
ret = avcodec_receive_packet(enc, pkt);
update_benchmark("%s_%s %d.%d", action, type_desc,
of->index, ost->index);
pkt->time_base = enc->time_base;
/* if two pass, output log on success and EOF */
if ((ret >= 0 || ret == AVERROR_EOF) && ost->logfile && enc->stats_out)
fprintf(ost->logfile, "%s", enc->stats_out);
if (ret == AVERROR(EAGAIN)) {
av_assert0(frame); // should never happen during flushing
return 0;
} else if (ret < 0) {
if (ret != AVERROR_EOF)
av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
return ret;
}
fd = packet_data(pkt);
if (!fd)
return AVERROR(ENOMEM);
fd->wallclock[LATENCY_PROBE_ENC_POST] = av_gettime_relative();
// attach stream parameters to first packet if requested
avcodec_parameters_free(&fd->par_enc);
if (e->attach_par && !e->packets_encoded) {
fd->par_enc = avcodec_parameters_alloc();
if (!fd->par_enc)
return AVERROR(ENOMEM);
ret = avcodec_parameters_from_context(fd->par_enc, enc);
if (ret < 0)
return ret;
}
pkt->flags |= AV_PKT_FLAG_TRUSTED;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
ret = update_video_stats(ost, pkt, !!vstats_filename);
if (ret < 0)
return ret;
}
if (ost->enc_stats_post.io)
enc_stats_write(ost, &ost->enc_stats_post, NULL, pkt,
e->packets_encoded);
if (debug_ts) {
av_log(ost, AV_LOG_INFO, "encoder -> type:%s "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
"duration:%s duration_time:%s\n",
type_desc,
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
}
e->data_size += pkt->size;
e->packets_encoded++;
ret = sch_enc_send(e->sch, e->sch_idx, pkt);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
}
}
av_assert0(0);
}
static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
const AVFrame *frame)
{
double pts_time;
if (kf->ref_pts == AV_NOPTS_VALUE)
kf->ref_pts = frame->pts;
pts_time = (frame->pts - kf->ref_pts) * av_q2d(frame->time_base);
if (kf->index < kf->nb_pts &&
av_compare_ts(frame->pts, frame->time_base, kf->pts[kf->index], AV_TIME_BASE_Q) >= 0) {
kf->index++;
goto force_keyframe;
} else if (kf->pexpr) {
double res;
kf->expr_const_values[FKF_T] = pts_time;
res = av_expr_eval(kf->pexpr,
kf->expr_const_values, NULL);
av_log(logctx, AV_LOG_TRACE,
"force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n",
kf->expr_const_values[FKF_N],
kf->expr_const_values[FKF_N_FORCED],
kf->expr_const_values[FKF_PREV_FORCED_N],
kf->expr_const_values[FKF_T],
kf->expr_const_values[FKF_PREV_FORCED_T],
res);
kf->expr_const_values[FKF_N] += 1;
if (res) {
kf->expr_const_values[FKF_PREV_FORCED_N] = kf->expr_const_values[FKF_N] - 1;
kf->expr_const_values[FKF_PREV_FORCED_T] = kf->expr_const_values[FKF_T];
kf->expr_const_values[FKF_N_FORCED] += 1;
goto force_keyframe;
}
} else if (kf->type == KF_FORCE_SOURCE && (frame->flags & AV_FRAME_FLAG_KEY)) {
goto force_keyframe;
}
return AV_PICTURE_TYPE_NONE;
force_keyframe:
av_log(logctx, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
return AV_PICTURE_TYPE_I;
}
static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
{
OutputFile *of = ost->file;
enum AVMediaType type = ost->type;
if (type == AVMEDIA_TYPE_SUBTITLE) {
const AVSubtitle *subtitle = frame && frame->buf[0] ?
(AVSubtitle*)frame->buf[0]->data : NULL;
// no flushing for subtitles
return subtitle && subtitle->num_rects ?
do_subtitle_out(of, ost, subtitle, pkt) : 0;
}
if (frame) {
if (!check_recording_time(ost, frame->pts, frame->time_base))
return AVERROR_EOF;
if (type == AVMEDIA_TYPE_VIDEO) {
frame->quality = ost->enc_ctx->global_quality;
frame->pict_type = forced_kf_apply(ost, &ost->kf, frame);
#if FFMPEG_OPT_TOP
if (ost->top_field_first >= 0) {
frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * (!!ost->top_field_first);
}
#endif
} else {
if (!(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
ost->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
av_log(ost, AV_LOG_ERROR,
"Audio channel count changed and encoder does not support parameter changes\n");
return 0;
}
}
}
return encode_frame(of, ost, frame, pkt);
}
static void enc_thread_set_name(const OutputStream *ost)
{
char name[16];
snprintf(name, sizeof(name), "enc%d:%d:%s", ost->file->index, ost->index,
ost->enc_ctx->codec->name);
ff_thread_setname(name);
}
static void enc_thread_uninit(EncoderThread *et)
{
av_packet_free(&et->pkt);
av_frame_free(&et->frame);
memset(et, 0, sizeof(*et));
}
static int enc_thread_init(EncoderThread *et)
{
memset(et, 0, sizeof(*et));
et->frame = av_frame_alloc();
if (!et->frame)
goto fail;
et->pkt = av_packet_alloc();
if (!et->pkt)
goto fail;
return 0;
fail:
enc_thread_uninit(et);
return AVERROR(ENOMEM);
}
int encoder_thread(void *arg)
{
OutputStream *ost = arg;
Encoder *e = ost->enc;
EncoderThread et;
int ret = 0, input_status = 0;
int name_set = 0;
ret = enc_thread_init(&et);
if (ret < 0)
goto finish;
/* Open the subtitle encoders immediately. AVFrame-based encoders
* are opened through a callback from the scheduler once they get
* their first frame
*
* N.B.: because the callback is called from a different thread,
* enc_ctx MUST NOT be accessed before sch_enc_receive() returns
* for the first time for audio/video. */
if (ost->type != AVMEDIA_TYPE_VIDEO && ost->type != AVMEDIA_TYPE_AUDIO) {
ret = enc_open(ost, NULL);
if (ret < 0)
goto finish;
}
while (!input_status) {
input_status = sch_enc_receive(e->sch, e->sch_idx, et.frame);
if (input_status < 0) {
if (input_status == AVERROR_EOF) {
av_log(ost, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
if (e->opened)
break;
av_log(ost, AV_LOG_ERROR, "Could not open encoder before EOF\n");
ret = AVERROR(EINVAL);
} else {
av_log(ost, AV_LOG_ERROR, "Error receiving a frame for encoding: %s\n",
av_err2str(ret));
ret = input_status;
}
goto finish;
}
if (!name_set) {
enc_thread_set_name(ost);
name_set = 1;
}
ret = frame_encode(ost, et.frame, et.pkt);
av_packet_unref(et.pkt);
av_frame_unref(et.frame);
if (ret < 0) {
if (ret == AVERROR_EOF)
av_log(ost, AV_LOG_VERBOSE, "Encoder returned EOF, finishing\n");
else
av_log(ost, AV_LOG_ERROR, "Error encoding a frame: %s\n",
av_err2str(ret));
break;
}
}
// flush the encoder
if (ret == 0 || ret == AVERROR_EOF) {
ret = frame_encode(ost, NULL, et.pkt);
if (ret < 0 && ret != AVERROR_EOF)
av_log(ost, AV_LOG_ERROR, "Error flushing encoder: %s\n",
av_err2str(ret));
}
// EOF is normal thread termination
if (ret == AVERROR_EOF)
ret = 0;
finish:
enc_thread_uninit(&et);
return ret;
}
int enc_loopback(Encoder *enc)
{
enc->attach_par = 1;
return enc->sch_idx;
}
+2192 -594
View File
File diff suppressed because it is too large Load Diff
+9 -271
View File
@@ -27,7 +27,7 @@
static int nb_hw_devices; static int nb_hw_devices;
static HWDevice **hw_devices; static HWDevice **hw_devices;
static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type) HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
{ {
HWDevice *found = NULL; HWDevice *found = NULL;
int i; int i;
@@ -242,9 +242,9 @@ fail:
goto done; goto done;
} }
static int hw_device_init_from_type(enum AVHWDeviceType type, int hw_device_init_from_type(enum AVHWDeviceType type,
const char *device, const char *device,
HWDevice **dev_out) HWDevice **dev_out)
{ {
AVBufferRef *device_ref = NULL; AVBufferRef *device_ref = NULL;
HWDevice *dev; HWDevice *dev;
@@ -297,268 +297,14 @@ void hw_device_free_all(void)
nb_hw_devices = 0; nb_hw_devices = 0;
} }
static HWDevice *hw_device_match_by_codec(const AVCodec *codec) AVBufferRef *hw_device_for_filter(void)
{ {
const AVCodecHWConfig *config;
HWDevice *dev;
int i;
for (i = 0;; i++) {
config = avcodec_get_hw_config(codec, i);
if (!config)
return NULL;
if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
continue;
dev = hw_device_get_by_type(config->device_type);
if (dev)
return dev;
}
}
int hw_device_setup_for_decode(InputStream *ist)
{
const AVCodecHWConfig *config;
enum AVHWDeviceType type;
HWDevice *dev = NULL;
int err, auto_device = 0;
if (ist->hwaccel_device) {
dev = hw_device_get_by_name(ist->hwaccel_device);
if (!dev) {
if (ist->hwaccel_id == HWACCEL_AUTO) {
auto_device = 1;
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
type = ist->hwaccel_device_type;
err = hw_device_init_from_type(type, ist->hwaccel_device,
&dev);
} else {
// This will be dealt with by API-specific initialisation
// (using hwaccel_device), so nothing further needed here.
return 0;
}
} else {
if (ist->hwaccel_id == HWACCEL_AUTO) {
ist->hwaccel_device_type = dev->type;
} else if (ist->hwaccel_device_type != dev->type) {
av_log(NULL, AV_LOG_ERROR, "Invalid hwaccel device "
"specified for decoder: device %s of type %s is not "
"usable with hwaccel %s.\n", dev->name,
av_hwdevice_get_type_name(dev->type),
av_hwdevice_get_type_name(ist->hwaccel_device_type));
return AVERROR(EINVAL);
}
}
} else {
if (ist->hwaccel_id == HWACCEL_AUTO) {
auto_device = 1;
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
type = ist->hwaccel_device_type;
dev = hw_device_get_by_type(type);
// When "-qsv_device device" is used, an internal QSV device named
// as "__qsv_device" is created. Another QSV device is created too
// if "-init_hw_device qsv=name:device" is used. There are 2 QSV devices
// if both "-qsv_device device" and "-init_hw_device qsv=name:device"
// are used, hw_device_get_by_type(AV_HWDEVICE_TYPE_QSV) returns NULL.
// To keep back-compatibility with the removed ad-hoc libmfx setup code,
// call hw_device_get_by_name("__qsv_device") to select the internal QSV
// device.
if (!dev && type == AV_HWDEVICE_TYPE_QSV)
dev = hw_device_get_by_name("__qsv_device");
if (!dev)
err = hw_device_init_from_type(type, NULL, &dev);
} else {
dev = hw_device_match_by_codec(ist->dec);
if (!dev) {
// No device for this codec, but not using generic hwaccel
// and therefore may well not need one - ignore.
return 0;
}
}
}
if (auto_device) {
int i;
if (!avcodec_get_hw_config(ist->dec, 0)) {
// Decoder does not support any hardware devices.
return 0;
}
for (i = 0; !dev; i++) {
config = avcodec_get_hw_config(ist->dec, i);
if (!config)
break;
type = config->device_type;
dev = hw_device_get_by_type(type);
if (dev) {
av_log(NULL, AV_LOG_INFO, "Using auto "
"hwaccel type %s with existing device %s.\n",
av_hwdevice_get_type_name(type), dev->name);
}
}
for (i = 0; !dev; i++) {
config = avcodec_get_hw_config(ist->dec, i);
if (!config)
break;
type = config->device_type;
// Try to make a new device of this type.
err = hw_device_init_from_type(type, ist->hwaccel_device,
&dev);
if (err < 0) {
// Can't make a device of this type.
continue;
}
if (ist->hwaccel_device) {
av_log(NULL, AV_LOG_INFO, "Using auto "
"hwaccel type %s with new device created "
"from %s.\n", av_hwdevice_get_type_name(type),
ist->hwaccel_device);
} else {
av_log(NULL, AV_LOG_INFO, "Using auto "
"hwaccel type %s with new default device.\n",
av_hwdevice_get_type_name(type));
}
}
if (dev) {
ist->hwaccel_device_type = type;
} else {
av_log(NULL, AV_LOG_INFO, "Auto hwaccel "
"disabled: no device found.\n");
ist->hwaccel_id = HWACCEL_NONE;
return 0;
}
}
if (!dev) {
av_log(NULL, AV_LOG_ERROR, "No device available "
"for decoder: device type %s needed for codec %s.\n",
av_hwdevice_get_type_name(type), ist->dec->name);
return err;
}
ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
if (!ist->dec_ctx->hw_device_ctx)
return AVERROR(ENOMEM);
return 0;
}
int hw_device_setup_for_encode(OutputStream *ost)
{
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_ctx->codec, 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_ctx->codec->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);
}
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_ctx->codec->name);
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
if (!ost->enc_ctx->hw_device_ctx)
return AVERROR(ENOMEM);
} else {
// No device required, or no device available.
}
return 0;
}
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
{
InputStream *ist = avctx->opaque;
AVFrame *output = NULL;
enum AVPixelFormat output_format = ist->hwaccel_output_format;
int err;
if (input->format == output_format) {
// Nothing to do.
return 0;
}
output = av_frame_alloc();
if (!output)
return AVERROR(ENOMEM);
output->format = output_format;
err = av_hwframe_transfer_data(output, input, 0);
if (err < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
"output frame: %d.\n", err);
goto fail;
}
err = av_frame_copy_props(output, input);
if (err < 0) {
av_frame_unref(output);
goto fail;
}
av_frame_unref(input);
av_frame_move_ref(input, output);
av_frame_free(&output);
return 0;
fail:
av_frame_free(&output);
return err;
}
int hwaccel_decode_init(AVCodecContext *avctx)
{
InputStream *ist = avctx->opaque;
ist->hwaccel_retrieve_data = &hwaccel_retrieve_data;
return 0;
}
int hw_device_setup_for_filter(FilterGraph *fg)
{
HWDevice *dev;
int i;
// Pick the last hardware device if the user doesn't pick the device for // Pick the last hardware device if the user doesn't pick the device for
// filters explicitly with the filter_hw_device option. // filters explicitly with the filter_hw_device option.
if (filter_hw_device) if (filter_hw_device)
dev = filter_hw_device; return filter_hw_device->device_ref;
else if (nb_hw_devices > 0) { else if (nb_hw_devices > 0) {
dev = hw_devices[nb_hw_devices - 1]; HWDevice *dev = hw_devices[nb_hw_devices - 1];
if (nb_hw_devices > 1) if (nb_hw_devices > 1)
av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device " av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
@@ -567,17 +313,9 @@ int hw_device_setup_for_filter(FilterGraph *fg)
"%s is not usable for filters.\n", "%s is not usable for filters.\n",
nb_hw_devices, dev->name, nb_hw_devices, dev->name,
av_hwdevice_get_type_name(dev->type), dev->name); av_hwdevice_get_type_name(dev->type), dev->name);
} else
dev = NULL;
if (dev) { return dev->device_ref;
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; return NULL;
} }
+506 -377
View File
File diff suppressed because it is too large Load Diff
+45 -34
View File
@@ -24,7 +24,7 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include "thread_queue.h" #include "ffmpeg_sched.h"
#include "libavformat/avformat.h" #include "libavformat/avformat.h"
@@ -32,67 +32,78 @@
#include "libavutil/dict.h" #include "libavutil/dict.h"
#include "libavutil/fifo.h" #include "libavutil/fifo.h"
#include "libavutil/thread.h"
typedef struct MuxStream { typedef struct MuxStream {
OutputStream ost; OutputStream ost;
// name used for logging // name used for logging
char log_name[32]; char log_name[32];
/* the packets are buffered here until the muxer is ready to be initialized */ AVBSFContext *bsf_ctx;
AVFifo *muxing_queue; AVPacket *bsf_pkt;
AVBSFContext *bsf_ctx; AVPacket *pkt;
EncStats stats; EncStats stats;
int64_t max_frames; int sch_idx;
int sch_idx_enc;
int sch_idx_src;
/* int sq_idx_mux;
* 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;
int max_muxing_queue_size; int64_t max_frames;
/* Threshold after which max_muxing_queue_size will be in effect */ // timestamp from which the streamcopied streams should start,
size_t muxing_queue_data_threshold; // in AV_TIME_BASE_Q;
// everything before it should be discarded
int64_t ts_copy_start;
/* dts of the last packet sent to the muxer, in the stream timebase /* dts of the last packet sent to the muxer, in the stream timebase
* used for making up missing dts values */ * used for making up missing dts values */
int64_t last_mux_dts; int64_t last_mux_dts;
int64_t stream_duration;
AVRational stream_duration_tb;
// state for av_rescale_delta() call for audio in write_packet()
int64_t ts_rescale_delta_last;
// combined size of all the packets sent to the muxer
uint64_t data_size_mux;
int copy_initial_nonkeyframes;
int copy_prior_start;
int streamcopy_started;
} MuxStream; } MuxStream;
typedef struct Muxer { typedef struct Muxer {
OutputFile of; OutputFile of;
// name used for logging // name used for logging
char log_name[32]; char log_name[32];
AVFormatContext *fc; AVFormatContext *fc;
pthread_t thread; Scheduler *sch;
ThreadQueue *tq; unsigned sch_idx;
AVDictionary *opts; // OutputStream indices indexed by scheduler stream indices
int *sch_stream_idx;
int nb_sch_stream_idx;
int thread_queue_size; AVDictionary *opts;
/* filesize limit expressed in bytes */ /* filesize limit expressed in bytes */
int64_t limit_filesize; int64_t limit_filesize;
atomic_int_least64_t last_filesize; atomic_int_least64_t last_filesize;
int header_written; int header_written;
SyncQueue *sq_mux; SyncQueue *sq_mux;
AVPacket *sq_pkt; AVPacket *sq_pkt;
} Muxer; } Muxer;
/* whether we want to print an SDP, set in of_open() */ int mux_check_init(void *arg);
extern int want_sdp;
int mux_check_init(Muxer *mux);
static MuxStream *ms_from_ost(OutputStream *ost) static MuxStream *ms_from_ost(OutputStream *ost)
{ {
+1597 -893
View File
File diff suppressed because it is too large Load Diff
+675 -535
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+489
View File
@@ -0,0 +1,489 @@
/*
* Inter-thread scheduling/synchronization.
* Copyright (c) 2023 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
*/
#ifndef FFTOOLS_FFMPEG_SCHED_H
#define FFTOOLS_FFMPEG_SCHED_H
#include <stddef.h>
#include <stdint.h>
#include "ffmpeg_utils.h"
/*
* This file contains the API for the transcode scheduler.
*
* Overall architecture of the transcoding process involves instances of the
* following components:
* - demuxers, each containing any number of demuxed streams; demuxed packets
* belonging to some stream are sent to any number of decoders (transcoding)
* and/or muxers (streamcopy);
* - decoders, which receive encoded packets from some demuxed stream or
* encoder, decode them, and send decoded frames to any number of filtergraph
* inputs (audio/video) or encoders (subtitles);
* - filtergraphs, each containing zero or more inputs (0 in case the
* filtergraph contains a lavfi source filter), and one or more outputs; the
* inputs and outputs need not have matching media types;
* each filtergraph input receives decoded frames from some decoder;
* filtered frames from each output are sent to some encoder;
* - encoders, which receive decoded frames from some decoder (subtitles) or
* some filtergraph output (audio/video), encode them, and send encoded
* packets to any number of muxed streams or decoders;
* - muxers, each containing any number of muxed streams; each muxed stream
* receives encoded packets from some demuxed stream (streamcopy) or some
* encoder (transcoding); those packets are interleaved and written out by the
* muxer.
*
* There must be at least one muxer instance, otherwise the transcode produces
* no output and is meaningless. Otherwise, in a generic transcoding scenario
* there may be arbitrary number of instances of any of the above components,
* interconnected in various ways.
*
* The code tries to keep all the output streams across all the muxers in sync
* (i.e. at the same DTS), which is accomplished by varying the rates at which
* packets are read from different demuxers and lavfi sources. Note that the
* degree of control we have over synchronization is fundamentally limited - if
* some demuxed streams in the same input are interleaved at different rates
* than that at which they are to be muxed (e.g. because an input file is badly
* interleaved, or the user changed their speed by mismatching amounts), then
* there will be increasing amounts of buffering followed by eventual
* transcoding failure.
*
* N.B. 1: there are meaningful transcode scenarios with no demuxers, e.g.
* - encoding and muxing output from filtergraph(s) that have no inputs;
* - creating a file that contains nothing but attachments and/or metadata.
*
* N.B. 2: a filtergraph output could, in principle, feed multiple encoders, but
* this is unnecessary because the (a)split filter provides the same
* functionality.
*
* The scheduler, in the above model, is the master object that oversees and
* facilitates the transcoding process. The basic idea is that all instances
* of the abovementioned components communicate only with the scheduler and not
* with each other. The scheduler is then the single place containing the
* knowledge about the whole transcoding pipeline.
*/
struct AVFrame;
struct AVPacket;
typedef struct Scheduler Scheduler;
enum SchedulerNodeType {
SCH_NODE_TYPE_NONE = 0,
SCH_NODE_TYPE_DEMUX,
SCH_NODE_TYPE_MUX,
SCH_NODE_TYPE_DEC,
SCH_NODE_TYPE_ENC,
SCH_NODE_TYPE_FILTER_IN,
SCH_NODE_TYPE_FILTER_OUT,
};
typedef struct SchedulerNode {
enum SchedulerNodeType type;
unsigned idx;
unsigned idx_stream;
} SchedulerNode;
typedef int (*SchThreadFunc)(void *arg);
#define SCH_DSTREAM(file, stream) \
(SchedulerNode){ .type = SCH_NODE_TYPE_DEMUX, \
.idx = file, .idx_stream = stream }
#define SCH_MSTREAM(file, stream) \
(SchedulerNode){ .type = SCH_NODE_TYPE_MUX, \
.idx = file, .idx_stream = stream }
#define SCH_DEC(decoder) \
(SchedulerNode){ .type = SCH_NODE_TYPE_DEC, \
.idx = decoder }
#define SCH_ENC(encoder) \
(SchedulerNode){ .type = SCH_NODE_TYPE_ENC, \
.idx = encoder }
#define SCH_FILTER_IN(filter, input) \
(SchedulerNode){ .type = SCH_NODE_TYPE_FILTER_IN, \
.idx = filter, .idx_stream = input }
#define SCH_FILTER_OUT(filter, output) \
(SchedulerNode){ .type = SCH_NODE_TYPE_FILTER_OUT, \
.idx = filter, .idx_stream = output }
Scheduler *sch_alloc(void);
void sch_free(Scheduler **sch);
int sch_start(Scheduler *sch);
int sch_stop(Scheduler *sch, int64_t *finish_ts);
/**
* Wait until transcoding terminates or the specified timeout elapses.
*
* @param timeout_us Amount of time in microseconds after which this function
* will timeout.
* @param transcode_ts Current transcode timestamp in AV_TIME_BASE_Q, for
* informational purposes only.
*
* @retval 0 waiting timed out, transcoding is not finished
* @retval 1 transcoding is finished
*/
int sch_wait(Scheduler *sch, uint64_t timeout_us, int64_t *transcode_ts);
/**
* Add a demuxer to the scheduler.
*
* @param func Function executed as the demuxer task.
* @param ctx Demuxer state; will be passed to func and used for logging.
*
* @retval ">=0" Index of the newly-created demuxer.
* @retval "<0" Error code.
*/
int sch_add_demux(Scheduler *sch, SchThreadFunc func, void *ctx);
/**
* Add a demuxed stream for a previously added demuxer.
*
* @param demux_idx index previously returned by sch_add_demux()
*
* @retval ">=0" Index of the newly-created demuxed stream.
* @retval "<0" Error code.
*/
int sch_add_demux_stream(Scheduler *sch, unsigned demux_idx);
/**
* Add a decoder to the scheduler.
*
* @param func Function executed as the decoder task.
* @param ctx Decoder state; will be passed to func and used for logging.
* @param send_end_ts The decoder will return an end timestamp after flush packets
* are delivered to it. See documentation for
* sch_dec_receive() for more details.
*
* @retval ">=0" Index of the newly-created decoder.
* @retval "<0" Error code.
*/
int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx,
int send_end_ts);
/**
* Add a filtergraph to the scheduler.
*
* @param nb_inputs Number of filtergraph inputs.
* @param nb_outputs number of filtergraph outputs
* @param func Function executed as the filtering task.
* @param ctx Filter state; will be passed to func and used for logging.
*
* @retval ">=0" Index of the newly-created filtergraph.
* @retval "<0" Error code.
*/
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs,
SchThreadFunc func, void *ctx);
/**
* Add a muxer to the scheduler.
*
* Note that muxer thread startup is more complicated than for other components,
* because
* - muxer streams fed by audio/video encoders become initialized dynamically at
* runtime, after those encoders receive their first frame and initialize
* themselves, followed by calling sch_mux_stream_ready()
* - the header can be written after all the streams for a muxer are initialized
* - we may need to write an SDP, which must happen
* - AFTER all the headers are written
* - BEFORE any packets are written by any muxer
* - with all the muxers quiescent
* To avoid complicated muxer-thread synchronization dances, we postpone
* starting the muxer threads until after the SDP is written. The sequence of
* events is then as follows:
* - After sch_mux_stream_ready() is called for all the streams in a given muxer,
* the header for that muxer is written (care is taken that headers for
* different muxers are not written concurrently, since they write file
* information to stderr). If SDP is not wanted, the muxer thread then starts
* and muxing begins.
* - When SDP _is_ wanted, no muxer threads start until the header for the last
* muxer is written. After that, the SDP is written, after which all the muxer
* threads are started at once.
*
* In order for the above to work, the scheduler needs to be able to invoke
* just writing the header, which is the reason the init parameter exists.
*
* @param func Function executed as the muxing task.
* @param init Callback that is called to initialize the muxer and write the
* header. Called after sch_mux_stream_ready() is called for all the
* streams in the muxer.
* @param ctx Muxer state; will be passed to func/init and used for logging.
* @param sdp_auto Determines automatic SDP writing - see sch_sdp_filename().
* @param thread_queue_size number of packets that can be buffered before
* sending to the muxer blocks
*
* @retval ">=0" Index of the newly-created muxer.
* @retval "<0" Error code.
*/
int sch_add_mux(Scheduler *sch, SchThreadFunc func, int (*init)(void *),
void *ctx, int sdp_auto, unsigned thread_queue_size);
/**
* Default size of a packet thread queue. For muxing this can be overridden by
* the thread_queue_size option as passed to a call to sch_add_mux().
*/
#define DEFAULT_PACKET_THREAD_QUEUE_SIZE 8
/**
* Default size of a frame thread queue.
*/
#define DEFAULT_FRAME_THREAD_QUEUE_SIZE 8
/**
* Add a muxed stream for a previously added muxer.
*
* @param mux_idx index previously returned by sch_add_mux()
*
* @retval ">=0" Index of the newly-created muxed stream.
* @retval "<0" Error code.
*/
int sch_add_mux_stream(Scheduler *sch, unsigned mux_idx);
/**
* Configure limits on packet buffering performed before the muxer task is
* started.
*
* @param mux_idx index previously returned by sch_add_mux()
* @param stream_idx_idx index previously returned by sch_add_mux_stream()
* @param data_threshold Total size of the buffered packets' data after which
* max_packets applies.
* @param max_packets maximum Maximum number of buffered packets after
* data_threshold is reached.
*/
void sch_mux_stream_buffering(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
size_t data_threshold, int max_packets);
/**
* Signal to the scheduler that the specified muxed stream is initialized and
* ready. Muxing is started once all the streams are ready.
*/
int sch_mux_stream_ready(Scheduler *sch, unsigned mux_idx, unsigned stream_idx);
/**
* Set the file path for the SDP.
*
* The SDP is written when either of the following is true:
* - this function is called at least once
* - sdp_auto=1 is passed to EVERY call of sch_add_mux()
*/
int sch_sdp_filename(Scheduler *sch, const char *sdp_filename);
/**
* Add an encoder to the scheduler.
*
* @param func Function executed as the encoding task.
* @param ctx Encoder state; will be passed to func and used for logging.
* @param open_cb This callback, if specified, will be called when the first
* frame is obtained for this encoder. For audio encoders with a
* fixed frame size (which use a sync queue in the scheduler to
* rechunk frames), it must return that frame size on success.
* Otherwise (non-audio, variable frame size) it should return 0.
*
* @retval ">=0" Index of the newly-created encoder.
* @retval "<0" Error code.
*/
int sch_add_enc(Scheduler *sch, SchThreadFunc func, void *ctx,
int (*open_cb)(void *func_arg, const struct AVFrame *frame));
/**
* Add an pre-encoding sync queue to the scheduler.
*
* @param buf_size_us Sync queue buffering size, passed to sq_alloc().
* @param logctx Logging context for the sync queue. passed to sq_alloc().
*
* @retval ">=0" Index of the newly-created sync queue.
* @retval "<0" Error code.
*/
int sch_add_sq_enc(Scheduler *sch, uint64_t buf_size_us, void *logctx);
int sch_sq_add_enc(Scheduler *sch, unsigned sq_idx, unsigned enc_idx,
int limiting, uint64_t max_frames);
int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst);
enum DemuxSendFlags {
/**
* Treat the packet as an EOF for SCH_NODE_TYPE_MUX destinations
* send normally to other types.
*/
DEMUX_SEND_STREAMCOPY_EOF = (1 << 0),
};
/**
* Called by demuxer tasks to communicate with their downstreams. The following
* may be sent:
* - a demuxed packet for the stream identified by pkt->stream_index;
* - demuxer discontinuity/reset (e.g. after a seek) - this is signalled by an
* empty packet with stream_index=-1.
*
* @param demux_idx demuxer index
* @param pkt A demuxed packet to send.
* When flushing (i.e. pkt->stream_index=-1 on entry to this
* function), on successful return pkt->pts/pkt->time_base will be
* set to the maximum end timestamp of any decoded audio stream, or
* AV_NOPTS_VALUE if no decoded audio streams are present.
*
* @retval "non-negative value" success
* @retval AVERROR_EOF all consumers for the stream are done
* @retval AVERROR_EXIT all consumers are done, should terminate demuxing
* @retval "anoter negative error code" other failure
*/
int sch_demux_send(Scheduler *sch, unsigned demux_idx, struct AVPacket *pkt,
unsigned flags);
/**
* Called by decoder tasks to receive a packet for decoding.
*
* @param dec_idx decoder index
* @param pkt Input packet will be written here on success.
*
* An empty packet signals that the decoder should be flushed, but
* more packets will follow (e.g. after seeking). When a decoder
* created with send_end_ts=1 receives a flush packet, it must write
* the end timestamp of the stream after flushing to
* pkt->pts/time_base on the next call to this function (if any).
*
* @retval "non-negative value" success
* @retval AVERROR_EOF no more packets will arrive, should terminate decoding
* @retval "another negative error code" other failure
*/
int sch_dec_receive(Scheduler *sch, unsigned dec_idx, struct AVPacket *pkt);
/**
* Called by decoder tasks to send a decoded frame downstream.
*
* @param dec_idx Decoder index previously returned by sch_add_dec().
* @param frame Decoded frame; on success it is consumed and cleared by this
* function
*
* @retval ">=0" success
* @retval AVERROR_EOF all consumers are done, should terminate decoding
* @retval "another negative error code" other failure
*/
int sch_dec_send(Scheduler *sch, unsigned dec_idx, struct AVFrame *frame);
/**
* Called by filtergraph tasks to obtain frames for filtering. Will wait for a
* frame to become available and return it in frame.
*
* Filtergraphs that contain lavfi sources and do not currently require new
* input frames should call this function as a means of rate control - then
* in_idx should be set equal to nb_inputs on entry to this function.
*
* @param fg_idx Filtergraph index previously returned by sch_add_filtergraph().
* @param[in,out] in_idx On input contains the index of the input on which a frame
* is most desired. May be set to nb_inputs to signal that
* the filtergraph does not need more input currently.
*
* On success, will be replaced with the input index of
* the actually returned frame or EOF timestamp.
*
* @retval ">=0" Frame data or EOF timestamp was delivered into frame, in_idx
* contains the index of the input it belongs to.
* @retval AVERROR(EAGAIN) No frame was returned, the filtergraph should
* resume filtering. May only be returned when
* in_idx=nb_inputs on entry to this function.
* @retval AVERROR_EOF No more frames will arrive, should terminate filtering.
*/
int sch_filter_receive(Scheduler *sch, unsigned fg_idx,
unsigned *in_idx, struct AVFrame *frame);
/**
* Called by filter tasks to signal that a filter input will no longer accept input.
*
* @param fg_idx Filtergraph index previously returned from sch_add_filtergraph().
* @param in_idx Index of the input to finish.
*/
void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx);
/**
* Called by filtergraph tasks to send a filtered frame or EOF to consumers.
*
* @param fg_idx Filtergraph index previously returned by sch_add_filtergraph().
* @param out_idx Index of the output which produced the frame.
* @param frame The frame to send to consumers. When NULL, signals that no more
* frames will be produced for the specified output. When non-NULL,
* the frame is consumed and cleared by this function on success.
*
* @retval "non-negative value" success
* @retval AVERROR_EOF all consumers are done
* @retval "anoter negative error code" other failure
*/
int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx,
struct AVFrame *frame);
int sch_filter_command(Scheduler *sch, unsigned fg_idx, struct AVFrame *frame);
/**
* Called by encoder tasks to obtain frames for encoding. Will wait for a frame
* to become available and return it in frame.
*
* @param enc_idx Encoder index previously returned by sch_add_enc().
* @param frame Newly-received frame will be stored here on success. Must be
* clean on entrance to this function.
*
* @retval 0 A frame was successfully delivered into frame.
* @retval AVERROR_EOF No more frames will be delivered, the encoder should
* flush everything and terminate.
*
*/
int sch_enc_receive(Scheduler *sch, unsigned enc_idx, struct AVFrame *frame);
/**
* Called by encoder tasks to send encoded packets downstream.
*
* @param enc_idx Encoder index previously returned by sch_add_enc().
* @param pkt An encoded packet; it will be consumed and cleared by this
* function on success.
*
* @retval 0 success
* @retval "<0" Error code.
*/
int sch_enc_send (Scheduler *sch, unsigned enc_idx, struct AVPacket *pkt);
/**
* Called by muxer tasks to obtain packets for muxing. Will wait for a packet
* for any muxed stream to become available and return it in pkt.
*
* @param mux_idx Muxer index previously returned by sch_add_mux().
* @param pkt Newly-received packet will be stored here on success. Must be
* clean on entrance to this function.
*
* @retval 0 A packet was successfully delivered into pkt. Its stream_index
* corresponds to a stream index previously returned from
* sch_add_mux_stream().
* @retval AVERROR_EOF When pkt->stream_index is non-negative, this signals that
* no more packets will be delivered for this stream index.
* Otherwise this indicates that no more packets will be
* delivered for any stream and the muxer should therefore
* flush everything and terminate.
*/
int sch_mux_receive(Scheduler *sch, unsigned mux_idx, struct AVPacket *pkt);
/**
* Called by muxer tasks to signal that a stream will no longer accept input.
*
* @param stream_idx Stream index previously returned from sch_add_mux_stream().
*/
void sch_mux_receive_finish(Scheduler *sch, unsigned mux_idx, unsigned stream_idx);
int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
unsigned dec_idx);
int sch_mux_sub_heartbeat(Scheduler *sch, unsigned mux_idx, unsigned stream_idx,
const AVPacket *pkt);
#endif /* FFTOOLS_FFMPEG_SCHED_H */
+56
View File
@@ -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 FFTOOLS_FFMPEG_UTILS_H
#define FFTOOLS_FFMPEG_UTILS_H
#include <stdint.h>
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavutil/rational.h"
#include "libavcodec/packet.h"
typedef struct Timestamp {
int64_t ts;
AVRational tb;
} Timestamp;
/**
* Merge two return codes - return one of the error codes if at least one of
* them was negative, 0 otherwise.
* Currently just picks the first one, eventually we might want to do something
* more sophisticated, like sorting them by priority.
*/
static inline int err_merge(int err0, int err1)
{
return (err0 < 0) ? err0 : FFMIN(err1, 0);
}
static inline void pkt_move(void *dst, void *src)
{
av_packet_move_ref(dst, src);
}
static inline void frame_move(void *dst, void *src)
{
av_frame_move_ref(dst, src);
}
#endif // FFTOOLS_FFMPEG_UTILS_H
+314 -191
View File
File diff suppressed because it is too large Load Diff
+835
View File
@@ -0,0 +1,835 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General 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 VK_NO_PROTOTYPES
#define VK_ENABLE_BETA_EXTENSIONS
#include "config.h"
#include "ffplay_renderer.h"
#if (SDL_VERSION_ATLEAST(2, 0, 6) && CONFIG_LIBPLACEBO)
/* Get PL_API_VER */
#include <libplacebo/config.h>
#define HAVE_VULKAN_RENDERER (PL_API_VER >= 278)
#else
#define HAVE_VULKAN_RENDERER 0
#endif
#if HAVE_VULKAN_RENDERER
#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR)
#define VK_USE_PLATFORM_WIN32_KHR
#endif
#include <libplacebo/vulkan.h>
#include <libplacebo/utils/frame_queue.h>
#include <libplacebo/utils/libav.h>
#include <SDL_vulkan.h>
#include "libavutil/bprint.h"
#endif
struct VkRenderer {
const AVClass *class;
int (*create)(VkRenderer *renderer, SDL_Window *window, AVDictionary *dict);
int (*get_hw_dev)(VkRenderer *renderer, AVBufferRef **dev);
int (*display)(VkRenderer *renderer, AVFrame *frame);
int (*resize)(VkRenderer *renderer, int width, int height);
void (*destroy)(VkRenderer *renderer);
};
#if HAVE_VULKAN_RENDERER
typedef struct RendererContext {
VkRenderer api;
// Can be NULL when vulkan instance is created by avutil
pl_vk_inst placebo_instance;
pl_vulkan placebo_vulkan;
pl_swapchain swapchain;
VkSurfaceKHR vk_surface;
pl_renderer renderer;
pl_tex tex[4];
pl_log vk_log;
AVBufferRef *hw_device_ref;
AVBufferRef *hw_frame_ref;
enum AVPixelFormat *transfer_formats;
AVHWFramesConstraints *constraints;
PFN_vkGetInstanceProcAddr get_proc_addr;
// This field is a copy from pl_vk_inst->instance or hw_device_ref instance.
VkInstance inst;
AVFrame *vk_frame;
} RendererContext;
static void vk_log_cb(void *log_priv, enum pl_log_level level,
const char *msg)
{
static const int level_map[] = {
AV_LOG_QUIET,
AV_LOG_FATAL,
AV_LOG_ERROR,
AV_LOG_WARNING,
AV_LOG_INFO,
AV_LOG_DEBUG,
AV_LOG_TRACE,
};
if (level > 0 && level < FF_ARRAY_ELEMS(level_map))
av_log(log_priv, level_map[level], "%s\n", msg);
}
// Should keep sync with optional_device_exts inside hwcontext_vulkan.c
static const char *optional_device_exts[] = {
/* Misc or required by other extensions */
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,
VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,
VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,
VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,
/* Imports/exports */
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
#ifdef _WIN32
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
#endif
/* Video encoding/decoding */
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,
"VK_MESA_video_decode_av1",
};
static inline int enable_debug(const AVDictionary *opt)
{
AVDictionaryEntry *entry = av_dict_get(opt, "debug", NULL, 0);
int debug = entry && strtol(entry->value, NULL, 10);
return debug;
}
static void hwctx_lock_queue(void *priv, uint32_t qf, uint32_t qidx)
{
AVHWDeviceContext *avhwctx = priv;
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
hwctx->lock_queue(avhwctx, qf, qidx);
}
static void hwctx_unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
{
AVHWDeviceContext *avhwctx = priv;
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
hwctx->unlock_queue(avhwctx, qf, qidx);
}
static int add_instance_extension(const char **ext, unsigned num_ext,
const AVDictionary *opt,
AVDictionary **dict)
{
const char *inst_ext_key = "instance_extensions";
AVDictionaryEntry *entry;
AVBPrint buf;
char *ext_list = NULL;
int ret;
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
for (int i = 0; i < num_ext; i++) {
if (i)
av_bprintf(&buf, "+%s", ext[i]);
else
av_bprintf(&buf, "%s", ext[i]);
}
entry = av_dict_get(opt, inst_ext_key, NULL, 0);
if (entry && entry->value && entry->value[0]) {
if (num_ext)
av_bprintf(&buf, "+");
av_bprintf(&buf, "%s", entry->value);
}
ret = av_bprint_finalize(&buf, &ext_list);
if (ret < 0)
return ret;
return av_dict_set(dict, inst_ext_key, ext_list, AV_DICT_DONT_STRDUP_VAL);
}
static int add_device_extension(const AVDictionary *opt,
AVDictionary **dict)
{
const char *dev_ext_key = "device_extensions";
AVDictionaryEntry *entry;
AVBPrint buf;
char *ext_list = NULL;
int ret;
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
av_bprintf(&buf, "%s", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
for (int i = 0; i < pl_vulkan_num_recommended_extensions; i++)
av_bprintf(&buf, "+%s", pl_vulkan_recommended_extensions[i]);
entry = av_dict_get(opt, dev_ext_key, NULL, 0);
if (entry && entry->value && entry->value[0])
av_bprintf(&buf, "+%s", entry->value);
ret = av_bprint_finalize(&buf, &ext_list);
if (ret < 0)
return ret;
return av_dict_set(dict, dev_ext_key, ext_list, AV_DICT_DONT_STRDUP_VAL);
}
static const char *select_device(const AVDictionary *opt)
{
const AVDictionaryEntry *entry;
entry = av_dict_get(opt, "device", NULL, 0);
if (entry)
return entry->value;
return NULL;
}
static int create_vk_by_hwcontext(VkRenderer *renderer,
const char **ext, unsigned num_ext,
const AVDictionary *opt)
{
RendererContext *ctx = (RendererContext *) renderer;
AVHWDeviceContext *dev;
AVVulkanDeviceContext *hwctx;
AVDictionary *dict = NULL;
int ret;
ret = add_instance_extension(ext, num_ext, opt, &dict);
if (ret < 0)
return ret;
ret = add_device_extension(opt, &dict);
if (ret) {
av_dict_free(&dict);
return ret;
}
ret = av_hwdevice_ctx_create(&ctx->hw_device_ref, AV_HWDEVICE_TYPE_VULKAN,
select_device(opt), dict, 0);
av_dict_free(&dict);
if (ret < 0)
return ret;
dev = (AVHWDeviceContext *) ctx->hw_device_ref->data;
hwctx = dev->hwctx;
// There is no way to pass SDL GetInstanceProcAddr to hwdevice.
// Check the result and return error if they don't match.
if (hwctx->get_proc_addr != SDL_Vulkan_GetVkGetInstanceProcAddr()) {
av_log(renderer, AV_LOG_ERROR,
"hwdevice and SDL use different get_proc_addr. "
"Try -vulkan_params create_by_placebo=1\n");
return AVERROR_PATCHWELCOME;
}
ctx->get_proc_addr = hwctx->get_proc_addr;
ctx->inst = hwctx->inst;
ctx->placebo_vulkan = pl_vulkan_import(ctx->vk_log,
pl_vulkan_import_params(
.instance = hwctx->inst,
.get_proc_addr = hwctx->get_proc_addr,
.phys_device = hwctx->phys_dev,
.device = hwctx->act_dev,
.extensions = hwctx->enabled_dev_extensions,
.num_extensions = hwctx->nb_enabled_dev_extensions,
.features = &hwctx->device_features,
.lock_queue = hwctx_lock_queue,
.unlock_queue = hwctx_unlock_queue,
.queue_ctx = dev,
.queue_graphics = {
.index = hwctx->queue_family_index,
.count = hwctx->nb_graphics_queues,
},
.queue_compute = {
.index = hwctx->queue_family_comp_index,
.count = hwctx->nb_comp_queues,
},
.queue_transfer = {
.index = hwctx->queue_family_tx_index,
.count = hwctx->nb_tx_queues,
},
));
if (!ctx->placebo_vulkan)
return AVERROR_EXTERNAL;
return 0;
}
static void placebo_lock_queue(struct AVHWDeviceContext *dev_ctx,
uint32_t queue_family, uint32_t index)
{
RendererContext *ctx = dev_ctx->user_opaque;
pl_vulkan vk = ctx->placebo_vulkan;
vk->lock_queue(vk, queue_family, index);
}
static void placebo_unlock_queue(struct AVHWDeviceContext *dev_ctx,
uint32_t queue_family,
uint32_t index)
{
RendererContext *ctx = dev_ctx->user_opaque;
pl_vulkan vk = ctx->placebo_vulkan;
vk->unlock_queue(vk, queue_family, index);
}
static int get_decode_queue(VkRenderer *renderer, int *index, int *count)
{
RendererContext *ctx = (RendererContext *) renderer;
VkQueueFamilyProperties *queue_family_prop = NULL;
uint32_t num_queue_family_prop = 0;
PFN_vkGetPhysicalDeviceQueueFamilyProperties get_queue_family_prop;
PFN_vkGetInstanceProcAddr get_proc_addr = ctx->get_proc_addr;
*index = -1;
*count = 0;
get_queue_family_prop = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)
get_proc_addr(ctx->placebo_instance->instance,
"vkGetPhysicalDeviceQueueFamilyProperties");
get_queue_family_prop(ctx->placebo_vulkan->phys_device,
&num_queue_family_prop, NULL);
if (!num_queue_family_prop)
return AVERROR_EXTERNAL;
queue_family_prop = av_calloc(num_queue_family_prop,
sizeof(*queue_family_prop));
if (!queue_family_prop)
return AVERROR(ENOMEM);
get_queue_family_prop(ctx->placebo_vulkan->phys_device,
&num_queue_family_prop,
queue_family_prop);
for (int i = 0; i < num_queue_family_prop; i++) {
if (queue_family_prop[i].queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
*index = i;
*count = queue_family_prop[i].queueCount;
break;
}
}
av_free(queue_family_prop);
return 0;
}
static int create_vk_by_placebo(VkRenderer *renderer,
const char **ext, unsigned num_ext,
const AVDictionary *opt)
{
RendererContext *ctx = (RendererContext *) renderer;
AVHWDeviceContext *device_ctx;
AVVulkanDeviceContext *vk_dev_ctx;
int decode_index;
int decode_count;
int ret;
ctx->get_proc_addr = SDL_Vulkan_GetVkGetInstanceProcAddr();
ctx->placebo_instance = pl_vk_inst_create(ctx->vk_log, pl_vk_inst_params(
.get_proc_addr = ctx->get_proc_addr,
.debug = enable_debug(opt),
.extensions = ext,
.num_extensions = num_ext
));
if (!ctx->placebo_instance) {
return AVERROR_EXTERNAL;
}
ctx->inst = ctx->placebo_instance->instance;
ctx->placebo_vulkan = pl_vulkan_create(ctx->vk_log, pl_vulkan_params(
.instance = ctx->placebo_instance->instance,
.get_proc_addr = ctx->placebo_instance->get_proc_addr,
.surface = ctx->vk_surface,
.allow_software = false,
.opt_extensions = optional_device_exts,
.num_opt_extensions = FF_ARRAY_ELEMS(optional_device_exts),
.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
.device_name = select_device(opt),
));
if (!ctx->placebo_vulkan)
return AVERROR_EXTERNAL;
ctx->hw_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VULKAN);
if (!ctx->hw_device_ref) {
return AVERROR(ENOMEM);
}
device_ctx = (AVHWDeviceContext *) ctx->hw_device_ref->data;
device_ctx->user_opaque = ctx;
vk_dev_ctx = device_ctx->hwctx;
vk_dev_ctx->lock_queue = placebo_lock_queue,
vk_dev_ctx->unlock_queue = placebo_unlock_queue;
vk_dev_ctx->get_proc_addr = ctx->placebo_instance->get_proc_addr;
vk_dev_ctx->inst = ctx->placebo_instance->instance;
vk_dev_ctx->phys_dev = ctx->placebo_vulkan->phys_device;
vk_dev_ctx->act_dev = ctx->placebo_vulkan->device;
vk_dev_ctx->device_features = *ctx->placebo_vulkan->features;
vk_dev_ctx->enabled_inst_extensions = ctx->placebo_instance->extensions;
vk_dev_ctx->nb_enabled_inst_extensions = ctx->placebo_instance->num_extensions;
vk_dev_ctx->enabled_dev_extensions = ctx->placebo_vulkan->extensions;
vk_dev_ctx->nb_enabled_dev_extensions = ctx->placebo_vulkan->num_extensions;
vk_dev_ctx->queue_family_index = ctx->placebo_vulkan->queue_graphics.index;
vk_dev_ctx->nb_graphics_queues = ctx->placebo_vulkan->queue_graphics.count;
vk_dev_ctx->queue_family_tx_index = ctx->placebo_vulkan->queue_transfer.index;
vk_dev_ctx->nb_tx_queues = ctx->placebo_vulkan->queue_transfer.count;
vk_dev_ctx->queue_family_comp_index = ctx->placebo_vulkan->queue_compute.index;
vk_dev_ctx->nb_comp_queues = ctx->placebo_vulkan->queue_compute.count;
ret = get_decode_queue(renderer, &decode_index, &decode_count);
if (ret < 0)
return ret;
vk_dev_ctx->queue_family_decode_index = decode_index;
vk_dev_ctx->nb_decode_queues = decode_count;
ret = av_hwdevice_ctx_init(ctx->hw_device_ref);
if (ret < 0)
return ret;
return 0;
}
static int create(VkRenderer *renderer, SDL_Window *window, AVDictionary *opt)
{
int ret = 0;
unsigned num_ext = 0;
const char **ext = NULL;
int w, h;
struct pl_log_params vk_log_params = {
.log_cb = vk_log_cb,
.log_level = PL_LOG_DEBUG,
.log_priv = renderer,
};
RendererContext *ctx = (RendererContext *) renderer;
AVDictionaryEntry *entry;
ctx->vk_log = pl_log_create(PL_API_VER, &vk_log_params);
if (!SDL_Vulkan_GetInstanceExtensions(window, &num_ext, NULL)) {
av_log(NULL, AV_LOG_FATAL, "Failed to get vulkan extensions: %s\n",
SDL_GetError());
return AVERROR_EXTERNAL;
}
ext = av_calloc(num_ext, sizeof(*ext));
if (!ext) {
ret = AVERROR(ENOMEM);
goto out;
}
SDL_Vulkan_GetInstanceExtensions(window, &num_ext, ext);
entry = av_dict_get(opt, "create_by_placebo", NULL, 0);
if (entry && strtol(entry->value, NULL, 10))
ret = create_vk_by_placebo(renderer, ext, num_ext, opt);
else
ret = create_vk_by_hwcontext(renderer, ext, num_ext, opt);
if (ret < 0)
goto out;
if (!SDL_Vulkan_CreateSurface(window, ctx->inst, &ctx->vk_surface)) {
ret = AVERROR_EXTERNAL;
goto out;
}
ctx->swapchain = pl_vulkan_create_swapchain(
ctx->placebo_vulkan,
pl_vulkan_swapchain_params(
.surface = ctx->vk_surface,
.present_mode = VK_PRESENT_MODE_FIFO_KHR));
if (!ctx->swapchain) {
ret = AVERROR_EXTERNAL;
goto out;
}
SDL_Vulkan_GetDrawableSize(window, &w, &h);
pl_swapchain_resize(ctx->swapchain, &w, &h);
ctx->renderer = pl_renderer_create(ctx->vk_log, ctx->placebo_vulkan->gpu);
if (!ctx->renderer) {
ret = AVERROR_EXTERNAL;
goto out;
}
ctx->vk_frame = av_frame_alloc();
if (!ctx->vk_frame) {
ret = AVERROR(ENOMEM);
goto out;
}
ret = 0;
out:
av_free(ext);
return ret;
}
static int get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
{
RendererContext *ctx = (RendererContext *) renderer;
*dev = ctx->hw_device_ref;
return 0;
}
static int create_hw_frame(VkRenderer *renderer, AVFrame *frame)
{
RendererContext *ctx = (RendererContext *) renderer;
AVHWFramesContext *src_hw_frame = (AVHWFramesContext *)
frame->hw_frames_ctx->data;
AVHWFramesContext *hw_frame;
AVVulkanFramesContext *vk_frame_ctx;
int ret;
if (ctx->hw_frame_ref) {
hw_frame = (AVHWFramesContext *) ctx->hw_frame_ref->data;
if (hw_frame->width == frame->width &&
hw_frame->height == frame->height &&
hw_frame->sw_format == src_hw_frame->sw_format)
return 0;
av_buffer_unref(&ctx->hw_frame_ref);
}
if (!ctx->constraints) {
ctx->constraints = av_hwdevice_get_hwframe_constraints(
ctx->hw_device_ref, NULL);
if (!ctx->constraints)
return AVERROR(ENOMEM);
}
// Check constraints and skip create hwframe. Don't take it as error since
// we can fallback to memory copy from GPU to CPU.
if ((ctx->constraints->max_width &&
ctx->constraints->max_width < frame->width) ||
(ctx->constraints->max_height &&
ctx->constraints->max_height < frame->height) ||
(ctx->constraints->min_width &&
ctx->constraints->min_width > frame->width) ||
(ctx->constraints->min_height &&
ctx->constraints->min_height > frame->height))
return 0;
if (ctx->constraints->valid_sw_formats) {
enum AVPixelFormat *sw_formats = ctx->constraints->valid_sw_formats;
while (*sw_formats != AV_PIX_FMT_NONE) {
if (*sw_formats == src_hw_frame->sw_format)
break;
sw_formats++;
}
if (*sw_formats == AV_PIX_FMT_NONE)
return 0;
}
ctx->hw_frame_ref = av_hwframe_ctx_alloc(ctx->hw_device_ref);
if (!ctx->hw_frame_ref)
return AVERROR(ENOMEM);
hw_frame = (AVHWFramesContext *) ctx->hw_frame_ref->data;
hw_frame->format = AV_PIX_FMT_VULKAN;
hw_frame->sw_format = src_hw_frame->sw_format;
hw_frame->width = frame->width;
hw_frame->height = frame->height;
if (frame->format == AV_PIX_FMT_CUDA) {
vk_frame_ctx = hw_frame->hwctx;
vk_frame_ctx->flags = AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE;
}
ret = av_hwframe_ctx_init(ctx->hw_frame_ref);
if (ret < 0) {
av_log(renderer, AV_LOG_ERROR, "Create hwframe context failed, %s\n",
av_err2str(ret));
return ret;
}
av_hwframe_transfer_get_formats(ctx->hw_frame_ref,
AV_HWFRAME_TRANSFER_DIRECTION_TO,
&ctx->transfer_formats, 0);
return 0;
}
static inline int check_hw_transfer(RendererContext *ctx, AVFrame *frame)
{
if (!ctx->hw_frame_ref || !ctx->transfer_formats)
return 0;
for (int i = 0; ctx->transfer_formats[i] != AV_PIX_FMT_NONE; i++)
if (ctx->transfer_formats[i] == frame->format)
return 1;
return 0;
}
static inline int move_to_output_frame(RendererContext *ctx, AVFrame *frame)
{
int ret = av_frame_copy_props(ctx->vk_frame, frame);
if (ret < 0)
return ret;
av_frame_unref(frame);
av_frame_move_ref(frame, ctx->vk_frame);
return 0;
}
static int map_frame(VkRenderer *renderer, AVFrame *frame, int use_hw_frame)
{
RendererContext *ctx = (RendererContext *) renderer;
int ret;
if (use_hw_frame && !ctx->hw_frame_ref)
return AVERROR(ENOSYS);
// Try map data first
av_frame_unref(ctx->vk_frame);
if (use_hw_frame) {
ctx->vk_frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frame_ref);
ctx->vk_frame->format = AV_PIX_FMT_VULKAN;
}
ret = av_hwframe_map(ctx->vk_frame, frame, 0);
if (!ret)
return move_to_output_frame(ctx, frame);
if (ret != AVERROR(ENOSYS))
av_log(NULL, AV_LOG_FATAL, "Map frame failed: %s\n", av_err2str(ret));
return ret;
}
static int transfer_frame(VkRenderer *renderer, AVFrame *frame, int use_hw_frame)
{
RendererContext *ctx = (RendererContext *) renderer;
int ret;
if (use_hw_frame && !check_hw_transfer(ctx, frame))
return AVERROR(ENOSYS);
av_frame_unref(ctx->vk_frame);
if (use_hw_frame)
av_hwframe_get_buffer(ctx->hw_frame_ref, ctx->vk_frame, 0);
ret = av_hwframe_transfer_data(ctx->vk_frame, frame, 1);
if (!ret)
return move_to_output_frame(ctx, frame);
if (ret != AVERROR(ENOSYS))
av_log(NULL, AV_LOG_FATAL, "Transfer frame failed: %s\n",
av_err2str(ret));
return ret;
}
static int convert_frame(VkRenderer *renderer, AVFrame *frame)
{
int ret;
if (!frame->hw_frames_ctx)
return 0;
if (frame->format == AV_PIX_FMT_VULKAN)
return 0;
ret = create_hw_frame(renderer, frame);
if (ret < 0)
return ret;
for (int use_hw = 1; use_hw >=0; use_hw--) {
ret = map_frame(renderer, frame, use_hw);
if (!ret)
return 0;
if (ret != AVERROR(ENOSYS))
return ret;
ret = transfer_frame(renderer, frame, use_hw);
if (!ret)
return 0;
if (ret != AVERROR(ENOSYS))
return ret;
}
return ret;
}
static int display(VkRenderer *renderer, AVFrame *frame)
{
struct pl_swapchain_frame swap_frame = {0};
struct pl_frame pl_frame = {0};
struct pl_frame target = {0};
RendererContext *ctx = (RendererContext *) renderer;
int ret = 0;
ret = convert_frame(renderer, frame);
if (ret < 0)
return ret;
if (!pl_map_avframe_ex(ctx->placebo_vulkan->gpu, &pl_frame, pl_avframe_params(
.frame = frame,
.tex = ctx->tex))) {
av_log(NULL, AV_LOG_ERROR, "pl_map_avframe_ex failed\n");
return AVERROR_EXTERNAL;
}
if (!pl_swapchain_start_frame(ctx->swapchain, &swap_frame)) {
av_log(NULL, AV_LOG_ERROR, "start frame failed\n");
ret = AVERROR_EXTERNAL;
goto out;
}
pl_frame_from_swapchain(&target, &swap_frame);
if (!pl_render_image(ctx->renderer, &pl_frame, &target,
&pl_render_default_params)) {
av_log(NULL, AV_LOG_ERROR, "pl_render_image failed\n");
ret = AVERROR_EXTERNAL;
goto out;
}
if (!pl_swapchain_submit_frame(ctx->swapchain)) {
av_log(NULL, AV_LOG_ERROR, "pl_swapchain_submit_frame failed\n");
ret = AVERROR_EXTERNAL;
goto out;
}
pl_swapchain_swap_buffers(ctx->swapchain);
out:
pl_unmap_avframe(ctx->placebo_vulkan->gpu, &pl_frame);
return ret;
}
static int resize(VkRenderer *renderer, int width, int height)
{
RendererContext *ctx = (RendererContext *) renderer;
if (!pl_swapchain_resize(ctx->swapchain, &width, &height))
return AVERROR_EXTERNAL;
return 0;
}
static void destroy(VkRenderer *renderer)
{
RendererContext *ctx = (RendererContext *) renderer;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
av_frame_free(&ctx->vk_frame);
av_freep(&ctx->transfer_formats);
av_hwframe_constraints_free(&ctx->constraints);
av_buffer_unref(&ctx->hw_frame_ref);
if (ctx->placebo_vulkan) {
for (int i = 0; i < FF_ARRAY_ELEMS(ctx->tex); i++)
pl_tex_destroy(ctx->placebo_vulkan->gpu, &ctx->tex[i]);
pl_renderer_destroy(&ctx->renderer);
pl_swapchain_destroy(&ctx->swapchain);
pl_vulkan_destroy(&ctx->placebo_vulkan);
}
if (ctx->vk_surface) {
vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)
ctx->get_proc_addr(ctx->inst, "vkDestroySurfaceKHR");
vkDestroySurfaceKHR(ctx->inst, ctx->vk_surface, NULL);
ctx->vk_surface = VK_NULL_HANDLE;
}
av_buffer_unref(&ctx->hw_device_ref);
pl_vk_inst_destroy(&ctx->placebo_instance);
pl_log_destroy(&ctx->vk_log);
}
static const AVClass vulkan_renderer_class = {
.class_name = "Vulkan Renderer",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
};
VkRenderer *vk_get_renderer(void)
{
RendererContext *ctx = av_mallocz(sizeof(*ctx));
VkRenderer *renderer;
if (!ctx)
return NULL;
renderer = &ctx->api;
renderer->class = &vulkan_renderer_class;
renderer->get_hw_dev = get_hw_dev;
renderer->create = create;
renderer->display = display;
renderer->resize = resize;
renderer->destroy = destroy;
return renderer;
}
#else
VkRenderer *vk_get_renderer(void)
{
return NULL;
}
#endif
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
AVDictionary *opt)
{
return renderer->create(renderer, window, opt);
}
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
{
return renderer->get_hw_dev(renderer, dev);
}
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame)
{
return renderer->display(renderer, frame);
}
int vk_renderer_resize(VkRenderer *renderer, int width, int height)
{
return renderer->resize(renderer, width, height);
}
void vk_renderer_destroy(VkRenderer *renderer)
{
renderer->destroy(renderer);
}
@@ -16,17 +16,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef AVCODEC_X86_FFT_H #ifndef FFTOOLS_FFPLAY_RENDERER_H
#define AVCODEC_X86_FFT_H #define FFTOOLS_FFPLAY_RENDERER_H
#include "libavcodec/fft.h" #include <SDL.h>
void ff_fft_permute_sse(FFTContext *s, FFTComplex *z); #include "libavutil/frame.h"
void ff_fft_calc_avx(FFTContext *s, FFTComplex *z);
void ff_fft_calc_sse(FFTContext *s, FFTComplex *z);
void ff_imdct_calc_sse(FFTContext *s, FFTSample *output, const FFTSample *input); typedef struct VkRenderer VkRenderer;
void ff_imdct_half_sse(FFTContext *s, FFTSample *output, const FFTSample *input);
void ff_imdct_half_avx(FFTContext *s, FFTSample *output, const FFTSample *input);
#endif /* AVCODEC_X86_FFT_H */ VkRenderer *vk_get_renderer(void);
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
AVDictionary *opt);
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev);
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame);
int vk_renderer_resize(VkRenderer *renderer, int width, int height);
void vk_renderer_destroy(VkRenderer *renderer);
#endif /* FFTOOLS_FFPLAY_RENDERER_H */
+936 -364
View File
File diff suppressed because it is too large Load Diff
+56 -37
View File
@@ -291,8 +291,6 @@ static void print_codec(const AVCodec *c)
printf("delay "); printf("delay ");
if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)
printf("small "); printf("small ");
if (c->capabilities & AV_CODEC_CAP_SUBFRAMES)
printf("subframes ");
if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL) if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL)
printf("exp "); printf("exp ");
if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF) if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF)
@@ -617,10 +615,10 @@ static void print_codecs_for_id(enum AVCodecID id, int encoder)
void *iter = NULL; void *iter = NULL;
const AVCodec *codec; const AVCodec *codec;
printf(" (%s: ", encoder ? "encoders" : "decoders"); printf(" (%s:", encoder ? "encoders" : "decoders");
while ((codec = next_codec_for_id(id, &iter, encoder))) while ((codec = next_codec_for_id(id, &iter, encoder)))
printf("%s ", codec->name); printf(" %s", codec->name);
printf(")"); printf(")");
} }
@@ -634,7 +632,7 @@ static int compare_codec_desc(const void *a, const void *b)
strcmp((*da)->name, (*db)->name); strcmp((*da)->name, (*db)->name);
} }
static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) static int get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
{ {
const AVCodecDescriptor *desc = NULL; const AVCodecDescriptor *desc = NULL;
const AVCodecDescriptor **codecs; const AVCodecDescriptor **codecs;
@@ -643,7 +641,7 @@ static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
while ((desc = avcodec_descriptor_next(desc))) while ((desc = avcodec_descriptor_next(desc)))
nb_codecs++; nb_codecs++;
if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs))))
report_and_exit(AVERROR(ENOMEM)); return AVERROR(ENOMEM);
desc = NULL; desc = NULL;
while ((desc = avcodec_descriptor_next(desc))) while ((desc = avcodec_descriptor_next(desc)))
codecs[i++] = desc; codecs[i++] = desc;
@@ -668,7 +666,11 @@ static char get_media_type_char(enum AVMediaType type)
int show_codecs(void *optctx, const char *opt, const char *arg) int show_codecs(void *optctx, const char *opt, const char *arg)
{ {
const AVCodecDescriptor **codecs; const AVCodecDescriptor **codecs;
unsigned i, nb_codecs = get_codecs_sorted(&codecs); unsigned i;
int nb_codecs = get_codecs_sorted(&codecs);
if (nb_codecs < 0)
return nb_codecs;
printf("Codecs:\n" printf("Codecs:\n"
" D..... = Decoding supported\n" " D..... = Decoding supported\n"
@@ -690,14 +692,13 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
if (strstr(desc->name, "_deprecated")) if (strstr(desc->name, "_deprecated"))
continue; continue;
printf(" "); printf(" %c%c%c%c%c%c",
printf(avcodec_find_decoder(desc->id) ? "D" : "."); avcodec_find_decoder(desc->id) ? 'D' : '.',
printf(avcodec_find_encoder(desc->id) ? "E" : "."); avcodec_find_encoder(desc->id) ? 'E' : '.',
get_media_type_char(desc->type),
printf("%c", get_media_type_char(desc->type)); (desc->props & AV_CODEC_PROP_INTRA_ONLY) ? 'I' : '.',
printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); (desc->props & AV_CODEC_PROP_LOSSY) ? 'L' : '.',
printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : "."); (desc->props & AV_CODEC_PROP_LOSSLESS) ? 'S' : '.');
printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : ".");
printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : "");
@@ -723,10 +724,13 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
return 0; return 0;
} }
static void print_codecs(int encoder) static int print_codecs(int encoder)
{ {
const AVCodecDescriptor **codecs; const AVCodecDescriptor **codecs;
unsigned i, nb_codecs = get_codecs_sorted(&codecs); int i, nb_codecs = get_codecs_sorted(&codecs);
if (nb_codecs < 0)
return nb_codecs;
printf("%s:\n" printf("%s:\n"
" V..... = Video\n" " V..... = Video\n"
@@ -745,12 +749,13 @@ static void print_codecs(int encoder)
void *iter = NULL; void *iter = NULL;
while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { while ((codec = next_codec_for_id(desc->id, &iter, encoder))) {
printf(" %c", get_media_type_char(desc->type)); printf(" %c%c%c%c%c%c",
printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : "."); get_media_type_char(desc->type),
printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : "."); (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? 'F' : '.',
printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : "."); (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? 'S' : '.',
printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : "."); (codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? 'X' : '.',
printf((codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : "."); (codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND) ? 'B' : '.',
(codec->capabilities & AV_CODEC_CAP_DR1) ? 'D' : '.');
printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
if (strcmp(codec->name, desc->name)) if (strcmp(codec->name, desc->name))
@@ -760,18 +765,17 @@ static void print_codecs(int encoder)
} }
} }
av_free(codecs); av_free(codecs);
return 0;
} }
int show_decoders(void *optctx, const char *opt, const char *arg) int show_decoders(void *optctx, const char *opt, const char *arg)
{ {
print_codecs(0); return print_codecs(0);
return 0;
} }
int show_encoders(void *optctx, const char *opt, const char *arg) int show_encoders(void *optctx, const char *opt, const char *arg)
{ {
print_codecs(1); return print_codecs(1);
return 0;
} }
int show_bsfs(void *optctx, const char *opt, const char *arg) int show_bsfs(void *optctx, const char *opt, const char *arg)
@@ -850,15 +854,22 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
const AVOutputFormat *ofmt = NULL; const AVOutputFormat *ofmt = NULL;
const char *last_name; const char *last_name;
int is_dev; int is_dev;
const char *is_device_placeholder = device_only ? "" : ".";
printf("%s:\n"
" D.%s = Demuxing supported\n"
" .E%s = Muxing supported\n"
"%s"
" ---\n",
device_only ? "Devices" : "Formats",
is_device_placeholder, is_device_placeholder,
device_only ? "": " ..d = Is a device\n");
printf("%s\n"
" D. = Demuxing supported\n"
" .E = Muxing supported\n"
" --\n", device_only ? "Devices:" : "File formats:");
last_name = "000"; last_name = "000";
for (;;) { for (;;) {
int decode = 0; int decode = 0;
int encode = 0; int encode = 0;
int device = 0;
const char *name = NULL; const char *name = NULL;
const char *long_name = NULL; const char *long_name = NULL;
@@ -873,6 +884,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
name = ofmt->name; name = ofmt->name;
long_name = ofmt->long_name; long_name = ofmt->long_name;
encode = 1; encode = 1;
device = is_dev;
} }
} }
} }
@@ -887,20 +899,24 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
name = ifmt->name; name = ifmt->name;
long_name = ifmt->long_name; long_name = ifmt->long_name;
encode = 0; encode = 0;
device = is_dev;
} }
if (name && strcmp(ifmt->name, name) == 0) if (name && strcmp(ifmt->name, name) == 0) {
decode = 1; decode = 1;
device = is_dev;
}
} }
} }
if (!name) if (!name)
break; break;
last_name = name; last_name = name;
printf(" %c%c %-15s %s\n", printf(" %c%c%s %-15s %s\n",
decode ? 'D' : ' ', decode ? 'D' : ' ',
encode ? 'E' : ' ', encode ? 'E' : ' ',
device_only ? "" : (device ? "d" : " "),
name, name,
long_name ? long_name:" "); long_name ? long_name : " ");
} }
return 0; return 0;
} }
@@ -1161,7 +1177,10 @@ int init_report(const char *env, FILE **file)
report_file_level = strtol(val, &tail, 10); report_file_level = strtol(val, &tail, 10);
if (*tail) { if (*tail) {
av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
exit_program(1); av_free(key);
av_free(val);
av_free(filename_template);
return AVERROR(EINVAL);
} }
envlevel = 1; envlevel = 1;
} else { } else {
@@ -1221,7 +1240,7 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg)
max = strtol(arg, &tail, 10); max = strtol(arg, &tail, 10);
if (*tail) { if (*tail) {
av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg);
exit_program(1); return AVERROR(EINVAL);
} }
av_max_alloc(max); av_max_alloc(max);
return 0; return 0;
@@ -1295,7 +1314,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg)
"Possible levels are numbers or:\n", arg); "Possible levels are numbers or:\n", arg);
for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
exit_program(1); return AVERROR(EINVAL);
} }
end: end:
+31 -31
View File
@@ -41,9 +41,9 @@ int show_sources(void *optctx, const char *opt, const char *arg);
#if CONFIG_AVDEVICE #if CONFIG_AVDEVICE
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \ #define CMDUTILS_COMMON_OPTIONS_AVDEVICE \
{ "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \ { "sources" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sources }, \
"list sources of the input device", "device" }, \ "list sources of the input device", "device" }, \
{ "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \ { "sinks" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sinks }, \
"list sinks of the output device", "device" }, \ "list sinks of the output device", "device" }, \
#else #else
@@ -197,35 +197,35 @@ int opt_cpuflags(void *optctx, const char *opt, const char *arg);
int opt_cpucount(void *optctx, const char *opt, const char *arg); int opt_cpucount(void *optctx, const char *opt, const char *arg);
#define CMDUTILS_COMMON_OPTIONS \ #define CMDUTILS_COMMON_OPTIONS \
{ "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \ { "L", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_license }, "show license" }, \
{ "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ { "h", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
{ "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ { "?", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
{ "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ { "help", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
{ "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ { "-help", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
{ "version", OPT_EXIT, { .func_arg = show_version }, "show version" }, \ { "version", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_version }, "show version" }, \
{ "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" }, \ { "buildconf", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_buildconf }, "show build configuration" }, \
{ "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" }, \ { "formats", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_formats }, "show available formats" }, \
{ "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \ { "muxers", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \
{ "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \ { "demuxers", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \
{ "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \ { "devices", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \
{ "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" }, \ { "codecs", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_codecs }, "show available codecs" }, \
{ "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \ { "decoders", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \
{ "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \ { "encoders", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \
{ "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \ { "bsfs", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \
{ "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \ { "protocols", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_protocols }, "show available protocols" }, \
{ "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \ { "filters", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \
{ "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \ { "pix_fmts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \
{ "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \ { "layouts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \
{ "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \ { "sample_fmts", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \
{ "dispositions", OPT_EXIT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \ { "dispositions", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \
{ "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ { "colors", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_colors }, "show available color names" }, \
{ "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ { "loglevel", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
{ "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ { "v", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
{ "report", 0, { .func_arg = opt_report }, "generate a report" }, \ { "report", OPT_TYPE_FUNC, OPT_EXPERT, { .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" }, \ { "max_alloc", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .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" }, \ { "cpuflags", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
{ "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \ { "cpucount", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \
{ "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ { "hide_banner", OPT_TYPE_BOOL, OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
CMDUTILS_COMMON_OPTIONS_AVDEVICE \ CMDUTILS_COMMON_OPTIONS_AVDEVICE \
#endif /* FFTOOLS_OPT_COMMON_H */ #endif /* FFTOOLS_OPT_COMMON_H */
+307 -36
View File
@@ -20,18 +20,59 @@
#include <string.h> #include <string.h>
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/cpu.h"
#include "libavutil/error.h" #include "libavutil/error.h"
#include "libavutil/fifo.h" #include "libavutil/fifo.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "libavutil/samplefmt.h"
#include "libavutil/timestamp.h"
#include "objpool.h" #include "objpool.h"
#include "sync_queue.h" #include "sync_queue.h"
/*
* How this works:
* --------------
* time: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
* -------------------------------------------------------------------
* | | | | | | | | | | | | | |
* |
* stream 0| d=1 d=2 d=1 d=3
* |
*
* stream 1d=1 d=5
*
* |
* stream 2| d=1d=1d=1d=1 <- stream 2 is the head stream of the queue
* |
* ^ ^
* [stream 2 tail] [stream 2 head]
*
* We have N streams (N=3 in the diagram), each stream is a FIFO. The *tail* of
* each FIFO is the frame with smallest end time, the *head* is the frame with
* the largest end time. Frames submitted to the queue with sq_send() are placed
* after the head, frames returned to the caller with sq_receive() are taken
* from the tail.
*
* The head stream of the whole queue (SyncQueue.head_stream) is the limiting
* stream with the *smallest* head timestamp, i.e. the stream whose source lags
* furthest behind all other streams. It determines which frames can be output
* from the queue.
*
* In the diagram, the head stream is 2, because it head time is t=5, while
* streams 0 and 1 end at t=8 and t=9 respectively. All frames that _end_ at
* or before t=5 can be output, i.e. the first 3 frames from stream 0, first
* frame from stream 1, and all 4 frames from stream 2.
*/
typedef struct SyncQueueStream { typedef struct SyncQueueStream {
AVFifo *fifo; AVFifo *fifo;
AVRational tb; AVRational tb;
/* number of audio samples in fifo */
uint64_t samples_queued;
/* stream head: largest timestamp seen */ /* stream head: largest timestamp seen */
int64_t head_ts; int64_t head_ts;
int limiting; int limiting;
@@ -39,12 +80,16 @@ typedef struct SyncQueueStream {
int finished; int finished;
uint64_t frames_sent; uint64_t frames_sent;
uint64_t samples_sent;
uint64_t frames_max; uint64_t frames_max;
int frame_samples;
} SyncQueueStream; } SyncQueueStream;
struct SyncQueue { struct SyncQueue {
enum SyncQueueType type; enum SyncQueueType type;
void *logctx;
/* no more frames will be sent for any stream */ /* no more frames will be sent for any stream */
int finished; int finished;
/* sync head: the stream with the _smallest_ head timestamp /* sync head: the stream with the _smallest_ head timestamp
@@ -61,6 +106,10 @@ struct SyncQueue {
// pool of preallocated frames to avoid constant allocations // pool of preallocated frames to avoid constant allocations
ObjPool *pool; ObjPool *pool;
int have_limiting;
uintptr_t align_mask;
}; };
static void frame_move(const SyncQueue *sq, SyncQueueFrame dst, static void frame_move(const SyncQueue *sq, SyncQueueFrame dst,
@@ -72,22 +121,62 @@ static void frame_move(const SyncQueue *sq, SyncQueueFrame dst,
av_frame_move_ref(dst.f, src.f); av_frame_move_ref(dst.f, src.f);
} }
static int64_t frame_ts(const SyncQueue *sq, SyncQueueFrame frame) /**
* Compute the end timestamp of a frame. If nb_samples is provided, consider
* the frame to have this number of audio samples, otherwise use frame duration.
*/
static int64_t frame_end(const SyncQueue *sq, SyncQueueFrame frame, int nb_samples)
{ {
if (nb_samples) {
int64_t d = av_rescale_q(nb_samples, (AVRational){ 1, frame.f->sample_rate},
frame.f->time_base);
return frame.f->pts + d;
}
return (sq->type == SYNC_QUEUE_PACKETS) ? return (sq->type == SYNC_QUEUE_PACKETS) ?
frame.p->pts + frame.p->duration : frame.p->pts + frame.p->duration :
frame.f->pts + frame.f->duration; frame.f->pts + frame.f->duration;
} }
static int frame_samples(const SyncQueue *sq, SyncQueueFrame frame)
{
return (sq->type == SYNC_QUEUE_PACKETS) ? 0 : frame.f->nb_samples;
}
static int frame_null(const SyncQueue *sq, SyncQueueFrame frame) static int frame_null(const SyncQueue *sq, SyncQueueFrame frame)
{ {
return (sq->type == SYNC_QUEUE_PACKETS) ? (frame.p == NULL) : (frame.f == NULL); return (sq->type == SYNC_QUEUE_PACKETS) ? (frame.p == NULL) : (frame.f == NULL);
} }
static void tb_update(const SyncQueue *sq, SyncQueueStream *st,
const SyncQueueFrame frame)
{
AVRational tb = (sq->type == SYNC_QUEUE_PACKETS) ?
frame.p->time_base : frame.f->time_base;
av_assert0(tb.num > 0 && tb.den > 0);
if (tb.num == st->tb.num && tb.den == st->tb.den)
return;
// timebase should not change after the first frame
av_assert0(!av_fifo_can_read(st->fifo));
if (st->head_ts != AV_NOPTS_VALUE)
st->head_ts = av_rescale_q(st->head_ts, st->tb, tb);
st->tb = tb;
}
static void finish_stream(SyncQueue *sq, unsigned int stream_idx) static void finish_stream(SyncQueue *sq, unsigned int stream_idx)
{ {
SyncQueueStream *st = &sq->streams[stream_idx]; SyncQueueStream *st = &sq->streams[stream_idx];
if (!st->finished)
av_log(sq->logctx, AV_LOG_DEBUG,
"sq: finish %u; head ts %s\n", stream_idx,
av_ts2timestr(st->head_ts, &st->tb));
st->finished = 1; st->finished = 1;
if (st->limiting && st->head_ts != AV_NOPTS_VALUE) { if (st->limiting && st->head_ts != AV_NOPTS_VALUE) {
@@ -105,8 +194,14 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx)
for (unsigned int i = 0; i < sq->nb_streams; i++) { for (unsigned int i = 0; i < sq->nb_streams; i++) {
SyncQueueStream *st1 = &sq->streams[i]; SyncQueueStream *st1 = &sq->streams[i];
if (st != st1 && st1->head_ts != AV_NOPTS_VALUE && if (st != st1 && st1->head_ts != AV_NOPTS_VALUE &&
av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0) av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0) {
if (!st1->finished)
av_log(sq->logctx, AV_LOG_DEBUG,
"sq: finish secondary %u; head ts %s\n", i,
av_ts2timestr(st1->head_ts, &st1->tb));
st1->finished = 1; st1->finished = 1;
}
} }
} }
@@ -116,21 +211,32 @@ static void finish_stream(SyncQueue *sq, unsigned int stream_idx)
return; return;
} }
sq->finished = 1; sq->finished = 1;
av_log(sq->logctx, AV_LOG_DEBUG, "sq: finish queue\n");
} }
static void queue_head_update(SyncQueue *sq) static void queue_head_update(SyncQueue *sq)
{ {
av_assert0(sq->have_limiting);
if (sq->head_stream < 0) { if (sq->head_stream < 0) {
unsigned first_limiting = UINT_MAX;
/* wait for one timestamp in each stream before determining /* wait for one timestamp in each stream before determining
* the queue head */ * the queue head */
for (unsigned int i = 0; i < sq->nb_streams; i++) { for (unsigned int i = 0; i < sq->nb_streams; i++) {
SyncQueueStream *st = &sq->streams[i]; SyncQueueStream *st = &sq->streams[i];
if (st->limiting && st->head_ts == AV_NOPTS_VALUE) if (!st->limiting)
continue;
if (st->head_ts == AV_NOPTS_VALUE)
return; return;
if (first_limiting == UINT_MAX)
first_limiting = i;
} }
// placeholder value, correct one will be found below // placeholder value, correct one will be found below
sq->head_stream = 0; av_assert0(first_limiting < UINT_MAX);
sq->head_stream = first_limiting;
} }
for (unsigned int i = 0; i < sq->nb_streams; i++) { for (unsigned int i = 0; i < sq->nb_streams; i++) {
@@ -203,7 +309,7 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx)
/* get the chosen stream's tail timestamp */ /* get the chosen stream's tail timestamp */
for (size_t i = 0; tail_ts == AV_NOPTS_VALUE && for (size_t i = 0; tail_ts == AV_NOPTS_VALUE &&
av_fifo_peek(st->fifo, &frame, 1, i) >= 0; i++) av_fifo_peek(st->fifo, &frame, 1, i) >= 0; i++)
tail_ts = frame_ts(sq, frame); tail_ts = frame_end(sq, frame, 0);
/* overflow triggers when the tail is over specified duration behind the head */ /* overflow triggers when the tail is over specified duration behind the head */
if (tail_ts == AV_NOPTS_VALUE || tail_ts >= st->head_ts || if (tail_ts == AV_NOPTS_VALUE || tail_ts >= st->head_ts ||
@@ -213,7 +319,7 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx)
/* signal a fake timestamp for all streams that prevent tail_ts from being output */ /* signal a fake timestamp for all streams that prevent tail_ts from being output */
tail_ts++; tail_ts++;
for (unsigned int i = 0; i < sq->nb_streams; i++) { for (unsigned int i = 0; i < sq->nb_streams; i++) {
SyncQueueStream *st1 = &sq->streams[i]; const SyncQueueStream *st1 = &sq->streams[i];
int64_t ts; int64_t ts;
if (st == st1 || st1->finished || if (st == st1 || st1->finished ||
@@ -225,6 +331,9 @@ static int overflow_heartbeat(SyncQueue *sq, int stream_idx)
if (st1->head_ts != AV_NOPTS_VALUE) if (st1->head_ts != AV_NOPTS_VALUE)
ts = FFMAX(st1->head_ts + 1, ts); ts = FFMAX(st1->head_ts + 1, ts);
av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u overflow heardbeat %s -> %s\n",
i, av_ts2timestr(st1->head_ts, &st1->tb), av_ts2timestr(ts, &st1->tb));
stream_update_ts(sq, i, ts); stream_update_ts(sq, i, ts);
} }
@@ -236,27 +345,39 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
SyncQueueStream *st; SyncQueueStream *st;
SyncQueueFrame dst; SyncQueueFrame dst;
int64_t ts; int64_t ts;
int ret; int ret, nb_samples;
av_assert0(stream_idx < sq->nb_streams); av_assert0(stream_idx < sq->nb_streams);
st = &sq->streams[stream_idx]; st = &sq->streams[stream_idx];
av_assert0(st->tb.num > 0 && st->tb.den > 0);
if (frame_null(sq, frame)) { if (frame_null(sq, frame)) {
av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u EOF\n", stream_idx);
finish_stream(sq, stream_idx); finish_stream(sq, stream_idx);
return 0; return 0;
} }
if (st->finished) if (st->finished)
return AVERROR_EOF; return AVERROR_EOF;
tb_update(sq, st, frame);
ret = objpool_get(sq->pool, (void**)&dst); ret = objpool_get(sq->pool, (void**)&dst);
if (ret < 0) if (ret < 0)
return ret; return ret;
frame_move(sq, dst, frame); frame_move(sq, dst, frame);
ts = frame_ts(sq, dst); nb_samples = frame_samples(sq, dst);
// make sure frame duration is consistent with sample count
if (nb_samples) {
av_assert0(dst.f->sample_rate > 0);
dst.f->duration = av_rescale_q(nb_samples, (AVRational){ 1, dst.f->sample_rate },
dst.f->time_base);
}
ts = frame_end(sq, dst, 0);
av_log(sq->logctx, AV_LOG_DEBUG, "sq: send %u ts %s\n", stream_idx,
av_ts2timestr(ts, &st->tb));
ret = av_fifo_write(st->fifo, &dst, 1); ret = av_fifo_write(st->fifo, &dst, 1);
if (ret < 0) { if (ret < 0) {
@@ -267,30 +388,161 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
stream_update_ts(sq, stream_idx, ts); stream_update_ts(sq, stream_idx, ts);
st->frames_sent++; st->samples_queued += nb_samples;
if (st->frames_sent >= st->frames_max) st->samples_sent += nb_samples;
if (st->frame_samples)
st->frames_sent = st->samples_sent / st->frame_samples;
else
st->frames_sent++;
if (st->frames_sent >= st->frames_max) {
av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u frames_max %"PRIu64" reached\n",
stream_idx, st->frames_max);
finish_stream(sq, stream_idx); finish_stream(sq, stream_idx);
}
return 0; return 0;
} }
static void offset_audio(AVFrame *f, int nb_samples)
{
const int planar = av_sample_fmt_is_planar(f->format);
const int planes = planar ? f->ch_layout.nb_channels : 1;
const int bps = av_get_bytes_per_sample(f->format);
const int offset = nb_samples * bps * (planar ? 1 : f->ch_layout.nb_channels);
av_assert0(bps > 0);
av_assert0(nb_samples < f->nb_samples);
for (int i = 0; i < planes; i++) {
f->extended_data[i] += offset;
if (i < FF_ARRAY_ELEMS(f->data))
f->data[i] = f->extended_data[i];
}
f->linesize[0] -= offset;
f->nb_samples -= nb_samples;
f->duration = av_rescale_q(f->nb_samples, (AVRational){ 1, f->sample_rate },
f->time_base);
f->pts += av_rescale_q(nb_samples, (AVRational){ 1, f->sample_rate },
f->time_base);
}
static int frame_is_aligned(const SyncQueue *sq, const AVFrame *frame)
{
// only checks linesize[0], so only works for audio
av_assert0(frame->nb_samples > 0);
av_assert0(sq->align_mask);
// only check data[0], because we always offset all data pointers
// by the same offset, so if one is aligned, all are
if (!((uintptr_t)frame->data[0] & sq->align_mask) &&
!(frame->linesize[0] & sq->align_mask) &&
frame->linesize[0] > sq->align_mask)
return 1;
return 0;
}
static int receive_samples(SyncQueue *sq, SyncQueueStream *st,
AVFrame *dst, int nb_samples)
{
SyncQueueFrame src;
int ret;
av_assert0(st->samples_queued >= nb_samples);
ret = av_fifo_peek(st->fifo, &src, 1, 0);
av_assert0(ret >= 0);
// peeked frame has enough samples and its data is aligned
// -> we can just make a reference and limit its sample count
if (src.f->nb_samples > nb_samples && frame_is_aligned(sq, src.f)) {
ret = av_frame_ref(dst, src.f);
if (ret < 0)
return ret;
dst->nb_samples = nb_samples;
offset_audio(src.f, nb_samples);
st->samples_queued -= nb_samples;
goto finish;
}
// otherwise allocate a new frame and copy the data
ret = av_channel_layout_copy(&dst->ch_layout, &src.f->ch_layout);
if (ret < 0)
return ret;
dst->format = src.f->format;
dst->nb_samples = nb_samples;
ret = av_frame_get_buffer(dst, 0);
if (ret < 0)
goto fail;
ret = av_frame_copy_props(dst, src.f);
if (ret < 0)
goto fail;
dst->nb_samples = 0;
while (dst->nb_samples < nb_samples) {
int to_copy;
ret = av_fifo_peek(st->fifo, &src, 1, 0);
av_assert0(ret >= 0);
to_copy = FFMIN(nb_samples - dst->nb_samples, src.f->nb_samples);
av_samples_copy(dst->extended_data, src.f->extended_data, dst->nb_samples,
0, to_copy, dst->ch_layout.nb_channels, dst->format);
if (to_copy < src.f->nb_samples)
offset_audio(src.f, to_copy);
else {
av_frame_unref(src.f);
objpool_release(sq->pool, (void**)&src);
av_fifo_drain2(st->fifo, 1);
}
st->samples_queued -= to_copy;
dst->nb_samples += to_copy;
}
finish:
dst->duration = av_rescale_q(nb_samples, (AVRational){ 1, dst->sample_rate },
dst->time_base);
return 0;
fail:
av_frame_unref(dst);
return ret;
}
static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx, static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx,
SyncQueueFrame frame) SyncQueueFrame frame)
{ {
SyncQueueStream *st_head = sq->head_stream >= 0 ? const SyncQueueStream *st_head = sq->head_stream >= 0 ?
&sq->streams[sq->head_stream] : NULL; &sq->streams[sq->head_stream] : NULL;
SyncQueueStream *st; SyncQueueStream *st;
av_assert0(stream_idx < sq->nb_streams); av_assert0(stream_idx < sq->nb_streams);
st = &sq->streams[stream_idx]; st = &sq->streams[stream_idx];
if (av_fifo_can_read(st->fifo)) { if (av_fifo_can_read(st->fifo) &&
(st->frame_samples <= st->samples_queued || st->finished)) {
int nb_samples = st->frame_samples;
SyncQueueFrame peek; SyncQueueFrame peek;
int64_t ts; int64_t ts;
int cmp = 1; int cmp = 1;
if (st->finished)
nb_samples = FFMIN(nb_samples, st->samples_queued);
av_fifo_peek(st->fifo, &peek, 1, 0); av_fifo_peek(st->fifo, &peek, 1, 0);
ts = frame_ts(sq, peek); ts = frame_end(sq, peek, nb_samples);
/* check if this stream's tail timestamp does not overtake /* check if this stream's tail timestamp does not overtake
* the overall queue head */ * the overall queue head */
@@ -299,11 +551,28 @@ static int receive_for_stream(SyncQueue *sq, unsigned int stream_idx,
/* We can release frames that do not end after the queue head. /* We can release frames that do not end after the queue head.
* Frames with no timestamps are just passed through with no conditions. * Frames with no timestamps are just passed through with no conditions.
* Frames are also passed through when there are no limiting streams.
*/ */
if (cmp <= 0 || ts == AV_NOPTS_VALUE) { if (cmp <= 0 || ts == AV_NOPTS_VALUE || !sq->have_limiting) {
frame_move(sq, frame, peek); if (nb_samples &&
objpool_release(sq->pool, (void**)&peek); (nb_samples != peek.f->nb_samples || !frame_is_aligned(sq, peek.f))) {
av_fifo_drain2(st->fifo, 1); int ret = receive_samples(sq, st, frame.f, nb_samples);
if (ret < 0)
return ret;
} else {
frame_move(sq, frame, peek);
objpool_release(sq->pool, (void**)&peek);
av_fifo_drain2(st->fifo, 1);
av_assert0(st->samples_queued >= frame_samples(sq, frame));
st->samples_queued -= frame_samples(sq, frame);
}
av_log(sq->logctx, AV_LOG_DEBUG,
"sq: receive %u ts %s queue head %d ts %s\n", stream_idx,
av_ts2timestr(frame_end(sq, frame, 0), &st->tb),
sq->head_stream,
st_head ? av_ts2timestr(st_head->head_ts, &st_head->tb) : "N/A");
return 0; return 0;
} }
} }
@@ -372,24 +641,11 @@ int sq_add_stream(SyncQueue *sq, int limiting)
st->frames_max = UINT64_MAX; st->frames_max = UINT64_MAX;
st->limiting = limiting; st->limiting = limiting;
sq->have_limiting |= limiting;
return sq->nb_streams++; return sq->nb_streams++;
} }
void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb)
{
SyncQueueStream *st;
av_assert0(stream_idx < sq->nb_streams);
st = &sq->streams[stream_idx];
av_assert0(!av_fifo_can_read(st->fifo));
if (st->head_ts != AV_NOPTS_VALUE)
st->head_ts = av_rescale_q(st->head_ts, st->tb, tb);
st->tb = tb;
}
void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames) void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames)
{ {
SyncQueueStream *st; SyncQueueStream *st;
@@ -402,7 +658,21 @@ void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames)
finish_stream(sq, stream_idx); finish_stream(sq, stream_idx);
} }
SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us) void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx,
int frame_samples)
{
SyncQueueStream *st;
av_assert0(sq->type == SYNC_QUEUE_FRAMES);
av_assert0(stream_idx < sq->nb_streams);
st = &sq->streams[stream_idx];
st->frame_samples = frame_samples;
sq->align_mask = av_cpu_max_align() - 1;
}
SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx)
{ {
SyncQueue *sq = av_mallocz(sizeof(*sq)); SyncQueue *sq = av_mallocz(sizeof(*sq));
@@ -411,6 +681,7 @@ SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us)
sq->type = type; sq->type = type;
sq->buf_size_us = buf_size_us; sq->buf_size_us = buf_size_us;
sq->logctx = logctx;
sq->head_stream = -1; sq->head_stream = -1;
sq->head_finished_stream = -1; sq->head_finished_stream = -1;
+16 -7
View File
@@ -38,6 +38,11 @@ typedef union SyncQueueFrame {
#define SQFRAME(frame) ((SyncQueueFrame){ .f = (frame) }) #define SQFRAME(frame) ((SyncQueueFrame){ .f = (frame) })
#define SQPKT(pkt) ((SyncQueueFrame){ .p = (pkt) }) #define SQPKT(pkt) ((SyncQueueFrame){ .p = (pkt) })
/**
* A sync queue provides timestamp synchronization between multiple streams.
* Some of these streams are marked as "limiting", then the queue ensures no
* stream gets ahead of any of the limiting streams.
*/
typedef struct SyncQueue SyncQueue; typedef struct SyncQueue SyncQueue;
/** /**
@@ -45,7 +50,7 @@ typedef struct SyncQueue SyncQueue;
* *
* @param buf_size_us maximum duration that will be buffered in microseconds * @param buf_size_us maximum duration that will be buffered in microseconds
*/ */
SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us); SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx);
void sq_free(SyncQueue **sq); void sq_free(SyncQueue **sq);
/** /**
@@ -59,12 +64,6 @@ void sq_free(SyncQueue **sq);
*/ */
int sq_add_stream(SyncQueue *sq, int limiting); int sq_add_stream(SyncQueue *sq, int limiting);
/**
* Set the timebase for the stream with index stream_idx. Should be called
* before sending any frames for this stream.
*/
void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb);
/** /**
* Limit the number of output frames for stream with index stream_idx * Limit the number of output frames for stream with index stream_idx
* to max_frames. * to max_frames.
@@ -72,6 +71,16 @@ void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb);
void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx,
uint64_t max_frames); uint64_t max_frames);
/**
* Set a constant output audio frame size, in samples. Can only be used with
* SYNC_QUEUE_FRAMES queues and audio streams.
*
* All output frames will have exactly frame_samples audio samples, except
* possibly for the last one, which may have fewer.
*/
void sq_frame_samples(SyncQueue *sq, unsigned int stream_idx,
int frame_samples);
/** /**
* Submit a frame for the stream with index stream_idx. * Submit a frame for the stream with index stream_idx.
* *
+14 -5
View File
@@ -164,7 +164,12 @@ static int receive_locked(ThreadQueue *tq, int *stream_idx,
FifoElem elem; FifoElem elem;
unsigned int nb_finished = 0; unsigned int nb_finished = 0;
if (av_fifo_read(tq->fifo, &elem, 1) >= 0) { while (av_fifo_read(tq->fifo, &elem, 1) >= 0) {
if (tq->finished[elem.stream_idx] & FINISHED_RECV) {
objpool_release(tq->obj_pool, &elem.obj);
continue;
}
tq->obj_move(data, elem.obj); tq->obj_move(data, elem.obj);
objpool_release(tq->obj_pool, &elem.obj); objpool_release(tq->obj_pool, &elem.obj);
*stream_idx = elem.stream_idx; *stream_idx = elem.stream_idx;
@@ -172,7 +177,7 @@ static int receive_locked(ThreadQueue *tq, int *stream_idx,
} }
for (unsigned int i = 0; i < tq->nb_streams; i++) { for (unsigned int i = 0; i < tq->nb_streams; i++) {
if (!(tq->finished[i] & FINISHED_SEND)) if (!tq->finished[i])
continue; continue;
/* return EOF to the consumer at most once for each stream */ /* return EOF to the consumer at most once for each stream */
@@ -197,7 +202,14 @@ int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
pthread_mutex_lock(&tq->lock); pthread_mutex_lock(&tq->lock);
while (1) { while (1) {
size_t can_read = av_fifo_can_read(tq->fifo);
ret = receive_locked(tq, stream_idx, data); ret = receive_locked(tq, stream_idx, data);
// signal other threads if the fifo state changed
if (can_read != av_fifo_can_read(tq->fifo))
pthread_cond_broadcast(&tq->cond);
if (ret == AVERROR(EAGAIN)) { if (ret == AVERROR(EAGAIN)) {
pthread_cond_wait(&tq->cond, &tq->lock); pthread_cond_wait(&tq->cond, &tq->lock);
continue; continue;
@@ -206,9 +218,6 @@ int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
break; break;
} }
if (ret == 0)
pthread_cond_broadcast(&tq->cond);
pthread_mutex_unlock(&tq->lock); pthread_mutex_unlock(&tq->lock);
return ret; return ret;
+1 -1
View File
@@ -65,7 +65,7 @@ static int zero12v_decode_frame(AVCodecContext *avctx, AVFrame *pic,
return ret; return ret;
pic->pict_type = AV_PICTURE_TYPE_I; pic->pict_type = AV_PICTURE_TYPE_I;
pic->key_frame = 1; pic->flags |= AV_FRAME_FLAG_KEY;
line_end = avpkt->data + stride; line_end = avpkt->data + stride;
for (line = 0; line < avctx->height; line++) { for (line = 0; line < avctx->height; line++) {
+14 -13
View File
@@ -125,7 +125,7 @@ static const uint8_t dequant_table[64] = {
20, 35, 34, 32, 31, 22, 15, 8, 20, 35, 34, 32, 31, 22, 15, 8,
}; };
static VLC block_type_vlc[2][4]; static VLCElem block_type_vlc[2][4][32];
typedef struct CFrameBuffer { typedef struct CFrameBuffer {
@@ -250,17 +250,15 @@ static void idct(int16_t block[64])
static av_cold void init_vlcs(void) static av_cold void init_vlcs(void)
{ {
static VLCElem table[2][4][32];
int i, j; int i, j;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
block_type_vlc[i][j].table = table[i][j]; ff_vlc_init_table_sparse(block_type_vlc[i][j], FF_ARRAY_ELEMS(block_type_vlc[i][j]),
block_type_vlc[i][j].table_allocated = 32; BLOCK_TYPE_VLC_BITS, 7,
init_vlc(&block_type_vlc[i][j], BLOCK_TYPE_VLC_BITS, 7, &block_type_tab[i][j][0][1], 2, 1,
&block_type_tab[i][j][0][1], 2, 1, &block_type_tab[i][j][0][0], 2, 1,
&block_type_tab[i][j][0][0], 2, 1, NULL, 0, 0, 0);
INIT_VLC_USE_NEW_STATIC);
} }
} }
} }
@@ -357,7 +355,7 @@ static int decode_p_block(FourXContext *f, uint16_t *dst, const uint16_t *src,
if (get_bits_left(&f->gb) < 1) if (get_bits_left(&f->gb) < 1)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
h = 1 << log2h; h = 1 << log2h;
code = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index].table, code = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index],
BLOCK_TYPE_VLC_BITS, 1); BLOCK_TYPE_VLC_BITS, 1);
av_assert0(code >= 0 && code <= 6); av_assert0(code >= 0 && code <= 6);
@@ -706,8 +704,8 @@ static const uint8_t *read_huffman_tables(FourXContext *f,
len_tab[j] = len; len_tab[j] = len;
} }
ff_free_vlc(&f->pre_vlc); ff_vlc_free(&f->pre_vlc);
if (init_vlc(&f->pre_vlc, ACDC_VLC_BITS, 257, len_tab, 1, 1, if (vlc_init(&f->pre_vlc, ACDC_VLC_BITS, 257, len_tab, 1, 1,
bits_tab, 4, 4, 0)) bits_tab, 4, 4, 0))
return NULL; return NULL;
@@ -959,7 +957,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture,
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
picture->key_frame = picture->pict_type == AV_PICTURE_TYPE_I; if (picture->pict_type == AV_PICTURE_TYPE_I)
picture->flags |= AV_FRAME_FLAG_KEY;
else
picture->flags &= ~AV_FRAME_FLAG_KEY;
av_image_copy_plane(picture->data[0], picture->linesize[0], av_image_copy_plane(picture->data[0], picture->linesize[0],
(const uint8_t*)f->frame_buffer, avctx->width * 2, (const uint8_t*)f->frame_buffer, avctx->width * 2,
@@ -984,7 +985,7 @@ static av_cold int decode_end(AVCodecContext *avctx)
av_freep(&f->cfrm[i].data); av_freep(&f->cfrm[i].data);
f->cfrm[i].allocated_size = 0; f->cfrm[i].allocated_size = 0;
} }
ff_free_vlc(&f->pre_vlc); ff_vlc_free(&f->pre_vlc);
return 0; return 0;
} }
+41 -44
View File
@@ -26,27 +26,23 @@
* http://www.pcisys.net/~melanson/codecs/ * http://www.pcisys.net/~melanson/codecs/
* *
* Supports: PAL8 (RGB 8bpp, paletted) * Supports: PAL8 (RGB 8bpp, paletted)
* : BGR24 (RGB 24bpp) (can also output it as RGB32) * : GBRP (RGB 24bpp)
* : RGB32 (RGB 32bpp, 4th plane is alpha) * : GBRAP (RGB 32bpp, 4th plane is alpha)
*/ */
#include <string.h> #include <string.h>
#include "libavutil/bswap.h" #include "libavutil/intreadwrite.h"
#include "libavutil/internal.h" #include "libavutil/internal.h"
#include "avcodec.h" #include "avcodec.h"
#include "codec_internal.h" #include "codec_internal.h"
#include "decode.h" #include "decode.h"
static const enum AVPixelFormat pixfmt_rgb24[] = {
AV_PIX_FMT_BGR24, AV_PIX_FMT_0RGB32, AV_PIX_FMT_NONE };
typedef struct EightBpsContext { typedef struct EightBpsContext {
AVCodecContext *avctx; AVCodecContext *avctx;
unsigned char planes; uint8_t planes;
unsigned char planemap[4]; uint8_t planemap[4];
uint32_t pal[256]; uint32_t pal[256];
} EightBpsContext; } EightBpsContext;
@@ -57,18 +53,17 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
const uint8_t *buf = avpkt->data; const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size; int buf_size = avpkt->size;
EightBpsContext * const c = avctx->priv_data; EightBpsContext * const c = avctx->priv_data;
const unsigned char *encoded = buf; const uint8_t *encoded = buf;
unsigned char *pixptr, *pixptr_end; uint8_t *pixptr, *pixptr_end;
unsigned int height = avctx->height; // Real image height unsigned int height = avctx->height; // Real image height
unsigned int dlen, p, row; unsigned int dlen, p, row;
const unsigned char *lp, *dp, *ep; const uint8_t *lp, *dp, *ep;
unsigned char count; uint8_t count;
unsigned int px_inc; const uint8_t *planemap = c->planemap;
unsigned int planes = c->planes; unsigned int planes = c->planes;
unsigned char *planemap = c->planemap;
int ret; int ret;
if (buf_size < planes * height * 2) if (buf_size < planes * height * (2 + 2*((avctx->width+128)/129)))
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
@@ -79,19 +74,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
/* Set data pointer after line lengths */ /* Set data pointer after line lengths */
dp = encoded + planes * (height << 1); dp = encoded + planes * (height << 1);
px_inc = planes + (avctx->pix_fmt == AV_PIX_FMT_0RGB32);
for (p = 0; p < planes; p++) { for (p = 0; p < planes; p++) {
const int pi = planemap[p];
/* Lines length pointer for this plane */ /* Lines length pointer for this plane */
lp = encoded + p * (height << 1); lp = encoded + p * (height << 1);
/* Decode a plane */ /* Decode a plane */
for (row = 0; row < height; row++) { for (row = 0; row < height; row++) {
pixptr = frame->data[0] + row * frame->linesize[0] + planemap[p]; pixptr = frame->data[pi] + row * frame->linesize[pi];
pixptr_end = pixptr + frame->linesize[0]; pixptr_end = pixptr + frame->linesize[pi];
if (ep - lp < row * 2 + 2) if (ep - lp < row * 2 + 2)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2)); dlen = AV_RB16(lp + row * 2);
/* Decode a row of this plane */ /* Decode a row of this plane */
while (dlen > 0) { while (dlen > 0) {
if (ep - dp <= 1) if (ep - dp <= 1)
@@ -99,22 +93,19 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
if ((count = *dp++) <= 127) { if ((count = *dp++) <= 127) {
count++; count++;
dlen -= count + 1; dlen -= count + 1;
if (pixptr_end - pixptr < count * px_inc) if (pixptr_end - pixptr < count)
break; break;
if (ep - dp < count) if (ep - dp < count)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
while (count--) { memcpy(pixptr, dp, count);
*pixptr = *dp++; pixptr += count;
pixptr += px_inc; dp += count;
}
} else { } else {
count = 257 - count; count = 257 - count;
if (pixptr_end - pixptr < count * px_inc) if (pixptr_end - pixptr < count)
break; break;
while (count--) { memset(pixptr, dp[0], count);
*pixptr = *dp; pixptr += count;
pixptr += px_inc;
}
dp++; dp++;
dlen -= 2; dlen -= 2;
} }
@@ -123,9 +114,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
} }
if (avctx->bits_per_coded_sample <= 8) { if (avctx->bits_per_coded_sample <= 8) {
frame->palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx); #if FF_API_PALETTE_HAS_CHANGED
FF_DISABLE_DEPRECATION_WARNINGS
frame->palette_has_changed =
#endif
ff_copy_palette(c->pal, avpkt, avctx);
#if FF_API_PALETTE_HAS_CHANGED
FF_ENABLE_DEPRECATION_WARNINGS
#endif
memcpy (frame->data[1], c->pal, AVPALETTE_SIZE); memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
} }
*got_frame = 1; *got_frame = 1;
@@ -147,16 +145,15 @@ static av_cold int decode_init(AVCodecContext *avctx)
c->planemap[0] = 0; // 1st plane is palette indexes c->planemap[0] = 0; // 1st plane is palette indexes
break; break;
case 24: case 24:
avctx->pix_fmt = ff_get_format(avctx, pixfmt_rgb24); avctx->pix_fmt = AV_PIX_FMT_GBRP;
c->planes = 3; c->planes = 3;
c->planemap[0] = 2; // 1st plane is red c->planemap[0] = 2; // 1st plane is red
c->planemap[1] = 1; // 2nd plane is green c->planemap[1] = 0; // 2nd plane is green
c->planemap[2] = 0; // 3rd plane is blue c->planemap[2] = 1; // 3rd plane is blue
break; break;
case 32: case 32:
avctx->pix_fmt = AV_PIX_FMT_RGB32; avctx->pix_fmt = AV_PIX_FMT_GBRAP;
c->planes = 4; c->planes = 4;
/* handle planemap setup later for decoding rgb24 data as rbg32 */
break; break;
default: default:
av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n",
@@ -164,11 +161,11 @@ static av_cold int decode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
if (avctx->pix_fmt == AV_PIX_FMT_RGB32) { if (avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
c->planemap[0] = HAVE_BIGENDIAN ? 1 : 2; // 1st plane is red c->planemap[0] = 2; // 1st plane is red
c->planemap[1] = HAVE_BIGENDIAN ? 2 : 1; // 2nd plane is green c->planemap[1] = 0; // 2nd plane is green
c->planemap[2] = HAVE_BIGENDIAN ? 3 : 0; // 3rd plane is blue c->planemap[2] = 1; // 3rd plane is blue
c->planemap[3] = HAVE_BIGENDIAN ? 0 : 3; // 4th plane is alpha c->planemap[3] = 3; // 4th plane is alpha
} }
return 0; return 0;
} }
+70 -82
View File
@@ -25,13 +25,13 @@ HEADERS = ac3_parser.h \
version_major.h \ version_major.h \
videotoolbox.h \ videotoolbox.h \
vorbis_parser.h \ vorbis_parser.h \
xvmc.h \
OBJS = ac3_parser.o \ OBJS = ac3_parser.o \
adts_parser.o \ adts_parser.o \
allcodecs.o \ allcodecs.o \
avcodec.o \ avcodec.o \
avdct.o \ avdct.o \
avfft.o \
avpacket.o \ avpacket.o \
bitstream.o \ bitstream.o \
bitstream_filters.o \ bitstream_filters.o \
@@ -55,6 +55,7 @@ OBJS = ac3_parser.o \
profiles.o \ profiles.o \
qsv_api.o \ qsv_api.o \
raw.o \ raw.o \
refstruct.o \
utils.o \ utils.o \
version.o \ version.o \
vlc.o \ vlc.o \
@@ -62,6 +63,8 @@ OBJS = ac3_parser.o \
xiph.o \ xiph.o \
# subsystems # subsystems
include $(SRC_PATH)/libavcodec/vvc/Makefile
-include $(SRC_PATH)/libavcodec/$(ARCH)/vvc/Makefile
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o
OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o
@@ -76,21 +79,19 @@ OBJS-$(CONFIG_CBS) += cbs.o cbs_bsf.o
OBJS-$(CONFIG_CBS_AV1) += cbs_av1.o OBJS-$(CONFIG_CBS_AV1) += cbs_av1.o
OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o cbs_sei.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_H265) += cbs_h2645.o cbs_sei.o h2645_parse.o
OBJS-$(CONFIG_CBS_H266) += cbs_h2645.o cbs_sei.o h2645_parse.o
OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o
OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o
OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o
OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
OBJS-$(CONFIG_EVCPARSE) += evc_parse.o evc_ps.o
OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o
OBJS-$(CONFIG_FAANDCT) += faandct.o OBJS-$(CONFIG_FAANDCT) += faandct.o
OBJS-$(CONFIG_FAANIDCT) += faanidct.o OBJS-$(CONFIG_FAANIDCT) += faanidct.o
OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o jfdctfst.o jfdctint.o OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o jfdctfst.o jfdctint.o
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_FMTCONVERT) += fmtconvert.o OBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o
OBJS-$(CONFIG_GOLOMB) += golomb.o OBJS-$(CONFIG_GOLOMB) += golomb.o
OBJS-$(CONFIG_H263DSP) += h263dsp.o OBJS-$(CONFIG_H263DSP) += h263dsp.o
@@ -104,7 +105,7 @@ OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o
OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o hevc_ps.o hevc_data.o \ OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o hevc_ps.o hevc_data.o \
h2645data.o h2645_parse.o h2645_vui.o h2645data.o h2645_parse.o h2645_vui.o
OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o h2645_sei.o \ OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o h2645_sei.o \
dynamic_hdr10_plus.o dynamic_hdr_vivid.o dynamic_hdr_vivid.o aom_film_grain.o
OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o
OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFMAN) += huffman.o
OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o
@@ -123,7 +124,6 @@ OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o
OBJS-$(CONFIG_LPC) += lpc.o OBJS-$(CONFIG_LPC) += lpc.o
OBJS-$(CONFIG_LSP) += lsp.o OBJS-$(CONFIG_LSP) += lsp.o
OBJS-$(CONFIG_LZF) += lzf.o OBJS-$(CONFIG_LZF) += lzf.o
OBJS-$(CONFIG_MDCT) += mdct_float.o mdct_fixed_32.o
OBJS-$(CONFIG_ME_CMP) += me_cmp.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_MEDIACODEC) += mediacodecdec_common.o mediacodec_surface.o mediacodec_wrapper.o mediacodec_sw_buffer.o
OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o
@@ -132,7 +132,8 @@ OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o \
OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \
mpegaudiodsp_data.o \ mpegaudiodsp_data.o \
mpegaudiodsp_fixed.o \ mpegaudiodsp_fixed.o \
mpegaudiodsp_float.o mpegaudiodsp_float.o \
dct32_fixed.o dct32_float.o
OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o
OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o
OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o rl.o \ OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o rl.o \
@@ -154,7 +155,6 @@ OBJS-$(CONFIG_QSV) += qsv.o
OBJS-$(CONFIG_QSVDEC) += qsvdec.o OBJS-$(CONFIG_QSVDEC) += qsvdec.o
OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_QSVENC) += qsvenc.o
OBJS-$(CONFIG_RANGECODER) += rangecoder.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o
OBJS-$(CONFIG_RDFT) += rdft.o
OBJS-$(CONFIG_RV34DSP) += rv34dsp.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o
OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_SINEWIN) += sinewin.o
OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_SNAPPY) += snappy.o
@@ -177,10 +177,12 @@ OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \ OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aacdec_common.o aactab.o \
aacsbr.o aacps_common.o aacps_float.o \
kbdwin.o \ kbdwin.o \
sbrdsp.o aacpsdsp_float.o cbrt_data.o sbrdsp.o aacpsdsp_float.o cbrt_data.o
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \ OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aacdec_common.o aactab.o \
aacsbr_fixed.o aacps_common.o aacps_fixed.o \
kbdwin.o \ kbdwin.o \
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
@@ -250,11 +252,13 @@ OBJS-$(CONFIG_ATRAC3PAL_DECODER) += atrac3plusdec.o atrac3plus.o \
OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o
OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
OBJS-$(CONFIG_AURA2_DECODER) += aura.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o
OBJS-$(CONFIG_AV1_VAAPI_ENCODER) += vaapi_encode_av1.o av1_levels.o
OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
@@ -336,6 +340,7 @@ OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o
OBJS-$(CONFIG_DXA_DECODER) += dxa.o OBJS-$(CONFIG_DXA_DECODER) += dxa.o
OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o
OBJS-$(CONFIG_DXV_DECODER) += dxv.o OBJS-$(CONFIG_DXV_DECODER) += dxv.o
OBJS-$(CONFIG_DXV_ENCODER) += dxvenc.o
OBJS-$(CONFIG_EAC3_DECODER) += eac3_data.o OBJS-$(CONFIG_EAC3_DECODER) += eac3_data.o
OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o
OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o
@@ -427,7 +432,7 @@ OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
hevc_cabac.o hevc_refs.o hevcpred.o \ hevc_cabac.o hevc_refs.o hevcpred.o \
hevcdsp.o hevc_filter.o hevc_data.o \ hevcdsp.o hevc_filter.o hevc_data.o \
h274.o h274.o aom_film_grain.o
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
@@ -444,8 +449,7 @@ OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadsp.o canopus.o
canopus.o
OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o hqxdsp.o canopus.o OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o hqxdsp.o canopus.o
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o
@@ -469,13 +473,14 @@ OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o
OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \
jpeg2000dwt.o jpeg2000dwt.o
OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \ OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \
jpeg2000dwt.o mqcdec.o mqc.o jpeg2000dwt.o mqcdec.o mqc.o jpeg2000htdec.o
OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o
OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o
OBJS-$(CONFIG_JV_DECODER) += jvdec.o OBJS-$(CONFIG_JV_DECODER) += jvdec.o
OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
OBJS-$(CONFIG_LEAD_DECODER) += leaddec.o jpegquanttables.o
OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o
OBJS-$(CONFIG_LOCO_DECODER) += loco.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o
OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o
@@ -542,6 +547,7 @@ OBJS-$(CONFIG_MPEG4_DECODER) += mpeg4videodsp.o xvididct.o
OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o
OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_MPEG4_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o
OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
@@ -550,6 +556,7 @@ OBJS-$(CONFIG_MSA1_DECODER) += mss3.o
OBJS-$(CONFIG_MSCC_DECODER) += mscc.o OBJS-$(CONFIG_MSCC_DECODER) += mscc.o
OBJS-$(CONFIG_MSNSIREN_DECODER) += siren.o OBJS-$(CONFIG_MSNSIREN_DECODER) += siren.o
OBJS-$(CONFIG_MSP2_DECODER) += msp2dec.o OBJS-$(CONFIG_MSP2_DECODER) += msp2dec.o
OBJS-$(CONFIG_MSRLE_ENCODER) += msrleenc.o
OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o
OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o
OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o wmv2data.o OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o wmv2data.o
@@ -574,6 +581,7 @@ OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opusdec_celt.o opus_celt.o \
opusdsp.o opus_parse.o opus_rc.o opusdsp.o opus_parse.o opus_rc.o
OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opusenc_psy.o opus_celt.o \ OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opusenc_psy.o opus_celt.o \
opus_pvq.o opus_rc.o opustab.o opus_pvq.o opus_rc.o opustab.o
OBJS-$(CONFIG_OSQ_DECODER) += osq.o
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o
OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o
OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o
@@ -582,6 +590,7 @@ OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o
OBJS-$(CONFIG_PCX_DECODER) += pcx.o OBJS-$(CONFIG_PCX_DECODER) += pcx.o
OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o
OBJS-$(CONFIG_PDV_DECODER) += pdvdec.o
OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o
OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o
@@ -614,6 +623,7 @@ OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o \
OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o
OBJS-$(CONFIG_QDMC_DECODER) += qdmc.o OBJS-$(CONFIG_QDMC_DECODER) += qdmc.o
OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o
OBJS-$(CONFIG_QOA_DECODER) += qoadec.o
OBJS-$(CONFIG_QOI_DECODER) += qoidec.o OBJS-$(CONFIG_QOI_DECODER) += qoidec.o
OBJS-$(CONFIG_QOI_ENCODER) += qoienc.o OBJS-$(CONFIG_QOI_ENCODER) += qoienc.o
OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o
@@ -640,6 +650,7 @@ OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o
OBJS-$(CONFIG_RPZA_DECODER) += rpza.o OBJS-$(CONFIG_RPZA_DECODER) += rpza.o
OBJS-$(CONFIG_RPZA_ENCODER) += rpzaenc.o OBJS-$(CONFIG_RPZA_ENCODER) += rpzaenc.o
OBJS-$(CONFIG_RSCC_DECODER) += rscc.o OBJS-$(CONFIG_RSCC_DECODER) += rscc.o
OBJS-$(CONFIG_RTV1_DECODER) += rtv1.o
OBJS-$(CONFIG_RV10_DECODER) += rv10.o OBJS-$(CONFIG_RV10_DECODER) += rv10.o
OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o
OBJS-$(CONFIG_RV20_DECODER) += rv10.o OBJS-$(CONFIG_RV20_DECODER) += rv10.o
@@ -749,6 +760,7 @@ OBJS-$(CONFIG_VC2_ENCODER) += vc2enc.o vc2enc_dwt.o diractab.o
OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdaudio.o OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdaudio.o
OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdvideo.o OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdvideo.o
OBJS-$(CONFIG_VMIX_DECODER) += vmixdec.o
OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o
OBJS-$(CONFIG_VNULL_DECODER) += null.o OBJS-$(CONFIG_VNULL_DECODER) += null.o
OBJS-$(CONFIG_VNULL_ENCODER) += null.o OBJS-$(CONFIG_VNULL_ENCODER) += null.o
@@ -760,10 +772,11 @@ OBJS-$(CONFIG_VP3_DECODER) += vp3.o jpegquanttables.o
OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vpx_rac.o OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vpx_rac.o
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \ OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \
vp6dsp.o vpx_rac.o vp6dsp.o vpx_rac.o
OBJS-$(CONFIG_VP7_DECODER) += vp8.o vpx_rac.o OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp8data.o vpx_rac.o
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vpx_rac.o OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8data.o vpx_rac.o
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_VP8_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o
OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o
@@ -774,6 +787,7 @@ OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9r
vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_VP9_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o
OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o
@@ -972,32 +986,40 @@ OBJS-$(CONFIG_ADPCM_ZORK_DECODER) += adpcm.o adpcm_data.o
# hardware accelerators # hardware accelerators
OBJS-$(CONFIG_D3D11VA) += dxva2.o OBJS-$(CONFIG_D3D11VA) += dxva2.o
OBJS-$(CONFIG_D3D12VA) += dxva2.o d3d12va_decode.o
OBJS-$(CONFIG_DXVA2) += dxva2.o OBJS-$(CONFIG_DXVA2) += dxva2.o
OBJS-$(CONFIG_NVDEC) += nvdec.o OBJS-$(CONFIG_NVDEC) += nvdec.o
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o
OBJS-$(CONFIG_VDPAU) += vdpau.o OBJS-$(CONFIG_VDPAU) += vdpau.o
OBJS-$(CONFIG_VULKAN) += vulkan.o vulkan_video.o
OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o
OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o
OBJS-$(CONFIG_AV1_D3D12VA_HWACCEL) += dxva2_av1.o d3d12va_av1.o
OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o
OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o
OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o
OBJS-$(CONFIG_AV1_VULKAN_HWACCEL) += vulkan_decode.o vulkan_av1.o
OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o
OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_D3D12VA_HWACCEL) += dxva2_h264.o d3d12va_h264.o
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
OBJS-$(CONFIG_H264_VULKAN_HWACCEL) += vulkan_decode.o vulkan_h264.o
OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_D3D12VA_HWACCEL) += dxva2_hevc.o d3d12va_hevc.o
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.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_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o
OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL) += vulkan_decode.o vulkan_hevc.o
OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o
OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o
OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o
@@ -1005,6 +1027,7 @@ OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_D3D12VA_HWACCEL) += dxva2_mpeg2.o d3d12va_mpeg2.o
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
@@ -1016,6 +1039,7 @@ OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
OBJS-$(CONFIG_VC1_D3D12VA_HWACCEL) += dxva2_vc1.o d3d12va_vc1.o
OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o
OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
@@ -1024,6 +1048,7 @@ OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o
OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o
OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o
OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o
OBJS-$(CONFIG_VP9_D3D12VA_HWACCEL) += dxva2_vp9.o d3d12va_vp9.o
OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o
OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o
@@ -1042,6 +1067,9 @@ STLIBOBJS-$(CONFIG_AVFORMAT) += to_upper4.o
STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o
STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o
STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o
STLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o
STLIBOBJS-$(CONFIG_JNI) += ffjni.o
STLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o
@@ -1079,10 +1107,11 @@ OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o
OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o
OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o av1_parse.o
OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o OBJS-$(CONFIG_LIBDAVS2_DECODER) += libdavs2.o
OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o
OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o
@@ -1101,7 +1130,6 @@ OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENH264_DECODER) += libopenh264dec.o libopenh264.o OBJS-$(CONFIG_LIBOPENH264_DECODER) += libopenh264dec.o libopenh264.o
OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o libopenh264.o OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o libopenh264.o
OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o
OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o
OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \
vorbis_data.o vorbis_data.o
@@ -1121,8 +1149,8 @@ OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \
vorbis_data.o vorbis_data.o
OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o
OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o
OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o
@@ -1130,6 +1158,8 @@ OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
OBJS-$(CONFIG_LIBXAVS2_ENCODER) += libxavs2.o OBJS-$(CONFIG_LIBXAVS2_ENCODER) += libxavs2.o
OBJS-$(CONFIG_LIBXEVD_DECODER) += libxevd.o
OBJS-$(CONFIG_LIBXEVE_ENCODER) += libxeve.o
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o
@@ -1140,7 +1170,7 @@ OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \
ac3_channel_layout_tab.o ac3_channel_layout_tab.o
OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o
OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o
OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o
OBJS-$(CONFIG_AVS2_PARSER) += avs2.o avs2_parser.o OBJS-$(CONFIG_AVS2_PARSER) += avs2.o avs2_parser.o
OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o
OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o
@@ -1157,6 +1187,7 @@ OBJS-$(CONFIG_DVAUDIO_PARSER) += dvaudio_parser.o
OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o
OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
@@ -1170,6 +1201,7 @@ OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o hevc_data.o
OBJS-$(CONFIG_HDR_PARSER) += hdr_parser.o OBJS-$(CONFIG_HDR_PARSER) += hdr_parser.o
OBJS-$(CONFIG_IPU_PARSER) += ipu_parser.o OBJS-$(CONFIG_IPU_PARSER) += ipu_parser.o
OBJS-$(CONFIG_JPEG2000_PARSER) += jpeg2000_parser.o OBJS-$(CONFIG_JPEG2000_PARSER) += jpeg2000_parser.o
OBJS-$(CONFIG_JPEGXL_PARSER) += jpegxl_parser.o jpegxl_parse.o
OBJS-$(CONFIG_MISC4_PARSER) += misc4_parser.o OBJS-$(CONFIG_MISC4_PARSER) += misc4_parser.o
OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o
OBJS-$(CONFIG_MLP_PARSER) += mlp_parse.o mlp_parser.o mlp.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parse.o mlp_parser.o mlp.o
@@ -1184,8 +1216,7 @@ OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus_parse.o \
OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
OBJS-$(CONFIG_QOI_PARSER) += qoi_parser.o OBJS-$(CONFIG_QOI_PARSER) += qoi_parser.o
OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o OBJS-$(CONFIG_RV34_PARSER) += rv34_parser.o
OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o
OBJS-$(CONFIG_SBC_PARSER) += sbc_parser.o OBJS-$(CONFIG_SBC_PARSER) += sbc_parser.o
OBJS-$(CONFIG_SIPR_PARSER) += sipr_parser.o OBJS-$(CONFIG_SIPR_PARSER) += sipr_parser.o
OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o
@@ -1194,57 +1225,21 @@ OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \
OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o
OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o
OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o
OBJS-$(CONFIG_VVC_PARSER) += vvc_parser.o
OBJS-$(CONFIG_WEBP_PARSER) += webp_parser.o OBJS-$(CONFIG_WEBP_PARSER) += webp_parser.o
OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o
OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o
OBJS-$(CONFIG_XWD_PARSER) += xwd_parser.o OBJS-$(CONFIG_XWD_PARSER) += xwd_parser.o
# bitstream filters # bitstream filters
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o include $(SRC_PATH)/libavcodec/bsf/Makefile
OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o
OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += av1_parse.o h2645_parse.o
OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o OBJS-$(CONFIG_H264_METADATA_BSF) += h264_levels.o h2645data.o
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += hap.o
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_profile_level.o h2645data.o
OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += av1_parse.o
OBJS-$(CONFIG_DTS2PTS_BSF) += dts2pts_bsf.o OBJS-$(CONFIG_TRUEHD_CORE_BSF) += mlp_parse.o mlp.o
OBJS-$(CONFIG_DV_ERROR_MARKER_BSF) += dv_error_marker_bsf.o
OBJS-$(CONFIG_EAC3_CORE_BSF) += eac3_core_bsf.o
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \
av1_parse.o h2645_parse.o
OBJS-$(CONFIG_FILTER_UNITS_BSF) += filter_units_bsf.o
OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o h264_levels.o \
h2645data.o
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o
OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += hapqa_extract_bsf.o hap.o
OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o h265_profile_level.o \
h2645data.o
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
OBJS-$(CONFIG_MEDIA100_TO_MJPEGB_BSF) += media100_to_mjpegb_bsf.o
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o
OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o
OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o
OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o
OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \
mpegaudiotabs.o
OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o
OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o
OBJS-$(CONFIG_NULL_BSF) += null_bsf.o
OBJS-$(CONFIG_OPUS_METADATA_BSF) += opus_metadata_bsf.o
OBJS-$(CONFIG_PCM_RECHUNK_BSF) += pcm_rechunk_bsf.o
OBJS-$(CONFIG_PGS_FRAME_MERGE_BSF) += pgs_frame_merge_bsf.o
OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o av1_parse.o
OBJS-$(CONFIG_SETTS_BSF) += setts_bsf.o
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
OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o
OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o
OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o
OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o
# thread libraries # thread libraries
OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o
@@ -1264,10 +1259,11 @@ SKIPHEADERS += %_tablegen.h \
aacenc_quantization.h \ aacenc_quantization.h \
aacenc_quantization_misc.h \ aacenc_quantization_misc.h \
bitstream_template.h \ bitstream_template.h \
$(ARCH)/vpx_arith.h \ $(ARCH)/vpx_arith.h \
SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_AMF) += amfenc.h
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h
SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h
SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h
SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h
@@ -1281,10 +1277,10 @@ SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h
SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h
SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h
SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.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_VDPAU) += vdpau.h vdpau_internal.h
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h
SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_video.h vulkan_decode.h
SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h
SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h
@@ -1298,9 +1294,8 @@ TESTPROGS = avcodec \
jpeg2000dwt \ jpeg2000dwt \
mathops \ mathops \
TESTPROGS-$(CONFIG_AV1_VAAPI_ENCODER) += av1_levels
TESTPROGS-$(CONFIG_CABAC) += cabac TESTPROGS-$(CONFIG_CABAC) += cabac
TESTPROGS-$(CONFIG_DCT) += avfft
TESTPROGS-$(CONFIG_FFT) += fft fft-fixed32
TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_GOLOMB) += golomb
TESTPROGS-$(CONFIG_IDCTDSP) += dct TESTPROGS-$(CONFIG_IDCTDSP) += dct
TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter
@@ -1320,7 +1315,6 @@ HOSTPROGS = aacps_tablegen \
aacps_fixed_tablegen \ aacps_fixed_tablegen \
cbrt_tablegen \ cbrt_tablegen \
cbrt_fixed_tablegen \ cbrt_fixed_tablegen \
cos_tablegen \
dv_tablegen \ dv_tablegen \
motionpixels_tablegen \ motionpixels_tablegen \
mpegaudio_tablegen \ mpegaudio_tablegen \
@@ -1335,12 +1329,6 @@ CLEANFILES = *_tables.c *_tables.h *_tablegen$(HOSTEXESUF)
$(SUBDIR)tests/dct$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o $(SUBDIR)tests/dct$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o
$(SUBDIR)dv_tablegen$(HOSTEXESUF): $(SUBDIR)dvdata_host.o $(SUBDIR)dv_tablegen$(HOSTEXESUF): $(SUBDIR)dvdata_host.o
TRIG_TABLES = cos cos_fixed sin
TRIG_TABLES := $(TRIG_TABLES:%=$(SUBDIR)%_tables.c)
$(TRIG_TABLES): $(SUBDIR)%_tables.c: $(SUBDIR)cos_tablegen$(HOSTEXESUF)
$(M)./$< $* > $@
ifdef CONFIG_SMALL ifdef CONFIG_SMALL
$(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=1 $(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=1
else else
-268
View File
@@ -32,16 +32,6 @@
#include "aac_defines.h" #include "aac_defines.h"
#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
#include "libavutil/fixed_dsp.h"
#include "libavutil/mem_internal.h"
#include "libavutil/tx.h"
#include "avcodec.h"
#include "mpeg4audio.h"
#include "sbr.h"
#include <stdint.h>
#define MAX_CHANNELS 64 #define MAX_CHANNELS 64
#define MAX_ELEM_ID 16 #define MAX_ELEM_ID 16
@@ -49,8 +39,6 @@
#define TNS_MAX_ORDER 20 #define TNS_MAX_ORDER 20
#define MAX_LTP_LONG_SFB 40 #define MAX_LTP_LONG_SFB 40
#define CLIP_AVOIDANCE_FACTOR 0.95f
enum RawDataBlockType { enum RawDataBlockType {
TYPE_SCE, TYPE_SCE,
TYPE_CPE, TYPE_CPE,
@@ -88,8 +76,6 @@ enum BandType {
INTENSITY_BT = 15, ///< Scalefactor data are intensity stereo positions (in phase). INTENSITY_BT = 15, ///< Scalefactor data are intensity stereo positions (in phase).
}; };
#define IS_CODEBOOK_UNSIGNED(x) (((x) - 1) & 10)
enum ChannelPosition { enum ChannelPosition {
AAC_CHANNEL_OFF = 0, AAC_CHANNEL_OFF = 0,
AAC_CHANNEL_FRONT = 1, AAC_CHANNEL_FRONT = 1,
@@ -99,34 +85,6 @@ enum ChannelPosition {
AAC_CHANNEL_CC = 5, AAC_CHANNEL_CC = 5,
}; };
/**
* The point during decoding at which channel coupling is applied.
*/
enum CouplingPoint {
BEFORE_TNS,
BETWEEN_TNS_AND_IMDCT,
AFTER_IMDCT = 3,
};
/**
* Output configuration status
*/
enum OCStatus {
OC_NONE, ///< Output unconfigured
OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE
OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header
OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked
OC_LOCKED, ///< Output configuration locked in place
};
typedef struct OutputConfiguration {
MPEG4AudioConfig m4ac;
uint8_t layout_map[MAX_ELEM_ID*4][3];
int layout_map_tags;
AVChannelLayout ch_layout;
enum OCStatus status;
} OutputConfiguration;
/** /**
* Predictor State * Predictor State
*/ */
@@ -155,70 +113,6 @@ typedef struct PredictorState {
#define NOISE_PRE_BITS 9 ///< length of preamble #define NOISE_PRE_BITS 9 ///< length of preamble
#define NOISE_OFFSET 90 ///< subtracted from global gain, used as offset for the preamble #define NOISE_OFFSET 90 ///< subtracted from global gain, used as offset for the preamble
/**
* Long Term Prediction
*/
typedef struct LongTermPrediction {
int8_t present;
int16_t lag;
int coef_idx;
INTFLOAT coef;
int8_t used[MAX_LTP_LONG_SFB];
} LongTermPrediction;
/**
* Individual Channel Stream
*/
typedef struct IndividualChannelStream {
uint8_t max_sfb; ///< number of scalefactor bands per group
enum WindowSequence window_sequence[2];
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
int num_window_groups;
uint8_t group_len[8];
LongTermPrediction ltp;
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window
int num_swb; ///< number of scalefactor window bands
int num_windows;
int tns_max_bands;
int predictor_present;
int predictor_initialized;
int predictor_reset_group;
int predictor_reset_count[31]; ///< used by encoder to count prediction resets
uint8_t prediction_used[41];
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
float clip_avoidance_factor; ///< set if any window is near clipping to the necessary atennuation factor to avoid it
} IndividualChannelStream;
/**
* Temporal Noise Shaping
*/
typedef struct TemporalNoiseShaping {
int present;
int n_filt[8];
int length[8][4];
int direction[8][4];
int order[8][4];
int coef_idx[8][4][TNS_MAX_ORDER];
INTFLOAT coef[8][4][TNS_MAX_ORDER];
} TemporalNoiseShaping;
/**
* Dynamic Range Control - decoded from the bitstream but not processed further.
*/
typedef struct DynamicRangeControl {
int pce_instance_tag; ///< Indicates with which program the DRC info is associated.
int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative
int dyn_rng_ctl[17]; ///< DRC magnitude information
int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing.
int band_incr; ///< Number of DRC bands greater than 1 having DRC info.
int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain.
int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines.
int prog_ref_level; /**< A reference level for the long-term program audio level for all
* channels combined.
*/
} DynamicRangeControl;
typedef struct Pulse { typedef struct Pulse {
int num_pulse; int num_pulse;
int start; int start;
@@ -226,166 +120,4 @@ typedef struct Pulse {
int amp[4]; int amp[4];
} Pulse; } Pulse;
/**
* coupling parameters
*/
typedef struct ChannelCoupling {
enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
int num_coupled; ///< number of target elements
enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
int id_select[8]; ///< element id
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
* [2] list of gains for left channel; [3] lists of gains for both channels
*/
INTFLOAT gain[16][120];
} ChannelCoupling;
/**
* Single Channel Element - used for both SCE and LFE elements.
*/
typedef struct SingleChannelElement {
IndividualChannelStream ics;
TemporalNoiseShaping tns;
Pulse pulse;
enum BandType band_type[128]; ///< band types
enum BandType band_alt[128]; ///< alternative band type (used by encoder)
int band_type_run_end[120]; ///< band type run end points
INTFLOAT sf[120]; ///< scalefactors
int sf_idx[128]; ///< scalefactor indices (used by encoder)
uint8_t zeroes[128]; ///< band is not coded (used by encoder)
uint8_t can_pns[128]; ///< band is allowed to PNS (informative)
float is_ener[128]; ///< Intensity stereo pos (used by encoder)
float pns_ener[128]; ///< Noise energy values (used by encoder)
DECLARE_ALIGNED(32, INTFLOAT, pcoeffs)[1024]; ///< coefficients for IMDCT, pristine
DECLARE_ALIGNED(32, INTFLOAT, coeffs)[1024]; ///< coefficients for IMDCT, maybe processed
DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap
DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
DECLARE_ALIGNED(32, AAC_FLOAT, lcoeffs)[1024]; ///< MDCT of LTP coefficients (used by encoder)
DECLARE_ALIGNED(32, AAC_FLOAT, prcoeffs)[1024]; ///< Main prediction coefs (used by encoder)
PredictorState predictor_state[MAX_PREDICTORS];
INTFLOAT *ret; ///< PCM output
} SingleChannelElement;
/**
* channel element - generic struct for SCE/CPE/CCE/LFE
*/
typedef struct ChannelElement {
int present;
// CPE specific
int common_window; ///< Set if channels share a common 'IndividualChannelStream' in bitstream.
int ms_mode; ///< Signals mid/side stereo flags coding mode (used by encoder)
uint8_t is_mode; ///< Set if any bands have been encoded using intensity stereo (used by encoder)
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
uint8_t is_mask[128]; ///< Set if intensity stereo is used (used by encoder)
// shared
SingleChannelElement ch[2];
// CCE specific
ChannelCoupling coup;
SpectralBandReplication sbr;
} ChannelElement;
enum AACOutputChannelOrder {
CHANNEL_ORDER_DEFAULT,
CHANNEL_ORDER_CODED,
};
/**
* main AAC context
*/
struct AACContext {
AVClass *class;
AVCodecContext *avctx;
AVFrame *frame;
int is_saved; ///< Set if elements have stored overlap from previous frame.
DynamicRangeControl che_drc;
/**
* @name Channel element related data
* @{
*/
ChannelElement *che[4][MAX_ELEM_ID];
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
int tags_mapped;
int warned_remapping_once;
/** @} */
/**
* @name temporary aligned temporary buffers
* (We do not want to have these on the stack.)
* @{
*/
DECLARE_ALIGNED(32, INTFLOAT, buf_mdct)[1024];
/** @} */
/**
* @name Computed / set up during initialization
* @{
*/
AVTXContext *mdct120;
AVTXContext *mdct128;
AVTXContext *mdct480;
AVTXContext *mdct512;
AVTXContext *mdct960;
AVTXContext *mdct1024;
AVTXContext *mdct_ltp;
av_tx_fn mdct120_fn;
av_tx_fn mdct128_fn;
av_tx_fn mdct480_fn;
av_tx_fn mdct512_fn;
av_tx_fn mdct960_fn;
av_tx_fn mdct1024_fn;
av_tx_fn mdct_ltp_fn;
#if USE_FIXED
AVFixedDSPContext *fdsp;
#else
AVFloatDSPContext *fdsp;
#endif /* USE_FIXED */
int random_state;
/** @} */
/**
* @name Members used for output
* @{
*/
SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement
/** @} */
/**
* @name Japanese DTV specific extension
* @{
*/
int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
/** @} */
enum AACOutputChannelOrder output_channel_order;
DECLARE_ALIGNED(32, INTFLOAT, temp)[128];
OutputConfiguration oc[2];
int warned_num_aac_frames;
int warned_960_sbr;
unsigned warned_71_wide;
int warned_gain_control;
int warned_he_aac_mono;
/* aacdec functions pointers */
void (*imdct_and_windowing)(AACContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(AACContext *ac, SingleChannelElement *sce);
void (*apply_tns)(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
IndividualChannelStream *ics, int decode);
void (*windowing_and_mdct_ltp)(AACContext *ac, INTFLOAT *out,
INTFLOAT *in, IndividualChannelStream *ics);
void (*update_ltp)(AACContext *ac, SingleChannelElement *sce);
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
};
void ff_aacdec_init_mips(AACContext *c);
#endif /* AVCODEC_AAC_H */ #endif /* AVCODEC_AAC_H */
-6
View File
@@ -135,12 +135,6 @@ get_next:
avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
avctx->ch_layout.nb_channels = hdr.channels; avctx->ch_layout.nb_channels = hdr.channels;
} }
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
avctx->channels = avctx->ch_layout.nb_channels;
avctx->channel_layout = hdr.channel_layout;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
} }
s1->duration = hdr.num_blocks * 256; s1->duration = hdr.num_blocks * 256;
avctx->audio_service_type = hdr.bitstream_mode; avctx->audio_service_type = hdr.bitstream_mode;
+9 -4
View File
@@ -30,7 +30,6 @@
#include "libavutil/softfloat.h" #include "libavutil/softfloat.h"
#define AAC_RENAME(x) x ## _fixed #define AAC_RENAME(x) x ## _fixed
#define AAC_RENAME_32(x) x ## _fixed_32
#define AAC_RENAME2(x) x ## _fixed #define AAC_RENAME2(x) x ## _fixed
typedef int INTFLOAT; typedef int INTFLOAT;
typedef unsigned UINTFLOAT; ///< Equivalent to INTFLOAT, Used as temporal cast to avoid undefined sign overflow operations. typedef unsigned UINTFLOAT; ///< Equivalent to INTFLOAT, Used as temporal cast to avoid undefined sign overflow operations.
@@ -72,12 +71,19 @@ typedef int AAC_SIGNE;
((int64_t)(y) * (z)) + \ ((int64_t)(y) * (z)) + \
0x40000000) >> 31) 0x40000000) >> 31)
#define AAC_HALF_SUM(x, y) (((x) >> 1) + ((y) >> 1)) #define AAC_HALF_SUM(x, y) (((x) >> 1) + ((y) >> 1))
#define AAC_SRA_R(x, y) (int)(((x) + (1 << ((y) - 1))) >> (y))
#ifdef LPC_USE_FIXED
#error aac_defines.h must be included before lpc_functions.h for fixed point decoder
#endif
#define LPC_USE_FIXED 1
#define LPC_MUL26(x, y) AAC_MUL26((x), (y))
#define LPC_FIXR(x) FIXR(x)
#define LPC_SRA_R(x, y) (int)(((x) + (1 << ((y) - 1))) >> (y))
#else #else
#define AAC_RENAME(x) x #define AAC_RENAME(x) x
#define AAC_RENAME_32(x) x
#define AAC_RENAME2(x) ff_ ## x #define AAC_RENAME2(x) ff_ ## x
typedef float INTFLOAT; typedef float INTFLOAT;
typedef float UINTFLOAT; typedef float UINTFLOAT;
@@ -105,7 +111,6 @@ typedef unsigned AAC_SIGNE;
(c) * (d) - (e) * (f)) (c) * (d) - (e) * (f))
#define AAC_MSUB31_V3(x, y, z) ((x) - (y)) * (z) #define AAC_MSUB31_V3(x, y, z) ((x) - (y)) * (z)
#define AAC_HALF_SUM(x, y) ((x) + (y)) * 0.5f #define AAC_HALF_SUM(x, y) ((x) + (y)) * 0.5f
#define AAC_SRA_R(x, y) (x)
#endif /* USE_FIXED */ #endif /* USE_FIXED */
+13 -13
View File
@@ -108,10 +108,10 @@ static av_always_inline float quantize_and_encode_band_cost_template(
return cost * lambda; return cost * lambda;
} }
if (!scaled) { if (!scaled) {
s->abs_pow34(s->scoefs, in, size); s->aacdsp.abs_pow34(s->scoefs, in, size);
scaled = s->scoefs; scaled = s->scoefs;
} }
s->quant_bands(s->qcoefs, in, scaled, size, !BT_UNSIGNED, aac_cb_maxval[cb], Q34, ROUNDING); s->aacdsp.quant_bands(s->qcoefs, in, scaled, size, !BT_UNSIGNED, aac_cb_maxval[cb], Q34, ROUNDING);
if (BT_UNSIGNED) { if (BT_UNSIGNED) {
off = 0; off = 0;
} else { } else {
@@ -311,7 +311,7 @@ static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce
float next_minrd = INFINITY; float next_minrd = INFINITY;
int next_mincb = 0; int next_mincb = 0;
s->abs_pow34(s->scoefs, sce->coeffs, 1024); s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
start = win*128; start = win*128;
for (cb = 0; cb < CB_TOT_ALL; cb++) { for (cb = 0; cb < CB_TOT_ALL; cb++) {
path[0][cb].cost = 0.0f; path[0][cb].cost = 0.0f;
@@ -522,7 +522,7 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
} }
} }
idx = 1; idx = 1;
s->abs_pow34(s->scoefs, sce->coeffs, 1024); s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
start = w*128; start = w*128;
for (g = 0; g < sce->ics.num_swb; g++) { for (g = 0; g < sce->ics.num_swb; g++) {
@@ -668,7 +668,7 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s,
if (!allz) if (!allz)
return; return;
s->abs_pow34(s->scoefs, sce->coeffs, 1024); s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
ff_quantize_band_cost_cache_init(s); ff_quantize_band_cost_cache_init(s);
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
@@ -874,8 +874,8 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]); s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]);
pns_senergy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]); pns_senergy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
pns_energy += pns_senergy; pns_energy += pns_senergy;
s->abs_pow34(NOR34, &sce->coeffs[start_c], sce->ics.swb_sizes[g]); s->aacdsp.abs_pow34(NOR34, &sce->coeffs[start_c], sce->ics.swb_sizes[g]);
s->abs_pow34(PNS34, PNS, sce->ics.swb_sizes[g]); s->aacdsp.abs_pow34(PNS34, PNS, sce->ics.swb_sizes[g]);
dist1 += quantize_band_cost(s, &sce->coeffs[start_c], dist1 += quantize_band_cost(s, &sce->coeffs[start_c],
NOR34, NOR34,
sce->ics.swb_sizes[g], sce->ics.swb_sizes[g],
@@ -1012,8 +1012,8 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
S[i] = M[i] S[i] = M[i]
- sce1->coeffs[start+(w+w2)*128+i]; - sce1->coeffs[start+(w+w2)*128+i];
} }
s->abs_pow34(M34, M, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(M34, M, sce0->ics.swb_sizes[g]);
s->abs_pow34(S34, S, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(S34, S, sce0->ics.swb_sizes[g]);
for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) { for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) {
Mmax = FFMAX(Mmax, M34[i]); Mmax = FFMAX(Mmax, M34[i]);
Smax = FFMAX(Smax, S34[i]); Smax = FFMAX(Smax, S34[i]);
@@ -1056,10 +1056,10 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
- sce1->coeffs[start+(w+w2)*128+i]; - sce1->coeffs[start+(w+w2)*128+i];
} }
s->abs_pow34(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
s->abs_pow34(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
s->abs_pow34(M34, M, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(M34, M, sce0->ics.swb_sizes[g]);
s->abs_pow34(S34, S, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(S34, S, sce0->ics.swb_sizes[g]);
dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128], dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128],
L34, L34,
sce0->ics.swb_sizes[g], sce0->ics.swb_sizes[g],
+1 -1
View File
@@ -70,7 +70,7 @@ static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce,
float next_minbits = INFINITY; float next_minbits = INFINITY;
int next_mincb = 0; int next_mincb = 0;
s->abs_pow34(s->scoefs, sce->coeffs, 1024); s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
start = win*128; start = win*128;
for (cb = 0; cb < CB_TOT_ALL; cb++) { for (cb = 0; cb < CB_TOT_ALL; cb++) {
path[0][cb].cost = run_bits+4; path[0][cb].cost = run_bits+4;
+1 -1
View File
@@ -291,7 +291,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
if (!allz) if (!allz)
return; return;
s->abs_pow34(s->scoefs, sce->coeffs, 1024); s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
ff_quantize_band_cost_cache_init(s); ff_quantize_band_cost_cache_init(s);
for (i = 0; i < sizeof(minsf) / sizeof(minsf[0]); ++i) for (i = 0; i < sizeof(minsf) / sizeof(minsf[0]); ++i)
+8 -10
View File
@@ -40,11 +40,11 @@
#include "avcodec.h" #include "avcodec.h"
#include "codec_internal.h" #include "codec_internal.h"
#include "get_bits.h" #include "get_bits.h"
#include "lpc.h"
#include "kbdwin.h" #include "kbdwin.h"
#include "sinewin.h" #include "sinewin.h"
#include "aac.h" #include "aac.h"
#include "aacdec.h"
#include "aactab.h" #include "aactab.h"
#include "aacdectab.h" #include "aacdectab.h"
#include "adts_header.h" #include "adts_header.h"
@@ -209,7 +209,7 @@ static av_always_inline void predict(PredictorState *ps, float *coef,
* *
* @param index index into coupling gain array * @param index index into coupling gain array
*/ */
static void apply_dependent_coupling(AACContext *ac, static void apply_dependent_coupling(AACDecContext *ac,
SingleChannelElement *target, SingleChannelElement *target,
ChannelElement *cce, int index) ChannelElement *cce, int index)
{ {
@@ -245,7 +245,7 @@ static void apply_dependent_coupling(AACContext *ac,
* *
* @param index index into coupling gain array * @param index index into coupling gain array
*/ */
static void apply_independent_coupling(AACContext *ac, static void apply_independent_coupling(AACDecContext *ac,
SingleChannelElement *target, SingleChannelElement *target,
ChannelElement *cce, int index) ChannelElement *cce, int index)
{ {
@@ -262,7 +262,7 @@ static void apply_independent_coupling(AACContext *ac,
#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word #define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
struct LATMContext { struct LATMContext {
AACContext aac_ctx; ///< containing AACContext AACDecContext aac_ctx; ///< containing AACContext
int initialized; ///< initialized after a valid extradata was seen int initialized; ///< initialized after a valid extradata was seen
// parser data // parser data
@@ -281,7 +281,7 @@ static inline uint32_t latm_get_value(GetBitContext *b)
static int latm_decode_audio_specific_config(struct LATMContext *latmctx, static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
GetBitContext *gb, int asclen) GetBitContext *gb, int asclen)
{ {
AACContext *ac = &latmctx->aac_ctx; AACDecContext *ac = &latmctx->aac_ctx;
AVCodecContext *avctx = ac->avctx; AVCodecContext *avctx = ac->avctx;
MPEG4AudioConfig m4ac = { 0 }; MPEG4AudioConfig m4ac = { 0 };
GetBitContext gbc; GetBitContext gbc;
@@ -555,7 +555,7 @@ const FFCodec ff_aac_decoder = {
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"), CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
.p.type = AVMEDIA_TYPE_AUDIO, .p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC, .p.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACContext), .priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init, .init = aac_decode_init,
.close = aac_decode_close, .close = aac_decode_close,
FF_CODEC_DECODE_CB(aac_decode_frame), FF_CODEC_DECODE_CB(aac_decode_frame),
@@ -564,8 +564,7 @@ const FFCodec ff_aac_decoder = {
}, },
.p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
CODEC_OLD_CHANNEL_LAYOUTS_ARRAY(aac_channel_layout) .p.ch_layouts = ff_aac_ch_layout,
.p.ch_layouts = aac_ch_layout,
.flush = flush, .flush = flush,
.p.priv_class = &aac_decoder_class, .p.priv_class = &aac_decoder_class,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
@@ -590,8 +589,7 @@ const FFCodec ff_aac_latm_decoder = {
}, },
.p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
CODEC_OLD_CHANNEL_LAYOUTS_ARRAY(aac_channel_layout) .p.ch_layouts = ff_aac_ch_layout,
.p.ch_layouts = aac_ch_layout,
.flush = flush, .flush = flush,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
}; };
+279
View File
@@ -0,0 +1,279 @@
/*
* AAC decoder definitions and structures
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail 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
*/
/**
* @file
* AAC decoder definitions and structures
* @author Oded Shimon ( ods15 ods15 dyndns org )
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
#ifndef AVCODEC_AACDEC_H
#define AVCODEC_AACDEC_H
#include <stdint.h>
#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
#include "libavutil/fixed_dsp.h"
#include "libavutil/mem_internal.h"
#include "libavutil/tx.h"
#include "aac.h"
#include "aac_defines.h"
#include "mpeg4audio.h"
#include "sbr.h"
/**
* Output configuration status
*/
enum OCStatus {
OC_NONE, ///< Output unconfigured
OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE
OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header
OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked
OC_LOCKED, ///< Output configuration locked in place
};
enum AACOutputChannelOrder {
CHANNEL_ORDER_DEFAULT,
CHANNEL_ORDER_CODED,
};
/**
* The point during decoding at which channel coupling is applied.
*/
enum CouplingPoint {
BEFORE_TNS,
BETWEEN_TNS_AND_IMDCT,
AFTER_IMDCT = 3,
};
/**
* Long Term Prediction
*/
typedef struct LongTermPrediction {
int8_t present;
int16_t lag;
INTFLOAT coef;
int8_t used[MAX_LTP_LONG_SFB];
} LongTermPrediction;
/**
* Individual Channel Stream
*/
typedef struct IndividualChannelStream {
uint8_t max_sfb; ///< number of scalefactor bands per group
enum WindowSequence window_sequence[2];
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
int num_window_groups;
uint8_t group_len[8];
LongTermPrediction ltp;
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
int num_swb; ///< number of scalefactor window bands
int num_windows;
int tns_max_bands;
int predictor_present;
int predictor_initialized;
int predictor_reset_group;
uint8_t prediction_used[41];
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
} IndividualChannelStream;
/**
* Temporal Noise Shaping
*/
typedef struct TemporalNoiseShaping {
int present;
int n_filt[8];
int length[8][4];
int direction[8][4];
int order[8][4];
INTFLOAT coef[8][4][TNS_MAX_ORDER];
} TemporalNoiseShaping;
/**
* coupling parameters
*/
typedef struct ChannelCoupling {
enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
int num_coupled; ///< number of target elements
enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
int id_select[8]; ///< element id
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
* [2] list of gains for left channel; [3] lists of gains for both channels
*/
INTFLOAT gain[16][120];
} ChannelCoupling;
/**
* Single Channel Element - used for both SCE and LFE elements.
*/
typedef struct SingleChannelElement {
IndividualChannelStream ics;
TemporalNoiseShaping tns;
enum BandType band_type[128]; ///< band types
int band_type_run_end[120]; ///< band type run end points
INTFLOAT sf[120]; ///< scalefactors
DECLARE_ALIGNED(32, INTFLOAT, coeffs)[1024]; ///< coefficients for IMDCT, maybe processed
DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap
DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
PredictorState predictor_state[MAX_PREDICTORS];
INTFLOAT *ret; ///< PCM output
} SingleChannelElement;
/**
* channel element - generic struct for SCE/CPE/CCE/LFE
*/
typedef struct ChannelElement {
int present;
// CPE specific
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
// shared
SingleChannelElement ch[2];
// CCE specific
ChannelCoupling coup;
SpectralBandReplication sbr;
} ChannelElement;
typedef struct OutputConfiguration {
MPEG4AudioConfig m4ac;
uint8_t layout_map[MAX_ELEM_ID*4][3];
int layout_map_tags;
AVChannelLayout ch_layout;
enum OCStatus status;
} OutputConfiguration;
/**
* Dynamic Range Control - decoded from the bitstream but not processed further.
*/
typedef struct DynamicRangeControl {
int pce_instance_tag; ///< Indicates with which program the DRC info is associated.
int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative
int dyn_rng_ctl[17]; ///< DRC magnitude information
int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing.
int band_incr; ///< Number of DRC bands greater than 1 having DRC info.
int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain.
int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines.
int prog_ref_level; /**< A reference level for the long-term program audio level for all
* channels combined.
*/
} DynamicRangeControl;
/**
* main AAC decoding context
*/
typedef struct AACDecContext {
const struct AVClass *class;
struct AVCodecContext *avctx;
struct AVFrame *frame;
int is_saved; ///< Set if elements have stored overlap from previous frame.
DynamicRangeControl che_drc;
/**
* @name Channel element related data
* @{
*/
ChannelElement *che[4][MAX_ELEM_ID];
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
int tags_mapped;
int warned_remapping_once;
/** @} */
/**
* @name temporary aligned temporary buffers
* (We do not want to have these on the stack.)
* @{
*/
DECLARE_ALIGNED(32, INTFLOAT, buf_mdct)[1024];
DECLARE_ALIGNED(32, INTFLOAT, temp)[128];
/** @} */
/**
* @name Computed / set up during initialization
* @{
*/
AVTXContext *mdct120;
AVTXContext *mdct128;
AVTXContext *mdct480;
AVTXContext *mdct512;
AVTXContext *mdct960;
AVTXContext *mdct1024;
AVTXContext *mdct_ltp;
av_tx_fn mdct120_fn;
av_tx_fn mdct128_fn;
av_tx_fn mdct480_fn;
av_tx_fn mdct512_fn;
av_tx_fn mdct960_fn;
av_tx_fn mdct1024_fn;
av_tx_fn mdct_ltp_fn;
#if USE_FIXED
AVFixedDSPContext *fdsp;
#else
AVFloatDSPContext *fdsp;
#endif /* USE_FIXED */
int random_state;
/** @} */
/**
* @name Members used for output
* @{
*/
SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement
/** @} */
/**
* @name Japanese DTV specific extension
* @{
*/
int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
/** @} */
enum AACOutputChannelOrder output_channel_order;
OutputConfiguration oc[2];
int warned_num_aac_frames;
int warned_960_sbr;
unsigned warned_71_wide;
int warned_gain_control;
int warned_he_aac_mono;
/* aacdec functions pointers */
void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*apply_tns)(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
IndividualChannelStream *ics, int decode);
void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, INTFLOAT *out,
INTFLOAT *in, IndividualChannelStream *ics);
void (*update_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
} AACDecContext;
void ff_aacdec_init_mips(AACDecContext *c);
#endif /* AVCODEC_AACDEC_H */
+307
View File
@@ -0,0 +1,307 @@
/*
* Common code and tables of the AAC fixed- and floating-point decoders
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail 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
*/
/**
* @file
* Common code and tables of the AAC fixed- and floating-point decoders
*/
#include "aac.h"
#include "aacdectab.h"
#include "aacps.h"
#include "aactab.h"
#include "vlc.h"
#include "libavutil/attributes.h"
#include "libavutil/thread.h"
const int8_t ff_tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 5, 5, 16, 5, 0 };
const uint8_t ff_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 }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 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_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },
{ { 0, } },
{ { 0, } },
{ { 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_BACK }, { 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_BACK }, // 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_SIDE }, // 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
},
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, { TYPE_CPE, 2, AAC_CHANNEL_FRONT }, },
{ { 0, } },
};
const int16_t ff_aac_channel_map[3][4][6] = {
{
{ AV_CHAN_FRONT_CENTER, AV_CHAN_FRONT_LEFT_OF_CENTER, AV_CHAN_FRONT_RIGHT_OF_CENTER, AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, AV_CHAN_BACK_CENTER },
{ AV_CHAN_LOW_FREQUENCY, AV_CHAN_LOW_FREQUENCY_2, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
},
{
{ AV_CHAN_TOP_FRONT_CENTER, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_FRONT_LEFT, AV_CHAN_TOP_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_TOP_SIDE_LEFT, AV_CHAN_TOP_SIDE_RIGHT, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_CENTER},
{ AV_CHAN_UNUSED, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_BACK_LEFT, AV_CHAN_TOP_BACK_RIGHT, AV_CHAN_TOP_BACK_CENTER},
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE},
},
{
{ AV_CHAN_BOTTOM_FRONT_CENTER, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_BOTTOM_FRONT_LEFT, AV_CHAN_BOTTOM_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
},
};
const AVChannelLayout ff_aac_ch_layout[] = {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND,
AV_CHANNEL_LAYOUT_4POINT0,
AV_CHANNEL_LAYOUT_5POINT0_BACK,
AV_CHANNEL_LAYOUT_5POINT1_BACK,
AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
AV_CHANNEL_LAYOUT_6POINT1_BACK,
AV_CHANNEL_LAYOUT_7POINT1,
AV_CHANNEL_LAYOUT_22POINT2,
AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK,
{ 0 },
};
VLCElem ff_vlc_scalefactors[352];
const VLCElem *ff_vlc_spectral[11];
/// Huffman tables for SBR
static const uint8_t sbr_huffman_tab[][2] = {
/* t_huffman_env_1_5dB - 121 entries */
{ 60, 2 }, { 59, 2 }, { 61, 3 }, { 58, 3 }, { 62, 4 },
{ 57, 4 }, { 63, 5 }, { 56, 5 }, { 64, 6 }, { 55, 6 },
{ 65, 7 }, { 54, 7 }, { 66, 8 }, { 53, 8 }, { 67, 9 },
{ 52, 9 }, { 51, 10 }, { 68, 10 }, { 50, 11 }, { 69, 12 },
{ 49, 12 }, { 70, 13 }, { 48, 13 }, { 47, 13 }, { 71, 14 },
{ 46, 14 }, { 72, 14 }, { 45, 14 }, { 44, 15 }, { 73, 15 },
{ 41, 16 }, { 42, 16 }, { 43, 16 }, { 74, 16 }, { 36, 16 },
{ 40, 16 }, { 76, 16 }, { 34, 17 }, { 39, 17 }, { 75, 17 },
{ 37, 17 }, { 35, 18 }, { 38, 18 }, { 0, 18 }, { 1, 18 },
{ 2, 18 }, { 3, 18 }, { 4, 18 }, { 5, 18 }, { 6, 19 },
{ 7, 19 }, { 8, 19 }, { 9, 19 }, { 10, 19 }, { 11, 19 },
{ 12, 19 }, { 13, 19 }, { 14, 19 }, { 15, 19 }, { 16, 19 },
{ 17, 19 }, { 18, 19 }, { 19, 19 }, { 20, 19 }, { 21, 19 },
{ 22, 19 }, { 23, 19 }, { 24, 19 }, { 25, 19 }, { 26, 19 },
{ 27, 19 }, { 28, 19 }, { 29, 19 }, { 30, 19 }, { 31, 19 },
{ 32, 19 }, { 33, 19 }, { 77, 19 }, { 78, 19 }, { 79, 19 },
{ 80, 19 }, { 81, 19 }, { 82, 19 }, { 83, 19 }, { 84, 19 },
{ 85, 19 }, { 86, 19 }, { 87, 19 }, { 88, 19 }, { 89, 19 },
{ 90, 19 }, { 91, 19 }, { 92, 19 }, { 93, 19 }, { 94, 19 },
{ 95, 19 }, { 96, 19 }, { 97, 19 }, { 98, 19 }, { 99, 19 },
{ 100, 19 }, { 101, 19 }, { 102, 19 }, { 103, 19 }, { 104, 19 },
{ 105, 19 }, { 106, 19 }, { 107, 19 }, { 108, 19 }, { 109, 19 },
{ 110, 19 }, { 111, 19 }, { 112, 19 }, { 113, 19 }, { 114, 19 },
{ 115, 19 }, { 116, 19 }, { 117, 19 }, { 118, 19 }, { 119, 19 },
{ 120, 19 },
/* f_huffman_env_1_5dB - 121 entries */
{ 60, 2 }, { 59, 2 }, { 61, 3 }, { 58, 3 }, { 57, 4 },
{ 62, 4 }, { 56, 5 }, { 63, 5 }, { 55, 6 }, { 64, 6 },
{ 54, 7 }, { 65, 8 }, { 53, 8 }, { 66, 8 }, { 52, 9 },
{ 67, 9 }, { 51, 9 }, { 68, 10 }, { 50, 10 }, { 69, 11 },
{ 49, 11 }, { 70, 11 }, { 71, 11 }, { 48, 12 }, { 72, 12 },
{ 47, 12 }, { 73, 12 }, { 74, 13 }, { 46, 13 }, { 45, 13 },
{ 75, 13 }, { 76, 14 }, { 77, 14 }, { 44, 14 }, { 43, 15 },
{ 42, 15 }, { 41, 16 }, { 78, 16 }, { 79, 16 }, { 40, 16 },
{ 39, 16 }, { 80, 17 }, { 81, 17 }, { 36, 17 }, { 37, 17 },
{ 38, 17 }, { 34, 17 }, { 32, 18 }, { 82, 18 }, { 83, 18 },
{ 85, 18 }, { 19, 18 }, { 35, 18 }, { 86, 18 }, { 87, 18 },
{ 30, 18 }, { 33, 18 }, { 84, 18 }, { 88, 18 }, { 104, 18 },
{ 9, 19 }, { 14, 19 }, { 16, 19 }, { 17, 19 }, { 23, 19 },
{ 27, 19 }, { 29, 19 }, { 31, 19 }, { 90, 19 }, { 97, 19 },
{ 102, 19 }, { 107, 19 }, { 108, 19 }, { 0, 19 }, { 1, 19 },
{ 2, 20 }, { 3, 20 }, { 4, 20 }, { 5, 20 }, { 6, 20 },
{ 7, 20 }, { 8, 20 }, { 10, 20 }, { 11, 20 }, { 12, 20 },
{ 13, 20 }, { 15, 20 }, { 18, 20 }, { 20, 20 }, { 21, 20 },
{ 22, 20 }, { 24, 20 }, { 25, 20 }, { 26, 20 }, { 28, 20 },
{ 89, 20 }, { 91, 20 }, { 92, 20 }, { 93, 20 }, { 94, 20 },
{ 95, 20 }, { 96, 20 }, { 98, 20 }, { 99, 20 }, { 100, 20 },
{ 101, 20 }, { 103, 20 }, { 105, 20 }, { 106, 20 }, { 109, 20 },
{ 110, 20 }, { 111, 20 }, { 112, 20 }, { 113, 20 }, { 114, 20 },
{ 115, 20 }, { 116, 20 }, { 117, 20 }, { 118, 20 }, { 119, 20 },
{ 120, 20 },
/* t_huffman_env_bal_1_5dB - 49 entries */
{ 24, 1 }, { 25, 2 }, { 23, 3 }, { 26, 4 }, { 22, 5 },
{ 27, 6 }, { 21, 7 }, { 28, 8 }, { 20, 9 }, { 19, 11 },
{ 29, 11 }, { 18, 12 }, { 30, 12 }, { 31, 15 }, { 17, 16 },
{ 32, 16 }, { 0, 16 }, { 1, 16 }, { 2, 16 }, { 3, 16 },
{ 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, { 8, 16 },
{ 9, 16 }, { 10, 16 }, { 11, 16 }, { 12, 16 }, { 13, 16 },
{ 14, 16 }, { 15, 16 }, { 16, 16 }, { 33, 16 }, { 34, 16 },
{ 35, 16 }, { 36, 16 }, { 37, 16 }, { 38, 16 }, { 39, 17 },
{ 40, 17 }, { 41, 17 }, { 42, 17 }, { 43, 17 }, { 44, 17 },
{ 45, 17 }, { 46, 17 }, { 47, 17 }, { 48, 17 },
/* f_huffman_env_bal_1_5dB - 49 entries */
{ 24, 1 }, { 23, 2 }, { 25, 3 }, { 22, 4 }, { 26, 5 },
{ 27, 6 }, { 21, 7 }, { 20, 8 }, { 28, 9 }, { 19, 11 },
{ 29, 11 }, { 18, 11 }, { 30, 12 }, { 17, 14 }, { 31, 15 },
{ 32, 16 }, { 15, 16 }, { 16, 17 }, { 0, 18 }, { 1, 18 },
{ 2, 18 }, { 3, 18 }, { 4, 18 }, { 5, 18 }, { 6, 18 },
{ 7, 18 }, { 8, 18 }, { 9, 18 }, { 10, 18 }, { 11, 18 },
{ 12, 18 }, { 13, 18 }, { 14, 18 }, { 33, 18 }, { 34, 18 },
{ 35, 18 }, { 36, 18 }, { 37, 18 }, { 38, 18 }, { 39, 18 },
{ 40, 18 }, { 41, 18 }, { 42, 18 }, { 43, 18 }, { 44, 18 },
{ 45, 18 }, { 46, 18 }, { 47, 19 }, { 48, 19 },
/* t_huffman_env_3_0dB - 63 entries */
{ 31, 1 }, { 30, 2 }, { 32, 3 }, { 29, 4 }, { 33, 5 },
{ 28, 6 }, { 34, 7 }, { 27, 8 }, { 35, 9 }, { 26, 11 },
{ 36, 11 }, { 25, 12 }, { 24, 13 }, { 37, 13 }, { 23, 14 },
{ 38, 14 }, { 22, 14 }, { 21, 14 }, { 39, 14 }, { 40, 15 },
{ 41, 16 }, { 18, 16 }, { 20, 16 }, { 19, 16 }, { 17, 17 },
{ 42, 17 }, { 43, 18 }, { 0, 18 }, { 1, 18 }, { 2, 19 },
{ 3, 19 }, { 4, 19 }, { 5, 19 }, { 6, 19 }, { 7, 19 },
{ 8, 19 }, { 9, 19 }, { 10, 19 }, { 11, 19 }, { 12, 19 },
{ 13, 19 }, { 14, 19 }, { 15, 19 }, { 16, 19 }, { 44, 19 },
{ 45, 19 }, { 46, 19 }, { 47, 19 }, { 48, 19 }, { 49, 19 },
{ 50, 19 }, { 51, 19 }, { 52, 19 }, { 53, 19 }, { 54, 19 },
{ 55, 19 }, { 56, 19 }, { 57, 19 }, { 58, 19 }, { 59, 19 },
{ 60, 19 }, { 61, 19 }, { 62, 19 },
/* f_huffman_env_3_0dB - 63 entries */
{ 31, 1 }, { 30, 2 }, { 32, 3 }, { 29, 4 }, { 33, 5 },
{ 28, 6 }, { 34, 8 }, { 27, 8 }, { 35, 9 }, { 26, 9 },
{ 36, 10 }, { 25, 10 }, { 37, 11 }, { 24, 11 }, { 38, 12 },
{ 23, 12 }, { 39, 13 }, { 40, 14 }, { 22, 14 }, { 21, 15 },
{ 41, 15 }, { 42, 15 }, { 20, 16 }, { 19, 16 }, { 43, 16 },
{ 44, 16 }, { 18, 17 }, { 16, 17 }, { 45, 17 }, { 46, 17 },
{ 17, 18 }, { 49, 18 }, { 13, 18 }, { 7, 18 }, { 12, 18 },
{ 47, 18 }, { 48, 18 }, { 9, 19 }, { 10, 19 }, { 15, 19 },
{ 51, 19 }, { 52, 19 }, { 53, 19 }, { 56, 19 }, { 8, 19 },
{ 11, 19 }, { 55, 19 }, { 0, 20 }, { 1, 20 }, { 2, 20 },
{ 3, 20 }, { 4, 20 }, { 5, 20 }, { 6, 20 }, { 14, 20 },
{ 50, 20 }, { 54, 20 }, { 57, 20 }, { 58, 20 }, { 59, 20 },
{ 60, 20 }, { 61, 20 }, { 62, 20 },
/* t_huffman_env_bal_3_0dB - 25 entries */
{ 12, 1 }, { 13, 2 }, { 11, 3 }, { 10, 4 }, { 14, 5 },
{ 15, 6 }, { 9, 7 }, { 8, 8 }, { 16, 9 }, { 7, 12 },
{ 0, 13 }, { 1, 13 }, { 2, 13 }, { 3, 13 }, { 4, 13 },
{ 5, 13 }, { 6, 13 }, { 17, 13 }, { 18, 13 }, { 19, 13 },
{ 20, 13 }, { 21, 13 }, { 22, 13 }, { 23, 14 }, { 24, 14 },
/* f_huffman_env_bal_3_0dB - 25 entries */
{ 12, 1 }, { 11, 2 }, { 13, 3 }, { 10, 4 }, { 14, 5 },
{ 15, 6 }, { 9, 7 }, { 8, 8 }, { 16, 9 }, { 7, 11 },
{ 17, 12 }, { 18, 13 }, { 0, 13 }, { 1, 13 }, { 2, 13 },
{ 3, 13 }, { 4, 13 }, { 5, 14 }, { 6, 14 }, { 19, 14 },
{ 20, 14 }, { 21, 14 }, { 22, 14 }, { 23, 14 }, { 24, 14 },
/* t_huffman_noise_3_0dB - 63 entries */
{ 31, 1 }, { 32, 2 }, { 30, 3 }, { 29, 4 }, { 33, 5 },
{ 28, 6 }, { 34, 8 }, { 27, 8 }, { 35, 10 }, { 26, 11 },
{ 36, 13 }, { 42, 13 }, { 0, 13 }, { 1, 13 }, { 2, 13 },
{ 3, 13 }, { 4, 13 }, { 5, 13 }, { 6, 13 }, { 7, 13 },
{ 8, 13 }, { 9, 13 }, { 10, 13 }, { 11, 13 }, { 12, 13 },
{ 13, 13 }, { 14, 13 }, { 15, 13 }, { 16, 13 }, { 17, 13 },
{ 18, 13 }, { 19, 13 }, { 20, 13 }, { 21, 13 }, { 22, 13 },
{ 23, 13 }, { 24, 13 }, { 25, 13 }, { 37, 13 }, { 38, 13 },
{ 39, 13 }, { 40, 13 }, { 41, 13 }, { 43, 13 }, { 44, 13 },
{ 45, 13 }, { 46, 13 }, { 47, 13 }, { 48, 13 }, { 49, 13 },
{ 50, 13 }, { 51, 13 }, { 52, 13 }, { 53, 13 }, { 54, 13 },
{ 55, 13 }, { 56, 13 }, { 57, 13 }, { 58, 13 }, { 59, 13 },
{ 60, 13 }, { 61, 14 }, { 62, 14 },
/* t_huffman_noise_bal_3_0dB - 25 entries */
{ 12, 1 }, { 11, 2 }, { 13, 3 }, { 10, 5 }, { 14, 6 },
{ 0, 8 }, { 1, 8 }, { 2, 8 }, { 3, 8 }, { 4, 8 },
{ 5, 8 }, { 6, 8 }, { 7, 8 }, { 8, 8 }, { 9, 8 },
{ 15, 8 }, { 16, 8 }, { 17, 8 }, { 18, 8 }, { 19, 8 },
{ 20, 8 }, { 21, 8 }, { 22, 8 }, { 23, 8 }, { 24, 8 },
};
static const uint8_t sbr_huffman_nb_codes[] = {
121, 121, 49, 49, 63, 63, 25, 25, 63, 25
};
static const int8_t sbr_vlc_offsets[10] = {
-60, -60, -24, -24, -31, -31, -12, -12, -31, -12
};
const VLCElem *ff_aac_sbr_vlc[10];
static av_cold void aacdec_common_init(void)
{
static VLCElem vlc_buf[(304 + 270 + 550 + 300 + 328 +
294 + 306 + 268 + 510 + 366 + 462) +
(1098 + 1092 + 768 + 1026 + 1058 +
1052 + 544 + 544 + 592 + 512)];
VLCInitState state = VLC_INIT_STATE(vlc_buf);
const uint8_t (*tab)[2] = sbr_huffman_tab;
for (unsigned i = 0; i < 11; i++) {
#define TAB_WRAP_SIZE(name) name[i], sizeof(name[i][0]), sizeof(name[i][0])
ff_vlc_spectral[i] =
ff_vlc_init_tables_sparse(&state, 8, ff_aac_spectral_sizes[i],
TAB_WRAP_SIZE(ff_aac_spectral_bits),
TAB_WRAP_SIZE(ff_aac_spectral_codes),
TAB_WRAP_SIZE(ff_aac_codebook_vector_idx),
0);
}
VLC_INIT_STATIC_TABLE(ff_vlc_scalefactors, 7,
FF_ARRAY_ELEMS(ff_aac_scalefactor_code),
ff_aac_scalefactor_bits,
sizeof(ff_aac_scalefactor_bits[0]),
sizeof(ff_aac_scalefactor_bits[0]),
ff_aac_scalefactor_code,
sizeof(ff_aac_scalefactor_code[0]),
sizeof(ff_aac_scalefactor_code[0]), 0);
// SBR VLC table initialization
for (int i = 0; i < FF_ARRAY_ELEMS(ff_aac_sbr_vlc); i++) {
ff_aac_sbr_vlc[i] =
ff_vlc_init_tables_from_lengths(&state, 9, sbr_huffman_nb_codes[i],
&tab[0][1], 2,
&tab[0][0], 2, 1,
sbr_vlc_offsets[i], 0);
tab += sbr_huffman_nb_codes[i];
}
ff_ps_init_common();
}
av_cold void ff_aacdec_common_init_once(void)
{
static AVOnce init_static_once = AV_ONCE_INIT;
ff_thread_once(&init_static_once, aacdec_common_init);
}
+48 -6
View File
@@ -66,11 +66,11 @@
#include "avcodec.h" #include "avcodec.h"
#include "codec_internal.h" #include "codec_internal.h"
#include "get_bits.h" #include "get_bits.h"
#include "lpc.h"
#include "kbdwin.h" #include "kbdwin.h"
#include "sinewin_fixed_tablegen.h" #include "sinewin_fixed_tablegen.h"
#include "aac.h" #include "aac.h"
#include "aacdec.h"
#include "aactab.h" #include "aactab.h"
#include "aacdectab.h" #include "aacdectab.h"
#include "adts_header.h" #include "adts_header.h"
@@ -89,6 +89,49 @@ DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_128))[128];
DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_long_960))[960]; DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_long_960))[960];
DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_120))[120]; DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_120))[120];
/* @name ltp_coef
* Table of the LTP coefficients
*/
static const int ltp_coef_fixed[8] = {
Q30(0.570829), Q30(0.696616), Q30(0.813004), Q30(0.911304),
Q30(0.984900), Q30(1.067894), Q30(1.194601), Q30(1.369533),
};
/* @name tns_tmp2_map
* Tables of the tmp2[] arrays of LPC coefficients used for TNS.
* The suffix _M_N[] indicate the values of coef_compress and coef_res
* respectively.
* @{
*/
static const int tns_tmp2_map_1_3[4] = {
Q31(0.00000000), Q31(-0.43388373), Q31(0.64278758), Q31(0.34202015),
};
static const int tns_tmp2_map_0_3[8] = {
Q31(0.00000000), Q31(-0.43388373), Q31(-0.78183150), Q31(-0.97492790),
Q31(0.98480773), Q31( 0.86602539), Q31( 0.64278758), Q31( 0.34202015),
};
static const int tns_tmp2_map_1_4[8] = {
Q31(0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
Q31(0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
};
static const int tns_tmp2_map_0_4[16] = {
Q31( 0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
Q31(-0.74314481), Q31(-0.86602539), Q31(-0.95105654), Q31(-0.99452192),
Q31( 0.99573416), Q31( 0.96182561), Q31( 0.89516330), Q31( 0.79801720),
Q31( 0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
};
static const int * const tns_tmp2_map_fixed[4] = {
tns_tmp2_map_0_3,
tns_tmp2_map_0_4,
tns_tmp2_map_1_3,
tns_tmp2_map_1_4
};
// @}
static av_always_inline void reset_predict_state(PredictorState *ps) static av_always_inline void reset_predict_state(PredictorState *ps)
{ {
ps->r0.mant = 0; ps->r0.mant = 0;
@@ -354,7 +397,7 @@ static const int cce_scale_fixed[8] = {
* *
* @param index index into coupling gain array * @param index index into coupling gain array
*/ */
static void apply_dependent_coupling_fixed(AACContext *ac, static void apply_dependent_coupling_fixed(AACDecContext *ac,
SingleChannelElement *target, SingleChannelElement *target,
ChannelElement *cce, int index) ChannelElement *cce, int index)
{ {
@@ -418,7 +461,7 @@ static void apply_dependent_coupling_fixed(AACContext *ac,
* *
* @param index index into coupling gain array * @param index index into coupling gain array
*/ */
static void apply_independent_coupling_fixed(AACContext *ac, static void apply_independent_coupling_fixed(AACDecContext *ac,
SingleChannelElement *target, SingleChannelElement *target,
ChannelElement *cce, int index) ChannelElement *cce, int index)
{ {
@@ -456,7 +499,7 @@ const FFCodec ff_aac_fixed_decoder = {
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"), CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
.p.type = AVMEDIA_TYPE_AUDIO, .p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC, .p.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACContext), .priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init, .init = aac_decode_init,
.close = aac_decode_close, .close = aac_decode_close,
FF_CODEC_DECODE_CB(aac_decode_frame), FF_CODEC_DECODE_CB(aac_decode_frame),
@@ -465,8 +508,7 @@ const FFCodec ff_aac_fixed_decoder = {
}, },
.p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
CODEC_OLD_CHANNEL_LAYOUTS_ARRAY(aac_channel_layout) .p.ch_layouts = ff_aac_ch_layout,
.p.ch_layouts = aac_ch_layout,
.p.priv_class = &aac_decoder_class, .p.priv_class = &aac_decoder_class,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
.flush = flush, .flush = flush,
+97 -129
View File
@@ -93,11 +93,9 @@
#include "libavutil/thread.h" #include "libavutil/thread.h"
#include "decode.h" #include "decode.h"
#include "internal.h" #include "internal.h"
#include "lpc_functions.h"
static VLC vlc_scalefactors; static int output_configure(AACDecContext *ac,
static VLC vlc_spectral[11];
static int output_configure(AACContext *ac,
uint8_t layout_map[MAX_ELEM_ID*4][3], int tags, uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
enum OCStatus oc_type, int get_new_frame); enum OCStatus oc_type, int get_new_frame);
@@ -127,7 +125,7 @@ static int count_channels(uint8_t (*layout)[3], int tags)
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static av_cold int che_configure(AACContext *ac, static av_cold int che_configure(AACDecContext *ac,
enum ChannelPosition che_pos, enum ChannelPosition che_pos,
int type, int id, int *channels) int type, int id, int *channels)
{ {
@@ -163,7 +161,7 @@ static av_cold int che_configure(AACContext *ac,
static int frame_configure_elements(AVCodecContext *avctx) static int frame_configure_elements(AVCodecContext *avctx)
{ {
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
int type, id, ch, ret; int type, id, ch, ret;
/* set channel pointers to internal buffers by default */ /* set channel pointers to internal buffers by default */
@@ -283,10 +281,10 @@ static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t
if (pos == AAC_CHANNEL_LFE) { if (pos == AAC_CHANNEL_LFE) {
while (nb_channels) { while (nb_channels) {
if (aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE) if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
return -1; return -1;
e2c_vec[i] = (struct elem_to_channel) { e2c_vec[i] = (struct elem_to_channel) {
.av_position = 1ULL << aac_channel_map[layer][pos - 1][j], .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][j],
.syn_ele = layout_map[i][0], .syn_ele = layout_map[i][0],
.elem_id = layout_map[i][1], .elem_id = layout_map[i][1],
.aac_position = pos .aac_position = pos
@@ -302,12 +300,12 @@ static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t
} }
while (nb_channels & 1) { while (nb_channels & 1) {
if (aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE) if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
return -1; return -1;
if (aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED) if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
break; break;
e2c_vec[i] = (struct elem_to_channel) { e2c_vec[i] = (struct elem_to_channel) {
.av_position = 1ULL << aac_channel_map[layer][pos - 1][0], .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][0],
.syn_ele = layout_map[i][0], .syn_ele = layout_map[i][0],
.elem_id = layout_map[i][1], .elem_id = layout_map[i][1],
.aac_position = pos .aac_position = pos
@@ -319,21 +317,21 @@ static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t
j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1; j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
while (nb_channels >= 2) { while (nb_channels >= 2) {
if (aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE || if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE ||
aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE) ff_aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
return -1; return -1;
i += assign_pair(e2c_vec, layout_map, i, i += assign_pair(e2c_vec, layout_map, i,
1ULL << aac_channel_map[layer][pos - 1][j], 1ULL << ff_aac_channel_map[layer][pos - 1][j],
1ULL << aac_channel_map[layer][pos - 1][j+1], 1ULL << ff_aac_channel_map[layer][pos - 1][j+1],
pos, layout); pos, layout);
j += 2; j += 2;
nb_channels -= 2; nb_channels -= 2;
} }
while (nb_channels & 1) { while (nb_channels & 1) {
if (aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE) if (ff_aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
return -1; return -1;
e2c_vec[i] = (struct elem_to_channel) { e2c_vec[i] = (struct elem_to_channel) {
.av_position = 1ULL << aac_channel_map[layer][pos - 1][5], .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][5],
.syn_ele = layout_map[i][0], .syn_ele = layout_map[i][0],
.elem_id = layout_map[i][1], .elem_id = layout_map[i][1],
.aac_position = pos .aac_position = pos
@@ -414,7 +412,8 @@ static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
/** /**
* Save current output configuration if and only if it has been locked. * Save current output configuration if and only if it has been locked.
*/ */
static int push_output_configuration(AACContext *ac) { static int push_output_configuration(AACDecContext *ac)
{
int pushed = 0; int pushed = 0;
if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) { if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) {
@@ -429,7 +428,8 @@ static int push_output_configuration(AACContext *ac) {
* Restore the previous output configuration if and only if the current * Restore the previous output configuration if and only if the current
* configuration is unlocked. * configuration is unlocked.
*/ */
static void pop_output_configuration(AACContext *ac) { static void pop_output_configuration(AACDecContext *ac)
{
if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) { if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
ac->oc[1] = ac->oc[0]; ac->oc[1] = ac->oc[0];
ac->avctx->ch_layout = ac->oc[1].ch_layout; ac->avctx->ch_layout = ac->oc[1].ch_layout;
@@ -444,7 +444,7 @@ static void pop_output_configuration(AACContext *ac) {
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int output_configure(AACContext *ac, static int output_configure(AACDecContext *ac,
uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags, uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
enum OCStatus oc_type, int get_new_frame) enum OCStatus oc_type, int get_new_frame)
{ {
@@ -469,13 +469,6 @@ static int output_configure(AACContext *ac,
} }
// Try to sniff a reasonable channel order, otherwise output the // Try to sniff a reasonable channel order, otherwise output the
// channels in the order the PCE declared them. // channels in the order the PCE declared them.
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
if (avctx->request_channel_layout == AV_CH_LAYOUT_NATIVE)
ac->output_channel_order = CHANNEL_ORDER_CODED;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT) if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
layout = sniff_channel_order(layout_map, tags); layout = sniff_channel_order(layout_map, tags);
for (i = 0; i < tags; i++) { for (i = 0; i < tags; i++) {
@@ -519,7 +512,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
static void flush(AVCodecContext *avctx) static void flush(AVCodecContext *avctx)
{ {
AACContext *ac= avctx->priv_data; AACDecContext *ac= avctx->priv_data;
int type, i, j; int type, i, j;
for (type = 3; type >= 0; type--) { for (type = 3; type >= 0; type--) {
@@ -540,7 +533,7 @@ static void flush(AVCodecContext *avctx)
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int set_default_channel_config(AACContext *ac, AVCodecContext *avctx, static int set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
uint8_t (*layout_map)[3], uint8_t (*layout_map)[3],
int *tags, int *tags,
int channel_config) int channel_config)
@@ -552,8 +545,8 @@ static int set_default_channel_config(AACContext *ac, AVCodecContext *avctx,
channel_config); channel_config);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
*tags = tags_per_config[channel_config]; *tags = ff_tags_per_config[channel_config];
memcpy(layout_map, aac_channel_layout_map[channel_config - 1], memcpy(layout_map, ff_aac_channel_layout_map[channel_config - 1],
*tags * sizeof(*layout_map)); *tags * sizeof(*layout_map));
/* /*
@@ -580,7 +573,7 @@ static int set_default_channel_config(AACContext *ac, AVCodecContext *avctx,
return 0; return 0;
} }
static ChannelElement *get_che(AACContext *ac, int type, int elem_id) static ChannelElement *get_che(AACDecContext *ac, int type, int elem_id)
{ {
/* For PCE based channel configurations map the channels solely based /* For PCE based channel configurations map the channels solely based
* on tags. */ * on tags. */
@@ -661,7 +654,7 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
* SCE[0] CPE[0] CPE[1] LFE[0]. * SCE[0] CPE[0] CPE[1] LFE[0].
* If we seem to have encountered such a stream, transfer * If we seem to have encountered such a stream, transfer
* the LFE[0] element to the SCE[1]'s mapping */ * the LFE[0] element to the SCE[1]'s mapping */
if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) { if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) { if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
av_log(ac->avctx, AV_LOG_WARNING, av_log(ac->avctx, AV_LOG_WARNING,
"This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n", "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
@@ -683,7 +676,7 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
* SCE[0] CPE[0] SCE[1]. * SCE[0] CPE[0] SCE[1].
* If we seem to have encountered such a stream, transfer * If we seem to have encountered such a stream, transfer
* the SCE[1] element to the LFE[0]'s mapping */ * the SCE[1] element to the LFE[0]'s mapping */
if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) { if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) { if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
av_log(ac->avctx, AV_LOG_WARNING, av_log(ac->avctx, AV_LOG_WARNING,
"This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n", "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
@@ -833,12 +826,12 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
/** /**
* Decode GA "General Audio" specific configuration; reference: table 4.1. * Decode GA "General Audio" specific configuration; reference: table 4.1.
* *
* @param ac pointer to AACContext, may be null * @param ac pointer to AACDecContext, may be null
* @param avctx pointer to AVCCodecContext, used for logging * @param avctx pointer to AVCCodecContext, used for logging
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
GetBitContext *gb, GetBitContext *gb,
int get_bit_alignment, int get_bit_alignment,
MPEG4AudioConfig *m4ac, MPEG4AudioConfig *m4ac,
@@ -919,7 +912,7 @@ static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx,
return 0; return 0;
} }
static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx, static int decode_eld_specific_config(AACDecContext *ac, AVCodecContext *avctx,
GetBitContext *gb, GetBitContext *gb,
MPEG4AudioConfig *m4ac, MPEG4AudioConfig *m4ac,
int channel_config) int channel_config)
@@ -979,7 +972,7 @@ static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx,
/** /**
* Decode audio specific configuration; reference: table 1.13. * Decode audio specific configuration; reference: table 1.13.
* *
* @param ac pointer to AACContext, may be null * @param ac pointer to AACDecContext, may be null
* @param avctx pointer to AVCCodecContext, used for logging * @param avctx pointer to AVCCodecContext, used for logging
* @param m4ac pointer to MPEG4AudioConfig, used for parsing * @param m4ac pointer to MPEG4AudioConfig, used for parsing
* @param gb buffer holding an audio specific config * @param gb buffer holding an audio specific config
@@ -988,7 +981,7 @@ static int decode_eld_specific_config(AACContext *ac, AVCodecContext *avctx,
* *
* @return Returns error status or number of consumed bits. <0 - error * @return Returns error status or number of consumed bits. <0 - error
*/ */
static int decode_audio_specific_config_gb(AACContext *ac, static int decode_audio_specific_config_gb(AACDecContext *ac,
AVCodecContext *avctx, AVCodecContext *avctx,
MPEG4AudioConfig *m4ac, MPEG4AudioConfig *m4ac,
GetBitContext *gb, GetBitContext *gb,
@@ -1055,7 +1048,7 @@ static int decode_audio_specific_config_gb(AACContext *ac,
return get_bits_count(gb); return get_bits_count(gb);
} }
static int decode_audio_specific_config(AACContext *ac, static int decode_audio_specific_config(AACDecContext *ac,
AVCodecContext *avctx, AVCodecContext *avctx,
MPEG4AudioConfig *m4ac, MPEG4AudioConfig *m4ac,
const uint8_t *data, int64_t bit_size, const uint8_t *data, int64_t bit_size,
@@ -1124,39 +1117,13 @@ static void reset_predictor_group(PredictorState *ps, int group_num)
reset_predict_state(&ps[i]); reset_predict_state(&ps[i]);
} }
static void aacdec_init(AACContext *ac); static void aacdec_init(AACDecContext *ac);
static av_cold void aac_static_table_init(void) static av_cold void aac_static_table_init(void)
{ {
static VLCElem vlc_buf[304 + 270 + 550 + 300 + 328 +
294 + 306 + 268 + 510 + 366 + 462];
for (unsigned i = 0, offset = 0; i < 11; i++) {
vlc_spectral[i].table = &vlc_buf[offset];
vlc_spectral[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset;
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)(); AAC_RENAME(ff_aac_sbr_init)();
ff_aac_tableinit(); ff_aacdec_common_init_once();
INIT_VLC_STATIC(&vlc_scalefactors, 7,
FF_ARRAY_ELEMS(ff_aac_scalefactor_code),
ff_aac_scalefactor_bits,
sizeof(ff_aac_scalefactor_bits[0]),
sizeof(ff_aac_scalefactor_bits[0]),
ff_aac_scalefactor_code,
sizeof(ff_aac_scalefactor_code[0]),
sizeof(ff_aac_scalefactor_code[0]),
352);
// window initialization // window initialization
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_long_960), 4.0, 960);
@@ -1181,7 +1148,7 @@ static AVOnce aac_table_init = AV_ONCE_INIT;
static av_cold int aac_decode_init(AVCodecContext *avctx) static av_cold int aac_decode_init(AVCodecContext *avctx)
{ {
float scale; float scale;
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
int ret; int ret;
if (avctx->sample_rate > 96000) if (avctx->sample_rate > 96000)
@@ -1279,7 +1246,7 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
/** /**
* Skip data_stream_element; reference: table 4.10. * Skip data_stream_element; reference: table 4.10.
*/ */
static int skip_data_stream_element(AACContext *ac, GetBitContext *gb) static int skip_data_stream_element(AACDecContext *ac, GetBitContext *gb)
{ {
int byte_align = get_bits1(gb); int byte_align = get_bits1(gb);
int count = get_bits(gb, 8); int count = get_bits(gb, 8);
@@ -1296,7 +1263,7 @@ static int skip_data_stream_element(AACContext *ac, GetBitContext *gb)
return 0; return 0;
} }
static int decode_prediction(AACContext *ac, IndividualChannelStream *ics, static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
GetBitContext *gb) GetBitContext *gb)
{ {
int sfb; int sfb;
@@ -1324,7 +1291,7 @@ static void decode_ltp(LongTermPrediction *ltp,
int sfb; int sfb;
ltp->lag = get_bits(gb, 11); ltp->lag = get_bits(gb, 11);
ltp->coef = ltp_coef[get_bits(gb, 3)]; ltp->coef = AAC_RENAME2(ltp_coef)[get_bits(gb, 3)];
for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++) for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
ltp->used[sfb] = get_bits1(gb); ltp->used[sfb] = get_bits1(gb);
} }
@@ -1332,7 +1299,7 @@ static void decode_ltp(LongTermPrediction *ltp,
/** /**
* Decode Individual Channel Stream info; reference: table 4.6. * Decode Individual Channel Stream info; reference: table 4.6.
*/ */
static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
GetBitContext *gb) GetBitContext *gb)
{ {
const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac; const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
@@ -1458,7 +1425,7 @@ fail:
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_band_types(AACContext *ac, enum BandType band_type[120], static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
int band_type_run_end[120], GetBitContext *gb, int band_type_run_end[120], GetBitContext *gb,
IndividualChannelStream *ics) IndividualChannelStream *ics)
{ {
@@ -1507,7 +1474,7 @@ static int decode_band_types(AACContext *ac, enum BandType band_type[120],
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_scalefactors(AACContext *ac, INTFLOAT sf[120], GetBitContext *gb, static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContext *gb,
unsigned int global_gain, unsigned int global_gain,
IndividualChannelStream *ics, IndividualChannelStream *ics,
enum BandType band_type[120], enum BandType band_type[120],
@@ -1526,7 +1493,7 @@ static int decode_scalefactors(AACContext *ac, INTFLOAT sf[120], GetBitContext *
} else if ((band_type[idx] == INTENSITY_BT) || } else if ((band_type[idx] == INTENSITY_BT) ||
(band_type[idx] == INTENSITY_BT2)) { (band_type[idx] == INTENSITY_BT2)) {
for (; i < run_end; i++, idx++) { for (; i < run_end; i++, idx++) {
offset[2] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - SCALE_DIFF_ZERO; offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
clipped_offset = av_clip(offset[2], -155, 100); clipped_offset = av_clip(offset[2], -155, 100);
if (offset[2] != clipped_offset) { if (offset[2] != clipped_offset) {
avpriv_request_sample(ac->avctx, avpriv_request_sample(ac->avctx,
@@ -1545,7 +1512,7 @@ static int decode_scalefactors(AACContext *ac, INTFLOAT sf[120], GetBitContext *
if (noise_flag-- > 0) if (noise_flag-- > 0)
offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE; offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
else else
offset[1] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - SCALE_DIFF_ZERO; offset[1] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
clipped_offset = av_clip(offset[1], -100, 155); clipped_offset = av_clip(offset[1], -100, 155);
if (offset[1] != clipped_offset) { if (offset[1] != clipped_offset) {
avpriv_request_sample(ac->avctx, avpriv_request_sample(ac->avctx,
@@ -1561,7 +1528,7 @@ static int decode_scalefactors(AACContext *ac, INTFLOAT sf[120], GetBitContext *
} }
} else { } else {
for (; i < run_end; i++, idx++) { for (; i < run_end; i++, idx++) {
offset[0] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - SCALE_DIFF_ZERO; offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
if (offset[0] > 255U) { if (offset[0] > 255U) {
av_log(ac->avctx, AV_LOG_ERROR, av_log(ac->avctx, AV_LOG_ERROR,
"Scalefactor (%d) out of range.\n", offset[0]); "Scalefactor (%d) out of range.\n", offset[0]);
@@ -1609,7 +1576,7 @@ static int decode_pulses(Pulse *pulse, GetBitContext *gb,
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_tns(AACContext *ac, TemporalNoiseShaping *tns, static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
GetBitContext *gb, const IndividualChannelStream *ics) GetBitContext *gb, const IndividualChannelStream *ics)
{ {
int w, filt, i, coef_len, coef_res, coef_compress; int w, filt, i, coef_len, coef_res, coef_compress;
@@ -1637,7 +1604,7 @@ static int decode_tns(AACContext *ac, TemporalNoiseShaping *tns,
tmp2_idx = 2 * coef_compress + coef_res; tmp2_idx = 2 * coef_compress + coef_res;
for (i = 0; i < tns->order[w][filt]; i++) for (i = 0; i < tns->order[w][filt]; i++)
tns->coef[w][filt][i] = tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]; tns->coef[w][filt][i] = AAC_RENAME2(tns_tmp2_map)[tmp2_idx][get_bits(gb, coef_len)];
} }
} }
} }
@@ -1677,7 +1644,7 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_spectrum_and_dequant(AACContext *ac, INTFLOAT coef[1024], static int decode_spectrum_and_dequant(AACDecContext *ac, INTFLOAT coef[1024],
GetBitContext *gb, const INTFLOAT sf[120], GetBitContext *gb, const INTFLOAT sf[120],
int pulse_present, const Pulse *pulse, int pulse_present, const Pulse *pulse,
const IndividualChannelStream *ics, const IndividualChannelStream *ics,
@@ -1734,7 +1701,7 @@ static int decode_spectrum_and_dequant(AACContext *ac, INTFLOAT coef[1024],
#if !USE_FIXED #if !USE_FIXED
const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; const float *vq = ff_aac_codebook_vector_vals[cbt_m1];
#endif /* !USE_FIXED */ #endif /* !USE_FIXED */
const VLCElem *vlc_tab = vlc_spectral[cbt_m1].table; const VLCElem *vlc_tab = ff_vlc_spectral[cbt_m1];
OPEN_READER(re, gb); OPEN_READER(re, gb);
switch (cbt_m1 >> 1) { switch (cbt_m1 >> 1) {
@@ -1972,7 +1939,7 @@ static int decode_spectrum_and_dequant(AACContext *ac, INTFLOAT coef[1024],
/** /**
* Apply AAC-Main style frequency domain prediction. * Apply AAC-Main style frequency domain prediction.
*/ */
static void apply_prediction(AACContext *ac, SingleChannelElement *sce) static void apply_prediction(AACDecContext *ac, SingleChannelElement *sce)
{ {
int sfb, k; int sfb, k;
@@ -2035,7 +2002,7 @@ static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_ics(AACContext *ac, SingleChannelElement *sce, static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
GetBitContext *gb, int common_window, int scale_flag) GetBitContext *gb, int common_window, int scale_flag)
{ {
Pulse pulse; Pulse pulse;
@@ -2126,7 +2093,7 @@ fail:
/** /**
* Mid/Side stereo decoding; reference: 4.6.8.1.3. * Mid/Side stereo decoding; reference: 4.6.8.1.3.
*/ */
static void apply_mid_side_stereo(AACContext *ac, ChannelElement *cpe) static void apply_mid_side_stereo(AACDecContext *ac, ChannelElement *cpe)
{ {
const IndividualChannelStream *ics = &cpe->ch[0].ics; const IndividualChannelStream *ics = &cpe->ch[0].ics;
INTFLOAT *ch0 = cpe->ch[0].coeffs; INTFLOAT *ch0 = cpe->ch[0].coeffs;
@@ -2164,7 +2131,7 @@ static void apply_mid_side_stereo(AACContext *ac, ChannelElement *cpe)
* [1] mask is decoded from bitstream; [2] mask is all 1s; * [1] mask is decoded from bitstream; [2] mask is all 1s;
* [3] reserved for scalable AAC * [3] reserved for scalable AAC
*/ */
static void apply_intensity_stereo(AACContext *ac, static void apply_intensity_stereo(AACDecContext *ac,
ChannelElement *cpe, int ms_present) ChannelElement *cpe, int ms_present)
{ {
const IndividualChannelStream *ics = &cpe->ch[1].ics; const IndividualChannelStream *ics = &cpe->ch[1].ics;
@@ -2214,7 +2181,7 @@ static void apply_intensity_stereo(AACContext *ac,
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe) static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
{ {
int i, ret, common_window, ms_present = 0; int i, ret, common_window, ms_present = 0;
int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD; int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
@@ -2267,7 +2234,7 @@ static const float cce_scale[] = {
* *
* @return Returns error status. 0 - OK, !0 - error * @return Returns error status. 0 - OK, !0 - error
*/ */
static int decode_cce(AACContext *ac, GetBitContext *gb, ChannelElement *che) static int decode_cce(AACDecContext *ac, GetBitContext *gb, ChannelElement *che)
{ {
int num_gain = 0; int num_gain = 0;
int c, g, sfb, ret; int c, g, sfb, ret;
@@ -2308,7 +2275,7 @@ static int decode_cce(AACContext *ac, GetBitContext *gb, ChannelElement *che)
INTFLOAT gain_cache = FIXR10(1.); INTFLOAT gain_cache = FIXR10(1.);
if (c) { if (c) {
cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb); cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0; gain = cge ? get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60: 0;
gain_cache = GET_GAIN(scale, gain); gain_cache = GET_GAIN(scale, gain);
#if USE_FIXED #if USE_FIXED
if ((abs(gain_cache)-1024) >> 3 > 30) if ((abs(gain_cache)-1024) >> 3 > 30)
@@ -2322,7 +2289,7 @@ static int decode_cce(AACContext *ac, GetBitContext *gb, ChannelElement *che)
for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) { for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) {
if (sce->band_type[idx] != ZERO_BT) { if (sce->band_type[idx] != ZERO_BT) {
if (!cge) { if (!cge) {
int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; int t = get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60;
if (t) { if (t) {
int s = 1; int s = 1;
t = gain += t; t = gain += t;
@@ -2417,7 +2384,7 @@ static int decode_dynamic_range(DynamicRangeControl *che_drc,
return n; return n;
} }
static int decode_fill(AACContext *ac, GetBitContext *gb, int len) { static int decode_fill(AACDecContext *ac, GetBitContext *gb, int len) {
uint8_t buf[256]; uint8_t buf[256];
int i, major, minor; int i, major, minor;
@@ -2450,7 +2417,7 @@ unknown:
* *
* @return Returns number of bytes consumed * @return Returns number of bytes consumed
*/ */
static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cnt,
ChannelElement *che, enum RawDataBlockType elem_type) ChannelElement *che, enum RawDataBlockType elem_type)
{ {
int crc_flag = 0; int crc_flag = 0;
@@ -2486,12 +2453,12 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt,
ac->avctx->ch_layout.nb_channels == 1) { ac->avctx->ch_layout.nb_channels == 1) {
ac->oc[1].m4ac.sbr = 1; ac->oc[1].m4ac.sbr = 1;
ac->oc[1].m4ac.ps = 1; ac->oc[1].m4ac.ps = 1;
ac->avctx->profile = FF_PROFILE_AAC_HE_V2; ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
ac->oc[1].status, 1); ac->oc[1].status, 1);
} else { } else {
ac->oc[1].m4ac.sbr = 1; ac->oc[1].m4ac.sbr = 1;
ac->avctx->profile = FF_PROFILE_AAC_HE; ac->avctx->profile = AV_PROFILE_AAC_HE;
} }
res = AAC_RENAME(ff_decode_sbr_extension)(ac, &che->sbr, gb, crc_flag, cnt, elem_type); res = AAC_RENAME(ff_decode_sbr_extension)(ac, &che->sbr, gb, crc_flag, cnt, elem_type);
if (ac->oc[1].m4ac.ps == 1 && !ac->warned_he_aac_mono) { if (ac->oc[1].m4ac.ps == 1 && !ac->warned_he_aac_mono) {
@@ -2543,7 +2510,7 @@ static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
continue; continue;
// tns_decode_coef // tns_decode_coef
AAC_RENAME(compute_lpc_coefs)(tns->coef[w][filt], order, lpc, 0, 0, 0); compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0);
start = ics->swb_offset[FFMIN(bottom, mmm)]; start = ics->swb_offset[FFMIN(bottom, mmm)];
end = ics->swb_offset[FFMIN( top, mmm)]; end = ics->swb_offset[FFMIN( top, mmm)];
@@ -2580,7 +2547,7 @@ static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
* Apply windowing and MDCT to obtain the spectral * Apply windowing and MDCT to obtain the spectral
* coefficient from the predicted sample by LTP. * coefficient from the predicted sample by LTP.
*/ */
static void windowing_and_mdct_ltp(AACContext *ac, INTFLOAT *out, static void windowing_and_mdct_ltp(AACDecContext *ac, INTFLOAT *out,
INTFLOAT *in, IndividualChannelStream *ics) INTFLOAT *in, IndividualChannelStream *ics)
{ {
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024); const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
@@ -2606,7 +2573,7 @@ static void windowing_and_mdct_ltp(AACContext *ac, INTFLOAT *out,
/** /**
* Apply the long term prediction * Apply the long term prediction
*/ */
static void apply_ltp(AACContext *ac, SingleChannelElement *sce) static void apply_ltp(AACDecContext *ac, SingleChannelElement *sce)
{ {
const LongTermPrediction *ltp = &sce->ics.ltp; const LongTermPrediction *ltp = &sce->ics.ltp;
const uint16_t *offsets = sce->ics.swb_offset; const uint16_t *offsets = sce->ics.swb_offset;
@@ -2638,7 +2605,7 @@ static void apply_ltp(AACContext *ac, SingleChannelElement *sce)
/** /**
* Update the LTP buffer for next frame * Update the LTP buffer for next frame
*/ */
static void update_ltp(AACContext *ac, SingleChannelElement *sce) static void update_ltp(AACDecContext *ac, SingleChannelElement *sce)
{ {
IndividualChannelStream *ics = &sce->ics; IndividualChannelStream *ics = &sce->ics;
INTFLOAT *saved = sce->saved; INTFLOAT *saved = sce->saved;
@@ -2676,7 +2643,7 @@ static void update_ltp(AACContext *ac, SingleChannelElement *sce)
/** /**
* Conduct IMDCT and windowing. * Conduct IMDCT and windowing.
*/ */
static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce) static void imdct_and_windowing(AACDecContext *ac, SingleChannelElement *sce)
{ {
IndividualChannelStream *ics = &sce->ics; IndividualChannelStream *ics = &sce->ics;
INTFLOAT *in = sce->coeffs; INTFLOAT *in = sce->coeffs;
@@ -2740,7 +2707,7 @@ static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce)
/** /**
* Conduct IMDCT and windowing. * Conduct IMDCT and windowing.
*/ */
static void imdct_and_windowing_960(AACContext *ac, SingleChannelElement *sce) static void imdct_and_windowing_960(AACDecContext *ac, SingleChannelElement *sce)
{ {
IndividualChannelStream *ics = &sce->ics; IndividualChannelStream *ics = &sce->ics;
INTFLOAT *in = sce->coeffs; INTFLOAT *in = sce->coeffs;
@@ -2801,7 +2768,7 @@ static void imdct_and_windowing_960(AACContext *ac, SingleChannelElement *sce)
memcpy( saved, buf + 480, 480 * sizeof(*saved)); memcpy( saved, buf + 480, 480 * sizeof(*saved));
} }
} }
static void imdct_and_windowing_ld(AACContext *ac, SingleChannelElement *sce) static void imdct_and_windowing_ld(AACDecContext *ac, SingleChannelElement *sce)
{ {
IndividualChannelStream *ics = &sce->ics; IndividualChannelStream *ics = &sce->ics;
INTFLOAT *in = sce->coeffs; INTFLOAT *in = sce->coeffs;
@@ -2826,7 +2793,7 @@ static void imdct_and_windowing_ld(AACContext *ac, SingleChannelElement *sce)
memcpy(saved, buf + 256, 256 * sizeof(*saved)); memcpy(saved, buf + 256, 256 * sizeof(*saved));
} }
static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce) static void imdct_and_windowing_eld(AACDecContext *ac, SingleChannelElement *sce)
{ {
UINTFLOAT *in = sce->coeffs; UINTFLOAT *in = sce->coeffs;
INTFLOAT *out = sce->ret; INTFLOAT *out = sce->ret;
@@ -2894,10 +2861,10 @@ static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce)
* *
* @param apply_coupling_method pointer to (in)dependent coupling function * @param apply_coupling_method pointer to (in)dependent coupling function
*/ */
static void apply_channel_coupling(AACContext *ac, ChannelElement *cc, static void apply_channel_coupling(AACDecContext *ac, ChannelElement *cc,
enum RawDataBlockType type, int elem_id, enum RawDataBlockType type, int elem_id,
enum CouplingPoint coupling_point, enum CouplingPoint coupling_point,
void (*apply_coupling_method)(AACContext *ac, SingleChannelElement *target, ChannelElement *cce, int index)) void (*apply_coupling_method)(AACDecContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
{ {
int i, c; int i, c;
@@ -2927,10 +2894,10 @@ static void apply_channel_coupling(AACContext *ac, ChannelElement *cc,
/** /**
* Convert spectral data to samples, applying all supported tools as appropriate. * Convert spectral data to samples, applying all supported tools as appropriate.
*/ */
static void spectral_to_sample(AACContext *ac, int samples) static void spectral_to_sample(AACDecContext *ac, int samples)
{ {
int i, type; int i, type;
void (*imdct_and_window)(AACContext *ac, SingleChannelElement *sce); void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
switch (ac->oc[1].m4ac.object_type) { switch (ac->oc[1].m4ac.object_type) {
case AOT_ER_AAC_LD: case AOT_ER_AAC_LD:
imdct_and_window = imdct_and_windowing_ld; imdct_and_window = imdct_and_windowing_ld;
@@ -2999,7 +2966,7 @@ static void spectral_to_sample(AACContext *ac, int samples)
} }
} }
static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb)
{ {
int size; int size;
AACADTSHeaderInfo hdr_info; AACADTSHeaderInfo hdr_info;
@@ -3061,10 +3028,10 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
return size; return size;
} }
static int aac_decode_er_frame(AVCodecContext *avctx, void *data, static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
int *got_frame_ptr, GetBitContext *gb) int *got_frame_ptr, GetBitContext *gb)
{ {
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac; const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
ChannelElement *che; ChannelElement *che;
int err, i; int err, i;
@@ -3075,12 +3042,12 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data,
if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
samples >>= 1; samples >>= 1;
ac->frame = data; ac->frame = frame;
if ((err = frame_configure_elements(avctx)) < 0) if ((err = frame_configure_elements(avctx)) < 0)
return err; return err;
// The FF_PROFILE_AAC_* defines are all object_type - 1 // The AV_PROFILE_AAC_* defines are all object_type - 1
// This may lead to an undefined profile being signaled // This may lead to an undefined profile being signaled
ac->avctx->profile = aot - 1; ac->avctx->profile = aot - 1;
@@ -3091,9 +3058,9 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data,
chan_config); chan_config);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
for (i = 0; i < tags_per_config[chan_config]; i++) { for (i = 0; i < ff_tags_per_config[chan_config]; i++) {
const int elem_type = aac_channel_layout_map[chan_config-1][i][0]; const int elem_type = ff_aac_channel_layout_map[chan_config-1][i][0];
const int elem_id = aac_channel_layout_map[chan_config-1][i][1]; const int elem_id = ff_aac_channel_layout_map[chan_config-1][i][1];
if (!(che=get_che(ac, elem_type, elem_id))) { if (!(che=get_che(ac, elem_type, elem_id))) {
av_log(ac->avctx, AV_LOG_ERROR, av_log(ac->avctx, AV_LOG_ERROR,
"channel element %d.%d is not allocated\n", "channel element %d.%d is not allocated\n",
@@ -3137,7 +3104,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
int *got_frame_ptr, GetBitContext *gb, int *got_frame_ptr, GetBitContext *gb,
const AVPacket *avpkt) const AVPacket *avpkt)
{ {
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
ChannelElement *che = NULL, *che_prev = NULL; ChannelElement *che = NULL, *che_prev = NULL;
enum RawDataBlockType elem_type, che_prev_type = TYPE_END; enum RawDataBlockType elem_type, che_prev_type = TYPE_END;
int err, elem_id; int err, elem_id;
@@ -3163,7 +3130,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
if ((err = frame_configure_elements(avctx)) < 0) if ((err = frame_configure_elements(avctx)) < 0)
goto fail; goto fail;
// The FF_PROFILE_AAC_* defines are all object_type - 1 // The AV_PROFILE_AAC_* defines are all object_type - 1
// This may lead to an undefined profile being signaled // This may lead to an undefined profile being signaled
ac->avctx->profile = ac->oc[1].m4ac.object_type - 1; ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
@@ -3346,7 +3313,7 @@ fail:
static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
int *got_frame_ptr, AVPacket *avpkt) int *got_frame_ptr, AVPacket *avpkt)
{ {
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
const uint8_t *buf = avpkt->data; const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size; int buf_size = avpkt->size;
GetBitContext gb; GetBitContext gb;
@@ -3408,7 +3375,7 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static av_cold int aac_decode_close(AVCodecContext *avctx) static av_cold int aac_decode_close(AVCodecContext *avctx)
{ {
AACContext *ac = avctx->priv_data; AACDecContext *ac = avctx->priv_data;
int i, type; int i, type;
for (i = 0; i < MAX_ELEM_ID; i++) { for (i = 0; i < MAX_ELEM_ID; i++) {
@@ -3431,7 +3398,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx)
return 0; return 0;
} }
static void aacdec_init(AACContext *c) static void aacdec_init(AACDecContext *c)
{ {
c->imdct_and_windowing = imdct_and_windowing; c->imdct_and_windowing = imdct_and_windowing;
c->apply_ltp = apply_ltp; c->apply_ltp = apply_ltp;
@@ -3453,23 +3420,24 @@ static void aacdec_init(AACContext *c)
* AVOptions for Japanese DTV specific extensions (ADTS only) * AVOptions for Japanese DTV specific extensions (ADTS only)
*/ */
#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM #define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
#define OFF(field) offsetof(AACDecContext, field)
static const AVOption options[] = { static const AVOption options[] = {
{"dual_mono_mode", "Select the channel to decode for dual mono", {"dual_mono_mode", "Select the channel to decode for dual mono",
offsetof(AACContext, force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2, OFF(force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2,
AACDEC_FLAGS, "dual_mono_mode"}, AACDEC_FLAGS, .unit = "dual_mono_mode"},
{"auto", "autoselection", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, {"auto", "autoselection", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
{"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
{"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
{"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, {"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
{ "channel_order", "Order in which the channels are to be exported", { "channel_order", "Order in which the channels are to be exported",
offsetof(AACContext, output_channel_order), AV_OPT_TYPE_INT, OFF(output_channel_order), AV_OPT_TYPE_INT,
{ .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, "channel_order" }, { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, .unit = "channel_order" },
{ "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST, { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST,
{ .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, "channel_order" }, { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
{ "coded", "order in which the channels are coded in the bitstream", { "coded", "order in which the channels are coded in the bitstream",
0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, "channel_order" }, 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
{NULL}, {NULL},
}; };
+17 -90
View File
@@ -1,7 +1,5 @@
/* /*
* AAC decoder data * AAC decoder data
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
* *
* This file is part of FFmpeg. * This file is part of FFmpeg.
* *
@@ -30,99 +28,28 @@
#ifndef AVCODEC_AACDECTAB_H #ifndef AVCODEC_AACDECTAB_H
#define AVCODEC_AACDECTAB_H #define AVCODEC_AACDECTAB_H
#include "libavutil/channel_layout.h"
#include "aac.h"
#include <stdint.h> #include <stdint.h>
static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 5, 5, 16, 5, 0 }; #include "vlc.h"
static const uint8_t aac_channel_layout_map[16][16][3] = { #include "libavutil/attributes_internal.h"
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, #include "libavutil/channel_layout.h"
{ { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 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_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },
{ { 0, } },
{ { 0, } },
{ { 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_BACK }, { 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_BACK }, // 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_SIDE }, // 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
},
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, { TYPE_CPE, 2, AAC_CHANNEL_FRONT }, },
{ { 0, } },
};
static const int16_t aac_channel_map[3][4][6] = { FF_VISIBILITY_PUSH_HIDDEN
{ void ff_aacdec_common_init_once(void);
{ AV_CHAN_FRONT_CENTER, AV_CHAN_FRONT_LEFT_OF_CENTER, AV_CHAN_FRONT_RIGHT_OF_CENTER, AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, AV_CHAN_BACK_CENTER },
{ AV_CHAN_LOW_FREQUENCY, AV_CHAN_LOW_FREQUENCY_2, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
},
{
{ AV_CHAN_TOP_FRONT_CENTER, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_FRONT_LEFT, AV_CHAN_TOP_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_TOP_SIDE_LEFT, AV_CHAN_TOP_SIDE_RIGHT, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_CENTER},
{ AV_CHAN_UNUSED, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_TOP_BACK_LEFT, AV_CHAN_TOP_BACK_RIGHT, AV_CHAN_TOP_BACK_CENTER},
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE},
},
{
{ AV_CHAN_BOTTOM_FRONT_CENTER, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_BOTTOM_FRONT_LEFT, AV_CHAN_BOTTOM_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
},
};
#if FF_API_OLD_CHANNEL_LAYOUT extern const VLCElem *ff_aac_sbr_vlc[10];
static const uint64_t aac_channel_layout[] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_SURROUND,
AV_CH_LAYOUT_4POINT0,
AV_CH_LAYOUT_5POINT0_BACK,
AV_CH_LAYOUT_5POINT1_BACK,
AV_CH_LAYOUT_7POINT1_WIDE_BACK,
AV_CH_LAYOUT_6POINT1_BACK,
AV_CH_LAYOUT_7POINT1,
AV_CH_LAYOUT_22POINT2,
AV_CH_LAYOUT_7POINT1_TOP_BACK,
0,
};
#endif
static const AVChannelLayout aac_ch_layout[] = { extern VLCElem ff_vlc_scalefactors[];
AV_CHANNEL_LAYOUT_MONO, extern const VLCElem *ff_vlc_spectral[11];
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND, extern const int8_t ff_tags_per_config[16];
AV_CHANNEL_LAYOUT_4POINT0,
AV_CHANNEL_LAYOUT_5POINT0_BACK, extern const uint8_t ff_aac_channel_layout_map[16][16][3];
AV_CHANNEL_LAYOUT_5POINT1_BACK,
AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, extern const int16_t ff_aac_channel_map[3][4][6];
AV_CHANNEL_LAYOUT_6POINT1_BACK,
AV_CHANNEL_LAYOUT_7POINT1, extern const AVChannelLayout ff_aac_ch_layout[];
AV_CHANNEL_LAYOUT_22POINT2, FF_VISIBILITY_POP_HIDDEN
AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK,
{ 0 },
};
#endif /* AVCODEC_AACDECTAB_H */ #endif /* AVCODEC_AACDECTAB_H */
+27 -25
View File
@@ -1106,6 +1106,18 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
too_many_bits = FFMIN(too_many_bits, 6144 * s->channels - 3); too_many_bits = FFMIN(too_many_bits, 6144 * s->channels - 3);
too_few_bits = FFMIN(FFMAX(rate_bits - rate_bits/4, target_bits), too_many_bits); too_few_bits = FFMIN(FFMAX(rate_bits - rate_bits/4, target_bits), too_many_bits);
/* When strict bit-rate control is demanded */
if (avctx->bit_rate_tolerance == 0) {
if (rate_bits < frame_bits) {
float ratio = ((float)rate_bits) / frame_bits;
s->lambda *= FFMIN(0.9f, ratio);
continue;
}
/* reset lambda when solution is found */
s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
break;
}
/* When using ABR, be strict (but only for increasing) */ /* When using ABR, be strict (but only for increasing) */
too_few_bits = too_few_bits - too_few_bits/8; too_few_bits = too_few_bits - too_few_bits/8;
too_many_bits = too_many_bits + too_many_bits/2; too_many_bits = too_many_bits + too_many_bits/2;
@@ -1198,9 +1210,6 @@ static av_cold int dsp_init(AVCodecContext *avctx, AACEncContext *s)
if (!s->fdsp) if (!s->fdsp)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
// window init
ff_aac_float_common_init();
if ((ret = av_tx_init(&s->mdct1024, &s->mdct1024_fn, AV_TX_FLOAT_MDCT, 0, if ((ret = av_tx_init(&s->mdct1024, &s->mdct1024_fn, AV_TX_FLOAT_MDCT, 0,
1024, &scale, 0)) < 0) 1024, &scale, 0)) < 0)
return ret; return ret;
@@ -1295,13 +1304,13 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
avctx->bit_rate); avctx->bit_rate);
/* Profile and option setting */ /* Profile and option setting */
avctx->profile = avctx->profile == FF_PROFILE_UNKNOWN ? FF_PROFILE_AAC_LOW : avctx->profile = avctx->profile == AV_PROFILE_UNKNOWN ? AV_PROFILE_AAC_LOW :
avctx->profile; avctx->profile;
for (i = 0; i < FF_ARRAY_ELEMS(aacenc_profiles); i++) for (i = 0; i < FF_ARRAY_ELEMS(aacenc_profiles); i++)
if (avctx->profile == aacenc_profiles[i]) if (avctx->profile == aacenc_profiles[i])
break; break;
if (avctx->profile == FF_PROFILE_MPEG2_AAC_LOW) { if (avctx->profile == AV_PROFILE_MPEG2_AAC_LOW) {
avctx->profile = FF_PROFILE_AAC_LOW; avctx->profile = AV_PROFILE_AAC_LOW;
ERROR_IF(s->options.pred, ERROR_IF(s->options.pred,
"Main prediction unavailable in the \"mpeg2_aac_low\" profile\n"); "Main prediction unavailable in the \"mpeg2_aac_low\" profile\n");
ERROR_IF(s->options.ltp, ERROR_IF(s->options.ltp,
@@ -1309,22 +1318,22 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
WARN_IF(s->options.pns, WARN_IF(s->options.pns,
"PNS unavailable in the \"mpeg2_aac_low\" profile, turning off\n"); "PNS unavailable in the \"mpeg2_aac_low\" profile, turning off\n");
s->options.pns = 0; s->options.pns = 0;
} else if (avctx->profile == FF_PROFILE_AAC_LTP) { } else if (avctx->profile == AV_PROFILE_AAC_LTP) {
s->options.ltp = 1; s->options.ltp = 1;
ERROR_IF(s->options.pred, ERROR_IF(s->options.pred,
"Main prediction unavailable in the \"aac_ltp\" profile\n"); "Main prediction unavailable in the \"aac_ltp\" profile\n");
} else if (avctx->profile == FF_PROFILE_AAC_MAIN) { } else if (avctx->profile == AV_PROFILE_AAC_MAIN) {
s->options.pred = 1; s->options.pred = 1;
ERROR_IF(s->options.ltp, ERROR_IF(s->options.ltp,
"LTP prediction unavailable in the \"aac_main\" profile\n"); "LTP prediction unavailable in the \"aac_main\" profile\n");
} else if (s->options.ltp) { } else if (s->options.ltp) {
avctx->profile = FF_PROFILE_AAC_LTP; avctx->profile = AV_PROFILE_AAC_LTP;
WARN_IF(1, WARN_IF(1,
"Chainging profile to \"aac_ltp\"\n"); "Chainging profile to \"aac_ltp\"\n");
ERROR_IF(s->options.pred, ERROR_IF(s->options.pred,
"Main prediction unavailable in the \"aac_ltp\" profile\n"); "Main prediction unavailable in the \"aac_ltp\" profile\n");
} else if (s->options.pred) { } else if (s->options.pred) {
avctx->profile = FF_PROFILE_AAC_MAIN; avctx->profile = AV_PROFILE_AAC_MAIN;
WARN_IF(1, WARN_IF(1,
"Chainging profile to \"aac_main\"\n"); "Chainging profile to \"aac_main\"\n");
ERROR_IF(s->options.ltp, ERROR_IF(s->options.ltp,
@@ -1347,6 +1356,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (s->channels > 3) if (s->channels > 3)
s->options.mid_side = 0; s->options.mid_side = 0;
// Initialize static tables
ff_aac_float_common_init();
if ((ret = dsp_init(avctx, s)) < 0) if ((ret = dsp_init(avctx, s)) < 0)
return ret; return ret;
@@ -1369,29 +1381,19 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON); ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON);
s->random_state = 0x1f2e3d4c; s->random_state = 0x1f2e3d4c;
s->abs_pow34 = abs_pow34_v; ff_aacenc_dsp_init(&s->aacdsp);
s->quant_bands = quantize_bands;
#if ARCH_X86
ff_aac_dsp_init_x86(s);
#endif
#if HAVE_MIPSDSP
ff_aac_coder_init_mips(s);
#endif
ff_af_queue_init(avctx, &s->afq); ff_af_queue_init(avctx, &s->afq);
ff_aac_tableinit();
return 0; return 0;
} }
#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM #define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
static const AVOption aacenc_options[] = { static const AVOption aacenc_options[] = {
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"}, {"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, .unit = "coder"},
{"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, {"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, {"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"fast", "Default fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"}, {"fast", "Default fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS}, {"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS},
{"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS}, {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS}, {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
+91 -6
View File
@@ -22,19 +22,25 @@
#ifndef AVCODEC_AACENC_H #ifndef AVCODEC_AACENC_H
#define AVCODEC_AACENC_H #define AVCODEC_AACENC_H
#include <stdint.h>
#include "libavutil/channel_layout.h" #include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h" #include "libavutil/float_dsp.h"
#include "libavutil/mem_internal.h" #include "libavutil/mem_internal.h"
#include "libavutil/tx.h"
#include "avcodec.h" #include "avcodec.h"
#include "put_bits.h" #include "put_bits.h"
#include "aac.h" #include "aac.h"
#include "aacencdsp.h"
#include "audio_frame_queue.h" #include "audio_frame_queue.h"
#include "psymodel.h" #include "psymodel.h"
#include "lpc.h" #include "lpc.h"
#define CLIP_AVOIDANCE_FACTOR 0.95f
typedef enum AACCoder { typedef enum AACCoder {
AAC_CODER_ANMR = 0, AAC_CODER_ANMR = 0,
AAC_CODER_TWOLOOP, AAC_CODER_TWOLOOP,
@@ -54,6 +60,90 @@ typedef struct AACEncOptions {
int intensity_stereo; int intensity_stereo;
} AACEncOptions; } AACEncOptions;
/**
* Long Term Prediction
*/
typedef struct LongTermPrediction {
int8_t present;
int16_t lag;
int coef_idx;
float coef;
int8_t used[MAX_LTP_LONG_SFB];
} LongTermPrediction;
/**
* Individual Channel Stream
*/
typedef struct IndividualChannelStream {
uint8_t max_sfb; ///< number of scalefactor bands per group
enum WindowSequence window_sequence[2];
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
uint8_t group_len[8];
LongTermPrediction ltp;
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window
int num_swb; ///< number of scalefactor window bands
int num_windows;
int tns_max_bands;
int predictor_present;
int predictor_initialized;
int predictor_reset_group;
int predictor_reset_count[31]; ///< used to count prediction resets
uint8_t prediction_used[41];
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
float clip_avoidance_factor; ///< set if any window is near clipping to the necessary atennuation factor to avoid it
} IndividualChannelStream;
/**
* Temporal Noise Shaping
*/
typedef struct TemporalNoiseShaping {
int present;
int n_filt[8];
int length[8][4];
int direction[8][4];
int order[8][4];
int coef_idx[8][4][TNS_MAX_ORDER];
float coef[8][4][TNS_MAX_ORDER];
} TemporalNoiseShaping;
/**
* Single Channel Element - used for both SCE and LFE elements.
*/
typedef struct SingleChannelElement {
IndividualChannelStream ics;
TemporalNoiseShaping tns;
Pulse pulse;
enum BandType band_type[128]; ///< band types
enum BandType band_alt[128]; ///< alternative band type
int sf_idx[128]; ///< scalefactor indices
uint8_t zeroes[128]; ///< band is not coded
uint8_t can_pns[128]; ///< band is allowed to PNS (informative)
float is_ener[128]; ///< Intensity stereo pos
float pns_ener[128]; ///< Noise energy values
DECLARE_ALIGNED(32, float, pcoeffs)[1024]; ///< coefficients for IMDCT, pristine
DECLARE_ALIGNED(32, float, coeffs)[1024]; ///< coefficients for IMDCT, maybe processed
DECLARE_ALIGNED(32, float, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, float, ltp_state)[3072]; ///< time signal for LTP
DECLARE_ALIGNED(32, float, lcoeffs)[1024]; ///< MDCT of LTP coefficients
DECLARE_ALIGNED(32, float, prcoeffs)[1024]; ///< Main prediction coefs
PredictorState predictor_state[MAX_PREDICTORS];
} SingleChannelElement;
/**
* channel element - generic struct for SCE/CPE/CCE/LFE
*/
typedef struct ChannelElement {
// CPE specific
int common_window; ///< Set if channels share a common 'IndividualChannelStream' in bitstream.
int ms_mode; ///< Signals mid/side stereo flags coding mode
uint8_t is_mode; ///< Set if any bands have been encoded using intensity stereo
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
uint8_t is_mask[128]; ///< Set if intensity stereo is used
// shared
SingleChannelElement ch[2];
} ChannelElement;
struct AACEncContext; struct AACEncContext;
typedef struct AACCoefficientsEncoder { typedef struct AACCoefficientsEncoder {
@@ -144,18 +234,13 @@ typedef struct AACEncContext {
uint16_t quantize_band_cost_cache_generation; uint16_t quantize_band_cost_cache_generation;
AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost
void (*abs_pow34)(float *out, const float *in, const int size); AACEncDSPContext aacdsp;
void (*quant_bands)(int *out, const float *in, const float *scaled,
int size, int is_signed, int maxval, const float Q34,
const float rounding);
struct { struct {
float *samples; float *samples;
} buffer; } buffer;
} AACEncContext; } AACEncContext;
void ff_aac_dsp_init_x86(AACEncContext *s);
void ff_aac_coder_init_mips(AACEncContext *c);
void ff_quantize_band_cost_cache_init(struct AACEncContext *s); void ff_quantize_band_cost_cache_init(struct AACEncContext *s);
+3 -3
View File
@@ -59,9 +59,9 @@ struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
float minthr = FFMIN(band0->threshold, band1->threshold); float minthr = FFMIN(band0->threshold, band1->threshold);
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01); IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);
s->abs_pow34(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
s->abs_pow34(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
s->abs_pow34(I34, IS, sce0->ics.swb_sizes[g]); s->aacdsp.abs_pow34(I34, IS, sce0->ics.swb_sizes[g]);
maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34); maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
is_band_type = find_min_book(maxval, is_sf_idx); is_band_type = find_min_book(maxval, is_sf_idx);
dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34, dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34,
+6 -6
View File
@@ -37,7 +37,7 @@ void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce,
{ {
int i; int i;
IndividualChannelStream *ics = &sce->ics; IndividualChannelStream *ics = &sce->ics;
if (s->profile != FF_PROFILE_AAC_LTP || !ics->predictor_present) if (s->profile != AV_PROFILE_AAC_LTP || !ics->predictor_present)
return; return;
if (common_window) if (common_window)
put_bits(&s->pb, 1, 0); put_bits(&s->pb, 1, 0);
@@ -92,8 +92,8 @@ static void get_lag(float *buf, const float *new, LongTermPrediction *ltp)
} }
} }
ltp->lag = FFMAX(av_clip_uintp2(lag, 11), 0); ltp->lag = FFMAX(av_clip_uintp2(lag, 11), 0);
ltp->coef_idx = quant_array_idx(max_ratio, ltp_coef, 8); ltp->coef_idx = quant_array_idx(max_ratio, ff_ltp_coef, 8);
ltp->coef = ltp_coef[ltp->coef_idx]; ltp->coef = ff_ltp_coef[ltp->coef_idx];
} }
static void generate_samples(float *buf, LongTermPrediction *ltp) static void generate_samples(float *buf, LongTermPrediction *ltp)
@@ -119,7 +119,7 @@ void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce)
float *pred_signal = &sce->ltp_state[0]; float *pred_signal = &sce->ltp_state[0];
const float *samples = &s->planar_samples[s->cur_channel][1024]; const float *samples = &s->planar_samples[s->cur_channel][1024];
if (s->profile != FF_PROFILE_AAC_LTP) if (s->profile != AV_PROFILE_AAC_LTP)
return; return;
/* Calculate lag */ /* Calculate lag */
@@ -190,8 +190,8 @@ void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce,
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
for (i = 0; i < sce->ics.swb_sizes[g]; i++) for (i = 0; i < sce->ics.swb_sizes[g]; i++)
PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i]; PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i];
s->abs_pow34(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]); s->aacdsp.abs_pow34(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]);
s->abs_pow34(PCD34, PCD, sce->ics.swb_sizes[g]); s->aacdsp.abs_pow34(PCD34, PCD, sce->ics.swb_sizes[g]);
dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g], dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g],
sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g], sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g],
s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL); s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL);

Some files were not shown because too many files have changed in this diff Show More