mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-10 08:50:03 +01:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0723b7e4e | ||
|
|
6fbd4d2285 | ||
|
|
fa511b03d3 | ||
|
|
5767941df8 | ||
|
|
e6584a3f19 | ||
|
|
e8a51675ea | ||
|
|
1c06f776e6 | ||
|
|
e95f80c8df | ||
|
|
6a78425604 | ||
|
|
288ef1939f | ||
|
|
cd894807fe | ||
|
|
22878e8177 | ||
|
|
d6a1e5980b | ||
|
|
83feded492 | ||
|
|
2720715dab | ||
|
|
e04cb59ecc | ||
|
|
b21d387d6f |
1
.mailmap
1
.mailmap
@@ -1,3 +1,4 @@
|
||||
<james.darnley@gmail.com> <jdarnley@obe.tv>
|
||||
<jeebjp@gmail.com> <jan.ekstrom@aminocom.com>
|
||||
<sw@jkqxz.net> <mrt@jkqxz.net>
|
||||
<u@pkh.me> <cboesch@gopro.com>
|
||||
|
||||
4
CREDITS
4
CREDITS
@@ -1,6 +1,6 @@
|
||||
See the Git history of the project (https://git.ffmpeg.org/ffmpeg) to
|
||||
See the Git history of the project (git://source.ffmpeg.org/ffmpeg) to
|
||||
get the names of people who have contributed to FFmpeg.
|
||||
|
||||
To check the log, you can type the command "git log" in the FFmpeg
|
||||
source directory, or browse the online repository at
|
||||
https://git.ffmpeg.org/ffmpeg
|
||||
http://source.ffmpeg.org.
|
||||
|
||||
464
Changelog
464
Changelog
@@ -1,469 +1,8 @@
|
||||
Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version 6.1.2
|
||||
avcodec/snow: Fix off by 1 error in run_buffer
|
||||
avcodec/utils: apply the same alignment to YUV410 as we do to YUV420 for snow
|
||||
swscale: [loongarch] Fix checkasm-sw_yuv2rgb failure.
|
||||
avcodec/pngenc: fix sBIT writing for indexed-color PNGs
|
||||
avcodec/pngdec: use 8-bit sBIT cap for indexed PNGs per spec
|
||||
avcodec/videotoolboxenc: Fix bitrate doesn't work as expected
|
||||
Changelog: update
|
||||
avdevice/dshow: Don't skip audio devices if no video device is present
|
||||
avcodec/hdrenc: Allocate more space
|
||||
avcodec/cfhdenc: Height of 16 is not supported
|
||||
avcodec/cfhdenc: Allocate more space
|
||||
avcodec/osq: fix integer overflow when applying factor
|
||||
avcodec/osq: avoid using too large numbers for shifts and integers in update_residue_parameter()
|
||||
avcodec/vaapi_encode: Check hwctx
|
||||
avcodec/proresdec: Consider negative bits left
|
||||
avcodec/alsdec: Clear shift_value
|
||||
avcodec/hevc/hevcdec: Do not allow slices to depend on failed slices
|
||||
avfilter/vf_xfade: Check ff_inlink_consume_frame() for failure
|
||||
avutil/slicethread: Check pthread_*_init() for failure
|
||||
avutil/frame: Check log2_crop_align
|
||||
avutil/buffer: Check ff_mutex_init() for failure
|
||||
avformat/xmv: Check this_packet_size
|
||||
avformat/ty: rec_size seems to only need 32bit
|
||||
avformat/tty: Check avio_size()
|
||||
avformat/siff: Basic pkt_size check
|
||||
avformat/sauce: Check avio_size() for failure
|
||||
avformat/sapdec: Check ffurl_get_file_handle() for error
|
||||
avformat/nsvdec: Check asize for PCM
|
||||
avformat/mp3dec: Check header_filesize
|
||||
avformat/mp3dec; Check for avio_size() failure
|
||||
avformat/mov: Use 64bit for str_size
|
||||
avformat/mm: Check length
|
||||
avformat/hnm: Check *chunk_size
|
||||
avformat/hlsenc: Check ret
|
||||
avformat/bintext: Check avio_size() return
|
||||
avformat/asfdec_o: Check size of index object
|
||||
avfilter/vf_scale: Check ff_scale_adjust_dimensions() for failure
|
||||
avfilter/scale_eval: Use 64bit, check values in ff_scale_adjust_dimensions()
|
||||
avfilter/vf_lut3d: Check av_scanf()
|
||||
avfilter/vf_elbg: Use unsigned for shifting into the top bit
|
||||
avfilter/vf_deshake_opencl: Ensure that the first iteration initializes the best variables
|
||||
swscale/output: Fix integer overflows in yuv2rgba64_X_c_template
|
||||
avformat/mxfdec: Reorder elements of expression in bisect loop
|
||||
avutil/timecode: Use a 64bit framenum internally
|
||||
avcodec/pnmdec: Use 64bit for input size check
|
||||
avcodec/mpeg12enc: Use av_rescale() in vbv_buffer_size computation
|
||||
avcodec/utvideoenc: Use unsigned shift to build flags
|
||||
avcodec/j2kenc: Merge dwt_norm into lambda
|
||||
avcodec/vc2enc: Fix overflows with storing large values
|
||||
avcodec/mpegvideo_enc: Do not duplicate pictures on shifting
|
||||
avdevice/dshow_capture: Fix error handling in ff_dshow_##prefix##_Create()
|
||||
avcodec/tiff: Check value on positive signed targets
|
||||
avfilter/vf_convolution_opencl: Assert that the filter name is one of the filters
|
||||
avfilter/vf_bm3d: Dont round MSE2SSE to an integer
|
||||
avdevice/dshow: Remove NULL check on pin
|
||||
avdevice/dshow: check ff_dshow_pin_ConnectionMediaType() for failure
|
||||
avdevice/dshow: Check device_filter_unique_name before use
|
||||
avdevice/dshow: Cleanup also on av_log case
|
||||
avdevice/dshow_filter: Use wcscpy_s()
|
||||
avcodec/flac_parser: Assert that we do not overrun the link_penalty array
|
||||
avcodec/osq: avoid signed overflow in downsample path
|
||||
avcodec/pixlet: Simplify pfx computation
|
||||
avcodec/motion_est: Fix score squaring overflow
|
||||
avcodec/mlpenc: Use 64 for ml, mr
|
||||
avcodec/loco: Check loco_get_rice() for failure
|
||||
avcodec/loco: check get_ur_golomb_jpegls() for failure
|
||||
avcodec/imm4: check cbphi for error
|
||||
avcodec/iff: Use signed count
|
||||
avcodec/golomb: Assert that k is in the supported range for get_ur/sr_golomb()
|
||||
avcodec/golomb: Document return for get_ur_golomb_jpegls() and get_sr_golomb_flac()
|
||||
avcodec/dxv: Fix type in get_opcodes()
|
||||
avcodec/cri: Check length
|
||||
avcodec/xsubdec: Check parse_timecode()
|
||||
avutil/imgutils: av_image_check_size2() ensure width and height fit in 32bit
|
||||
doc/examples/mux: remove nop
|
||||
avcodec/proresenc_kostya: use unsigned alpha for rotation
|
||||
avformat/rtpenc_rfc4175: Use 64bit in computation if copy_offset
|
||||
avformat/rtmppkt: Simplify and deobfuscate amf_tag_skip() slightly
|
||||
avformat/rmdec: use 64bit for audio_framesize checks
|
||||
avutil/wchar_filename: Correct sizeof
|
||||
avutil/hwcontext_d3d11va: correct sizeof IDirect3DSurface9
|
||||
avutil/hwcontext_d3d11va: Free AVD3D11FrameDescriptor on error
|
||||
avutil/hwcontext_d3d11va: correct sizeof AVD3D11FrameDescriptor
|
||||
doc/examples/vaapi_encode: Try to check fwrite() for failure
|
||||
avformat/usmdec: Initialize value
|
||||
avformat/tls_schannel: Initialize ret
|
||||
avformat/subfile: Assert that whence is a known case
|
||||
avformat/subfile: Merge if into switch()
|
||||
avformat/rtsp: Check that lower transport is handled in one of the if()
|
||||
avformat/rtsp: initialize reply1
|
||||
avformat/rtsp: use < 0 for error check
|
||||
avformat/rtpenc_vc2hq: Check sizes
|
||||
avfilter/af_aderivative: Free out on error
|
||||
swscale/swscale: Use ptrdiff_t for linesize computations
|
||||
avfilter/af_afir: Assert format
|
||||
avfilter/af_afftdn: Assert format
|
||||
avfilter/af_pan: check nb_output_channels before use
|
||||
cbs_av1: Reject thirty-two zero bits in uvlc code
|
||||
avfilter/af_mcompand: compute half frequency in double
|
||||
avfilter/af_channelsplit: Assert that av_channel_layout_channel_from_index() succeeds
|
||||
avfilter/af_aresample: Cleanup on av_channel_layout_copy() failure
|
||||
tools/coverity: Phase 1 study of anti-halicogenic for coverity av_rescale()
|
||||
avfilter/vf_avgblur: Check plane instead of AVFrame
|
||||
avfilter/drawutils: Fix depthb computation
|
||||
avfilter/avf_showcwt: Check av_parse_video_rate() for failure
|
||||
avformat/rdt: Check pkt_len
|
||||
avformat/mpeg: Check len in mpegps_probe()
|
||||
avformat/mxfenc: resurrects the error print
|
||||
avdevice/dshow: Check ICaptureGraphBuilder2_SetFiltergraph() for failure
|
||||
avcodec/mfenc: check IMFSample_ConvertToContiguousBuffer() for failure
|
||||
avcodec/vc1_loopfilter: Factor duplicate code in vc1_b_h_intfi_loop_filter()
|
||||
avformat/img2dec: assert no pipe on ts_from_file
|
||||
avcodec/cbs_jpeg: Try to move the read entity to one side in a test
|
||||
fftools/ffmpeg_enc: Initialize fd
|
||||
fftools/ffmpeg_enc: simplify opaque_ref check
|
||||
avformat/mov: Check edit list for overflow
|
||||
fftools/ffmpeg: Check read() for failure
|
||||
MAINTAINERS: Add Timo Rothenpieler to server admins
|
||||
swscale/output: Avoid undefined overflow in yuv2rgb_write_full()
|
||||
swscale/output: alpha can become negative after scaling, use multiply
|
||||
avcodec/targaenc: Allocate space for the palette
|
||||
avcodec/r210enc: Use av_rescale for bitrate
|
||||
avcodec/jfdctint_template: Fewer integer anomalies
|
||||
avcodec/snowenc: MV limits due to mv_penalty table size
|
||||
tools/target_dec_fuzzer: Adjust threshold for MV30
|
||||
tools/target_dec_fuzzer: Adjust threshold for jpeg2000
|
||||
avformat/mxfdec: Check container_ul->desc before use
|
||||
avcodec/libvpxenc: Cleanup on error
|
||||
MAINTAINERS: Update the entries for the release maintainer for FFmpeg
|
||||
configure: update copyright year
|
||||
doc/developer: Provide information about git send-email and gmail
|
||||
avfilter/vf_rotate: Check ff_draw_init2() return value
|
||||
avformat/mov: Use int64_t in intermediate for corrected_dts
|
||||
avformat/mov: Use 64bit in intermediate for current_dts
|
||||
avformat/matroskadec: Assert that num_levels is non negative
|
||||
avformat/libzmq: Check av_strstart()
|
||||
avformat/img2dec: Little JFIF / Exif cleanup
|
||||
avformat/img2dec: Move DQT after unrelated if()
|
||||
avformat/imfdec: Simplify get_next_track_with_minimum_timestamp()
|
||||
avdevice/xcbgrab: Check sscanf() return
|
||||
fftools/cmdutils: Add protective () to FLAGS
|
||||
avformat/sdp: Check before appending ","
|
||||
avcodec/ilbcdec: Remove dead code
|
||||
avcodec/vp8: Check cond init
|
||||
avcodec/vp8: Check mutex init
|
||||
avcodec/proresenc_anatoliy: Assert that AV_PROFILE_UNKNOWN is replaced
|
||||
avcodec/pcm-dvdenc: 64bit pkt-size
|
||||
avcodec/notchlc: Check init_get_bits8() for failure
|
||||
avcodec/tests/dct: Use 64bit in intermediate for error computation
|
||||
avcodec/scpr3: Check add_dec() for failure
|
||||
avcodec/rv34: assert that size is not 0 in rv34_gen_vlc_ext()
|
||||
avcodec/wavpackenc: Use unsigned for potential 31bit shift
|
||||
avcodec/tests/jpeg2000dwt: Use 64bit in comparission
|
||||
avcodec/tests/jpeg2000dwt: Use 64bit in err2 computation
|
||||
avformat/fwse: Remove always false expression
|
||||
avcodec/sga: Make it clear that the return is intentionally not checked
|
||||
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
|
||||
fftools/ffmpeg: prefer real errors over EOF in err_merge()
|
||||
avcodec/png: more informative error message for invalid sBIT size
|
||||
avcodec/pngdec: avoid erroring with sBIT on indexed-color images
|
||||
avcodec/nvenc: fix segfault in intra-only mode
|
||||
aarch64: Add OpenBSD runtime detection of dotprod and i8mm using sysctl
|
||||
qsv: Initialize impl_value
|
||||
avutil/hwcontext_qsv: fix GCC 14.1 warnings
|
||||
lavc/vp9: reset segmentation fields when segmentation isn't enabled
|
||||
configure: enable ffnvcodec, nvenc, nvdec for FreeBSD
|
||||
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/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
|
||||
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
|
||||
avutil/thread: fix pthread_setname_np parameters for NetBSD and Apple
|
||||
avutil/thread: add support for setting thread name on *bsd and solaris
|
||||
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
|
||||
avfilter/avfilter: fix OOM case for default activate
|
||||
avfilter/buffersrc: switch to activate
|
||||
avcodec/mediacodecenc: set quality in cq mode
|
||||
Update for 6.1.2
|
||||
fate/subtitles: Ignore line endings for sub-scc test
|
||||
avformat/mxfdec: Check index_edit_rate
|
||||
swscale/utils: Fix xInc overflow
|
||||
avcodec/wavarc: fix signed integer overflow in block type 6/19
|
||||
doc/developer: (security) researchers should be credited
|
||||
avformat/isom: Uninit layout in ff_mp4_read_dec_config_descr()
|
||||
avcodec/exr: Dont use 64bits to hold 6bits
|
||||
avcodec/exr: Check for remaining bits in huf_unpack_enc_table()
|
||||
avcodec/apedec: Use NABS to avoid undefined negation
|
||||
avformat/mpegts: Reset local nb_prg on add_program() failure
|
||||
avformat/aiffdec: Check for previously set channels
|
||||
avformat/mxfdec: Make edit_unit_byte_count unsigned
|
||||
avformat/movenc: Check that cts fits in 32bit
|
||||
avformat/mxfdec: Check first case of offset_temp computation for overflow
|
||||
avcodec/jpeg2000htdec: warn about non zero roi shift
|
||||
avcodec/jpeg2000htdec: Check magp before using it in a shift
|
||||
avfilter/vf_signature: Dont crash on no frames
|
||||
avformat/westwood_vqa: Fix 2g packets
|
||||
avformat/matroskadec: Check timescale
|
||||
avformat/wavdec: satuarte next_tag_ofs, data_end
|
||||
avformat/wavdec: sanity check channels and bps before using them for block_align
|
||||
avformat/sbgdec: Check for negative duration
|
||||
avformat/rpl: Use 64bit for total_audio_size and check it
|
||||
avformat/timecode: use 64bit for intermediate for rounding in fps_from_frame_rate()
|
||||
avformat/mov: use 64bit for intermediate for rounding
|
||||
avformat/jacosubdec: Use 64bit for abs
|
||||
avformat/concatdec: Check user_duration sum
|
||||
avcodec/wavarc: avoid signed integer overflow in AC code
|
||||
avcodec/wavarc: Avoid signed integer overflow in sample
|
||||
avcodec/truemotion1: Height not being a multiple of 4 is unsupported
|
||||
avcodec/rtv1: fix undefined FFALIGN
|
||||
avcodec/hcadec: do not allow code to continue after failed init
|
||||
avcodec/hcadec: do not set hfr_group_count to invalid values
|
||||
avformat/concatdec: clip outpoint - inpoint overflow in get_best_effort_duration()
|
||||
avcodec/osq: avoid several signed integer overflows
|
||||
avformat/jacosubdec: clarify code
|
||||
avformat/cafdec: Check that data chunk end fits within 64bit
|
||||
avformat/iff: Saturate avio_tell() + 12
|
||||
avformat/dxa: Adjust order of operations around block align
|
||||
avformat/cafdec: dont seek beyond 64bit
|
||||
avformat/id3v2: read_uslt() check for the amount read
|
||||
avcodec/vmixdec: Check shift before use
|
||||
avformat/mov: Check sample_count and auxiliary_info_default_size to be 0
|
||||
avformat/wady: Check >0 samplerate and channels 1 || 2.
|
||||
avcodec/cbs_h266_syntax_template: Check tile_y
|
||||
avcodec/proresenc_kostya: Remove bug similarity text
|
||||
avcodec/vorbisdec: Check remaining data in vorbis_residue_decode_internal()
|
||||
avformat/concatdec: Check in and outpoints to be to produce a positive representable duration
|
||||
avcodec/8bps: Consider width in the minimal size check
|
||||
libswscale/utils: Fix bayer to yuvj
|
||||
swscale/swscale: Check srcSliceH for bayer
|
||||
swscale/utils: Allocate more dithererror
|
||||
avcodec/indeo3: Round dimensions up in allocate_frame_buffers()
|
||||
avutil/rational: Document what is to be expected from av_d2q() of doubles representing rational numbers
|
||||
avfilter/signature_lookup: Do not dereference NULL pointers after malloc failure
|
||||
avfilter/signature_lookup: dont leave uncleared pointers in sll_free()
|
||||
avcodec/mpegvideo_enc: Use ptrdiff_t for stride
|
||||
libavformat/hlsenc.c: Populate OTI using AAC profile in write_codec_attr.
|
||||
avformat/mov: Check if a key is longer than the atom containing it
|
||||
avcodec/nvenc: support SDK 12.2 bit depth API
|
||||
avcodec/nvenc: stop using long deprecated format specifiers
|
||||
avfilter/buffersrc: fix overriding unknown channel layouts with negotiated one
|
||||
avfilter/af_channelmap: disallow channel index 64
|
||||
avfilter/af_channelmap: fix mapping if in_channel was a string but out_channel was not specified
|
||||
avfilter/af_channelmap: fix error message if FL source channel was missing
|
||||
avcodec/nvdec: reset bitstream_len/nb_slices when resetting bitstream pointer
|
||||
avformat/mov: don't abort on duplicate Mastering Display Metadata boxes
|
||||
fftools/ffplay: use correct buffersink channel layout parameters
|
||||
avformat/mpegts: detect synchronous metadata KLV more reliably
|
||||
swresample/resample: fix rounding errors with filter_size=1 and phase_shift=0
|
||||
avformat/mxfdec: remove resolve_strong_ref usage with AnyType
|
||||
avfilter/vf_convolution: add float user_rdiv[4] to allow user options to apply correctly
|
||||
avformat/libsrt: use SRT_EPOLL_IN for waiting for an incoming connection
|
||||
avformat/mxfdec: do not use AnyType when resolving Descriptors and MultipleDescriptors
|
||||
avformat/mxfdec: move resolving Descriptors to the multi descriptor resolve function
|
||||
avutil/hwcontext_d3d11va: prefer DXGI 1.1 factory when available
|
||||
avcodec/libsvtav1: send the EOS signal without a one frame delay to allow for the library to operate in a low-delay mode
|
||||
avcodec/libsvtav1: add version guard for external param
|
||||
lavc/vvc: Read subpic ID when only one subpicture is present
|
||||
lavc/vvc: Correct sps_num_subpics_minus1 minimum
|
||||
avcodec/cbs_h2645: Avoid function pointer casts, fix UB
|
||||
avcodec/cbs_h266_syntax_template: Don't omit unused function parameter
|
||||
avcodec/cbs_h266_syntax_template: check aps_adaptation_parameter_set_id
|
||||
lavc/vvc: Add check to num_multi_layer_olss
|
||||
avcodec/cbs_h266: fix logic setting num_layers_in_ols when vps_ols_mode_idc is 2
|
||||
avcodec/av1dec: fix matrix coefficients exposed by codec context
|
||||
{avcodec,tests}: rename the bundled Mesa AV1 vulkan video headers
|
||||
avformat/mov_chan: never override number of channels based on chan atom
|
||||
avformat/mov_chan: do not assume channels are in native order
|
||||
avfft: avoid overreads with RDFT API users
|
||||
avcodec/nvdec: don't free NVDECContext->bitstream
|
||||
avcodec/mediacodecdec: fix return EAGAIN after EOF
|
||||
|
||||
|
||||
version 6.1.1
|
||||
- avcodec/mpegvideo_enc: Dont copy beyond the image
|
||||
- avfilter/vf_minterpolate: Check pts before division
|
||||
- avfilter/avf_showwaves: Check history_nb_samples
|
||||
- avformat/flacdec: Avoid double AVERRORS
|
||||
- avfilter/vf_vidstabdetect: Avoid double AVERRORS
|
||||
- avcodec/vaapi_encode: Avoid double AVERRORS
|
||||
- avfilter/vf_swaprect: round coordinates down
|
||||
- avfilter/vf_swaprect: Use height for vertical variables
|
||||
- avfilter/vf_swaprect: assert that rectangles are within memory
|
||||
- avfilter/af_alimiter: Check nextpos before use
|
||||
- avfilter/f_reverse: Apply PTS compensation only when pts is available
|
||||
- avfilter/af_stereowiden: Check length
|
||||
- avformat/mov: Fix MSAN issue with stsd_id
|
||||
- avcodec/jpegxl_parser: Check get_vlc2()
|
||||
- avfilter/vf_weave: Fix odd height handling
|
||||
- avfilter/edge_template: Fix small inputs with gaussian_blur()
|
||||
- avfilter/vf_gradfun: Do not overread last line
|
||||
- avfilter/avf_showspectrum: fix off by 1 error
|
||||
- avcodec/jpegxl_parser: Add padding to cs_buffer
|
||||
- avformat/mov: do not set sign bit for chunk_offsets
|
||||
- avcodec/jpeglsdec: Check Jpeg-LS LSE
|
||||
- avcodec/osq: Implement flush()
|
||||
- configure: Enable section_data_rel_ro for FreeBSD and NetBSD aarch64 / arm
|
||||
- avcodec/cbs_h266: more restrictive check on pps_tile_idx_delta_val
|
||||
- avcodec/jpeg2000htdec: check if block decoding will exceed internal precision
|
||||
- tools/target_dec_fuzzer: Adjust threshold for VMIX
|
||||
- avcodec/av1dec: Fix resolving zero divisor
|
||||
- avformat/mov: Ignore duplicate ftyp
|
||||
- avformat/mov: Fix integer overflow in mov_read_packet().
|
||||
- lavc/qsvdec: return 0 if more data is required
|
||||
- avcodec/jpegxl_parser: check ANS cluster alphabet size vs bundle size
|
||||
- libavformat/vvc: Make probe more conservative
|
||||
- hwcontext_vulkan: guard unistd.h include
|
||||
- lavc/Makefile: build vulkan decode code if vulkan_av1 has been enabled
|
||||
- lavc/dvdsubenc: only check canvas size when it is actually set
|
||||
- avcodec/decode: validate hw_frames_ctx when AVHWAccel.free_frame_priv is used
|
||||
- avcoded/fft: Fix memory leak if ctx2 is used
|
||||
- avcodec/fft: Use av_mallocz to avoid invalid free/uninit
|
||||
|
||||
|
||||
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:
|
||||
- Radiance HDR image support
|
||||
- ddagrab (Desktop Duplication) video capture filter
|
||||
- ffmpeg -shortest_buf_duration option
|
||||
- ffmpeg now requires threading to be built
|
||||
- ffmpeg now runs every muxer in a separate thread
|
||||
- Add new mode to cropdetect filter to detect crop-area based on motion vectors and edges
|
||||
- VAAPI decoding and encoding for 10/12bit 422, 10/12bit 444 HEVC and VP9
|
||||
- WBMP (Wireless Application Protocol Bitmap) image format
|
||||
- a3dscope filter
|
||||
- bonk decoder and demuxer
|
||||
- Micronas SC-4 audio decoder
|
||||
- LAF demuxer
|
||||
- APAC decoder and demuxer
|
||||
- Media 100i decoders
|
||||
- DTS to PTS reorder bsf
|
||||
- ViewQuest VQC decoder
|
||||
- backgroundkey filter
|
||||
- nvenc AV1 encoding support
|
||||
- MediaCodec decoder via NDKMediaCodec
|
||||
- MediaCodec encoder
|
||||
- oneVPL support for QSV
|
||||
- QSV AV1 encoder
|
||||
- QSV decoding and encoding for 10/12bit 422, 10/12bit 444 HEVC and VP9
|
||||
- showcwt multimedia filter
|
||||
- corr video filter
|
||||
- adrc audio filter
|
||||
- afdelaysrc audio filter
|
||||
- WADY DPCM decoder and demuxer
|
||||
- CBD2 DPCM decoder
|
||||
- ssim360 video filter
|
||||
- ffmpeg CLI new options: -stats_enc_pre[_fmt], -stats_enc_post[_fmt],
|
||||
-stats_mux_pre[_fmt]
|
||||
- hstack_vaapi, vstack_vaapi and xstack_vaapi filters
|
||||
- XMD ADPCM decoder and demuxer
|
||||
- media100 to mjpegb bsf
|
||||
- ffmpeg CLI new option: -fix_sub_duration_heartbeat
|
||||
- WavArc decoder and demuxer
|
||||
- CrystalHD decoders deprecated
|
||||
- SDNS demuxer
|
||||
- RKA decoder and demuxer
|
||||
- filtergraph syntax in ffmpeg CLI now supports passing file contents
|
||||
as option values, by prefixing option name with '/'
|
||||
- hstack_qsv, vstack_qsv and xstack_qsv filters
|
||||
|
||||
|
||||
version 5.1:
|
||||
- add ipfs/ipns gateway support
|
||||
- add ipfs/ipns protocol support
|
||||
- dialogue enhance audio filter
|
||||
- dropped obsolete XvMC hwaccel
|
||||
- pcm-bluray encoder
|
||||
@@ -486,7 +25,6 @@ version 5.1:
|
||||
- PHM image format support
|
||||
- remap_opencl filter
|
||||
- added chromakey_cuda filter
|
||||
- added bilateral_cuda filter
|
||||
|
||||
|
||||
version 5.0:
|
||||
|
||||
35
MAINTAINERS
35
MAINTAINERS
@@ -11,11 +11,17 @@ A (CC <address>) after the name means that the maintainer prefers to be CC-ed on
|
||||
patches and related discussions.
|
||||
|
||||
|
||||
Project Leader
|
||||
==============
|
||||
|
||||
final design decisions
|
||||
|
||||
|
||||
Applications
|
||||
============
|
||||
|
||||
ffmpeg:
|
||||
ffmpeg.c Michael Niedermayer, Anton Khirnov
|
||||
ffmpeg.c Michael Niedermayer
|
||||
|
||||
ffplay:
|
||||
ffplay.c Marton Balint
|
||||
@@ -34,8 +40,7 @@ Miscellaneous Areas
|
||||
===================
|
||||
|
||||
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, Timo Rothenpieler
|
||||
project server emergencies Árpád Gereöffy, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov, Timo Rothenpieler
|
||||
project server Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Nikolay Aleksandrov
|
||||
presets Robert Swain
|
||||
metadata subsystem Aurelien Jacobs
|
||||
release management Michael Niedermayer
|
||||
@@ -110,6 +115,8 @@ Generic Parts:
|
||||
lzw.* Michael Niedermayer
|
||||
floating point AAN DCT:
|
||||
faandct.c, faandct.h Michael Niedermayer
|
||||
Non-power-of-two MDCT:
|
||||
mdct15.c, mdct15.h Rostislav Pehlivanov
|
||||
Golomb coding:
|
||||
golomb.c, golomb.h Michael Niedermayer
|
||||
motion estimation:
|
||||
@@ -134,7 +141,6 @@ Codecs:
|
||||
adpcm.c Zane van Iperen
|
||||
alacenc.c Jaikrishnan Menon
|
||||
alsdec.c Thilo Borgmann, Umair Khan
|
||||
amfenc* Dmitrii Ovchinnikov
|
||||
aptx.c Aurelien Jacobs
|
||||
ass* Aurelien Jacobs
|
||||
asv* Michael Niedermayer
|
||||
@@ -151,6 +157,7 @@ Codecs:
|
||||
ccaption_dec.c Anshul Maheshwari, Aman Gupta
|
||||
cljr Alex Beregszaszi
|
||||
cpia.c Stephan Hilb
|
||||
crystalhd.c Philip Langdale
|
||||
cscd.c Reimar Doeffinger
|
||||
cuviddec.c Timo Rothenpieler
|
||||
dca* foo86
|
||||
@@ -181,7 +188,6 @@ Codecs:
|
||||
interplayvideo.c Mike Melanson
|
||||
jni*, ffjni* Matthieu Bouron
|
||||
jpeg2000* Nicolas Bertrand
|
||||
jpegxl* Leo Izen
|
||||
jvdec.c Peter Ross
|
||||
lcl*.c Roberto Togni, Reimar Doeffinger
|
||||
libcelt_dec.c Nicolas George
|
||||
@@ -211,7 +217,6 @@ Codecs:
|
||||
mqc* Nicolas Bertrand
|
||||
msmpeg4.c, msmpeg4data.h Michael Niedermayer
|
||||
msrle.c Mike Melanson
|
||||
msrleenc.c Tomas Härdin
|
||||
msvideo1.c Mike Melanson
|
||||
nuv.c Reimar Doeffinger
|
||||
nvdec*, nvenc* Timo Rothenpieler
|
||||
@@ -266,6 +271,7 @@ Codecs:
|
||||
xwd* Paul B Mahol
|
||||
|
||||
Hardware acceleration:
|
||||
crystalhd.c Philip Langdale
|
||||
dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme
|
||||
d3d11va* Steve Lhomme
|
||||
mediacodec* Matthieu Bouron, Aman Gupta
|
||||
@@ -419,7 +425,6 @@ Muxers/Demuxers:
|
||||
dv.c Roman Shaposhnik
|
||||
electronicarts.c Peter Ross
|
||||
epafdec.c Paul B Mahol
|
||||
evc* Samsung (Dawid Kozinski)
|
||||
ffm* Baptiste Coudurier
|
||||
flic.c Mike Melanson
|
||||
flvdec.c Michael Niedermayer
|
||||
@@ -430,12 +435,11 @@ Muxers/Demuxers:
|
||||
idcin.c Mike Melanson
|
||||
idroqdec.c Mike Melanson
|
||||
iff.c Jaikrishnan Menon
|
||||
imf* Pierre-Anthony Lemieux
|
||||
img2*.c Michael Niedermayer
|
||||
ipmovie.c Mike Melanson
|
||||
ircam* Paul B Mahol
|
||||
iss.c Stefan Gehrer
|
||||
jpegxl* Leo Izen
|
||||
jpegxl_probe.* Leo Izen
|
||||
jvdec.c Peter Ross
|
||||
kvag.c Zane van Iperen
|
||||
libmodplug.c Clément Bœsch
|
||||
@@ -546,7 +550,6 @@ LoongArch Shiyou Yin
|
||||
Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier
|
||||
Amiga / PowerPC Colin Ward
|
||||
Linux / PowerPC Lauri Kasanen
|
||||
RISC-V Rémi Denis-Courmont
|
||||
Windows MinGW Alex Beregszaszi, Ramiro Polla
|
||||
Windows Cygwin Victor Paesa
|
||||
Windows MSVC Matthew Oliver, Hendrik Leppkes
|
||||
@@ -588,12 +591,10 @@ wm4
|
||||
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.7 Michael Niedermayer
|
||||
2.6 Michael Niedermayer
|
||||
2.5 Michael Niedermayer
|
||||
|
||||
If you want to maintain an older release, please contact us
|
||||
|
||||
@@ -620,18 +621,16 @@ Haihao Xiang (haihao) 1F0C 31E8 B4FE F7A4 4DC1 DC99 E0F5 76D4 76FC 437F
|
||||
Jaikrishnan Menon 61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368
|
||||
James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0
|
||||
Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A
|
||||
Leo Izen (Traneptora) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A
|
||||
Leo Izen (thebombzen) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A
|
||||
Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE
|
||||
Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464
|
||||
Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB
|
||||
DD1E C9E8 DE08 5C62 9B3E 1846 B18E 8928 B394 8D64
|
||||
Nicolas George 24CE 01CE 9ACC 5CEB 74D8 8D9D B063 D997 36E5 4C93
|
||||
Niklas Haas (haasn) 1DDB 8076 B14D 5B48 32FC 99D9 EB52 DA9C 02BA 6FB4
|
||||
Nikolay Aleksandrov 8978 1D8C FB71 588E 4B27 EAA8 C4F0 B5FC E011 13B1
|
||||
Panagiotis Issaris 6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029
|
||||
Peter Ross A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B
|
||||
Philip Langdale 5DC5 8D66 5FBA 3A43 18EC 045E F8D6 B194 6A75 682E
|
||||
Pierre-Anthony Lemieux (pal) F4B3 9492 E6F2 E4AF AEC8 46CB 698F A1F0 F8D4 EED4
|
||||
Ramiro Polla 7859 C65B 751B 1179 792E DAE8 8E95 8B2F 9B6C 5700
|
||||
Reimar Doeffinger C61D 16E5 9E2C D10C 8958 38A4 0899 A2B9 06D4 D9C7
|
||||
Reinhard Tartler 9300 5DC2 7E87 6C37 ED7B CA9A 9808 3544 9453 48A4
|
||||
|
||||
6
Makefile
6
Makefile
@@ -47,7 +47,7 @@ FF_DEP_LIBS := $(DEP_LIBS)
|
||||
FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS)
|
||||
|
||||
$(TOOLS): %$(EXESUF): %.o
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter-out $(FF_DEP_LIBS), $^) $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS)
|
||||
|
||||
target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS)
|
||||
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
|
||||
@@ -67,8 +67,6 @@ tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS)
|
||||
|
||||
tools/enum_options$(EXESUF): ELIBS = $(FF_EXTRALIBS)
|
||||
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): ELIBS = $(FF_EXTRALIBS)
|
||||
tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS)
|
||||
@@ -93,7 +91,7 @@ ffbuild/.config: $(CONFIGURABLE_COMPONENTS)
|
||||
SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \
|
||||
HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \
|
||||
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 \
|
||||
MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \
|
||||
STLIBOBJS HOSTOBJS TESTOBJS
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
|
||||
┌──────────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 6.1 "Heaviside" │
|
||||
└──────────────────────────────────────────┘
|
||||
┌────────────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 5.1 "Riemann" LTS │
|
||||
└────────────────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 6.1 "Heaviside", about 8
|
||||
months after the release of FFmpeg 6.0.
|
||||
The FFmpeg Project proudly presents FFmpeg 5.1 "Riemann" LTS, about 6
|
||||
months after the release of FFmpeg 5.0, our first Long Term Support
|
||||
release. While several past FFmpeg releases have enjoyed long term
|
||||
support, this is the first release where such an intention is made
|
||||
clear at release.
|
||||
|
||||
A complete Changelog is available at the root of the project, and the
|
||||
complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef COMPAT_ATOMICS_WIN32_STDATOMIC_H
|
||||
#define COMPAT_ATOMICS_WIN32_STDATOMIC_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
@@ -187,6 +187,5 @@ static inline __device__ float __saturatef(float a) { return __nvvm_saturate_f(a
|
||||
static inline __device__ float __sinf(float a) { return __nvvm_sin_approx_f(a); }
|
||||
static inline __device__ float __cosf(float a) { return __nvvm_cos_approx_f(a); }
|
||||
static inline __device__ float __expf(float a) { return __nvvm_ex2_approx_f(a * (float)__builtin_log2(__builtin_exp(1))); }
|
||||
static inline __device__ float __powf(float a, float b) { return __nvvm_ex2_approx_f(__nvvm_lg2_approx_f(a) * b); }
|
||||
|
||||
#endif /* COMPAT_CUDA_CUDA_RUNTIME_H */
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
* As most functions here are used without checking return values,
|
||||
* only implement return values as necessary. */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
@@ -65,14 +66,7 @@ typedef CONDITION_VARIABLE pthread_cond_t;
|
||||
#define PTHREAD_CANCEL_ENABLE 1
|
||||
#define PTHREAD_CANCEL_DISABLE 0
|
||||
|
||||
#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)
|
||||
static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg)
|
||||
{
|
||||
pthread_t *h = (pthread_t*)arg;
|
||||
h->ret = h->func(h->arg);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$1" = "--version" ]; then
|
||||
rc.exe -?
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Usage: mswindres [-I/include/path ...] [-DSOME_DEFINE ...] [-o output.o] input.rc [output.o]" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
EXTRA_OPTS="-nologo"
|
||||
|
||||
while [ $# -gt 2 ]; do
|
||||
case $1 in
|
||||
-D*) EXTRA_OPTS="$EXTRA_OPTS -d$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;;
|
||||
-I*) EXTRA_OPTS="$EXTRA_OPTS -i$(echo $1 | sed -e "s/^..//" -e "s/ /\\\\ /g")" ;;
|
||||
-o) OPT_OUT="$2"; shift ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
IN="$1"
|
||||
if [ -z "$OPT_OUT" ]; then
|
||||
OUT="$2"
|
||||
else
|
||||
OUT="$OPT_OUT"
|
||||
fi
|
||||
|
||||
eval set -- $EXTRA_OPTS
|
||||
rc.exe "$@" -fo "$OUT" "$IN"
|
||||
319
doc/APIchanges
319
doc/APIchanges
@@ -1,312 +1,19 @@
|
||||
The last version increases of all libraries were on 2023-02-09
|
||||
Never assume the API of libav* to be stable unless at least 1 month has passed
|
||||
since the last major version increase or the API was added.
|
||||
|
||||
The last version increases were:
|
||||
libavcodec: 2021-04-27
|
||||
libavdevice: 2021-04-27
|
||||
libavfilter: 2021-04-27
|
||||
libavformat: 2021-04-27
|
||||
libpostproc: 2021-04-27
|
||||
libswresample: 2021-04-27
|
||||
libswscale: 2021-04-27
|
||||
libavutil: 2021-04-27
|
||||
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
-------- 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< ---------
|
||||
|
||||
2023-02-16 - 927042b409 - lavf 60.2.100 - avformat.h
|
||||
Deprecate AVFormatContext io_close callback.
|
||||
The superior io_close2 callback should be used instead.
|
||||
|
||||
2023-02-13 - 2296078397 - lavu 58.1.100 - frame.h
|
||||
Deprecate AVFrame.coded_picture_number and display_picture_number.
|
||||
Their usefulness is questionable and very few decoders set them.
|
||||
|
||||
2023-02-13 - 6b6f7db819 - lavc 60.2.100 - avcodec.h
|
||||
Add AVCodecContext.frame_num as a 64bit version of frame_number.
|
||||
Deprecate AVCodecContext.frame_number.
|
||||
|
||||
2023-02-12 - d1b9a3ddb4 - lavfi 9.1.100 - avfilter.h
|
||||
Add filtergraph segment parsing API.
|
||||
New structs:
|
||||
- AVFilterGraphSegment
|
||||
- AVFilterChain
|
||||
- AVFilterParams
|
||||
- AVFilterPadParams
|
||||
New functions:
|
||||
- avfilter_graph_segment_parse()
|
||||
- avfilter_graph_segment_create_filters()
|
||||
- avfilter_graph_segment_apply_opts()
|
||||
- avfilter_graph_segment_init()
|
||||
- avfilter_graph_segment_link()
|
||||
- avfilter_graph_segment_apply()
|
||||
|
||||
2023-02-09 - 719a93f4e4 - lavu 58.0.100 - csp.h
|
||||
Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id().
|
||||
Add av_csp_trc_function.
|
||||
|
||||
2023-02-09 - 868a31b42d - lavc 60.0.100 - avcodec.h
|
||||
avcodec_decode_subtitle2() now accepts const AVPacket*.
|
||||
|
||||
2023-02-04 - d02340b9e3 - lavc 59.63.100
|
||||
Allow AV_CODEC_FLAG_COPY_OPAQUE to be used with decoders.
|
||||
|
||||
2023-01-29 - a1a80f2e64 - lavc 59.59.100 - avcodec.h
|
||||
Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION.
|
||||
|
||||
2023-01-13 - 002d0ec740 - lavu 57.44.100 - ambient_viewing_environment.h frame.h
|
||||
Adds a new structure for holding H.274 Ambient Viewing Environment metadata,
|
||||
AVAmbientViewingEnvironment.
|
||||
Adds a new AVFrameSideDataType entry AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT
|
||||
for it.
|
||||
|
||||
2022-12-10 - 7a8d78f7e3 - lavc 59.55.100 - avcodec.h
|
||||
Add AV_HWACCEL_FLAG_UNSAFE_OUTPUT.
|
||||
|
||||
2022-11-24 - e97368eba5 - lavu 57.43.100 - tx.h
|
||||
Add AV_TX_FLOAT_DCT, AV_TX_DOUBLE_DCT and AV_TX_INT32_DCT.
|
||||
|
||||
2022-11-06 - 9dad237928 - lavu 57.42.100 - dict.h
|
||||
Add av_dict_iterate().
|
||||
|
||||
2022-11-03 - 6228ba141d - lavu 57.41.100 - channel_layout.h
|
||||
Add AV_CH_LAYOUT_7POINT1_TOP_BACK and AV_CHANNEL_LAYOUT_7POINT1_TOP_BACK.
|
||||
|
||||
2022-10-30 - 83e918de71 - lavu 57.40.100 - channel_layout.h
|
||||
Add AV_CH_LAYOUT_CUBE and AV_CHANNEL_LAYOUT_CUBE.
|
||||
|
||||
2022-10-11 - 479747645f - lavu 57.39.101 - pixfmt.h
|
||||
Add AV_PIX_FMT_RGBF32 and AV_PIX_FMT_RGBAF32.
|
||||
|
||||
2022-10-05 - 37d5ddc317 - lavu 57.39.100 - cpu.h
|
||||
Add AV_CPU_FLAG_RVB_BASIC.
|
||||
|
||||
2022-10-03 - d09776d486 - lavf 59.34.100 - avio.h
|
||||
Make AVIODirContext an opaque type in a future major version bump.
|
||||
|
||||
2022-09-27 - 0c0a3deb18 - lavu 57.38.100 - cpu.h
|
||||
Add CPU flags for RISC-V vector extensions:
|
||||
AV_CPU_FLAG_RVV_I32, AV_CPU_FLAG_RVV_F32, AV_CPU_FLAG_RVV_I64,
|
||||
AV_CPU_FLAG_RVV_F64
|
||||
|
||||
2022-09-26 - a02a0e8db4 - lavc 59.48.100 - avcodec.h
|
||||
Deprecate avcodec_enum_to_chroma_pos() and avcodec_chroma_pos_to_enum().
|
||||
Use av_chroma_location_enum_to_pos() or av_chroma_location_pos_to_enum()
|
||||
instead.
|
||||
|
||||
2022-09-26 - xxxxxxxxxx - lavu 57.37.100 - pixdesc.h pixfmt.h
|
||||
Add av_chroma_location_enum_to_pos() and av_chroma_location_pos_to_enum().
|
||||
Add AV_PIX_FMT_RGBF32BE, AV_PIX_FMT_RGBF32LE, AV_PIX_FMT_RGBAF32BE,
|
||||
AV_PIX_FMT_RGBAF32LE.
|
||||
|
||||
2022-09-26 - cf856d8957 - lavc 59.47.100 - avcodec.h defs.h
|
||||
Move the AV_EF_* and FF_COMPLIANCE_* defines from avcodec.h to defs.h.
|
||||
|
||||
2022-09-03 - d75c4693fe - lavu 57.36.100 - pixfmt.h
|
||||
Add AV_PIX_FMT_P012, AV_PIX_FMT_Y212, AV_PIX_FMT_XV30, AV_PIX_FMT_XV36
|
||||
|
||||
2022-09-03 - dea9744560 - lavu 57.35.100 - file.h
|
||||
Deprecate av_tempfile() without replacement.
|
||||
|
||||
2022-08-03 - cc5a5c9860 - lavu 57.34.100 - pixfmt.h
|
||||
Add AV_PIX_FMT_VUYX.
|
||||
|
||||
2022-08-22 - 14726571dd - lavf 59 - avformat.h
|
||||
Deprecate av_stream_get_end_pts() without replacement.
|
||||
|
||||
2022-08-19 - 352799dca8 - lavc 59.42.102 - codec_id.h
|
||||
Deprecate AV_CODEC_ID_AYUV and ayuv decoder/encoder. The rawvideo codec
|
||||
and vuya pixel format combination will be used instead from now on.
|
||||
|
||||
2022-08-07 - e95b08a7dd - lavu 57.33.101 - pixfmt.h
|
||||
Add AV_PIX_FMT_RGBAF16{BE,LE} pixel formats.
|
||||
|
||||
2022-08-12 - e0bbdbe0a6 - lavu 57.33.100 - hwcontext_qsv.h
|
||||
Add loader field to AVQSVDeviceContext
|
||||
|
||||
2022-08-03 - 6ab8a9d375 - lavu 57.32.100 - pixfmt.h
|
||||
Add AV_PIX_FMT_VUYA.
|
||||
|
||||
2022-08-02 - e3838b856f - lavc 59.41.100 - avcodec.h codec.h
|
||||
Add AV_CODEC_FLAG_RECON_FRAME and AV_CODEC_CAP_ENCODER_RECON_FRAME.
|
||||
avcodec_receive_frame() may now be used on encoders when
|
||||
AV_CODEC_FLAG_RECON_FRAME is active.
|
||||
|
||||
2022-08-02 - eede1d2927 - lavu 57.31.100 - frame.h
|
||||
av_frame_make_writable() may now be called on non-refcounted
|
||||
frames and will make a refcounted copy out of them.
|
||||
Previously an error was returned in such cases.
|
||||
|
||||
2022-07-30 - e1a0f2df3d - lavc 59.40.100 - avcodec.h
|
||||
Add the AV_CODEC_FLAG2_ICC_PROFILES flag to AVCodecContext, to enable
|
||||
automatic reading and writing of embedded ICC profiles in image files.
|
||||
The "flags2" option now supports the corresponding flag "icc_profiles".
|
||||
|
||||
2022-07-19 - 4397f9a5a0 - lavu 57.30.100 - frame.h
|
||||
Add AVFrame.duration, deprecate AVFrame.pkt_duration.
|
||||
|
||||
-------- 8< --------- FFmpeg 5.1 was cut here -------- 8< ---------
|
||||
|
||||
2022-06-12 - 7cae3d8b76 - lavf 59.25.100 - avio.h
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 6.1.2
|
||||
PROJECT_NUMBER = 5.1
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@@ -1980,7 +1980,6 @@ PREDEFINED = __attribute__(x)= \
|
||||
av_alloc_size(...)= \
|
||||
AV_GCC_VERSION_AT_LEAST(x,y)=1 \
|
||||
AV_GCC_VERSION_AT_MOST(x,y)=0 \
|
||||
"FF_PAD_STRUCTURE(name,size,...)=typedef struct name { __VA_ARGS__ } name;" \
|
||||
__GNUC__
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
|
||||
@@ -19,7 +19,6 @@ MANPAGES3 = $(LIBRARIES-yes:%=doc/%.3)
|
||||
MANPAGES = $(MANPAGES1) $(MANPAGES3)
|
||||
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) \
|
||||
doc/community.html \
|
||||
doc/developer.html \
|
||||
doc/faq.html \
|
||||
doc/fate.html \
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
The FFmpeg developers.
|
||||
|
||||
For details about the authorship, see the Git history of the project
|
||||
(https://git.ffmpeg.org/ffmpeg), e.g. by typing the command
|
||||
(git://source.ffmpeg.org/ffmpeg), e.g. by typing the command
|
||||
@command{git log} in the FFmpeg source directory, or browsing the
|
||||
online repository at @url{https://git.ffmpeg.org/ffmpeg}.
|
||||
online repository at @url{http://source.ffmpeg.org}.
|
||||
|
||||
Maintainers for the specific components are listed in the file
|
||||
@file{MAINTAINERS} in the source code tree.
|
||||
|
||||
@@ -382,6 +382,9 @@ This applies a specific fixup to some Blu-ray streams which contain
|
||||
redundant PPSs modifying irrelevant parameters of the stream which
|
||||
confuse other transformations which require correct extradata.
|
||||
|
||||
A new single global PPS is created, and all of the redundant PPSs
|
||||
within the stream are removed.
|
||||
|
||||
@section hevc_metadata
|
||||
|
||||
Modify metadata embedded in an HEVC stream.
|
||||
|
||||
2
doc/bootstrap.min.css
vendored
2
doc/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -644,8 +644,6 @@ for codecs that support it. See also @file{doc/examples/export_mvs.c}.
|
||||
Do not skip samples and export skip information as frame side data.
|
||||
@item ass_ro_flush_noop
|
||||
Do not reset ASS ReadOrder field on flush.
|
||||
@item icc_profiles
|
||||
Generate/parse embedded ICC profiles from/to colorimetry tags.
|
||||
@end table
|
||||
|
||||
@item export_side_data @var{flags} (@emph{decoding/encoding,audio,video,subtitles})
|
||||
@@ -697,13 +695,10 @@ profiles are documented in the relevant encoder documentation.
|
||||
|
||||
@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:
|
||||
@table @samp
|
||||
@item unknown
|
||||
|
||||
@end table
|
||||
|
||||
@item lowres @var{integer} (@emph{decoding,audio,video})
|
||||
@@ -778,6 +773,7 @@ Possible values:
|
||||
@end table
|
||||
@item rc_max_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})
|
||||
Possible values:
|
||||
@@ -892,11 +888,9 @@ Possible values:
|
||||
@table @samp
|
||||
@item tv
|
||||
@item mpeg
|
||||
@item limited
|
||||
MPEG (219*2^(n-8))
|
||||
@item pc
|
||||
@item jpeg
|
||||
@item full
|
||||
JPEG (2^n-1)
|
||||
@end table
|
||||
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
\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 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`.
|
||||
|
||||
@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
|
||||
@@ -77,17 +77,13 @@ The following options are supported by the libdav1d wrapper.
|
||||
@item framethreads
|
||||
Set amount of frame threads to use during decoding. The default value is 0 (autodetect).
|
||||
This option is deprecated for libdav1d >= 1.0 and will be removed in the future. Use the
|
||||
option @code{max_frame_delay} and the global option @code{threads} instead.
|
||||
global option @code{threads} instead.
|
||||
|
||||
@item tilethreads
|
||||
Set amount of tile threads to use during decoding. The default value is 0 (autodetect).
|
||||
This option is deprecated for libdav1d >= 1.0 and will be removed in the future. Use the
|
||||
global option @code{threads} instead.
|
||||
|
||||
@item max_frame_delay
|
||||
Set max amount of frames the decoder may buffer internally. The default value is 0
|
||||
(autodetect).
|
||||
|
||||
@item filmgrain
|
||||
Apply film grain to the decoded video if present in the bitstream. Defaults to the
|
||||
internal default of the library.
|
||||
@@ -353,169 +349,6 @@ Enabled by default.
|
||||
|
||||
@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
|
||||
|
||||
@subsection Options
|
||||
|
||||
@@ -285,37 +285,11 @@ This demuxer accepts the following option:
|
||||
|
||||
@end table
|
||||
|
||||
@section ea
|
||||
|
||||
Electronic Arts Multimedia format demuxer.
|
||||
|
||||
This format is used by various Electronic Arts games.
|
||||
|
||||
@subsection Options
|
||||
|
||||
@table @option
|
||||
|
||||
@item merge_alpha @var{bool}
|
||||
|
||||
Normally the VP6 alpha channel (if exists) is returned as a secondary video
|
||||
stream, by setting this option you can make the demuxer return a single video
|
||||
stream which contains the alpha channel in addition to the ordinary video.
|
||||
|
||||
@end table
|
||||
|
||||
@section imf
|
||||
|
||||
Interoperable Master Format demuxer.
|
||||
|
||||
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.
|
||||
This demuxer presents audio and video streams found in an IMF Composition.
|
||||
|
||||
@section flv, live_flv, kux
|
||||
|
||||
@@ -427,10 +401,6 @@ Use HTTP partial requests for downloading HTTP segments.
|
||||
|
||||
@item seg_format_options
|
||||
Set options for the demuxer of media segments using a list of key=value pairs separated by @code{:}.
|
||||
|
||||
@item seg_max_retry
|
||||
Maximum number of times to reload a segment on error, useful when segment skip on network error is not desired.
|
||||
Default value is 0.
|
||||
@end table
|
||||
|
||||
@section image2
|
||||
@@ -779,13 +749,6 @@ cast to int32 are used to adjust onward dts.
|
||||
|
||||
Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto
|
||||
a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range.
|
||||
|
||||
@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
|
||||
|
||||
@subsection Audible AAX
|
||||
|
||||
79
doc/dev_community/community.md
Normal file
79
doc/dev_community/community.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# FFmpeg project
|
||||
|
||||
## Organisation
|
||||
|
||||
The FFmpeg project is organized through a community working on global consensus.
|
||||
|
||||
Decisions are taken by the ensemble of active members, through voting and
|
||||
are aided by two committees.
|
||||
|
||||
## General Assembly
|
||||
|
||||
The ensemble of active members is called the General Assembly (GA).
|
||||
|
||||
The General Assembly is sovereign and legitimate for all its decisions
|
||||
regarding the FFmpeg project.
|
||||
|
||||
The General Assembly is made up of active contributors.
|
||||
|
||||
Contributors are considered "active contributors" if they have pushed more
|
||||
than 20 patches in the last 36 months in the main FFmpeg repository, or
|
||||
if they have been voted in by the GA.
|
||||
|
||||
Additional members are added to the General Assembly through a vote after
|
||||
proposal by a member of the General Assembly.
|
||||
They are part of the GA for two years, after which they need a confirmation by
|
||||
the GA.
|
||||
|
||||
## Voting
|
||||
|
||||
Voting is done using a ranked voting system, currently running on https://vote.ffmpeg.org/ .
|
||||
|
||||
Majority vote means more than 50% of the expressed ballots.
|
||||
|
||||
## Technical Committee
|
||||
|
||||
The Technical Committee (TC) is here to arbitrate and make decisions when
|
||||
technical conflicts occur in the project.
|
||||
They will consider the merits of all the positions, judge them and make a
|
||||
decision.
|
||||
|
||||
The TC resolves technical conflicts but is not a technical steering committee.
|
||||
|
||||
Decisions by the TC are binding for all the contributors.
|
||||
|
||||
Decisions made by the TC can be re-opened after 1 year or by a majority vote
|
||||
of the General Assembly, requested by one of the member of the GA.
|
||||
|
||||
The TC is elected by the General Assembly for a duration of 1 year, and
|
||||
is composed of 5 members.
|
||||
Members can be re-elected if they wish. A majority vote in the General Assembly
|
||||
can trigger a new election of the TC.
|
||||
|
||||
The members of the TC can be elected from outside of the GA.
|
||||
Candidates for election can either be suggested or self-nominated.
|
||||
|
||||
The conflict resolution process is detailed in the [resolution process](resolution_process.md) document.
|
||||
|
||||
## Community committee
|
||||
|
||||
The Community Committee (CC) is here to arbitrage and make decisions when
|
||||
inter-personal conflicts occur in the project. It will decide quickly and
|
||||
take actions, for the sake of the project.
|
||||
|
||||
The CC can remove privileges of offending members, including removal of
|
||||
commit access and temporary ban from the community.
|
||||
|
||||
Decisions made by the CC can be re-opened after 1 year or by a majority vote
|
||||
of the General Assembly. Indefinite bans from the community must be confirmed
|
||||
by the General Assembly, in a majority vote.
|
||||
|
||||
The CC is elected by the General Assembly for a duration of 1 year, and is
|
||||
composed of 5 members.
|
||||
Members can be re-elected if they wish. A majority vote in the General Assembly
|
||||
can trigger a new election of the CC.
|
||||
|
||||
The members of the CC can be elected from outside of the GA.
|
||||
Candidates for election can either be suggested or self-nominated.
|
||||
|
||||
The CC is governed by and responsible for enforcing the Code of Conduct.
|
||||
91
doc/dev_community/resolution_process.md
Normal file
91
doc/dev_community/resolution_process.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Technical Committee
|
||||
|
||||
_This document only makes sense with the rules from [the community document](community)_.
|
||||
|
||||
The Technical Committee (**TC**) is here to arbitrate and make decisions when
|
||||
technical conflicts occur in the project.
|
||||
|
||||
The TC main role is to resolve technical conflicts.
|
||||
It is therefore not a technical steering committee, but it is understood that
|
||||
some decisions might impact the future of the project.
|
||||
|
||||
# Process
|
||||
|
||||
## Seizing
|
||||
|
||||
The TC can take possession of any technical matter that it sees fit.
|
||||
|
||||
To involve the TC in a matter, email tc@ or CC them on an ongoing discussion.
|
||||
|
||||
As members of TC are developers, they also can email tc@ to raise an issue.
|
||||
|
||||
## Announcement
|
||||
|
||||
The TC, once seized, must announce itself on the main mailing list, with a _[TC]_ tag.
|
||||
|
||||
The TC has 2 modes of operation: a RFC one and an internal one.
|
||||
|
||||
If the TC thinks it needs the input from the larger community, the TC can call
|
||||
for a RFC. Else, it can decide by itself.
|
||||
|
||||
If the disagreement involves a member of the TC, that member should recuse
|
||||
themselves from the decision.
|
||||
|
||||
The decision to use a RFC process or an internal discussion is a discretionary
|
||||
decision of the TC.
|
||||
|
||||
The TC can also reject a seizure for a few reasons such as:
|
||||
the matter was not discussed enough previously; it lacks expertise to reach a
|
||||
beneficial decision on the matter; or the matter is too trivial.
|
||||
|
||||
### RFC call
|
||||
|
||||
In the RFC mode, one person from the TC posts on the mailing list the
|
||||
technical question and will request input from the community.
|
||||
|
||||
The mail will have the following specification:
|
||||
* a precise title
|
||||
* a specific tag [TC RFC]
|
||||
* a top-level email
|
||||
* contain a precise question that does not exceed 100 words and that is answerable by developers
|
||||
* may have an extra description, or a link to a previous discussion, if deemed necessary,
|
||||
* contain a precise end date for the answers.
|
||||
|
||||
The answers from the community must be on the main mailing list and must have
|
||||
the following specification:
|
||||
* keep the tag and the title unchanged
|
||||
* limited to 400 words
|
||||
* a first-level, answering directly to the main email
|
||||
* answering to the question.
|
||||
|
||||
Further replies to answers are permitted, as long as they conform to the
|
||||
community standards of politeness, they are limited to 100 words, and are not
|
||||
nested more than once. (max-depth=2)
|
||||
|
||||
After the end-date, mails on the thread will be ignored.
|
||||
|
||||
Violations of those rules will be escalated through the Community Committee.
|
||||
|
||||
After all the emails are in, the TC has 96 hours to give its final decision.
|
||||
Exceptionally, the TC can request an extra delay, that will be notified on the
|
||||
mailing list.
|
||||
|
||||
### Within TC
|
||||
|
||||
In the internal case, the TC has 96 hours to give its final decision.
|
||||
Exceptionally, the TC can request an extra delay.
|
||||
|
||||
|
||||
## Decisions
|
||||
|
||||
The decisions from the TC will be sent on the mailing list, with the _[TC]_ tag.
|
||||
|
||||
Internally, the TC should take decisions with a majority, or using
|
||||
ranked-choice voting.
|
||||
|
||||
The decision from the TC should be published with a summary of the reasons that
|
||||
lead to this decision.
|
||||
|
||||
The decisions from the TC are final, until the matters are reopened after
|
||||
no less than one year.
|
||||
|
||||
@@ -10,115 +10,41 @@
|
||||
|
||||
@contents
|
||||
|
||||
@chapter Introduction
|
||||
@chapter Notes for external developers
|
||||
|
||||
This text is concerned with the development @emph{of} FFmpeg itself. Information
|
||||
on using the FFmpeg libraries in other programs can be found elsewhere, e.g. in:
|
||||
@itemize @bullet
|
||||
@item
|
||||
the installed header files
|
||||
@item
|
||||
@url{http://ffmpeg.org/doxygen/trunk/index.html, the Doxygen documentation}
|
||||
generated from the headers
|
||||
@item
|
||||
the examples under @file{doc/examples}
|
||||
@end itemize
|
||||
This document is mostly useful for internal FFmpeg developers.
|
||||
External developers who need to use the API in their application should
|
||||
refer to the API doxygen documentation in the public headers, and
|
||||
check the examples in @file{doc/examples} and in the source code to
|
||||
see how the public API is employed.
|
||||
|
||||
You can use the FFmpeg libraries in your commercial program, but you
|
||||
are encouraged to @emph{publish any patch you make}. In this case the
|
||||
best way to proceed is to send your patches to the ffmpeg-devel
|
||||
mailing list following the guidelines illustrated in the remainder of
|
||||
this document.
|
||||
|
||||
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
|
||||
@emph{submit your changes back to us}, using this document as a guide. There are
|
||||
both pragmatic and ideological reasons to do so:
|
||||
@chapter Contributing
|
||||
|
||||
There are 2 ways by which code gets into FFmpeg:
|
||||
@itemize @bullet
|
||||
@item
|
||||
Maintaining external changes to keep up with upstream development is
|
||||
time-consuming and error-prone. With your code in the main tree, it will be
|
||||
maintained by FFmpeg developers.
|
||||
@item
|
||||
FFmpeg developers include leading experts in the field who can find bugs or
|
||||
design flaws in your code.
|
||||
@item
|
||||
By supporting the project you find useful you ensure it continues to be
|
||||
maintained and developed.
|
||||
@item Submitting patches to the ffmpeg-devel mailing list.
|
||||
See @ref{Submitting patches} for details.
|
||||
@item Directly committing changes to the main tree.
|
||||
@end itemize
|
||||
|
||||
All proposed code changes should be submitted for review to
|
||||
@url{mailto:ffmpeg-devel@@ffmpeg.org, the development mailing list}, as
|
||||
described in more detail in the @ref{Submitting patches} chapter. The code
|
||||
should comply with the @ref{Development Policy} and follow the @ref{Coding Rules}.
|
||||
Whichever way, changes should be reviewed by the maintainer of the code
|
||||
before they are committed. And they should follow the @ref{Coding Rules}.
|
||||
The developer making the commit and the author are responsible for their changes
|
||||
and should try to fix issues their commit causes.
|
||||
|
||||
@anchor{Coding Rules}
|
||||
@chapter Coding Rules
|
||||
|
||||
@section Language
|
||||
|
||||
FFmpeg is mainly programmed in the ISO C99 language, extended with:
|
||||
@itemize @bullet
|
||||
@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
|
||||
depended on, i.e. the code must still compile and work with compilers lacking
|
||||
the extension.
|
||||
|
||||
The following C99 features must not be used anywhere in the codebase:
|
||||
@itemize @bullet
|
||||
@item
|
||||
variable-length arrays;
|
||||
|
||||
@item
|
||||
complex numbers;
|
||||
|
||||
@item
|
||||
mixed statements and declarations.
|
||||
@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.
|
||||
@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
|
||||
|
||||
There are the following guidelines regarding the indentation in files:
|
||||
@@ -141,39 +67,8 @@ K&R coding style is used.
|
||||
@end itemize
|
||||
The presentation is one inspired by 'indent -i4 -kr -nut'.
|
||||
|
||||
@subsection Vim configuration
|
||||
In order to configure Vim to follow FFmpeg formatting conventions, paste
|
||||
the following snippet into your @file{.vimrc}:
|
||||
@example
|
||||
" indentation rules for FFmpeg: 4 spaces, no tabs
|
||||
set expandtab
|
||||
set shiftwidth=4
|
||||
set softtabstop=4
|
||||
set cindent
|
||||
set cinoptions=(0
|
||||
" Allow tabs in Makefiles.
|
||||
autocmd FileType make,automake set noexpandtab shiftwidth=8 softtabstop=8
|
||||
" Trailing whitespace and tabs are forbidden, so highlight them.
|
||||
highlight ForbiddenWhitespace ctermbg=red guibg=red
|
||||
match ForbiddenWhitespace /\s\+$\|\t/
|
||||
" Do not highlight spaces at the end of line while typing on that line.
|
||||
autocmd InsertEnter * match ForbiddenWhitespace /\t\|\s\+\%#\@@<!$/
|
||||
@end example
|
||||
|
||||
@subsection Emacs configuration
|
||||
For Emacs, add these roughly equivalent lines to your @file{.emacs.d/init.el}:
|
||||
@lisp
|
||||
(c-add-style "ffmpeg"
|
||||
'("k&r"
|
||||
(c-basic-offset . 4)
|
||||
(indent-tabs-mode . nil)
|
||||
(show-trailing-whitespace . t)
|
||||
(c-offsets-alist
|
||||
(statement-cont . (c-lineup-assignments +)))
|
||||
)
|
||||
)
|
||||
(setq c-default-style "ffmpeg")
|
||||
@end lisp
|
||||
The main priority in FFmpeg is simplicity and small code size in order to
|
||||
minimize the bug count.
|
||||
|
||||
@section Comments
|
||||
Use the JavaDoc/Doxygen format (see examples below) so that code documentation
|
||||
@@ -215,52 +110,92 @@ int myfunc(int my_parameter)
|
||||
...
|
||||
@end example
|
||||
|
||||
@anchor{Naming conventions}
|
||||
@section Naming conventions
|
||||
@section C language features
|
||||
|
||||
Names of functions, variables, and struct members must be lowercase, using
|
||||
underscores (_) to separate words. For example, @samp{avfilter_get_video_buffer}
|
||||
is an acceptable function name and @samp{AVFilterGetVideo} is not.
|
||||
FFmpeg is programmed in the ISO C90 language with a few additional
|
||||
features from ISO C99, namely:
|
||||
|
||||
Struct, union, enum, and typedeffed type names must use CamelCase. All structs
|
||||
and unions should be typedeffed to the same name as the struct/union tag, e.g.
|
||||
@code{typedef struct AVFoo @{ ... @} AVFoo;}. Enums are typically not
|
||||
typedeffed.
|
||||
|
||||
Enumeration constants and macros must be UPPERCASE, except for macros
|
||||
masquerading as functions, which should use the function naming convention.
|
||||
|
||||
All identifiers in the libraries should be namespaced as follows:
|
||||
@itemize @bullet
|
||||
@item
|
||||
No namespacing for identifiers with file and lower scope (e.g. local variables,
|
||||
static functions), and struct and union members,
|
||||
the @samp{inline} keyword;
|
||||
|
||||
@item
|
||||
The @code{ff_} prefix must be used for variables and functions visible outside
|
||||
of file scope, but only used internally within a single library, e.g.
|
||||
@samp{ff_w64_demuxer}. This prevents name collisions when FFmpeg is statically
|
||||
linked.
|
||||
@samp{//} comments;
|
||||
|
||||
@item
|
||||
designated struct initializers (@samp{struct s x = @{ .i = 17 @};});
|
||||
|
||||
@item
|
||||
compound literals (@samp{x = (struct s) @{ 17, 23 @};}).
|
||||
|
||||
@item
|
||||
for loops with variable definition (@samp{for (int i = 0; i < 8; i++)});
|
||||
|
||||
@item
|
||||
Variadic macros (@samp{#define ARRAY(nb, ...) (int[nb + 1])@{ nb, __VA_ARGS__ @}});
|
||||
|
||||
@item
|
||||
Implementation defined behavior for signed integers is assumed to match the
|
||||
expected behavior for two's complement. Non representable values in integer
|
||||
casts are binary truncated. Shift right of signed values uses sign extension.
|
||||
@end itemize
|
||||
|
||||
These features are supported by all compilers we care about, so we will not
|
||||
accept patches to remove their use unless they absolutely do not impair
|
||||
clarity and performance.
|
||||
|
||||
All code must compile with recent versions of GCC and a number of other
|
||||
currently supported compilers. To ensure compatibility, please do not use
|
||||
additional C99 features or GCC extensions. Especially watch out for:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
mixing statements and declarations;
|
||||
|
||||
@item
|
||||
@samp{long long} (use @samp{int64_t} instead);
|
||||
|
||||
@item
|
||||
@samp{__attribute__} not protected by @samp{#ifdef __GNUC__} or similar;
|
||||
|
||||
@item
|
||||
GCC statement expressions (@samp{(x = (@{ int y = 4; y; @})}).
|
||||
@end itemize
|
||||
|
||||
@section Naming conventions
|
||||
All names should be composed with underscores (_), not CamelCase. For example,
|
||||
@samp{avfilter_get_video_buffer} is an acceptable function name and
|
||||
@samp{AVFilterGetVideo} is not. The exception from this are type names, like
|
||||
for example structs and enums; they should always be in CamelCase.
|
||||
|
||||
There are the following conventions for naming variables and functions:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
For local variables no prefix is required.
|
||||
|
||||
@item
|
||||
For file-scope variables and functions declared as @code{static}, no prefix
|
||||
is required.
|
||||
|
||||
@item
|
||||
For variables and functions visible outside of file scope, but only used
|
||||
internally by a library, an @code{ff_} prefix should be used,
|
||||
e.g. @samp{ff_w64_demuxer}.
|
||||
|
||||
@item
|
||||
For variables and functions visible outside of file scope, used internally
|
||||
across multiple libraries, use @code{avpriv_} as prefix, for example,
|
||||
@samp{avpriv_report_missing_feature}.
|
||||
|
||||
@item
|
||||
All other internal identifiers, like private type or macro names, should be
|
||||
namespaced only to avoid possible internal conflicts. E.g. @code{H264_NAL_SPS}
|
||||
vs. @code{HEVC_NAL_SPS}.
|
||||
|
||||
@item
|
||||
Each library has its own prefix for public symbols, in addition to the
|
||||
commonly used @code{av_} (@code{avformat_} for libavformat,
|
||||
@code{avcodec_} for libavcodec, @code{swr_} for libswresample, etc).
|
||||
Check the existing code and choose names accordingly.
|
||||
|
||||
@item
|
||||
Other public identifiers (struct, union, enum, macro, type names) must use their
|
||||
library's public prefix (@code{AV}, @code{Sws}, or @code{Swr}).
|
||||
Note that some symbols without these prefixes are also exported for
|
||||
retro-compatibility reasons. These exceptions are declared in the
|
||||
@code{lib<name>/lib<name>.v} files.
|
||||
@end itemize
|
||||
|
||||
Furthermore, name space reserved for the system should not be invaded.
|
||||
@@ -274,50 +209,50 @@ symbols. If in doubt, just avoid names starting with @code{_} altogether.
|
||||
@section Miscellaneous conventions
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
fprintf and printf are forbidden in libavformat and libavcodec,
|
||||
please use av_log() instead.
|
||||
|
||||
@item
|
||||
Casts should be used only when necessary. Unneeded parentheses
|
||||
should also be avoided if they don't make the code easier to understand.
|
||||
@end itemize
|
||||
|
||||
@anchor{Development Policy}
|
||||
@section Editor configuration
|
||||
In order to configure Vim to follow FFmpeg formatting conventions, paste
|
||||
the following snippet into your @file{.vimrc}:
|
||||
@example
|
||||
" indentation rules for FFmpeg: 4 spaces, no tabs
|
||||
set expandtab
|
||||
set shiftwidth=4
|
||||
set softtabstop=4
|
||||
set cindent
|
||||
set cinoptions=(0
|
||||
" Allow tabs in Makefiles.
|
||||
autocmd FileType make,automake set noexpandtab shiftwidth=8 softtabstop=8
|
||||
" Trailing whitespace and tabs are forbidden, so highlight them.
|
||||
highlight ForbiddenWhitespace ctermbg=red guibg=red
|
||||
match ForbiddenWhitespace /\s\+$\|\t/
|
||||
" Do not highlight spaces at the end of line while typing on that line.
|
||||
autocmd InsertEnter * match ForbiddenWhitespace /\t\|\s\+\%#\@@<!$/
|
||||
@end example
|
||||
|
||||
For Emacs, add these roughly equivalent lines to your @file{.emacs.d/init.el}:
|
||||
@lisp
|
||||
(c-add-style "ffmpeg"
|
||||
'("k&r"
|
||||
(c-basic-offset . 4)
|
||||
(indent-tabs-mode . nil)
|
||||
(show-trailing-whitespace . t)
|
||||
(c-offsets-alist
|
||||
(statement-cont . (c-lineup-assignments +)))
|
||||
)
|
||||
)
|
||||
(setq c-default-style "ffmpeg")
|
||||
@end lisp
|
||||
|
||||
@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
|
||||
@subheading Licenses for patches must be compatible with FFmpeg.
|
||||
Contributions should be licensed under the
|
||||
@@ -340,24 +275,13 @@ missing samples or an implementation with a small subset of features.
|
||||
Always check the mailing list for any reviewers with issues and test
|
||||
FATE before you push.
|
||||
|
||||
@subheading Commit messages
|
||||
Commit messages are highly important tools for informing other developers on
|
||||
what a given change does and why. Every commit must always have a properly
|
||||
filled out commit message with the following format:
|
||||
@example
|
||||
area changed: short 1 line description
|
||||
|
||||
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 Keep the main commit message short with an extended description below.
|
||||
The commit message should have a short first line in the form of
|
||||
a @samp{topic: short description} as a header, separated by a newline
|
||||
from the body consisting of an explanation of why the change is necessary.
|
||||
If the commit fixes a known bug on the bug tracker, the commit message
|
||||
should include its bug ID. Referring to the issue on the bug tracker does
|
||||
not exempt you from writing an excerpt of the bug in the commit message.
|
||||
|
||||
@subheading Testing must be adequate but not excessive.
|
||||
If it works for you, others, and passes FATE then it should be OK to commit
|
||||
@@ -376,6 +300,15 @@ later on.
|
||||
Also if you have doubts about splitting or not splitting, do not hesitate to
|
||||
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.
|
||||
We refuse source indentation and other cosmetic changes if they are mixed
|
||||
with functional changes, such commits will be rejected and removed. Every
|
||||
@@ -390,15 +323,27 @@ 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
|
||||
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.
|
||||
Make sure the author of the commit is set correctly. (see git commit --author)
|
||||
If you apply a patch, send an
|
||||
answer to ffmpeg-devel (or wherever you got the patch from) saying that
|
||||
you applied the patch.
|
||||
|
||||
@subheading Credit any researchers
|
||||
If a commit/patch fixes an issues found by some researcher, always credit the
|
||||
researcher in the commit message for finding/reporting the issue.
|
||||
@subheading Complex patches should refer to discussion surrounding them.
|
||||
When applying patches that have been discussed (at length) on the mailing
|
||||
list, reference the thread in the log message.
|
||||
|
||||
@subheading Always wait long enough before pushing changes
|
||||
Do NOT commit to code actively maintained by others without permission.
|
||||
@@ -408,6 +353,22 @@ 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!
|
||||
|
||||
@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.
|
||||
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
|
||||
@@ -417,150 +378,10 @@ 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
|
||||
or obfuscates the code.
|
||||
|
||||
@section Library public interfaces
|
||||
Every library in FFmpeg provides a set of public APIs in its installed headers,
|
||||
which are those listed in the variable @code{HEADERS} in that library's
|
||||
@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
|
||||
@subheading Check untrusted input properly.
|
||||
Never write to unallocated memory, never write over the end of arrays,
|
||||
always check values read from some untrusted source before using them
|
||||
as array index or other risky things.
|
||||
|
||||
@section Documentation/Other
|
||||
@subheading Subscribe to the ffmpeg-devel mailing list.
|
||||
@@ -604,6 +425,35 @@ 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.
|
||||
|
||||
@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}
|
||||
@chapter Submitting patches
|
||||
|
||||
@@ -644,11 +494,6 @@ patch is inline or attached per mail.
|
||||
You can check @url{https://patchwork.ffmpeg.org}, if your patch does not show up, its mime type
|
||||
likely was wrong.
|
||||
|
||||
@subheading 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
|
||||
Using @code{git send-email} might not be desirable for everyone. The
|
||||
following trick allows to send patches via email clients in a safe
|
||||
@@ -825,14 +670,16 @@ Lines with similar content should be aligned vertically when doing so
|
||||
improves readability.
|
||||
|
||||
@item
|
||||
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.
|
||||
Consider adding a regression test for your code.
|
||||
|
||||
@item
|
||||
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
|
||||
Test your code with valgrind and or Address Sanitizer to ensure it's free
|
||||
of leaks, out of array accesses, etc.
|
||||
@@ -882,8 +729,6 @@ accordingly].
|
||||
|
||||
@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
|
||||
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
|
||||
|
||||
@@ -789,11 +789,6 @@ about 80-96 kbps/channel
|
||||
@end table
|
||||
|
||||
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
|
||||
|
||||
@subsection Examples
|
||||
@@ -864,13 +859,6 @@ Enable the encoder to use ABR when set to 1. The @command{lame}
|
||||
@option{--abr} sets the target bitrate, while this options only
|
||||
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
|
||||
|
||||
@section libopencore-amrnb
|
||||
@@ -977,17 +965,14 @@ Favor improved speech intelligibility.
|
||||
@item audio
|
||||
Favor faithfulness to the input (the default).
|
||||
@item lowdelay
|
||||
Restrict to only the lowest delay modes by disabling voice-optimized
|
||||
modes.
|
||||
Restrict to only the lowest delay modes.
|
||||
@end table
|
||||
|
||||
@item cutoff (N.A.)
|
||||
Set cutoff bandwidth in Hz. The argument must be exactly one of the
|
||||
following: 4000, 6000, 8000, 12000, or 20000, corresponding to
|
||||
narrowband, mediumband, wideband, super wideband, and fullband
|
||||
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.
|
||||
respectively. The default is 0 (cutoff disabled).
|
||||
|
||||
@item mapping_family (@emph{mapping_family})
|
||||
Set channel mapping family to be used by the encoder. The default value of -1
|
||||
@@ -1964,6 +1949,22 @@ Set the number of slices, used in parallelized encoding. Default value
|
||||
is 0. This is only used when @option{slice_mode} is set to
|
||||
@samp{fixed}.
|
||||
|
||||
@item slice_mode
|
||||
Set slice mode. Can assume one of the following possible values:
|
||||
|
||||
@table @samp
|
||||
@item fixed
|
||||
a fixed number of slices
|
||||
@item rowmb
|
||||
one slice per row of macroblocks
|
||||
@item auto
|
||||
automatic number of slices according to number of threads
|
||||
@item dyn
|
||||
dynamic slicing
|
||||
@end table
|
||||
|
||||
Default value is @samp{auto}.
|
||||
|
||||
@item loopfilter
|
||||
Enable loop filter, if set to 1 (automatically enabled). To disable
|
||||
set a value of 0.
|
||||
@@ -2175,8 +2176,6 @@ Set altref noise reduction filter type: backward, forward, centered.
|
||||
Set altref noise reduction filter strength.
|
||||
@item rc-lookahead, lag-in-frames (@emph{lag-in-frames})
|
||||
Set number of frames to look ahead for frametype and ratecontrol.
|
||||
@item min-gf-interval
|
||||
Set minimum golden/alternate reference frame interval (VP9 only).
|
||||
@end table
|
||||
|
||||
@item error-resilient
|
||||
@@ -2449,20 +2448,6 @@ Quantizer curve compression factor
|
||||
@item refs (@emph{ref})
|
||||
Number of reference frames each P-frame can use. The range is from @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})
|
||||
Sets the threshold for the scene change detection.
|
||||
|
||||
@@ -2755,10 +2740,6 @@ Only the mpeg2 and h264 decoders provide these. Default is 1 (on).
|
||||
@item udu_sei @var{boolean}
|
||||
Import user data unregistered SEI if available into output. Default is 0 (off).
|
||||
|
||||
@item mb_info @var{boolean}
|
||||
Set mb_info data through AVFrameSideData, only useful when used from the
|
||||
API. Default is 0 (off).
|
||||
|
||||
@item x264-params (N.A.)
|
||||
Override the x264 configuration using a :-separated list of key=value
|
||||
parameters.
|
||||
@@ -2979,24 +2960,27 @@ Place global headers in extradata instead of every keyframe.
|
||||
|
||||
@item trellis
|
||||
|
||||
@item me_quality
|
||||
Set motion estimation quality level. Possible values in decreasing order of
|
||||
@item me_method
|
||||
Set motion estimation method. Possible values in decreasing order of
|
||||
speed and increasing order of quality:
|
||||
|
||||
@table @samp
|
||||
@item 0
|
||||
@item zero
|
||||
Use no motion estimation (default).
|
||||
|
||||
@item 1, 2
|
||||
@item phods
|
||||
@item x1
|
||||
@item log
|
||||
Enable advanced diamond zonal search for 16x16 blocks and half-pixel
|
||||
refinement for 16x16 blocks.
|
||||
refinement for 16x16 blocks. @samp{x1} and @samp{log} are aliases for
|
||||
@samp{phods}.
|
||||
|
||||
@item 3, 4
|
||||
@item epzs
|
||||
Enable all of the things described above, plus advanced diamond zonal
|
||||
search for 8x8 blocks and half-pixel refinement for 8x8 blocks, also
|
||||
enable motion estimation on chroma planes for P and B-frames.
|
||||
search for 8x8 blocks, half-pixel refinement for 8x8 blocks, and motion
|
||||
estimation on chroma planes.
|
||||
|
||||
@item 5, 6
|
||||
@item full
|
||||
Enable all of the things described above, plus extended 16x16 and 8x8
|
||||
blocks search.
|
||||
@end table
|
||||
@@ -3079,20 +3063,6 @@ Video encoders can take input in either of nv12 or yuv420p form
|
||||
(some encoders support both, some support only either - in practice,
|
||||
nv12 is the safer choice, especially among HW encoders).
|
||||
|
||||
@section 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
|
||||
|
||||
MPEG-2 video encoder.
|
||||
@@ -3232,8 +3202,8 @@ recommended value) and do not set a size constraint.
|
||||
|
||||
@section QSV Encoders
|
||||
|
||||
The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG,
|
||||
VP9, AV1)
|
||||
The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG
|
||||
and VP9)
|
||||
|
||||
@subsection Ratecontrol Method
|
||||
The ratecontrol method is selected as follows:
|
||||
@@ -3274,9 +3244,9 @@ the average bitrate.
|
||||
than the average bitrate.
|
||||
|
||||
@item
|
||||
@var{AVBR} - average VBR mode, when @option{maxrate} is not specified, both
|
||||
@option{avbr_accuracy} and @option{avbr_convergence} are set to non-zero. This
|
||||
mode is available for H264 and HEVC on Windows.
|
||||
@var{AVBR} - average VBR mode, when @option{maxrate} is not specified. This mode
|
||||
is further configured by the @option{avbr_accuracy} and
|
||||
@option{avbr_convergence} options.
|
||||
@end itemize
|
||||
@end itemize
|
||||
|
||||
@@ -3330,6 +3300,19 @@ Specifies how many asynchronous operations an application performs
|
||||
before the application explicitly synchronizes the result. If zero,
|
||||
the value is not specified.
|
||||
|
||||
@item @var{avbr_accuracy}
|
||||
Accuracy of the AVBR ratecontrol (unit of tenth of percent).
|
||||
|
||||
@item @var{avbr_convergence}
|
||||
Convergence of the AVBR ratecontrol (unit of 100 frames)
|
||||
|
||||
The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the
|
||||
average variable bitrate control (AVBR) algorithm.
|
||||
The algorithm focuses on overall encoding quality while meeting the specified
|
||||
bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy},
|
||||
after a @var{avbr_Convergence} period. This method does not follow HRD and the
|
||||
instant bitrate is not capped or padded.
|
||||
|
||||
@item @var{preset}
|
||||
This option itemizes a range of choices from veryfast (best speed) to veryslow
|
||||
(best quality).
|
||||
@@ -3354,55 +3337,10 @@ For encoders set this flag to ON to reduce power consumption and GPU usage.
|
||||
Following options can be used durning qsv encoding.
|
||||
|
||||
@table @option
|
||||
@item @var{global_quality}
|
||||
@item @var{i_quant_factor}
|
||||
@item @var{i_quant_offset}
|
||||
@item @var{b_quant_factor}
|
||||
@item @var{b_quant_offset}
|
||||
@item @var{qsv_config_qp}
|
||||
Supported in h264_qsv and hevc_qsv.
|
||||
Change these value to reset qsv codec's qp configuration.
|
||||
|
||||
@item @var{max_frame_size}
|
||||
Supported in h264_qsv and hevc_qsv.
|
||||
Change this value to reset qsv codec's MaxFrameSize configuration.
|
||||
|
||||
@item @var{gop_size}
|
||||
Change this value to reset qsv codec's gop configuration.
|
||||
|
||||
@item @var{int_ref_type}
|
||||
@item @var{int_ref_cycle_size}
|
||||
@item @var{int_ref_qp_delta}
|
||||
@item @var{int_ref_cycle_dist}
|
||||
Supported in h264_qsv and hevc_qsv.
|
||||
Change these value to reset qsv codec's Intra Refresh configuration.
|
||||
|
||||
@item @var{qmax}
|
||||
@item @var{qmin}
|
||||
@item @var{max_qp_i}
|
||||
@item @var{min_qp_i}
|
||||
@item @var{max_qp_p}
|
||||
@item @var{min_qp_p}
|
||||
@item @var{max_qp_b}
|
||||
@item @var{min_qp_b}
|
||||
Supported in h264_qsv.
|
||||
Change these value to reset qsv codec's max/min qp configuration.
|
||||
|
||||
@item @var{low_delay_brc}
|
||||
Supported in h264_qsv, hevc_qsv and av1_qsv.
|
||||
Change this value to reset qsv codec's low_delay_brc configuration.
|
||||
|
||||
@item @var{framerate}
|
||||
Change this value to reset qsv codec's framerate configuration.
|
||||
|
||||
@item @var{bit_rate}
|
||||
@item @var{rc_buffer_size}
|
||||
@item @var{rc_initial_buffer_occupancy}
|
||||
@item @var{rc_max_rate}
|
||||
Change these value to reset qsv codec's bitrate control configuration.
|
||||
|
||||
@item @var{pic_timing_sei}
|
||||
Supported in h264_qsv and hevc_qsv.
|
||||
Change this value to reset qsv codec's pic_timing_sei configuration.
|
||||
This option can be set in per-frame metadata. QP parameter can be dynamically
|
||||
changed when encoding in CQP mode.
|
||||
@end table
|
||||
|
||||
@subsection H264 options
|
||||
@@ -3506,10 +3444,8 @@ Specifies intra refresh type. The major goal of intra refresh is improvement of
|
||||
error resilience without significant impact on encoded bitstream size caused by
|
||||
I frames. The SDK encoder achieves this by encoding part of each frame in
|
||||
refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means
|
||||
vertical refresh, by column of MBs. @var{horizontal} means horizontal refresh,
|
||||
by rows of MBs. @var{slice} means horizontal refresh by slices without
|
||||
overlapping. In case of @var{slice}, in_ref_cycle_size is ignored. To enable
|
||||
intra refresh, B frame should be set to 0.
|
||||
vertical refresh, by column of MBs. To enable intra refresh, B frame should be
|
||||
set to 0.
|
||||
|
||||
@item @var{int_ref_cycle_size}
|
||||
Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are
|
||||
@@ -3564,52 +3500,6 @@ Maximum video quantizer scale for B frame.
|
||||
|
||||
@item @var{min_qp_b}
|
||||
Minimum video quantizer scale for B frame.
|
||||
|
||||
@item @var{scenario}
|
||||
Provides a hint to encoder about the scenario for the encoding session.
|
||||
@table @samp
|
||||
@item unknown
|
||||
@item displayremoting
|
||||
@item videoconference
|
||||
@item archive
|
||||
@item livestreaming
|
||||
@item cameracapture
|
||||
@item videosurveillance
|
||||
@item gamestreaming
|
||||
@item remotegaming
|
||||
@end table
|
||||
|
||||
@item @var{avbr_accuracy}
|
||||
Accuracy of the AVBR ratecontrol (unit of tenth of percent).
|
||||
|
||||
@item @var{avbr_convergence}
|
||||
Convergence of the AVBR ratecontrol (unit of 100 frames)
|
||||
|
||||
The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the
|
||||
average variable bitrate control (AVBR) algorithm.
|
||||
The algorithm focuses on overall encoding quality while meeting the specified
|
||||
bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy},
|
||||
after a @var{avbr_Convergence} period. This method does not follow HRD and the
|
||||
instant bitrate is not capped or padded.
|
||||
|
||||
@item @var{skip_frame}
|
||||
Use per-frame metadata "qsv_skip_frame" to skip frame when encoding. This option
|
||||
defines the usage of this metadata.
|
||||
@table @samp
|
||||
@item no_skip
|
||||
Frame skipping is disabled.
|
||||
@item insert_dummy
|
||||
Encoder inserts into bitstream frame where all macroblocks are encoded as
|
||||
skipped.
|
||||
@item insert_nothing
|
||||
Similar to insert_dummy, but encoder inserts nothing into bitstream. The skipped
|
||||
frames are still used in brc. For example, gop still include skipped frames, and
|
||||
the frames after skipped frames will be larger in size.
|
||||
@item brc_only
|
||||
skip_frame metadata indicates the number of missed frames before the current
|
||||
frame.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@subsection HEVC Options
|
||||
@@ -3650,13 +3540,6 @@ Setting this flag turns on or off LowDelayBRC feautre in qsv plugin, which provi
|
||||
more accurate bitrate control to minimize the variance of bitstream size frame
|
||||
by frame. Value: -1-default 0-off 1-on
|
||||
|
||||
@item @var{adaptive_i}
|
||||
This flag controls insertion of I frames by the QSV encoder. Turn ON this flag
|
||||
to allow changing of frame type from P and B to I.
|
||||
|
||||
@item @var{adaptive_b}
|
||||
This flag controls changing of frame type from B to P.
|
||||
|
||||
@item @var{p_strategy}
|
||||
Enable P-pyramid: 0-default 1-simple 2-pyramid(bf need to be set to 0).
|
||||
|
||||
@@ -3700,15 +3583,6 @@ Set the encoding profile (scc requires libmfx >= 1.32).
|
||||
@item scc
|
||||
@end table
|
||||
|
||||
@item @var{tier}
|
||||
Set the encoding tier (only level >= 4 can support high tier).
|
||||
This option only takes effect when the level option is specified.
|
||||
|
||||
@table @samp
|
||||
@item main
|
||||
@item high
|
||||
@end table
|
||||
|
||||
@item @var{gpb}
|
||||
1: GPB (generalized P/B frame)
|
||||
|
||||
@@ -3735,10 +3609,8 @@ Specifies intra refresh type. The major goal of intra refresh is improvement of
|
||||
error resilience without significant impact on encoded bitstream size caused by
|
||||
I frames. The SDK encoder achieves this by encoding part of each frame in
|
||||
refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means
|
||||
vertical refresh, by column of MBs. @var{horizontal} means horizontal refresh,
|
||||
by rows of MBs. @var{slice} means horizontal refresh by slices without
|
||||
overlapping. In case of @var{slice}, in_ref_cycle_size is ignored. To enable
|
||||
intra refresh, B frame should be set to 0.
|
||||
vertical refresh, by column of MBs. To enable intra refresh, B frame should be
|
||||
set to 0.
|
||||
|
||||
@item @var{int_ref_cycle_size}
|
||||
Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are
|
||||
@@ -3769,52 +3641,6 @@ Maximum video quantizer scale for B frame.
|
||||
|
||||
@item @var{min_qp_b}
|
||||
Minimum video quantizer scale for B frame.
|
||||
|
||||
@item @var{scenario}
|
||||
Provides a hint to encoder about the scenario for the encoding session.
|
||||
@table @samp
|
||||
@item unknown
|
||||
@item displayremoting
|
||||
@item videoconference
|
||||
@item archive
|
||||
@item livestreaming
|
||||
@item cameracapture
|
||||
@item videosurveillance
|
||||
@item gamestreaming
|
||||
@item remotegaming
|
||||
@end table
|
||||
|
||||
@item @var{avbr_accuracy}
|
||||
Accuracy of the AVBR ratecontrol (unit of tenth of percent).
|
||||
|
||||
@item @var{avbr_convergence}
|
||||
Convergence of the AVBR ratecontrol (unit of 100 frames)
|
||||
|
||||
The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the
|
||||
average variable bitrate control (AVBR) algorithm.
|
||||
The algorithm focuses on overall encoding quality while meeting the specified
|
||||
bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy},
|
||||
after a @var{avbr_Convergence} period. This method does not follow HRD and the
|
||||
instant bitrate is not capped or padded.
|
||||
|
||||
@item @var{skip_frame}
|
||||
Use per-frame metadata "qsv_skip_frame" to skip frame when encoding. This option
|
||||
defines the usage of this metadata.
|
||||
@table @samp
|
||||
@item no_skip
|
||||
Frame skipping is disabled.
|
||||
@item insert_dummy
|
||||
Encoder inserts into bitstream frame where all macroblocks are encoded as
|
||||
skipped.
|
||||
@item insert_nothing
|
||||
Similar to insert_dummy, but encoder inserts nothing into bitstream. The skipped
|
||||
frames are still used in brc. For example, gop still include skipped frames, and
|
||||
the frames after skipped frames will be larger in size.
|
||||
@item brc_only
|
||||
skip_frame metadata indicates the number of missed frames before the current
|
||||
frame.
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@subsection MPEG2 Options
|
||||
@@ -3848,48 +3674,6 @@ Number of columns for tiled encoding (requires libmfx >= 1.29).
|
||||
Number of rows for tiled encoding (requires libmfx >= 1.29).
|
||||
@end table
|
||||
|
||||
@subsection AV1 Options
|
||||
These options are used by av1_qsv (requires libvpl).
|
||||
@table @option
|
||||
@item @var{profile}
|
||||
@table @samp
|
||||
@item unknown
|
||||
@item main
|
||||
@end table
|
||||
|
||||
@item @var{tile_cols}
|
||||
Number of columns for tiled encoding.
|
||||
|
||||
@item @var{tile_rows}
|
||||
Number of rows for tiled encoding.
|
||||
|
||||
@item @var{adaptive_i}
|
||||
This flag controls insertion of I frames by the QSV encoder. Turn ON this flag
|
||||
to allow changing of frame type from P and B to I.
|
||||
|
||||
@item @var{adaptive_b}
|
||||
This flag controls changing of frame type from B to P.
|
||||
|
||||
@item @var{b_strategy}
|
||||
This option controls usage of B frames as reference.
|
||||
|
||||
@item @var{extbrc}
|
||||
Extended bitrate control.
|
||||
|
||||
@item @var{look_ahead_depth}
|
||||
Depth of look ahead in number frames, available when extbrc option is enabled.
|
||||
|
||||
@item @var{low_delay_brc}
|
||||
Setting this flag turns on or off LowDelayBRC feautre in qsv plugin, which provides
|
||||
more accurate bitrate control to minimize the variance of bitstream size frame
|
||||
by frame. Value: -1-default 0-off 1-on
|
||||
|
||||
@item max_frame_size
|
||||
Set the allowed max size in bytes for each frame. If the frame size exceeds
|
||||
the limitation, encoder will adjust the QP value to control the frame size.
|
||||
Invalid in CQP rate control mode.
|
||||
@end table
|
||||
|
||||
@section snow
|
||||
|
||||
@subsection Options
|
||||
@@ -4009,20 +3793,6 @@ Average variable bitrate.
|
||||
Each encoder also has its own specific options:
|
||||
@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
|
||||
@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}.
|
||||
|
||||
1
doc/examples/.gitignore
vendored
1
doc/examples/.gitignore
vendored
@@ -22,4 +22,3 @@
|
||||
/transcoding
|
||||
/vaapi_encode
|
||||
/vaapi_transcode
|
||||
/qsv_transcode
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
EXAMPLES-$(CONFIG_AVIO_HTTP_SERVE_FILES) += avio_http_serve_files
|
||||
EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir
|
||||
EXAMPLES-$(CONFIG_AVIO_READ_CALLBACK_EXAMPLE) += avio_read_callback
|
||||
EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading
|
||||
EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio
|
||||
EXAMPLES-$(CONFIG_DECODE_FILTER_AUDIO_EXAMPLE) += decode_filter_audio
|
||||
EXAMPLES-$(CONFIG_DECODE_FILTER_VIDEO_EXAMPLE) += decode_filter_video
|
||||
EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video
|
||||
EXAMPLES-$(CONFIG_DEMUX_DECODE_EXAMPLE) += demux_decode
|
||||
EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding
|
||||
EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio
|
||||
EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video
|
||||
EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs
|
||||
EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio
|
||||
EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio
|
||||
EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video
|
||||
EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient
|
||||
EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode
|
||||
EXAMPLES-$(CONFIG_MUX_EXAMPLE) += mux
|
||||
EXAMPLES-$(CONFIG_QSV_DECODE_EXAMPLE) += qsv_decode
|
||||
EXAMPLES-$(CONFIG_REMUX_EXAMPLE) += remux
|
||||
EXAMPLES-$(CONFIG_RESAMPLE_AUDIO_EXAMPLE) += resample_audio
|
||||
EXAMPLES-$(CONFIG_SCALE_VIDEO_EXAMPLE) += scale_video
|
||||
EXAMPLES-$(CONFIG_SHOW_METADATA_EXAMPLE) += show_metadata
|
||||
EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata
|
||||
EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing
|
||||
EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec
|
||||
EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing
|
||||
EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio
|
||||
EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video
|
||||
EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac
|
||||
EXAMPLES-$(CONFIG_TRANSCODE_EXAMPLE) += transcode
|
||||
EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding
|
||||
EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode
|
||||
EXAMPLES-$(CONFIG_VAAPI_TRANSCODE_EXAMPLE) += vaapi_transcode
|
||||
EXAMPLES-$(CONFIG_QSV_TRANSCODE_EXAMPLE) += qsv_transcode
|
||||
|
||||
EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF))
|
||||
EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF))
|
||||
|
||||
@@ -11,40 +11,33 @@ CFLAGS += -Wall -g
|
||||
CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS)
|
||||
LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS)
|
||||
|
||||
# missing the following targets, since they need special options in the FFmpeg build:
|
||||
# qsv_decode
|
||||
# qsv_transcode
|
||||
# vaapi_encode
|
||||
# vaapi_transcode
|
||||
|
||||
EXAMPLES=\
|
||||
avio_http_serve_files \
|
||||
avio_list_dir \
|
||||
avio_read_callback \
|
||||
EXAMPLES= avio_list_dir \
|
||||
avio_reading \
|
||||
decode_audio \
|
||||
decode_filter_audio \
|
||||
decode_filter_video \
|
||||
decode_video \
|
||||
demux_decode \
|
||||
demuxing_decoding \
|
||||
encode_audio \
|
||||
encode_video \
|
||||
extract_mvs \
|
||||
filtering_video \
|
||||
filtering_audio \
|
||||
http_multiclient \
|
||||
hw_decode \
|
||||
mux \
|
||||
remux \
|
||||
resample_audio \
|
||||
scale_video \
|
||||
show_metadata \
|
||||
metadata \
|
||||
muxing \
|
||||
remuxing \
|
||||
resampling_audio \
|
||||
scaling_video \
|
||||
transcode_aac \
|
||||
transcode
|
||||
transcoding \
|
||||
|
||||
OBJS=$(addsuffix .o,$(EXAMPLES))
|
||||
|
||||
# the following examples make explicit use of the math library
|
||||
avcodec: LDLIBS += -lm
|
||||
encode_audio: LDLIBS += -lm
|
||||
mux: LDLIBS += -lm
|
||||
resample_audio: LDLIBS += -lm
|
||||
muxing: LDLIBS += -lm
|
||||
resampling_audio: LDLIBS += -lm
|
||||
|
||||
.phony: all clean-test clean
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ that you have them installed and working on your system.
|
||||
|
||||
Method 1: build the installed examples in a generic read/write user directory
|
||||
|
||||
Copy to a read/write user directory and run:
|
||||
make -f Makefile.example
|
||||
|
||||
It will link to the libraries on your system, assuming the PKG_CONFIG_PATH is
|
||||
Copy to a read/write user directory and just use "make", it will link
|
||||
to the libraries on your system, assuming the PKG_CONFIG_PATH is
|
||||
correctly configured.
|
||||
|
||||
Method 2: build the examples in-tree
|
||||
@@ -22,4 +20,4 @@ examples using "make examplesclean"
|
||||
|
||||
If you want to try the dedicated Makefile examples (to emulate the first
|
||||
method), go into doc/examples and run a command such as
|
||||
PKG_CONFIG_PATH=pc-uninstalled make -f Makefile.example
|
||||
PKG_CONFIG_PATH=pc-uninstalled make.
|
||||
|
||||
@@ -20,13 +20,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat AVIOContext list directory API usage example
|
||||
* @example avio_list_dir.c
|
||||
*
|
||||
* Show how to list directories through the libavformat AVIOContext API.
|
||||
*/
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat AVIOContext read callback API usage example
|
||||
* @example avio_read_callback.c
|
||||
* @file
|
||||
* libavformat AVIOContext API example.
|
||||
*
|
||||
* Make libavformat demuxer access media content through a custom
|
||||
* AVIOContext read callback.
|
||||
* @example avio_reading.c
|
||||
*/
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
@@ -21,11 +21,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavcodec audio decoding API usage example
|
||||
* @example decode_audio.c
|
||||
* @file
|
||||
* audio decoding with libavcodec API example
|
||||
*
|
||||
* Decode data from an MP2 input file and generate a raw audio file to
|
||||
* be played with ffplay.
|
||||
* @example decode_audio.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavcodec video decoding API usage example
|
||||
* @example decode_video.c *
|
||||
* @file
|
||||
* video decoding with libavcodec API example
|
||||
*
|
||||
* Read from an MPEG1 video file, decode frames, and generate PGM images as
|
||||
* output.
|
||||
* @example decode_video.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -70,12 +69,12 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("saving frame %3"PRId64"\n", dec_ctx->frame_num);
|
||||
printf("saving frame %3d\n", dec_ctx->frame_number);
|
||||
fflush(stdout);
|
||||
|
||||
/* the picture is allocated by the decoder. no need to
|
||||
free it */
|
||||
snprintf(buf, sizeof(buf), "%s-%"PRId64, filename, dec_ctx->frame_num);
|
||||
snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
|
||||
pgm_save(frame->data[0], frame->linesize[0],
|
||||
frame->width, frame->height, buf);
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat and libavcodec demuxing and decoding API usage example
|
||||
* @example demux_decode.c
|
||||
* @file
|
||||
* Demuxing and decoding example.
|
||||
*
|
||||
* Show how to use the libavformat and libavcodec API to demux and decode audio
|
||||
* and video data. Write the output as raw audio and input files to be played by
|
||||
* ffplay.
|
||||
* Show how to use the libavformat and libavcodec API to demux and
|
||||
* decode audio and video data.
|
||||
* @example demuxing_decoding.c
|
||||
*/
|
||||
|
||||
#include <libavutil/imgutils.h>
|
||||
@@ -73,14 +73,14 @@ static int output_video_frame(AVFrame *frame)
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("video_frame n:%d\n",
|
||||
video_frame_count++);
|
||||
printf("video_frame n:%d coded_n:%d\n",
|
||||
video_frame_count++, frame->coded_picture_number);
|
||||
|
||||
/* copy decoded frame to destination buffer:
|
||||
* this is required since rawvideo expects non aligned data */
|
||||
av_image_copy2(video_dst_data, video_dst_linesize,
|
||||
frame->data, frame->linesize,
|
||||
pix_fmt, width, height);
|
||||
av_image_copy(video_dst_data, video_dst_linesize,
|
||||
(const uint8_t **)(frame->data), frame->linesize,
|
||||
pix_fmt, width, height);
|
||||
|
||||
/* write to rawvideo file */
|
||||
fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file);
|
||||
@@ -138,9 +138,11 @@ static int decode_packet(AVCodecContext *dec, const AVPacket *pkt)
|
||||
ret = output_audio_frame(frame);
|
||||
|
||||
av_frame_unref(frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_codec_context(int *stream_idx,
|
||||
@@ -21,10 +21,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavcodec encoding audio API usage examples
|
||||
* @example encode_audio.c
|
||||
* @file
|
||||
* audio encoding with libavcodec API example.
|
||||
*
|
||||
* Generate a synthetic audio signal and encode it to an output MP2 file.
|
||||
* @example encode_audio.c
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavcodec encoding video API usage example
|
||||
* @example encode_video.c
|
||||
* @file
|
||||
* video encoding with libavcodec API example
|
||||
*
|
||||
* Generate synthetic video data and encode it to an output file.
|
||||
* @example encode_video.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
|
||||
It makes only sense because this tiny examples writes packets
|
||||
directly. This is called "elementary stream" and only works for some
|
||||
codecs. To create a valid file, you usually need to write packets
|
||||
into a proper file format or protocol; see mux.c.
|
||||
into a proper file format or protocol; see muxing.c.
|
||||
*/
|
||||
if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)
|
||||
fwrite(endcode, 1, sizeof(endcode), f);
|
||||
|
||||
@@ -21,14 +21,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavcodec motion vectors extraction API usage example
|
||||
* @example extract_mvs.c
|
||||
*
|
||||
* Read from input file, decode video stream and print a motion vectors
|
||||
* representation to stdout.
|
||||
*/
|
||||
|
||||
#include <libavutil/motion_vector.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -69,11 +61,10 @@ static int decode_packet(const AVPacket *pkt)
|
||||
const AVMotionVector *mvs = (const AVMotionVector *)sd->data;
|
||||
for (i = 0; i < sd->size / sizeof(*mvs); i++) {
|
||||
const AVMotionVector *mv = &mvs[i];
|
||||
printf("%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%"PRIx64",%4d,%4d,%4d\n",
|
||||
printf("%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%"PRIx64"\n",
|
||||
video_frame_count, mv->source,
|
||||
mv->w, mv->h, mv->src_x, mv->src_y,
|
||||
mv->dst_x, mv->dst_y, mv->flags,
|
||||
mv->motion_x, mv->motion_y, mv->motion_scale);
|
||||
mv->dst_x, mv->dst_y, mv->flags);
|
||||
}
|
||||
}
|
||||
av_frame_unref(frame);
|
||||
@@ -175,7 +166,7 @@ int main(int argc, char **argv)
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("framenum,source,blockw,blockh,srcx,srcy,dstx,dsty,flags,motion_x,motion_y,motion_scale\n");
|
||||
printf("framenum,source,blockw,blockh,srcx,srcy,dstx,dsty,flags\n");
|
||||
|
||||
/* read frames from the file */
|
||||
while (av_read_frame(fmt_ctx, pkt) >= 0) {
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavfilter audio filtering API usage example
|
||||
* @example filter_audio.c
|
||||
* @file
|
||||
* libavfilter API usage example.
|
||||
*
|
||||
* This example will generate a sine wave audio, pass it through a simple filter
|
||||
* chain, and then compute the MD5 checksum of the output data.
|
||||
* @example filter_audio.c
|
||||
* This example will generate a sine wave audio,
|
||||
* pass it through a simple filter chain, and then compute the MD5 checksum of
|
||||
* the output data.
|
||||
*
|
||||
* The filter chain it uses is:
|
||||
* (input) -> abuffer -> volume -> aformat -> abuffersink -> (output)
|
||||
|
||||
@@ -23,11 +23,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file audio decoding and filtering usage example
|
||||
* @example decode_filter_audio.c
|
||||
*
|
||||
* Demux, decode and filter audio input file, generate a raw audio
|
||||
* file to be played with ffplay.
|
||||
* @file
|
||||
* API example for audio decoding and filtering
|
||||
* @example filtering_audio.c
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -24,7 +24,7 @@
|
||||
/**
|
||||
* @file
|
||||
* API example for decoding and filtering
|
||||
* @example decode_filter_video.c
|
||||
* @example filtering_video.c
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 600 /* for usleep */
|
||||
@@ -21,11 +21,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat multi-client network API usage example
|
||||
* @example avio_http_serve_files.c
|
||||
* @file
|
||||
* libavformat multi-client network API usage example.
|
||||
*
|
||||
* Serve a file without decoding or demuxing it over the HTTP protocol. Multiple
|
||||
* clients can connect and will receive the same file.
|
||||
* @example http_multiclient.c
|
||||
* This example will serve a file without decoding or demuxing it over http.
|
||||
* Multiple clients can connect and will receive the same file.
|
||||
*/
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -24,11 +24,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HW-accelerated decoding API usage.example
|
||||
* @example hw_decode.c
|
||||
* @file
|
||||
* HW-Accelerated decoding example.
|
||||
*
|
||||
* Perform HW-accelerated decoding with output frames from HW video
|
||||
* surfaces.
|
||||
* @example hw_decode.c
|
||||
* This example shows how to do HW-accelerated decoding with output
|
||||
* frames from the HW video surfaces.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -21,10 +21,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat metadata extraction API usage example
|
||||
* @example show_metadata.c
|
||||
*
|
||||
* Show metadata from an input file.
|
||||
* @file
|
||||
* Shows how the metadata API can be used in application programs.
|
||||
* @example metadata.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -53,7 +52,7 @@ int main (int argc, char **argv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
while ((tag = av_dict_iterate(fmt_ctx->metadata, tag)))
|
||||
while ((tag = av_dict_get(fmt_ctx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||
printf("%s=%s\n", tag->key, tag->value);
|
||||
|
||||
avformat_close_input(&fmt_ctx);
|
||||
@@ -21,11 +21,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat muxing API usage example
|
||||
* @example mux.c
|
||||
* @file
|
||||
* libavformat API example.
|
||||
*
|
||||
* Generate a synthetic audio and video signal and mux them to a media file in
|
||||
* any supported libavformat format. The default codecs are used.
|
||||
* Output a media file in any supported libavformat format. The default
|
||||
* codecs are used.
|
||||
* @example muxing.c
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -218,6 +219,8 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
|
||||
int sample_rate, int nb_samples)
|
||||
{
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
int ret;
|
||||
|
||||
if (!frame) {
|
||||
fprintf(stderr, "Error allocating an audio frame\n");
|
||||
exit(1);
|
||||
@@ -229,7 +232,8 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
|
||||
frame->nb_samples = nb_samples;
|
||||
|
||||
if (nb_samples) {
|
||||
if (av_frame_get_buffer(frame, 0) < 0) {
|
||||
ret = av_frame_get_buffer(frame, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error allocating an audio buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -347,7 +351,8 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
|
||||
if (frame) {
|
||||
/* convert samples from native format to destination codec format, using the resampler */
|
||||
/* compute destination number of samples */
|
||||
dst_nb_samples = swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples;
|
||||
dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
|
||||
c->sample_rate, c->sample_rate, AV_ROUND_UP);
|
||||
av_assert0(dst_nb_samples == frame->nb_samples);
|
||||
|
||||
/* when we pass a frame to the encoder, it may keep a reference to it
|
||||
@@ -378,27 +383,27 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
|
||||
/**************************************************************/
|
||||
/* video output */
|
||||
|
||||
static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height)
|
||||
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
AVFrame *frame;
|
||||
AVFrame *picture;
|
||||
int ret;
|
||||
|
||||
frame = av_frame_alloc();
|
||||
if (!frame)
|
||||
picture = av_frame_alloc();
|
||||
if (!picture)
|
||||
return NULL;
|
||||
|
||||
frame->format = pix_fmt;
|
||||
frame->width = width;
|
||||
frame->height = height;
|
||||
picture->format = pix_fmt;
|
||||
picture->width = width;
|
||||
picture->height = height;
|
||||
|
||||
/* allocate the buffers for the frame data */
|
||||
ret = av_frame_get_buffer(frame, 0);
|
||||
ret = av_frame_get_buffer(picture, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not allocate frame data.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return frame;
|
||||
return picture;
|
||||
}
|
||||
|
||||
static void open_video(AVFormatContext *oc, const AVCodec *codec,
|
||||
@@ -419,7 +424,7 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec,
|
||||
}
|
||||
|
||||
/* allocate and init a re-usable frame */
|
||||
ost->frame = alloc_frame(c->pix_fmt, c->width, c->height);
|
||||
ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
|
||||
if (!ost->frame) {
|
||||
fprintf(stderr, "Could not allocate video frame\n");
|
||||
exit(1);
|
||||
@@ -430,9 +435,9 @@ static void open_video(AVFormatContext *oc, const AVCodec *codec,
|
||||
* output format. */
|
||||
ost->tmp_frame = NULL;
|
||||
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
|
||||
ost->tmp_frame = alloc_frame(AV_PIX_FMT_YUV420P, c->width, c->height);
|
||||
ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
|
||||
if (!ost->tmp_frame) {
|
||||
fprintf(stderr, "Could not allocate temporary video frame\n");
|
||||
fprintf(stderr, "Could not allocate temporary picture\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1,435 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Intel QSV-accelerated video transcoding API usage example
|
||||
* @example qsv_transcode.c
|
||||
*
|
||||
* Perform QSV-accelerated transcoding and show to dynamically change
|
||||
* encoder's options.
|
||||
*
|
||||
* Usage: qsv_transcode input_stream codec output_stream initial option
|
||||
* { frame_number new_option }
|
||||
* e.g: - qsv_transcode input.mp4 h264_qsv output_h264.mp4 "g 60"
|
||||
* - qsv_transcode input.mp4 hevc_qsv output_hevc.mp4 "g 60 async_depth 1"
|
||||
* 100 "g 120"
|
||||
* (initialize codec with gop_size 60 and change it to 120 after 100
|
||||
* frames)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
static AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
|
||||
static AVBufferRef *hw_device_ctx = NULL;
|
||||
static AVCodecContext *decoder_ctx = NULL, *encoder_ctx = NULL;
|
||||
static int video_stream = -1;
|
||||
|
||||
typedef struct DynamicSetting {
|
||||
int frame_number;
|
||||
char* optstr;
|
||||
} DynamicSetting;
|
||||
static DynamicSetting *dynamic_setting;
|
||||
static int setting_number;
|
||||
static int current_setting_number;
|
||||
|
||||
static int str_to_dict(char* optstr, AVDictionary **opt)
|
||||
{
|
||||
char *key, *value;
|
||||
if (strlen(optstr) == 0)
|
||||
return 0;
|
||||
key = strtok(optstr, " ");
|
||||
if (key == NULL)
|
||||
return AVERROR(ENAVAIL);
|
||||
value = strtok(NULL, " ");
|
||||
if (value == NULL)
|
||||
return AVERROR(ENAVAIL);
|
||||
av_dict_set(opt, key, value, 0);
|
||||
do {
|
||||
key = strtok(NULL, " ");
|
||||
if (key == NULL)
|
||||
return 0;
|
||||
value = strtok(NULL, " ");
|
||||
if (value == NULL)
|
||||
return AVERROR(ENAVAIL);
|
||||
av_dict_set(opt, key, value, 0);
|
||||
} while(1);
|
||||
}
|
||||
|
||||
static int dynamic_set_parameter(AVCodecContext *avctx)
|
||||
{
|
||||
AVDictionary *opts = NULL;
|
||||
int ret = 0;
|
||||
static int frame_number = 0;
|
||||
frame_number++;
|
||||
if (current_setting_number < setting_number &&
|
||||
frame_number == dynamic_setting[current_setting_number].frame_number) {
|
||||
AVDictionaryEntry *e = NULL;
|
||||
ret = str_to_dict(dynamic_setting[current_setting_number++].optstr, &opts);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "The dynamic parameter is wrong\n");
|
||||
goto fail;
|
||||
}
|
||||
/* Set common option. The dictionary will be freed and replaced
|
||||
* by a new one containing all options not found in common option list.
|
||||
* Then this new dictionary is used to set private option. */
|
||||
if ((ret = av_opt_set_dict(avctx, &opts)) < 0)
|
||||
goto fail;
|
||||
/* Set codec specific option */
|
||||
if ((ret = av_opt_set_dict(avctx->priv_data, &opts)) < 0)
|
||||
goto fail;
|
||||
/* There is no "framerate" option in commom option list. Use "-r" to set
|
||||
* framerate, which is compatible with ffmpeg commandline. The video is
|
||||
* assumed to be average frame rate, so set time_base to 1/framerate. */
|
||||
e = av_dict_get(opts, "r", NULL, 0);
|
||||
if (e) {
|
||||
avctx->framerate = av_d2q(atof(e->value), INT_MAX);
|
||||
encoder_ctx->time_base = av_inv_q(encoder_ctx->framerate);
|
||||
}
|
||||
}
|
||||
fail:
|
||||
av_dict_free(&opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
while (*pix_fmts != AV_PIX_FMT_NONE) {
|
||||
if (*pix_fmts == AV_PIX_FMT_QSV) {
|
||||
return AV_PIX_FMT_QSV;
|
||||
}
|
||||
|
||||
pix_fmts++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "The QSV pixel format not offered in get_format()\n");
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
static int open_input_file(char *filename)
|
||||
{
|
||||
int ret;
|
||||
const AVCodec *decoder = NULL;
|
||||
AVStream *video = NULL;
|
||||
|
||||
if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
|
||||
fprintf(stderr, "Cannot open input file '%s', Error code: %s\n",
|
||||
filename, av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
|
||||
fprintf(stderr, "Cannot find input stream information. Error code: %s\n",
|
||||
av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Cannot find a video stream in the input file. "
|
||||
"Error code: %s\n", av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
video_stream = ret;
|
||||
video = ifmt_ctx->streams[video_stream];
|
||||
|
||||
switch(video->codecpar->codec_id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
decoder = avcodec_find_decoder_by_name("h264_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_HEVC:
|
||||
decoder = avcodec_find_decoder_by_name("hevc_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_VP9:
|
||||
decoder = avcodec_find_decoder_by_name("vp9_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_VP8:
|
||||
decoder = avcodec_find_decoder_by_name("vp8_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_AV1:
|
||||
decoder = avcodec_find_decoder_by_name("av1_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_MPEG2VIDEO:
|
||||
decoder = avcodec_find_decoder_by_name("mpeg2_qsv");
|
||||
break;
|
||||
case AV_CODEC_ID_MJPEG:
|
||||
decoder = avcodec_find_decoder_by_name("mjpeg_qsv");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Codec is not supportted by qsv\n");
|
||||
return AVERROR(ENAVAIL);
|
||||
}
|
||||
|
||||
if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if ((ret = avcodec_parameters_to_context(decoder_ctx, video->codecpar)) < 0) {
|
||||
fprintf(stderr, "avcodec_parameters_to_context error. Error code: %s\n",
|
||||
av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
decoder_ctx->framerate = av_guess_frame_rate(ifmt_ctx, video, NULL);
|
||||
|
||||
decoder_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
|
||||
if (!decoder_ctx->hw_device_ctx) {
|
||||
fprintf(stderr, "A hardware device reference create failed.\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
decoder_ctx->get_format = get_format;
|
||||
decoder_ctx->pkt_timebase = video->time_base;
|
||||
if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0)
|
||||
fprintf(stderr, "Failed to open codec for decoding. Error code: %s\n",
|
||||
av_err2str(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int encode_write(AVPacket *enc_pkt, AVFrame *frame)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
av_packet_unref(enc_pkt);
|
||||
|
||||
if((ret = dynamic_set_parameter(encoder_ctx)) < 0) {
|
||||
fprintf(stderr, "Failed to set dynamic parameter. Error code: %s\n",
|
||||
av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((ret = avcodec_send_frame(encoder_ctx, frame)) < 0) {
|
||||
fprintf(stderr, "Error during encoding. Error code: %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
while (1) {
|
||||
if (ret = avcodec_receive_packet(encoder_ctx, enc_pkt))
|
||||
break;
|
||||
enc_pkt->stream_index = 0;
|
||||
av_packet_rescale_ts(enc_pkt, encoder_ctx->time_base,
|
||||
ofmt_ctx->streams[0]->time_base);
|
||||
if ((ret = av_interleaved_write_frame(ofmt_ctx, enc_pkt)) < 0) {
|
||||
fprintf(stderr, "Error during writing data to output file. "
|
||||
"Error code: %s\n", av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (ret == AVERROR_EOF)
|
||||
return 0;
|
||||
ret = ((ret == AVERROR(EAGAIN)) ? 0:-1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dec_enc(AVPacket *pkt, const AVCodec *enc_codec, char *optstr)
|
||||
{
|
||||
AVFrame *frame;
|
||||
int ret = 0;
|
||||
|
||||
ret = avcodec_send_packet(decoder_ctx, pkt);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error during decoding. Error code: %s\n", av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (ret >= 0) {
|
||||
if (!(frame = av_frame_alloc()))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = avcodec_receive_frame(decoder_ctx, frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
} else if (ret < 0) {
|
||||
fprintf(stderr, "Error while decoding. Error code: %s\n", av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
if (!encoder_ctx->hw_frames_ctx) {
|
||||
AVDictionaryEntry *e = NULL;
|
||||
AVDictionary *opts = NULL;
|
||||
AVStream *ost;
|
||||
/* we need to ref hw_frames_ctx of decoder to initialize encoder's codec.
|
||||
Only after we get a decoded frame, can we obtain its hw_frames_ctx */
|
||||
encoder_ctx->hw_frames_ctx = av_buffer_ref(decoder_ctx->hw_frames_ctx);
|
||||
if (!encoder_ctx->hw_frames_ctx) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
/* set AVCodecContext Parameters for encoder, here we keep them stay
|
||||
* the same as decoder.
|
||||
*/
|
||||
encoder_ctx->time_base = av_inv_q(decoder_ctx->framerate);
|
||||
encoder_ctx->pix_fmt = AV_PIX_FMT_QSV;
|
||||
encoder_ctx->width = decoder_ctx->width;
|
||||
encoder_ctx->height = decoder_ctx->height;
|
||||
if ((ret = str_to_dict(optstr, &opts)) < 0) {
|
||||
fprintf(stderr, "Failed to set encoding parameter.\n");
|
||||
goto fail;
|
||||
}
|
||||
/* There is no "framerate" option in commom option list. Use "-r" to
|
||||
* set framerate, which is compatible with ffmpeg commandline. The
|
||||
* video is assumed to be average frame rate, so set time_base to
|
||||
* 1/framerate. */
|
||||
e = av_dict_get(opts, "r", NULL, 0);
|
||||
if (e) {
|
||||
encoder_ctx->framerate = av_d2q(atof(e->value), INT_MAX);
|
||||
encoder_ctx->time_base = av_inv_q(encoder_ctx->framerate);
|
||||
}
|
||||
if ((ret = avcodec_open2(encoder_ctx, enc_codec, &opts)) < 0) {
|
||||
fprintf(stderr, "Failed to open encode codec. Error code: %s\n",
|
||||
av_err2str(ret));
|
||||
av_dict_free(&opts);
|
||||
goto fail;
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
|
||||
if (!(ost = avformat_new_stream(ofmt_ctx, enc_codec))) {
|
||||
fprintf(stderr, "Failed to allocate stream for output format.\n");
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ost->time_base = encoder_ctx->time_base;
|
||||
ret = avcodec_parameters_from_context(ost->codecpar, encoder_ctx);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to copy the stream parameters. "
|
||||
"Error code: %s\n", av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* write the stream header */
|
||||
if ((ret = avformat_write_header(ofmt_ctx, NULL)) < 0) {
|
||||
fprintf(stderr, "Error while writing stream header. "
|
||||
"Error code: %s\n", av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
frame->pts = av_rescale_q(frame->pts, decoder_ctx->pkt_timebase,
|
||||
encoder_ctx->time_base);
|
||||
if ((ret = encode_write(pkt, frame)) < 0)
|
||||
fprintf(stderr, "Error during encoding and writing.\n");
|
||||
|
||||
fail:
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const AVCodec *enc_codec;
|
||||
int ret = 0;
|
||||
AVPacket *dec_pkt = NULL;
|
||||
|
||||
if (argc < 5 || (argc - 5) % 2) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file> <encoder> <output file>"
|
||||
" <\"encoding option set 0\"> [<frame_number> <\"encoding options set 1\">]...\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
setting_number = (argc - 5) / 2;
|
||||
dynamic_setting = av_malloc(setting_number * sizeof(*dynamic_setting));
|
||||
current_setting_number = 0;
|
||||
for (int i = 0; i < setting_number; i++) {
|
||||
dynamic_setting[i].frame_number = atoi(argv[i*2 + 5]);
|
||||
dynamic_setting[i].optstr = argv[i*2 + 6];
|
||||
}
|
||||
|
||||
ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, NULL, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to create a QSV device. Error code: %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
dec_pkt = av_packet_alloc();
|
||||
if (!dec_pkt) {
|
||||
fprintf(stderr, "Failed to allocate decode packet\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((ret = open_input_file(argv[1])) < 0)
|
||||
goto end;
|
||||
|
||||
if (!(enc_codec = avcodec_find_encoder_by_name(argv[2]))) {
|
||||
fprintf(stderr, "Could not find encoder '%s'\n", argv[2]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((ret = (avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, argv[3]))) < 0) {
|
||||
fprintf(stderr, "Failed to deduce output format from file extension. Error code: "
|
||||
"%s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(encoder_ctx = avcodec_alloc_context3(enc_codec))) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = avio_open(&ofmt_ctx->pb, argv[3], AVIO_FLAG_WRITE);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Cannot open output file. "
|
||||
"Error code: %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* read all packets and only transcoding video */
|
||||
while (ret >= 0) {
|
||||
if ((ret = av_read_frame(ifmt_ctx, dec_pkt)) < 0)
|
||||
break;
|
||||
|
||||
if (video_stream == dec_pkt->stream_index)
|
||||
ret = dec_enc(dec_pkt, enc_codec, argv[4]);
|
||||
|
||||
av_packet_unref(dec_pkt);
|
||||
}
|
||||
|
||||
/* flush decoder */
|
||||
av_packet_unref(dec_pkt);
|
||||
if ((ret = dec_enc(dec_pkt, enc_codec, argv[4])) < 0) {
|
||||
fprintf(stderr, "Failed to flush decoder %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* flush encoder */
|
||||
if ((ret = encode_write(dec_pkt, NULL)) < 0) {
|
||||
fprintf(stderr, "Failed to flush encoder %s\n", av_err2str(ret));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* write the trailer for output stream */
|
||||
if ((ret = av_write_trailer(ofmt_ctx)) < 0)
|
||||
fprintf(stderr, "Failed to write trailer %s\n", av_err2str(ret));
|
||||
|
||||
end:
|
||||
avformat_close_input(&ifmt_ctx);
|
||||
avformat_close_input(&ofmt_ctx);
|
||||
avcodec_free_context(&decoder_ctx);
|
||||
avcodec_free_context(&encoder_ctx);
|
||||
av_buffer_unref(&hw_device_ctx);
|
||||
av_packet_free(&dec_pkt);
|
||||
av_freep(&dynamic_setting);
|
||||
return ret;
|
||||
}
|
||||
@@ -21,11 +21,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Intel QSV-accelerated H.264 decoding API usage example
|
||||
* @example qsv_decode.c
|
||||
* @file
|
||||
* Intel QSV-accelerated H.264 decoding example.
|
||||
*
|
||||
* Perform QSV-accelerated H.264 decoding with output frames in the
|
||||
* GPU video surfaces, write the decoded frames to an output file.
|
||||
* @example qsvdec.c
|
||||
* This example shows how to do QSV-accelerated H.264 decoding with output
|
||||
* frames in the GPU video surfaces.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -21,11 +21,11 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libavformat/libavcodec demuxing and muxing API usage example
|
||||
* @example remux.c
|
||||
* @file
|
||||
* libavformat/libavcodec demuxing and muxing API example.
|
||||
*
|
||||
* Remux streams from one container format to another. Data is copied from the
|
||||
* input to the output without transcoding.
|
||||
* Remux streams from one container format to another.
|
||||
* @example remuxing.c
|
||||
*/
|
||||
|
||||
#include <libavutil/timestamp.h>
|
||||
@@ -21,12 +21,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file audio resampling API usage example
|
||||
* @example resample_audio.c
|
||||
*
|
||||
* Generate a synthetic audio signal, and Use libswresample API to perform audio
|
||||
* resampling. The output is written to a raw audio file to be played with
|
||||
* ffplay.
|
||||
* @example resampling_audio.c
|
||||
* libswresample API use example.
|
||||
*/
|
||||
|
||||
#include <libavutil/opt.h>
|
||||
@@ -21,10 +21,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libswscale API usage example
|
||||
* @example scale_video.c
|
||||
*
|
||||
* Generate a synthetic video signal and use libswscale to perform rescaling.
|
||||
* @file
|
||||
* libswscale API use example.
|
||||
* @example scaling_video.c
|
||||
*/
|
||||
|
||||
#include <libavutil/imgutils.h>
|
||||
@@ -19,11 +19,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file audio transcoding to MPEG/AAC API usage example
|
||||
* @example transcode_aac.c
|
||||
* @file
|
||||
* Simple audio converter
|
||||
*
|
||||
* Convert an input audio file to AAC in an MP4 container. Formats other than
|
||||
* MP4 are supported based on the output file extension.
|
||||
* @example transcode_aac.c
|
||||
* Convert an input audio file to AAC in an MP4 container using FFmpeg.
|
||||
* Formats other than MP4 are supported based on the output file extension.
|
||||
* @author Andreas Unterweger (dustsigns@gmail.com)
|
||||
*/
|
||||
|
||||
@@ -447,17 +448,26 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
|
||||
int error;
|
||||
|
||||
/* Allocate as many pointers as there are audio channels.
|
||||
* Each pointer will point to the audio samples of the corresponding
|
||||
* Each pointer will later point to the audio samples of the corresponding
|
||||
* 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. */
|
||||
if ((error = av_samples_alloc_array_and_samples(converted_input_samples, NULL,
|
||||
if ((error = av_samples_alloc(*converted_input_samples, NULL,
|
||||
output_codec_context->ch_layout.nb_channels,
|
||||
frame_size,
|
||||
output_codec_context->sample_fmt, 0)) < 0) {
|
||||
fprintf(stderr,
|
||||
"Could not allocate converted input samples (error '%s')\n",
|
||||
av_err2str(error));
|
||||
av_freep(&(*converted_input_samples)[0]);
|
||||
free(*converted_input_samples);
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
@@ -589,9 +599,10 @@ static int read_decode_convert_and_store(AVAudioFifo *fifo,
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (converted_input_samples)
|
||||
if (converted_input_samples) {
|
||||
av_freep(&converted_input_samples[0]);
|
||||
av_freep(&converted_input_samples);
|
||||
free(converted_input_samples);
|
||||
}
|
||||
av_frame_free(&input_frame);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -23,11 +23,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file demuxing, decoding, filtering, encoding and muxing API usage example
|
||||
* @example transcode.c
|
||||
*
|
||||
* Convert input to output file, applying some hard-coded filter-graph on both
|
||||
* audio and video streams.
|
||||
* @file
|
||||
* API example for demuxing, decoding, filtering, encoding and muxing
|
||||
* @example transcoding.c
|
||||
*/
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
@@ -97,11 +95,6 @@ static int open_input_file(const char *filename)
|
||||
"for stream #%u\n", i);
|
||||
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. */
|
||||
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
|
||||
|| codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
@@ -271,7 +264,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
|
||||
snprintf(args, sizeof(args),
|
||||
"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->pkt_timebase.num, dec_ctx->pkt_timebase.den,
|
||||
dec_ctx->time_base.num, dec_ctx->time_base.den,
|
||||
dec_ctx->sample_aspect_ratio.num,
|
||||
dec_ctx->sample_aspect_ratio.den);
|
||||
|
||||
@@ -311,7 +304,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
|
||||
av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf));
|
||||
snprintf(args, sizeof(args),
|
||||
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s",
|
||||
dec_ctx->pkt_timebase.num, dec_ctx->pkt_timebase.den, dec_ctx->sample_rate,
|
||||
dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
|
||||
av_get_sample_fmt_name(dec_ctx->sample_fmt),
|
||||
buf);
|
||||
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
|
||||
@@ -441,10 +434,6 @@ static int encode_write_frame(unsigned int stream_index, int flush)
|
||||
/* encode filtered frame */
|
||||
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);
|
||||
|
||||
if (ret < 0)
|
||||
@@ -499,7 +488,6 @@ static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
|
||||
break;
|
||||
}
|
||||
|
||||
filter->filtered_frame->time_base = av_buffersink_get_time_base(filter->buffersink_ctx);;
|
||||
filter->filtered_frame->pict_type = AV_PICTURE_TYPE_NONE;
|
||||
ret = encode_write_frame(stream_index, 0);
|
||||
av_frame_unref(filter->filtered_frame);
|
||||
@@ -554,6 +542,9 @@ int main(int argc, char **argv)
|
||||
|
||||
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);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
|
||||
@@ -585,38 +576,11 @@ int main(int argc, char **argv)
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
|
||||
/* flush decoders, filters and encoders */
|
||||
/* flush filters and encoders */
|
||||
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
|
||||
StreamContext *stream;
|
||||
|
||||
/* flush filter */
|
||||
if (!filter_ctx[i].filter_graph)
|
||||
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);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
|
||||
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
* Video Acceleration API (video encoding) encode sample
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
@@ -19,12 +21,13 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Intel VAAPI-accelerated encoding API usage example
|
||||
* @example vaapi_encode.c
|
||||
* @file
|
||||
* Intel VAAPI-accelerated encoding example.
|
||||
*
|
||||
* @example vaapi_encode.c
|
||||
* This example shows how to do VAAPI-accelerated encoding. now only support NV12
|
||||
* raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264
|
||||
*
|
||||
* Perform VAAPI-accelerated encoding. Read input from an NV12 raw
|
||||
* file, and write the H.264 encoded data to an output raw file.
|
||||
* Usage: vaapi_encode 1920 1080 input.yuv output.h264
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -88,10 +91,6 @@ static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout)
|
||||
enc_pkt->stream_index = 0;
|
||||
ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout);
|
||||
av_packet_unref(enc_pkt);
|
||||
if (ret != enc_pkt->size) {
|
||||
ret = AVERROR(errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
* Video Acceleration API (video transcoding) transcode sample
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
@@ -19,10 +21,11 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Intel VAAPI-accelerated transcoding API usage example
|
||||
* @example vaapi_transcode.c
|
||||
* @file
|
||||
* Intel VAAPI-accelerated transcoding example.
|
||||
*
|
||||
* Perform VAAPI-accelerated transcoding.
|
||||
* @example vaapi_transcode.c
|
||||
* This example shows how to do VAAPI-accelerated transcoding.
|
||||
* Usage: vaapi_transcode input_stream codec output_stream
|
||||
* e.g: - vaapi_transcode input.mp4 h264_vaapi output_h264.mp4
|
||||
* - vaapi_transcode input.mp4 vp9_vaapi output_vp9.ivf
|
||||
@@ -215,8 +218,10 @@ static int dec_enc(AVPacket *pkt, const AVCodec *enc_codec)
|
||||
|
||||
fail:
|
||||
av_frame_free(&frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
@@ -223,14 +223,6 @@ meaning only while running the regression tests.
|
||||
Specify how many threads to use while running regression tests, it is
|
||||
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
|
||||
Specify which threading strategy test, either @samp{slice} or @samp{frame},
|
||||
by default @samp{slice+frame}
|
||||
|
||||
480
doc/ffmpeg.texi
480
doc/ffmpeg.texi
@@ -17,9 +17,9 @@ ffmpeg [@var{global_options}] @{[@var{input_file_options}] -i @file{input_url}@}
|
||||
@chapter Description
|
||||
@c man begin DESCRIPTION
|
||||
|
||||
@command{ffmpeg} is a universal media converter. It can read a wide variety of
|
||||
inputs - including live grabbing/recording devices - filter, and transcode them
|
||||
into a plethora of output formats.
|
||||
@command{ffmpeg} is a very fast video and audio converter that can also grab from
|
||||
a live audio/video source. It can also convert between arbitrary sample
|
||||
rates and resize video on the fly with a high quality polyphase filter.
|
||||
|
||||
@command{ffmpeg} reads from an arbitrary number of input "files" (which can be regular
|
||||
files, pipes, network streams, grabbing devices, etc.), specified by the
|
||||
@@ -49,32 +49,24 @@ 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
|
||||
options apply ONLY to the next input or output file and are reset between files.
|
||||
|
||||
Some simple examples follow.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Convert an input media file to a different format, by re-encoding media streams:
|
||||
To set the video bitrate of the output file to 64 kbit/s:
|
||||
@example
|
||||
ffmpeg -i input.avi output.mp4
|
||||
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi
|
||||
@end example
|
||||
|
||||
@item
|
||||
Set the video bitrate of the output file to 64 kbit/s:
|
||||
To force the frame rate of the output file to 24 fps:
|
||||
@example
|
||||
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4
|
||||
ffmpeg -i input.avi -r 24 output.avi
|
||||
@end example
|
||||
|
||||
@item
|
||||
Force the frame rate of the output file to 24 fps:
|
||||
To 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 -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
|
||||
ffmpeg -r 1 -i input.m2v -r 24 output.avi
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
@@ -777,7 +769,6 @@ syntax.
|
||||
See the @ref{filter_complex_option,,-filter_complex option} if you
|
||||
want to create filtergraphs with multiple inputs and/or outputs.
|
||||
|
||||
@anchor{filter_script option}
|
||||
@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
|
||||
@@ -886,20 +877,9 @@ This is not the same as the @option{-framerate} option used for some input forma
|
||||
like image2 or v4l2 (it used to be the same in older versions of FFmpeg).
|
||||
If in doubt use @option{-framerate} instead of the input option @option{-r}.
|
||||
|
||||
As an output option:
|
||||
@table @option
|
||||
@item video encoding
|
||||
Duplicate or drop frames right before encoding them to achieve constant output
|
||||
As an output option, duplicate or drop input frames to achieve constant output
|
||||
frame rate @var{fps}.
|
||||
|
||||
@item video streamcopy
|
||||
Indicate to the muxer that @var{fps} is the stream frame rate. No data is
|
||||
dropped or duplicated in this case. This may produce invalid files if @var{fps}
|
||||
does not match the actual stream frame rate as determined by packet timestamps.
|
||||
See also the @code{setts} bitstream filter.
|
||||
|
||||
@end table
|
||||
|
||||
@item -fpsmax[:@var{stream_specifier}] @var{fps} (@emph{output,per-stream})
|
||||
Set maximum frame rate (Hz value, fraction or abbreviation).
|
||||
|
||||
@@ -932,32 +912,6 @@ If used together with @option{-vcodec copy}, it will affect the aspect ratio
|
||||
stored at container level, but not the aspect ratio stored in encoded
|
||||
frames, if it exists.
|
||||
|
||||
@item -display_rotation[:@var{stream_specifier}] @var{rotation} (@emph{input,per-stream})
|
||||
Set video rotation metadata.
|
||||
|
||||
@var{rotation} is a decimal number specifying the amount in degree by
|
||||
which the video should be rotated counter-clockwise before being
|
||||
displayed.
|
||||
|
||||
This option overrides the rotation/display transform metadata stored in
|
||||
the file, if any. When the video is being transcoded (rather than
|
||||
copied) and @code{-autorotate} is enabled, the video will be rotated at
|
||||
the filtering stage. Otherwise, the metadata will be written into the
|
||||
output file if the muxer supports it.
|
||||
|
||||
If the @code{-display_hflip} and/or @code{-display_vflip} options are
|
||||
given, they are applied after the rotation specified by this option.
|
||||
|
||||
@item -display_hflip[:@var{stream_specifier}] (@emph{input,per-stream})
|
||||
Set whether on display the image should be horizontally flipped.
|
||||
|
||||
See the @code{-display_rotation} option for more details.
|
||||
|
||||
@item -display_vflip[:@var{stream_specifier}] (@emph{input,per-stream})
|
||||
Set whether on display the image should be vertically flipped.
|
||||
|
||||
See the @code{-display_rotation} option for more details.
|
||||
|
||||
@item -vn (@emph{input/output})
|
||||
As an input option, blocks all video streams of a file from being filtered or
|
||||
being automatically selected or mapped for any output. See @code{-discard}
|
||||
@@ -1023,12 +977,7 @@ 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.
|
||||
|
||||
@item -sws_flags @var{flags} (@emph{input/output})
|
||||
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.
|
||||
Set SwScaler flags.
|
||||
|
||||
@item -rc_override[:@var{stream_specifier}] @var{override} (@emph{output,per-stream})
|
||||
Rate control override for specific intervals, formatted as "int,int,int"
|
||||
@@ -1036,30 +985,43 @@ list separated with slashes. Two first values are the beginning and
|
||||
end frame numbers, last one is quantizer to use if positive, or quality
|
||||
factor if negative.
|
||||
|
||||
@item -ilme
|
||||
Force interlacing support in encoder (MPEG-2 and MPEG-4 only).
|
||||
Use this option if your input file is interlaced and you want
|
||||
to keep the interlaced format for minimum losses.
|
||||
The alternative is to deinterlace the input stream by use of a filter
|
||||
such as @code{yadif} or @code{bwdif}, but deinterlacing introduces losses.
|
||||
@item -psnr
|
||||
Calculate PSNR of compressed frames. This option is deprecated, pass the
|
||||
PSNR flag to the encoder instead, using @code{-flags +psnr}.
|
||||
|
||||
Calculate PSNR of compressed frames.
|
||||
@item -vstats
|
||||
Dump video coding statistics to @file{vstats_HHMMSS.log}. See the
|
||||
@ref{vstats_file_format,,vstats file format} section for the format description.
|
||||
|
||||
Dump video coding statistics to @file{vstats_HHMMSS.log}.
|
||||
@item -vstats_file @var{file}
|
||||
Dump video coding statistics to @var{file}. See the
|
||||
@ref{vstats_file_format,,vstats file format} section for the format description.
|
||||
|
||||
Dump video coding statistics to @var{file}.
|
||||
@item -vstats_version @var{file}
|
||||
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.
|
||||
Specifies which version of the vstats format to use. Default is 2.
|
||||
|
||||
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 -dc @var{precision}
|
||||
Intra_dc_precision.
|
||||
@item -vtag @var{fourcc/tag} (@emph{output})
|
||||
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}] 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_no_drop (@emph{output,per-stream})
|
||||
|
||||
@var{force_key_frames} can take arguments of the following form:
|
||||
|
||||
@@ -1120,6 +1082,10 @@ starting from second 13:
|
||||
@item source
|
||||
If the argument is @code{source}, ffmpeg will force a key frame if
|
||||
the current frame being encoded is marked as a key frame in its source.
|
||||
|
||||
@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,
|
||||
enforce the next available frame to become a key frame instead.
|
||||
|
||||
@@ -1167,10 +1133,9 @@ Choose the first device and use the primary device context.
|
||||
@var{device} is the number of the Direct3D 11 display adapter.
|
||||
|
||||
@item vaapi
|
||||
@var{device} is either an X11 display name, a DRM render node or a DirectX adapter index.
|
||||
@var{device} is either an X11 display name or a DRM render node.
|
||||
If not specified, it will attempt to open the default X11 display (@emph{$DISPLAY})
|
||||
and then the first DRM render node (@emph{/dev/dri/renderD128}), or the default
|
||||
DirectX adapter on Windows.
|
||||
and then the first DRM render node (@emph{/dev/dri/renderD128}).
|
||||
|
||||
@item vdpau
|
||||
@var{device} is an X11 display name.
|
||||
@@ -1347,22 +1312,6 @@ List all hardware acceleration components enabled in this build of ffmpeg.
|
||||
Actual runtime availability depends on the hardware and its suitable driver
|
||||
being installed.
|
||||
|
||||
@item -fix_sub_duration_heartbeat[:@var{stream_specifier}]
|
||||
Set a specific output video stream as the heartbeat stream according to which
|
||||
to split and push through currently in-progress subtitle upon receipt of a
|
||||
random access packet.
|
||||
|
||||
This lowers the latency of subtitles for which the end packet or the following
|
||||
subtitle has not yet been received. As a drawback, this will most likely lead
|
||||
to duplication of subtitle events in order to cover the full duration, so
|
||||
when dealing with use cases where latency of when the subtitle event is passed
|
||||
on to output is not relevant this option should not be utilized.
|
||||
|
||||
Requires @option{-fix_sub_duration} to be set for the relevant input subtitle
|
||||
stream for this to have any effect, as well as for the input subtitle stream
|
||||
having to be directly mapped to the same output in which the heartbeat stream
|
||||
resides.
|
||||
|
||||
@end table
|
||||
|
||||
@section Audio Options
|
||||
@@ -1461,18 +1410,18 @@ Set the size of the canvas used to render subtitles.
|
||||
@section Advanced options
|
||||
|
||||
@table @option
|
||||
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][?] | @var{[linklabel]} (@emph{output})
|
||||
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][?][,@var{sync_file_id}[:@var{stream_specifier}]] | @var{[linklabel]} (@emph{output})
|
||||
|
||||
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
|
||||
input file (specified with @code{-i}), the second takes an output from some
|
||||
complex filtergraph (specified with @code{-filter_complex} or
|
||||
@code{-filter_complex_script}).
|
||||
Designate one or more input streams as a source for the output file. Each input
|
||||
stream is identified by the input file index @var{input_file_id} and
|
||||
the input stream index @var{input_stream_id} within the input
|
||||
file. Both indices start at 0. If specified,
|
||||
@var{sync_file_id}:@var{stream_specifier} sets which input stream
|
||||
is used as a presentation sync reference.
|
||||
|
||||
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,
|
||||
only those streams that match the specifier are used (see the
|
||||
@ref{Stream specifiers} section for the @var{stream_specifier} syntax).
|
||||
The first @code{-map} option on the command line specifies the
|
||||
source for output stream 0, the second @code{-map} option specifies
|
||||
the source for output stream 1, etc.
|
||||
|
||||
A @code{-} character before the stream identifier creates a "negative" mapping.
|
||||
It disables matching streams from already created mappings.
|
||||
@@ -1486,56 +1435,39 @@ An alternative @var{[linklabel]} form will map outputs from complex filter
|
||||
graphs (see the @option{-filter_complex} option) to the output file.
|
||||
@var{linklabel} must correspond to a defined output link label in the graph.
|
||||
|
||||
This option may be specified multiple times, each adding more streams to the
|
||||
output file. Any given input stream may also be mapped any number of times as a
|
||||
source for different output streams, e.g. in order to use different encoding
|
||||
options and/or filters. The streams are created in the output in the same order
|
||||
in which the @code{-map} options are given on the commandline.
|
||||
|
||||
Using this option disables the default mappings for this output file.
|
||||
|
||||
Examples:
|
||||
|
||||
@table @emph
|
||||
|
||||
@item map everything
|
||||
To map ALL streams from the first input file to output
|
||||
For example, to map ALL streams from the first input file to output
|
||||
@example
|
||||
ffmpeg -i INPUT -map 0 output
|
||||
@end example
|
||||
|
||||
@item select specific stream
|
||||
If you have two audio streams in the first input file, these streams are
|
||||
identified by @var{0:0} and @var{0:1}. You can use @code{-map} to select which
|
||||
streams to place in an output file. For example:
|
||||
For example, if you have two audio streams in the first input file,
|
||||
these streams are identified by "0:0" and "0:1". You can use
|
||||
@code{-map} to select which streams to place in an output file. For
|
||||
example:
|
||||
@example
|
||||
ffmpeg -i INPUT -map 0:1 out.wav
|
||||
@end example
|
||||
will map the second input stream in @file{INPUT} to the (single) output stream
|
||||
in @file{out.wav}.
|
||||
will map the input stream in @file{INPUT} identified by "0:1" to
|
||||
the (single) output stream in @file{out.wav}.
|
||||
|
||||
@item create multiple streams
|
||||
To select the stream with index 2 from input file @file{a.mov} (specified by the
|
||||
identifier @var{0:2}), and stream with index 6 from input @file{b.mov}
|
||||
(specified by the identifier @var{1:6}), and copy them to the output file
|
||||
@file{out.mov}:
|
||||
For example, to select the stream with index 2 from input file
|
||||
@file{a.mov} (specified by the identifier "0:2"), and stream with
|
||||
index 6 from input @file{b.mov} (specified by the identifier "1:6"),
|
||||
and copy them to the output file @file{out.mov}:
|
||||
@example
|
||||
ffmpeg -i a.mov -i b.mov -c copy -map 0:2 -map 1:6 out.mov
|
||||
@end example
|
||||
|
||||
@item create multiple streams 2
|
||||
To select all video and the third audio stream from an input file:
|
||||
@example
|
||||
ffmpeg -i INPUT -map 0:v -map 0:a:2 OUTPUT
|
||||
@end example
|
||||
|
||||
@item negative map
|
||||
To map all the streams except the second audio, use negative mappings
|
||||
@example
|
||||
ffmpeg -i INPUT -map 0 -map -0:a:1 OUTPUT
|
||||
@end example
|
||||
|
||||
@item optional map
|
||||
To map the video and audio streams from the first input, and using the
|
||||
trailing @code{?}, ignore the audio mapping if no audio streams exist in
|
||||
the first input:
|
||||
@@ -1543,13 +1475,12 @@ the first input:
|
||||
ffmpeg -i INPUT -map 0:v -map 0:a? OUTPUT
|
||||
@end example
|
||||
|
||||
@item map by language
|
||||
To pick the English audio stream:
|
||||
@example
|
||||
ffmpeg -i INPUT -map 0:m:language:eng OUTPUT
|
||||
@end example
|
||||
|
||||
@end table
|
||||
Note that using this option disables the default mappings for this output file.
|
||||
|
||||
@item -ignore_unknown
|
||||
Ignore input streams with unknown type instead of failing if copying
|
||||
@@ -1560,10 +1491,6 @@ Allow input streams with unknown type to be copied instead of failing if copying
|
||||
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.
|
||||
@@ -1706,9 +1633,6 @@ it may cause packet loss.
|
||||
It is useful for when flow speed of output packets is important, such as live streaming.
|
||||
@item -re (@emph{input})
|
||||
Read input at native frame rate. This is equivalent to setting @code{-readrate 1}.
|
||||
@item -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})
|
||||
@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
|
||||
@@ -1750,6 +1674,24 @@ 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
|
||||
timestamps.
|
||||
|
||||
@item -async @var{samples_per_second}
|
||||
Audio sync method. "Stretches/squeezes" the audio stream to match the timestamps,
|
||||
the parameter is the maximum samples per second by which the audio is changed.
|
||||
-async 1 is a special case where only the start of the audio stream is corrected
|
||||
without any later correction.
|
||||
|
||||
Note that the timestamps may be further modified by the muxer, after this.
|
||||
For example, in the case that the format option @option{avoid_negative_ts}
|
||||
is enabled.
|
||||
|
||||
This option has been deprecated. Use the @code{aresample} audio filter instead.
|
||||
|
||||
@item -adrift_threshold @var{time}
|
||||
Set the minimum difference between timestamps and audio data (in seconds) to trigger
|
||||
adding/dropping samples to make it match the timestamps. This option effectively is
|
||||
a threshold to select between hard (add/drop) and soft (squeeze/stretch) compensation.
|
||||
@code{-async} must be set to a positive value.
|
||||
|
||||
@item -apad @var{parameters} (@emph{output,per-stream})
|
||||
Pad the output audio stream(s). This is the same as applying @code{-af apad}.
|
||||
Argument is a string of filter parameters composed the same as with the @code{apad} filter.
|
||||
@@ -1796,7 +1738,8 @@ Try to make the choice automatically, in order to generate a sane output.
|
||||
Default value is -1.
|
||||
|
||||
@item -enc_time_base[:@var{stream_specifier}] @var{timebase} (@emph{output,per-stream})
|
||||
Set the encoder timebase. @var{timebase} can assume one of the following values:
|
||||
Set the encoder timebase. @var{timebase} is a floating point number,
|
||||
and can assume one of the following values:
|
||||
|
||||
@table @option
|
||||
@item 0
|
||||
@@ -1804,17 +1747,16 @@ Assign a default value according to the media type.
|
||||
|
||||
For video - use 1/framerate, for audio - use 1/samplerate.
|
||||
|
||||
@item demux
|
||||
Use the timebase from the demuxer.
|
||||
@item -1
|
||||
Use the input stream timebase when possible.
|
||||
|
||||
@item filter
|
||||
Use the timebase from the filtergraph.
|
||||
If an input stream is not available, the default timebase will be used.
|
||||
|
||||
@item a positive number
|
||||
@item >0
|
||||
Use the provided number as the timebase.
|
||||
|
||||
This field can be provided as a ratio of two integers (e.g. 1:24, 1:48000)
|
||||
or as a decimal number (e.g. 0.04166, 2.0833e-5)
|
||||
or as a floating point number (e.g. 0.04166, 2.0833e-5)
|
||||
@end table
|
||||
|
||||
Default value is 0.
|
||||
@@ -1823,54 +1765,12 @@ Default value is 0.
|
||||
Enable bitexact mode for (de)muxer and (de/en)coder
|
||||
@item -shortest (@emph{output})
|
||||
Finish encoding when the shortest output stream ends.
|
||||
|
||||
Note that this option may require buffering frames, which introduces extra
|
||||
latency. The maximum amount of this latency may be controlled with the
|
||||
@code{-shortest_buf_duration} option.
|
||||
|
||||
@item -shortest_buf_duration @var{duration} (@emph{output})
|
||||
The @code{-shortest} option may require buffering potentially large amounts
|
||||
of data when at least one of the streams is "sparse" (i.e. has large gaps
|
||||
between frames – this is typically the case for subtitles).
|
||||
|
||||
This option controls the maximum duration of buffered frames in seconds.
|
||||
Larger values may allow the @code{-shortest} option to produce more accurate
|
||||
results, but increase memory use and latency.
|
||||
|
||||
The default value is 10 seconds.
|
||||
|
||||
@item -dts_delta_threshold @var{threshold}
|
||||
Timestamp discontinuity delta threshold, expressed as a decimal number
|
||||
of seconds.
|
||||
|
||||
The timestamp discontinuity correction enabled by this option is only
|
||||
applied to input formats accepting timestamp discontinuity (for which
|
||||
the @code{AV_FMT_DISCONT} flag is enabled), e.g. MPEG-TS and HLS, and
|
||||
is automatically disabled when employing the @code{-copy_ts} 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{AV_FMT_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 -dts_delta_threshold
|
||||
Timestamp discontinuity delta threshold.
|
||||
@item -dts_error_threshold @var{seconds}
|
||||
Timestamp error delta threshold. This threshold use to discard crazy/damaged
|
||||
timestamps and the default is 30 hours which is arbitrarily picked and quite
|
||||
conservative.
|
||||
@item -muxdelay @var{seconds} (@emph{output})
|
||||
Set the maximum demux-decode delay.
|
||||
@item -muxpreload @var{seconds} (@emph{output})
|
||||
@@ -1981,7 +1881,6 @@ The default is the number of available CPUs.
|
||||
Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or
|
||||
outputs. Equivalent to @option{-filter_complex}.
|
||||
|
||||
@anchor{filter_complex_script option}
|
||||
@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
|
||||
@@ -2000,16 +1899,13 @@ to the @option{-ss} option is considered an actual timestamp, and is not
|
||||
offset by the start time of the file. This matters only for files which do
|
||||
not start from timestamp 0, such as transport streams.
|
||||
|
||||
@item -thread_queue_size @var{size} (@emph{input/output})
|
||||
For input, this option sets the maximum number of queued packets when reading
|
||||
from the file or device. With low latency / high rate live streams, packets may
|
||||
be discarded if they are not read in a timely manner; setting this value can
|
||||
@item -thread_queue_size @var{size} (@emph{input})
|
||||
This option sets the maximum number of queued packets when reading from the
|
||||
file or device. With low latency / high rate live streams, packets may be
|
||||
discarded if they are not read in a timely manner; setting this value can
|
||||
force ffmpeg to use a separate input thread and read packets as soon as they
|
||||
arrive. By default ffmpeg only does this if multiple inputs are specified.
|
||||
|
||||
For output, this option specified the maximum number of packets that may be
|
||||
queued to each muxing thread.
|
||||
|
||||
@item -sdp_file @var{file} (@emph{global})
|
||||
Print sdp information for an output stream to @var{file}.
|
||||
This allows dumping sdp information when at least one output isn't an
|
||||
@@ -2090,125 +1986,6 @@ encoder/muxer, it does not change the stream to conform to this value. Setting
|
||||
values that do not match the stream properties may result in encoding failures
|
||||
or invalid output files.
|
||||
|
||||
@anchor{stats_enc_options}
|
||||
@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_mux_pre[:@var{stream_specifier}] @var{path} (@emph{output,per-stream})
|
||||
Write per-frame encoding information about the matching streams into the file
|
||||
given by @var{path}.
|
||||
|
||||
@option{-stats_enc_pre} writes information about raw video or audio frames right
|
||||
before they are sent for encoding, while @option{-stats_enc_post} writes
|
||||
information about encoded packets as they are received from the encoder.
|
||||
@option{-stats_mux_pre} writes information about packets just as they are about to
|
||||
be sent to the muxer. Every frame or packet produces one line in the specified
|
||||
file. The format of this line is controlled by @option{-stats_enc_pre_fmt} /
|
||||
@option{-stats_enc_post_fmt} / @option{-stats_mux_pre_fmt}.
|
||||
|
||||
When stats for multiple streams are written into a single file, the lines
|
||||
corresponding to different streams will be interleaved. The precise order of
|
||||
this interleaving is not specified and not guaranteed to remain stable between
|
||||
different invocations of the program, even with the same options.
|
||||
|
||||
@item -stats_enc_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||
@item -stats_enc_post_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||
@item -stats_mux_pre_fmt[:@var{stream_specifier}] @var{format_spec} (@emph{output,per-stream})
|
||||
Specify the format for the lines written with @option{-stats_enc_pre} /
|
||||
@option{-stats_enc_post} / @option{-stats_mux_pre}.
|
||||
|
||||
@var{format_spec} is a string that may contain directives of the form
|
||||
@var{@{fmt@}}. @var{format_spec} is backslash-escaped --- use \@{, \@}, and \\
|
||||
to write a literal @{, @}, or \, respectively, into the output.
|
||||
|
||||
The directives given with @var{fmt} may be one of the following:
|
||||
@table @option
|
||||
@item fidx
|
||||
Index of the output file.
|
||||
|
||||
@item sidx
|
||||
Index of the output stream in the file.
|
||||
|
||||
@item n
|
||||
Frame number. Pre-encoding: number of frames sent to the encoder so far.
|
||||
Post-encoding: number of packets received from the encoder so far.
|
||||
Muxing: number of packets submitted to the muxer for this stream so far.
|
||||
|
||||
@item ni
|
||||
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.
|
||||
|
||||
@item tb
|
||||
Timebase in which this frame/packet's timestamps are expressed, as a rational
|
||||
number @var{num/den}. Note that encoder and muxer may use different timebases.
|
||||
|
||||
@item tbi
|
||||
Timebase for @var{ptsi}, as a rational number @var{num/den}. Available when
|
||||
@var{ptsi} is available, @var{0/1} otherwise.
|
||||
|
||||
@item pts
|
||||
Presentation timestamp of the frame or packet, as an integer. Should be
|
||||
multiplied by the timebase to compute presentation time.
|
||||
|
||||
@item ptsi
|
||||
Presentation timestamp of the input frame (see @var{ni}), as an integer. Should
|
||||
be multiplied by @var{tbi} to compute presentation time. Printed as
|
||||
(2^63 - 1 = 9223372036854775807) when not available.
|
||||
|
||||
@item t
|
||||
Presentation time of the frame or packet, as a decimal number. Equal to
|
||||
@var{pts} multiplied by @var{tb}.
|
||||
|
||||
@item ti
|
||||
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.
|
||||
|
||||
@item dts (@emph{packet})
|
||||
Decoding timestamp of the packet, as an integer. Should be multiplied by the
|
||||
timebase to compute presentation time.
|
||||
|
||||
@item dt (@emph{packet})
|
||||
Decoding time of the frame or packet, as a decimal number. Equal to
|
||||
@var{dts} multiplied by @var{tb}.
|
||||
|
||||
@item sn (@emph{frame,audio})
|
||||
Number of audio samples sent to the encoder so far.
|
||||
|
||||
@item samp (@emph{frame,audio})
|
||||
Number of audio samples in the frame.
|
||||
|
||||
@item size (@emph{packet})
|
||||
Size of the encoded packet in bytes.
|
||||
|
||||
@item br (@emph{packet})
|
||||
Current bitrate in bits per second. Post-encoding only.
|
||||
|
||||
@item abr (@emph{packet})
|
||||
Average bitrate for the whole stream so far, in bits per second, -1 if it cannot
|
||||
be determined at this point. Post-encoding only.
|
||||
@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:
|
||||
@table @option
|
||||
@item pre-encoding
|
||||
@{fidx@} @{sidx@} @{n@} @{t@}
|
||||
@item post-encoding
|
||||
@{fidx@} @{sidx@} @{n@} @{t@}
|
||||
@end table
|
||||
In the future, new items may be added to the end of the default formatting
|
||||
strings. Users who depend on the format staying exactly the same, should
|
||||
prescribe it manually.
|
||||
|
||||
Note that stats for different streams written into the same file may have
|
||||
different formats.
|
||||
|
||||
@end table
|
||||
|
||||
@section Preset files
|
||||
@@ -2266,63 +2043,6 @@ search for the file @file{libvpx-1080p.avpreset}.
|
||||
If no such file is found, then ffmpeg will search for a file named
|
||||
@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
|
||||
|
||||
@chapter Examples
|
||||
@@ -2586,7 +2306,7 @@ ffmpeg-devices(1), ffmpeg-protocols(1), ffmpeg-filters(1)
|
||||
@ignore
|
||||
|
||||
@setfilename ffmpeg
|
||||
@settitle ffmpeg media converter
|
||||
@settitle ffmpeg video converter
|
||||
|
||||
@end ignore
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ ffprobe will show it.
|
||||
|
||||
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
|
||||
writer, which is specified by the @option{output_format} option.
|
||||
writer, which is specified by the @option{print_format} option.
|
||||
|
||||
Sections may contain other nested sections, and are identified by a
|
||||
name (which may be shared by other sections), and an unique
|
||||
@@ -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
|
||||
options "-unit -prefix -byte_binary_prefix -sexagesimal".
|
||||
|
||||
@item -output_format, -of, -print_format @var{writer_name}[=@var{writer_options}]
|
||||
@item -of, -print_format @var{writer_name}[=@var{writer_options}]
|
||||
Set the output printing format.
|
||||
|
||||
@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:
|
||||
@example
|
||||
-output_format json
|
||||
-print_format json
|
||||
@end example
|
||||
|
||||
For more details on the available output printing formats, see the
|
||||
|
||||
699
doc/ffprobe.xsd
699
doc/ffprobe.xsd
@@ -1,409 +1,386 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://www.ffmpeg.org/schema/ffprobe"
|
||||
xmlns:ffprobe="http://www.ffmpeg.org/schema/ffprobe">
|
||||
targetNamespace="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:sequence>
|
||||
<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="pixel_formats" type="ffprobe:pixelFormatsType" 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="packets_and_frames" type="ffprobe:packetsAndFramesType" 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="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="ffprobeType">
|
||||
<xsd:sequence>
|
||||
<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="pixel_formats" type="ffprobe:pixelFormatsType" 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="packets_and_frames" type="ffprobe:packetsAndFramesType" 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="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="packetsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="packet" type="ffprobe:packetType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="packetsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="packet" type="ffprobe:packetType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="framesType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="frame" type="ffprobe:frameType"/>
|
||||
<xsd:element name="subtitle" type="ffprobe:subtitleType"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="framesType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="frame" type="ffprobe:frameType"/>
|
||||
<xsd:element name="subtitle" type="ffprobe:subtitleType"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="packetsAndFramesType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="packet" type="ffprobe:packetType"/>
|
||||
<xsd:element name="frame" type="ffprobe:frameType"/>
|
||||
<xsd:element name="subtitle" type="ffprobe:subtitleType"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="packetsAndFramesType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="packet" type="ffprobe:packetType"/>
|
||||
<xsd:element name="frame" type="ffprobe:frameType"/>
|
||||
<xsd:element name="subtitle" type="ffprobe:subtitleType"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="tagsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="packetType">
|
||||
<xsd:sequence>
|
||||
<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:complexType name="packetType">
|
||||
<xsd:sequence>
|
||||
<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:attribute name="codec_type" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="stream_index" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<xsd:attribute name="pts_time" type="xsd:float" />
|
||||
<xsd:attribute name="dts" type="xsd:long" />
|
||||
<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:attribute name="codec_type" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="stream_index" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<xsd:attribute name="pts_time" type="xsd:float" />
|
||||
<xsd:attribute name="dts" type="xsd:long" />
|
||||
<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:sequence>
|
||||
<xsd:element name="side_data" type="ffprobe:packetSideDataType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="packetSideDataType">
|
||||
<xsd:attribute name="side_data_type" type="xsd:string"/>
|
||||
<xsd:attribute name="side_data_size" type="xsd:int" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="packetSideDataListType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="side_data" type="ffprobe:packetSideDataType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="frameType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element name="logs" type="ffprobe:logsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="side_data_list" type="ffprobe:frameSideDataListType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:complexType name="packetSideDataType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="side_datum" type="ffprobe:packetSideDatumType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="media_type" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="stream_index" type="xsd:int" />
|
||||
<xsd:attribute name="key_frame" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<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="pkt_pos" type="xsd:long" />
|
||||
<xsd:attribute name="pkt_size" type="xsd:int" />
|
||||
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
<!-- audio attributes -->
|
||||
<xsd:attribute name="sample_fmt" type="xsd:string"/>
|
||||
<xsd:attribute name="nb_samples" type="xsd:long" />
|
||||
<xsd:attribute name="channels" type="xsd:int" />
|
||||
<xsd:attribute name="channel_layout" type="xsd:string"/>
|
||||
|
||||
<xsd:complexType name="packetSideDatumType">
|
||||
<xsd:attribute name="key" type="xsd:string"/>
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
<!-- video attributes -->
|
||||
<xsd:attribute name="width" type="xsd:long" />
|
||||
<xsd:attribute name="height" 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="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="frameType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="logs" type="ffprobe:logsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="side_data_list" type="ffprobe:frameSideDataListType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:complexType name="logsType">
|
||||
<xsd:sequence>
|
||||
<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:attribute name="media_type" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="stream_index" type="xsd:int" />
|
||||
<xsd:attribute name="key_frame" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<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" />
|
||||
<xsd:complexType name="frameSideDataListType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="side_data" type="ffprobe:frameSideDataType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="frameSideDataType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecodes" type="ffprobe:frameSideDataTimecodeList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<!-- audio attributes -->
|
||||
<xsd:attribute name="sample_fmt" type="xsd:string"/>
|
||||
<xsd:attribute name="nb_samples" type="xsd:long" />
|
||||
<xsd:attribute name="channels" type="xsd:int" />
|
||||
<xsd:attribute name="channel_layout" type="xsd:string"/>
|
||||
<xsd:attribute name="side_data_type" type="xsd:string"/>
|
||||
<xsd:attribute name="side_data_size" type="xsd:int" />
|
||||
<xsd:attribute name="timecode" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- video attributes -->
|
||||
<xsd:attribute name="width" type="xsd:long" />
|
||||
<xsd:attribute name="height" type="xsd:long" />
|
||||
<xsd:attribute name="crop_top" type="xsd:long" />
|
||||
<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="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="frameSideDataTimecodeList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecode" type="ffprobe:frameSideDataTimecodeType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="logsType">
|
||||
<xsd:sequence>
|
||||
<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="frameSideDataTimecodeType">
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataListType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="side_data" type="ffprobe:frameSideDataType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="frameSideDataType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecodes" type="ffprobe:frameSideDataTimecodeList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:complexType name="subtitleType">
|
||||
<xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/>
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<xsd:attribute name="pts_time" type="xsd:float"/>
|
||||
<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="side_data_type" type="xsd:string"/>
|
||||
<xsd:attribute name="side_data_size" type="xsd:int" />
|
||||
<xsd:attribute name="timecode" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="streamsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataTimecodeList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="timecode" type="ffprobe:frameSideDataTimecodeType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="programsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="program" type="ffprobe:programType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="frameSideDataTimecodeType">
|
||||
<xsd:attribute name="value" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="streamDispositionType">
|
||||
<xsd:attribute name="default" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="dub" type="xsd:int" use="required" />
|
||||
<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="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="subtitleType">
|
||||
<xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/>
|
||||
<xsd:attribute name="pts" type="xsd:long" />
|
||||
<xsd:attribute name="pts_time" type="xsd:float"/>
|
||||
<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:complexType name="streamType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/>
|
||||
<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:complexType name="streamsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:attribute name="index" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="codec_name" type="xsd:string" />
|
||||
<xsd:attribute name="codec_long_name" type="xsd:string" />
|
||||
<xsd:attribute name="profile" type="xsd:string" />
|
||||
<xsd:attribute name="codec_type" type="xsd:string" />
|
||||
<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" />
|
||||
|
||||
<xsd:complexType name="programsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="program" type="ffprobe:programType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<!-- video attributes -->
|
||||
<xsd:attribute name="width" type="xsd:int"/>
|
||||
<xsd:attribute name="height" type="xsd:int"/>
|
||||
<xsd:attribute name="coded_width" type="xsd:int"/>
|
||||
<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="streamDispositionType">
|
||||
<xsd:attribute name="default" type="xsd:int" use="required" />
|
||||
<xsd:attribute name="dub" type="xsd:int" use="required" />
|
||||
<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>
|
||||
<!-- audio attributes -->
|
||||
<xsd:attribute name="sample_fmt" type="xsd:string"/>
|
||||
<xsd:attribute name="sample_rate" type="xsd:int"/>
|
||||
<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:complexType name="streamType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="disposition" type="ffprobe:streamDispositionType" minOccurs="0" maxOccurs="1"/>
|
||||
<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:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="r_frame_rate" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="avg_frame_rate" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="time_base" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="start_pts" type="xsd:long"/>
|
||||
<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:attribute name="index" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="codec_name" type="xsd:string" />
|
||||
<xsd:attribute name="codec_long_name" type="xsd:string" />
|
||||
<xsd:attribute name="profile" type="xsd:string" />
|
||||
<xsd:attribute name="codec_type" type="xsd:string" />
|
||||
<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" />
|
||||
<xsd:complexType name="programType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<!-- video attributes -->
|
||||
<xsd:attribute name="width" type="xsd:int"/>
|
||||
<xsd:attribute name="height" type="xsd:int"/>
|
||||
<xsd:attribute name="coded_width" type="xsd:int"/>
|
||||
<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:attribute name="program_id" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="program_num" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pmt_pid" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pcr_pid" type="xsd:int" use="required"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- audio attributes -->
|
||||
<xsd:attribute name="sample_fmt" type="xsd:string"/>
|
||||
<xsd:attribute name="sample_rate" type="xsd:int"/>
|
||||
<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:complexType name="formatType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="r_frame_rate" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="avg_frame_rate" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="time_base" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="start_pts" type="xsd:long"/>
|
||||
<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: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="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="programType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<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:attribute name="program_id" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="program_num" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="nb_streams" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pmt_pid" type="xsd:int" use="required"/>
|
||||
<xsd:attribute name="pcr_pid" type="xsd:int" 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="formatType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<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: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="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="chaptersType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="chapter" type="ffprobe:chapterType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</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="chapterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<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: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="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="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="chaptersType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="chapter" type="ffprobe:chapterType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</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="chapterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="tags" type="ffprobe:tagsType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<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: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="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="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="pixelFormatComponentsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="component" type="ffprobe:pixelFormatComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</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="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: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: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="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:complexType name="pixelFormatsType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="pixel_format" type="ffprobe:pixelFormatType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
|
||||
2939
doc/filters.texi
2939
doc/filters.texi
File diff suppressed because it is too large
Load Diff
@@ -510,8 +510,6 @@ library:
|
||||
@tab A format used by libvpx
|
||||
@item Internet Video Recording @tab @tab X
|
||||
@item IRCAM @tab X @tab X
|
||||
@item LAF @tab @tab X
|
||||
@tab Limitless Audio Format
|
||||
@item LATM @tab X @tab X
|
||||
@item LMLM4 @tab @tab X
|
||||
@tab Used by Linux Media Labs MPEG-4 PCI boards
|
||||
@@ -534,8 +532,6 @@ library:
|
||||
@item Metal Gear Solid: The Twin Snakes @tab @tab X
|
||||
@item Megalux Frame @tab @tab X
|
||||
@tab Used by Megalux Ultimate Paint
|
||||
@item MobiClip MODS @tab @tab X
|
||||
@item MobiClip MOFLEX @tab @tab X
|
||||
@item Mobotix .mxg @tab @tab X
|
||||
@item Monkey's Audio @tab @tab X
|
||||
@item Motion Pixels MVI @tab @tab X
|
||||
@@ -579,7 +575,6 @@ library:
|
||||
@item Ogg @tab X @tab X
|
||||
@item Playstation Portable PMP @tab @tab X
|
||||
@item Portable Voice Format @tab @tab X
|
||||
@item RK Audio (RKA) @tab @tab X
|
||||
@item TechnoTrend PVA @tab @tab X
|
||||
@tab Used by TechnoTrend DVB PCI boards.
|
||||
@item QCP @tab @tab X
|
||||
@@ -587,10 +582,8 @@ library:
|
||||
@item raw AC-3 @tab X @tab X
|
||||
@item raw AMR-NB @tab @tab X
|
||||
@item raw AMR-WB @tab @tab X
|
||||
@item raw APAC @tab @tab X
|
||||
@item raw aptX @tab X @tab X
|
||||
@item raw aptX HD @tab X @tab X
|
||||
@item raw Bonk @tab @tab X
|
||||
@item raw Chinese AVS video @tab X @tab X
|
||||
@item raw DFPWM @tab X @tab X
|
||||
@item raw Dirac @tab X @tab X
|
||||
@@ -615,7 +608,6 @@ library:
|
||||
@item raw video @tab X @tab X
|
||||
@item raw id RoQ @tab X @tab
|
||||
@item raw OBU @tab X @tab X
|
||||
@item raw OSQ @tab @tab X
|
||||
@item raw SBC @tab X @tab X
|
||||
@item raw Shorten @tab @tab X
|
||||
@item raw TAK @tab @tab X
|
||||
@@ -667,10 +659,8 @@ library:
|
||||
@item Sample Dump eXchange @tab @tab X
|
||||
@item SAP @tab X @tab X
|
||||
@item SBG @tab @tab X
|
||||
@item SDNS @tab @tab X
|
||||
@item SDP @tab @tab X
|
||||
@item SER @tab @tab X
|
||||
@item Digital Pictures SGA @tab @tab X
|
||||
@item Sega FILM/CPK @tab X @tab X
|
||||
@tab Used in many Sega Saturn console games.
|
||||
@item Silicon Graphics Movie @tab @tab X
|
||||
@@ -708,9 +698,7 @@ library:
|
||||
@item Vivo @tab @tab X
|
||||
@item VPK @tab @tab X
|
||||
@tab Audio format used in Sony PS games.
|
||||
@item Marble WADY @tab @tab X
|
||||
@item WAV @tab X @tab X
|
||||
@item Waveform Archiver @tab @tab X
|
||||
@item WavPack @tab X @tab X
|
||||
@item WebM @tab X @tab X
|
||||
@item Windows Televison (WTV) @tab X @tab X
|
||||
@@ -722,7 +710,6 @@ library:
|
||||
@tab Multimedia format used in Westwood Studios games.
|
||||
@item Wideband Single-bit Data (WSD) @tab @tab X
|
||||
@item WVE @tab @tab X
|
||||
@item Konami XMD @tab @tab X
|
||||
@item XMV @tab @tab X
|
||||
@tab Microsoft video container used in Xbox games.
|
||||
@item XVAG @tab @tab X
|
||||
@@ -762,8 +749,6 @@ following image formats are supported:
|
||||
@tab OpenEXR
|
||||
@item FITS @tab X @tab X
|
||||
@tab Flexible Image Transport System
|
||||
@item HDR @tab X @tab X
|
||||
@tab Radiance HDR RGBE Image format
|
||||
@item IMG @tab @tab X
|
||||
@tab GEM Raster image
|
||||
@item JPEG @tab X @tab X
|
||||
@@ -772,7 +757,6 @@ following image formats are supported:
|
||||
@item JPEG-LS @tab X @tab X
|
||||
@item LJPEG @tab X @tab
|
||||
@tab Lossless JPEG
|
||||
@item Media 100 @tab @tab X
|
||||
@item MSP @tab @tab X
|
||||
@tab Microsoft Paint image
|
||||
@item PAM @tab X @tab X
|
||||
@@ -815,8 +799,6 @@ following image formats are supported:
|
||||
@tab Targa (.TGA) image format
|
||||
@item VBN @tab X @tab X
|
||||
@tab Vizrt Binary Image format
|
||||
@item WBMP @tab X @tab X
|
||||
@tab Wireless Application Protocol Bitmap image format
|
||||
@item WebP @tab E @tab X
|
||||
@tab WebP image format, encoding supported through external library libwebp
|
||||
@item XBM @tab X @tab X
|
||||
@@ -1007,7 +989,7 @@ following image formats are supported:
|
||||
@tab Also known as Microsoft Screen 3.
|
||||
@item Microsoft Expression Encoder Screen @tab @tab X
|
||||
@tab Also known as Microsoft Titanium Screen 2.
|
||||
@item Microsoft RLE @tab X @tab X
|
||||
@item Microsoft RLE @tab @tab X
|
||||
@item Microsoft Screen 1 @tab @tab X
|
||||
@tab Also known as Windows Media Video V7 Screen.
|
||||
@item Microsoft Screen 2 @tab @tab X
|
||||
@@ -1067,8 +1049,6 @@ following image formats are supported:
|
||||
@item RealVideo 4.0 @tab @tab X
|
||||
@item Renderware TXD (TeXture Dictionary) @tab @tab X
|
||||
@tab Texture dictionaries used by the Renderware Engine.
|
||||
@item RivaTuner Video @tab @tab X
|
||||
@tab fourcc: 'RTV1'
|
||||
@item RL2 video @tab @tab X
|
||||
@tab used in some games by Entertainment Software Partners
|
||||
@item ScreenPressor @tab @tab X
|
||||
@@ -1105,8 +1085,6 @@ following image formats are supported:
|
||||
@item v408 QuickTime uncompressed 4:4:4:4 @tab X @tab X
|
||||
@item v410 QuickTime uncompressed 4:4:4 10-bit @tab X @tab X
|
||||
@item VBLE Lossless Codec @tab @tab X
|
||||
@item vMix Video @tab @tab X
|
||||
@tab fourcc: 'VMX1'
|
||||
@item VMware Screen Codec / VMware Video @tab @tab X
|
||||
@tab Codec used in videos captured by VMware.
|
||||
@item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X
|
||||
@@ -1173,7 +1151,6 @@ following image formats are supported:
|
||||
@item ADPCM IMA Electronic Arts SEAD @tab @tab X
|
||||
@item ADPCM IMA Funcom @tab @tab X
|
||||
@item ADPCM IMA High Voltage Software ALP @tab X @tab X
|
||||
@item ADPCM IMA Mobiclip MOFLEX @tab @tab X
|
||||
@item ADPCM IMA QuickTime @tab X @tab X
|
||||
@item ADPCM IMA Simon & Schuster Interactive @tab X @tab X
|
||||
@item ADPCM IMA Ubisoft APM @tab X @tab X
|
||||
@@ -1203,7 +1180,6 @@ following image formats are supported:
|
||||
@item ADPCM Sound Blaster Pro 4-bit @tab @tab X
|
||||
@item ADPCM VIMA @tab @tab X
|
||||
@tab Used in LucasArts SMUSH animations.
|
||||
@item ADPCM Konami XMD @tab @tab X
|
||||
@item ADPCM Westwood Studios IMA @tab X @tab X
|
||||
@tab Used in Westwood Studios games like Command and Conquer.
|
||||
@item ADPCM Yamaha @tab X @tab X
|
||||
@@ -1225,7 +1201,6 @@ following image formats are supported:
|
||||
@item ATRAC9 @tab @tab X
|
||||
@item Bink Audio @tab @tab X
|
||||
@tab Used in Bink and Smacker files in many games.
|
||||
@item Bonk audio @tab @tab X
|
||||
@item CELT @tab @tab E
|
||||
@tab decoding supported through external library libcelt
|
||||
@item codec2 @tab E @tab E
|
||||
@@ -1241,12 +1216,9 @@ following image formats are supported:
|
||||
@item DCA (DTS Coherent Acoustics) @tab X @tab X
|
||||
@tab supported extensions: XCh, XXCH, X96, XBR, XLL, LBR (partially)
|
||||
@item Dolby E @tab @tab X
|
||||
@item DPCM Cuberoot-Delta-Exact @tab @tab X
|
||||
@tab Used in few games.
|
||||
@item DPCM Gremlin @tab @tab X
|
||||
@item DPCM id RoQ @tab X @tab X
|
||||
@tab Used in Quake III, Jedi Knight 2 and other computer games.
|
||||
@item DPCM Marble WADY @tab @tab X
|
||||
@item DPCM Interplay @tab @tab X
|
||||
@tab Used in various Interplay computer games.
|
||||
@item DPCM Squareroot-Delta-Exact @tab @tab X
|
||||
@@ -1267,7 +1239,6 @@ following image formats are supported:
|
||||
@item Enhanced AC-3 @tab X @tab X
|
||||
@item EVRC (Enhanced Variable Rate Codec) @tab @tab X
|
||||
@item FLAC (Free Lossless Audio Codec) @tab X @tab IX
|
||||
@item FTR Voice @tab @tab X
|
||||
@item G.723.1 @tab X @tab X
|
||||
@item G.729 @tab @tab X
|
||||
@item GSM @tab E @tab X
|
||||
@@ -1281,8 +1252,6 @@ following image formats are supported:
|
||||
@item Interplay ACM @tab @tab X
|
||||
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X
|
||||
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X
|
||||
@item Marian's A-pac audio @tab @tab X
|
||||
@item MI-SC4 (Micronas SC-4 Audio) @tab @tab X
|
||||
@item MLP (Meridian Lossless Packing) @tab X @tab X
|
||||
@tab Used in DVD-Audio discs.
|
||||
@item Monkey's Audio @tab @tab X
|
||||
@@ -1292,14 +1261,12 @@ following image formats are supported:
|
||||
@item MP3 (MPEG audio layer 3) @tab E @tab IX
|
||||
@tab encoding supported through external library LAME, ADU MP3 and MP3onMP4 also supported
|
||||
@item MPEG-4 Audio Lossless Coding (ALS) @tab @tab X
|
||||
@item MobiClip FastAudio @tab @tab X
|
||||
@item Musepack SV7 @tab @tab X
|
||||
@item Musepack SV8 @tab @tab X
|
||||
@item Nellymoser Asao @tab X @tab X
|
||||
@item On2 AVC (Audio for Video Codec) @tab @tab X
|
||||
@item Opus @tab E @tab X
|
||||
@tab encoding supported through external library libopus
|
||||
@item OSQ (Original Sound Quality) @tab @tab X
|
||||
@item PCM A-law @tab X @tab X
|
||||
@item PCM mu-law @tab X @tab X
|
||||
@item PCM Archimedes VIDC @tab X @tab X
|
||||
@@ -1328,7 +1295,6 @@ following image formats are supported:
|
||||
@item PCM unsigned 24-bit little-endian @tab X @tab X
|
||||
@item PCM unsigned 32-bit big-endian @tab X @tab X
|
||||
@item PCM unsigned 32-bit little-endian @tab X @tab X
|
||||
@item PCM SGA @tab @tab X
|
||||
@item QCELP / PureVoice @tab @tab X
|
||||
@item QDesign Music Codec 1 @tab @tab X
|
||||
@item QDesign Music Codec 2 @tab @tab X
|
||||
@@ -1341,7 +1307,6 @@ following image formats are supported:
|
||||
@tab Real low bitrate AC-3 codec
|
||||
@item RealAudio Lossless @tab @tab X
|
||||
@item RealAudio SIPR / ACELP.NET @tab @tab X
|
||||
@item RK Audio (RKA) @tab @tab X
|
||||
@item SBC (low-complexity subband codec) @tab X @tab X
|
||||
@tab Used in Bluetooth A2DP
|
||||
@item Shorten @tab @tab X
|
||||
@@ -1362,11 +1327,9 @@ following image formats are supported:
|
||||
@item TwinVQ (VQF flavor) @tab @tab X
|
||||
@item VIMA @tab @tab X
|
||||
@tab Used in LucasArts SMUSH animations.
|
||||
@item ViewQuest VQC @tab @tab X
|
||||
@item Vorbis @tab E @tab X
|
||||
@tab A native but very primitive encoder exists.
|
||||
@item Voxware MetaSound @tab @tab X
|
||||
@item Waveform Archiver @tab @tab X
|
||||
@item WavPack @tab X @tab X
|
||||
@item Westwood Audio (SND1) @tab @tab X
|
||||
@item Windows Media Audio 1 @tab X @tab X
|
||||
|
||||
@@ -53,7 +53,7 @@ Most distribution and operating system provide a package for it.
|
||||
@section Cloning the source tree
|
||||
|
||||
@example
|
||||
git clone https://git.ffmpeg.org/ffmpeg.git <target>
|
||||
git clone git://source.ffmpeg.org/ffmpeg <target>
|
||||
@end example
|
||||
|
||||
This will put the FFmpeg sources into the directory @var{<target>}.
|
||||
@@ -187,18 +187,11 @@ to make sure you don't have untracked files or deletions.
|
||||
git add [-i|-p|-A] <filenames/dirnames>
|
||||
@end example
|
||||
|
||||
Make sure you have told Git your name, email address and GPG key
|
||||
Make sure you have told Git your name and email address
|
||||
|
||||
@example
|
||||
git config --global user.name "My Name"
|
||||
git config --global user.email my@@email.invalid
|
||||
git config --global user.signingkey ABCDEF0123245
|
||||
@end example
|
||||
|
||||
Enable signing all commits or use -S
|
||||
|
||||
@example
|
||||
git config --global commit.gpgsign true
|
||||
@end example
|
||||
|
||||
Use @option{--global} to set the global configuration for all your Git checkouts.
|
||||
@@ -430,19 +423,6 @@ git checkout -b svn_23456 $SHA1
|
||||
where @var{$SHA1} is the commit hash from the @command{git log} output.
|
||||
|
||||
|
||||
@chapter gpg key generation
|
||||
|
||||
If you have no gpg key yet, we recommend that you create a ed25519 based key as it
|
||||
is small, fast and secure. Especially it results in small signatures in git.
|
||||
|
||||
@example
|
||||
gpg --default-new-key-algo "ed25519/cert,sign+cv25519/encr" --quick-generate-key "human@@server.com"
|
||||
@end example
|
||||
|
||||
When generating a key, make sure the email specified matches the email used in git as some sites like
|
||||
github consider mismatches a reason to declare such commits unverified. After generating a key you
|
||||
can add it to the MAINTAINER file and upload it to a keyserver.
|
||||
|
||||
@chapter Pre-push checklist
|
||||
|
||||
Once you have a set of commits that you feel are ready for pushing,
|
||||
|
||||
@@ -991,8 +991,9 @@ This input device reads data from the open output pads of a libavfilter
|
||||
filtergraph.
|
||||
|
||||
For each filtergraph open output, the input device will create a
|
||||
corresponding stream which is mapped to the generated output.
|
||||
The filtergraph is specified through the option @option{graph}.
|
||||
corresponding stream which is mapped to the generated output. Currently
|
||||
only video data is supported. The filtergraph is specified through the
|
||||
option @option{graph}.
|
||||
|
||||
@subsection Options
|
||||
|
||||
|
||||
@@ -344,7 +344,7 @@ recommended.
|
||||
Avoid sending the same message to multiple mailing lists.
|
||||
|
||||
@item
|
||||
Please follow our @url{https://ffmpeg.org/community.html#Code-of-conduct, Code of Conduct}.
|
||||
Please follow our @url{https://ffmpeg.org/developer.html#Code-of-conduct, Code of Conduct}.
|
||||
@end itemize
|
||||
|
||||
@chapter Help
|
||||
|
||||
@@ -48,6 +48,11 @@ Files that have MIPS copyright notice in them:
|
||||
float_dsp_mips.c
|
||||
libm_mips.h
|
||||
softfloat_tables.h
|
||||
* libavcodec/
|
||||
fft_fixed_32.c
|
||||
fft_init_table.c
|
||||
fft_table.h
|
||||
mdct_fixed_32.c
|
||||
* libavcodec/mips/
|
||||
aacdec_fixed.c
|
||||
aacsbr_fixed.c
|
||||
@@ -65,6 +70,9 @@ Files that have MIPS copyright notice in them:
|
||||
compute_antialias_float.h
|
||||
lsp_mips.h
|
||||
dsputil_mips.c
|
||||
fft_mips.c
|
||||
fft_table.h
|
||||
fft_init_table.c
|
||||
fmtconvert_mips.c
|
||||
iirfilter_mips.c
|
||||
mpegaudiodsp_mips_fixed.c
|
||||
|
||||
@@ -55,7 +55,8 @@ speed gain at this point but it should work.
|
||||
|
||||
If there are inter-frame dependencies, so the codec calls
|
||||
ff_thread_report/await_progress(), set FF_CODEC_CAP_ALLOCATE_PROGRESS in
|
||||
FFCodec.caps_internal and use ff_thread_get_buffer() to allocate frames.
|
||||
AVCodec.caps_internal and use ff_thread_get_buffer() to allocate frames. The
|
||||
frames must then be freed with ff_thread_release_buffer().
|
||||
Otherwise decode directly into the user-supplied frames.
|
||||
|
||||
Call ff_thread_report_progress() after some part of the current picture has decoded.
|
||||
|
||||
113
doc/muxers.texi
113
doc/muxers.texi
@@ -795,6 +795,12 @@ deletes them. Increase this to allow continue clients to download segments which
|
||||
were recently referenced in the playlist. Default value is 1, meaning segments older than
|
||||
@code{hls_list_size+1} will be deleted.
|
||||
|
||||
@item hls_ts_options @var{options_list}
|
||||
Set output format options using a :-separated list of key=value
|
||||
parameters. Values containing @code{:} special characters must be
|
||||
escaped.
|
||||
@code{hls_ts_options} is deprecated, use hls_segment_options instead of it..
|
||||
|
||||
@item hls_start_number_source
|
||||
Start the playlist sequence number (@code{#EXT-X-MEDIA-SEQUENCE}) according to the specified source.
|
||||
Unless @code{hls_flags single_file} is set, it also specifies source of starting sequence numbers of
|
||||
@@ -1325,7 +1331,7 @@ Use persistent HTTP connections. Applicable only for HTTP output.
|
||||
@item timeout
|
||||
Set timeout for socket I/O operations. Applicable only for HTTP output.
|
||||
|
||||
@item ignore_io_errors
|
||||
@item -ignore_io_errors
|
||||
Ignore IO errors during open, write and delete. Useful for long-duration runs with network output.
|
||||
|
||||
@item headers
|
||||
@@ -1468,7 +1474,7 @@ ffmpeg -f v4l2 -r 1 -i /dev/video0 -f image2 -strftime 1 "%Y-%m-%d_%H-%M-%S.jpg"
|
||||
|
||||
You can set the file name with current frame's PTS:
|
||||
@example
|
||||
ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg
|
||||
ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg"
|
||||
@end example
|
||||
|
||||
A more complex example is to publish contents of your desktop directly to a
|
||||
@@ -1630,10 +1636,8 @@ MOV/MP4/ISMV (Smooth Streaming) muxer.
|
||||
The mov/mp4/ismv muxer supports fragmentation. Normally, a MOV/MP4
|
||||
file has all the metadata about all packets stored in one location
|
||||
(written at the end of the file, it can be moved to the start for
|
||||
better playback by adding @code{+faststart} to the @code{-movflags}, or
|
||||
using the @command{qt-faststart} tool).
|
||||
|
||||
A fragmented
|
||||
better playback by adding @var{faststart} to the @var{movflags}, or
|
||||
using the @command{qt-faststart} tool). A fragmented
|
||||
file consists of a number of fragments, where packets and metadata
|
||||
about these packets are stored together. Writing a fragmented
|
||||
file has the advantage that the file is decodable even if the
|
||||
@@ -1643,34 +1647,40 @@ very long files (since writing normal MOV/MP4 files stores info about
|
||||
every single packet in memory until the file is closed). The downside
|
||||
is that it is less compatible with other applications.
|
||||
|
||||
Fragmentation is enabled by setting one of the options that define
|
||||
how to cut the file into fragments: @code{-frag_duration}, @code{-frag_size},
|
||||
@code{-min_frag_duration}, @code{-movflags +frag_keyframe} and
|
||||
@code{-movflags +frag_custom}. If more than one condition is specified,
|
||||
fragments are cut when one of the specified conditions is fulfilled. The
|
||||
exception to this is @code{-min_frag_duration}, which has to be fulfilled for
|
||||
any of the other conditions to apply.
|
||||
|
||||
@subsection Options
|
||||
|
||||
Fragmentation is enabled by setting one of the AVOptions that define
|
||||
how to cut the file into fragments:
|
||||
|
||||
@table @option
|
||||
@item frag_duration @var{duration}
|
||||
Create fragments that are @var{duration} microseconds long.
|
||||
@item frag_size @var{size}
|
||||
Create fragments that contain up to @var{size} bytes of payload data.
|
||||
@item min_frag_duration @var{duration}
|
||||
Don't create fragments that are shorter than @var{duration} microseconds long.
|
||||
@item movflags @var{flags}
|
||||
Set various muxing switches. The following flags can be used:
|
||||
@table @samp
|
||||
@item frag_keyframe
|
||||
@item -moov_size @var{bytes}
|
||||
Reserves space for the moov atom at the beginning of the file instead of placing the
|
||||
moov atom at the end. If the space reserved is insufficient, muxing will fail.
|
||||
@item -movflags frag_keyframe
|
||||
Start a new fragment at each video keyframe.
|
||||
@item frag_custom
|
||||
@item -frag_duration @var{duration}
|
||||
Create fragments that are @var{duration} microseconds long.
|
||||
@item -frag_size @var{size}
|
||||
Create fragments that contain up to @var{size} bytes of payload data.
|
||||
@item -movflags frag_custom
|
||||
Allow the caller to manually choose when to cut fragments, by
|
||||
calling @code{av_write_frame(ctx, NULL)} to write a fragment with
|
||||
the packets written so far. (This is only useful with other
|
||||
applications integrating libavformat, not from @command{ffmpeg}.)
|
||||
@item empty_moov
|
||||
@item -min_frag_duration @var{duration}
|
||||
Don't create fragments that are shorter than @var{duration} microseconds long.
|
||||
@end table
|
||||
|
||||
If more than one condition is specified, fragments are cut when
|
||||
one of the specified conditions is fulfilled. The exception to this is
|
||||
@code{-min_frag_duration}, which has to be fulfilled for any of the other
|
||||
conditions to apply.
|
||||
|
||||
Additionally, the way the output file is written can be adjusted
|
||||
through a few other options:
|
||||
|
||||
@table @option
|
||||
@item -movflags empty_moov
|
||||
Write an initial moov atom directly at the start of the file, without
|
||||
describing any samples in it. Generally, an mdat/moov pair is written
|
||||
at the start of the file, as a normal MOV/MP4 file, containing only
|
||||
@@ -1679,40 +1689,43 @@ mdat atom, and the moov atom only describes the tracks but has
|
||||
a zero duration.
|
||||
|
||||
This option is implicitly set when writing ismv (Smooth Streaming) files.
|
||||
@item separate_moof
|
||||
@item -movflags separate_moof
|
||||
Write a separate moof (movie fragment) atom for each track. Normally,
|
||||
packets for all tracks are written in a moof atom (which is slightly
|
||||
more efficient), but with this option set, the muxer writes one moof/mdat
|
||||
pair for each track, making it easier to separate tracks.
|
||||
|
||||
This option is implicitly set when writing ismv (Smooth Streaming) files.
|
||||
@item skip_sidx
|
||||
@item -movflags skip_sidx
|
||||
Skip writing of sidx atom. When bitrate overhead due to sidx atom is high,
|
||||
this option could be used for cases where sidx atom is not mandatory.
|
||||
When global_sidx flag is enabled, this option will be ignored.
|
||||
@item faststart
|
||||
@item -movflags faststart
|
||||
Run a second pass moving the index (moov atom) to the beginning of the file.
|
||||
This operation can take a while, and will not work in various situations such
|
||||
as fragmented output, thus it is not enabled by default.
|
||||
@item rtphint
|
||||
@item -movflags rtphint
|
||||
Add RTP hinting tracks to the output file.
|
||||
@item disable_chpl
|
||||
@item -movflags disable_chpl
|
||||
Disable Nero chapter markers (chpl atom). Normally, both Nero chapters
|
||||
and a QuickTime chapter track are written to the file. With this option
|
||||
set, only the QuickTime chapter track will be written. Nero chapters can
|
||||
cause failures when the file is reprocessed with certain tagging programs, like
|
||||
mp3Tag 2.61a and iTunes 11.3, most likely other versions are affected as well.
|
||||
@item omit_tfhd_offset
|
||||
@item -movflags omit_tfhd_offset
|
||||
Do not write any absolute base_data_offset in tfhd atoms. This avoids
|
||||
tying fragments to absolute byte positions in the file/streams.
|
||||
@item default_base_moof
|
||||
@item -movflags default_base_moof
|
||||
Similarly to the omit_tfhd_offset, this flag avoids writing the
|
||||
absolute base_data_offset field in tfhd atoms, but does so by using
|
||||
the new default-base-is-moof flag instead. This flag is new from
|
||||
14496-12:2012. This may make the fragments easier to parse in certain
|
||||
circumstances (avoiding basing track fragment location calculations
|
||||
on the implicit end of the previous track fragment).
|
||||
@item negative_cts_offsets
|
||||
@item -write_tmcd
|
||||
Specify @code{on} to force writing a timecode track, @code{off} to disable it
|
||||
and @code{auto} to write a timecode track only for mov and mp4 output (default).
|
||||
@item -movflags negative_cts_offsets
|
||||
Enables utilization of version 1 of the CTTS box, in which the CTS offsets can
|
||||
be negative. This enables the initial sample to have DTS/CTS of zero, and
|
||||
reduces the need for edit lists for some cases such as video tracks with
|
||||
@@ -1720,24 +1733,15 @@ B-frames. Additionally, eases conformance with the DASH-IF interoperability
|
||||
guidelines.
|
||||
|
||||
This option is implicitly set when writing ismv (Smooth Streaming) files.
|
||||
@end table
|
||||
|
||||
@item moov_size @var{bytes}
|
||||
Reserves space for the moov atom at the beginning of the file instead of placing the
|
||||
moov atom at the end. If the space reserved is insufficient, muxing will fail.
|
||||
|
||||
@item write_tmcd
|
||||
Specify @code{on} to force writing a timecode track, @code{off} to disable it
|
||||
and @code{auto} to write a timecode track only for mov and mp4 output (default).
|
||||
|
||||
@item write_btrt @var{bool}
|
||||
@item -write_btrt @var{bool}
|
||||
Force or disable writing bitrate box inside stsd box of a track.
|
||||
The box contains decoding buffer size (in bytes), maximum bitrate and
|
||||
average bitrate for the track. The box will be skipped if none of these values
|
||||
can be computed.
|
||||
Default is @code{-1} or @code{auto}, which will write the box only in MP4 mode.
|
||||
|
||||
@item write_prft
|
||||
@item -write_prft
|
||||
Write producer time reference box (PRFT) with a specified time source for the
|
||||
NTP field in the PRFT box. Set value as @samp{wallclock} to specify timesource
|
||||
as wallclock time and @samp{pts} to specify timesource as input packets' PTS
|
||||
@@ -1748,15 +1752,15 @@ where PTS values are set as as wallclock time at the source. For example, an
|
||||
encoding use case with decklink capture source where @option{video_pts} and
|
||||
@option{audio_pts} are set to @samp{abs_wallclock}.
|
||||
|
||||
@item empty_hdlr_name @var{bool}
|
||||
@item -empty_hdlr_name @var{bool}
|
||||
Enable to skip writing the name inside a @code{hdlr} box.
|
||||
Default is @code{false}.
|
||||
|
||||
@item movie_timescale @var{scale}
|
||||
@item -movie_timescale @var{scale}
|
||||
Set the timescale written in the movie header box (@code{mvhd}).
|
||||
Range is 1 to INT_MAX. Default is 1000.
|
||||
|
||||
@item video_track_timescale @var{scale}
|
||||
@item -video_track_timescale @var{scale}
|
||||
Set the timescale used for video tracks. Range is 0 to INT_MAX.
|
||||
If set to @code{0}, the timescale is automatically set based on
|
||||
the native stream time base. Default is 0.
|
||||
@@ -1911,8 +1915,6 @@ Conform to System B (DVB) instead of System A (ATSC).
|
||||
Mark the initial packet of each stream as discontinuity.
|
||||
@item nit
|
||||
Emit NIT table.
|
||||
@item omit_rai
|
||||
Disable writing of random access indicator.
|
||||
@end table
|
||||
|
||||
@item mpegts_copyts @var{boolean}
|
||||
@@ -2122,12 +2124,6 @@ DTS Coherent Acoustics (DCA) audio.
|
||||
|
||||
Dolby Digital Plus, also known as Enhanced AC-3, audio.
|
||||
|
||||
@subsection evc
|
||||
|
||||
MPEG-5 Essential Video Coding (EVC) / EVC / MPEG-5 Part 1 EVC video.
|
||||
|
||||
Extensions: evc
|
||||
|
||||
@subsection g722
|
||||
|
||||
ITU-T G.722 audio.
|
||||
@@ -2371,11 +2367,6 @@ Note that splitting may not be accurate, unless you force the
|
||||
reference stream key-frames at the given time. See the introductory
|
||||
notice and the examples below.
|
||||
|
||||
@item min_seg_duration @var{time}
|
||||
Set minimum segment duration to @var{time}, the value must be a duration
|
||||
specification. This prevents the muxer ending segments at a duration below
|
||||
this value. Only effective with @code{segment_time}. Default value is "0".
|
||||
|
||||
@item segment_atclocktime @var{1|0}
|
||||
If set to "1" split at regular clock time intervals starting from 00:00
|
||||
o'clock. The @var{time} value specified in @option{segment_time} is
|
||||
|
||||
@@ -267,11 +267,6 @@ CELL/SPU:
|
||||
http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/30B3520C93F437AB87257060006FFE5E/$file/Language_Extensions_for_CBEA_2.4.pdf
|
||||
http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/9F820A5FFA3ECE8C8725716A0062585F/$file/CBE_Handbook_v1.1_24APR2007_pub.pdf
|
||||
|
||||
RISC-V-specific:
|
||||
----------------
|
||||
The RISC-V Instruction Set Manual, Volume 1, Unprivileged ISA:
|
||||
https://riscv.org/technical/specifications/
|
||||
|
||||
GCC asm links:
|
||||
--------------
|
||||
official doc but quite ugly
|
||||
|
||||
@@ -235,11 +235,6 @@ Enable SMPTE Level A mode on the used output.
|
||||
Must be @samp{unset}, @samp{true} or @samp{false}.
|
||||
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
|
||||
|
||||
@subsection Examples
|
||||
@@ -426,18 +421,13 @@ For more information about SDL, check:
|
||||
|
||||
@table @option
|
||||
|
||||
@item window_borderless
|
||||
Set SDL window border off.
|
||||
Default value is 0 (enable window border).
|
||||
@item window_title
|
||||
Set the SDL window title, if not specified default to the filename
|
||||
specified for the output device.
|
||||
|
||||
@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).
|
||||
|
||||
@item window_fullscreen
|
||||
Set fullscreen mode when non-zero value is provided.
|
||||
Default value is zero.
|
||||
@item icon_title
|
||||
Set the name of the iconified SDL window, if not specified it is set
|
||||
to the same value of @var{window_title}.
|
||||
|
||||
@item window_size
|
||||
Set the SDL window size, can be a string of the form
|
||||
@@ -445,13 +435,18 @@ Set the SDL window size, can be a string of the form
|
||||
If not specified it defaults to the size of the input video,
|
||||
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_y
|
||||
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
|
||||
|
||||
@subsection Interactive commands
|
||||
|
||||
@@ -92,6 +92,9 @@ For information about compiling FFmpeg on OS/2 see
|
||||
|
||||
@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
|
||||
|
||||
FFmpeg can be built to run natively on Windows using the MinGW-w64
|
||||
|
||||
@@ -275,33 +275,6 @@ For example, to convert a GIF file given inline with @command{ffmpeg}:
|
||||
ffmpeg -i "data:image/gif;base64,R0lGODdhCAAIAMIEAAAAAAAA//8AAP//AP///////////////ywAAAAACAAIAAADF0gEDLojDgdGiJdJqUX02iB4E8Q9jUMkADs=" smiley.png
|
||||
@end example
|
||||
|
||||
@section fd
|
||||
|
||||
File descriptor access protocol.
|
||||
|
||||
The accepted syntax is:
|
||||
@example
|
||||
fd: -fd @var{file_descriptor}
|
||||
@end example
|
||||
|
||||
If @option{fd} is not specified, by default the stdout file descriptor will be
|
||||
used for writing, stdin for reading. Unlike the pipe protocol, fd protocol has
|
||||
seek support if it corresponding to a regular file. fd protocol doesn't support
|
||||
pass file descriptor via URL for security.
|
||||
|
||||
This protocol accepts the following options:
|
||||
|
||||
@table @option
|
||||
@item blocksize
|
||||
Set I/O operation maximum block size, in bytes. Default value is
|
||||
@code{INT_MAX}, which results in not limiting the requested block size.
|
||||
Setting this value reasonably low improves user termination request reaction
|
||||
time, which is valuable if data transmission is slow.
|
||||
|
||||
@item fd
|
||||
Set file descriptor.
|
||||
@end table
|
||||
|
||||
@section file
|
||||
|
||||
File access protocol.
|
||||
@@ -649,6 +622,9 @@ This protocol wraps the IPFS native protocols (ipfs:// and ipns://) to be sent
|
||||
to such a gateway. Users can (and should) host their own node which means this
|
||||
protocol will use one's local gateway to access files on the IPFS network.
|
||||
|
||||
If a user doesn't have a node of their own then the public gateway @code{https://dweb.link}
|
||||
is used by default.
|
||||
|
||||
This protocol accepts the following options:
|
||||
|
||||
@table @option
|
||||
@@ -656,18 +632,18 @@ This protocol accepts the following options:
|
||||
@item gateway
|
||||
Defines the gateway to use. When not set, the protocol will first try
|
||||
locating the local gateway by looking at @code{$IPFS_GATEWAY}, @code{$IPFS_PATH}
|
||||
and @code{$HOME/.ipfs/}, in that order.
|
||||
and @code{$HOME/.ipfs/}, in that order. If that fails @code{https://dweb.link} will be used.
|
||||
|
||||
@end table
|
||||
|
||||
One can use this protocol in 2 ways. Using IPFS:
|
||||
@example
|
||||
ffplay ipfs://<hash>
|
||||
ffplay ipfs://QmbGtJg23skhvFmu9mJiePVByhfzu5rwo74MEkVDYAmF5T
|
||||
@end example
|
||||
|
||||
Or the IPNS protocol (IPNS is mutable IPFS):
|
||||
@example
|
||||
ffplay ipns://<hash>
|
||||
ffplay ipns://QmbGtJg23skhvFmu9mJiePVByhfzu5rwo74MEkVDYAmF5T
|
||||
@end example
|
||||
|
||||
@section mmst
|
||||
@@ -714,7 +690,7 @@ The accepted syntax is:
|
||||
pipe:[@var{number}]
|
||||
@end example
|
||||
|
||||
If @option{fd} isn't specified, @var{number} is the number corresponding to the file descriptor of the
|
||||
@var{number} is the number corresponding to the file descriptor of the
|
||||
pipe (e.g. 0 for stdin, 1 for stdout, 2 for stderr). If @var{number}
|
||||
is not specified, by default the stdout file descriptor will be used
|
||||
for writing, stdin for reading.
|
||||
@@ -741,8 +717,6 @@ Set I/O operation maximum block size, in bytes. Default value is
|
||||
@code{INT_MAX}, which results in not limiting the requested block size.
|
||||
Setting this value reasonably low improves user termination request reaction
|
||||
time, which is valuable if data transmission is slow.
|
||||
@item fd
|
||||
Set file descriptor.
|
||||
@end table
|
||||
|
||||
Note that some formats (typically MOV), require the output protocol to
|
||||
@@ -896,13 +870,6 @@ 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
|
||||
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
|
||||
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;
|
||||
@@ -1211,59 +1178,6 @@ Options can be set on the @command{ffmpeg}/@command{ffplay} command
|
||||
line, or set in code via @code{AVOption}s or in
|
||||
@code{avformat_open_input}.
|
||||
|
||||
@subsection Muxer
|
||||
The following options are supported.
|
||||
|
||||
@table @option
|
||||
@item rtsp_transport
|
||||
Set RTSP transport protocols.
|
||||
|
||||
It accepts the following values:
|
||||
@table @samp
|
||||
@item udp
|
||||
Use UDP as lower transport protocol.
|
||||
|
||||
@item tcp
|
||||
Use TCP (interleaving within the RTSP control channel) as lower
|
||||
transport protocol.
|
||||
@end table
|
||||
|
||||
Default value is @samp{0}.
|
||||
|
||||
@item rtsp_flags
|
||||
Set RTSP flags.
|
||||
|
||||
The following values are accepted:
|
||||
@table @samp
|
||||
@item latm
|
||||
Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC.
|
||||
@item rfc2190
|
||||
Use RFC 2190 packetization instead of RFC 4629 for H.263.
|
||||
@item skip_rtcp
|
||||
Don't send RTCP sender reports.
|
||||
@item h264_mode0
|
||||
Use mode 0 for H.264 in RTP.
|
||||
@item send_bye
|
||||
Send RTCP BYE packets when finishing.
|
||||
@end table
|
||||
|
||||
Default value is @samp{0}.
|
||||
|
||||
|
||||
@item min_port
|
||||
Set minimum local UDP port. Default value is 5000.
|
||||
|
||||
@item max_port
|
||||
Set maximum local UDP port. Default value is 65000.
|
||||
|
||||
@item buffer_size
|
||||
Set the maximum socket buffer size in bytes.
|
||||
|
||||
@item pkt_size
|
||||
Set max send packet size (in bytes). Default value is 1472.
|
||||
@end table
|
||||
|
||||
@subsection Demuxer
|
||||
The following options are supported.
|
||||
|
||||
@table @option
|
||||
@@ -1289,10 +1203,6 @@ Use UDP multicast as lower transport protocol.
|
||||
@item http
|
||||
Use HTTP tunneling as lower transport protocol, which is useful for
|
||||
passing proxies.
|
||||
|
||||
@item https
|
||||
Use HTTPs tunneling as lower transport protocol, which is useful for
|
||||
passing proxies and widely used for security consideration.
|
||||
@end table
|
||||
|
||||
Multiple lower transport protocols may be specified, in that case they are
|
||||
@@ -1310,9 +1220,6 @@ Accept packets only from negotiated peer address and port.
|
||||
Act as a server, listening for an incoming connection.
|
||||
@item prefer_tcp
|
||||
Try TCP for RTP transport first, if TCP is available as RTSP RTP transport.
|
||||
@item satip_raw
|
||||
Export raw MPEG-TS stream instead of demuxing. The flag will simply write out
|
||||
the raw stream, with the original PAT/PMT/PIDs intact.
|
||||
@end table
|
||||
|
||||
Default value is @samp{none}.
|
||||
@@ -1325,7 +1232,6 @@ The following flags are accepted:
|
||||
@item video
|
||||
@item audio
|
||||
@item data
|
||||
@item subtitle
|
||||
@end table
|
||||
|
||||
By default it accepts all media types.
|
||||
@@ -1350,9 +1256,6 @@ Set socket TCP I/O timeout in microseconds.
|
||||
@item user_agent
|
||||
Override User-Agent header. If not specified, it defaults to the
|
||||
libavformat identifier string.
|
||||
|
||||
@item buffer_size
|
||||
Set the maximum socket buffer size in bytes.
|
||||
@end table
|
||||
|
||||
When receiving data over UDP, the demuxer tries to reorder received packets
|
||||
@@ -1889,12 +1792,6 @@ The list of supported options follows.
|
||||
Listen for an incoming connection. 0 disables listen, 1 enables listen in
|
||||
single client mode, 2 enables listen in multi-client mode. Default value is 0.
|
||||
|
||||
@item 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}
|
||||
Set raise error timeout, expressed in microseconds.
|
||||
|
||||
|
||||
@@ -11,8 +11,18 @@ programmatic use.
|
||||
|
||||
@table @option
|
||||
|
||||
@item uchl, used_chlayout
|
||||
Set used input channel layout. Default is unset. This option is
|
||||
@item ich, in_channel_count
|
||||
Set the number of input channels. Default value is 0. Setting this
|
||||
value is not mandatory if the corresponding channel layout
|
||||
@option{in_channel_layout} is set.
|
||||
|
||||
@item och, out_channel_count
|
||||
Set the number of output channels. Default value is 0. Setting this
|
||||
value is not mandatory if the corresponding channel layout
|
||||
@option{out_channel_layout} is set.
|
||||
|
||||
@item uch, used_channel_count
|
||||
Set the number of used input channels. Default value is 0. This option is
|
||||
only used for special remapping.
|
||||
|
||||
@item isr, in_sample_rate
|
||||
@@ -31,8 +41,8 @@ Specify the output sample format. It is set by default to @code{none}.
|
||||
Set the internal sample format. Default value is @code{none}.
|
||||
This will automatically be chosen when it is not explicitly set.
|
||||
|
||||
@item ichl, in_chlayout
|
||||
@item ochl, out_chlayout
|
||||
@item icl, in_channel_layout
|
||||
@item ocl, out_channel_layout
|
||||
Set the input/output channel layout.
|
||||
|
||||
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
|
||||
|
||||
106
doc/t2h.pm
106
doc/t2h.pm
@@ -20,45 +20,8 @@
|
||||
# License along with FFmpeg; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Texinfo 7.0 changed the syntax of various functions.
|
||||
# Provide a shim for older versions.
|
||||
sub ff_set_from_init_file($$) {
|
||||
my $key = shift;
|
||||
my $value = shift;
|
||||
if (exists &{'texinfo_set_from_init_file'}) {
|
||||
texinfo_set_from_init_file($key, $value);
|
||||
} else {
|
||||
set_from_init_file($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
sub ff_get_conf($) {
|
||||
my $key = shift;
|
||||
if (exists &{'texinfo_get_conf'}) {
|
||||
texinfo_get_conf($key);
|
||||
} else {
|
||||
get_conf($key);
|
||||
}
|
||||
}
|
||||
|
||||
sub get_formatting_function($$) {
|
||||
my $obj = shift;
|
||||
my $func = shift;
|
||||
|
||||
my $sub = $obj->can('formatting_function');
|
||||
if ($sub) {
|
||||
return $obj->formatting_function($func);
|
||||
} else {
|
||||
return $obj->{$func};
|
||||
}
|
||||
}
|
||||
|
||||
# determine texinfo version
|
||||
my $program_version_num = version->declare(ff_get_conf('PACKAGE_VERSION'))->numify;
|
||||
my $program_version_6_8 = $program_version_num >= 6.008000;
|
||||
|
||||
# no navigation elements
|
||||
ff_set_from_init_file('HEADERS', 0);
|
||||
set_from_init_file('HEADERS', 0);
|
||||
|
||||
sub ffmpeg_heading_command($$$$$)
|
||||
{
|
||||
@@ -92,7 +55,7 @@ sub ffmpeg_heading_command($$$$$)
|
||||
$element = $command->{'parent'};
|
||||
}
|
||||
if ($element) {
|
||||
$result .= &{get_formatting_function($self, 'format_element_header')}($self, $cmdname,
|
||||
$result .= &{$self->{'format_element_header'}}($self, $cmdname,
|
||||
$command, $element);
|
||||
}
|
||||
|
||||
@@ -149,11 +112,7 @@ sub ffmpeg_heading_command($$$$$)
|
||||
$cmdname
|
||||
= $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
|
||||
}
|
||||
# format_heading_text expects an array of headings for texinfo >= 7.0
|
||||
if ($program_version_num >= 7.000000) {
|
||||
$heading = [$heading];
|
||||
}
|
||||
$result .= &{get_formatting_function($self,'format_heading_text')}(
|
||||
$result .= &{$self->{'format_heading_text'}}(
|
||||
$self, $cmdname, $heading,
|
||||
$heading_level +
|
||||
$self->get_conf('CHAPTER_HEADER_LEVEL') - 1, $command);
|
||||
@@ -167,19 +126,23 @@ foreach my $command (keys(%Texinfo::Common::sectioning_commands), 'node') {
|
||||
texinfo_register_command_formatting($command, \&ffmpeg_heading_command);
|
||||
}
|
||||
|
||||
# determine if texinfo is at least version 6.8
|
||||
my $program_version_num = version->declare(get_conf('PACKAGE_VERSION'))->numify;
|
||||
my $program_version_6_8 = $program_version_num >= 6.008000;
|
||||
|
||||
# print the TOC where @contents is used
|
||||
if ($program_version_6_8) {
|
||||
ff_set_from_init_file('CONTENTS_OUTPUT_LOCATION', 'inline');
|
||||
set_from_init_file('CONTENTS_OUTPUT_LOCATION', 'inline');
|
||||
} else {
|
||||
ff_set_from_init_file('INLINE_CONTENTS', 1);
|
||||
set_from_init_file('INLINE_CONTENTS', 1);
|
||||
}
|
||||
|
||||
# make chapters <h2>
|
||||
ff_set_from_init_file('CHAPTER_HEADER_LEVEL', 2);
|
||||
set_from_init_file('CHAPTER_HEADER_LEVEL', 2);
|
||||
|
||||
# Do not add <hr>
|
||||
ff_set_from_init_file('DEFAULT_RULE', '');
|
||||
ff_set_from_init_file('BIG_RULE', '');
|
||||
set_from_init_file('DEFAULT_RULE', '');
|
||||
set_from_init_file('BIG_RULE', '');
|
||||
|
||||
# Customized file beginning
|
||||
sub ffmpeg_begin_file($$$)
|
||||
@@ -196,18 +159,7 @@ sub ffmpeg_begin_file($$$)
|
||||
my ($title, $description, $encoding, $date, $css_lines,
|
||||
$doctype, $bodytext, $copying_comment, $after_body_open,
|
||||
$extra_head, $program_and_version, $program_homepage,
|
||||
$program, $generator);
|
||||
if ($program_version_num >= 7.000000) {
|
||||
($title, $description, $encoding, $date, $css_lines,
|
||||
$doctype, $bodytext, $copying_comment, $after_body_open,
|
||||
$extra_head, $program_and_version, $program_homepage,
|
||||
$program, $generator) = $self->_file_header_information($command);
|
||||
} else {
|
||||
($title, $description, $encoding, $date, $css_lines,
|
||||
$doctype, $bodytext, $copying_comment, $after_body_open,
|
||||
$extra_head, $program_and_version, $program_homepage,
|
||||
$program, $generator) = $self->_file_header_informations($command);
|
||||
}
|
||||
$program, $generator) = $self->_file_header_informations($command);
|
||||
|
||||
my $links = $self->_get_links ($filename, $element);
|
||||
|
||||
@@ -271,7 +223,7 @@ if ($program_version_6_8) {
|
||||
sub ffmpeg_end_file($)
|
||||
{
|
||||
my $self = shift;
|
||||
my $program_string = &{get_formatting_function($self,'format_program_string')}($self);
|
||||
my $program_string = &{$self->{'format_program_string'}}($self);
|
||||
my $program_text = <<EOT;
|
||||
<p style="font-size: small;">
|
||||
$program_string
|
||||
@@ -292,7 +244,7 @@ if ($program_version_6_8) {
|
||||
|
||||
# Dummy title command
|
||||
# Ignore title. Title is handled through ffmpeg_begin_file().
|
||||
ff_set_from_init_file('USE_TITLEPAGE_FOR_TITLE', 1);
|
||||
set_from_init_file('USE_TITLEPAGE_FOR_TITLE', 1);
|
||||
sub ffmpeg_title($$$$)
|
||||
{
|
||||
return '';
|
||||
@@ -310,14 +262,8 @@ sub ffmpeg_float($$$$$)
|
||||
my $args = shift;
|
||||
my $content = shift;
|
||||
|
||||
my ($caption, $prepended);
|
||||
if ($program_version_num >= 7.000000) {
|
||||
($caption, $prepended) = Texinfo::Convert::Converter::float_name_caption($self,
|
||||
$command);
|
||||
} else {
|
||||
($caption, $prepended) = Texinfo::Common::float_name_caption($self,
|
||||
$command);
|
||||
}
|
||||
my ($caption, $prepended) = Texinfo::Common::float_name_caption($self,
|
||||
$command);
|
||||
my $caption_text = '';
|
||||
my $prepended_text;
|
||||
my $prepended_save = '';
|
||||
@@ -389,13 +335,8 @@ sub ffmpeg_float($$$$$)
|
||||
$caption->{'args'}->[0], 'float caption');
|
||||
}
|
||||
if ($prepended_text.$caption_text ne '') {
|
||||
if ($program_version_num >= 7.000000) {
|
||||
$prepended_text = $self->html_attribute_class('div',['float-caption']). '>'
|
||||
. $prepended_text;
|
||||
} else {
|
||||
$prepended_text = $self->_attribute_class('div','float-caption'). '>'
|
||||
. $prepended_text;
|
||||
}
|
||||
$prepended_text = $self->_attribute_class('div','float-caption'). '>'
|
||||
. $prepended_text;
|
||||
$caption_text .= '</div>';
|
||||
}
|
||||
my $html_class = '';
|
||||
@@ -408,13 +349,8 @@ sub ffmpeg_float($$$$$)
|
||||
$prepended_text = '';
|
||||
$caption_text = '';
|
||||
}
|
||||
if ($program_version_num >= 7.000000) {
|
||||
return $self->html_attribute_class('div', [$html_class]). '>' . "\n" .
|
||||
$prepended_text . $caption_text . $content . '</div>';
|
||||
} else {
|
||||
return $self->_attribute_class('div', $html_class). '>' . "\n" .
|
||||
$prepended_text . $caption_text . $content . '</div>';
|
||||
}
|
||||
return $self->_attribute_class('div', $html_class). '>' . "\n" .
|
||||
$prepended_text . $caption_text . $content . '</div>';
|
||||
}
|
||||
|
||||
texinfo_register_command_formatting('float',
|
||||
|
||||
@@ -704,326 +704,3 @@ Also note that this function requires a special iteration way, due to coefficien
|
||||
beginning to overlap, particularly `[o1]` with `[0]` after the second iteration.
|
||||
To iterate further, set `z = &z[16]` via `z += 8` for the second iteration. After
|
||||
the 4th iteration, the layout resets, so repeat the same.
|
||||
|
||||
|
||||
# 15-point AVX FFT transform
|
||||
The 15-point transform is based on the following unrolling. The input
|
||||
must be permuted via the following loop:
|
||||
|
||||
``` C
|
||||
for (int k = 0; k < s->sub[0].len; k++) {
|
||||
int cnt = 0;
|
||||
int tmp[15];
|
||||
memcpy(tmp, &s->map[k*15], 15*sizeof(*tmp));
|
||||
for (int i = 1; i < 15; i += 3) {
|
||||
s->map[k*15 + cnt] = tmp[i];
|
||||
cnt++;
|
||||
}
|
||||
for (int i = 2; i < 15; i += 3) {
|
||||
s->map[k*15 + cnt] = tmp[i];
|
||||
cnt++;
|
||||
}
|
||||
for (int i = 0; i < 15; i += 3) {
|
||||
s->map[k*15 + cnt] = tmp[i];
|
||||
cnt++;
|
||||
}
|
||||
memmove(&s->map[k*15 + 7], &s->map[k*15 + 6], 4*sizeof(int));
|
||||
memmove(&s->map[k*15 + 3], &s->map[k*15 + 1], 4*sizeof(int));
|
||||
s->map[k*15 + 1] = tmp[2];
|
||||
s->map[k*15 + 2] = tmp[0];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This separates the ACs from the DCs and flips the SIMD direction to
|
||||
performing 5x3pt transforms at once, followed by 3x5pt transforms.
|
||||
|
||||
``` C
|
||||
static av_always_inline void fft15(TXComplex *out, TXComplex *in,
|
||||
ptrdiff_t stride)
|
||||
{
|
||||
const TXSample *tab = TX_TAB(ff_tx_tab_53);
|
||||
TXComplex q[20];
|
||||
TXComplex dc[3], pc[32];
|
||||
TXComplex y[32], k[32];
|
||||
TXComplex t[32];
|
||||
TXComplex r[32];
|
||||
TXComplex z0[32];
|
||||
|
||||
/* DC */
|
||||
pc[0].re = in[ 1].im - in[ 0].im;
|
||||
pc[0].im = in[ 1].re - in[ 0].re;
|
||||
pc[1].re = in[ 1].re + in[ 0].re;
|
||||
pc[1].im = in[ 1].im + in[ 0].im;
|
||||
|
||||
dc[0].re = in[2].re + pc[1].re;
|
||||
dc[0].im = in[2].im + pc[1].im;
|
||||
|
||||
pc[0].re = tab[ 8] * pc[0].re;
|
||||
pc[0].im = tab[ 9] * pc[0].im;
|
||||
pc[1].re = tab[10] * pc[1].re;
|
||||
pc[1].im = tab[11] * pc[1].im;
|
||||
|
||||
dc[1].re = pc[0].re + pc[1].re;
|
||||
dc[1].im = pc[0].im + pc[1].im;
|
||||
dc[2].re = pc[1].re - pc[0].re;
|
||||
dc[2].im = pc[1].im - pc[0].im;
|
||||
|
||||
dc[1].re = in[2].re - dc[1].re;
|
||||
dc[1].im = in[2].im + dc[1].im;
|
||||
dc[2].re = in[2].re - dc[2].re;
|
||||
dc[2].im = in[2].im + dc[2].im;
|
||||
|
||||
/* ACs */
|
||||
q[0].im = in[ 3].re - in[ 7].re; // NOTE THE ORDER
|
||||
q[0].re = in[ 3].im - in[ 7].im;
|
||||
q[1].im = in[ 4].re - in[ 8].re;
|
||||
q[1].re = in[ 4].im - in[ 8].im;
|
||||
q[2].im = in[ 5].re - in[ 9].re;
|
||||
q[2].re = in[ 5].im - in[ 9].im;
|
||||
q[3].re = in[ 6].im - in[10].im;
|
||||
q[3].im = in[ 6].re - in[10].re;
|
||||
|
||||
q[4].re = in[ 3].re + in[ 7].re;
|
||||
q[4].im = in[ 3].im + in[ 7].im;
|
||||
q[5].re = in[ 4].re + in[ 8].re;
|
||||
q[5].im = in[ 4].im + in[ 8].im;
|
||||
q[6].re = in[ 5].re + in[ 9].re;
|
||||
q[6].im = in[ 5].im + in[ 9].im;
|
||||
q[7].re = in[ 6].re + in[10].re;
|
||||
q[7].im = in[ 6].im + in[10].im;
|
||||
|
||||
y[0].re = in[11].re + q[4].re;
|
||||
y[0].im = in[11].im + q[4].im;
|
||||
y[1].re = in[12].re + q[5].re;
|
||||
y[1].im = in[12].im + q[5].im;
|
||||
y[2].re = in[13].re + q[6].re;
|
||||
y[2].im = in[13].im + q[6].im;
|
||||
y[3].re = in[14].re + q[7].re;
|
||||
y[3].im = in[14].im + q[7].im;
|
||||
|
||||
q[0].re = tab[ 8] * q[0].re;
|
||||
q[0].im = tab[ 9] * q[0].im;
|
||||
q[1].re = tab[ 8] * q[1].re;
|
||||
q[1].im = tab[ 9] * q[1].im;
|
||||
q[2].re = tab[ 8] * q[2].re;
|
||||
q[2].im = tab[ 9] * q[2].im;
|
||||
q[3].re = tab[ 8] * q[3].re;
|
||||
q[3].im = tab[ 9] * q[3].im;
|
||||
|
||||
q[4].re = tab[10] * q[4].re;
|
||||
q[4].im = tab[11] * q[4].im;
|
||||
q[5].re = tab[10] * q[5].re;
|
||||
q[5].im = tab[11] * q[5].im;
|
||||
q[6].re = tab[10] * q[6].re;
|
||||
q[6].im = tab[11] * q[6].im;
|
||||
q[7].re = tab[10] * q[7].re;
|
||||
q[7].im = tab[11] * q[7].im;
|
||||
|
||||
k[0].re = q[4].re - q[0].re;
|
||||
k[0].im = q[4].im - q[0].im;
|
||||
k[1].re = q[5].re - q[1].re;
|
||||
k[1].im = q[5].im - q[1].im;
|
||||
k[2].re = q[6].re - q[2].re;
|
||||
k[2].im = q[6].im - q[2].im;
|
||||
k[3].re = q[7].re - q[3].re;
|
||||
k[3].im = q[7].im - q[3].im;
|
||||
|
||||
k[4].re = q[4].re + q[0].re;
|
||||
k[4].im = q[4].im + q[0].im;
|
||||
k[5].re = q[5].re + q[1].re;
|
||||
k[5].im = q[5].im + q[1].im;
|
||||
k[6].re = q[6].re + q[2].re;
|
||||
k[6].im = q[6].im + q[2].im;
|
||||
k[7].re = q[7].re + q[3].re;
|
||||
k[7].im = q[7].im + q[3].im;
|
||||
|
||||
k[0].re = in[11].re - k[0].re;
|
||||
k[0].im = in[11].im + k[0].im;
|
||||
k[1].re = in[12].re - k[1].re;
|
||||
k[1].im = in[12].im + k[1].im;
|
||||
k[2].re = in[13].re - k[2].re;
|
||||
k[2].im = in[13].im + k[2].im;
|
||||
k[3].re = in[14].re - k[3].re;
|
||||
k[3].im = in[14].im + k[3].im;
|
||||
|
||||
k[4].re = in[11].re - k[4].re;
|
||||
k[4].im = in[11].im + k[4].im;
|
||||
k[5].re = in[12].re - k[5].re;
|
||||
k[5].im = in[12].im + k[5].im;
|
||||
k[6].re = in[13].re - k[6].re;
|
||||
k[6].im = in[13].im + k[6].im;
|
||||
k[7].re = in[14].re - k[7].re;
|
||||
k[7].im = in[14].im + k[7].im;
|
||||
|
||||
/* 15pt start here */
|
||||
t[0].re = y[3].re + y[0].re;
|
||||
t[0].im = y[3].im + y[0].im;
|
||||
t[1].re = y[2].re + y[1].re;
|
||||
t[1].im = y[2].im + y[1].im;
|
||||
t[2].re = y[1].re - y[2].re;
|
||||
t[2].im = y[1].im - y[2].im;
|
||||
t[3].re = y[0].re - y[3].re;
|
||||
t[3].im = y[0].im - y[3].im;
|
||||
|
||||
t[4].re = k[3].re + k[0].re;
|
||||
t[4].im = k[3].im + k[0].im;
|
||||
t[5].re = k[2].re + k[1].re;
|
||||
t[5].im = k[2].im + k[1].im;
|
||||
t[6].re = k[1].re - k[2].re;
|
||||
t[6].im = k[1].im - k[2].im;
|
||||
t[7].re = k[0].re - k[3].re;
|
||||
t[7].im = k[0].im - k[3].im;
|
||||
|
||||
t[ 8].re = k[7].re + k[4].re;
|
||||
t[ 8].im = k[7].im + k[4].im;
|
||||
t[ 9].re = k[6].re + k[5].re;
|
||||
t[ 9].im = k[6].im + k[5].im;
|
||||
t[10].re = k[5].re - k[6].re;
|
||||
t[10].im = k[5].im - k[6].im;
|
||||
t[11].re = k[4].re - k[7].re;
|
||||
t[11].im = k[4].im - k[7].im;
|
||||
|
||||
out[ 0*stride].re = dc[0].re + t[0].re + t[ 1].re;
|
||||
out[ 0*stride].im = dc[0].im + t[0].im + t[ 1].im;
|
||||
out[10*stride].re = dc[1].re + t[4].re + t[ 5].re;
|
||||
out[10*stride].im = dc[1].im + t[4].im + t[ 5].im;
|
||||
out[ 5*stride].re = dc[2].re + t[8].re + t[ 9].re;
|
||||
out[ 5*stride].im = dc[2].im + t[8].im + t[ 9].im;
|
||||
|
||||
r[0].re = t[0].re * tab[0];
|
||||
r[0].im = t[0].im * tab[1];
|
||||
r[1].re = t[1].re * tab[0];
|
||||
r[1].im = t[1].im * tab[1];
|
||||
r[2].re = t[2].re * tab[4];
|
||||
r[2].im = t[2].im * tab[5];
|
||||
r[3].re = t[3].re * tab[4];
|
||||
r[3].im = t[3].im * tab[5];
|
||||
|
||||
r[4].re = t[4].re * tab[0];
|
||||
r[4].im = t[4].im * tab[1];
|
||||
r[5].re = t[5].re * tab[0];
|
||||
r[5].im = t[5].im * tab[1];
|
||||
r[6].re = t[6].re * tab[4];
|
||||
r[6].im = t[6].im * tab[5];
|
||||
r[7].re = t[7].re * tab[4];
|
||||
r[7].im = t[7].im * tab[5];
|
||||
|
||||
r[ 8].re = t[ 8].re * tab[0];
|
||||
r[ 8].im = t[ 8].im * tab[1];
|
||||
r[ 9].re = t[ 9].re * tab[0];
|
||||
r[ 9].im = t[ 9].im * tab[1];
|
||||
r[10].re = t[10].re * tab[4];
|
||||
r[10].im = t[10].im * tab[5];
|
||||
r[11].re = t[11].re * tab[4];
|
||||
r[11].im = t[11].im * tab[5];
|
||||
|
||||
t[0].re = t[0].re * tab[2];
|
||||
t[0].im = t[0].im * tab[3];
|
||||
t[1].re = t[1].re * tab[2];
|
||||
t[1].im = t[1].im * tab[3];
|
||||
t[2].re = t[2].re * tab[6];
|
||||
t[2].im = t[2].im * tab[7];
|
||||
t[3].re = t[3].re * tab[6];
|
||||
t[3].im = t[3].im * tab[7];
|
||||
|
||||
t[4].re = t[4].re * tab[2];
|
||||
t[4].im = t[4].im * tab[3];
|
||||
t[5].re = t[5].re * tab[2];
|
||||
t[5].im = t[5].im * tab[3];
|
||||
t[6].re = t[6].re * tab[6];
|
||||
t[6].im = t[6].im * tab[7];
|
||||
t[7].re = t[7].re * tab[6];
|
||||
t[7].im = t[7].im * tab[7];
|
||||
|
||||
t[ 8].re = t[ 8].re * tab[2];
|
||||
t[ 8].im = t[ 8].im * tab[3];
|
||||
t[ 9].re = t[ 9].re * tab[2];
|
||||
t[ 9].im = t[ 9].im * tab[3];
|
||||
t[10].re = t[10].re * tab[6];
|
||||
t[10].im = t[10].im * tab[7];
|
||||
t[11].re = t[11].re * tab[6];
|
||||
t[11].im = t[11].im * tab[7];
|
||||
|
||||
r[0].re = r[0].re - t[1].re;
|
||||
r[0].im = r[0].im - t[1].im;
|
||||
r[1].re = r[1].re - t[0].re;
|
||||
r[1].im = r[1].im - t[0].im;
|
||||
r[2].re = r[2].re - t[3].re;
|
||||
r[2].im = r[2].im - t[3].im;
|
||||
r[3].re = r[3].re + t[2].re;
|
||||
r[3].im = r[3].im + t[2].im;
|
||||
|
||||
r[4].re = r[4].re - t[5].re;
|
||||
r[4].im = r[4].im - t[5].im;
|
||||
r[5].re = r[5].re - t[4].re;
|
||||
r[5].im = r[5].im - t[4].im;
|
||||
r[6].re = r[6].re - t[7].re;
|
||||
r[6].im = r[6].im - t[7].im;
|
||||
r[7].re = r[7].re + t[6].re;
|
||||
r[7].im = r[7].im + t[6].im;
|
||||
|
||||
r[ 8].re = r[ 8].re - t[ 9].re;
|
||||
r[ 8].im = r[ 8].im - t[ 9].im;
|
||||
r[ 9].re = r[ 9].re - t[ 8].re;
|
||||
r[ 9].im = r[ 9].im - t[ 8].im;
|
||||
r[10].re = r[10].re - t[11].re;
|
||||
r[10].im = r[10].im - t[11].im;
|
||||
r[11].re = r[11].re + t[10].re;
|
||||
r[11].im = r[11].im + t[10].im;
|
||||
|
||||
z0[ 0].re = r[ 3].im + r[ 0].re;
|
||||
z0[ 0].im = r[ 3].re + r[ 0].im;
|
||||
z0[ 1].re = r[ 2].im + r[ 1].re;
|
||||
z0[ 1].im = r[ 2].re + r[ 1].im;
|
||||
z0[ 2].re = r[ 1].im - r[ 2].re;
|
||||
z0[ 2].im = r[ 1].re - r[ 2].im;
|
||||
z0[ 3].re = r[ 0].im - r[ 3].re;
|
||||
z0[ 3].im = r[ 0].re - r[ 3].im;
|
||||
|
||||
z0[ 4].re = r[ 7].im + r[ 4].re;
|
||||
z0[ 4].im = r[ 7].re + r[ 4].im;
|
||||
z0[ 5].re = r[ 6].im + r[ 5].re;
|
||||
z0[ 5].im = r[ 6].re + r[ 5].im;
|
||||
z0[ 6].re = r[ 5].im - r[ 6].re;
|
||||
z0[ 6].im = r[ 5].re - r[ 6].im;
|
||||
z0[ 7].re = r[ 4].im - r[ 7].re;
|
||||
z0[ 7].im = r[ 4].re - r[ 7].im;
|
||||
|
||||
z0[ 8].re = r[11].im + r[ 8].re;
|
||||
z0[ 8].im = r[11].re + r[ 8].im;
|
||||
z0[ 9].re = r[10].im + r[ 9].re;
|
||||
z0[ 9].im = r[10].re + r[ 9].im;
|
||||
z0[10].re = r[ 9].im - r[10].re;
|
||||
z0[10].im = r[ 9].re - r[10].im;
|
||||
z0[11].re = r[ 8].im - r[11].re;
|
||||
z0[11].im = r[ 8].re - r[11].im;
|
||||
|
||||
out[ 6*stride].re = dc[0].re + z0[0].re;
|
||||
out[ 6*stride].im = dc[0].im + z0[3].re;
|
||||
out[12*stride].re = dc[0].re + z0[2].im;
|
||||
out[12*stride].im = dc[0].im + z0[1].im;
|
||||
out[ 3*stride].re = dc[0].re + z0[1].re;
|
||||
out[ 3*stride].im = dc[0].im + z0[2].re;
|
||||
out[ 9*stride].re = dc[0].re + z0[3].im;
|
||||
out[ 9*stride].im = dc[0].im + z0[0].im;
|
||||
|
||||
out[ 1*stride].re = dc[1].re + z0[4].re;
|
||||
out[ 1*stride].im = dc[1].im + z0[7].re;
|
||||
out[ 7*stride].re = dc[1].re + z0[6].im;
|
||||
out[ 7*stride].im = dc[1].im + z0[5].im;
|
||||
out[13*stride].re = dc[1].re + z0[5].re;
|
||||
out[13*stride].im = dc[1].im + z0[6].re;
|
||||
out[ 4*stride].re = dc[1].re + z0[7].im;
|
||||
out[ 4*stride].im = dc[1].im + z0[4].im;
|
||||
|
||||
out[11*stride].re = dc[2].re + z0[8].re;
|
||||
out[11*stride].im = dc[2].im + z0[11].re;
|
||||
out[ 2*stride].re = dc[2].re + z0[10].im;
|
||||
out[ 2*stride].im = dc[2].im + z0[9].im;
|
||||
out[ 8*stride].re = dc[2].re + z0[9].re;
|
||||
out[ 8*stride].im = dc[2].im + z0[10].re;
|
||||
out[14*stride].re = dc[2].re + z0[11].im;
|
||||
out[14*stride].im = dc[2].im + z0[8].im;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -695,8 +695,6 @@ FL+FR+FC+LFE+SL+SR
|
||||
FL+FR+FC+BC+SL+SR
|
||||
@item 6.0(front)
|
||||
FL+FR+FLC+FRC+SL+SR
|
||||
@item 3.1.2
|
||||
FL+FR+FC+LFE+TFL+TFR
|
||||
@item hexagonal
|
||||
FL+FR+FC+BL+BR+BC
|
||||
@item 6.1
|
||||
@@ -715,18 +713,8 @@ FL+FR+FC+LFE+BL+BR+SL+SR
|
||||
FL+FR+FC+LFE+BL+BR+FLC+FRC
|
||||
@item 7.1(wide-side)
|
||||
FL+FR+FC+LFE+FLC+FRC+SL+SR
|
||||
@item 5.1.2
|
||||
FL+FR+FC+LFE+BL+BR+TFL+TFR
|
||||
@item octagonal
|
||||
FL+FR+FC+BL+BR+BC+SL+SR
|
||||
@item cube
|
||||
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 hexadecagonal
|
||||
FL+FR+FC+BL+BR+BC+SL+SR+WL+WR+TBL+TBR+TBC+TFC+TFL+TFR
|
||||
@item downmix
|
||||
@@ -1085,13 +1073,13 @@ indication of the corresponding powers of 10 and of 2.
|
||||
@item T
|
||||
10^12 / 2^40
|
||||
@item P
|
||||
10^15 / 2^50
|
||||
10^15 / 2^40
|
||||
@item E
|
||||
10^18 / 2^60
|
||||
10^18 / 2^50
|
||||
@item Z
|
||||
10^21 / 2^70
|
||||
10^21 / 2^60
|
||||
@item Y
|
||||
10^24 / 2^80
|
||||
10^24 / 2^70
|
||||
@end table
|
||||
|
||||
@c man end EXPRESSION EVALUATION
|
||||
|
||||
@@ -15,7 +15,5 @@ OBJS-$(HAVE_LASX) += $(LASX-OBJS) $(LASX-OBJS-yes)
|
||||
OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes)
|
||||
OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes)
|
||||
|
||||
OBJS-$(HAVE_RVV) += $(RVV-OBJS) $(RVV-OBJS-yes)
|
||||
|
||||
OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes)
|
||||
OBJS-$(HAVE_X86ASM) += $(X86ASM-OBJS) $(X86ASM-OBJS-yes)
|
||||
|
||||
@@ -10,23 +10,13 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
|
||||
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
|
||||
|
||||
OBJS-ffmpeg += \
|
||||
fftools/ffmpeg_dec.o \
|
||||
fftools/ffmpeg_demux.o \
|
||||
fftools/ffmpeg_enc.o \
|
||||
fftools/ffmpeg_filter.o \
|
||||
fftools/ffmpeg_hw.o \
|
||||
fftools/ffmpeg_mux.o \
|
||||
fftools/ffmpeg_mux_init.o \
|
||||
fftools/ffmpeg_opt.o \
|
||||
fftools/objpool.o \
|
||||
fftools/sync_queue.o \
|
||||
fftools/thread_queue.o \
|
||||
|
||||
define DOFFTOOL
|
||||
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
|
||||
ifdef HAVE_GNU_WINDRES
|
||||
OBJS-$(1) += fftools/fftoolsres.o
|
||||
endif
|
||||
$(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
|
||||
$$(OBJS-$(1)): | fftools
|
||||
$$(OBJS-$(1)): CFLAGS += $(CFLAGS-$(1))
|
||||
|
||||
@@ -83,8 +83,23 @@ void init_dynload(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int parse_number(const char *context, const char *numstr, int type,
|
||||
double min, double max, double *dst)
|
||||
static void (*program_exit)(int ret);
|
||||
|
||||
void register_exit(void (*cb)(int ret))
|
||||
{
|
||||
program_exit = cb;
|
||||
}
|
||||
|
||||
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;
|
||||
const char *error;
|
||||
@@ -97,13 +112,23 @@ int parse_number(const char *context, const char *numstr, int type,
|
||||
error = "Expected int64 for %s but found %s\n";
|
||||
else if (type == OPT_INT && (int)d != d)
|
||||
error = "Expected int for %s but found %s\n";
|
||||
else {
|
||||
*dst = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
else
|
||||
return d;
|
||||
av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
|
||||
return AVERROR(EINVAL);
|
||||
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;
|
||||
}
|
||||
|
||||
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
@@ -231,8 +256,6 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
|
||||
void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ?
|
||||
(uint8_t *)optctx + po->u.off : po->u.dst_ptr;
|
||||
int *dstcount;
|
||||
double num;
|
||||
int ret;
|
||||
|
||||
if (po->flags & OPT_SPEC) {
|
||||
SpecifierOpt **so = dst;
|
||||
@@ -240,10 +263,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
|
||||
char *str;
|
||||
|
||||
dstcount = (int *)(so + 1);
|
||||
ret = grow_array((void**)so, sizeof(**so), dstcount, *dstcount + 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1);
|
||||
str = av_strdup(p ? p + 1 : "");
|
||||
if (!str)
|
||||
return AVERROR(ENOMEM);
|
||||
@@ -259,36 +279,15 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
|
||||
return AVERROR(ENOMEM);
|
||||
*(char **)dst = str;
|
||||
} else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
|
||||
ret = parse_number(opt, arg, OPT_INT64, INT_MIN, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*(int *)dst = num;
|
||||
*(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
|
||||
} else if (po->flags & OPT_INT64) {
|
||||
ret = parse_number(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*(int64_t *)dst = num;
|
||||
*(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX);
|
||||
} else if (po->flags & OPT_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);
|
||||
return ret;
|
||||
}
|
||||
*(int64_t *)dst = parse_time_or_die(opt, arg, 1);
|
||||
} else if (po->flags & OPT_FLOAT) {
|
||||
ret = parse_number(opt, arg, OPT_FLOAT, -INFINITY, INFINITY, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*(float *)dst = num;
|
||||
*(float *)dst = parse_number_or_die(opt, arg, OPT_FLOAT, -INFINITY, INFINITY);
|
||||
} else if (po->flags & OPT_DOUBLE) {
|
||||
ret = parse_number(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*(double *)dst = num;
|
||||
*(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY);
|
||||
} else if (po->u.func_arg) {
|
||||
int ret = po->u.func_arg(optctx, opt, arg);
|
||||
if (ret < 0) {
|
||||
@@ -299,7 +298,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
|
||||
}
|
||||
}
|
||||
if (po->flags & OPT_EXIT)
|
||||
return AVERROR_EXIT;
|
||||
exit_program(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -343,8 +342,8 @@ int parse_option(void *optctx, const char *opt, const char *arg,
|
||||
return !!(po->flags & HAS_ARG);
|
||||
}
|
||||
|
||||
int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
int (*parse_arg_function)(void *, const char*))
|
||||
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
void (*parse_arg_function)(void *, const char*))
|
||||
{
|
||||
const char *opt;
|
||||
int optindex, handleoptions = 1, ret;
|
||||
@@ -365,18 +364,13 @@ int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
opt++;
|
||||
|
||||
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
|
||||
return ret;
|
||||
exit_program(1);
|
||||
optindex += ret;
|
||||
} else {
|
||||
if (parse_arg_function) {
|
||||
ret = parse_arg_function(optctx, opt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (parse_arg_function)
|
||||
parse_arg_function(optctx, opt);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_optgroup(void *optctx, OptionGroup *g)
|
||||
@@ -512,7 +506,7 @@ static const AVOption *opt_find(void *obj, const char *name, const char *unit,
|
||||
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)
|
||||
{
|
||||
const AVOption *o;
|
||||
@@ -605,17 +599,13 @@ static int match_group_separator(const OptionGroupDef *groups, int nb_groups,
|
||||
* @param group_idx which group definition should this group belong to
|
||||
* @param arg argument of the group delimiting option
|
||||
*/
|
||||
static int finish_group(OptionParseContext *octx, int group_idx,
|
||||
const char *arg)
|
||||
static void finish_group(OptionParseContext *octx, int group_idx,
|
||||
const char *arg)
|
||||
{
|
||||
OptionGroupList *l = &octx->groups[group_idx];
|
||||
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 = octx->cur_group;
|
||||
@@ -632,33 +622,25 @@ static int finish_group(OptionParseContext *octx, int group_idx,
|
||||
swr_opts = NULL;
|
||||
|
||||
memset(&octx->cur_group, 0, sizeof(octx->cur_group));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an option instance to currently parsed group.
|
||||
*/
|
||||
static int add_opt(OptionParseContext *octx, const OptionDef *opt,
|
||||
const char *key, const char *val)
|
||||
static void add_opt(OptionParseContext *octx, const OptionDef *opt,
|
||||
const char *key, const char *val)
|
||||
{
|
||||
int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET));
|
||||
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].key = key;
|
||||
g->opts[g->nb_opts - 1].val = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_parse_context(OptionParseContext *octx,
|
||||
const OptionGroupDef *groups, int nb_groups)
|
||||
static void init_parse_context(OptionParseContext *octx,
|
||||
const OptionGroupDef *groups, int nb_groups)
|
||||
{
|
||||
static const OptionGroupDef global_group = { "global" };
|
||||
int i;
|
||||
@@ -668,15 +650,13 @@ static int init_parse_context(OptionParseContext *octx,
|
||||
octx->nb_groups = nb_groups;
|
||||
octx->groups = av_calloc(octx->nb_groups, sizeof(*octx->groups));
|
||||
if (!octx->groups)
|
||||
return AVERROR(ENOMEM);
|
||||
exit_program(1);
|
||||
|
||||
for (i = 0; i < octx->nb_groups; i++)
|
||||
octx->groups[i].group_def = &groups[i];
|
||||
|
||||
octx->global_opts.group_def = &global_group;
|
||||
octx->global_opts.arg = "";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uninit_parse_context(OptionParseContext *octx)
|
||||
@@ -708,17 +688,13 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[],
|
||||
const OptionDef *options,
|
||||
const OptionGroupDef *groups, int nb_groups)
|
||||
{
|
||||
int ret;
|
||||
int optindex = 1;
|
||||
int dashdash = -2;
|
||||
|
||||
/* perform system-dependent conversions for arguments list */
|
||||
prepare_app_arguments(&argc, &argv);
|
||||
|
||||
ret = init_parse_context(octx, groups, nb_groups);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
init_parse_context(octx, groups, nb_groups);
|
||||
av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");
|
||||
|
||||
while (optindex < argc) {
|
||||
@@ -734,10 +710,7 @@ int split_commandline(OptionParseContext *octx, int argc, char *argv[],
|
||||
}
|
||||
/* unnamed group separators, e.g. output filename */
|
||||
if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) {
|
||||
ret = finish_group(octx, 0, opt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
finish_group(octx, 0, opt);
|
||||
av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name);
|
||||
continue;
|
||||
}
|
||||
@@ -755,10 +728,7 @@ do { \
|
||||
/* named group separators, e.g. -i */
|
||||
if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
|
||||
GET_ARG(arg);
|
||||
ret = finish_group(octx, ret, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
finish_group(octx, ret, arg);
|
||||
av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
|
||||
groups[ret].name, arg);
|
||||
continue;
|
||||
@@ -776,10 +746,7 @@ do { \
|
||||
arg = "1";
|
||||
}
|
||||
|
||||
ret = add_opt(octx, po, opt, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
add_opt(octx, po, opt, arg);
|
||||
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
|
||||
"argument '%s'.\n", po->name, po->help, arg);
|
||||
continue;
|
||||
@@ -804,10 +771,7 @@ do { \
|
||||
if (opt[0] == 'n' && opt[1] == 'o' &&
|
||||
(po = find_option(options, opt + 2)) &&
|
||||
po->name && po->flags & OPT_BOOL) {
|
||||
ret = add_opt(octx, po, opt, "0");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
add_opt(octx, po, opt, "0");
|
||||
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
|
||||
"argument 0.\n", po->name, po->help);
|
||||
continue;
|
||||
@@ -828,7 +792,12 @@ do { \
|
||||
|
||||
void print_error(const char *filename, int err)
|
||||
{
|
||||
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, av_err2str(err));
|
||||
char errbuf[128];
|
||||
const char *errbuf_ptr = errbuf;
|
||||
|
||||
if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
|
||||
errbuf_ptr = strerror(AVUNERROR(err));
|
||||
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
|
||||
}
|
||||
|
||||
int read_yesno(void)
|
||||
@@ -922,9 +891,8 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
||||
AVDictionary **dst)
|
||||
AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec)
|
||||
{
|
||||
AVDictionary *ret = NULL;
|
||||
const AVDictionaryEntry *t = NULL;
|
||||
@@ -952,21 +920,17 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
break;
|
||||
}
|
||||
|
||||
while (t = av_dict_iterate(opts, t)) {
|
||||
while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) {
|
||||
const AVClass *priv_class;
|
||||
char *p = strchr(t->key, ':');
|
||||
|
||||
/* check stream specification in opt name */
|
||||
if (p) {
|
||||
int err = check_stream_specifier(s, st, p + 1);
|
||||
if (err < 0) {
|
||||
av_dict_free(&ret);
|
||||
return err;
|
||||
} else if (!err)
|
||||
continue;
|
||||
|
||||
*p = 0;
|
||||
}
|
||||
if (p)
|
||||
switch (check_stream_specifier(s, st, p + 1)) {
|
||||
case 1: *p = 0; break;
|
||||
case 0: continue;
|
||||
default: exit_program(1);
|
||||
}
|
||||
|
||||
if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
|
||||
!codec ||
|
||||
@@ -982,58 +946,46 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
if (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;
|
||||
}
|
||||
|
||||
int grow_array(void **array, int elem_size, int *size, int new_size)
|
||||
AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
|
||||
AVDictionary *codec_opts)
|
||||
{
|
||||
int i;
|
||||
AVDictionary **opts;
|
||||
|
||||
if (!s->nb_streams)
|
||||
return NULL;
|
||||
opts = av_calloc(s->nb_streams, sizeof(*opts));
|
||||
if (!opts) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Could not alloc memory for stream options.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
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) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
|
||||
return AVERROR(ERANGE);
|
||||
exit_program(1);
|
||||
}
|
||||
if (*size < new_size) {
|
||||
uint8_t *tmp = av_realloc_array(*array, new_size, elem_size);
|
||||
if (!tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
uint8_t *tmp = av_realloc_array(array, new_size, elem_size);
|
||||
if (!tmp) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
|
||||
*size = new_size;
|
||||
*array = tmp;
|
||||
return 0;
|
||||
return tmp;
|
||||
}
|
||||
return 0;
|
||||
return array;
|
||||
}
|
||||
|
||||
void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems)
|
||||
@@ -1041,12 +993,14 @@ void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems)
|
||||
void *new_elem;
|
||||
|
||||
if (!(new_elem = av_mallocz(elem_size)) ||
|
||||
av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0)
|
||||
return NULL;
|
||||
av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
return new_elem;
|
||||
}
|
||||
|
||||
double get_rotation(const int32_t *displaymatrix)
|
||||
double get_rotation(int32_t *displaymatrix)
|
||||
{
|
||||
double theta = 0;
|
||||
if (displaymatrix)
|
||||
|
||||
@@ -49,6 +49,16 @@ extern AVDictionary *swr_opts;
|
||||
extern AVDictionary *format_opts, *codec_opts;
|
||||
extern int hide_banner;
|
||||
|
||||
/**
|
||||
* Register a program-specific cleanup routine.
|
||||
*/
|
||||
void register_exit(void (*cb)(int ret));
|
||||
|
||||
/**
|
||||
* Wraps exit with a program-specific cleanup routine.
|
||||
*/
|
||||
void exit_program(int ret) av_noreturn;
|
||||
|
||||
/**
|
||||
* Initialize dynamic library loading
|
||||
*/
|
||||
@@ -79,6 +89,8 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* corresponding command line option name)
|
||||
@@ -88,8 +100,25 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg);
|
||||
* @param min the minimum valid accepted value
|
||||
* @param max the maximum valid accepted value
|
||||
*/
|
||||
int parse_number(const char *context, const char *numstr, int type,
|
||||
double min, double max, double *dst);
|
||||
double parse_number_or_die(const char *context, const char *numstr, int type,
|
||||
double min, double max);
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
char *specifier; /**< stream/chapter/program/... specifier */
|
||||
@@ -173,8 +202,8 @@ void show_help_default(const char *opt, const char *arg);
|
||||
* argument without a leading option name flag. NULL if such arguments do
|
||||
* not have to be processed.
|
||||
*/
|
||||
int parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
int (* parse_arg_function)(void *optctx, const char*));
|
||||
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options,
|
||||
void (* parse_arg_function)(void *optctx, const char*));
|
||||
|
||||
/**
|
||||
* Parse one given option.
|
||||
@@ -312,12 +341,10 @@ 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 codec The particular codec for which the options should be filtered.
|
||||
* If null, the default one is looked up according to the codec id.
|
||||
* @param dst a pointer to the created dictionary
|
||||
* @return a non-negative number on success, a negative error code on failure
|
||||
* @return a pointer to the created dictionary
|
||||
*/
|
||||
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
||||
AVDictionary **dst);
|
||||
AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
|
||||
AVFormatContext *s, AVStream *st, const AVCodec *codec);
|
||||
|
||||
/**
|
||||
* Setup AVCodecContext options for avformat_find_stream_info().
|
||||
@@ -326,10 +353,12 @@ int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||
* contained in s.
|
||||
* Each dictionary will contain the options from codec_opts which can
|
||||
* be applied to the corresponding stream codec context.
|
||||
*
|
||||
* @return pointer to the created array of dictionaries.
|
||||
* Calls exit() on failure.
|
||||
*/
|
||||
int setup_find_stream_info_opts(AVFormatContext *s,
|
||||
AVDictionary *codec_opts,
|
||||
AVDictionary ***dst);
|
||||
AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
|
||||
AVDictionary *codec_opts);
|
||||
|
||||
/**
|
||||
* Print an error message to stderr, indicating filename and a human
|
||||
@@ -378,31 +407,35 @@ FILE *get_preset_file(char *filename, size_t filename_size,
|
||||
|
||||
/**
|
||||
* Realloc array to hold new_size elements of elem_size.
|
||||
* Calls exit() on failure.
|
||||
*
|
||||
* @param array pointer to the array to reallocate, will be updated
|
||||
* with a new pointer on success
|
||||
* @param array array to reallocate
|
||||
* @param elem_size size in bytes of each element
|
||||
* @param size new element count will be written here
|
||||
* @param new_size number of elements to place in reallocated array
|
||||
* @return a non-negative number on success, a negative error code on failure
|
||||
* @return reallocated array
|
||||
*/
|
||||
int grow_array(void **array, int elem_size, int *size, int new_size);
|
||||
void *grow_array(void *array, int elem_size, int *size, int new_size);
|
||||
|
||||
/**
|
||||
* Atomically add a new element to an array of pointers, i.e. allocate
|
||||
* a new entry, reallocate the array of pointers and make the new last
|
||||
* member of this array point to the newly allocated buffer.
|
||||
* Calls exit() on failure.
|
||||
*
|
||||
* @param array array of pointers to reallocate
|
||||
* @param elem_size size of the new element to allocate
|
||||
* @param nb_elems pointer to the number of elements of the array array;
|
||||
* *nb_elems will be incremented by one by this function.
|
||||
* @return pointer to the newly allocated entry or NULL on failure
|
||||
* @return pointer to the newly allocated entry
|
||||
*/
|
||||
void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
|
||||
|
||||
#define GROW_ARRAY(array, nb_elems)\
|
||||
grow_array((void**)&array, sizeof(*array), &nb_elems, nb_elems + 1)
|
||||
array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1)
|
||||
|
||||
#define ALLOC_ARRAY_ELEM(array, nb_elems)\
|
||||
allocate_array_elem(&array, sizeof(*array[0]), &nb_elems)
|
||||
|
||||
#define GET_PIX_FMT_NAME(pix_fmt)\
|
||||
const char *name = av_get_pix_fmt_name(pix_fmt);
|
||||
@@ -417,6 +450,6 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
|
||||
char name[16];\
|
||||
snprintf(name, sizeof(name), "%d", rate);
|
||||
|
||||
double get_rotation(const int32_t *displaymatrix);
|
||||
double get_rotation(int32_t *displaymatrix);
|
||||
|
||||
#endif /* FFTOOLS_CMDUTILS_H */
|
||||
|
||||
4051
fftools/ffmpeg.c
4051
fftools/ffmpeg.c
File diff suppressed because it is too large
Load Diff
699
fftools/ffmpeg.h
699
fftools/ffmpeg.h
File diff suppressed because it is too large
Load Diff
1145
fftools/ffmpeg_dec.c
1145
fftools/ffmpeg_dec.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,888 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ffmpeg.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/timestamp.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
struct Encoder {
|
||||
AVFrame *sq_frame;
|
||||
|
||||
// packet for receiving encoded output
|
||||
AVPacket *pkt;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
void enc_free(Encoder **penc)
|
||||
{
|
||||
Encoder *enc = *penc;
|
||||
|
||||
if (!enc)
|
||||
return;
|
||||
|
||||
av_frame_free(&enc->sq_frame);
|
||||
|
||||
av_packet_free(&enc->pkt);
|
||||
|
||||
av_freep(penc);
|
||||
}
|
||||
|
||||
int enc_alloc(Encoder **penc, const AVCodec *codec)
|
||||
{
|
||||
Encoder *enc;
|
||||
|
||||
*penc = NULL;
|
||||
|
||||
enc = av_mallocz(sizeof(*enc));
|
||||
if (!enc)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
enc->pkt = av_packet_alloc();
|
||||
if (!enc->pkt)
|
||||
goto fail;
|
||||
|
||||
*penc = enc;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
enc_free(&enc);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
static int hw_device_setup_for_encode(OutputStream *ost, AVBufferRef *frames_ref)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
HWDevice *dev = NULL;
|
||||
int i;
|
||||
|
||||
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 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(OutputStream *ost, const AVFrame *frame)
|
||||
{
|
||||
InputStream *ist = ost->ist;
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc_ctx = ost->enc_ctx;
|
||||
AVCodecContext *dec_ctx = NULL;
|
||||
const AVCodec *enc = enc_ctx->codec;
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
FrameData *fd;
|
||||
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(output_files[ost->file_index], ost);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ist) {
|
||||
dec_ctx = ist->dec_ctx;
|
||||
}
|
||||
|
||||
// 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:
|
||||
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: {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
if (dec_ctx && dec_ctx->subtitle_header) {
|
||||
/* ASS code assumes this buffer is null terminated so add extra byte. */
|
||||
enc_ctx->subtitle_header = av_mallocz(dec_ctx->subtitle_header_size + 1);
|
||||
if (!enc_ctx->subtitle_header)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(enc_ctx->subtitle_header, dec_ctx->subtitle_header,
|
||||
dec_ctx->subtitle_header_size);
|
||||
enc_ctx->subtitle_header_size = dec_ctx->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->sq_idx_encode >= 0) {
|
||||
e->sq_frame = av_frame_alloc();
|
||||
if (!e->sq_frame)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
if (ost->enc_ctx->frame_size) {
|
||||
av_assert0(ost->sq_idx_encode >= 0);
|
||||
sq_frame_samples(output_files[ost->file_index]->sq_encode,
|
||||
ost->sq_idx_encode, 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) {
|
||||
int i;
|
||||
for (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 0;
|
||||
}
|
||||
|
||||
static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
|
||||
if (of->recording_time != INT64_MAX &&
|
||||
av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) {
|
||||
close_output_stream(ost);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int enc_subtitle(OutputFile *of, OutputStream *ost, const AVSubtitle *sub)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
int subtitle_out_max_size = 1024 * 1024;
|
||||
int subtitle_out_size, nb, i, ret;
|
||||
AVCodecContext *enc;
|
||||
AVPacket *pkt = e->pkt;
|
||||
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 (ost->finished ||
|
||||
(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 (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE)
|
||||
pts -= output_files[ost->file_index]->start_time;
|
||||
for (i = 0; i < nb; i++) {
|
||||
AVSubtitle local_sub = *sub;
|
||||
|
||||
if (!check_recording_time(ost, pts, AV_TIME_BASE_Q))
|
||||
return 0;
|
||||
|
||||
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 = of_output_packet(of, ost, pkt);
|
||||
if (ret < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ost->quality = sd ? AV_RL32(sd) : -1;
|
||||
pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
|
||||
|
||||
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,
|
||||
ost->quality / (float)FF_QP2LAMBDA);
|
||||
} else {
|
||||
fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number,
|
||||
ost->quality / (float)FF_QP2LAMBDA);
|
||||
}
|
||||
|
||||
if (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.0fkB 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)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
AVPacket *pkt = e->pkt;
|
||||
const char *type_desc = av_get_media_type_string(enc->codec_type);
|
||||
const char *action = frame ? "encode" : "flush";
|
||||
int ret;
|
||||
|
||||
if (frame) {
|
||||
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) {
|
||||
av_packet_unref(pkt);
|
||||
|
||||
ret = avcodec_receive_packet(enc, pkt);
|
||||
update_benchmark("%s_%s %d.%d", action, type_desc,
|
||||
ost->file_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 == AVERROR_EOF) {
|
||||
ret = of_output_packet(of, ost, NULL);
|
||||
return ret < 0 ? ret : AVERROR_EOF;
|
||||
} else if (ret < 0) {
|
||||
av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
if ((ret = trigger_fix_sub_duration_heartbeat(ost, pkt)) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Subtitle heartbeat logic failed in %s! (%s)\n",
|
||||
__func__, av_err2str(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
e->data_size += pkt->size;
|
||||
|
||||
e->packets_encoded++;
|
||||
|
||||
ret = of_output_packet(of, ost, pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
av_assert0(0);
|
||||
}
|
||||
|
||||
static int submit_encode_frame(OutputFile *of, OutputStream *ost,
|
||||
AVFrame *frame)
|
||||
{
|
||||
Encoder *e = ost->enc;
|
||||
int ret;
|
||||
|
||||
if (ost->sq_idx_encode < 0)
|
||||
return encode_frame(of, ost, frame);
|
||||
|
||||
if (frame) {
|
||||
ret = av_frame_ref(e->sq_frame, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
frame = e->sq_frame;
|
||||
}
|
||||
|
||||
ret = sq_send(of->sq_encode, ost->sq_idx_encode,
|
||||
SQFRAME(frame));
|
||||
if (ret < 0) {
|
||||
if (frame)
|
||||
av_frame_unref(frame);
|
||||
if (ret != AVERROR_EOF)
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
AVFrame *enc_frame = e->sq_frame;
|
||||
|
||||
ret = sq_receive(of->sq_encode, ost->sq_idx_encode,
|
||||
SQFRAME(enc_frame));
|
||||
if (ret == AVERROR_EOF) {
|
||||
enc_frame = NULL;
|
||||
} else if (ret < 0) {
|
||||
return (ret == AVERROR(EAGAIN)) ? 0 : ret;
|
||||
}
|
||||
|
||||
ret = encode_frame(of, ost, enc_frame);
|
||||
if (enc_frame)
|
||||
av_frame_unref(enc_frame);
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_EOF)
|
||||
close_output_stream(ost);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int do_audio_out(OutputFile *of, OutputStream *ost,
|
||||
AVFrame *frame)
|
||||
{
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
int ret;
|
||||
|
||||
if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
|
||||
enc->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;
|
||||
}
|
||||
|
||||
if (!check_recording_time(ost, frame->pts, frame->time_base))
|
||||
return 0;
|
||||
|
||||
ret = submit_encode_frame(of, ost, frame);
|
||||
return (ret < 0 && ret != AVERROR_EOF) ? ret : 0;
|
||||
}
|
||||
|
||||
static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
|
||||
AVRational tb, const AVFrame *in_picture)
|
||||
{
|
||||
double pts_time;
|
||||
|
||||
if (kf->ref_pts == AV_NOPTS_VALUE)
|
||||
kf->ref_pts = in_picture->pts;
|
||||
|
||||
pts_time = (in_picture->pts - kf->ref_pts) * av_q2d(tb);
|
||||
if (kf->index < kf->nb_pts &&
|
||||
av_compare_ts(in_picture->pts, tb, 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 && (in_picture->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;
|
||||
}
|
||||
|
||||
/* May modify/reset frame */
|
||||
static int do_video_out(OutputFile *of, OutputStream *ost, AVFrame *in_picture)
|
||||
{
|
||||
int ret;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
|
||||
if (!check_recording_time(ost, in_picture->pts, ost->enc_ctx->time_base))
|
||||
return 0;
|
||||
|
||||
in_picture->quality = enc->global_quality;
|
||||
in_picture->pict_type = forced_kf_apply(ost, &ost->kf, enc->time_base, in_picture);
|
||||
|
||||
#if FFMPEG_OPT_TOP
|
||||
if (ost->top_field_first >= 0) {
|
||||
in_picture->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
|
||||
in_picture->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * (!!ost->top_field_first);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = submit_encode_frame(of, ost, in_picture);
|
||||
return (ret == AVERROR_EOF) ? 0 : ret;
|
||||
}
|
||||
|
||||
int enc_frame(OutputStream *ost, AVFrame *frame)
|
||||
{
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
int ret;
|
||||
|
||||
ret = enc_open(ost, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ?
|
||||
do_video_out(of, ost, frame) : do_audio_out(of, ost, frame);
|
||||
}
|
||||
|
||||
int enc_flush(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
if (ost->sq_idx_encode >= 0)
|
||||
sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL));
|
||||
}
|
||||
|
||||
for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
|
||||
Encoder *e = ost->enc;
|
||||
AVCodecContext *enc = ost->enc_ctx;
|
||||
OutputFile *of = output_files[ost->file_index];
|
||||
|
||||
if (!enc || !e->opened ||
|
||||
(enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO))
|
||||
continue;
|
||||
|
||||
ret = submit_encode_frame(of, ost, NULL);
|
||||
if (ret != AVERROR_EOF)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@
|
||||
static int nb_hw_devices;
|
||||
static HWDevice **hw_devices;
|
||||
|
||||
HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
|
||||
static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
|
||||
{
|
||||
HWDevice *found = NULL;
|
||||
int i;
|
||||
@@ -242,9 +242,9 @@ fail:
|
||||
goto done;
|
||||
}
|
||||
|
||||
int hw_device_init_from_type(enum AVHWDeviceType type,
|
||||
const char *device,
|
||||
HWDevice **dev_out)
|
||||
static int hw_device_init_from_type(enum AVHWDeviceType type,
|
||||
const char *device,
|
||||
HWDevice **dev_out)
|
||||
{
|
||||
AVBufferRef *device_ref = NULL;
|
||||
HWDevice *dev;
|
||||
@@ -297,7 +297,207 @@ void hw_device_free_all(void)
|
||||
nb_hw_devices = 0;
|
||||
}
|
||||
|
||||
int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
|
||||
static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
|
||||
{
|
||||
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(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
|
||||
"specified for decoder: device %s of type %s is not "
|
||||
"usable with hwaccel %s.\n", dev->name,
|
||||
av_hwdevice_get_type_name(dev->type),
|
||||
av_hwdevice_get_type_name(ist->hwaccel_device_type));
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ist->hwaccel_id == HWACCEL_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(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with existing device %s.\n",
|
||||
av_hwdevice_get_type_name(type), dev->name);
|
||||
}
|
||||
}
|
||||
for (i = 0; !dev; i++) {
|
||||
config = avcodec_get_hw_config(ist->dec, i);
|
||||
if (!config)
|
||||
break;
|
||||
type = config->device_type;
|
||||
// Try to make a new device of this type.
|
||||
err = hw_device_init_from_type(type, ist->hwaccel_device,
|
||||
&dev);
|
||||
if (err < 0) {
|
||||
// Can't make a device of this type.
|
||||
continue;
|
||||
}
|
||||
if (ist->hwaccel_device) {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new device created "
|
||||
"from %s.\n", av_hwdevice_get_type_name(type),
|
||||
ist->hwaccel_device);
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new default device.\n",
|
||||
av_hwdevice_get_type_name(type));
|
||||
}
|
||||
}
|
||||
if (dev) {
|
||||
ist->hwaccel_device_type = type;
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
|
||||
"disabled: no device found.\n");
|
||||
ist->hwaccel_id = HWACCEL_NONE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
av_log(ist->dec_ctx, AV_LOG_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, i);
|
||||
if (!config)
|
||||
break;
|
||||
|
||||
if (frames_ref &&
|
||||
config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX &&
|
||||
(config->pix_fmt == AV_PIX_FMT_NONE ||
|
||||
config->pix_fmt == ost->enc_ctx->pix_fmt)) {
|
||||
av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input "
|
||||
"frames context (format %s) with %s encoder.\n",
|
||||
av_get_pix_fmt_name(ost->enc_ctx->pix_fmt),
|
||||
ost->enc->name);
|
||||
ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref);
|
||||
if (!ost->enc_ctx->hw_frames_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev &&
|
||||
config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)
|
||||
dev = hw_device_get_by_type(config->device_type);
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s "
|
||||
"(type %s) with %s encoder.\n", dev->name,
|
||||
av_hwdevice_get_type_name(dev->type), ost->enc->name);
|
||||
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
|
||||
if (!ost->enc_ctx->hw_device_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
} 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;
|
||||
@@ -339,14 +539,26 @@ fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
AVBufferRef *hw_device_for_filter(void)
|
||||
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
|
||||
// filters explicitly with the filter_hw_device option.
|
||||
if (filter_hw_device)
|
||||
return filter_hw_device->device_ref;
|
||||
dev = filter_hw_device;
|
||||
else if (nb_hw_devices > 0) {
|
||||
HWDevice *dev = hw_devices[nb_hw_devices - 1];
|
||||
dev = hw_devices[nb_hw_devices - 1];
|
||||
|
||||
if (nb_hw_devices > 1)
|
||||
av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
|
||||
@@ -355,9 +567,17 @@ AVBufferRef *hw_device_for_filter(void)
|
||||
"%s is not usable for filters.\n",
|
||||
nb_hw_devices, dev->name,
|
||||
av_hwdevice_get_type_name(dev->type), dev->name);
|
||||
} else
|
||||
dev = NULL;
|
||||
|
||||
return dev->device_ref;
|
||||
if (dev) {
|
||||
for (i = 0; i < fg->graph->nb_filters; i++) {
|
||||
fg->graph->filters[i]->hw_device_ctx =
|
||||
av_buffer_ref(dev->device_ref);
|
||||
if (!fg->graph->filters[i]->hw_device_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Muxer internal APIs - should not be included outside of ffmpeg_mux*
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General 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_MUX_H
|
||||
#define FFTOOLS_FFMPEG_MUX_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "thread_queue.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
#include "libavcodec/packet.h"
|
||||
|
||||
#include "libavutil/dict.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
typedef struct MuxStream {
|
||||
OutputStream ost;
|
||||
|
||||
// name used for logging
|
||||
char log_name[32];
|
||||
|
||||
/* the packets are buffered here until the muxer is ready to be initialized */
|
||||
AVFifo *muxing_queue;
|
||||
|
||||
AVBSFContext *bsf_ctx;
|
||||
AVPacket *bsf_pkt;
|
||||
|
||||
AVPacket *pkt;
|
||||
|
||||
EncStats stats;
|
||||
|
||||
int64_t max_frames;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* Threshold after which max_muxing_queue_size will be in effect */
|
||||
size_t muxing_queue_data_threshold;
|
||||
|
||||
// timestamp from which the streamcopied streams should start,
|
||||
// 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
|
||||
* used for making up missing dts values */
|
||||
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;
|
||||
|
||||
typedef struct Muxer {
|
||||
OutputFile of;
|
||||
|
||||
// name used for logging
|
||||
char log_name[32];
|
||||
|
||||
AVFormatContext *fc;
|
||||
|
||||
pthread_t thread;
|
||||
ThreadQueue *tq;
|
||||
|
||||
AVDictionary *opts;
|
||||
|
||||
int thread_queue_size;
|
||||
|
||||
/* filesize limit expressed in bytes */
|
||||
int64_t limit_filesize;
|
||||
atomic_int_least64_t last_filesize;
|
||||
int header_written;
|
||||
|
||||
SyncQueue *sq_mux;
|
||||
AVPacket *sq_pkt;
|
||||
} Muxer;
|
||||
|
||||
/* whether we want to print an SDP, set in of_open() */
|
||||
extern int want_sdp;
|
||||
|
||||
int mux_check_init(Muxer *mux);
|
||||
|
||||
static MuxStream *ms_from_ost(OutputStream *ost)
|
||||
{
|
||||
return (MuxStream*)ost;
|
||||
}
|
||||
|
||||
#endif /* FFTOOLS_FFMPEG_MUX_H */
|
||||
File diff suppressed because it is too large
Load Diff
2722
fftools/ffmpeg_opt.c
2722
fftools/ffmpeg_opt.c
File diff suppressed because it is too large
Load Diff
269
fftools/ffplay.c
269
fftools/ffplay.c
@@ -47,12 +47,14 @@
|
||||
#include "libavdevice/avdevice.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/tx.h"
|
||||
#include "libavcodec/avfft.h"
|
||||
#include "libswresample/swresample.h"
|
||||
|
||||
#include "libavfilter/avfilter.h"
|
||||
#include "libavfilter/buffersink.h"
|
||||
#include "libavfilter/buffersrc.h"
|
||||
#if CONFIG_AVFILTER
|
||||
# include "libavfilter/avfilter.h"
|
||||
# include "libavfilter/buffersink.h"
|
||||
# include "libavfilter/buffersrc.h"
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
@@ -107,6 +109,8 @@ const int program_birth_year = 2003;
|
||||
|
||||
#define USE_ONEPASS_SUBTITLE_RENDER 1
|
||||
|
||||
static unsigned sws_flags = SWS_BICUBIC;
|
||||
|
||||
typedef struct MyAVPacketList {
|
||||
AVPacket *pkt;
|
||||
int serial;
|
||||
@@ -146,10 +150,6 @@ typedef struct Clock {
|
||||
int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
|
||||
} Clock;
|
||||
|
||||
typedef struct FrameData {
|
||||
int64_t pkt_pos;
|
||||
} FrameData;
|
||||
|
||||
/* Common struct for handling all types of decoded data and allocated render buffers. */
|
||||
typedef struct Frame {
|
||||
AVFrame *frame;
|
||||
@@ -250,7 +250,9 @@ typedef struct VideoState {
|
||||
int audio_volume;
|
||||
int muted;
|
||||
struct AudioParams audio_src;
|
||||
#if CONFIG_AVFILTER
|
||||
struct AudioParams audio_filter_src;
|
||||
#endif
|
||||
struct AudioParams audio_tgt;
|
||||
struct SwrContext *swr_ctx;
|
||||
int frame_drops_early;
|
||||
@@ -262,11 +264,9 @@ typedef struct VideoState {
|
||||
int16_t sample_array[SAMPLE_ARRAY_SIZE];
|
||||
int sample_array_index;
|
||||
int last_i_start;
|
||||
AVTXContext *rdft;
|
||||
av_tx_fn rdft_fn;
|
||||
RDFTContext *rdft;
|
||||
int rdft_bits;
|
||||
float *real_data;
|
||||
AVComplexFloat *rdft_data;
|
||||
FFTSample *rdft_data;
|
||||
int xpos;
|
||||
double last_vis_time;
|
||||
SDL_Texture *vis_texture;
|
||||
@@ -284,6 +284,7 @@ typedef struct VideoState {
|
||||
AVStream *video_st;
|
||||
PacketQueue videoq;
|
||||
double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
|
||||
struct SwsContext *img_convert_ctx;
|
||||
struct SwsContext *sub_convert_ctx;
|
||||
int eof;
|
||||
|
||||
@@ -291,12 +292,14 @@ typedef struct VideoState {
|
||||
int width, height, xleft, ytop;
|
||||
int step;
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
int vfilter_idx;
|
||||
AVFilterContext *in_video_filter; // the first filter in the video chain
|
||||
AVFilterContext *out_video_filter; // the last filter in the video chain
|
||||
AVFilterContext *in_audio_filter; // the first filter in the audio chain
|
||||
AVFilterContext *out_audio_filter; // the last filter in the audio chain
|
||||
AVFilterGraph *agraph; // audio filter graph
|
||||
#endif
|
||||
|
||||
int last_video_stream, last_audio_stream, last_subtitle_stream;
|
||||
|
||||
@@ -344,9 +347,11 @@ static const char *video_codec_name;
|
||||
double rdftspeed = 0.02;
|
||||
static int64_t cursor_last_shown;
|
||||
static int cursor_hidden = 0;
|
||||
#if CONFIG_AVFILTER
|
||||
static const char **vfilters_list = NULL;
|
||||
static int nb_vfilters = 0;
|
||||
static char *afilters = NULL;
|
||||
#endif
|
||||
static int autorotate = 1;
|
||||
static int find_stream_info = 1;
|
||||
static int filter_nbthreads = 0;
|
||||
@@ -388,15 +393,14 @@ static const struct TextureFormatEntry {
|
||||
{ AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN },
|
||||
};
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
int ret = GROW_ARRAY(vfilters_list, nb_vfilters);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
GROW_ARRAY(vfilters_list, nb_vfilters);
|
||||
vfilters_list[nb_vfilters - 1] = arg;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
|
||||
@@ -649,16 +653,6 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
|
||||
}
|
||||
av_packet_unref(d->pkt);
|
||||
} else {
|
||||
if (d->pkt->buf && !d->pkt->opaque_ref) {
|
||||
FrameData *fd;
|
||||
|
||||
d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd));
|
||||
if (!d->pkt->opaque_ref)
|
||||
return AVERROR(ENOMEM);
|
||||
fd = (FrameData*)d->pkt->opaque_ref->data;
|
||||
fd->pkt_pos = d->pkt->pos;
|
||||
}
|
||||
|
||||
if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
|
||||
av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
|
||||
d->packet_pending = 1;
|
||||
@@ -701,7 +695,7 @@ static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void frame_queue_destroy(FrameQueue *f)
|
||||
static void frame_queue_destory(FrameQueue *f)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < f->max_size; i++) {
|
||||
@@ -897,8 +891,7 @@ static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_B
|
||||
}
|
||||
}
|
||||
|
||||
static int upload_texture(SDL_Texture **tex, AVFrame *frame)
|
||||
{
|
||||
static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) {
|
||||
int ret = 0;
|
||||
Uint32 sdl_pix_fmt;
|
||||
SDL_BlendMode sdl_blendmode;
|
||||
@@ -906,6 +899,24 @@ static int upload_texture(SDL_Texture **tex, AVFrame *frame)
|
||||
if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
|
||||
return -1;
|
||||
switch (sdl_pix_fmt) {
|
||||
case SDL_PIXELFORMAT_UNKNOWN:
|
||||
/* This should only happen if we are not using avfilter... */
|
||||
*img_convert_ctx = sws_getCachedContext(*img_convert_ctx,
|
||||
frame->width, frame->height, frame->format, frame->width, frame->height,
|
||||
AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
|
||||
if (*img_convert_ctx != NULL) {
|
||||
uint8_t *pixels[4];
|
||||
int pitch[4];
|
||||
if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) {
|
||||
sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize,
|
||||
0, frame->height, pixels, pitch);
|
||||
SDL_UnlockTexture(*tex);
|
||||
}
|
||||
} else {
|
||||
av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
|
||||
ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
|
||||
@@ -1003,7 +1014,7 @@ static void video_image_display(VideoState *is)
|
||||
set_sdl_yuv_conversion_mode(vp->frame);
|
||||
|
||||
if (!vp->uploaded) {
|
||||
if (upload_texture(&is->vid_texture, vp->frame) < 0) {
|
||||
if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) {
|
||||
set_sdl_yuv_conversion_mode(NULL);
|
||||
return;
|
||||
}
|
||||
@@ -1122,7 +1133,6 @@ static void video_audio_display(VideoState *s)
|
||||
fill_rectangle(s->xleft, y, s->width, 1);
|
||||
}
|
||||
} else {
|
||||
int err = 0;
|
||||
if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
|
||||
return;
|
||||
|
||||
@@ -1130,39 +1140,31 @@ static void video_audio_display(VideoState *s)
|
||||
s->xpos = 0;
|
||||
nb_display_channels= FFMIN(nb_display_channels, 2);
|
||||
if (rdft_bits != s->rdft_bits) {
|
||||
const float rdft_scale = 1.0;
|
||||
av_tx_uninit(&s->rdft);
|
||||
av_freep(&s->real_data);
|
||||
av_freep(&s->rdft_data);
|
||||
av_rdft_end(s->rdft);
|
||||
av_free(s->rdft_data);
|
||||
s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
|
||||
s->rdft_bits = rdft_bits;
|
||||
s->real_data = av_malloc_array(nb_freq, 4 *sizeof(*s->real_data));
|
||||
s->rdft_data = av_malloc_array(nb_freq + 1, 2 *sizeof(*s->rdft_data));
|
||||
err = av_tx_init(&s->rdft, &s->rdft_fn, AV_TX_FLOAT_RDFT,
|
||||
0, 1 << rdft_bits, &rdft_scale, 0);
|
||||
s->rdft_data = av_malloc_array(nb_freq, 4 *sizeof(*s->rdft_data));
|
||||
}
|
||||
if (err < 0 || !s->rdft_data) {
|
||||
if (!s->rdft || !s->rdft_data){
|
||||
av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
|
||||
s->show_mode = SHOW_MODE_WAVES;
|
||||
} else {
|
||||
float *data_in[2];
|
||||
AVComplexFloat *data[2];
|
||||
FFTSample *data[2];
|
||||
SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
|
||||
uint32_t *pixels;
|
||||
int pitch;
|
||||
for (ch = 0; ch < nb_display_channels; ch++) {
|
||||
data_in[ch] = s->real_data + 2 * nb_freq * ch;
|
||||
data[ch] = s->rdft_data + nb_freq * ch;
|
||||
data[ch] = s->rdft_data + 2 * nb_freq * ch;
|
||||
i = i_start + ch;
|
||||
for (x = 0; x < 2 * nb_freq; x++) {
|
||||
double w = (x-nb_freq) * (1.0 / nb_freq);
|
||||
data_in[ch][x] = s->sample_array[i] * (1.0 - w * w);
|
||||
data[ch][x] = s->sample_array[i] * (1.0 - w * w);
|
||||
i += channels;
|
||||
if (i >= SAMPLE_ARRAY_SIZE)
|
||||
i -= SAMPLE_ARRAY_SIZE;
|
||||
}
|
||||
s->rdft_fn(s->rdft, data[ch], data_in[ch], sizeof(float));
|
||||
data[ch][0].im = data[ch][nb_freq].re;
|
||||
data[ch][nb_freq].re = 0;
|
||||
av_rdft_calc(s->rdft, data[ch]);
|
||||
}
|
||||
/* Least efficient way to do this, we should of course
|
||||
* directly access it but it is more than fast enough. */
|
||||
@@ -1171,8 +1173,8 @@ static void video_audio_display(VideoState *s)
|
||||
pixels += pitch * s->height;
|
||||
for (y = 0; y < s->height; y++) {
|
||||
double w = 1 / sqrt(nb_freq);
|
||||
int a = sqrt(w * sqrt(data[0][y].re * data[0][y].re + data[0][y].im * data[0][y].im));
|
||||
int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][y].re, data[1][y].im))
|
||||
int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
|
||||
int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
|
||||
: a;
|
||||
a = FFMIN(a, 255);
|
||||
b = FFMIN(b, 255);
|
||||
@@ -1208,8 +1210,7 @@ static void stream_component_close(VideoState *is, int stream_index)
|
||||
is->audio_buf = NULL;
|
||||
|
||||
if (is->rdft) {
|
||||
av_tx_uninit(&is->rdft);
|
||||
av_freep(&is->real_data);
|
||||
av_rdft_end(is->rdft);
|
||||
av_freep(&is->rdft_data);
|
||||
is->rdft = NULL;
|
||||
is->rdft_bits = 0;
|
||||
@@ -1267,10 +1268,11 @@ static void stream_close(VideoState *is)
|
||||
packet_queue_destroy(&is->subtitleq);
|
||||
|
||||
/* free all pictures */
|
||||
frame_queue_destroy(&is->pictq);
|
||||
frame_queue_destroy(&is->sampq);
|
||||
frame_queue_destroy(&is->subpq);
|
||||
frame_queue_destory(&is->pictq);
|
||||
frame_queue_destory(&is->sampq);
|
||||
frame_queue_destory(&is->subpq);
|
||||
SDL_DestroyCond(is->continue_read_thread);
|
||||
sws_freeContext(is->img_convert_ctx);
|
||||
sws_freeContext(is->sub_convert_ctx);
|
||||
av_free(is->filename);
|
||||
if (is->vis_texture)
|
||||
@@ -1292,7 +1294,9 @@ static void do_exit(VideoState *is)
|
||||
if (window)
|
||||
SDL_DestroyWindow(window);
|
||||
uninit_opts();
|
||||
#if CONFIG_AVFILTER
|
||||
av_freep(&vfilters_list);
|
||||
#endif
|
||||
avformat_network_deinit();
|
||||
if (show_status)
|
||||
printf("\n");
|
||||
@@ -1549,8 +1553,7 @@ static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
|
||||
}
|
||||
}
|
||||
|
||||
static void update_video_pts(VideoState *is, double pts, int serial)
|
||||
{
|
||||
static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) {
|
||||
/* update current video pts */
|
||||
set_clock(&is->vidclk, pts, serial);
|
||||
sync_clock_to_slave(&is->extclk, &is->vidclk);
|
||||
@@ -1615,7 +1618,7 @@ retry:
|
||||
|
||||
SDL_LockMutex(is->pictq.mutex);
|
||||
if (!isnan(vp->pts))
|
||||
update_video_pts(is, vp->pts, vp->serial);
|
||||
update_video_pts(is, vp->pts, vp->pos, vp->serial);
|
||||
SDL_UnlockMutex(is->pictq.mutex);
|
||||
|
||||
if (frame_queue_nb_remaining(&is->pictq) > 1) {
|
||||
@@ -1790,6 +1793,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame)
|
||||
return got_picture;
|
||||
}
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
|
||||
AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
|
||||
{
|
||||
@@ -1856,7 +1860,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
}
|
||||
pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE;
|
||||
|
||||
while ((e = av_dict_iterate(sws_dict, e))) {
|
||||
while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if (!strcmp(e->key, "sws_flags")) {
|
||||
av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
|
||||
} else
|
||||
@@ -1911,19 +1915,8 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
|
||||
} while (0)
|
||||
|
||||
if (autorotate) {
|
||||
double theta = 0.0;
|
||||
int32_t *displaymatrix = NULL;
|
||||
AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
|
||||
if (sd)
|
||||
displaymatrix = (int32_t *)sd->data;
|
||||
if (!displaymatrix) {
|
||||
const AVPacketSideData *sd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
|
||||
is->video_st->codecpar->nb_coded_side_data,
|
||||
AV_PKT_DATA_DISPLAYMATRIX);
|
||||
if (sd)
|
||||
displaymatrix = (int32_t *)sd->data;
|
||||
}
|
||||
theta = get_rotation(displaymatrix);
|
||||
int32_t *displaymatrix = (int32_t *)av_stream_get_side_data(is->video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
|
||||
double theta = get_rotation(displaymatrix);
|
||||
|
||||
if (fabs(theta - 90) < 1.0) {
|
||||
INSERT_FILT("transpose", "clock");
|
||||
@@ -1967,7 +1960,7 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for
|
||||
|
||||
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
|
||||
|
||||
while ((e = av_dict_iterate(swr_opts, e)))
|
||||
while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX)))
|
||||
av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
|
||||
if (strlen(aresample_swr_opts))
|
||||
aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
|
||||
@@ -1999,8 +1992,6 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for
|
||||
goto end;
|
||||
|
||||
if (force_output_format) {
|
||||
av_bprint_clear(&bp);
|
||||
av_channel_layout_describe_bprint(&is->audio_tgt.ch_layout, &bp);
|
||||
sample_rates [0] = is->audio_tgt.freq;
|
||||
if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0)
|
||||
goto end;
|
||||
@@ -2024,14 +2015,17 @@ end:
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_AVFILTER */
|
||||
|
||||
static int audio_thread(void *arg)
|
||||
{
|
||||
VideoState *is = arg;
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
Frame *af;
|
||||
#if CONFIG_AVFILTER
|
||||
int last_serial = -1;
|
||||
int reconfigure;
|
||||
#endif
|
||||
int got_frame = 0;
|
||||
AVRational tb;
|
||||
int ret = 0;
|
||||
@@ -2046,6 +2040,7 @@ static int audio_thread(void *arg)
|
||||
if (got_frame) {
|
||||
tb = (AVRational){1, frame->sample_rate};
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
reconfigure =
|
||||
cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels,
|
||||
frame->format, frame->ch_layout.nb_channels) ||
|
||||
@@ -2077,28 +2072,32 @@ static int audio_thread(void *arg)
|
||||
goto the_end;
|
||||
|
||||
while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
|
||||
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
|
||||
tb = av_buffersink_get_time_base(is->out_audio_filter);
|
||||
#endif
|
||||
if (!(af = frame_queue_peek_writable(&is->sampq)))
|
||||
goto the_end;
|
||||
|
||||
af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
|
||||
af->pos = fd ? fd->pkt_pos : -1;
|
||||
af->pos = frame->pkt_pos;
|
||||
af->serial = is->auddec.pkt_serial;
|
||||
af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
|
||||
|
||||
av_frame_move_ref(af->frame, frame);
|
||||
frame_queue_push(&is->sampq);
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
if (is->audioq.serial != is->auddec.pkt_serial)
|
||||
break;
|
||||
}
|
||||
if (ret == AVERROR_EOF)
|
||||
is->auddec.finished = is->auddec.pkt_serial;
|
||||
#endif
|
||||
}
|
||||
} while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
|
||||
the_end:
|
||||
#if CONFIG_AVFILTER
|
||||
avfilter_graph_free(&is->agraph);
|
||||
#endif
|
||||
av_frame_free(&frame);
|
||||
return ret;
|
||||
}
|
||||
@@ -2124,6 +2123,7 @@ static int video_thread(void *arg)
|
||||
AVRational tb = is->video_st->time_base;
|
||||
AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
AVFilterGraph *graph = NULL;
|
||||
AVFilterContext *filt_out = NULL, *filt_in = NULL;
|
||||
int last_w = 0;
|
||||
@@ -2131,6 +2131,7 @@ static int video_thread(void *arg)
|
||||
enum AVPixelFormat last_format = -2;
|
||||
int last_serial = -1;
|
||||
int last_vfilter_idx = 0;
|
||||
#endif
|
||||
|
||||
if (!frame)
|
||||
return AVERROR(ENOMEM);
|
||||
@@ -2142,6 +2143,7 @@ static int video_thread(void *arg)
|
||||
if (!ret)
|
||||
continue;
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
if ( last_w != frame->width
|
||||
|| last_h != frame->height
|
||||
|| last_format != frame->format
|
||||
@@ -2182,8 +2184,6 @@ static int video_thread(void *arg)
|
||||
goto the_end;
|
||||
|
||||
while (ret >= 0) {
|
||||
FrameData *fd;
|
||||
|
||||
is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
|
||||
|
||||
ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
|
||||
@@ -2194,25 +2194,28 @@ static int video_thread(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
|
||||
|
||||
is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
|
||||
if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
|
||||
is->frame_last_filter_delay = 0;
|
||||
tb = av_buffersink_get_time_base(filt_out);
|
||||
#endif
|
||||
duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
|
||||
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
|
||||
ret = queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial);
|
||||
ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
|
||||
av_frame_unref(frame);
|
||||
#if CONFIG_AVFILTER
|
||||
if (is->videoq.serial != is->viddec.pkt_serial)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
goto the_end;
|
||||
}
|
||||
the_end:
|
||||
#if CONFIG_AVFILTER
|
||||
avfilter_graph_free(&graph);
|
||||
#endif
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
}
|
||||
@@ -2353,13 +2356,12 @@ static int audio_decode_frame(VideoState *is)
|
||||
av_channel_layout_compare(&af->frame->ch_layout, &is->audio_src.ch_layout) ||
|
||||
af->frame->sample_rate != is->audio_src.freq ||
|
||||
(wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
|
||||
int ret;
|
||||
swr_free(&is->swr_ctx);
|
||||
ret = swr_alloc_set_opts2(&is->swr_ctx,
|
||||
swr_alloc_set_opts2(&is->swr_ctx,
|
||||
&is->audio_tgt.ch_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
|
||||
&af->frame->ch_layout, af->frame->format, af->frame->sample_rate,
|
||||
0, NULL);
|
||||
if (ret < 0 || swr_init(is->swr_ctx) < 0) {
|
||||
if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
|
||||
af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->ch_layout.nb_channels,
|
||||
@@ -2604,18 +2606,11 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
if (fast)
|
||||
avctx->flags2 |= AV_CODEC_FLAG2_FAST;
|
||||
|
||||
ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
|
||||
ic->streams[stream_index], codec, &opts);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
|
||||
if (!av_dict_get(opts, "threads", NULL, 0))
|
||||
av_dict_set(&opts, "threads", "auto", 0);
|
||||
if (stream_lowres)
|
||||
av_dict_set_int(&opts, "lowres", stream_lowres, 0);
|
||||
|
||||
av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
|
||||
|
||||
if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2629,6 +2624,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
|
||||
switch (avctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
#if CONFIG_AVFILTER
|
||||
{
|
||||
AVFilterContext *sink;
|
||||
|
||||
@@ -2645,6 +2641,12 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
sample_rate = avctx->sample_rate;
|
||||
ret = av_channel_layout_copy(&ch_layout, &avctx->ch_layout);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
/* prepare audio output */
|
||||
if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0)
|
||||
@@ -2666,7 +2668,7 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
|
||||
if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0)
|
||||
goto fail;
|
||||
if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) {
|
||||
if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) {
|
||||
is->auddec.start_pts = is->audio_st->start_time;
|
||||
is->auddec.start_pts_tb = is->audio_st->time_base;
|
||||
}
|
||||
@@ -2797,17 +2799,11 @@ static int read_thread(void *arg)
|
||||
if (genpts)
|
||||
ic->flags |= AVFMT_FLAG_GENPTS;
|
||||
|
||||
if (find_stream_info) {
|
||||
AVDictionary **opts;
|
||||
int orig_nb_streams = ic->nb_streams;
|
||||
av_format_inject_global_side_data(ic);
|
||||
|
||||
err = setup_find_stream_info_opts(ic, codec_opts, &opts);
|
||||
if (err < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Error setting up avformat_find_stream_info() options\n");
|
||||
ret = err;
|
||||
goto fail;
|
||||
}
|
||||
if (find_stream_info) {
|
||||
AVDictionary **opts = setup_find_stream_info_opts(ic, codec_opts);
|
||||
int orig_nb_streams = ic->nb_streams;
|
||||
|
||||
err = avformat_find_stream_info(ic, opts);
|
||||
|
||||
@@ -3324,6 +3320,7 @@ static void event_loop(VideoState *cur_stream)
|
||||
stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
|
||||
break;
|
||||
case SDLK_w:
|
||||
#if CONFIG_AVFILTER
|
||||
if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
|
||||
if (++cur_stream->vfilter_idx >= nb_vfilters)
|
||||
cur_stream->vfilter_idx = 0;
|
||||
@@ -3331,6 +3328,9 @@ static void event_loop(VideoState *cur_stream)
|
||||
cur_stream->vfilter_idx = 0;
|
||||
toggle_audio_display(cur_stream);
|
||||
}
|
||||
#else
|
||||
toggle_audio_display(cur_stream);
|
||||
#endif
|
||||
break;
|
||||
case SDLK_PAGEUP:
|
||||
if (cur_stream->ic->nb_chapters <= 1) {
|
||||
@@ -3466,23 +3466,13 @@ static void event_loop(VideoState *cur_stream)
|
||||
|
||||
static int opt_width(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
screen_width = num;
|
||||
screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_height(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_INT64, 1, INT_MAX, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
screen_height = num;
|
||||
screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3511,35 +3501,38 @@ static int opt_sync(void *optctx, const char *opt, const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_seek(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
start_time = parse_time_or_die(opt, arg, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_duration(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
duration = parse_time_or_die(opt, arg, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_show_mode(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
|
||||
!strcmp(arg, "waves") ? SHOW_MODE_WAVES :
|
||||
!strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
|
||||
|
||||
if (show_mode == SHOW_MODE_NONE) {
|
||||
double num;
|
||||
int ret = parse_number(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1, &num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
show_mode = num;
|
||||
}
|
||||
!strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT :
|
||||
parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_input_file(void *optctx, const char *filename)
|
||||
static void opt_input_file(void *optctx, const char *filename)
|
||||
{
|
||||
if (input_filename) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
|
||||
filename, input_filename);
|
||||
return AVERROR(EINVAL);
|
||||
exit(1);
|
||||
}
|
||||
if (!strcmp(filename, "-"))
|
||||
filename = "fd:";
|
||||
filename = "pipe:";
|
||||
input_filename = filename;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_codec(void *optctx, const char *opt, const char *arg)
|
||||
@@ -3577,8 +3570,8 @@ static const OptionDef options[] = {
|
||||
{ "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
|
||||
{ "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
|
||||
{ "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
|
||||
{ "ss", HAS_ARG | OPT_TIME, { &start_time }, "seek to a given position in seconds", "pos" },
|
||||
{ "t", HAS_ARG | OPT_TIME, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
|
||||
{ "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
|
||||
{ "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
|
||||
{ "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
|
||||
{ "seek_interval", OPT_FLOAT | HAS_ARG, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
|
||||
{ "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
|
||||
@@ -3601,8 +3594,10 @@ static const OptionDef options[] = {
|
||||
{ "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
|
||||
{ "left", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
|
||||
{ "top", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
|
||||
#if CONFIG_AVFILTER
|
||||
{ "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
|
||||
{ "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
|
||||
#endif
|
||||
{ "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
|
||||
{ "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
|
||||
{ "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
|
||||
@@ -3633,7 +3628,11 @@ void show_help_default(const char *opt, const char *arg)
|
||||
printf("\n");
|
||||
show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
|
||||
show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
|
||||
#if !CONFIG_AVFILTER
|
||||
show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
|
||||
#else
|
||||
show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
|
||||
#endif
|
||||
printf("\nWhile playing:\n"
|
||||
"q, ESC quit\n"
|
||||
"f toggle full screen\n"
|
||||
@@ -3658,7 +3657,7 @@ void show_help_default(const char *opt, const char *arg)
|
||||
/* Called from the main */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int flags, ret;
|
||||
int flags;
|
||||
VideoState *is;
|
||||
|
||||
init_dynload();
|
||||
@@ -3677,9 +3676,7 @@ int main(int argc, char **argv)
|
||||
|
||||
show_banner(argc, argv, options);
|
||||
|
||||
ret = parse_options(NULL, argc, argv, options, opt_input_file);
|
||||
if (ret < 0)
|
||||
exit(ret == AVERROR_EXIT ? 0 : 1);
|
||||
parse_options(NULL, argc, argv, options, opt_input_file);
|
||||
|
||||
if (!input_filename) {
|
||||
show_usage();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
@@ -1,2 +0,0 @@
|
||||
#include <windows.h>
|
||||
1 RT_MANIFEST fftools.manifest
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavcodec/packet.h"
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#include "objpool.h"
|
||||
|
||||
struct ObjPool {
|
||||
void *pool[32];
|
||||
unsigned int pool_count;
|
||||
|
||||
ObjPoolCBAlloc alloc;
|
||||
ObjPoolCBReset reset;
|
||||
ObjPoolCBFree free;
|
||||
};
|
||||
|
||||
ObjPool *objpool_alloc(ObjPoolCBAlloc cb_alloc, ObjPoolCBReset cb_reset,
|
||||
ObjPoolCBFree cb_free)
|
||||
{
|
||||
ObjPool *op = av_mallocz(sizeof(*op));
|
||||
|
||||
if (!op)
|
||||
return NULL;
|
||||
|
||||
op->alloc = cb_alloc;
|
||||
op->reset = cb_reset;
|
||||
op->free = cb_free;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void objpool_free(ObjPool **pop)
|
||||
{
|
||||
ObjPool *op = *pop;
|
||||
|
||||
if (!op)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < op->pool_count; i++)
|
||||
op->free(&op->pool[i]);
|
||||
|
||||
av_freep(pop);
|
||||
}
|
||||
|
||||
int objpool_get(ObjPool *op, void **obj)
|
||||
{
|
||||
if (op->pool_count) {
|
||||
*obj = op->pool[--op->pool_count];
|
||||
op->pool[op->pool_count] = NULL;
|
||||
} else
|
||||
*obj = op->alloc();
|
||||
|
||||
return *obj ? 0 : AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
void objpool_release(ObjPool *op, void **obj)
|
||||
{
|
||||
if (!*obj)
|
||||
return;
|
||||
|
||||
op->reset(*obj);
|
||||
|
||||
if (op->pool_count < FF_ARRAY_ELEMS(op->pool))
|
||||
op->pool[op->pool_count++] = *obj;
|
||||
else
|
||||
op->free(obj);
|
||||
|
||||
*obj = NULL;
|
||||
}
|
||||
|
||||
static void *alloc_packet(void)
|
||||
{
|
||||
return av_packet_alloc();
|
||||
}
|
||||
static void *alloc_frame(void)
|
||||
{
|
||||
return av_frame_alloc();
|
||||
}
|
||||
|
||||
static void reset_packet(void *obj)
|
||||
{
|
||||
av_packet_unref(obj);
|
||||
}
|
||||
static void reset_frame(void *obj)
|
||||
{
|
||||
av_frame_unref(obj);
|
||||
}
|
||||
|
||||
static void free_packet(void **obj)
|
||||
{
|
||||
AVPacket *pkt = *obj;
|
||||
av_packet_free(&pkt);
|
||||
*obj = NULL;
|
||||
}
|
||||
static void free_frame(void **obj)
|
||||
{
|
||||
AVFrame *frame = *obj;
|
||||
av_frame_free(&frame);
|
||||
*obj = NULL;
|
||||
}
|
||||
|
||||
ObjPool *objpool_alloc_packets(void)
|
||||
{
|
||||
return objpool_alloc(alloc_packet, reset_packet, free_packet);
|
||||
}
|
||||
ObjPool *objpool_alloc_frames(void)
|
||||
{
|
||||
return objpool_alloc(alloc_frame, reset_frame, free_frame);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_OBJPOOL_H
|
||||
#define FFTOOLS_OBJPOOL_H
|
||||
|
||||
typedef struct ObjPool ObjPool;
|
||||
|
||||
typedef void* (*ObjPoolCBAlloc)(void);
|
||||
typedef void (*ObjPoolCBReset)(void *);
|
||||
typedef void (*ObjPoolCBFree)(void **);
|
||||
|
||||
void objpool_free(ObjPool **op);
|
||||
ObjPool *objpool_alloc(ObjPoolCBAlloc cb_alloc, ObjPoolCBReset cb_reset,
|
||||
ObjPoolCBFree cb_free);
|
||||
ObjPool *objpool_alloc_packets(void);
|
||||
ObjPool *objpool_alloc_frames(void);
|
||||
|
||||
int objpool_get(ObjPool *op, void **obj);
|
||||
void objpool_release(ObjPool *op, void **obj);
|
||||
|
||||
#endif // FFTOOLS_OBJPOOL_H
|
||||
@@ -291,6 +291,8 @@ static void print_codec(const AVCodec *c)
|
||||
printf("delay ");
|
||||
if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)
|
||||
printf("small ");
|
||||
if (c->capabilities & AV_CODEC_CAP_SUBFRAMES)
|
||||
printf("subframes ");
|
||||
if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL)
|
||||
printf("exp ");
|
||||
if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF)
|
||||
@@ -333,12 +335,9 @@ static void print_codec(const AVCodec *c)
|
||||
printf(" Supported hardware devices: ");
|
||||
for (int i = 0;; i++) {
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(c, i);
|
||||
const char *name;
|
||||
if (!config)
|
||||
break;
|
||||
name = av_hwdevice_get_type_name(config->device_type);
|
||||
if (name)
|
||||
printf("%s ", name);
|
||||
printf("%s ", av_hwdevice_get_type_name(config->device_type));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@@ -615,10 +614,10 @@ static void print_codecs_for_id(enum AVCodecID id, int encoder)
|
||||
void *iter = NULL;
|
||||
const AVCodec *codec;
|
||||
|
||||
printf(" (%s:", encoder ? "encoders" : "decoders");
|
||||
printf(" (%s: ", encoder ? "encoders" : "decoders");
|
||||
|
||||
while ((codec = next_codec_for_id(id, &iter, encoder)))
|
||||
printf(" %s", codec->name);
|
||||
printf("%s ", codec->name);
|
||||
|
||||
printf(")");
|
||||
}
|
||||
@@ -632,7 +631,7 @@ static int compare_codec_desc(const void *a, const void *b)
|
||||
strcmp((*da)->name, (*db)->name);
|
||||
}
|
||||
|
||||
static int get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
|
||||
static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
|
||||
{
|
||||
const AVCodecDescriptor *desc = NULL;
|
||||
const AVCodecDescriptor **codecs;
|
||||
@@ -640,8 +639,10 @@ static int get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
|
||||
|
||||
while ((desc = avcodec_descriptor_next(desc)))
|
||||
nb_codecs++;
|
||||
if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs))))
|
||||
return AVERROR(ENOMEM);
|
||||
if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Out of memory\n");
|
||||
exit_program(1);
|
||||
}
|
||||
desc = NULL;
|
||||
while ((desc = avcodec_descriptor_next(desc)))
|
||||
codecs[i++] = desc;
|
||||
@@ -666,11 +667,7 @@ static char get_media_type_char(enum AVMediaType type)
|
||||
int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
const AVCodecDescriptor **codecs;
|
||||
unsigned i;
|
||||
int nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
if (nb_codecs < 0)
|
||||
return nb_codecs;
|
||||
unsigned i, nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
printf("Codecs:\n"
|
||||
" D..... = Decoding supported\n"
|
||||
@@ -692,13 +689,14 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
if (strstr(desc->name, "_deprecated"))
|
||||
continue;
|
||||
|
||||
printf(" %c%c%c%c%c%c",
|
||||
avcodec_find_decoder(desc->id) ? 'D' : '.',
|
||||
avcodec_find_encoder(desc->id) ? 'E' : '.',
|
||||
get_media_type_char(desc->type),
|
||||
(desc->props & AV_CODEC_PROP_INTRA_ONLY) ? 'I' : '.',
|
||||
(desc->props & AV_CODEC_PROP_LOSSY) ? 'L' : '.',
|
||||
(desc->props & AV_CODEC_PROP_LOSSLESS) ? 'S' : '.');
|
||||
printf(" ");
|
||||
printf(avcodec_find_decoder(desc->id) ? "D" : ".");
|
||||
printf(avcodec_find_encoder(desc->id) ? "E" : ".");
|
||||
|
||||
printf("%c", get_media_type_char(desc->type));
|
||||
printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : ".");
|
||||
printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : ".");
|
||||
printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : ".");
|
||||
|
||||
printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : "");
|
||||
|
||||
@@ -724,13 +722,10 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_codecs(int encoder)
|
||||
static void print_codecs(int encoder)
|
||||
{
|
||||
const AVCodecDescriptor **codecs;
|
||||
int i, nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
if (nb_codecs < 0)
|
||||
return nb_codecs;
|
||||
unsigned i, nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
printf("%s:\n"
|
||||
" V..... = Video\n"
|
||||
@@ -749,13 +744,12 @@ static int print_codecs(int encoder)
|
||||
void *iter = NULL;
|
||||
|
||||
while ((codec = next_codec_for_id(desc->id, &iter, encoder))) {
|
||||
printf(" %c%c%c%c%c%c",
|
||||
get_media_type_char(desc->type),
|
||||
(codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? 'F' : '.',
|
||||
(codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? 'S' : '.',
|
||||
(codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? 'X' : '.',
|
||||
(codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND) ? 'B' : '.',
|
||||
(codec->capabilities & AV_CODEC_CAP_DR1) ? 'D' : '.');
|
||||
printf(" %c", get_media_type_char(desc->type));
|
||||
printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
|
||||
printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
|
||||
printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
|
||||
printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
|
||||
printf((codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : ".");
|
||||
|
||||
printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
|
||||
if (strcmp(codec->name, desc->name))
|
||||
@@ -765,17 +759,18 @@ static int print_codecs(int encoder)
|
||||
}
|
||||
}
|
||||
av_free(codecs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int show_decoders(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
return print_codecs(0);
|
||||
print_codecs(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int show_encoders(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
return print_codecs(1);
|
||||
print_codecs(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int show_bsfs(void *optctx, const char *opt, const char *arg)
|
||||
@@ -1165,10 +1160,7 @@ int init_report(const char *env, FILE **file)
|
||||
report_file_level = strtol(val, &tail, 10);
|
||||
if (*tail) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
|
||||
av_free(key);
|
||||
av_free(val);
|
||||
av_free(filename_template);
|
||||
return AVERROR(EINVAL);
|
||||
exit_program(1);
|
||||
}
|
||||
envlevel = 1;
|
||||
} else {
|
||||
@@ -1228,7 +1220,7 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg)
|
||||
max = strtol(arg, &tail, 10);
|
||||
if (*tail) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg);
|
||||
return AVERROR(EINVAL);
|
||||
exit_program(1);
|
||||
}
|
||||
av_max_alloc(max);
|
||||
return 0;
|
||||
@@ -1302,7 +1294,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg)
|
||||
"Possible levels are numbers or:\n", arg);
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
|
||||
av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
|
||||
return AVERROR(EINVAL);
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@@ -1,719 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/cpu.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "libavutil/timestamp.h"
|
||||
|
||||
#include "objpool.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 1│d=1│ │ d=5 │
|
||||
* └───┘ └───────────────────────┘
|
||||
* | ┌───┐┌───┐┌───┐┌───┐
|
||||
* stream 2| │d=1││d=1││d=1││d=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 {
|
||||
AVFifo *fifo;
|
||||
AVRational tb;
|
||||
|
||||
/* number of audio samples in fifo */
|
||||
uint64_t samples_queued;
|
||||
/* stream head: largest timestamp seen */
|
||||
int64_t head_ts;
|
||||
int limiting;
|
||||
/* no more frames will be sent for this stream */
|
||||
int finished;
|
||||
|
||||
uint64_t frames_sent;
|
||||
uint64_t samples_sent;
|
||||
uint64_t frames_max;
|
||||
int frame_samples;
|
||||
} SyncQueueStream;
|
||||
|
||||
struct SyncQueue {
|
||||
enum SyncQueueType type;
|
||||
|
||||
void *logctx;
|
||||
|
||||
/* no more frames will be sent for any stream */
|
||||
int finished;
|
||||
/* sync head: the stream with the _smallest_ head timestamp
|
||||
* this stream determines which frames can be output */
|
||||
int head_stream;
|
||||
/* the finished stream with the smallest finish timestamp or -1 */
|
||||
int head_finished_stream;
|
||||
|
||||
// maximum buffering duration in microseconds
|
||||
int64_t buf_size_us;
|
||||
|
||||
SyncQueueStream *streams;
|
||||
unsigned int nb_streams;
|
||||
|
||||
// pool of preallocated frames to avoid constant allocations
|
||||
ObjPool *pool;
|
||||
|
||||
int have_limiting;
|
||||
|
||||
uintptr_t align_mask;
|
||||
};
|
||||
|
||||
static void frame_move(const SyncQueue *sq, SyncQueueFrame dst,
|
||||
SyncQueueFrame src)
|
||||
{
|
||||
if (sq->type == SYNC_QUEUE_PACKETS)
|
||||
av_packet_move_ref(dst.p, src.p);
|
||||
else
|
||||
av_frame_move_ref(dst.f, src.f);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) ?
|
||||
frame.p->pts + frame.p->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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (st->limiting && st->head_ts != AV_NOPTS_VALUE) {
|
||||
/* check if this stream is the new finished head */
|
||||
if (sq->head_finished_stream < 0 ||
|
||||
av_compare_ts(st->head_ts, st->tb,
|
||||
sq->streams[sq->head_finished_stream].head_ts,
|
||||
sq->streams[sq->head_finished_stream].tb) < 0) {
|
||||
sq->head_finished_stream = stream_idx;
|
||||
}
|
||||
|
||||
/* mark as finished all streams that should no longer receive new frames,
|
||||
* due to them being ahead of some finished stream */
|
||||
st = &sq->streams[sq->head_finished_stream];
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
SyncQueueStream *st1 = &sq->streams[i];
|
||||
if (st != st1 && st1->head_ts != AV_NOPTS_VALUE &&
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mark the whole queue as finished if all streams are finished */
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
if (!sq->streams[i].finished)
|
||||
return;
|
||||
}
|
||||
sq->finished = 1;
|
||||
|
||||
av_log(sq->logctx, AV_LOG_DEBUG, "sq: finish queue\n");
|
||||
}
|
||||
|
||||
static void queue_head_update(SyncQueue *sq)
|
||||
{
|
||||
av_assert0(sq->have_limiting);
|
||||
|
||||
if (sq->head_stream < 0) {
|
||||
unsigned first_limiting = UINT_MAX;
|
||||
|
||||
/* wait for one timestamp in each stream before determining
|
||||
* the queue head */
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
SyncQueueStream *st = &sq->streams[i];
|
||||
if (!st->limiting)
|
||||
continue;
|
||||
if (st->head_ts == AV_NOPTS_VALUE)
|
||||
return;
|
||||
if (first_limiting == UINT_MAX)
|
||||
first_limiting = i;
|
||||
}
|
||||
|
||||
// placeholder value, correct one will be found below
|
||||
av_assert0(first_limiting < UINT_MAX);
|
||||
sq->head_stream = first_limiting;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
SyncQueueStream *st_head = &sq->streams[sq->head_stream];
|
||||
SyncQueueStream *st_other = &sq->streams[i];
|
||||
if (st_other->limiting && st_other->head_ts != AV_NOPTS_VALUE &&
|
||||
av_compare_ts(st_other->head_ts, st_other->tb,
|
||||
st_head->head_ts, st_head->tb) < 0)
|
||||
sq->head_stream = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* update this stream's head timestamp */
|
||||
static void stream_update_ts(SyncQueue *sq, unsigned int stream_idx, int64_t ts)
|
||||
{
|
||||
SyncQueueStream *st = &sq->streams[stream_idx];
|
||||
|
||||
if (ts == AV_NOPTS_VALUE ||
|
||||
(st->head_ts != AV_NOPTS_VALUE && st->head_ts >= ts))
|
||||
return;
|
||||
|
||||
st->head_ts = ts;
|
||||
|
||||
/* if this stream is now ahead of some finished stream, then
|
||||
* this stream is also finished */
|
||||
if (sq->head_finished_stream >= 0 &&
|
||||
av_compare_ts(sq->streams[sq->head_finished_stream].head_ts,
|
||||
sq->streams[sq->head_finished_stream].tb,
|
||||
ts, st->tb) <= 0)
|
||||
finish_stream(sq, stream_idx);
|
||||
|
||||
/* update the overall head timestamp if it could have changed */
|
||||
if (st->limiting &&
|
||||
(sq->head_stream < 0 || sq->head_stream == stream_idx))
|
||||
queue_head_update(sq);
|
||||
}
|
||||
|
||||
/* If the queue for the given stream (or all streams when stream_idx=-1)
|
||||
* is overflowing, trigger a fake heartbeat on lagging streams.
|
||||
*
|
||||
* @return 1 if heartbeat triggered, 0 otherwise
|
||||
*/
|
||||
static int overflow_heartbeat(SyncQueue *sq, int stream_idx)
|
||||
{
|
||||
SyncQueueStream *st;
|
||||
SyncQueueFrame frame;
|
||||
int64_t tail_ts = AV_NOPTS_VALUE;
|
||||
|
||||
/* if no stream specified, pick the one that is most ahead */
|
||||
if (stream_idx < 0) {
|
||||
int64_t ts = AV_NOPTS_VALUE;
|
||||
|
||||
for (int i = 0; i < sq->nb_streams; i++) {
|
||||
st = &sq->streams[i];
|
||||
if (st->head_ts != AV_NOPTS_VALUE &&
|
||||
(ts == AV_NOPTS_VALUE ||
|
||||
av_compare_ts(ts, sq->streams[stream_idx].tb,
|
||||
st->head_ts, st->tb) < 0)) {
|
||||
ts = st->head_ts;
|
||||
stream_idx = i;
|
||||
}
|
||||
}
|
||||
/* no stream has a timestamp yet -> nothing to do */
|
||||
if (stream_idx < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
st = &sq->streams[stream_idx];
|
||||
|
||||
/* get the chosen stream's tail timestamp */
|
||||
for (size_t i = 0; tail_ts == AV_NOPTS_VALUE &&
|
||||
av_fifo_peek(st->fifo, &frame, 1, i) >= 0; i++)
|
||||
tail_ts = frame_end(sq, frame, 0);
|
||||
|
||||
/* overflow triggers when the tail is over specified duration behind the head */
|
||||
if (tail_ts == AV_NOPTS_VALUE || tail_ts >= st->head_ts ||
|
||||
av_rescale_q(st->head_ts - tail_ts, st->tb, AV_TIME_BASE_Q) < sq->buf_size_us)
|
||||
return 0;
|
||||
|
||||
/* signal a fake timestamp for all streams that prevent tail_ts from being output */
|
||||
tail_ts++;
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
SyncQueueStream *st1 = &sq->streams[i];
|
||||
int64_t ts;
|
||||
|
||||
if (st == st1 || st1->finished ||
|
||||
(st1->head_ts != AV_NOPTS_VALUE &&
|
||||
av_compare_ts(tail_ts, st->tb, st1->head_ts, st1->tb) <= 0))
|
||||
continue;
|
||||
|
||||
ts = av_rescale_q(tail_ts, st->tb, st1->tb);
|
||||
if (st1->head_ts != AV_NOPTS_VALUE)
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
|
||||
{
|
||||
SyncQueueStream *st;
|
||||
SyncQueueFrame dst;
|
||||
int64_t ts;
|
||||
int ret, nb_samples;
|
||||
|
||||
av_assert0(stream_idx < sq->nb_streams);
|
||||
st = &sq->streams[stream_idx];
|
||||
|
||||
if (frame_null(sq, frame)) {
|
||||
av_log(sq->logctx, AV_LOG_DEBUG, "sq: %u EOF\n", stream_idx);
|
||||
finish_stream(sq, stream_idx);
|
||||
return 0;
|
||||
}
|
||||
if (st->finished)
|
||||
return AVERROR_EOF;
|
||||
|
||||
tb_update(sq, st, frame);
|
||||
|
||||
ret = objpool_get(sq->pool, (void**)&dst);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
frame_move(sq, dst, frame);
|
||||
|
||||
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);
|
||||
if (ret < 0) {
|
||||
frame_move(sq, frame, dst);
|
||||
objpool_release(sq->pool, (void**)&dst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream_update_ts(sq, stream_idx, ts);
|
||||
|
||||
st->samples_queued += nb_samples;
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
SyncQueueFrame frame)
|
||||
{
|
||||
SyncQueueStream *st_head = sq->head_stream >= 0 ?
|
||||
&sq->streams[sq->head_stream] : NULL;
|
||||
SyncQueueStream *st;
|
||||
|
||||
av_assert0(stream_idx < sq->nb_streams);
|
||||
st = &sq->streams[stream_idx];
|
||||
|
||||
if (av_fifo_can_read(st->fifo) &&
|
||||
(st->frame_samples <= st->samples_queued || st->finished)) {
|
||||
int nb_samples = st->frame_samples;
|
||||
SyncQueueFrame peek;
|
||||
int64_t ts;
|
||||
int cmp = 1;
|
||||
|
||||
if (st->finished)
|
||||
nb_samples = FFMIN(nb_samples, st->samples_queued);
|
||||
|
||||
av_fifo_peek(st->fifo, &peek, 1, 0);
|
||||
ts = frame_end(sq, peek, nb_samples);
|
||||
|
||||
/* check if this stream's tail timestamp does not overtake
|
||||
* the overall queue head */
|
||||
if (ts != AV_NOPTS_VALUE && st_head)
|
||||
cmp = av_compare_ts(ts, st->tb, st_head->head_ts, st_head->tb);
|
||||
|
||||
/* We can release frames that do not end after the queue head.
|
||||
* 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 || !sq->have_limiting) {
|
||||
if (nb_samples &&
|
||||
(nb_samples != peek.f->nb_samples || !frame_is_aligned(sq, peek.f))) {
|
||||
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 (sq->finished || (st->finished && !av_fifo_can_read(st->fifo))) ?
|
||||
AVERROR_EOF : AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
static int receive_internal(SyncQueue *sq, int stream_idx, SyncQueueFrame frame)
|
||||
{
|
||||
int nb_eof = 0;
|
||||
int ret;
|
||||
|
||||
/* read a frame for a specific stream */
|
||||
if (stream_idx >= 0) {
|
||||
ret = receive_for_stream(sq, stream_idx, frame);
|
||||
return (ret < 0) ? ret : stream_idx;
|
||||
}
|
||||
|
||||
/* read a frame for any stream with available output */
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
ret = receive_for_stream(sq, i, frame);
|
||||
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
|
||||
nb_eof += (ret == AVERROR_EOF);
|
||||
continue;
|
||||
}
|
||||
return (ret < 0) ? ret : i;
|
||||
}
|
||||
|
||||
return (nb_eof == sq->nb_streams) ? AVERROR_EOF : AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
int sq_receive(SyncQueue *sq, int stream_idx, SyncQueueFrame frame)
|
||||
{
|
||||
int ret = receive_internal(sq, stream_idx, frame);
|
||||
|
||||
/* try again if the queue overflowed and triggered a fake heartbeat
|
||||
* for lagging streams */
|
||||
if (ret == AVERROR(EAGAIN) && overflow_heartbeat(sq, stream_idx))
|
||||
ret = receive_internal(sq, stream_idx, frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sq_add_stream(SyncQueue *sq, int limiting)
|
||||
{
|
||||
SyncQueueStream *tmp, *st;
|
||||
|
||||
tmp = av_realloc_array(sq->streams, sq->nb_streams + 1, sizeof(*sq->streams));
|
||||
if (!tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
sq->streams = tmp;
|
||||
|
||||
st = &sq->streams[sq->nb_streams];
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
||||
st->fifo = av_fifo_alloc2(1, sizeof(SyncQueueFrame), AV_FIFO_FLAG_AUTO_GROW);
|
||||
if (!st->fifo)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
/* we set a valid default, so that a pathological stream that never
|
||||
* receives even a real timebase (and no frames) won't stall all other
|
||||
* streams forever; cf. overflow_heartbeat() */
|
||||
st->tb = (AVRational){ 1, 1 };
|
||||
st->head_ts = AV_NOPTS_VALUE;
|
||||
st->frames_max = UINT64_MAX;
|
||||
st->limiting = limiting;
|
||||
|
||||
sq->have_limiting |= limiting;
|
||||
|
||||
return sq->nb_streams++;
|
||||
}
|
||||
|
||||
void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames)
|
||||
{
|
||||
SyncQueueStream *st;
|
||||
|
||||
av_assert0(stream_idx < sq->nb_streams);
|
||||
st = &sq->streams[stream_idx];
|
||||
|
||||
st->frames_max = frames;
|
||||
if (st->frames_sent >= st->frames_max)
|
||||
finish_stream(sq, stream_idx);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (!sq)
|
||||
return NULL;
|
||||
|
||||
sq->type = type;
|
||||
sq->buf_size_us = buf_size_us;
|
||||
sq->logctx = logctx;
|
||||
|
||||
sq->head_stream = -1;
|
||||
sq->head_finished_stream = -1;
|
||||
|
||||
sq->pool = (type == SYNC_QUEUE_PACKETS) ? objpool_alloc_packets() :
|
||||
objpool_alloc_frames();
|
||||
if (!sq->pool) {
|
||||
av_freep(&sq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sq;
|
||||
}
|
||||
|
||||
void sq_free(SyncQueue **psq)
|
||||
{
|
||||
SyncQueue *sq = *psq;
|
||||
|
||||
if (!sq)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < sq->nb_streams; i++) {
|
||||
SyncQueueFrame frame;
|
||||
while (av_fifo_read(sq->streams[i].fifo, &frame, 1) >= 0)
|
||||
objpool_release(sq->pool, (void**)&frame);
|
||||
|
||||
av_fifo_freep2(&sq->streams[i].fifo);
|
||||
}
|
||||
|
||||
av_freep(&sq->streams);
|
||||
|
||||
objpool_free(&sq->pool);
|
||||
|
||||
av_freep(psq);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_SYNC_QUEUE_H
|
||||
#define FFTOOLS_SYNC_QUEUE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavcodec/packet.h"
|
||||
|
||||
#include "libavutil/frame.h"
|
||||
|
||||
enum SyncQueueType {
|
||||
SYNC_QUEUE_PACKETS,
|
||||
SYNC_QUEUE_FRAMES,
|
||||
};
|
||||
|
||||
typedef union SyncQueueFrame {
|
||||
AVFrame *f;
|
||||
AVPacket *p;
|
||||
} SyncQueueFrame;
|
||||
|
||||
#define SQFRAME(frame) ((SyncQueueFrame){ .f = (frame) })
|
||||
#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;
|
||||
|
||||
/**
|
||||
* Allocate a sync queue of the given type.
|
||||
*
|
||||
* @param buf_size_us maximum duration that will be buffered in microseconds
|
||||
*/
|
||||
SyncQueue *sq_alloc(enum SyncQueueType type, int64_t buf_size_us, void *logctx);
|
||||
void sq_free(SyncQueue **sq);
|
||||
|
||||
/**
|
||||
* Add a new stream to the sync queue.
|
||||
*
|
||||
* @param limiting whether the stream is limiting, i.e. no other stream can be
|
||||
* longer than this one
|
||||
* @return
|
||||
* - a non-negative stream index on success
|
||||
* - a negative error code on error
|
||||
*/
|
||||
int sq_add_stream(SyncQueue *sq, int limiting);
|
||||
|
||||
/**
|
||||
* Limit the number of output frames for stream with index stream_idx
|
||||
* to max_frames.
|
||||
*/
|
||||
void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx,
|
||||
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.
|
||||
*
|
||||
* On success, the sync queue takes ownership of the frame and will reset the
|
||||
* contents of the supplied frame. On failure, the frame remains owned by the
|
||||
* caller.
|
||||
*
|
||||
* Sending a frame with NULL contents marks the stream as finished.
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - AVERROR_EOF when no more frames should be submitted for this stream
|
||||
* - another a negative error code on failure
|
||||
*/
|
||||
int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame);
|
||||
|
||||
/**
|
||||
* Read a frame from the queue.
|
||||
*
|
||||
* @param stream_idx index of the stream to read a frame for. May be -1, then
|
||||
* try to read a frame from any stream that is ready for
|
||||
* output.
|
||||
* @param frame output frame will be written here on success. The frame is owned
|
||||
* by the caller.
|
||||
*
|
||||
* @return
|
||||
* - a non-negative index of the stream to which the returned frame belongs
|
||||
* - AVERROR(EAGAIN) when more frames need to be submitted to the queue
|
||||
* - AVERROR_EOF when no more frames will be available for this stream (for any
|
||||
* stream if stream_idx is -1)
|
||||
* - another negative error code on failure
|
||||
*/
|
||||
int sq_receive(SyncQueue *sq, int stream_idx, SyncQueueFrame frame);
|
||||
|
||||
#endif // FFTOOLS_SYNC_QUEUE_H
|
||||
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
#include "objpool.h"
|
||||
#include "thread_queue.h"
|
||||
|
||||
enum {
|
||||
FINISHED_SEND = (1 << 0),
|
||||
FINISHED_RECV = (1 << 1),
|
||||
};
|
||||
|
||||
typedef struct FifoElem {
|
||||
void *obj;
|
||||
unsigned int stream_idx;
|
||||
} FifoElem;
|
||||
|
||||
struct ThreadQueue {
|
||||
int *finished;
|
||||
unsigned int nb_streams;
|
||||
|
||||
AVFifo *fifo;
|
||||
|
||||
ObjPool *obj_pool;
|
||||
void (*obj_move)(void *dst, void *src);
|
||||
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
void tq_free(ThreadQueue **ptq)
|
||||
{
|
||||
ThreadQueue *tq = *ptq;
|
||||
|
||||
if (!tq)
|
||||
return;
|
||||
|
||||
if (tq->fifo) {
|
||||
FifoElem elem;
|
||||
while (av_fifo_read(tq->fifo, &elem, 1) >= 0)
|
||||
objpool_release(tq->obj_pool, &elem.obj);
|
||||
}
|
||||
av_fifo_freep2(&tq->fifo);
|
||||
|
||||
objpool_free(&tq->obj_pool);
|
||||
|
||||
av_freep(&tq->finished);
|
||||
|
||||
pthread_cond_destroy(&tq->cond);
|
||||
pthread_mutex_destroy(&tq->lock);
|
||||
|
||||
av_freep(ptq);
|
||||
}
|
||||
|
||||
ThreadQueue *tq_alloc(unsigned int nb_streams, size_t queue_size,
|
||||
ObjPool *obj_pool, void (*obj_move)(void *dst, void *src))
|
||||
{
|
||||
ThreadQueue *tq;
|
||||
int ret;
|
||||
|
||||
tq = av_mallocz(sizeof(*tq));
|
||||
if (!tq)
|
||||
return NULL;
|
||||
|
||||
ret = pthread_cond_init(&tq->cond, NULL);
|
||||
if (ret) {
|
||||
av_freep(&tq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = pthread_mutex_init(&tq->lock, NULL);
|
||||
if (ret) {
|
||||
pthread_cond_destroy(&tq->cond);
|
||||
av_freep(&tq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tq->finished = av_calloc(nb_streams, sizeof(*tq->finished));
|
||||
if (!tq->finished)
|
||||
goto fail;
|
||||
tq->nb_streams = nb_streams;
|
||||
|
||||
tq->fifo = av_fifo_alloc2(queue_size, sizeof(FifoElem), 0);
|
||||
if (!tq->fifo)
|
||||
goto fail;
|
||||
|
||||
tq->obj_pool = obj_pool;
|
||||
tq->obj_move = obj_move;
|
||||
|
||||
return tq;
|
||||
fail:
|
||||
tq_free(&tq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tq_send(ThreadQueue *tq, unsigned int stream_idx, void *data)
|
||||
{
|
||||
int *finished;
|
||||
int ret;
|
||||
|
||||
av_assert0(stream_idx < tq->nb_streams);
|
||||
finished = &tq->finished[stream_idx];
|
||||
|
||||
pthread_mutex_lock(&tq->lock);
|
||||
|
||||
if (*finished & FINISHED_SEND) {
|
||||
ret = AVERROR(EINVAL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
while (!(*finished & FINISHED_RECV) && !av_fifo_can_write(tq->fifo))
|
||||
pthread_cond_wait(&tq->cond, &tq->lock);
|
||||
|
||||
if (*finished & FINISHED_RECV) {
|
||||
ret = AVERROR_EOF;
|
||||
*finished |= FINISHED_SEND;
|
||||
} else {
|
||||
FifoElem elem = { .stream_idx = stream_idx };
|
||||
|
||||
ret = objpool_get(tq->obj_pool, &elem.obj);
|
||||
if (ret < 0)
|
||||
goto finish;
|
||||
|
||||
tq->obj_move(elem.obj, data);
|
||||
|
||||
ret = av_fifo_write(tq->fifo, &elem, 1);
|
||||
av_assert0(ret >= 0);
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
}
|
||||
|
||||
finish:
|
||||
pthread_mutex_unlock(&tq->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int receive_locked(ThreadQueue *tq, int *stream_idx,
|
||||
void *data)
|
||||
{
|
||||
FifoElem elem;
|
||||
unsigned int nb_finished = 0;
|
||||
|
||||
if (av_fifo_read(tq->fifo, &elem, 1) >= 0) {
|
||||
tq->obj_move(data, elem.obj);
|
||||
objpool_release(tq->obj_pool, &elem.obj);
|
||||
*stream_idx = elem.stream_idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < tq->nb_streams; i++) {
|
||||
if (!(tq->finished[i] & FINISHED_SEND))
|
||||
continue;
|
||||
|
||||
/* return EOF to the consumer at most once for each stream */
|
||||
if (!(tq->finished[i] & FINISHED_RECV)) {
|
||||
tq->finished[i] |= FINISHED_RECV;
|
||||
*stream_idx = i;
|
||||
return AVERROR_EOF;
|
||||
}
|
||||
|
||||
nb_finished++;
|
||||
}
|
||||
|
||||
return nb_finished == tq->nb_streams ? AVERROR_EOF : AVERROR(EAGAIN);
|
||||
}
|
||||
|
||||
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*stream_idx = -1;
|
||||
|
||||
pthread_mutex_lock(&tq->lock);
|
||||
|
||||
while (1) {
|
||||
ret = receive_locked(tq, stream_idx, data);
|
||||
if (ret == AVERROR(EAGAIN)) {
|
||||
pthread_cond_wait(&tq->cond, &tq->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
|
||||
pthread_mutex_unlock(&tq->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tq_send_finish(ThreadQueue *tq, unsigned int stream_idx)
|
||||
{
|
||||
av_assert0(stream_idx < tq->nb_streams);
|
||||
|
||||
pthread_mutex_lock(&tq->lock);
|
||||
|
||||
/* mark the stream as send-finished;
|
||||
* next time the consumer thread tries to read this stream it will get
|
||||
* an EOF and recv-finished flag will be set */
|
||||
tq->finished[stream_idx] |= FINISHED_SEND;
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
|
||||
pthread_mutex_unlock(&tq->lock);
|
||||
}
|
||||
|
||||
void tq_receive_finish(ThreadQueue *tq, unsigned int stream_idx)
|
||||
{
|
||||
av_assert0(stream_idx < tq->nb_streams);
|
||||
|
||||
pthread_mutex_lock(&tq->lock);
|
||||
|
||||
/* mark the stream as recv-finished;
|
||||
* next time the producer thread tries to send for this stream, it will
|
||||
* get an EOF and send-finished flag will be set */
|
||||
tq->finished[stream_idx] |= FINISHED_RECV;
|
||||
pthread_cond_broadcast(&tq->cond);
|
||||
|
||||
pthread_mutex_unlock(&tq->lock);
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FFTOOLS_THREAD_QUEUE_H
|
||||
#define FFTOOLS_THREAD_QUEUE_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "objpool.h"
|
||||
|
||||
typedef struct ThreadQueue ThreadQueue;
|
||||
|
||||
/**
|
||||
* Allocate a queue for sending data between threads.
|
||||
*
|
||||
* @param nb_streams number of streams for which a distinct EOF state is
|
||||
* maintained
|
||||
* @param queue_size number of items that can be stored in the queue without
|
||||
* blocking
|
||||
* @param obj_pool object pool that will be used to allocate items stored in the
|
||||
* queue; the pool becomes owned by the queue
|
||||
* @param callback that moves the contents between two data pointers
|
||||
*/
|
||||
ThreadQueue *tq_alloc(unsigned int nb_streams, size_t queue_size,
|
||||
ObjPool *obj_pool, void (*obj_move)(void *dst, void *src));
|
||||
void tq_free(ThreadQueue **tq);
|
||||
|
||||
/**
|
||||
* Send an item for the given stream to the queue.
|
||||
*
|
||||
* @param data the item to send, its contents will be moved using the callback
|
||||
* provided to tq_alloc(); on failure the item will be left
|
||||
* untouched
|
||||
* @return
|
||||
* - 0 the item was successfully sent
|
||||
* - AVERROR(ENOMEM) could not allocate an item for writing to the FIFO
|
||||
* - AVERROR(EINVAL) the sending side has previously been marked as finished
|
||||
* - AVERROR_EOF the receiving side has marked the given stream as finished
|
||||
*/
|
||||
int tq_send(ThreadQueue *tq, unsigned int stream_idx, void *data);
|
||||
/**
|
||||
* Mark the given stream finished from the sending side.
|
||||
*/
|
||||
void tq_send_finish(ThreadQueue *tq, unsigned int stream_idx);
|
||||
|
||||
/**
|
||||
* Read the next item from the queue.
|
||||
*
|
||||
* @param stream_idx the index of the stream that was processed or -1 will be
|
||||
* written here
|
||||
* @param data the data item will be written here on success using the
|
||||
* callback provided to tq_alloc()
|
||||
* @return
|
||||
* - 0 a data item was successfully read; *stream_idx contains a non-negative
|
||||
* stream index
|
||||
* - AVERROR_EOF When *stream_idx is non-negative, this signals that the sending
|
||||
* side has marked the given stream as finished. This will happen at most once
|
||||
* for each stream. When *stream_idx is -1, all streams are done.
|
||||
*/
|
||||
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data);
|
||||
/**
|
||||
* Mark the given stream finished from the receiving side.
|
||||
*/
|
||||
void tq_receive_finish(ThreadQueue *tq, unsigned int stream_idx);
|
||||
|
||||
#endif // FFTOOLS_THREAD_QUEUE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user