Compare commits

..

136 Commits

Author SHA1 Message Date
Michael Niedermayer 894da5ca7d Changelog: include last 3 fixes
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-20 02:43:51 +01:00
Zhao Zhili 4c788cb200 avutil/common: cast GET_BYTE/GET_16BIT returned value
In case of GET_BYTE/GET_16BIT return signed value.

(cherry picked from commit 0ae8df5f2c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-20 02:32:05 +01:00
Zhao Zhili 9c4d3a7add avfilter/vf_drawtext: fix call GET_UTF8 with invalid argument
For GET_UTF8(val, GET_BYTE, ERROR), val has type of uint32_t,
GET_BYTE must return an unsigned integer, otherwise signed
extension happened due to val= (GET_BYTE), and GET_UTF8 went to
the error path.

This bug incidentally cancelled the bug where hb_buffer_add_utf8
was being called with incorrect argument, allowing drawtext to
function correctly on x86 and macOS ARM, which defined char as
signed. However, on Linux and Android ARM environments, because
char is unsigned by default, GET_UTF8 now returns the correct
return, which unexpectedly revealed issue #20906.

(cherry picked from commit a5cc0e5c9e)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-20 02:31:47 +01:00
Zhao Zhili b5fb8749b9 avfilter/vf_drawtext: fix incorrect text length
From the doc of HarfBuzz, what hb_buffer_add_utf8 needs is the
number of bytes, not Unicode character:
hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));

Fix issue #20906.

(cherry picked from commit 9bc3c572ea)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-20 02:30:46 +01:00
Michael Niedermayer 946407193a Update for 8.0.1
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 03:51:22 +01:00
Michael Niedermayer 27def36203 avfilter/vf_drawtext: Account for bbox text seperator
Fixes: out of array access
no test case

Found-by: Joshua Rogers <joshua@joshua.hu> with ZeroPath
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit ad956ff076)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:03 +01:00
Michael Niedermayer 6777ab8e88 avcodec/mediacodecdec_common: Check that the input to mediacodec_wrap_sw_audio_buffer() contains channel * sample_size
Fixes: out of array access
no testcase

Found-by: Joshua Rogers <joshua@joshua.hu> with ZeroPath
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 41a9c6ec5f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:03 +01:00
Michael Niedermayer 0831f98933 avcodec/rv60dec: Clear blk_info
Fixes: use of uninitialized memory
Fixes: 418335931/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RV60_fuzzer-5103986067963904

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 729d0379ab)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:02 +01:00
Michael Niedermayer 719171a375 avformat/whip: Fix rtp_ctx->streams access
Fixes: out of array access
No testcase

Found-by: Joshua Rogers <joshua@joshua.hu> with ZeroPath
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c199b3d48f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:02 +01:00
Michael Niedermayer 6157fafd8a avcodec/utvideodec: Set B for the width= 1 case in restore_median_planar_il()
Fixes: use of uninitialized memory
Fixes: 439878388/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_UTVIDEO_DEC_fuzzer-5635866203848704

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 59db32b433)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:02 +01:00
Michael Niedermayer 6a1bb9c09f avcodec/osq: Fix 32bit sample overflow
Fixes: signed integer overflow: 2147483565 + 128 cannot be represented in type 'int'
Fixes: 428055715/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_OSQ_fuzzer-6358069900804096

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 08816b9376)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:02 +01:00
Michael Niedermayer 58efabb076 avformat/rtpdec_rfc4175: Only change PayloadContext on success
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c03e49dd1d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:02 +01:00
Michael Niedermayer b833558b76 avformat/rtpdec_rfc4175: Check dimensions
Fixes: out of array access
Fixes: zeropath/int_overflow_in_rtpdec_rfc4175

Found-by: Joshua Rogers <joshua@joshua.hu>
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d4e0d5ed48)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
Michael Niedermayer c1b57e2102 avformat/rtpdec_rfc4175: Fix memleak of sampling
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit af3dee3132)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
Michael Niedermayer cfc6fe6400 avformat/http: Fix off by 1 error
Fixes: out of array access
Fixes: zeropath/off-by-one-one-byte

Found-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b518c027a0)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
Michael Niedermayer 915272f5c7 avcodec/exr: spelling
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d80f8f3651)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
oblivionsage 5a6e2b0ab1 avcodec/rv60dec: add upper bound check for qp
The quantization parameter (qp) can exceed 63 when the base value
from frame header (0-63) is combined with the offset from slice data
(up to +2), resulting in qp=65. This causes out-of-bounds access to
the rv60_qp_to_idx[64] array in decode_cbp8(), decode_cbp16(), and
get_c4x4_set().

Fixes: Out-of-bounds read
Signed-off-by: oblivionsage <cookieandcream560@gmail.com>

No testsample is available

This is related to 61cbcaf93f and clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RV60_fuzzer-5160167345291264
which fixed rv60_qp_to_idx[qp + 32] out of array access
These 2 checks are not redundant and neither covers the cases of the other

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 8abeb879df)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
veygax a048a80554 avcodec/exr: use tile dimensions in pxr24 UINT case
update the switch statement for EXR_UINT in pxr24_uncompress to
correctly use the tile width td->xsize instead of using the full window
width s->xdelta. s->delta is larger than td->xsize which lead to two
buffer overflows when interacting with the ptr variable in the same
switch statement.

Fixes: out of bounds read and write
Found-by: veygax's insomnia network (INSOMNIA-1)
Signed-off-by: veygax <veyga@veygax.dev>
(cherry picked from commit 162f75b5e6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:01 +01:00
Michael Niedermayer 68e61becf9 avcodec/exr: Simple check for available channels
The existing is_luma check is fragile as depending on the order
of channels it can be set or reset

No testcase

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 6e8cf0377f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer bc680e230c avformat/sctp: Check size in sctp_write()
Fixes: out of array access
No testcase

Found-by: Joshua Rogers <joshua@joshua.hu> with ZeroPath
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 5b98cea4bf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer 89c5d8bdab avformat/rtmpproto: consider command line argument lengths
Fixes: out of array access
Fixes: zeropath/rtmp-2025-10

Found-by: Joshua Rogers <joshua@joshua.hu>
Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 83e0298de2)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer bb680a9d53 avformat/rtmpproto_ Check tcurl and flashver length
Fixes: out of array accesses

Reviewed-by: Joshua Rogers <joshua@joshua.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit a64e037429)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer dd062bfaf3 avcodec/g723_1enc: Make min_err 64bit
This is intending to fix the case described in https://lists.ffmpeg.org/archives/list/ffmpeg-devel@ffmpeg.org/thread/AAZ7GJPPUJI5SCVTDGJ6QL7UUEP56WOM/
Where FCBParam optim is used uninitialized

a min_err of 1<<30, allows the struct to be never initilialized as all
err (which is int32_t) can be larger than min_err. By increasing min_err
above the int32_t range this is no longer possible

Untested, as i do not have the testcase

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>i
(cherry picked from commit 909af3a571)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer a130ed479b avcodec/vlc: Clear val8/16 in vlc_multi_gen() by av_mallocz()
Fixes: use of uninitialized memory
Fixes: 427814450/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MAGICYUV_DEC_fuzzer-646512196065689
Fixes: 445961558/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_UTVIDEO_DEC_fuzzer-5515158672965632

the multi vlc code will otherwise return uninitialized data. Now one can argue that this data should
not be used, but on errors this data can remain ...

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d8ffec5bf9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:05:00 +01:00
Michael Niedermayer 8b42ed314a avformat/rtpenc_h264_hevc: Check space for nal_length_size in ff_rtp_send_h264_hevc()
Fixes: memcpy with negative size
Fixes: momo_trip-poc/input

Reported-by: Momoko Shiraishi <shiraishi@os.is.s.u-tokyo.ac.jp>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d03483bd26)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:59 +01:00
Michael Niedermayer 67ed7fddac avcodec/ffv1enc: Consider variation in slice sizes
When splitting a 5 lines image in 2 slices one will be 3 lines and thus need more space

Fixes: Assertion sc->slice_coding_mode == 0 failed at libavcodec/ffv1enc.c:1668
Fixes: 422811239/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FFV1_fuzzer-4933405139861504

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 388e6fb3be)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:59 +01:00
Michael Niedermayer 71ecb3d626 libavcodec/cbs_apv_syntax_template: limit tile to 2gb
We do not support larger tiles as we use signed int
Alternatively we can check this in apv_decode_tile_component() or init_get_bits*()
or support bitstreams above 2gb length

Fixes: init_get_bits() failure later
Fixes: 421817631/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-4957386534354944

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4666c1eed3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:59 +01:00
Michael Niedermayer dcf7f9b70c swscale/output: Fix unsigned cast position in yuv2*
Fixes: signed overflow

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 566e9032b1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:59 +01:00
Michael Niedermayer 716cf25eb8 swscale/output: Fix integer overflow in yuv2ya16_X_c_template()
Found-by: colod colod <colodcolod7@gmail.com>

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0c6b7f9483)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:59 +01:00
Michael Niedermayer aad0a7d8f6 avcodec/exr: Check that DWA has 3 channels
The implementation hardcodes access to 3 channels, so we need to check that
Fixes: out of array access
Fixes: BIGSLEEP-445394503-crash.exr

Found-by: Google Big Sleep
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7896cc67c1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Michael Niedermayer 1cac745f2d avcodec/exr: check ac_size
Fixes: out of array read
Fixes: dwa_uncompress.py.crash.exr

The code will read from the ac data even if ac_size is 0, thus that case
is not implemented and we ask for a sample and error out cleanly

Found-by: Google Big Sleep

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 8e078826da)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Michael Niedermayer ac0a59de51 avcodec/exr: Round dc_w/h up
Without rounding them up there are too few dc coeffs for the blocks.
We do not know if this way of handling odd dimensions is correct, as we have
no such DWA sample.
thus we ask the user for a sample if she encounters such a file

Fixes: out of array access
Fixes: BIGSLEEP-445392027-crash.exr

Found-by: Google Big Sleep
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c911e00011)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Michael Niedermayer 9f6c98a32e avcodec/mjpegdec: Explain buf_size/width/height check
Suggested-by: Ramiro

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 61b6877637)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Michael Niedermayer a7f9caa662 configure: strip non numeric trailer from gcc version
Fixes: ../configure: 7820: [: Illegal number: 13-win32

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b1cbc7c8ff)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Michael Niedermayer 8674f8c3cd avformat/dhav: Fix off by length of read element error
Fixes: out of array read
Fixes: BIGSLEEP-445383648
Fixes: crash_input_1/2/3.dhav

Found-by: Google Big Sleep
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 55e71768cf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:58 +01:00
Andreas Rheinhardt bb0e3e7a7c avformat/aviobuf: Keep checksum_ptr consistent in avio_seek()
Otherwise it might be > buf_ptr in which case ffio_get_checksum()
could segfault (s->buf_ptr - s->checksum_ptr would be negative
which would be converted to something very big when converted
to unsigned for the update_checksum callback).

Fixes ticket #11233.

Reported-by: Du4t
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit 987c955cd7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:57 +01:00
Zhao Zhili 277384f039 doc/examples/vaapi_encode: fix invalid check on fwrite
enc_pkt->size is 0 after av_packet_unref, which makes the check invalid.

Fix regression from 3e4bfff2.

Co-Authored-by: Jin Bo <jinbo@loongson.cn>
Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit 09856e4e48)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:57 +01:00
Andrey Semashev 4a73c79ad5 avcodec/librsvgdec: fix compilation with librsvg 2.50.3
This fixes compilation with librsvg 2.50.3: error: viewport undeclared

This was a regression since commit
86ed68420d.

Fixes #10722.

Reviewed-by: Leo Izen <leo.izen@gmail.com>
(cherry picked from commit 9ee7796c54)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:57 +01:00
Cameron Gutman 7d741cc3b4 avcodec/mfenc: fix memory leak with D3D11 input surfaces
Fixes: d56522c6eb ("avcodec/mfenc: add support for D3D11 input surfaces")
Signed-off-by: Cameron Gutman <aicommander@gmail.com>
(cherry picked from commit b2910ec92e)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:57 +01:00
Niklas Haas 520570dbeb swscale/graph: fix double-free when legacy pass fails initializing
If this function returns an error after ff_sws_graph_add_pass() has been
called, and the pass->free callback is therefore already set up to free the
context, the graph will end up freed twice: once by the pass->free callback
(during ff_sws_graph_free()), and once before that by failure path of the
caller (e.g. add_legacy_sws_pass(), or init_legacy_subpass() itself for
cascaded contexts.)

The solution is to redefine the ownership of SwsGraph to pass clearly from
the caller of add_legacy_sws_pass() to init_legacy_subpass(), which can then
deal with appropriately freeing the context conditional on whether or not the
pass was already registered in the pass list.

Reported-by: 김영민 <kunshim@naver.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry picked from commit 4ede75b5f4)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-11-19 02:04:57 +01:00
Desmond Liu 8e8c1f498d libavformat/udp: Fix call to recvfrom(2)
Last parameter to recvfrom() is not initialized, causing
recvfrom() to randomly return EINVAL. Issue was introduced in
af04a27893.

(cherry picked from commit 4348bde2d2)
2025-11-19 00:58:21 +00:00
Carl Hetherington via ffmpeg-devel 5630394ebf avfilter/f_ebur128: Fix incorrect ebur128 peak calculation.
Since 3b26b782ee it would only look at the
first channel.

Signed-off-by: Carl Hetherington <cth@carlh.net>
Reviewed-by: Niklas Haas <ffmpeg@haasn.xyz>
(cherry picked from commit 1eb2cbd865)
2025-11-18 08:56:57 +01:00
Brad Smith cb570f824d avformat/udp: fix warning about unused varible
libavformat/udp.c:283:9: warning: unused variable 'i' [-Wunused-variable]

Signed-off-by: Brad Smith <brad@comstyle.com>
(cherry picked from commit db0b86a4ad)
2025-11-16 21:13:46 -05:00
James Almer 2790dd608c avdevice/lavfi: stop setting deprecated buffersink options
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit b478037423)
2025-11-13 21:05:12 -03:00
Gyan Doshi 22d0f10943 configure: unbreak glslang build
Don't unconditionally link to libSPVRemapper which was removed in 16.0 in 3a7f787
2025-11-12 21:23:34 +01:00
Ramiro Polla 44bfe0da61 swscale/range_convert: fix truncation bias in range conversion
384fe39623 introduced a regression in the
range conversion offset calculation, resulting in a slight green tint
in full-range RGB to YUV conversions of grayscale values.

The offset being calculated was not taking into consideration a bias
needed for correctly rounding the result from the multiplication stage,
leading to a truncated value.

Fixes issue #11646.

(cherry picked from commit 4bee010844)
2025-11-06 21:57:08 +01:00
Bin Peng b660192fb8 lavc/aarch64: Fix addp overflow in ff_pred16x16_plane_neon_10
The mismatch between neon and C functions can be reproduced
using the following bitstream and command line on aarch64 devices.

wget https://streams.videolan.org/ffmpeg/incoming/replay_intra_pred_16x16.h264
 ./ffmpeg -cpuflags 0  -threads 1 -i replay_intra_pred_16x16.h264  -f framemd5 -y md5_ref
 ./ffmpeg              -threads 1 -i replay_intra_pred_16x16.h264 -f framemd5 -y md5_neon

Signed-off-by: Bin Peng <pengbin@visionular.com>
(cherry picked from commit 3115c0c0e6)
2025-11-03 15:53:36 +02:00
James Almer 71007e6c12 avcodec/mlpdec: don't depend on context channel layout when setting substream masks
If avctx->ch_layout is unset (as it's allowed and even expeced by the
AV_CODEC_CAP_CHANNEL_CONF flag), the code setting substream masks will fail for
stereo and mono layouts unless a downmix channel was requested.
Fix this by deriving the mask with coded values only.

Fixes issue #20764.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 530ca627a3)
2025-10-28 13:39:37 -03:00
James Almer 24205bc657 avformat/demux: pass new extradata to the parser
The parser API doesn't work with packets, only raw data, so in order for it to
be made aware of new extradata propagated through packet side data we need to
pass it in some other form, namely, replacing the main extradata and ensuring
it will be parsed by restarting the parser.

Signed-off-by: James Almer <jamrial@gmail.com>
2025-10-28 11:45:10 -03:00
Vittorio Palmisano 7cbc26267b avfilter/af_whisper: fix srt index
The srt index should be incremented for each segment.

(cherry picked from commit 9970dc32bf)
2025-10-20 12:46:16 +08:00
Vittorio Palmisano d8049e01d7 avfilter/af_whisper: fix int64 printf format
Use PRId64 for printing int64_t values in the SRT output.

(cherry picked from commit f18b1e2389)
2025-10-20 12:46:04 +08:00
Vittorio Palmisano adc819773b avfilter/af_whisper: fix srt file format
The SRT file format requires commas in the time string, not periods.

(cherry picked from commit 73d411c399)
2025-10-20 12:45:51 +08:00
Gyan Doshi b784c3eb6d avfilter/whisper: correct option formatting
(cherry picked from commit 7df9271272)
2025-10-20 12:45:40 +08:00
Zhao Zhili bb65f51fce avfilter/af_whisper: fix broken output for multibyte character
text + 1 can break a multibyte character, e.g., Chinese in UTF-8.
There is no space at the beginning in this case.

(cherry picked from commit 1d06e8ddcd)
2025-10-20 12:45:27 +08:00
Marvin Scholz d1f31a829d avformat/rtsp: fix leading space in RTSP reason
When parsing the RTSP message reason, the whole remainder
after parsing the status code was used, which would lead to
a leading space in the parsed reason string.

(cherry picked from commit e63e040f0c)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-10-16 15:57:19 +02:00
Marvin Scholz 1e56c51d3b avformat/rtsp: do not log invalid values
When reading fails the first time, ch would be uninitialized and
printed in the log message. Instead check for an error early and
log it properly.

(cherry picked from commit 2ed47ab725)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-10-16 15:57:19 +02:00
Marvin Scholz 45fcd5567a avformat/http: Handle IPv6 Zone ID in hostname
When using a literal IPv6 address as hostname, it can contain a Zone ID
especially in the case of link-local addresses. Sending this to the
server in the Host header is not useful to the server and in some cases
servers refuse such requests.

To prevent any such issues, strip the Zone ID from the address if it's
an IPv6 address. This also removes it for the Cookies lookup.

Based on a patch by: Daniel N Pettersson <danielnp@axis.com>

(cherry picked from commit 5cb6d2221a)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-10-16 15:57:19 +02:00
James Almer 558994b051 avformat/dump: fix log level passed to av_log when printing stream group side data
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 2e1d702cfc)
2025-10-15 20:31:21 -03:00
James Almer dd00a614e1 avcodec/hevc/sei: don't attempt to use stale values in HEVCSEITDRDI
Invalidate the whole struct on SEI reset.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 8e01bff774)
2025-10-09 12:15:41 -03:00
James Almer 046a8293e1 avcodec/hevc/sei: prevent storing a potentially bogus num_ref_displays value in HEVCSEITDRDI
Fixes: 439711052/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-4956250308935680
Fixes: out of array access

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit d448d6d1a0)
2025-10-09 12:15:41 -03:00
James Almer d961a634fb avcodec/hevc/refs: don't unconditionally discard non-IRAP frames if no IRAP frame was seen before
Should fix issue #20661

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 4377affc28)
2025-10-09 12:15:41 -03:00
Brad Smith d8605a6b55 libavutil/arm: Rename the HWCAP defines
Rename the HWCAP defines to use the same naming scheme as AArch64 and PPC.

(cherry picked from commit ced4a6ebc9)
Signed-off-by: Brad Smith <brad@comstyle.com>
2025-09-24 19:55:16 -04:00
Brad Smith c9b8e5999b libavutil/arm: Make use of elf_aux_info() on FreeBSD/OpenBSD
- FreBSD/OpenBSD have elf_aux_info() on arm
- Wrap AT_HWCAP as the value is different for BSD vs Linux (16 vs 25)

(cherry picked from commit cdae5c3639)
Signed-off-by: Brad Smith <brad@comstyle.com>
2025-09-24 19:53:04 -04:00
Patrick Wang b9adbf0fcc fftools/ffmpeg: fix gracefully shutdown
d119ae2fd8 removed the loop-breaking condition
received_sigterm.
Thus, signals no longer gracefully shutdown ffmpeg.

Fixes: #10834

Signed-off-by: Patrick Wang <mail6543210@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d7173e982e)
2025-09-22 22:46:25 +02:00
James Almer e322e2e5d9 avcodec/decode: sync initial_pict_type and intra_only_flag with thread worker's avctx
Regression since 5acbdd2264, which removed
setting both values from PerThreadContext.
Given the pthread code calls ff_decode_receive_frame_internal() on the frame,
any value set before it will be overwritten, so instead sync each thread's
DecodeContext and let ff_decode_receive_frame_internal() handle these values.

Fixes issue #20534.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 26f4230082)
2025-09-16 15:55:22 -03:00
James Almer 61c50407fd avcodec/x86/pngdsp: add missing emms at the end of add_png_paeth_prediction
Fixes unpredictable behavior with floats.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 57a29f2e7d)
2025-09-15 23:42:58 -03:00
Zhao Zhili b9dd25b80a avcodec/videotoolboxenc: ensure bitrate is set in low_delay mode
VideoToolbox doesn't support automatic bitrate in low delay mode.
Check bitrate and show error message so user knows what's going
wrong.

(cherry picked from commit c1dc2e2b7c)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-09-15 12:25:00 +00:00
Cameron Gutman 0ca188e0d6 avcodec/videotoolboxenc: allow low latency RC with HEVC
It is supported only for H.264 on Intel Macs, but it can be used with
both H.264 and HEVC on Apple Silicon.

Signed-off-by: Cameron Gutman <aicommander@gmail.com>
(cherry picked from commit d87210745e)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-09-15 12:25:00 +00:00
Zhao Zhili d3265e15ee avcodec/videotoolboxenc: support global_quality without qscale
(cherry picked from commit fc45127bcc)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-09-15 12:25:00 +00:00
Zhao Zhili a2179be5e9 avcodec/videotoolboxenc: fix the loss of precision when calculating quality
(cherry picked from commit 73750489a6)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2025-09-15 12:25:00 +00:00
James Almer 4f8b3891ee fftools/ffmpeg_demux: ensure the display_rotation option is honored
If requested, it should have priotity over any coded value.
Fixes ticket #11649.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 70a6ad6c74)
2025-09-11 23:24:00 -03:00
James Almer e0a971a8fa avcodec/mjpegdec: use ff_frame_new_side_data() to export display matrix
Otherwise, the user requested priority of packet side data will be ignored.

Signed-off-by: James Almer <jamrial@gmail.com>
2025-09-11 23:23:54 -03:00
James Almer 7cc24cee16 avutil/tests/aes_ctr: extend the test to cover payloads smaller than a block
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 799c133273)
2025-09-11 18:38:36 -03:00
James Almer e4e57bef31 avutil/aes_ctr: reintroduce the block offset state
Wrongly removed in fe73b84879, it's required for
calls with a payload smaller than a full block.

Fixes issue #20474.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 335ba4a649)
2025-09-11 18:38:36 -03:00
James Almer 08a81b090b avfilter/vf_lcevc: support LCEVCdec version 4
Signed-off-by: James Almer <jamrial@gmail.com>
2025-08-25 10:42:12 -03:00
James Almer 1c9d70c4af avcodec/lcevcdec: support LCEVCdec version 4
Signed-off-by: James Almer <jamrial@gmail.com>
2025-08-25 10:41:50 -03:00
Damiano Galassi e219c8f77b movenc: ensure chapters track extradata is not null and populated
fix a regression introduced in 4eca8df,
writing chapters failed if chapters where
not available before mov_write_header().

(cherry picked from commit b2f5bc7fd3)
2025-08-24 10:32:33 -03:00
Michael Niedermayer 140fd653ae Changelog: Remove "version <next>"
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-22 01:57:24 +02:00
Michael Niedermayer 09f15530e5 RELEASE_NOTES: Based on the version from 5.1
Name suggested by 3 people on ML

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-22 01:15:31 +02:00
Manuel Lauss af310e68db avcodec/sanm: fix issues with FTCH offset hack
Just add an extra x/y offset parameter pair to process_frame_obj(),
and store the size of the data to FTCH in a separate context member.
The only valid sizes for FTCH are 6 and 12, reject any other.
Finally, if a FOBJ uses codecs37 and above, enforce it to be subversion 2,
to use the simpler STOR/FTCH method.

Fixes BIGSLEEP-440183164/process_ftch.anim

Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d311382c38)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-22 01:07:20 +02:00
Michael Niedermayer c3747e011e avcodec/sanm: Eliminate reference into reallocated frame
AFAIK the original decoder uses the frame buffers in very strange ways
our implementation seems to mimic that and that results in the
bitstream input to point into a frame buffer while code then
parses that and potentially reallocates the frame buffer
leaving pointers hanging into dealllocated space

This simply uses a temporary buffer

Fixes: Writing into freed buffers
Fixes: BIGSLEEP-440183164/old_codec21.anim
Fixes: BIGSLEEP-440183164/old_codec4.anim

Found-by: Google Big Sleep

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c41a70b6bb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-22 01:07:20 +02:00
Michael Niedermayer f258c9a8e5 avcodec/sanm: Replace impossible bitstream check by assert
the space left and size have already been cross checked by the caller

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d4e28917af)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-22 01:07:19 +02:00
Marvin Scholz a6c578ef65 avformat/hlsproto: explicitly deprecate it
This makes it more clear that it will be removed in a future release.
2025-08-22 00:28:33 +02:00
Mark Thompson efa64c2acc hwcontext_vulkan: Fix build with older Vulkan headers
(cherry picked from commit 4a42e5a1e2)
2025-08-22 04:44:19 +09:00
Mark Thompson 9c5f654e44 hwcontext_vulkan: Fix build
(cherry picked from commit 19473362fc)
2025-08-22 04:44:19 +09:00
Mark Thompson 5494973d28 cbs_vp9: Fix VP9 passthrough
Don't overwrite the bitstream values when updating the top-level loop
filter and segmentation state, instead do the update separately at the
end of the frame parsing.

This also reverts the change to the passthrough tests which made them
have output not matching the input.

(cherry picked from commit 26a2a76346)
2025-08-22 04:44:19 +09:00
Benjamin Cheng 15cb74fc68 vulkan_vp9: Read segment and lf data from cbs
The previous change 26a2a76346 broke Vulkan decoding because the lf and
segmentation values contained within VP9RawFrameHeader can no longer be
updated.

Read the propogated values from the CBS instead.

(cherry picked from commit 7bfaa6d662)
2025-08-22 04:42:30 +09:00
vytskalt 9ddd245b09 hwcontext_vulkan: transfer EXCLUSIVE images to correct queue families
(cherry picked from commit a6b5a382dd)
2025-08-22 04:42:30 +09:00
Lynne c1a7f4040a lavfi/bwdif_vulkan: fix typo in temp_diff assignment
Thanks to Niklas Haas for pointing this out.

(cherry picked from commit 451e6bed43)
2025-08-22 04:42:30 +09:00
Kacper Michajłow 17f4cc0992 avcodec/vulkan_encode_av1: use CODEC_PIXFMTS to define pix_fmts
Fixes deprecation warnings.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit b7a3c426ea)
2025-08-22 04:42:30 +09:00
Niklas Haas eeff85f15d avutil/hwcontext_vulkan: also re-query dprops in device_init()
This can be unset if using an externally provided device, as in this case
device_create() never gets called.

(cherry picked from commit 881224b213)
2025-08-22 04:42:30 +09:00
Michael Niedermayer bc88c1d62e Prepare for 8.0
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 21:51:04 +02:00
Lynne 3b8fe34a30 aacdec_usac: use RefStruct to track unfinished extension buffers
Extensions in AAC USAC can be stored across multiple frames (mainly to keep CBR compliance).
This means that we need to reallocate a buffer when new data is received, accumulate the bitstream data,
and so on until the end of extension flag is signalled and the extension can be decoded.

This is made more complicated by the way in which the AAC channel layout switching is performed.
After decades of evolution, our AAC decoder evolved to double-buffer its entire configuration.
All changes are buffered, verified, and applied, on a per-frame basis if required, in often
random order.

Since we allocate the extension data on heap, this means that if configuration is applied,
in order to avoid double-freeing, we have to keep track of what we've allocated.

It should be noted that extensions which are spread in multiple frames are generally rare,
so an optimization to introduce av_refstruct_realloc() wouldn't generally be useful across the codebase.
Therefore, a copy is good enough for now.

Thanks to Michael Niedermayer for additional fixing.

Fixes: double free
Fixes: 393523547/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AAC_LATM_fuzzer-6740617236905984

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
(cherry picked from commit c05fc27dd3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:52 +02:00
Michael Niedermayer ac8cbf2ad7 avcode: Use av_fast_realloc() in ff_lzf_uncompress()
Fixes: 438961582/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_DEC_fuzzer-5850827739955200
Fixes: mixed up realloc() functions

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Co-Authored-by: James Almer <jamrial@gmail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 0a5046c099)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:52 +02:00
Michael Niedermayer 30b308f7a8 avcodec/dxv: Check coded_height, to avoid invalid av_clip()
Fixes: assertion failure
Fixes: 438961582/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_DEC_fuzzer-5850827739955200

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit cdee519d40)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:51 +02:00
Michael Niedermayer afc8c20946 avcodec/aac/aacdec: dont allow ff_aac_output_configure() allocating a new frame if it has no frame
Fixes: null pointer dereference
Fixes: crash_test.mp4

Found-by: Intel PSIRT
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit fcf180d9ea)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:51 +02:00
Michael Niedermayer debbeb006b avformat/lrcdec: Fix fate-sub-lrc-ms-remux on x86-32
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0243cf89b1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:51 +02:00
Michael Niedermayer 8c117d7fec swscale/swscale_internal: Use more precisse gamma
Avoids failure of xyz12 fate tests on mingw and linux x86-32

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit ca20d42cd7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:50 +02:00
Michael Niedermayer 5f8cb575e8 avcodec/sanm: Check w,h,left,top
The setup code fow w,h,left,top is complex, the code using it also falls in
at least 2 different classes, one using left/top the other not.

To ensure no out of array access happens we add this clear check.

Fixes: out of array access
Fixes: 439261995/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SANM_fuzzer-5383455572819968

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 134fbfd1dc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:50 +02:00
James Almer abf123b744 avformat/mov: don't use an allocated array for sample_size with HEIF images
The array is only ever needed for streams where each sample entry may have a
different value. Given that for non animated HEIF there's a single value that
applies to the image, use the field defined for that.

Fixes: NULL pointer dereference
Fixes: 437528618/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6537287645331456

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit a28e01a6c1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:50 +02:00
Michael Niedermayer e97babf6bc avcodec/rv60dec: clear pu_info
pu_info is read uninitialized on damaged input and at that point the following codepath is dependant
on the uninitialized data. In one of these pathes out of array accesses happen.
None of this is replicatable

Less uninitialized data also should result in more reproducable reports

Fixes: Use of uninitialized memory
Fixes: 418335931/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RV60_fuzzer-5103986067963904

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 50affd2b09)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:49 +02:00
Kacper Michajłow 9bc89a2605 avformat/tls_openssl: use ascii - (0x2D) instead of 0x2010 hyphen
Too much AI is bad for you...

Fixes: 167e343bbe
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit 3a8b3dfeca)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:49 +02:00
Michael Niedermayer ac5ff0ae89 avcodec/utvideodec: Clear plane_start array
in pack mode the array is passed into decode_plane() without being initialized or used

Fixes: use of uninitialized memory
Fixes: 438780119/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_UTVIDEO_DEC_fuzzer-5464037027807232

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 2a22972db3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:48 +02:00
Oliver Chang a2e445918e avcodec/prores_raw: Fix heap buffer overflow
When dimensions differ from context, those were updated using
ff_set_dimensions, however this overwrote the aligned coded_width and
coded_height that were set before, leading to a buffer overflow when
writing the frame data.

Fixes: OssFuzz 438771336
Fixes: Heap-buffer-overflow

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Reviewed-by: Marvin Scholz <epirat07@gmail.com>
(cherry picked from commit c9e93df4ee)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:48 +02:00
Michael Niedermayer 34c39367aa .forgejo/CODEOWNERS: remove reference to secret apparently uncommited code
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7d606ef0cc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:48 +02:00
Michael Niedermayer 3cab009519 fftools/ffmpeg_mux_init: Use 64bit for score computation in map_auto_video()
Fixes: signed integer overflow: 10 * 1952737655 cannot be represented in type 'int'
Fixes: PoC_avi_demux

Found-by: 2ourc3 (Salim LARGO)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit cdbb5f1b93)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:47 +02:00
Michael Niedermayer 3e05b89590 tools/merge-all-source-plugins: Fix merge_internal() return code
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b5b306ca31)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:47 +02:00
Michael Niedermayer 4a3e5ea8d2 tools: Split the list of source plugins out of "merge-all-source-plugins"
(cherry picked from commit fd31df4306)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:47 +02:00
Jiasheng Jiang 263e819aa4 libavfilter/dnn/dnn_backend_tf: Remove redundant av_freep() to avoid double free
Remove redundant av_freep() to avoid double free since task will be freed in dnn_free_model_tf() after the success of ff_queue_push_back().

Fixes: af052f9066 ("lavfi/dnn: fix mem leak in TF backend error handle")
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
(cherry picked from commit b8d5f65b9e)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:46 +02:00
Michael Niedermayer 23655160ea avcodec/dxv: Use av_fast_realloc() for op_data
makes things consistent

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 373bd80b16)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:46 +02:00
Michael Niedermayer f2507dba3b avcodec/dxv: Use av_fast_realloc() and clear all new space
The code writing in the buffer has a wide range of error checks
which simply leave it partly uninitialized.

Initializing it on allocation ensures no sensitive data leaks and that
bugs are more reliably reproduceable

Fixes: use of uninitialized memory
Fixes: 435225510/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_DEC_fuzzer-4521918634196992

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4a0b793737)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:46 +02:00
Michael Niedermayer da3f5273fc avcodec/dxv: Clear ctex
same issue as with tex

Fixes: 431665305/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_DEC_fuzzer-5339599339847680
Fixes: use of uninitialized memory

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4e5f25c0a5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:45 +02:00
Michael Niedermayer 6049800a10 avcodec/dxv: Check that we initialize op_data
Fixes: 431665305/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_DEC_fuzzer-5339599339847680
Fixes: use of uninitialized memory

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 6a8c41dcac)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:45 +02:00
Michael Niedermayer e726f7af17 avcodec/sanm: Check mv in codec48_block()
Fixes: out of array read
Fixes: 436943287/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SANM_fuzzer-5011037029203968

This issue did oddly enough, not replicate

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d5bdb0b705)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:45 +02:00
Michael Niedermayer de76fb27a6 avcodec/exr: Check for pixel type consistency in DWA
Fixes: out of array access
Fixes: BIGSLEEP-436511754/testcase.exr

Found-by: Google Big Sleep
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0469d68acb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:44 +02:00
Kacper Michajłow 995d329cf9 avcodec/d3d12va_encode: fix label followed by a declaration warning
Fixes: d3d12va_encode.c: warning: label followed by a declaration is a
       C23 extension

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit ac6db22e37)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:44 +02:00
Kacper Michajłow 81dcb67813 avcodec/libvorbisdec: avoid overflow when assinging sample rate from long to int
Fixes: 416134551/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_LIBVORBIS_DEC_fuzzer-6096101407260672
Found-by: OSS-Fuzz
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit 2287a19abb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:44 +02:00
Kacper Michajłow bde02336a4 avcodec/g726: init missing sample rate
Fixes: 416134551/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ADPCM_G726_DEC_fuzzer-5695764455292928
Found-by: OSS-Fuzz
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit c2f7dae70d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:43 +02:00
Kacper Michajłow 6b1f994e43 avformat/lrcdec: limit input timestamp range to avoid overflows
Fixes: clusterfuzz-testcase-ffmpeg_dem_LRC_fuzzer-5226140131459072
Found-by: OSS-Fuzz
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit c74bc74398)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:43 +02:00
Michael Niedermayer 5051753833 avcodec/scpr3: Clear clr
clr is passing into decode_run_p() its not used when not set
but this possibly triggers msan (it doesnt locally)

Fixes?: use of uninintialized memory
Fixes?: 436997807/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SCPR_fuzzer-6253316466606080

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 3542260376)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:42 +02:00
Michael Niedermayer a676267a2c avcodec/ilbcdec: Clear cbvec when used with create_augmented_vector()
Fixes: use of uninitialized memory
Fixes: 42538134/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ILBC_fuzzer-6322020827070464

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9686fdd729)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:42 +02:00
Kacper Michajłow bd55bf8300 avformat/mov: clear old name from infe
heif_items are reused and to avoid leaking memory or using stale name,
clear it first.

Fixes: 432505829/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6654363487764480
Found-by: OSS-Fuzz
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit 3bf8bf965f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:42 +02:00
Leon Grutters 64c71cbe4e doc/community.texi: fix spelling error
Fixes: 262d41c804 ("all: fix typos found by codespell")
Signed-off-by: Leon Grutters <gruttersleonbot2@gmail.com>
(cherry picked from commit 777408d149)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:41 +02:00
Michael Niedermayer 2feaad5cb9 tools/merge-all-source-plugins: set version
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-19 17:56:41 +02:00
wangbin 048f6f4bd5 configure: fix -L flags for lld-link 2025-08-15 20:22:51 +02:00
Kacper Michajłow 4558ad6a77 avcodec/Makefile: add missing dependency for prores raw decoder (again)
proresdata.o is also needed, missed in a9e7b5aa07

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-14 21:08:15 +02:00
Kacper Michajłow 937d9ed849 avcodec/Makefile: add missing dependency for prores raw decoder
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-14 07:54:51 -04:00
James Almer 13b161cd24 avcodec/cbs_apv: store derived tile information in a per frame basis
If a single fragment contains more than one frame unit, the tile information stored
in the private context will only correspond to one of them.

Fixes: crash (out of array access)
Fixes: 435489659/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-6194885205229568

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 4b39d776c3)
2025-08-12 19:13:06 -03:00
Michael Niedermayer 7c92f740ee avcodec/apv_decode: make apv_format_table consistent with the code and check it
Fixes: writing in a null pointer
Fixes: 435278398/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-4566392923029504

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit cfce595572)
2025-08-12 19:13:06 -03:00
Marton Balint 057b94649f swscale/swscale_unscaled: use 8 line alignment for planarCopyWrapper with dithering
Dithering relies on a 8 line dithering table and the code always uses it from
the beginning. So in order to make dithering independent from height of the
slices used we must enforce a 8 line alignment.

Fixes issue #20071.

Signed-off-by: Marton Balint <cus@passwd.hu>
(cherry picked from commit b61e510e75)
2025-08-13 00:02:59 +02:00
Martin Storsjö 26da3d0069 fate: Fix the sub-mcc tests on Windows in eastern time zones
Previously, these tests failed when running on Windows, if the
system is configured with a time zone east of Greenwich, i.e.
with a positive GMT offset.

The muxer converts the creation_date given by the user using
av_parse_time to unix time, as a time_t. The creation_date is
interpreted as a local time, i.e. according to the current time
zone. (This time_t value is then converted back to a broken out
local time form with localtime_r.)

The given reference date/time, "1970-01-01T00:00:00", is the
origin point for unix time, corresponding to time_t zero. However
when interpreted as local time, this doesn't map to exactly zero.
Time zones east of Greenwich reached this time a number of hours
before the point of zero time_t - so the corresponding time_t
value essentially is minus the GMT offset, in seconds.

Windows mktime returns an error, returning (time_t)-1, when given
such a "struct tm", while e.g. glibc mktime happily returns a
negative time_t. av_parse_time doesn't check the return value of
mktime for potential errors.

This is observable with the following test snippet:

    struct tm tm = { 0 };
    tm.tm_year = 70;
    tm.tm_isdst = -1;
    tm.tm_mday = 1;
    tm.tm_hour = 0;
    time_t t = mktime(&tm);
    printf("%d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
    printf("t %d\n", (int)t);

By varying the value of tm_hour and the system time zone, one
can observe that Windows mktime returns -1 for all time_t values
that would have been negative.

This range limit is also documented by Microsoft in detail at
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/mktime-mktime32-mktime64.

To avoid the issue, pick a different, arbitrary reference time,
which should have a nonnegative time_t for all time zones.

(cherry picked from commit 13139d6d83)
Signed-off-by: Martin Storsjö <martin@martin.st>
2025-08-12 13:45:57 +03:00
Leo Izen a8fdfddedb avcodec/vp9: fix leaked cbs fragment AVBufferRef
When this function returns, the fragment is never reset, so
current_frag->data_ref is never unref-ed, which ends up leaking it.
We call ff_cbs_fragment_reset to release the reference on its buffer.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
2025-08-10 21:05:43 -04:00
Jacob Lifshay 89849ca92a tests/fate/subtitles: add test for smpte436m_to_eia608 bsf
Signed-off-by: Jacob Lifshay <programmerjake@gmail.com>
2025-08-10 13:13:35 -04:00
Jacob Lifshay 370cff8b33 lavc/bsf/smpte436m_to_eia608: fix memory leak -- forgot to free input av_packet
Signed-off-by: Jacob Lifshay <programmerjake@gmail.com>
2025-08-10 13:13:26 -04:00
Jacob Lifshay 9fd3869212 lavc/bsf/eia608_to_smpte436m: fix memory leak -- forgot to free input av_packet
reported in https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20024#issuecomment-2405

Reported-by: Sean McGovern <gseanmcg@gmail.com>
Signed-off-by: Jacob Lifshay <programmerjake@gmail.com>
2025-08-10 13:13:15 -04:00
Jacob Lifshay 0a167141d0 tests/fate/subtitles: fix mcc test input file paths
they use tests/ref/fate/sub-mcc-remux as input,
so prefix them with $(SRC_PATH) so building works
when not in the source directory.

Fixes: #20183
Reported-by: Sean McGovern <gseanmcg@gmail.com>
Signed-off-by: Jacob Lifshay <programmerjake@gmail.com>
2025-08-10 13:13:07 -04:00
3017 changed files with 61401 additions and 180651 deletions
+7 -176
View File
@@ -12,173 +12,45 @@
# =======
libavcodec/.*aac.* @lynne
libavcodec/.*ac3.* @lynne
libavcodec/.*adpcm.* @zane @pross
libavcodec/anm.* @pross
libavcodec/amf.* @OvchinnikovDmitrii @ArazIusubov
libavcodec/ansi.* @pross
libavcodec/aom_film_grain.* @haasn
libavcodec/.*atrac9.* @lynne
libavcodec/bink.* @pross
libavcodec/bintext.* @pross
libavcodec/.*bitpacked.* @lynne
libavcodec/.*d3d12va.* @jianhuaw @tong1wu @younengxiao
libavcodec/.*d3d12va.* @jianhuaw
libavcodec/.*dirac.* @lynne
libavcodec/.*dovi_rpu.* @haasn
libavcodec/dpx.* @pross
libavcodec/dsd.* @pross
libavcodec/eacmv.* @pross
libavcodec/eaidct.* @pross
libavcodec/eamad.* @pross
libavcodec/eat.* @pross
libavcodec/.*exif.* @Traneptora
libavcodec/.*ffv1.* @lynne @michaelni
libavcodec/g728.* @pross
libavcodec/gem.* @pross
libavcodec/golomb.* @michaelni
libavcodec/.*h266.* @frankplow @NuoMi @jianhuaw
libavcodec/h26x/.* @frankplow @NuoMi @jianhuaw
libavcodec/.*h274.* @haasn
libavcodec/iff.* @pross
libavcodec/.*jpegxl.* @lynne @Traneptora
libavcodec/jpeg2000htdec.* @cae
libavcodec/jv.* @pross
libavcodec/.*jxl.* @lynne @Traneptora
libavcodec/.*lcms2.* @haasn
libavcodec/lead.* @pross
libavcodec/mediacodec* @quink
libavcodec/mjpeg* @michaelni
libavcodec/mmvideo.* @pross
libavcodec/msp2.* @pross
libavcodec/mvc.* @pross
libavcodec/oh* @quink
libavcodec/.*jpegxl.* @lynne
libavcodec/.*jxl.* @lynne
libavcodec/.*opus.* @lynne
libavcodec/pictor.* @pross
libavcodec/.*png.* @Traneptora
libavcodec/.*prores.* @lynne
libavcodec/rangecoder.* @michaelni
libavcodec/ratecontrol.* @michaelni
libavcodec/rkmpp* @quink
libavcodec/rv60.* @pross
libavcodec/sgirle.* @pross
libavcodec/.*siren.* @lynne
libavcodec/smpte_436m.* @programmerjake
libavcodec/svq1.* @pross
libavcodec/svq3.* @pross
libavcodec/.*vc2.* @lynne
libavcodec/videotoolbox.* @ePirat
libavcodec/vp3.* @pross
libavcodec/vp4.* @pross
libavcodec/vp5.* @pross
libavcodec/vp6.* @pross
libavcodec/vp8.* @rbultje @pross
libavcodec/vp9.* @rbultje
libavcodec/vpx.* @rbultje @pross
libavcodec/vqc.* @pross
libavcodec/.*vvc.* @frankplow @NuoMi @jianhuaw
libavcodec/wmavoice.* @rbultje
libavcodec/wbmp.* @pross
# bitstream filters
libavcodec/bsf/eia608_to_smpte436m.* @programmerjake
libavcodec/bsf/smpte436m_to_eia608.* @programmerjake
# architecture-specific
libavcodec/aarch64/.* @lynne @mstorsjo
libavcodec/arm/.* @mstorsjo
libavcodec/ppc/.* @sean_mcg
libavcodec/riscv/.* @Courmisch
libavcodec/wasm/hevc/.* @quink
libavcodec/x86/.* @lynne
libavcodec/x86/vp8.* @rbultje
libavcodec/x86/vp9.* @rbultje
libavcodec/x86/vpx.* @rbultje
# avfilter
# =======
libavfilter/af_loudnorm.* @kylophone
libavfilter/aarch64/.* @mstorsjo
libavfilter/af_whisper.* @vpalmisano
libavfilter/.*_amf* @OvchinnikovDmitrii @ArazIusubov
libavfilter/avfiltergraph.* @haasn
libavfilter/colorspace.* @rbultje
libavfilter/formats.* @haasn
libavfilter/.*f_ebur128.* @haasn
libavfilter/vf_blackdetect.* @haasn
libavfilter/vf_colordetect.* @haasn
libavfilter/vf_colorspace.* @rbultje
libavfilter/.*drawvg.* @ayosec
libavfilter/vf_find_rect.* @michaelni
libavfilter/vf_icc.* @haasn
libavfilter/vf_libplacebo.* @haasn
libavfilter/vf_libvmaf.* @kylophone
libavfilter/vf_mpdecimate.* @dana-feng
libavfilter/vf_premultiply.* @haasn
libavfilter/vf_scale.* @haasn
libavfilter/vf_scale_vt.* @quink
libavfilter/vf_thumbnail.* @haasn
libavfilter/vf_transpose_vt.* @quink
libavfilter/vf_yadif.* @michaelni
libavfilter/vsrc_mandelbrot.* @michaelni
libavfilter/aarch64/.* @mstorsjo
libavfilter/riscv/.* @Courmisch
libavfilter/x86/colorspace.* @rbultje
libavfilter/x86/scene_sad.* @haasn
# avformat
# =======
libavformat/alp.* @zane
libavformat/amv.* @zane
libavformat/anm.* @pross
libavformat/apm.* @zane
libavformat/argo_.* @zane
libavformat/bink.* @pross
libavformat/bintext.* @pross
libavformat/caf.* @pross
libavformat/cine.* @pross
libavformat/dsf.* @pross
libavformat/eacdata.* @pross
libavformat/electronicarts.* @pross
libavformat/.*exif.* @Traneptora
libavformat/filmstrip.* @pross
libavformat/frm.* @pross
libavformat/hls.* @kasper93
libavformat/hxvs.* @quink
libavformat/iamf.* @jamrial
libavformat/icecast.c @ePirat
libavformat/ico.* @pross
libavformat/iff.* @pross
libavformat/.*jpegxl.* @Traneptora
libavformat/jv.* @pross
libavformat/.*jxl.* @Traneptora
libavformat/kvag.* @zane
libavformat/mccdec.* @programmerjake
libavformat/mccenc.* @programmerjake
libavformat/mlv.* @pross
libavformat/mm.* @pross
libavformat/msp.* @pross
libavformat/mv.* @pross
libavformat/ogg.* @toots
libavformat/pp_bnk.* @zane
libavformat/rm.* @pross
libavformat/sauce.* @pross
libavformat/scd.* @zane
libavformat/tty.* @pross
libavformat/whip.c @JackLau
libavformat/wsd.* @pross
libavformat/wtv.* @pross
# avutil
# ======
libavutil/.*_amf* @OvchinnikovDmitrii @ArazIusubov
libavutil/.*crc.* @lynne @michaelni
libavutil/.*d3d12va.* @jianhuaw @tong1wu @younengxiao
libavutil/csp.* @rbultje @haasn
libavutil/.*d3d12va.* @jianhuaw
libavutil/eval.* @michaelni
libavutil/film_grain.* @haasn
libavutil/dovi_meta.* @haasn
libavutil/hwcontext_oh.* @quink
libavutil/hwcontext_mediacodec.* @quink
libavutil/hwcontext_videotoolbox.* @ePirat
libavutil/iamf.* @jamrial
libavutil/integer.* @michaelni
libavutil/lfg.* @michaelni
@@ -197,8 +69,6 @@ libavutil/tx.* @lynne
libavutil/aarch64/.* @lynne @mstorsjo
libavutil/arm/.* @mstorsjo
libavutil/ppc/.* @sean_mcg
libavutil/riscv/.* @Courmisch
libavutil/wasm/.* @quink
libavutil/x86/.* @lynne
# swresample
@@ -212,13 +82,6 @@ libswresample/.* @michaelni
libswscale/aarch64/.* @mstorsjo
libswscale/arm/.* @mstorsjo
libswscale/ppc/.* @sean_mcg
libswscale/riscv/.* @Courmisch
libswscale/.* @haasn
# tools
# =====
fftools/ffplay_renderer.* @haasn
tools/target_dec_fuzzer.c @michaelni
# doc
# ===
@@ -226,37 +89,5 @@ doc/.* @GyanD
# Frameworks
# ==========
.*d3d12va.* @jianhuaw @tong1wu @younengxiao
.*vulkan.* @lynne @haasn
# tests
# =====
tests/checkasm/riscv/.* @Courmisch
libavutil/tests/ambient_viewing_environment.* @MarcosAsh
libavutil/tests/buffer.* @MarcosAsh
libavutil/tests/csp.* @MarcosAsh
libavutil/tests/dovi_meta.* @MarcosAsh
libavutil/tests/hdr_dynamic_vivid_metadata.* @MarcosAsh
libavutil/tests/mastering_display_metadata.* @MarcosAsh
libavutil/tests/tdrdi.* @MarcosAsh
libavutil/tests/timestamp.* @MarcosAsh
libavutil/tests/video_hint.* @MarcosAsh
tests/ref/.*drawvg.* @ayosec
tests/ref/fate/ambient_viewing_environment @MarcosAsh
tests/ref/fate/buffer @MarcosAsh
tests/ref/fate/csp @MarcosAsh
tests/ref/fate/dovi_meta @MarcosAsh
tests/ref/fate/hdr_dynamic_vivid_metadata @MarcosAsh
tests/ref/fate/mastering_display_metadata @MarcosAsh
tests/ref/fate/sub-mcc.* @programmerjake
tests/ref/fate/tdrdi @MarcosAsh
tests/ref/fate/timestamp @MarcosAsh
tests/ref/fate/video_hint @MarcosAsh
# Forgejo
# =======
.forgejo/CODEOWNERS @michaelni
# /
# =
MAINTAINERS @michaelni
.*d3d12va.* @jianhuaw
.*vulkan.* @lynne
-14
View File
@@ -1,14 +0,0 @@
# Summary of changes
Briefly describe what this PR does and why.
<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).
Attached filenames must match the sample's filename:
```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->
-40
View File
@@ -1,40 +0,0 @@
name: Rebase PR onto target
inputs:
path:
description: Directory to run in
required: false
default: .
runs:
using: composite
steps:
- name: Rebase onto target branch
if: ${{ forge.event_name == 'pull_request' }}
working-directory: ${{ inputs.path }}
run: |
set -x
# Fetch all PR commits + merge-base
commits=$(curl -s -o /dev/null -w '%header{X-Total-Count}' '${{ forge.api_url }}/repos/${{ forge.repository }}/pulls/${{ forge.event.pull_request.number }}/commits?limit=1&verification=false&files=false')
git fetch -vv --deepen=$commits origin pull/${{ forge.event.pull_request.number }}/head
if [ "$(wc -l < .git/shallow)" -ne 1 ]; then
echo "Complex PR history detected, falling back to merge"
git fetch -vv --unshallow origin pull/${{ forge.event.pull_request.number }}/head
git fetch -vv origin ${{ forge.base_ref }}
git merge --no-edit origin/${{ forge.base_ref }} \
|| { echo "Does not merge cleanly with ${{ forge.base_ref }}"; exit 1; }
exit 0
fi
# Unfortunately, Forgejo does not update the merge-base when PR branch
# is updated, the `forge.event.pull_request.merge_base` is stale value,
# from the time when PR was created. We cannot rely on it, so try to
# infer parent commit of the PR from the shallow clone that we have.
base=$(cat .git/shallow)
# Fetch target branch
git fetch -vv --depth=1 origin ${{ forge.base_ref }}
# Rebase PR commits onto the current state of target branch
git rebase --onto origin/${{ forge.base_ref }} $base \
|| { echo "Does not rebase cleanly onto ${{ forge.base_ref }}"; exit 1; }
-174
View File
@@ -1,174 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2026 Romain Beauxis <romain.beauxis@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""Inject PR attachment samples into the fate-suite directory.
Usage: inject-pr-samples.py <pr-number>
Reads SAMPLES from the environment (defaults to fate-suite). For each path
listed in a ```fate-samples``` block in the PR description, downloads the
matching PR attachment into $SAMPLES/<path>.
The PR description should contain a block like:
```fate-samples
vorbis/tos.ogg
mov/some-new-sample.mov
```
Each filename must match a file attached to the PR.
"""
import hashlib
import json
import os
import re
import sys
import tempfile
import urllib.request
from pathlib import Path, PurePosixPath
FORGEJO_API = "https://code.ffmpeg.org/api/v1/repos/ffmpeg/ffmpeg/issues"
ATTACHMENT_BASE = "https://code.ffmpeg.org/attachments/"
def fetch_json(url):
with urllib.request.urlopen(url) as r:
return json.load(r)
def parse_fate_samples(body):
paths = []
in_block = False
for line in body.splitlines():
if line == "```fate-samples":
in_block = True
elif line == "```" and in_block:
break
elif in_block:
parts = line.split()
if len(parts) == 1:
paths.append(parts[0])
return paths
MAX_PATH_DEPTH = 3
def validate_path(path):
p = PurePosixPath(path)
if p.is_absolute():
raise ValueError(f"path must be relative: {path!r}")
if ".." in p.parts:
raise ValueError(f"path must not contain '..': {path!r}")
if not p.parts:
raise ValueError(f"empty path")
if len(p.parts) > MAX_PATH_DEPTH:
raise ValueError(f"path too deep (max {MAX_PATH_DEPTH} components): {path!r}")
def validate_url(url):
if not url.startswith(ATTACHMENT_BASE):
raise ValueError(f"unexpected attachment URL: {url!r}")
def digest(path):
h = hashlib.sha256()
with open(path, "rb") as f:
while chunk := f.read(1 << 16):
h.update(chunk)
return h.digest()
def download(url, dst):
dst.parent.mkdir(parents=True, exist_ok=True)
with tempfile.NamedTemporaryFile(dir=dst.parent, delete=False) as tmp:
tmp_path = Path(tmp.name)
try:
with urllib.request.urlopen(url) as r:
while chunk := r.read(1 << 16):
tmp.write(chunk)
if dst.exists() and digest(dst) != digest(tmp_path):
raise ValueError(f"already exists with different content: {dst}")
tmp_path.rename(dst)
except:
tmp_path.unlink(missing_ok=True)
raise
def main():
if len(sys.argv) != 2 or not re.fullmatch(r"[0-9]+", sys.argv[1]):
print(f"Usage: {sys.argv[0]} <pr-number>", file=sys.stderr)
sys.exit(1)
pr_number = sys.argv[1]
samples_dir = Path(os.environ.get("SAMPLES", "fate-suite"))
pr = fetch_json(f"{FORGEJO_API}/{pr_number}")
assets = {a["name"]: a["browser_download_url"] for a in pr.get("assets", [])}
paths = parse_fate_samples(pr.get("body", ""))
if not paths:
sys.exit(0)
new_samples = False
for path in paths:
try:
validate_path(path)
except ValueError as e:
print(f"fate-samples: {e}", file=sys.stderr)
sys.exit(1)
name = PurePosixPath(path).name
url = assets.get(name)
if url is None:
print(f"fate-samples: no attachment named {name!r}", file=sys.stderr)
sys.exit(1)
try:
validate_url(url)
except ValueError as e:
print(f"fate-samples: {e}", file=sys.stderr)
sys.exit(1)
dst = samples_dir / path
is_new = not dst.exists()
try:
download(url, dst)
except ValueError as e:
print(f"fate-samples: {e}", file=sys.stderr)
sys.exit(1)
if is_new:
new_samples = True
print(f"Injected: {path}")
output_file = os.environ.get("FORGEJO_OUTPUT")
if output_file:
with open(output_file, "a") as f:
print(f"new_samples={'true' if new_samples else 'false'}", file=f)
if __name__ == "__main__":
main()
+7 -45
View File
@@ -1,7 +1,6 @@
module.exports = async ({github, context}) => {
const title = (context.payload.pull_request?.title || context.payload.issue?.title || '').toLowerCase();
const labels = [];
const issueNumber = context.payload.pull_request?.number || context.payload.issue?.number;
const kwmap = {
'avcodec': 'avcodec',
@@ -11,55 +10,18 @@ module.exports = async ({github, context}) => {
'avutil': 'avutil',
'swresample': 'swresample',
'swscale': 'swscale',
'fftools': 'CLI',
'vulkan': 'vulkan'
'fftools': 'CLI'
};
async function isOrgMember(username) {
try {
const response = await github.rest.orgs.checkMembershipForUser({
org: context.repo.owner,
username: username
});
return response.status === 204;
} catch (error) {
return false;
}
}
if (context.payload.action === 'closed' ||
(context.payload.action !== 'opened' && (
context.payload.action === 'assigned' ||
context.payload.action === 'label_updated' ||
context.payload.action === 'labeled' ||
context.payload.comment) &&
await isOrgMember(context.payload.sender.login))
) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
// this should say 'new', but forgejo deviates from GitHub API here and expects the ID
name: '41'
});
console.log('Removed "new" label');
} catch (error) {
if (error.status !== 404 && error.status !== 410) {
console.log('Could not remove "new" label');
}
}
} else if (context.payload.action === 'opened') {
if (context.payload.action === 'opened') {
labels.push('new');
console.log('Detected label: new');
}
if ((context.payload.action === 'opened' || context.payload.action === 'edited') && context.eventName !== 'issue_comment') {
for (const [kw, label] of Object.entries(kwmap)) {
if (title.includes(kw)) {
labels.push(label);
console.log('Detected label: ' + label);
}
for (const [kw, label] of Object.entries(kwmap)) {
if (title.includes(kw)) {
labels.push(label);
console.log('Detected label: ' + label);
}
}
@@ -67,7 +29,7 @@ module.exports = async ({github, context}) => {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
issue_number: context.payload.pull_request?.number || context.payload.issue?.number,
labels: labels,
});
}
+8 -12
View File
@@ -1,35 +1,31 @@
avcodec:
- changed-files:
- any-glob-to-any-file: 'libavcodec/**'
- any-glob-to-any-file: libavcodec/**
avdevice:
- changed-files:
- any-glob-to-any-file: 'libavdevice/**'
- any-glob-to-any-file: libavdevice/**
avfilter:
- changed-files:
- any-glob-to-any-file: 'libavfilter/**'
- any-glob-to-any-file: libavfilter/**
avformat:
- changed-files:
- any-glob-to-any-file: 'libavformat/**'
- any-glob-to-any-file: libavformat/**
avutil:
- changed-files:
- any-glob-to-any-file: 'libavutil/**'
- any-glob-to-any-file: libavutil/**
swresample:
- changed-files:
- any-glob-to-any-file: 'libswresample/**'
- any-glob-to-any-file: libswresample/**
swscale:
- changed-files:
- any-glob-to-any-file: 'libswscale/**'
- any-glob-to-any-file: libswscale/**
CLI:
- changed-files:
- any-glob-to-any-file: 'fftools/**'
vulkan:
- changed-files:
- any-glob-to-any-file: '**/*vulkan*'
- any-glob-to-any-file: fftools/**
+1 -24
View File
@@ -1,14 +1,5 @@
exclude: ^tests/ref/
# This repository keeps its pre-commit config in this nondefault path.
# Install hooks from here with:
# pre-commit install -c .forgejo/pre-commit/config.yaml
# The command above installs both the pre-commit and commit-msg hooks because
# default_install_hook_types includes them below.
default_install_hook_types:
- pre-commit
- commit-msg
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
@@ -27,20 +18,6 @@ repos:
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: trailing-whitespace
- repo: local
hooks:
- id: check-commit-message
name: validate commit message format
language: script
entry: ./tools/check_commit_msg.sh
stages: [commit-msg]
always_run: true
- id: arm-asm-indent
name: fix arm/aarch64 assembly indentation
files: ^.*/(arm|aarch64)/.*\.S$
language: script
entry: ./tools/check_arm_indent.sh --apply
pass_filenames: false
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
@@ -48,4 +25,4 @@ repos:
args:
- --ignore-words=.forgejo/pre-commit/ignored-words.txt
- --ignore-multiline-regex=codespell:off.*?(codespell:on|\Z)
exclude: ^tools/(patcheck|clean-diff)|tests/checkasm/ext/.*$
exclude: ^tools/(patcheck|clean-diff)$
-1
View File
@@ -69,7 +69,6 @@ pEvents
PixelX
Psot
quater
re-use
readd
recuse
redY
+5 -12
View File
@@ -1,30 +1,23 @@
name: Autolabel
on:
pull_request_target:
types: [opened, edited, synchronize, closed, assigned, labeled, unlabeled]
types: [opened, edited, synchronize]
issues:
types: [opened, edited, closed, assigned, labeled, unlabeled]
issue_comment:
types: [created]
types: [opened, edited]
jobs:
pr_labeler:
name: Labeler
runs-on: utilities
if: ${{ github.event.sender.login != 'ffmpeg-devel' }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Label by file-changes
uses: actions/labeler@v6
uses: https://github.com/actions/labeler@v5
if: ${{ forge.event_name == 'pull_request_target' }}
with:
configuration-path: .forgejo/labeler/labeler.yml
repo-token: ${{ secrets.AUTOLABELER_TOKEN }}
sync-labels: true
- name: Label by title-match
uses: actions/github-script@v8
uses: https://github.com/actions/github-script@v7
with:
script: |
const script = require('.forgejo/labeler/labeler.js')
+2 -10
View File
@@ -1,23 +1,15 @@
name: Lint
on:
push:
branches:
- master
pull_request:
concurrency:
cancel-in-progress: ${{ forge.event_name == 'pull_request' }}
jobs:
lint:
name: Pre-Commit
runs-on: utilities
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Rebase onto target branch
uses: ./.forgejo/actions/rebase-pr
uses: actions/checkout@v4
- name: Install pre-commit CI
id: install
run: |
@@ -26,7 +18,7 @@ jobs:
~/pre-commit/bin/pip install pre-commit
echo "envhash=$({ python3 --version && cat .forgejo/pre-commit/config.yaml; } | sha256sum | cut -d' ' -f1)" >> $FORGEJO_OUTPUT
- name: Cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ steps.install.outputs.envhash }}
+13 -99
View File
@@ -1,49 +1,26 @@
name: Test
on:
push:
branches:
- master
pull_request:
concurrency:
cancel-in-progress: ${{ forge.event_name == 'pull_request' }}
jobs:
run_fate:
name: Fate (${{ matrix.runner }}, ${{ matrix.shared }}, ${{ matrix.bits }} bit)
strategy:
fail-fast: false
matrix:
runner: [linux-aarch64]
shared: ['static']
bits: ['64']
include:
- runner: linux-amd64
shared: 'static'
bits: '32'
- runner: linux-amd64
shared: 'shared'
bits: '64'
runner: [linux-amd64,linux-aarch64]
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Rebase onto target branch
uses: ./.forgejo/actions/rebase-pr
uses: actions/checkout@v4
- name: Configure
run: |
./configure --enable-gpl --enable-nonfree --enable-memory-poisoning --assert-level=2 \
$([ "${{ matrix.bits }}" != "32" ] || echo --arch=x86_32 --extra-cflags=-m32 --extra-cxxflags=-m32 --extra-ldflags=-m32) \
$([ "${{ matrix.shared }}" != "shared" ] || echo --enable-shared --disable-static) \
|| CFGRES=$?
cat ffbuild/config.log
exit ${CFGRES:-0}
run: ./configure --enable-gpl --enable-nonfree --enable-memory-poisoning --assert-level=2
- name: Build
run: make -j$(nproc)
- name: Restore Cached Fate-Suite
id: cache
uses: actions/cache/restore@v5
uses: actions/cache/restore@v4
with:
path: fate-suite
key: fate-suite
@@ -53,93 +30,30 @@ jobs:
id: fate
run: |
make fate-rsync SAMPLES=$PWD/fate-suite
echo "hash=$(find fate-suite -type f -printf "%P %s %T@\n" | sort | sha256sum | cut -d' ' -f1)" >> $FORGEJO_OUTPUT
echo "hash=$(find fate-suite -type f | sort | sha256sum | cut -d' ' -f1)" >> $FORGEJO_OUTPUT
- name: Cache Fate-Suite
uses: actions/cache/save@v5
uses: actions/cache/save@v4
if: ${{ format('fate-suite-{0}', steps.fate.outputs.hash) != steps.cache.outputs.cache-matched-key }}
with:
path: fate-suite
key: fate-suite-${{ steps.fate.outputs.hash }}
- name: Inject PR Samples
id: inject
if: ${{ forge.event_name == 'pull_request' }}
run: SAMPLES=$PWD/fate-suite .forgejo/inject-pr-samples.py ${{ forge.event.pull_request.number }}
- name: Run Fate
run: |
LD_LIBRARY_PATH="$(printf "%s:" "$PWD"/lib*)$PWD" make fate fate-build SAMPLES="$PWD/fate-suite" -j$(nproc) || FATERES=$?
find . -name "*.err" -exec printf '::group::%s\n' {} \; -exec cat {} \; -exec printf '::endgroup::\n' \;
exit ${FATERES:-0}
- name: Fail if new samples were injected
if: ${{ steps.inject.outputs.new_samples == 'true' }}
run: |
echo "New FATE samples were injected from PR attachments. Please add them to the official fate-suite before merging."
exit 1
run_fate_full:
name: Fate (Full, ${{ matrix.target_exec }})
run: make fate SAMPLES=$PWD/fate-suite -j$(nproc)
compile_only:
strategy:
fail-fast: false
matrix:
image: ['ghcr.io/btbn/ffmpeg-builds/win64-gpl:latest']
target_exec: ['wine']
image: ["ghcr.io/btbn/ffmpeg-builds/win64-gpl:latest"]
runs-on: linux-amd64
container: ${{ matrix.image }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
path: ffmpeg
- name: Rebase onto target branch
uses: ./ffmpeg/.forgejo/actions/rebase-pr
with:
path: ffmpeg
uses: actions/checkout@v4
- name: Configure
run: |
mkdir build && cd build
../ffmpeg/configure --pkg-config-flags="--static" $FFBUILD_TARGET_FLAGS $FF_CONFIGURE \
./configure --pkg-config-flags="--static" $FFBUILD_TARGET_FLAGS $FF_CONFIGURE \
--cc="$CC" --cxx="$CXX" --ar="$AR" --ranlib="$RANLIB" --nm="$NM" \
--extra-cflags="$FF_CFLAGS" --extra-cxxflags="$FF_CXXFLAGS" \
--extra-libs="$FF_LIBS" --extra-ldflags="$FF_LDFLAGS" --extra-ldexeflags="$FF_LDEXEFLAGS" \
--enable-memory-poisoning --assert-level=2 --target-exec="${{ matrix.target_exec }}" \
--enable-hardcoded-tables \
|| CFGRES=$?
cat ffbuild/config.log
exit ${CFGRES:-0}
--extra-libs="$FF_LIBS" --extra-ldflags="$FF_LDFLAGS" --extra-ldexeflags="$FF_LDEXEFLAGS"
- name: Build
run: make -C build -j$(nproc)
- name: Restore Cached Fate-Suite
id: cache
uses: actions/cache/restore@v5
with:
path: fate-suite
key: fate-suite
restore-keys: |
fate-suite-
- name: Sync Fate-Suite
id: fate
run: |
make -C build fate-rsync SAMPLES=$PWD/fate-suite
echo "hash=$(find fate-suite -type f -printf "%P %s %T@\n" | sort | sha256sum | cut -d' ' -f1)" >> $FORGEJO_OUTPUT
- name: Cache Fate-Suite
uses: actions/cache/save@v5
if: ${{ format('fate-suite-{0}', steps.fate.outputs.hash) != steps.cache.outputs.cache-matched-key }}
with:
path: fate-suite
key: fate-suite-${{ steps.fate.outputs.hash }}
- name: Inject PR Samples
id: inject
if: ${{ forge.event_name == 'pull_request' }}
run: SAMPLES=$PWD/fate-suite ffmpeg/.forgejo/inject-pr-samples.py ${{ forge.event.pull_request.number }}
- name: Run Fate
run: |
if [[ "${{ matrix.target_exec }}" == "wine" ]]; then
export WINEDEBUG=-all
export FREI0R_PATH="$(winepath -w "$FREI0R_PATH")"
fi
LD_LIBRARY_PATH="$(printf "%s:" "$PWD"/lib*)$PWD" make -C build fate fate-build SAMPLES="$PWD/fate-suite" -j$(nproc) || FATERES=$?
find . -name "*.err" -exec printf '::group::%s\n' {} \; -exec cat {} \; -exec printf '::endgroup::\n' \;
exit ${FATERES:-0}
- name: Fail if new samples were injected
if: ${{ steps.inject.outputs.new_samples == 'true' }}
run: |
echo "New FATE samples were injected from PR attachments. Please add them to the official fate-suite before merging."
exit 1
run: make -j$(nproc)
-10
View File
@@ -23,12 +23,6 @@
*.metal.air
*.metallib
*.metallib.c
*.spv
*.spv.c
*.spv.gz
*.gen.asm
*.gen.c
*.gen.S
*.ptx
*.ptx.c
*.ptx.gz
@@ -40,12 +34,8 @@
/ffmpeg
/ffplay
/ffprobe
/checkasm_config_generated.asm
/checkasm_config_generated.h
/checkasm_header_config_generated.h
/config.asm
/config.h
/config_components.asm
/config_components.h
/coverage.info
/lcov/
+1 -2
View File
@@ -1,5 +1,4 @@
# Note to Github users
Patches should be submitted to [Forgejo](https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls) or the [ffmpeg-devel mailing list](https://ffmpeg.org/mailman/listinfo/ffmpeg-devel) using `git format-patch` or `git send-email`. Github pull requests should be avoided because they are not part of our review process and **will be ignored**.
Patches should be submitted to the [ffmpeg-devel mailing list](https://ffmpeg.org/mailman/listinfo/ffmpeg-devel) using `git format-patch` or `git send-email`. Github pull requests should be avoided because they are not part of our review process and **will be ignored**.
See [https://ffmpeg.org/developer.html#Contributing](https://ffmpeg.org/developer.html#Contributing) for more information.
+77 -59
View File
@@ -1,69 +1,89 @@
Entries are sorted chronologically from oldest to youngest within each release,
releases are sorted from youngest to oldest.
version <next>:
- extensively improved AAC encoder
- APV Vulkan encoder
version 9.0:
- Extend AMF Color Converter (vf_vpp_amf) HDR capabilities
- LCEVC track muxing support in MP4 muxer
- Playdate video encoder and muxer
- Add v360_vulkan filter
- HE-AAC 960 decoding (DAB+)
- transpose_cuda filter
- Add AMF Frame Rate Converter (vf_frc_amf) filter
- SMPTE 2094-50 metadata support and passthrough
- ProRes RAW VideoToolbox hwaccel
- APV Vulkan hwaccel
- Animated WebP decoder
- Animated WebP demuxer
- Remove CELT decoding support (doesn't affect Opus CELT)
- Remove ogg/celt parsing
- Bitstream filter to split Dolby Vision multi-layer HEVC
- Add AMF hardware memory mapping support.
- ONNX Runtime DNN backend with GPU execution provider support
- Remove deprecated NVENC options and support for pre-11.1 SDK versions
- iTerm2 inline image protocol muxer
version 8.1:
- ffprobe -codec option
- EXIF Metadata Parsing
- gfxcapture: Windows.Graphics.Capture based window/monitor capture
- hxvs demuxer for HXVS/HXVT IP camera format
- MPEG-H 3D Audio decoding via mpeghdec
- D3D12 H.264 encoder
- drawvg filter via libcairo
- ffmpeg CLI tiled HEIF support
- D3D12 AV1 encoder
- ProRes Vulkan hwaccel
- DPX Vulkan hwaccel
- Rockchip H.264/HEVC hardware encoder
- Add vf_scale_d3d12 filter
- JPEG-XS parser
- JPEG-XS decoder and encoder through libsvtjpegxs
- JPEG-XS raw bitstream muxer and demuxer
- IAMF Projection mode Ambisonic Audio Elements muxing and demuxing
- Add vf_mestimate_d3d12 filter
- xHE-AAC Mps212 decoding support (experimental)
- Remove the old HLS protocol handler
- Vulkan compute codec optimizations
- swscale Vulkan support
- LCEVC metadata bitstream filter
- Add vf_deinterlace_d3d12 filter
- ffprobe: only show refs field in stream section when reading frames
- ProRes Vulkan encoder
- LCEVC parser
- LCEVC enhancement layer exporting in MPEG-TS
version 8.0.1:
avutil/common: cast GET_BYTE/GET_16BIT returned value
avfilter/vf_drawtext: fix call GET_UTF8 with invalid argument
avfilter/vf_drawtext: fix incorrect text length
Update for 8.0.1
avfilter/vf_drawtext: Account for bbox text seperator
avcodec/mediacodecdec_common: Check that the input to mediacodec_wrap_sw_audio_buffer() contains channel * sample_size
avcodec/rv60dec: Clear blk_info
avformat/whip: Fix rtp_ctx->streams access
avcodec/utvideodec: Set B for the width= 1 case in restore_median_planar_il()
avcodec/osq: Fix 32bit sample overflow
avformat/rtpdec_rfc4175: Only change PayloadContext on success
avformat/rtpdec_rfc4175: Check dimensions
avformat/rtpdec_rfc4175: Fix memleak of sampling
avformat/http: Fix off by 1 error
avcodec/exr: spelling
avcodec/rv60dec: add upper bound check for qp
avcodec/exr: use tile dimensions in pxr24 UINT case
avcodec/exr: Simple check for available channels
avformat/sctp: Check size in sctp_write()
avformat/rtmpproto: consider command line argument lengths
avformat/rtmpproto_ Check tcurl and flashver length
avcodec/g723_1enc: Make min_err 64bit
avcodec/vlc: Clear val8/16 in vlc_multi_gen() by av_mallocz()
avformat/rtpenc_h264_hevc: Check space for nal_length_size in ff_rtp_send_h264_hevc()
avcodec/ffv1enc: Consider variation in slice sizes
libavcodec/cbs_apv_syntax_template: limit tile to 2gb
swscale/output: Fix unsigned cast position in yuv2*
swscale/output: Fix integer overflow in yuv2ya16_X_c_template()
avcodec/exr: Check that DWA has 3 channels
avcodec/exr: check ac_size
avcodec/exr: Round dc_w/h up
avcodec/mjpegdec: Explain buf_size/width/height check
configure: strip non numeric trailer from gcc version
avformat/dhav: Fix off by length of read element error
avformat/aviobuf: Keep checksum_ptr consistent in avio_seek()
doc/examples/vaapi_encode: fix invalid check on fwrite
avcodec/librsvgdec: fix compilation with librsvg 2.50.3
avcodec/mfenc: fix memory leak with D3D11 input surfaces
swscale/graph: fix double-free when legacy pass fails initializing
libavformat/udp: Fix call to recvfrom(2)
avfilter/f_ebur128: Fix incorrect ebur128 peak calculation.
avformat/udp: fix warning about unused varible
avdevice/lavfi: stop setting deprecated buffersink options
configure: unbreak glslang build
swscale/range_convert: fix truncation bias in range conversion
lavc/aarch64: Fix addp overflow in ff_pred16x16_plane_neon_10
avcodec/mlpdec: don't depend on context channel layout when setting substream masks
avformat/demux: pass new extradata to the parser
avfilter/af_whisper: fix srt index
avfilter/af_whisper: fix int64 printf format
avfilter/af_whisper: fix srt file format
avfilter/whisper: correct option formatting
avfilter/af_whisper: fix broken output for multibyte character
avformat/rtsp: fix leading space in RTSP reason
avformat/rtsp: do not log invalid values
avformat/http: Handle IPv6 Zone ID in hostname
avformat/dump: fix log level passed to av_log when printing stream group side data
avcodec/hevc/sei: don't attempt to use stale values in HEVCSEITDRDI
avcodec/hevc/sei: prevent storing a potentially bogus num_ref_displays value in HEVCSEITDRDI
avcodec/hevc/refs: don't unconditionally discard non-IRAP frames if no IRAP frame was seen before
libavutil/arm: Rename the HWCAP defines
libavutil/arm: Make use of elf_aux_info() on FreeBSD/OpenBSD
fftools/ffmpeg: fix gracefully shutdown
avcodec/decode: sync initial_pict_type and intra_only_flag with thread worker's avctx
avcodec/x86/pngdsp: add missing emms at the end of add_png_paeth_prediction
avcodec/videotoolboxenc: ensure bitrate is set in low_delay mode
avcodec/videotoolboxenc: allow low latency RC with HEVC
avcodec/videotoolboxenc: support global_quality without qscale
avcodec/videotoolboxenc: fix the loss of precision when calculating quality
fftools/ffmpeg_demux: ensure the display_rotation option is honored
avcodec/mjpegdec: use ff_frame_new_side_data() to export display matrix
avutil/tests/aes_ctr: extend the test to cover payloads smaller than a block
avutil/aes_ctr: reintroduce the block offset state
avfilter/vf_lcevc: support LCEVCdec version 4
avcodec/lcevcdec: support LCEVCdec version 4
movenc: ensure chapters track extradata is not null and populated
version 8.0:
- Whisper filter
- Drop support for OpenSSL < 1.1.0
- Enable TLS peer certificate verification by default (on next major version bump)
- Drop support for OpenSSL < 1.1.1
- yasm support dropped, users need to use nasm
- VVC VAAPI decoder
- RealVideo 6.0 decoder
@@ -92,8 +112,6 @@ version 8.0:
- AV1 Vulkan encoder
- ProRes RAW decoder
- ProRes RAW Vulkan hwaccel
- ffprobe -codec option
- HDR10+ metadata passthrough when decoding/encoding with libaom-av1
version 7.1:
+10 -6
View File
@@ -1,4 +1,4 @@
# Installing FFmpeg
## Installing FFmpeg
0. If you like to include source plugins, merge them before configure
for example run tools/merge-all-source-plugins
@@ -14,11 +14,15 @@ path when launching `configure`, e.g. `/ffmpegdir/ffmpeg/configure`.
3. Type `make install` to install all binaries and libraries you built.
## NOTICE
NOTICE
------
- Non system dependencies (e.g. libx264, libvpx) are disabled by default.
- Non system dependencies (e.g. libx264, libvpx) are disabled by default.
## NOTICE for Package Maintainers
NOTICE for Package Maintainers
------------------------------
- It is recommended to build FFmpeg twice, first with minimal external dependencies so that 3rd party packages, which depend on FFmpegs libavutil/libavfilter/libavcodec/libavformat
can then be built. And last build FFmpeg with full dependencies (which may in turn depend on some of these 3rd party packages). This avoids circular dependencies during build.
- It is recommended to build FFmpeg twice, first with minimal external dependencies so
that 3rd party packages, which depend on FFmpegs libavutil/libavfilter/libavcodec/libavformat
can then be built. And last build FFmpeg with full dependencies (which may in turn depend on
some of these 3rd party packages). This avoids circular dependencies during build.
+11 -23
View File
@@ -65,14 +65,14 @@ Communication
=============
website (T: https://git.ffmpeg.org/ffmpeg-web) Deby Barbara Lepage
fate.ffmpeg.org (L: fate-admin@ffmpeg.org) (W: https://fate.ffmpeg.org) (P: https://ffmpeg.org/fate.html) (S: https://git.ffmpeg.org/fateserver) Timo Rothenpieler
Trac bug tracker [X] (W: https://trac.ffmpeg.org) Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos
Forgejo issue tracker (W: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues)
Trac bug tracker (W: https://trac.ffmpeg.org) Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos
Patchwork [2] (W: https://patchwork.ffmpeg.org) Andriy Gelman
mailing lists (W: https://ffmpeg.org/contact.html#MailingLists) Baptiste Coudurier
Twitter Reynaldo H. Verdejo Pinochet
Launchpad Timothy Gu
ffmpeg-security [2] (L: ffmpeg-security@ffmpeg.org) (W: https://ffmpeg.org/security.html) Michael Niedermayer, Reimar Doeffinger
libavutil
=========
@@ -93,7 +93,6 @@ Other:
hash Reimar Doeffinger
hwcontext_cuda* Timo Rothenpieler
hwcontext_d3d12va* Wu Jianhua
hwcontext_oh* Zhao Zhili
hwcontext_vulkan* [2] Lynne
intfloat* Michael Niedermayer
integer.c, integer.h Michael Niedermayer
@@ -153,13 +152,13 @@ Codecs:
adpcm.c Zane van Iperen
alacenc.c Jaikrishnan Menon
alsdec.c Thilo Borgmann, Umair Khan
amfdec*,amfenc* [2] Dmitrii Ovchinnikov, Araz Iusubov
amfenc* Dmitrii Ovchinnikov
aptx.c Aurelien Jacobs
ass* Aurelien Jacobs
asv* Michael Niedermayer
atrac3plus* Maxim Poliakovski
audiotoolbox* rcombs
avs2* Huiwen Ren, Zhao Zhili
avs2* Huiwen Ren
bgmc.c, bgmc.h Thilo Borgmann
binkaudio.c Peter Ross
cavs* Stefan Gehrer
@@ -212,7 +211,7 @@ Codecs:
libkvazaar.c Arttu Ylä-Outinen
libopenh264enc.c Martin Storsjo, Linjie Fu
libopenjpegenc.c Michael Bradshaw
libtheoraenc.c [0]
libtheoraenc.c David Conrad
libvorbis.c David Conrad
libvpx* James Zern
libxavs.c Stefan Gehrer
@@ -233,7 +232,7 @@ Codecs:
msvideo1.c Mike Melanson
nuv.c Reimar Doeffinger
nvdec*, nvenc* Timo Rothenpieler
oh* Zhao Zhili
omx.c Martin Storsjo, Aman Gupta
opus* Rostislav Pehlivanov
pcx.c Ivo van Poorten
pgssubdec.c Reimar Doeffinger
@@ -244,7 +243,6 @@ Codecs:
qtrle.c Mike Melanson
ra144.c, ra144.h, ra288.c, ra288.h Roberto Togni
resample2.c Michael Niedermayer
rkmppenc* Zhao Zhili
rl2.c Sascha Sommer
rpza.c Roberto Togni
rtjpeg.c, rtjpeg.h Reimar Doeffinger
@@ -252,6 +250,7 @@ Codecs:
sanm.c Manuel Lauss
smc.c Mike Melanson
snow* Michael Niedermayer, Loren Merritt
sonic.c Alex Beregszaszi
speedhq.c Steinar H. Gunderson
srt* Aurelien Jacobs
sunrast.c Ivo van Poorten
@@ -279,7 +278,6 @@ Codecs:
xface Stefano Sabatini
Hardware acceleration:
amf* [2] Dmitrii Ovchinnikov, Araz Iusubov
dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme
d3d11va* Steve Lhomme
d3d12va* Wu Jianhua
@@ -318,10 +316,6 @@ libavfilter
===========
Generic parts:
Framework and orphaned filters Nicolas George
(except hardware acceleration)
graphdump.c Nicolas George
motion_estimation.c Davinder Singh
@@ -353,9 +347,7 @@ Filters:
vf_minterpolate.c Davinder Singh
vf_readvitc.c Tobias Rapp (CC t.rapp at noa-archive dot com)
vf_scale.c [2] Michael Niedermayer
vf_scale_vt.c Zhao Zhili
vf_tonemap_opencl.c Ruiling Song
vf_transpose_vt.c Zhao Zhili
vf_yadif.c [2] Michael Niedermayer
vf_xfade_vulkan.c [2] Marvin Scholz (CC <epirat07@gmail.com>)
@@ -413,9 +405,7 @@ Muxers/Demuxers:
flvenc.c Michael Niedermayer, Steven Liu
gxf.c Reimar Doeffinger
gxfenc.c Baptiste Coudurier
hls.c Kacper Michajłow
hlsenc.c Christian Suloway, Steven Liu
hxvs.c Zhao Zhili
iamf* [2] James Almer
idcin.c Mike Melanson
idroqdec.c Mike Melanson
@@ -451,9 +441,9 @@ Muxers/Demuxers:
nsvdec.c Francois Revol
nut* Michael Niedermayer
nuv.c Reimar Doeffinger
oggdec.c, oggdec.h David Conrad, Romain Beauxis
oggenc.c Baptiste Coudurier, Romain Beauxis
oggparse*.c David Conrad, Romain Beauxis
oggdec.c, oggdec.h David Conrad
oggenc.c Baptiste Coudurier
oggparse*.c David Conrad
oma.c Maxim Poliakovski
pp_bnk.c Zane van Iperen
psxstr.c Mike Melanson
@@ -492,7 +482,6 @@ Muxers/Demuxers:
webm dash (matroskaenc.c) Vignesh Venkatasubramanian
webvtt* Matthew J Heaney
westwood.c Mike Melanson
whip.c [2] Jack Lau
wtv.c Peter Ross
Protocols:
@@ -532,7 +521,7 @@ LoongArch [2] Shiyou Yin
Darwin (macOS, iOS) [2] Marvin Scholz
Mac OS X / PowerPC [0]
Amiga / PowerPC Colin Ward
Linux / PowerPC [2] Sean McGovern (CC <gseanmcg@gmail.com>), Lauri Kasanen
Linux / PowerPC [1] Lauri Kasanen
RISC-V [2] Rémi Denis-Courmont
Windows MinGW Alex Beregszaszi, Ramiro Polla
Windows Cygwin Victor Paesa
@@ -628,7 +617,6 @@ Reinhard Tartler 9300 5DC2 7E87 6C37 ED7B CA9A 9808 3544 9453 48A4
Reynaldo H. Verdejo Pinochet 6E27 CD34 170C C78E 4D4F 5F40 C18E 077F 3114 452A
Robert Swain EE7A 56EA 4A81 A7B5 2001 A521 67FA 362D A2FC 3E71
Sascha Sommer 38A0 F88B 868E 9D3A 97D4 D6A0 E823 706F 1E07 0D3C
Sean McGovern (Sean_McG) 6D03 BC60 3A33 E615 6E2E 06AD 8C06 8175 6F59 8684
Stefano Sabatini 0D0B AD6B 5330 BBAD D3D6 6A0C 719C 2839 FC43 2D5F
Steinar H. Gunderson C2E9 004F F028 C18E 4EAD DB83 7F61 7561 7797 8F76
Stephan Hilb 4F38 0B3A 5F39 B99B F505 E562 8D5C 5554 4E17 8863
+16 -22
View File
@@ -11,8 +11,6 @@ vpath %.asm $(SRC_PATH)
vpath %.rc $(SRC_PATH)
vpath %.v $(SRC_PATH)
vpath %.texi $(SRC_PATH)
vpath %.glsl $(SRC_PATH)
vpath %.spv $(SRC_PATH)
vpath %.cu $(SRC_PATH)
vpath %.ptx $(SRC_PATH)
vpath %.metal $(SRC_PATH)
@@ -55,31 +53,31 @@ FF_DEP_LIBS := $(DEP_LIBS)
FF_STATIC_DEP_LIBS := $(STATIC_DEP_LIBS)
$(TOOLS): %$(EXESUF): %.o
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter-out $(FF_DEP_LIBS), $^) $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter-out $(FF_DEP_LIBS), $^) $(EXTRALIBS-$(*F)) $(EXTRALIBS) $(ELIBS)
target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
target_enc_%_fuzzer$(EXESUF): target_enc_%_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_bsf_%_fuzzer$(EXESUF): tools/target_bsf_%_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
target_dem_%_fuzzer$(EXESUF): target_dem_%_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_dem_fuzzer$(EXESUF): tools/target_dem_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_sws_fuzzer$(EXESUF): tools/target_sws_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/target_swr_fuzzer$(EXESUF): tools/target_swr_fuzzer.o $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH)
tools/enum_options$(EXESUF): ELIBS = $(FF_EXTRALIBS)
tools/enum_options$(EXESUF): $(FF_DEP_LIBS)
@@ -106,14 +104,13 @@ ffbuild/.config: $(CONFIGURABLE_COMPONENTS)
@-printf '\nWARNING: $(?) newer than config_components.h, rerun configure\n\n'
@-tput sgr0 2>/dev/null
SUBDIR_VARS := CLEANFILES FFLIBS DEVPROGS HOSTPROGS TESTPROGS TOOLS \
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 X86ASM-OBJS \
ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \
MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \
MMI-OBJS LSX-OBJS LASX-OBJS RV-OBJS RVV-OBJS RVVB-OBJS \
OBJS SHLIBOBJS STLIBOBJS HOSTOBJS TESTOBJS SIMD128-OBJS \
SVE-OBJS SVE2-OBJS SME-OBJS SME2-OBJS
OBJS SHLIBOBJS STLIBOBJS HOSTOBJS TESTOBJS SIMD128-OBJS
define RESET
$(1) :=
@@ -143,13 +140,11 @@ ifeq ($(STRIPTYPE),direct)
else
$(RM) $@
$(CP) $< $@
ifneq ($(STRIPTYPE),nostrip)
$(STRIP) $@
endif
endif
%$(PROGSSUF)_g$(EXESUF): $(FF_DEP_LIBS)
$(call LINK,$(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS))
$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS)
VERSION_SH = $(SRC_PATH)/ffbuild/version.sh
ifeq ($(VERSION_TRACKING),yes)
@@ -189,8 +184,7 @@ clean::
$(RM) -rf coverage.info coverage.info.in lcov
distclean:: clean
$(RM) .version config.asm config.h config_components.* mapfile \
checkasm_config_generated.* checkasm_header_config_generated.h \
$(RM) .version config.asm config.h config_components.h mapfile \
ffbuild/.config ffbuild/config.* libavutil/avconfig.h \
version.h libavutil/ffversion.h libavcodec/codec_names.h \
libavcodec/bsf_list.c libavformat/protocol_list.c \
@@ -205,8 +199,8 @@ endif
config:
$(SRC_PATH)/configure $(value FFMPEG_CONFIGURATION)
build: all alltools devprogs examples testprogs
check: all alltools devprogs examples testprogs fate
build: all alltools examples testprogs
check: all alltools examples testprogs fate
include $(SRC_PATH)/tests/Makefile
+2 -1
View File
@@ -1,4 +1,5 @@
# FFmpeg README
FFmpeg README
=============
FFmpeg is a collection of libraries and tools to process multimedia content
such as audio, video, subtitles and related metadata.
+1 -1
View File
@@ -1 +1 @@
8.0.git
8.0.1
+15
View File
@@ -0,0 +1,15 @@
┌────────────────────────────────────────┐
│ RELEASE NOTES for FFmpeg 8.0 "Huffman" │
└────────────────────────────────────────┘
The FFmpeg Project proudly presents FFmpeg 8.0 "Huffman", about 11
months after the release of FFmpeg 7.1.
A complete Changelog is available at the root of the project, and the
complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git
We hope you will like this release as much as we enjoyed working on it, and
as usual, if you have any questions about it, or any FFmpeg related topic,
feel free to join us on the #ffmpeg IRC channel (on irc.libera.chat) or ask
on the mailing-lists.
-114
View File
@@ -1,114 +0,0 @@
/*
* Android Binder handler
*
* Copyright (c) 2025 Dmitrii Okunev
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(__ANDROID__)
#include <dlfcn.h>
#include <stdint.h>
#include <stdlib.h>
#include "libavutil/log.h"
#include "binder.h"
#define THREAD_POOL_SIZE 1
static void *dlopen_libbinder_ndk(void)
{
/*
* libbinder_ndk.so often does not contain the functions we need, so making
* this dependency optional, thus using dlopen/dlsym instead of linking.
*
* See also: https://source.android.com/docs/core/architecture/aidl/aidl-backends
*/
void *h = dlopen("libbinder_ndk.so", RTLD_NOW | RTLD_LOCAL);
if (h != NULL)
return h;
av_log(NULL, AV_LOG_WARNING,
"android/binder: unable to load libbinder_ndk.so: '%s'; skipping binder threadpool init (MediaCodec likely won't work)\n",
dlerror());
return NULL;
}
static void android_binder_threadpool_init(void)
{
typedef int (*set_thread_pool_max_fn)(uint32_t);
typedef void (*start_thread_pool_fn)(void);
set_thread_pool_max_fn set_thread_pool_max = NULL;
start_thread_pool_fn start_thread_pool = NULL;
void *h = dlopen_libbinder_ndk();
if (h == NULL)
return;
unsigned thead_pool_size = THREAD_POOL_SIZE;
set_thread_pool_max =
(set_thread_pool_max_fn) dlsym(h,
"ABinderProcess_setThreadPoolMaxThreadCount");
start_thread_pool =
(start_thread_pool_fn) dlsym(h, "ABinderProcess_startThreadPool");
if (start_thread_pool == NULL) {
av_log(NULL, AV_LOG_WARNING,
"android/binder: ABinderProcess_startThreadPool not found; skipping threadpool init (MediaCodec likely won't work)\n");
return;
}
if (set_thread_pool_max != NULL) {
int ok = set_thread_pool_max(thead_pool_size);
av_log(NULL, AV_LOG_DEBUG,
"android/binder: ABinderProcess_setThreadPoolMaxThreadCount(%u) => %s\n",
thead_pool_size, ok ? "ok" : "fail");
} else {
av_log(NULL, AV_LOG_DEBUG,
"android/binder: ABinderProcess_setThreadPoolMaxThreadCount is unavailable; using the library default\n");
}
start_thread_pool();
av_log(NULL, AV_LOG_DEBUG,
"android/binder: ABinderProcess_startThreadPool() called\n");
}
void android_binder_threadpool_init_if_required(void)
{
#if __ANDROID_API__ >= 24
if (android_get_device_api_level() < 35) {
// the issue with the thread pool was introduced in Android 15 (API 35)
av_log(NULL, AV_LOG_DEBUG,
"android/binder: API<35, thus no need to initialize a thread pool\n");
return;
}
android_binder_threadpool_init();
#else
// android_get_device_api_level was introduced in API 24, so we cannot use it
// to detect the API level in API<24. For simplicity we just assume
// libbinder_ndk.so on the system running this code would have API level < 35;
av_log(NULL, AV_LOG_DEBUG,
"android/binder: is built with API<24, assuming this is not Android 15+\n");
#endif
}
#endif /* __ANDROID__ */
-1
View File
@@ -182,7 +182,6 @@ static inline __device__ float fabsf(float a) { return __builtin_fabsf(a); }
static inline __device__ float fabs(float a) { return __builtin_fabsf(a); }
static inline __device__ double fabs(double a) { return __builtin_fabs(a); }
static inline __device__ float sqrtf(float a) { return __builtin_sqrtf(a); }
static inline __device__ float rintf(float a) { return __builtin_rintf(a); }
static inline __device__ float __saturatef(float a) { return __nvvm_saturate_f(a); }
static inline __device__ float __sinf(float a) { return __nvvm_sin_approx_f(a); }
+1 -1
View File
@@ -38,7 +38,7 @@ static int optind = 1;
static int optopt;
static char *optarg;
static int getopt(int argc, char *argv[], const char *opts)
static int getopt(int argc, char *argv[], char *opts)
{
static int sp = 1;
int c;
+6 -41
View File
@@ -44,9 +44,8 @@
#include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/time.h"
#include "libavutil/wchar_filename.h"
typedef struct w32pthread_t {
typedef struct pthread_t {
void *handle;
void *(*func)(void* arg);
void *arg;
@@ -72,7 +71,7 @@ typedef CONDITION_VARIABLE pthread_cond_t;
#define THREADFUNC_RETTYPE unsigned
#endif
av_unused static THREADFUNC_RETTYPE
static av_unused THREADFUNC_RETTYPE
__stdcall attribute_align_arg win32thread_worker(void *arg)
{
pthread_t h = (pthread_t)arg;
@@ -80,12 +79,12 @@ __stdcall attribute_align_arg win32thread_worker(void *arg)
return 0;
}
av_unused static int pthread_create(pthread_t *thread, const void *unused_attr,
static av_unused int pthread_create(pthread_t *thread, const void *unused_attr,
void *(*start_routine)(void*), void *arg)
{
pthread_t ret;
ret = (pthread_t)av_mallocz(sizeof(*ret));
ret = av_mallocz(sizeof(*ret));
if (!ret)
return EAGAIN;
@@ -109,7 +108,7 @@ av_unused static int pthread_create(pthread_t *thread, const void *unused_attr,
return 0;
}
av_unused static int pthread_join(pthread_t thread, void **value_ptr)
static av_unused int pthread_join(pthread_t thread, void **value_ptr)
{
DWORD ret = WaitForSingleObject(thread->handle, INFINITE);
if (ret != WAIT_OBJECT_0) {
@@ -149,7 +148,7 @@ static inline int pthread_mutex_unlock(pthread_mutex_t *m)
typedef INIT_ONCE pthread_once_t;
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
av_unused static int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
BOOL pending = FALSE;
InitOnceBeginInitialize(once_control, 0, &pending, NULL);
@@ -210,38 +209,4 @@ static inline int pthread_setcancelstate(int state, int *oldstate)
return 0;
}
static inline int win32_thread_setname(const char *name)
{
#if !HAVE_UWP
typedef HRESULT (WINAPI *SetThreadDescriptionFn)(HANDLE, PCWSTR);
// Although SetThreadDescription lives in kernel32.dll, on Windows Server 2016,
// Windows 10 LTSB 2016 and Windows 10 version 1607, it was only available in
// kernelbase.dll. So, load it from there for maximum coverage.
HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
if (!kernelbase)
return AVERROR(ENOSYS);
SetThreadDescriptionFn pSetThreadDescription =
(SetThreadDescriptionFn)GetProcAddress(kernelbase, "SetThreadDescription");
if (!pSetThreadDescription)
return AVERROR(ENOSYS);
wchar_t *wname;
if (utf8towchar(name, &wname) < 0)
return AVERROR(ENOMEM);
HRESULT hr = pSetThreadDescription(GetCurrentThread(), wname);
av_free(wname);
return SUCCEEDED(hr) ? 0 : AVERROR(EINVAL);
#else
// UWP is not supported because we cannot use LoadLibrary/GetProcAddress to
// detect the availability of the SetThreadDescription API. There is a small
// gap in Windows builds 1507-1607 where it was not available. UWP allows
// querying the availability of APIs with QueryOptionalDelayLoadedAPI, but it
// requires /DELAYLOAD:kernel32.dll during linking, and we cannot enforce that.
return AVERROR(ENOSYS);
#endif
}
#endif /* COMPAT_W32PTHREADS_H */
+5 -25
View File
@@ -33,11 +33,6 @@ if [ ! -f "$vscript" ]; then
fi
for object in "$@"; do
case "$object" in
@*)
object="${object#@}"
;;
esac
if [ ! -f "$object" ]; then
echo "Object does not exist: ${object}" >&2
exit 1
@@ -53,13 +48,7 @@ trap 'rm -f -- $libname' EXIT
if [ -n "$AR" ]; then
$AR rcs ${libname} $@ >/dev/null
else
machine_flag=""
case "$LDFLAGS" in
*"machine:arm64ec"*)
machine_flag="-machine:arm64ec"
;;
esac
lib.exe ${machine_flag} -out:${libname} $@ >/dev/null
lib.exe -out:${libname} $@ >/dev/null
fi
if [ $? != 0 ]; then
echo "Could not create temporary library." >&2
@@ -117,21 +106,12 @@ if [ -n "$NM" ]; then
grep -v : |
grep -v ^$ |
cut -d' ' -f3 |
sed -e "s/^${prefix}//" -e "s/^#//" |
grep -v '\$entry_thunk' |
grep -v '\$exit_thunk')
sed -e "s/^${prefix}//")
else
member=1
case "$LDFLAGS" in
*"machine:arm64ec"*)
member=32
;;
esac
dump=$(dumpbin.exe -linkermember:${member} ${libname} |
sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e 's/^[[:space:]]*[0-9A-Fa-f]\{1,\}[[:space:]]\{1,\}//' -e "s/^${prefix}//" -e 's/^#//' |
dump=$(dumpbin.exe -linkermember:1 ${libname} |
sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |
tail -n +2 |
grep -v '\$entry_thunk' |
grep -v '\$exit_thunk')
cut -d' ' -f3)
fi
rm ${libname}
Vendored
+314 -795
View File
File diff suppressed because it is too large Load Diff
+1 -207
View File
@@ -1,213 +1,7 @@
The last version increases of all libraries were on 2026-06-23.
The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
2026-06-23 - 61693f6c35f - lavu 60.34.100 - hwcontext_vulkan.h
Switch AVVkFrame.access to VkAccessFlagBits2.
2026-06-23 - 191be14fb6d - lavc 62.37.100 - packet.h
av_packet_pack_dictionary() now accepts const AVDictionary*.
2026-06-10 - 12dc67b6fe0 - lavu 60.33.100 - frame.h
Add AV_FRAME_DATA_RAW_COLOR_PARAMS.
2026-06-03 - 972c0cf91f4 - lsws 9.8.100 - swscale.h
Add enum SwsBackend and SwsContext.backends
2026-06-02 - 9fe5758da5c - lavu 60.32.100 - hwcontext_vulkan.h
Add AVVulkanDeviceContext.queue_flags.
2026-05-31 - 1e3883df9f0 - lavf 62.19.100 - avformat.h
Add AVStreamGroupLayeredVideo
Add AVStreamGroup.params.layered_video
Add AV_STREAM_GROUP_PARAMS_DOLBY_VISION
Deprecate AVStreamGroupLCEVC
Deprecate AVStreamGroup.params.lcevc
2026-05-30 - 5f6dff5e7db - lavc 62.35.100 - packet.h
Add AV_PKT_DATA_HEVC_CONF side data type.
2026-05-14 - xxxxxxxxxxx - lavf 62.18.100 - avformat.h
Add AV_FDEBUG_ID3V2 debug flag, deprecate FF_FDEBUG_TS in favor of
AV_FDEBUG_TS.
2026-05-17 - a5822fca94f - lavf 62.17.100 - avformat.h
Add AV_STREAM_GROUP_PARAMS_TREF.
Add AVStreamGroupTREF.
2026-05-16 - c0bdc3b62a5 - lavf 62.16.100 - avformat.h
Add AVFMT_FIXED_FRAMESIZE.
2026-05-16 - b1120b1ed80 - lavc 62.33.100 - avcodec.h
Add AV_CODEC_FLAG2_FIXED_FRAME_SIZE.
2026-05-12 - 99908c6e05e - lavu 60.31.100 - frame.h
Add IAMF frame side data types to enum AVFrameSideDataType:
- AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM
- AV_FRAME_DATA_IAMF_DEMIXING_INFO_PARAM
- AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM
2026-05-05 - 5c557dd5d55 - lavf 62.15.100 - avformat.h
Add av_program_copy().
2026-05-05 - 7623379a770 - lavf 62.14.100 - avformat.h
Add av_program_add_stream_index2().
2026-04-14 - 7faa6ee2aa - lavc 62.30.100 - packet.h
Add AV_PKT_DATA_DYNAMIC_HDR_SMPTE_2094_APP5 side data type.
2026-04-09 - 6ba6db4f19 - lavu 60.30.100 - hdr_dynamic_metadata.h frame.h
Add AVDynamicHDRSmpte2094App5 struct and functions.
Add AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5 side data type.
2026-03-14 - c102e89448a - lavu 60.29.100 - hwcontext_vulkan.h
Deprecate AVVulkanDeviceContext.lock_queue and
AVVulkanDeviceContext.unlock_queue without replacement.
2026-03-12 - 3503b19711c - lsws 9.7.100 - swscale.h
Add enum SwsScaler, and SwsContext.scaler/scaler_sub.
2026-03-11 - 910000fe59d - lavu 60.28.100 - hwcontext_amf.h
Add av_amf_display_mastering_meta_to_hdrmeta(), av_amf_light_metadata_to_hdrmeta().
Add av_amf_extract_hdr_metadata(), av_amf_attach_hdr_metadata().
Add av_amf_get_color_profile().
2026-03-07 - c23d56b173a - lavc 62.26.100 - codec_desc.h
Add AV_CODEC_PROP_ENHANCEMENT.
2026-03-07 - f37cfb370f8 - lavc 62.25.100 - avcodec.h
Deprecate AVCodecContext.intra_dc_precision.
2026-02-26 - 26d6ac56c10 - lsws 9.4.100 - swscale.h
Add sws_test_hw_format().
2026-02-19 - ca011ee7547 - lavf 62.10.100 - avformat.h
Add demuxer command API consisting of:
- Add avformat_send_command().
- Add avformat_receive_command_reply().
- Add enum AVFormatCommandID.
2026-02-13 - 66766bb1c76 - lavu 60.25.100 - avassert.h
Deprecate av_assert0_fpu() and av_assert2_fpu() without replacement.
2026-02-09 - f2b13f783ac - lavf 62.9.100 - avformat.h
Add AVFormatContext.name.
2026-01-26 - 714152dd9a0 - lavu 60.24.100 - hwcontext_d3d11va.h
Add BindFlags and MiscFlags to AVD3D11VADeviceContext
2026-01-04 - 0645c484537 - lavu 60.23.100 - cpu.h
Add AV_CPU_FLAG_ARM_CRC.
2026-01-04 - e382772e4a1 - lavu 60.22.100 - cpu.h
Add AV_CPU_FLAG_CLMUL.
2025-12-29 - a6e5fa3fbb5 - lavu 60.21.100 - iamf.h
Add nb_demixing_matrix to AVIAMFLayer
2025-12-13 - b8ee68cffe - lavc 62.23.100 - codec_id.h
Add AV_CODEC_ID_JPEGXS.
2025-12-12 - c9b5e145b71 - lavf 62.7.100 - avformat.h
Add av_mime_codec_str
2025-12-08 - 212eb8413a6 - lavu 60.20.100 - hwcontext_vulkan.h
Add av_vk_get_optional_instance_extensions().
Add av_vk_get_optional_device_extensions().
2025-12-07 - 00caeba050d - lavc 62.22.101 - avcodec.h
Add avcodec_receive_frame_flags().
Add AV_CODEC_RECEIVE_FRAME_FLAG_SYNCHRONOUS.
2025-11-26 - 623669a02cd - lavfi 11.10.100 - buffersrc.h
Add av_buffersrc_get_status().
2025-11-18 - 140b4f28c30 - lavu 60.19.100 - hwcontext_amf.h
avutil/hwcontext_amf: add lock and unlock for AVAMFDeviceContext.
2025-11-16 - 643e2e10f98 - lavu 60.18.100 - cpu.h
Deprecate AV_CPU_FLAG_FORCE without replacement.
2025-11-01 - 8a322c956f3 - lavc 62.19.100 - avcodec.h
Schedule AVCodecParser and av_parser_init() to use enum AVCodecID
for codec ids on the next major version bump.
2025-11-01 - e0b0ca81112 - lavc 62.18.100 - avcodec.h
Deprecate AVCodecParser fields priv_data_size, parser_init,
parser_parse, parser_close, and split with no replacement.
2025-10-30 - 6879c8ee5dd - lavc 62.17.100 - packet.h
Add av_packet_side_data_from_frame() and av_packet_side_data_to_frame().
2025-10-28 - 71c7b9156bd - lavu 60.16.100 - pixfmt.h
Add AVCOL_TRC_EXT_BASE, AVCOL_TRC_V_LOG,
AVCOL_PRI_EXT_BASE and AVCOL_PRI_V_GAMUT.
2025-10-24 - 00e43619cd3 - lavu 60.14.100 - csp.h
Add av_csp_approximate_eotf_gamma().
2025-08-xx - xxxxxxxxxx - lavf 62.6.100 - oggparsevorbis.h oggparseopus.h oggparseflac.h
Drop header packets from secondary chained ogg/{flac, opus, vorbis} streams
from demuxer output.
2025-09-08 - 1b97966199f - lavu 60.13.100 - hwcontext_d3d12va.h
Add resource_flags and heap_flags to AVD3D12VADeviceContext
Add heap_flags to AVD3D12VAFramesContext
2025-09-05 - 9458a6f8ec2 - lavf 62.5.100 - avformat.h
Add AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION
2025-09-03 - c2ce3873859 - lavu 60.12.100 - hwcontext_d3d12va.h
Add support for texture array mode AVD3D12VAFrame.subresource_index,
AVD3D12VAFramesContext.texture_array
Add enum AVD3D12VAFrameFlags to define the behaviours of frame allocation.
Renanme AVD3D12VAFramesContext.flags to AVD3D12VAFramesContext.resource_flags.
Add flags to AVD3D12VAFramesContext
Add flags to AVD3D12VAFrame
2025-09-02 - de297ae2fca - lavfi 11.8.100 - buffersrc.h
Add AVBufferSrcParameters.alpha_mode.
2025-09-02 - 0fbd90d78f8 - lavfi 11.7.100 - buffersink.h
Add av_buffersink_get_alpha_mode().
2025-09-02 - ecebf9c6935 - lavc 62.15.100 - avcodec.h codec_par.h
Add AVCodecContext.alpha_mode, AVCodecParameters.alpha_mode, and
AV_CODEC_CONFIG_ALPHA_MODE.
2025-09-02 - eea99a77eda - lavfi 11.6.100 - avfilter.h
Add AVFilterLink.alpha_mode.
2025-09-02 - 22929bd044c - lavu 60.11.100 - frame.h pixfmt.h
Add AVAlphaMode, AVFrame.alpha_mode, av_alpha_mode_name() and
av_alpha_mode_from_name().
2025-09-01 - ce0938da8cd - lsws 9.3.100 - swscale.h
Add SWS_UNSTABLE flag.
2025-09-01 - 4ffd621523e - lavc 62.14.100 - packet.h
Add AV_PKT_DATA_EXIF
2025-08-24 - 368b5e0ffc2 - lavc 62.13.101 - exif.h
Add AV_EXIF_FLAG_RECURSIVE
2025-08-19 - ad77345a5d1..fe496b0308f - lavc 62.13.100 - exif.h
Add:
- enum AVTiffDataType, enum AVExifHeaderMode
- struct AVExifMetadata, struct AVExifEntry
- av_exif_get_tag_name, av_exif_get_tag_id,
av_exif_set_entry, av_exif_get_entry,
av_exif_remove_entry, av_exif_parse_buffer,
av_exif_write, av_exif_free,
av_exif_ifd_to_dict, av_exif_clone_ifd,
av_exif_matrix_to_orientation,
av_exif_orientation_to_matrix,
2025-08-19 - bb90b262d6d - lavu 60.10.100 - frame.h
Add AV_FRAME_DATA_EXIF.
-------- 8< --------- FFmpeg 8.0 was cut here -------- 8< ---------
2025-07-29 - 1c85a3832af - lavc 62.10.100 - smpte_436m.h
Add a new public header smpte_436m.h with API for
manipulating AV_CODEC_ID_SMPTE_436M_ANC data.
-40
View File
@@ -1,40 +0,0 @@
This document is work in progress
*What is CVSS*
The Common Vulnerability Scoring System (CVSS) is an open, industry-standard framework used to measure and communicate the severity of software vulnerabilities, ranging from 0.0 to 10.0.
*Why we need this Document*
It is important that FFmpeg CVEs have consistent and correct CVSS, not only for the obvious reason that one can recognize the severity of an issue at first glance.
But also as these numbers form the basis of rewards paid in bug bounty systems. Inconsistent CVSS could lead to unfair payouts.
*What is this Document*
Prior 2026, FFmpeg had no guideline about CVSS.
This document describes how to select the CVSS for a FFmpeg related CVE. It currently only covers the Base Score.
*What is the CVSS Base Score*
AV Attack Vector (Network, Adjacent, Local, Physical)
AC Attack Complexity (Low, High)
PR Privileges Required (None, Low, High)
UI User Interaction (None, Required)
S Scope (Unchanged, Changed)
C Confidentiality (None, Low, High)
I Integrity (None, Low, High)
A Availability (None, Low, High)
*Things people have set incorrectly*
Below are general guidelines and in specific cases other things may apply.
Attack Vector.
Quote from https://www.first.org/cvss/v3.1/user-guide
"Specifically, analysts should only score for Network or Adjacent when a vulnerability is bound to the network stack.
Vulnerabilities which require user interaction to download or receive malicious content (which could also be delivered locally, e.g., via USB drives) should be scored as Local."
Availability.
FFmpeg Crashes -> AVAILABILITY IMPACT: Low
FFmpeg is frequently used as a short-lived, single-run process instead of a continuously running service that handles ongoing streams of user input. In that usage model, a crash usually causes only limited disruption.
User Interaction
Please consider if an attacker can actually set the parameters required for an attack.
In general arbitrary filter parameters cannot be set by an attacker and require the user/account owner/admin to set them
+2 -2
View File
@@ -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 =
PROJECT_NUMBER = 8.0.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
@@ -295,7 +295,7 @@ MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word
# be prevented in individual cases by by putting a % sign in front of the word
# or globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
+3 -4
View File
@@ -28,7 +28,6 @@ HTMLPAGES = $(AVPROGS-yes:%=doc/%.html) $(AVPROGS-yes:%=doc/%-all.html) $(COMP
doc/mailing-list-faq.html \
doc/nut.html \
doc/platform.html \
doc/drawvg-reference.html \
$(SRC_PATH)/doc/bootstrap.min.css \
$(SRC_PATH)/doc/style.min.css \
$(SRC_PATH)/doc/default.css \
@@ -54,7 +53,7 @@ TEXIDEP = perl $(SRC_PATH)/doc/texidep.pl $(SRC_PATH) $< $@ >$(@:%=%.d)
doc/%.txt: TAG = TXT
doc/%.txt: doc/%.texi
$(Q)$(TEXIDEP)
$(M)$(MAKEINFO) --force --no-headers -o $@ $< 2>/dev/null
$(M)makeinfo --force --no-headers -o $@ $< 2>/dev/null
GENTEXI = format codec
GENTEXI := $(GENTEXI:%=doc/avoptions_%.texi)
@@ -69,11 +68,11 @@ doc/%-all.html: TAG = HTML
ifdef HAVE_MAKEINFO_HTML
doc/%.html: doc/%.texi $(SRC_PATH)/doc/t2h.pm $(GENTEXI)
$(Q)$(TEXIDEP)
$(M)$(MAKEINFO) --html -I doc --no-split -D config-not-all --init-file=$(SRC_PATH)/doc/t2h.pm --output $@ $<
$(M)makeinfo --html -I doc --no-split -D config-not-all --init-file=$(SRC_PATH)/doc/t2h.pm --output $@ $<
doc/%-all.html: doc/%.texi $(SRC_PATH)/doc/t2h.pm $(GENTEXI)
$(Q)$(TEXIDEP)
$(M)$(MAKEINFO) --html -I doc --no-split -D config-all --init-file=$(SRC_PATH)/doc/t2h.pm --output $@ $<
$(M)makeinfo --html -I doc --no-split -D config-all --init-file=$(SRC_PATH)/doc/t2h.pm --output $@ $<
else
doc/%.html: doc/%.texi $(SRC_PATH)/doc/t2h.init $(GENTEXI)
$(Q)$(TEXIDEP)
+1 -30
View File
@@ -124,33 +124,6 @@ that this level currently behaves the same as @samp{limited} in libavcodec.
@end table
@end table
@section dovi_split
Split a Dolby Vision Profile 7 multi-layer HEVC bitstream. Profile 7 carries the
enhancement-layer HEVC bitstream interleaved inside the base-layer access units,
wrapped in user-unspecified NAL units of type 63 (UNSPEC63), and the RPU metadata
as a sibling user-unspecified NAL of type 62 (UNSPEC62).
@table @option
@item mode
Which Dolby Vision components to keep in the output bitstream.
@table @samp
@item bl
Base layer only: drop every UNSPEC63 (EL) and every UNSPEC62 (RPU).
The output is a plain HEVC stream with no Dolby Vision markers. This is the
default.
@item bl_rpu
Base layer with the RPU NAL kept.
@item el
Enhancement layer only: for every UNSPEC63 NAL, strip the two-byte outer NAL
header and emit the inner payload. The result is a standalone HEVC bitstream.
UNSPEC62 (RPU) is dropped.
@item el_rpu
Enhancement layer with the RPU NAL kept verbatim. Same as @samp{el}, but the
UNSPEC62 RPU NALs are also emitted alongside the unwrapped EL NALs.
@end table
@end table
@section dump_extra
Add extradata to the beginning of the filtered packets except when
@@ -940,8 +913,6 @@ Set expressions for PTS, DTS or both.
Set expression for duration.
@item time_base
Set output time base.
@item prescale
Set whether to convert time fields to user-set output time base before evaluation of expressions. Defaults to 0.
@end table
The expressions are evaluated through the eval API and can contain the following
@@ -1002,7 +973,7 @@ The next input PTS.
The next input duration.
@item TB
The timebase in which time fields are denominated. The user-set output timebase if prescale is enabled, else the input timebase.
The timebase of stream packet belongs.
@item TB_OUT
The output timebase.
+5
View File
@@ -7,6 +7,11 @@ V
Disable the default terse mode, the full command issued by make and its
output will be shown on the screen.
DBG
Preprocess x86 external assembler files to a .dbg.asm file in the object
directory, which then gets compiled. Helps in developing those assembler
files.
DESTDIR
Destination directory for the install targets, useful to prepare packages
or install FFmpeg in cross-environments.
-10
View File
@@ -646,8 +646,6 @@ Do not skip samples and export skip information as frame side data.
Do not reset ASS ReadOrder field on flush.
@item icc_profiles
Generate/parse embedded ICC profiles from/to colorimetry tags.
@item fixed_frame_size
Force audio encoders to use a fixed frame size.
@end table
@item export_side_data @var{flags} (@emph{decoding/encoding,audio,video,subtitles})
@@ -915,14 +913,6 @@ Possible values:
@end table
@item alpha_mode @var{integer} (@emph{decoding/encoding,video})
Possible values:
@table @samp
@item premultiplied
@item straight
@end table
@item log_level_offset @var{integer}
Set the log level offset.
+18 -9
View File
@@ -119,6 +119,16 @@ The following options are supported by the libdav1d wrapper.
@table @option
@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.
@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).
@@ -307,6 +317,14 @@ This decoder generates wave patterns according to predefined sequences. Its
use is purely internal and the format of the data it accepts is not publicly
documented.
@section libcelt
libcelt decoder wrapper.
libcelt allows libavcodec to decode the Xiph CELT ultra-low delay audio codec.
Requires the presence of the libcelt headers and library during configuration.
You need to explicitly configure the build with @code{--enable-libcelt}.
@section libgsm
libgsm decoder wrapper.
@@ -338,15 +356,6 @@ value is 0 (disabled).
@end table
@section libmpeghdec
libmpeghdec decoder wrapper.
libmpeghdec allows libmpeghdec to decode the MPEG-H 3D audio codec.
Requires the presence of the libmpeghdec headers and library during
configuration. You need to explicitly configure the build with
@code{--enable-libmpeghdec --enable-nonfree}.
@section libopencore-amrnb
libopencore-amrnb decoder wrapper.
+24 -64
View File
@@ -281,11 +281,7 @@ This demuxer accepts the following option:
@table @option
@item cenc_decryption_key
Default 16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7).
@item cenc_decryption_keys
Dictionary of 16-byte key ID => 16-byte key, both in hex, to decrypt files encrypted using ISO Common Encryption
(CENC/AES-128 CTR; ISO/IEC 23001-7).
16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7).
@end table
@@ -668,9 +664,30 @@ Select a glob wildcard pattern type.
The pattern is interpreted like a @code{glob()} pattern. This is only
selectable if libavformat was compiled with globbing support.
@item glob_sequence @emph{(deprecated, will be removed)}
Select a mixed glob wildcard/sequence pattern.
If your version of libavformat was compiled with globbing support, and
the provided pattern contains at least one glob meta character among
@code{%*?[]@{@}} that is preceded by an unescaped "%", the pattern is
interpreted like a @code{glob()} pattern, otherwise it is interpreted
like a sequence pattern.
All glob special characters @code{%*?[]@{@}} must be prefixed
with "%". To escape a literal "%" you shall use "%%".
For example the pattern @code{foo-%*.jpeg} will match all the
filenames prefixed by "foo-" and terminating with ".jpeg", and
@code{foo-%?%?%?.jpeg} will match all the filenames prefixed with
"foo-", followed by a sequence of three characters, and terminating
with ".jpeg".
This pattern type is deprecated in favor of @var{glob} and
@var{sequence}.
@end table
Default value is @var{sequence}.
Default value is @var{glob_sequence}.
@item pixel_format
Set the pixel format of the images to read. If not specified the pixel
format is guessed from the first image file in the sequence.
@@ -944,11 +961,7 @@ Fixed key used for handling Audible AAX/AAX+ files. It has been pre-set so shoul
specify.
@item decryption_key
Default 16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7).
@item decryption_keys
Dictionary of 16-byte key ID => 16-byte key, both in hex, to decrypt files encrypted using ISO Common Encryption
(CENC/AES-128 CTR; ISO/IEC 23001-7).
16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7).
@item max_stts_delta
Very high sample deltas written in a trak's stts box may occasionally be intended but usually they are written in
@@ -1043,11 +1056,6 @@ Set input video frame rate. Default value is 25.
@item pixel_format
Set the input video pixel format. Default value is @code{yuv420p}.
@item stride
Set frame line size in bytes, only required if there are extra padding.
For multiplane formats, @option{stride} is a list of line size for each
plane.
@item video_size
Set the input video size. This value must be specified explicitly.
@end table
@@ -1060,13 +1068,6 @@ the command:
ffplay -f rawvideo -pixel_format rgb24 -video_size 320x240 -framerate 10 input.raw
@end example
Read a rawvideo with @command{ffplay}, assuming a pixel format of @code{yuv420p},
a video size of @code{1080x1920}, has 8 bytes of padding in each line of Y plane,
and 4 bytes of padding with UV plane,
@example
ffplay -f rawvideo -pixel_format yuv420p -video_size 1080x1920 -stride 1088,544,544 input.raw
@end example
@anchor{rcwtdec}
@section rcwt
@@ -1181,51 +1182,10 @@ RIFF Wave Audio demuxer.
This demuxer accepts the following options:
@table @option
@item ignore_length @var{bool}
Ignore the size of the @code{data} chunk and keep reading until the end of the file if set.
May be useful to read broken or partial files where the header was not properly updated,
but will misinterpret files with non-audio chunks after the @code{data} chunk.
Default is disabled.
@item max_size
Specify the maximum packet size in bytes for the demuxed packets. By default
this is set to 0, which means that a sensible value is chosen based on the
input format.
@end table
@section webp
Animated WebP demuxer.
It accepts the following options:
@table @option
@item -min_delay @var{int}
Set the minimum valid delay between frames in milliseconds.
Range is 0 to 60000. Default value is 10.
@item -max_webp_delay @var{int}
Set the maximum valid delay between frames in milliseconds.
Range is 0 to 16777215. Default value is 16777215 (over four hours),
the maximum value allowed by the specification.
@item -default_delay @var{int}
Set the default delay between frames in milliseconds.
Range is 0 to 60000. Default value is 100.
@item -ignore_loop @var{bool}
WebP files can contain information to loop a certain number of times
(or infinitely). If @option{ignore_loop} is set to true, then the loop
setting from the input will be ignored and looping will not occur.
If set to false, then looping will occur and will cycle the number
of times according to the WebP. Default value is true.
@item usebgcolor @var{bool}
WebP files contain a background color hint in the ANIM chunk, but the
WebP specification says that viewer applications are not required to
use it. If @option{usebgcolor} is set to true, then the background
color hint will be used, otherwise transparent black will be used for
the background. Default value is false.
@end table
@c man end DEMUXERS
+4 -38
View File
@@ -45,7 +45,6 @@ maintained and developed.
@end itemize
All proposed code changes should be submitted for review to
@url{https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls, Forgejo} or
@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}.
@@ -225,25 +224,6 @@ AVStream *stream;
AVStream* stream;
@end example
@item
When sensible, prefer a narrow variable scope, especially in for loops:
@example c, good
// Good
for (unsigned i = 0; i < submix->nb_elements; i++) @{
// Do something...
@}
@end example
@example c, bad
// Bad style
unsigned i;
//...
for (i = 0; i < submix->nb_elements; i++) @{
// Do something...
@}
@end example
@end itemize
If you work on a file that does not follow these guidelines consistently,
@@ -386,9 +366,6 @@ symbols. If in doubt, just avoid names starting with @code{_} altogether.
@item
Casts should be used only when necessary. Unneeded parentheses
should also be avoided if they don't make the code easier to understand.
@item
Where applicable, SI units shall be used. For example timeouts should use seconds as the fundamental unit not microseconds.
That means a bare value like @samp{1.0} must mean 1 second, @samp{50m} means 50 milliseconds. For weight, gram shall be used.
@end itemize
@anchor{Development Policy}
@@ -488,25 +465,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 Bug fixes intended for backporting should stay focused.
Keep bug fixes as small as possible while fully fixing the reported issue.
Changes not needed for correctness or robustness should be submitted separately,
especially if they increase complexity or affect backporting.
@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. However,
indentation changes that can be ignored by @code{git diff --ignore-all-space}
(e.g. changes in whitespace amount, leading/trailing spaces) may be mixed with
functional changes, since reviewers can use @code{git diff -w} or
@code{git log -p --ignore-all-space} to review only the functional parts of
the change. Forgejo's pull request interface also provides a
``Hide whitespace changes'' option for this purpose. Every
with functional changes, such commits will be rejected and removed. Every
developer has his own indentation style, you should not change it. Of course
if you (re)write something, you can use your own style, even though we would
prefer if the indentation throughout FFmpeg was consistent (Many projects
force a given indentation style - we do not.). If you really need to make
non-whitespace cosmetic changes, separate them strictly from real changes.
indentation changes (try to avoid this), separate them strictly from real
changes.
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
@@ -755,8 +722,7 @@ and has no lrint()')
Also please if you send several patches, send each patch as a separate mail,
do not attach several unrelated patches to the same mail.
Patches should be posted to
@uref{https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls, Forgejo} or the
Patches should be posted to the
@uref{https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel, ffmpeg-devel}
mailing list. Use @code{git send-email} when possible since it will properly
send patches without requiring extra care. If you cannot, then send patches
File diff suppressed because it is too large Load Diff
+2 -138
View File
@@ -1045,10 +1045,6 @@ Other values include 0 for mono and stereo, 1 for surround sound with masking
and LFE bandwidth optimizations, and 255 for independent streams with an
unspecified channel layout.
@item dtx (N.A.)
Allow discontinuous transmission when set to 1. The default value is 0
(disabled).
@item apply_phase_inv (N.A.) (requires libopus >= 1.2)
If set to 0, disables the use of phase inversion for intensity stereo,
improving the quality of mono downmixes, but slightly reducing normal stereo
@@ -2000,49 +1996,6 @@ by ":". See the SVT-AV1 encoder user guide for a list of accepted parameters.
@end table
@section libsvtjpegxs
SVT-JPEG-XS encoder wrapper.
Requires the presence of the SVT-JPEG-XS headers and library during configuration.
You need to explicitly configure the build with @code{--enable-libsvtjpegxs}.
@subsection Options
@table @option
@item decomp_v
Set vertical decomposition level
@item decomp_h
Set horizontal decomposition level
@item quantization
Set the quantization algorithm.
@table @samp
@item deadzone
@item uniform
@end table
@item coding-signs
Enable Signs handling strategy
@table @samp
@item disable
@item fast
@item full
@end table
@item coding-sigf
Enable Significance coding
@item coding-vpred
Enable Vertical Prediction coding
@table @samp
@item disable
@item no_residuals
@item no_coeffs
@end table
@end table
@section libjxl
libjxl JPEG XL encoder wrapper.
@@ -3087,10 +3040,6 @@ Quantizer curve compression factor
Normally, when forcing a I-frame type, the encoder can select any type
of I-frame. This option forces it to choose an IDR-frame.
@item x265-stats
Specify the file name for 2-pass stats. This is set automatically when using
the @option{-passlogfile} option.
@item udu_sei @var{boolean}
Import user data unregistered SEI if available into output. Default is 0 (off).
@@ -3464,97 +3413,12 @@ Maximum quantization parameter for B frame.
@section MediaFoundation
The following wrappers for encoders in the MediaFoundation framework are
available:
@itemize
@item h264_mf
@item hevc_mf
@item av1_mf
@end itemize
These support both software and hardware encoding.
This provides wrappers to encoders (both audio and video) in the
MediaFoundation framework. It can access both SW and HW encoders.
Video encoders can take input in either of nv12 or yuv420p form
(some encoders support both, some support only either - in practice,
nv12 is the safer choice, especially among HW encoders).
Hardware-accelerated encoding requires D3D11, including hardware
scaling capabilities through the scale_d3d11 filter.
To list all available options for the MediaFoundation encoders, use:
@command{ffmpeg -h encoder=<encoder>} e.g. @command{ffmpeg -h encoder=h264_mf}
@subsection Options
@table @option
@item rate_control
Select rate control mode. Available modes:
@table @samp
@item default
Default mode
@item cbr
CBR mode
@item pc_vbr
Peak constrained VBR mode
@item u_vbr
Unconstrained VBR mode
@item quality
Quality mode
@item ld_vbr
Low delay VBR mode (requires Windows 8+)
@item g_vbr
Global VBR mode (requires Windows 8+)
@item gld_vbr
Global low delay VBR mode (requires Windows 8+)
@end table
@item scenario
Select usage scenario. Available scenarios:
@table @samp
@item default
Default scenario
@item display_remoting
Display remoting scenario
@item video_conference
Video conference scenario
@item archive
Archive scenario
@item live_streaming
Live streaming scenario
@item camera_record
Camera record scenario
@item display_remoting_with_feature_map
Display remoting with feature map scenario
@end table
@item quality
Set encoding quality (0-100). -1 means default quality.
@item hw_encoding
Force hardware encoding (0-1). Default is 0 (disabled).
@end table
@subsection Examples
Hardware encoding:
@example
ffmpeg -i input.mp4 -c:v h264_mf -hw_encoding 1 output.mp4
@end example
Hardware-accelerated decoding with hardware encoding:
@example
ffmpeg -hwaccel d3d11va -i input.mp4 -c:v h264_mf -hw_encoding 1 output.mp4
@end example
Hardware-accelerated decoding, HW scaling and encoding with quality setting:
@example
ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -i input.mp4 -vf scale_d3d11=1920:1080 -c:v hevc_mf -hw_encoding 1 -quality 80 output.mp4
@end example
@section Microsoft RLE
Microsoft RLE aka MSRLE encoder.
+2
View File
@@ -30,6 +30,8 @@
* file to be played with ffplay.
*/
#include <unistd.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/buffersink.h>
+3 -2
View File
@@ -27,6 +27,8 @@
* @example decode_filter_video.c
*/
#define _XOPEN_SOURCE 600 /* for usleep */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,7 +38,6 @@
#include <libavfilter/buffersrc.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#include <libavutil/time.h>
const char *filter_descr = "scale=78:24,transpose=cclock";
/* other way:
@@ -194,7 +195,7 @@ static void display_frame(const AVFrame *frame, AVRational time_base)
delay = av_rescale_q(frame->pts - last_pts,
time_base, AV_TIME_BASE_Q);
if (delay > 0 && delay < 1000000)
av_usleep(delay);
usleep(delay);
}
last_pts = frame->pts;
}
+1 -5
View File
@@ -42,11 +42,7 @@ static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
FILE *f;
int i;
f = fopen(filename, "wb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
return;
}
f = fopen(filename,"wb");
fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
for (i = 0; i < ysize; i++)
fwrite(buf + i * wrap, 1, xsize, f);
+5 -10
View File
@@ -336,17 +336,15 @@ int main (int argc, char **argv)
if (video_stream) {
printf("Play the output video file with the command:\n"
"ffplay -f rawvideo -pixel_format %s -video_size %dx%d %s\n",
"ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
av_get_pix_fmt_name(pix_fmt), width, height,
video_dst_filename);
}
if (audio_stream) {
enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt;
AVChannelLayout mono = AV_CHANNEL_LAYOUT_MONO;
AVChannelLayout *ch_layout = &audio_dec_ctx->ch_layout;
int n_channels = audio_dec_ctx->ch_layout.nb_channels;
const char *fmt;
char buf[64];
if (av_sample_fmt_is_planar(sfmt)) {
const char *packed = av_get_sample_fmt_name(sfmt);
@@ -354,18 +352,15 @@ int main (int argc, char **argv)
"(%s). This example will output the first channel only.\n",
packed ? packed : "?");
sfmt = av_get_packed_sample_fmt(sfmt);
ch_layout = &mono;
n_channels = 1;
}
if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0)
goto end;
if ((ret = av_channel_layout_describe(ch_layout, buf, sizeof(buf))) < 0)
goto end;
printf("Play the output audio file with the command:\n"
"ffplay -f %s -ch_layout %s -sample_rate %d %s\n",
fmt, buf, audio_dec_ctx->sample_rate,
"ffplay -f %s -ac %d -ar %d %s\n",
fmt, n_channels, audio_dec_ctx->sample_rate,
audio_dst_filename);
}
+9 -31
View File
@@ -41,17 +41,7 @@
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
const void *out_config;
int ret = avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT,
0, &out_config, NULL);
if (ret < 0) {
fprintf(stderr, "Error getting supported sample formats\n");
exit(1);
}
const enum AVSampleFormat *p = out_config;
if (!p)
return 1;
const enum AVSampleFormat *p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
@@ -64,19 +54,13 @@ static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt
/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
const void *out_config;
int ret = avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE,
0, &out_config, NULL);
if (ret < 0) {
fprintf(stderr, "Error getting supported sample rates\n");
exit(1);
}
const int *p = out_config;
const int *p;
int best_samplerate = 0;
if (!p)
if (!codec->supported_samplerates)
return 44100;
p = codec->supported_samplerates;
while (*p) {
if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
best_samplerate = *p;
@@ -88,19 +72,13 @@ static int select_sample_rate(const AVCodec *codec)
/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst)
{
const void *out_config;
int ret = avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_CHANNEL_LAYOUT,
0, &out_config, NULL);
if (ret < 0) {
fprintf(stderr, "Error getting supported channel layouts\n");
exit(1);
}
const AVChannelLayout *p = out_config, *best_ch_layout;
const AVChannelLayout *p, *best_ch_layout;
int best_nb_channels = 0;
if (!p)
if (!codec->ch_layouts)
return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
p = codec->ch_layouts;
while (p->nb_channels) {
int nb_channels = p->nb_channels;
@@ -240,10 +218,10 @@ int main(int argc, char **argv)
samples = (uint16_t*)frame->data[0];
for (j = 0; j < c->frame_size; j++) {
samples[c->ch_layout.nb_channels*j] = (int)(sin(t) * 10000);
samples[2*j] = (int)(sin(t) * 10000);
for (k = 1; k < c->ch_layout.nb_channels; k++)
samples[c->ch_layout.nb_channels*j + k] = samples[c->ch_layout.nb_channels*j];
samples[2*j + k] = samples[2*j];
t += tincr;
}
encode(c, frame, pkt, f);
-1
View File
@@ -109,7 +109,6 @@ static int open_codec_context(AVFormatContext *fmt_ctx, enum AVMediaType type)
ret = avcodec_parameters_to_context(dec_ctx, st->codecpar);
if (ret < 0) {
fprintf(stderr, "Failed to copy codec parameters to codec context\n");
avcodec_free_context(&dec_ctx);
return ret;
}
+2 -9
View File
@@ -132,9 +132,8 @@ static int decode_write(AVCodecContext *avctx, AVPacket *packet)
goto fail;
}
if (fwrite(buffer, 1, size, output_file) != size) {
if ((ret = fwrite(buffer, 1, size, output_file)) < 0) {
fprintf(stderr, "Failed to dump raw data.\n");
ret = -1;
goto fail;
}
@@ -216,10 +215,8 @@ int main(int argc, char *argv[])
return AVERROR(ENOMEM);
video = input_ctx->streams[video_stream];
if (avcodec_parameters_to_context(decoder_ctx, video->codecpar) < 0) {
avcodec_free_context(&decoder_ctx);
if (avcodec_parameters_to_context(decoder_ctx, video->codecpar) < 0)
return -1;
}
decoder_ctx->get_format = get_hw_format;
@@ -233,10 +230,6 @@ int main(int argc, char *argv[])
/* open the file to dump raw data */
output_file = fopen(argv[3], "w+b");
if (!output_file) {
fprintf(stderr, "Cannot open output file '%s'\n", argv[3]);
return -1;
}
/* actual decoding and dump the raw data */
while (ret >= 0) {
+9 -25
View File
@@ -127,7 +127,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc,
enum AVCodecID codec_id)
{
AVCodecContext *c;
int ret;
int i;
/* find the encoder */
*codec = avcodec_find_encoder(codec_id);
@@ -157,37 +157,21 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc,
ost->enc = c;
switch ((*codec)->type) {
case AVMEDIA_TYPE_AUDIO: {
const void *codec_config;
case AVMEDIA_TYPE_AUDIO:
c->sample_fmt = (*codec)->sample_fmts ?
(*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
c->bit_rate = 64000;
ret = avcodec_get_supported_config(c, NULL, AV_CODEC_CONFIG_SAMPLE_FORMAT,
0, &codec_config, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to get supported sample formats\n");
exit(1);
}
c->sample_fmt = codec_config ? *(const enum AVSampleFormat*)codec_config
: AV_SAMPLE_FMT_FLTP;
ret = avcodec_get_supported_config(c, NULL, AV_CODEC_CONFIG_SAMPLE_RATE,
0, &codec_config, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to get supported sample rates\n");
exit(1);
}
if (codec_config) {
const int *supported_samplerates = codec_config;
c->sample_rate = supported_samplerates[0];
for (; *supported_samplerates; supported_samplerates++) {
if (*supported_samplerates == 44100)
c->sample_rate = 44100;
if ((*codec)->supported_samplerates) {
c->sample_rate = (*codec)->supported_samplerates[0];
for (i = 0; (*codec)->supported_samplerates[i]; i++) {
if ((*codec)->supported_samplerates[i] == 44100)
c->sample_rate = 44100;
}
} else {
c->sample_rate = 44100;
}
av_channel_layout_copy(&c->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
ost->st->time_base = (AVRational){ 1, c->sample_rate };
break;
}
case AVMEDIA_TYPE_VIDEO:
c->codec_id = codec_id;
+3 -11
View File
@@ -39,7 +39,6 @@
#include <libavutil/error.h>
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_qsv.h>
#include <libavutil/imgutils.h>
#include <libavutil/mem.h>
static int get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts)
@@ -89,16 +88,9 @@ static int decode_packet(AVCodecContext *decoder_ctx,
goto fail;
}
for (i = 0; i < FF_ARRAY_ELEMS(sw_frame->data) && sw_frame->data[i]; i++) {
int h = sw_frame->height >> (i > 0);
int linesize = av_image_get_linesize(sw_frame->format, sw_frame->width, i);
if (linesize < 0) {
ret = linesize;
goto fail;
}
for (j = 0; j < h; j++)
avio_write(output_ctx, sw_frame->data[i] + j * sw_frame->linesize[i], linesize);
}
for (i = 0; i < FF_ARRAY_ELEMS(sw_frame->data) && sw_frame->data[i]; i++)
for (j = 0; j < (sw_frame->height >> (i > 0)); j++)
avio_write(output_ctx, sw_frame->data[i] + j * sw_frame->linesize[i], sw_frame->width);
fail:
av_frame_unref(sw_frame);
+1 -7
View File
@@ -351,10 +351,6 @@ int main(int argc, char **argv)
}
setting_number = (argc - 5) / 2;
dynamic_setting = av_malloc(setting_number * sizeof(*dynamic_setting));
if (!dynamic_setting) {
ret = AVERROR(ENOMEM);
goto end;
}
current_setting_number = 0;
for (int i = 0; i < setting_number; i++) {
dynamic_setting[i].frame_number = atoi(argv[i*2 + 5]);
@@ -430,9 +426,7 @@ int main(int argc, char **argv)
end:
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
avformat_close_input(&ofmt_ctx);
avcodec_free_context(&decoder_ctx);
avcodec_free_context(&encoder_ctx);
av_buffer_unref(&hw_device_ctx);
+1 -1
View File
@@ -184,7 +184,7 @@ end:
avformat_close_input(&ifmt_ctx);
/* close output */
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
+2 -2
View File
@@ -177,7 +177,7 @@ static int open_output_file(const char *filename)
enc_ctx->width = dec_ctx->width;
enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
ret = avcodec_get_supported_config(enc_ctx, NULL,
ret = avcodec_get_supported_config(dec_ctx, NULL,
AV_CODEC_CONFIG_PIX_FORMAT, 0,
(const void**)&pix_fmts, NULL);
@@ -195,7 +195,7 @@ static int open_output_file(const char *filename)
if (ret < 0)
return ret;
ret = avcodec_get_supported_config(enc_ctx, NULL,
ret = avcodec_get_supported_config(dec_ctx, NULL,
AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
(const void**)&sample_fmts, NULL);
+1 -6
View File
@@ -152,7 +152,6 @@ static int open_output_file(const char *filename,
AVIOContext *output_io_context = NULL;
AVStream *stream = NULL;
const AVCodec *output_codec = NULL;
const void *sample_fmts;
int error;
/* Open the output file to write to it. */
@@ -208,12 +207,8 @@ static int open_output_file(const char *filename,
/* Set the basic encoder parameters.
* The input file's sample rate is used to avoid a sample rate conversion. */
av_channel_layout_default(&avctx->ch_layout, OUTPUT_CHANNELS);
error = avcodec_get_supported_config(avctx, NULL, AV_CODEC_CONFIG_SAMPLE_FORMAT,
0, &sample_fmts, NULL);
av_assert0(error >= 0);
avctx->sample_fmt = sample_fmts ? *(const enum AVSampleFormat*)sample_fmts
: input_codec_context->sample_fmt;
avctx->sample_rate = input_codec_context->sample_rate;
avctx->sample_fmt = output_codec->sample_fmts[0];
avctx->bit_rate = OUTPUT_BIT_RATE;
/* Set the sample rate for the container. */
+3 -3
View File
@@ -96,6 +96,7 @@ static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout)
end:
av_packet_free(&enc_pkt);
ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1);
return ret;
}
@@ -117,7 +118,7 @@ int main(int argc, char *argv[])
height = atoi(argv[2]);
size = width * height;
if (!(fin = fopen(argv[3], "rb"))) {
if (!(fin = fopen(argv[3], "r"))) {
fprintf(stderr, "Fail to open input file : %s\n", strerror(errno));
return -1;
}
@@ -197,8 +198,7 @@ int main(int argc, char *argv[])
goto close;
}
err = encode_write(avctx, hw_frame, fout);
if (err != AVERROR(EAGAIN) && err < 0) {
if ((err = (encode_write(avctx, hw_frame, fout))) < 0) {
fprintf(stderr, "Failed to encode.\n");
goto close;
}
+1 -3
View File
@@ -294,9 +294,7 @@ int main(int argc, char **argv)
end:
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
avformat_close_input(&ofmt_ctx);
avcodec_free_context(&decoder_ctx);
avcodec_free_context(&encoder_ctx);
av_buffer_unref(&hw_device_ctx);
+18 -38
View File
@@ -42,60 +42,41 @@ targets and variables.
@chapter Using FATE from your FFmpeg source directory
If you want to run FATE on your machine, FFmpeg needs to be configured first.
You may specify the location of samples during configuration by adding the
argument @code{--samples=/path/to/fate-suite}.
If you want to run FATE on your machine you need to have the samples
in place. You can get the samples via the build target fate-rsync.
Use this command from the top-level source directory:
@example
./configure --enable-somelib --samples=/path/to/fate-suite
make fate-rsync SAMPLES=fate-suite/
make fate SAMPLES=fate-suite/
@end example
After successful configuration, you need to add and/or update the samples in place:
The above commands set the samples location by passing a makefile
variable via command line. It is also possible to set the samples
location at source configuration time by invoking configure with
@option{--samples=<path to the samples directory>}. Afterwards you can
invoke the makefile targets without setting the @var{SAMPLES} makefile
variable. This is illustrated by the following commands:
@example
make fate-rsync
@end example
Now you are ready to run FATE:
@example
make fate
@end example
See @ref{makefile variables} for a list of arguments that can be added.
If you did not set the samples path during configuration, or if you wish to
override it just before starting FATE, you can do so in one of three ways.
Either by setting a make variable:
@example
make fate-rsync SAMPLES=/path/to/fate-suite
make fate SAMPLES=/path/to/fate-suite
@end example
or by setting an environment variable for the current session:
@example
export FATE_SAMPLES=/path/to/fate-suite
./configure --samples=fate-suite/
make fate-rsync
make fate
@end example
or in isolation for a single command by prepending it:
Yet another way to tell FATE about the location of the sample
directory is by making sure the environment variable FATE_SAMPLES
contains the path to your samples directory. This can be achieved
by e.g. putting that variable in your shell profile or by setting
it in your interactive session.
@example
FATE_SAMPLES=/path/to/fate-suite make fate-rsync
FATE_SAMPLES=/path/to/fate-suite make fate
FATE_SAMPLES=fate-suite/ make fate
@end example
This variable can also be set in your shell profile to make it permanent.
@float NOTE
Do not put a '~' character in the samples path to indicate a home
directory. Because of shell nuances, this will cause FATE to fail.
Also, on Windows the path has to be relative to the build path
which in this case is the FFmpeg source directory.
@end float
Beware that some assertions are disabled by default, so mind setting
@@ -239,7 +220,6 @@ Run the FATE test suite (requires the fate-suite dataset).
@end table
@section Makefile variables
@anchor{makefile variables}
@table @env
@item V
-7
View File
@@ -6,28 +6,21 @@ workdir= # directory in which to do all the work
#fate_recv="ssh -T fate@fate.ffmpeg.org" # command to submit report
comment= # optional description
build_only= # set to "yes" for a compile-only instance that skips tests
skip_clean= # set to "yes" to preserve build/install directories
ignore_tests=
# the following are optional and map to configure options
arch=
cpu=
toolchain=
cross_prefix=
ar=
as=
cc=
cxx=
ld=
nm=
target_os=
sysroot=
target_exec=
target_path=
target_samples=
extra_cflags=
extra_cxxflags=
extra_objcflags=
extra_ldflags=
extra_libs=
extra_conf= # extra configure options not covered above
+13 -37
View File
@@ -1569,27 +1569,6 @@ Set whether on display the image should be vertically flipped.
See the @code{-display_rotation} option for more details.
@item -mastering_display[:@var{stream_specifier}] @var{G(%u,%u)B(%u,%u)R(%u,%u)WP(%u,%u)L(%u,%u)} (@emph{input,per-stream})
Set video mastering display metadata.
@var{G(%u,%u)B(%u,%u)R(%u,%u)WP(%u,%u)L(%u,%u)} is a string specifying
X,Y display primaries for GBR channels and white point (WP) in units of
0.00002, and max-min luminance (L) values in units of 0.0001 candela per
meter square. The values are unsigned integers representing the numerator
of a rational with an implicit denominator of 50000 for GBR and (WP), and
implicit denominator 10000 for (L).
This option overrides the mastering display metadata stored in the file,
if any.
@item -content_light[:@var{stream_specifier}] @var{%u,%u} (@emph{input,per-stream})
Set video content light metadata.
@var{%u,%u} is a string specifying max content light level and maximum picture
average light level.
This option overrides the content light metadata stored in the file, if any.
@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}
@@ -1686,7 +1665,6 @@ Force video tag/fourcc. This is an alias for @code{-tag:v}.
@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}] scd_metadata (@emph{output,per-stream})
@var{force_key_frames} can take arguments of the following form:
@@ -1750,14 +1728,6 @@ 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.
@item scd_metadata
If the argument is @code{scd_metadata}, ffmpeg will force a key frame if
the current frame contains a metadata entry with the key @code{lavfi.scd.time}.
The metadata can be added by filters like @code{scdet} and @code{scdet_vulkan}.
Avoid inserting filters that duplicate frames after @code{scdet}, as this can
cause duplicate metadata for multiple frames and repeated insertion of key
frames.
@end table
Note that forcing too many keyframes is very harmful for the lookahead
@@ -2388,19 +2358,25 @@ If either the input or output is blocked leading to actual read speed falling be
specified readrate, then this rate takes effect till the input catches up with the
specified readrate. Must not be lower than the primary readrate.
@item -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream})
Set video sync method / framerate mode.
@item -vsync @var{parameter} (@emph{global})
@itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream})
Set video sync method / framerate mode. vsync is applied to all output video streams
but can be overridden for a stream by setting fps_mode. vsync is deprecated and will be
removed in the future.
For compatibility reasons some of the values for vsync can be specified as numbers (shown
in parentheses in the following table).
@table @option
@item passthrough
@item passthrough (0)
Each frame is passed with its timestamp from the demuxer to the muxer.
@item cfr
@item cfr (1)
Frames will be duplicated and dropped to achieve exactly the requested
constant frame rate.
@item vfr
@item vfr (2)
Frames are passed through with their timestamp or dropped so as to
prevent 2 frames from having the same timestamp.
@item auto
@item auto (-1)
Chooses between cfr and vfr depending on muxer capabilities. This is the
default method.
@end table
@@ -2430,7 +2406,7 @@ Do not process input timestamps, but keep their values without trying
to sanitize them. In particular, do not remove the initial start time
offset value.
Note that, depending on the @option{fps_mode} option or on specific muxer
Note that, depending on the @option{vsync} option or on specific muxer
processing (e.g. in case the format option @option{avoid_negative_ts}
is enabled) the output timestamps may mismatch with the input
timestamps even when this option is selected.
+4 -10
View File
@@ -208,14 +208,6 @@ Vulkan configuration using a list of @var{key}=@var{value} pairs separated by
Use HW accelerated decoding. Enable this option will enable vulkan renderer
automatically.
@item -video_bg @var{pattern}
Set the video background pattern used for transparent videos. For solid color
patterns you can use the color name or color code as specified in the
@ref{color syntax,,Color section in the ffmpeg-utils(1) manual,ffmpeg-utils}.
You can also use the special @code{tiles} keyword for a checker board style
pattern. This is also the default. The @code{none} pattern does rendering
without alpha blending effectively ignoring alpha channel.
@end table
@section While playing
@@ -259,13 +251,15 @@ Pause if the stream is not already paused, step to the next video
frame, and pause.
@item left/right
Seek backward/forward by 10 seconds or a custom interval if -seek_interval is set.
Seek backward/forward 10 seconds.
@item down/up
Seek backward/forward 1 minute.
@item page down/page up
Seek to previous/next chapter or backward/forward 10 minutes if no chapters.
Seek to the previous/next chapter.
or if there are no chapters
Seek backward/forward 10 minutes.
@item right mouse click
Seek to percentage in file corresponding to fraction of width.
+1 -13
View File
@@ -117,8 +117,7 @@ ffprobe -show_packets -select_streams v:1 INPUT
@end example
@item -show_data
Show payload data, as a hexadecimal and ASCII dump (other formats can be
selected using @option{-data_dump_format}). Coupled with
Show payload data, as a hexadecimal and ASCII dump. Coupled with
@option{-show_packets}, it will dump the packets' data. Coupled with
@option{-show_streams}, it will dump the codec extradata.
@@ -128,11 +127,6 @@ The dump is printed as the "data" field. It may contain newlines.
Show a hash of payload data, for packets with @option{-show_packets} and for
codec extradata with @option{-show_streams}.
@item -data_dump_format @var{format}
Select a format used for the data dumps enabled with the @option{-show_data}
option. The default is @code{xxd} which is a hexdump format compatible with the
well-known @command{xxd} program. @code{base64} is also supported.
@item -show_error
Show information about the error found when trying to probe the input.
@@ -374,12 +368,6 @@ Read @var{input_url}.
Write output to @var{output_url}. If not specified, the output is sent
to stdout.
@item -c:@var{media_specifier} @var{codec_name}
@itemx -codec:@var{media_specifier} @var{codec_name}
Force a specific decoder implementation for the stream identified by
@var{media_specifier}, which can assume the values @code{a} (audio),
@code{v} (video), @code{s} (subtitle), and @code{d} (data).
@end table
@c man end
-2
View File
@@ -276,7 +276,6 @@
<xsd:attribute name="extradata" type="xsd:string" />
<xsd:attribute name="extradata_size" type="xsd:int" />
<xsd:attribute name="extradata_hash" type="xsd:string" />
<xsd:attribute name="mime_codec_string" type="xsd:string" />
<!-- video attributes -->
<xsd:attribute name="width" type="xsd:int"/>
@@ -357,7 +356,6 @@
<xsd:complexType name="streamGroupComponentType">
<xsd:sequence>
<xsd:element name="subcomponents" type="ffprobe:streamGroupSubComponentList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="side_data_list" type="ffprobe:packetSideDataListType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="component_entry" type="ffprobe:streamGroupEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
+1 -1
View File
@@ -98,7 +98,7 @@ These options are shared amongst the ff* tools.
@table @option
@item -L, -license
@item -L
Show license.
@item -h, -?, -help, --help [@var{arg}]
+418 -1012
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -100,9 +100,6 @@ Print specific debug info.
Possible values:
@table @samp
@item ts
Print timestamp information.
@item id3v2
Print ID3v2 frame data when demuxing files containing ID3v2 tags.
@end table
@item max_delay @var{integer} (@emph{input/output})
+2 -54
View File
@@ -205,39 +205,6 @@ FFmpeg can make use of this library, originating in Modplug-XMMS, to read from M
See @url{https://github.com/Konstanty/libmodplug}. Pass @code{--enable-libmodplug} to configure to
enable it.
@section ONNX Runtime
FFmpeg can make use of the ONNX Runtime library as a backend for DNN based filters.
Go to @url{https://onnxruntime.ai/} and follow the instructions for installing
the library. Pre-built packages are available for various platforms.
Configure FFmpeg with ONNX Runtime support:
@example
./configure \
--enable-libonnxruntime \
--extra-cflags="-I/path/to/onnxruntime/include" \
--extra-ldflags="-L/path/to/onnxruntime/lib"
@end example
On ELF-based systems (Linux, BSD) you may also want to embed the
library search path so that the installed @file{ffmpeg} binary finds the
shared library at run time without setting @env{LD_LIBRARY_PATH}:
@example
./configure \
--enable-libonnxruntime \
--extra-cflags="-I/path/to/onnxruntime/include" \
--extra-ldflags="-L/path/to/onnxruntime/lib -Wl,-rpath,/path/to/onnxruntime/lib"
@end example
The @code{-Wl,-rpath} flag is ELF-specific and should be omitted on
other platforms (Windows, macOS).
For MinGW GCC builds, add the @code{-D_stdcall=__stdcall} flag for compatibility
with ONNX Runtime headers.
@section OpenCORE, VisualOn, and Fraunhofer libraries
Spun off Google Android sources, OpenCore, VisualOn and Fraunhofer
@@ -283,14 +250,6 @@ Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the
instructions for installing the library.
Then pass @code{--enable-libfdk-aac} to configure to enable it.
@subsection Fraunhofer MPEG-H 3D Audio decoder library
FFmpeg can make use of the Fraunhofer MPEG-H decoder library for MPEG-H 3DA decoding.
Go to @url{https://github.com/Fraunhofer-IIS/mpeghdec} and follow the
instructions for installing the library.
Then pass @code{--enable-libmpeghdec --enable-nonfree} to configure to enable it.
@subsection LC3 library
FFmpeg can make use of the Google LC3 library for LC3 decoding & encoding.
@@ -336,15 +295,6 @@ Go to @url{https://gitlab.com/AOMediaCodec/SVT-AV1/} and follow the instructions
for installing the library. Then pass @code{--enable-libsvtav1} to configure to
enable it.
@section SVT-JPEG-XS
FFmpeg can make use of the Scalable Video Technology for JPEG-XS library for JPEG-XS
decoding and encoding.
Go to @url{https://github.com/OpenVisualCloud/SVT-JPEG-XS} and follow the instructions
for installing the library. Then pass @code{--enable-libsvtjpegxs} to configure to
enable it.
@section TwoLAME
FFmpeg can make use of the TwoLAME library for MP2 encoding.
@@ -861,8 +811,6 @@ following image formats are supported:
@tab Progressive JPEG is not supported.
@item JPEG 2000 @tab X @tab X
@item JPEG-LS @tab X @tab X
@item JPEG-XS @tab E @tab E
@tab Supported through external library libsvtjpegxs
@item LJPEG @tab X @tab
@tab Lossless JPEG
@item Media 100 @tab @tab X
@@ -1328,6 +1276,8 @@ following image formats are supported:
@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
@tab en/decoding supported through external library libcodec2
@item CRI HCA @tab @tab X
@@ -1394,8 +1344,6 @@ 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 MPEG-H 3D Audio @tab @tab E
@tab decoding supported through external library libmpeghdec
@item MobiClip FastAudio @tab @tab X
@item Musepack SV7 @tab @tab X
@item Musepack SV8 @tab @tab X
-1
View File
@@ -4,4 +4,3 @@ ffmpeg-formats mono ./ffmpeg-formats.html
ffmpeg-resampler mono ./ffmpeg-resampler.html
ffmpeg-scaler mono ./ffmpeg-scaler.html
ffmpeg-utils mono ./ffmpeg-utils.html
drawvg-reference mono ./drawvg-reference.html
+1 -22
View File
@@ -24,26 +24,6 @@ Our Main server is hosted at telepoint.bg
for more details see: https://www.ffmpeg.org/#thanks_sponsor_0001
Nothing runs on our main server directly, instead several VMs run on it.
Main server security:
---------------------
Telepoint is one of the largest Bulgarian DC providers with multiple sibling companies offering
Internet, SDH, DWDM, peering exchange and hosting. They have multiple DC buildings in Sofia and
FFmpeg is hosted in XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. The building is locked down and accessible
only with personal key cards that are registered. People who are granted access to a rack have
to go through the access center with their ID to get logged and receive a one-time access card
that can open the service elevator and only the hall where the destination rack is. All racks are
locked, once access is granted to someone they will get a key for the rack for the duration of
their visit. There are security cameras everywhere and personnel in the access center 24/7. As for
software security, our BIOS and IPMI are protected by password and encrypted connection, and
the machines can be accessed only by root administrators with their SSH keys. They're using
a Ubuntu LTS release and get regular security updates as they are released. We also get
notified by email for various security related events (e.g. failed sudo).
Side note - Telepoint provides the rack and physical infrastructure, their sibling company called
Telehouse which is an ISP provides the connectivity, they are directly connected with
over 15 tier-1 service providers and have over 100 PoPs (points of presence)
in various cities. You can see more on www.telehouse.bg
ffmpeg.org VM:
--------------
@@ -52,8 +32,7 @@ Web, mail, and public facing git, also website git
fftrac VM:
----------
trac.ffmpeg.org Legacy issue tracking
code.ffmpeg.org Primary issue tracking
trac.ffmpeg.org Issue tracking
gpg encrypted backups of the trac repositories are created once a day
and can be downloaded by any of the admins.
+1 -4
View File
@@ -21,10 +21,7 @@ a mail for every change to every issue.
The subscription URL for the ffmpeg-trac list is:
https://lists.ffmpeg.org/mailman/listinfo/ffmpeg-trac
The primary issue tracker is:
https://code.ffmpeg.org/FFmpeg/FFmpeg/issues
Legacy issues may still exist on:
The URL of the webinterface of the tracker is:
https://trac.ffmpeg.org
Type:
+1 -1
View File
@@ -341,7 +341,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/community.html#Code-of-conduct, Code of Conduct}.
@end itemize
@chapter Help
+5 -212
View File
@@ -1330,21 +1330,11 @@ element. Imply that the @option{single_file} option is set to
@var{true}. In the template, @code{$ext$} is replaced with the file
name extension specific for the segment format.
@item availability_start_time_ms @var{milliseconds}
Set the MPD @code{availabilityStartTime} attribute as Unix epoch time in
milliseconds. If set to @code{0}, the wall clock is used when the first
packet is written. This is useful for live outputs that need a stable
availability start time across restarts.
@item streaming @var{bool}
Enable or disable chunk streaming mode of output. In chunk streaming
mode, each frame will be a @code{moof} fragment which forms a
chunk. This is disabled by default.
@item suggested_presentation_delay @var{duration}
Set the MPD @code{suggestedPresentationDelay} attribute. If set to
@code{0}, the last segment duration is used.
@item target_latency @var{target_latency}
Set an intended target latency in seconds for serving (fractional
value can be set). Applicable only when the @option{streaming} and
@@ -1769,7 +1759,7 @@ See also the @ref{framehash} and @ref{md5} muxers.
Animated GIF muxer.
Note that the GIF format has a very large time base: the delay between two frames can
therefore not be smaller than one centisecond.
therefore not be smaller than one centi second.
@subsection Options
@table @option
@@ -2654,12 +2644,6 @@ writing is completed. Default is disabled.
@item protocol_opts @var{options_list}
Set protocol options as a :-separated list of key=value parameters. Values
containing the @code{:} special character must be escaped.
@item update_filemtime @var{bool}
If set to 1, set each output file's modification time to the
@code{creation_time} metadata value plus the frame's PTS offset.
If @code{creation_time} is missing or unparsable, a warning is
logged and the option is ignored. Default value is 0.
@end table
@subsection Examples
@@ -2668,7 +2652,7 @@ logged and the option is ignored. Default value is 0.
Use @command{ffmpeg} for creating a sequence of files @file{img-001.jpeg},
@file{img-002.jpeg}, ..., taking one image every second from the input video:
@example
ffmpeg -i in.avi -fps_mode cfr -r 1 -f image2 'img-%03d.jpeg'
ffmpeg -i in.avi -vsync cfr -r 1 -f image2 'img-%03d.jpeg'
@end example
Note that with @command{ffmpeg}, if the format is not specified with the
@@ -2676,7 +2660,7 @@ Note that with @command{ffmpeg}, if the format is not specified with the
format, the image2 muxer is automatically selected, so the previous
command can be written as:
@example
ffmpeg -i in.avi -fps_mode cfr -r 1 'img-%03d.jpeg'
ffmpeg -i in.avi -vsync cfr -r 1 'img-%03d.jpeg'
@end example
Note also that the pattern must not necessarily contain "%d" or
@@ -2728,58 +2712,6 @@ computer-generated compositions.
This muxer accepts a single audio stream containing PCM data.
@section iterm2
iTerm2 inline image protocol muxer.
This muxer writes video frames as OSC 1337 inline images for display in
terminals that support the iTerm2 image protocol. Use @option{-re} to limit
the output rate to the source framerate; without it, frames are emitted as
fast as they are encoded, which is usually not desired for live display.
Frames are sent with the multipart form of the protocol, which splits each
image across several short control sequences. This avoids the per-sequence
size limit that otherwise discards large frames, and requires iTerm2 3.5 or
newer.
The output is a self-contained byte stream and can be redirected to a file.
Replaying the file with @command{cat} displays the images in the terminal.
@subsection Options
@table @option
@item display_width @var{size}
Set the displayed image width. @var{size} can be @samp{auto}, @var{N} terminal
cells, @var{N}px pixels, or @var{N}% of the terminal width. When unset, the
terminal derives the width from the image.
@item display_height @var{size}
Set the displayed image height. @var{size} uses the same syntax as
@option{display_width}. When unset, the terminal derives the height from the
image.
@item keep_aspect @var{bool}
Preserve the input aspect ratio when scaling. Default is enabled.
@item tmux @var{bool}
Wrap image data in tmux DCS passthrough. This requires a tmux version whose
passthrough sequence size limit is large enough for image data, with
passthrough enabled via @command{tmux set -g allow-passthrough on}. Default is
disabled.
@end table
@subsection Examples
Display a video in an iTerm2 terminal:
@example
ffmpeg -re -i input.mp4 -f iterm2 -
@end example
Scale the displayed image to 40 terminal cells tall. Inside tmux, enable
passthrough first with @command{tmux set -g allow-passthrough on}, then add
@option{tmux}:
@example
ffmpeg -re -i input.mp4 -f iterm2 -display_height 40 -tmux 1 -
@end example
@section ivf
On2 IVF muxer.
@@ -2819,14 +2751,6 @@ song lyrics with an audio file, such as MP3, Vorbis, or MIDI.
This muxer accepts a single @samp{subrip} or @samp{text} subtitles stream.
@subsection Options
@table @option
@item precision @var{number}
Set the number of decimal digits used for the fractional (sub-second)
part of the timestamps. Range is @code{1} to @code{6}. Default is
@code{2}, i.e. centiseconds.
@end table
@subsection Metadata
The following metadata tags are converted to the format corresponding
metadata:
@@ -3145,7 +3069,7 @@ Default is @code{0x0001}.
Set the @samp{original_network_id}. This is unique identifier of a
network in DVB. Its main use is in the unique identification of a service
through the path @samp{Original_Network_ID, Transport_Stream_ID}. Default
is @code{0xff01}.
is @code{0x0001}.
@item mpegts_service_id @var{integer}
Set the @samp{service_id}, also known as program in DVB. Default is
@@ -3172,8 +3096,6 @@ MPEG2 Digital HDTV service.
Advanced Codec Digital SDTV service.
@item advanced_codec_digital_hdtv
Advanced Codec Digital HDTV service.
@item hevc_digital_hdtv
HEVC Digital Television service.
@end table
@item mpegts_pmt_start_pid @var{integer}
@@ -3350,19 +3272,6 @@ ogg files can be safely chained.
@end table
@section pdv
Playdate Video muxer.
This muxer writes the Playdate video container used by Panic's Playdate SDK.
It requires a seekable output and a single PDV video stream.
@table @option
@item max_frames @var{frames}
Reserve space for at most @var{frames} video frames in the file header. This
option is mandatory.
@end table
@anchor{rcwtenc}
@section rcwt
@@ -3608,13 +3517,6 @@ Wrap around segment index once it reaches @var{limit}.
@item segment_start_number @var{number}
Set the sequence number of the first segment. Defaults to @code{0}.
@item segment_wrap_number @var{number}
Set the number of times the segment index is assumed to have already wrapped
when generating the indexes reported in the segment list. Together with
@option{segment_wrap} and @option{segment_start_number} it offsets the reported
index, which is computed as @code{segment_start_number + segment_wrap *
segment_wrap_number}. Defaults to @code{0}.
@item strftime @var{1|0}
Use the @code{strftime} function to define the name of the new
segments to write. If this is selected, the output segment name must
@@ -3641,25 +3543,6 @@ argument must be a time duration specification, and defaults to 0.
If enabled, write an empty segment if there are no packets during the period a
segment would usually span. Otherwise, the segment will be filled with the next
packet written. Defaults to @code{0}.
@item write_header_trailer @var{bool}
Write a header to the first segment and a trailer to the last one, instead of
writing a header and a trailer to every individual segment. Disabling it
(@code{false}) also forces @option{individual_header_trailer} to @code{false},
so that no segment is given a header or trailer. Default value is @code{true}.
@item individual_header_trailer @var{bool}
If enabled, write a complete header and trailer to every segment, making each
segment an independently usable file. If disabled (@code{false}), only the first
segment is given a header and only the last one a trailer. It is forced to
@code{false} when @option{write_header_trailer} is @code{false} or when
@option{segment_header_filename} is set. Default value is @code{true}.
@item segment_header_filename @var{name}
Write the stream header to a separate file named @var{name} instead of storing
it in the segments. Setting it forces @option{write_header_trailer} to
@code{true} and @option{individual_header_trailer} to @code{false}, so the
header is written only once, to @var{name}. Unset by default.
@end table
Make sure to require a closed GOP when encoding and to set the GOP
@@ -3925,76 +3808,6 @@ ffmpeg -i ... -map 0 -flags +global_header -c:v libx264 -c:a aac
@end example
@end itemize
@section wav
RIFF Wave Audio muxer.
@subsection Options
@table @option
@item rf64 @var{mode}
Choose whether to use the RF64 file format instead of RIFF.
RF64 allows files larger than 4 gigabytes, but RF64 support is not as
universal as RIFF.
The following modes are recognized:
@table @samp
@item auto
Start writing a standard RIFF file to retain compatibility with non-RF64-aware
software, but switch to RF64 if the output file grows larger than 4 gigabytes.
Reserves a small amount of extra space in the header using a @code{JUNK} chunk,
which should be ignored by all compliant RIFF readers, but some extremely
simplistic WAV readers may be confused by this.
@item always
Always use the RF64 format regardless of file size. The output file will only
be readable by RF64-compatible software and is no longer a standard RIFF WAVE
file.
@item never
Always use plain RIFF, never RF64. This mode is the most compatible with legacy
software, but if the output file grows beyond 4 gigabytes, the 32-bit size field
in the @code{data} chunk will no longer be able to correctly represent the size,
and most audio software will not be able to read some or all of the data.
(The @ref{wav} demuxer's @code{ignore_length} option can be used to recover such
a file.)
This is the default mode.
@end table
@item write_bext @var{bool}
Add a Broadcast Wave Format @code{BEXT} chunk containing extended audio
metadata if enabled. Defaults to false.
@item write_peak @var{mode}
Add a Peak Envelope chunk (EBU Tech 3285 Supplement 3) if enabled.
Defaults to off.
@table @samp
@item off
Do not add the Peak Envelope chunk.
@item on
Add the Peak Envelope chunk, calculating the peak values based on the
@code{peak_block_size}, @code{peak_format}, and @code{peak_ppv} options.
@item only
Like @code{on}, but skip writing the actual audio data (no @code{data}
chunk will be written to the file; only the Peak Envelope and other metadata
chunks will be written.)
@end table
@item peak_block_size @var{int}
Number of audio samples used to generate each peak frame, up to 65536.
Default is 256.
@item peak_format @var{format}
The format of the peak envelope data (1: uint8, 2: uint16). Default is 2 (uint16).
@item peak_ppv @var{int}
Number of peak points per peak value (1 or 2). Default is 2.
@end table
@section webm_chunk
WebM Live Chunk Muxer.
@@ -4138,29 +3951,9 @@ This muxer supports the following options:
Set the timeout in milliseconds for ICE and DTLS handshake.
Default value is 5000.
@item timeout @var{integer}
Set timeout in seconds for socket I/O operations. Applicable only for HTTP output.
Default value is -1.
@item pkt_size @var{integer}
Set the maximum size, in bytes, of RTP packets that send out.
Default value is 1200.
@item ts_buffer_size @var{integer}
Set the buffer size, in bytes, of underlying protocol.
Default value is -1(auto). The UDP auto selects a reasonable value.
@item whip_flags @var{flags}
Possible values:
@table @samp
@item dtls_active
The muxer will try to set dtls active role and send the first client hello.
@end table
@item rtp_history @var{integer}
Set the number of RTP history items to store.
Default value is 512.
Default value is 1500.
@item authorization @var{string}
The optional Bearer token for WHIP Authorization.
+7 -2
View File
@@ -5,7 +5,7 @@ What to optimize:
-----------------
If you plan to do non-x86 architecture specific optimizations (SIMD normally),
then take a look in the x86/ directory, as most important functions are
already optimized for x86.
already optimized for MMX.
If you want to do x86 optimizations then you can either try to fine-tune the
stuff in the x86 directory or find some other functions in the C source to
@@ -20,7 +20,7 @@ architecture-specific versions. It is recommended to look at older
revisions of the interesting files (web frontends for the various FFmpeg
branches are listed at http://ffmpeg.org/download.html).
Alternatively, look into the other architecture-specific versions in
the x86/, ppc/, aarch64/ subdirectories. Even if you don't exactly
the x86/, ppc/, alpha/ subdirectories. Even if you don't exactly
comprehend the instructions, it could help understanding the functions
and how they can be optimized.
@@ -191,6 +191,11 @@ __asm__() block.
Use external asm (nasm) or inline asm (__asm__()), do not use intrinsics.
The latter requires a good optimizing compiler which gcc is not.
When debugging a x86 external asm compilation issue, if lost in the macro
expansions, add DBG=1 to your make command-line: the input file will be
preprocessed, stripped of the debug/empty lines, then compiled, showing the
actual lines causing issues.
Inline asm vs. external asm
---------------------------
Both inline asm (__asm__("..") in a .c file, handled by a compiler such as gcc)
-16
View File
@@ -330,20 +330,4 @@ and for a build with shared libraries
./configure --target-os=mingw32 --enable-shared --disable-static --extra-cflags=-mno-cygwin --extra-libs=-mno-cygwin
@end example
@section ARM64EC
FFmpeg does not intend to support the Windows ARM64EC build configuration;
patches for changing the individual libraries for the purposes of ARM64EC will
not be accepted.
It may still be possible to build FFmpeg in this build configuration;
such a build may seem to work to some extent. Such a build may have some
amounts of ABI inconsistencies though - which we are not willing to fix.
(Changing aarch64 assembly code to strictly support ARM64EC would require
ifdeffing/changing essentially all such assembly code, and would be a
huge maintenance burden. Additionally, changing the library ABI
surfaces to fix ABI inconsistencies could require extensive and intrusive
changes.)
@bye
+50 -256
View File
@@ -169,7 +169,6 @@ Read angle 2 of playlist 4 from BluRay mounted to /mnt/bluray, start from chapte
-playlist 4 -angle 2 -chapter 2 bluray:/mnt/bluray
@end example
@anchor{cache}
@section cache
Caching wrapper for input stream.
@@ -344,8 +343,7 @@ time, which is valuable for files on slow medium.
If set to 1, the protocol will retry reading at the end of the file, allowing
reading files that still are being written. In order for this to terminate,
you either need to use the rw_timeout option, or use the interrupt callback
(for API users). Setting this option also ignores the file size reported by
the file system.
(for API users).
@item seekable
Controls if seekability is advertised on the file. 0 means non-seekable, -1
@@ -354,17 +352,6 @@ means auto (seekable for normal files, non-seekable for named pipes).
Many demuxers handle seekable and non-seekable resources differently,
overriding this might speed up opening certain files at the cost of losing some
features (e.g. accurate seeking).
@item pkt_size
Set the maximum packet size used for file I/O. A smaller value may reduce
memory usage. A higher value may increase throughput especially with networked
filesystems.
For reading, if explicitly set, it overrides the default internal buffer size
(32 KB) and limits the maximum amount of data read per operation.
For writing, this sets the size of each write operation. The default is 256 KB
for regular files, 32 KB otherwise.
@end table
@section ftp
@@ -419,6 +406,26 @@ Gophers protocol.
The Gopher protocol with TLS encapsulation.
@section hls
Read Apple HTTP Live Streaming compliant segmented stream as
a uniform one. The M3U8 playlists describing the segments can be
remote HTTP resources or local files, accessed using the standard
file protocol.
The nested protocol is declared by specifying
"+@var{proto}" after the hls URI scheme name, where @var{proto}
is either "file" or "http".
@example
hls+http://host/path/to/remote/resource.m3u8
hls+file://path/to/local/resource.m3u8
@end example
Using this protocol is discouraged - the hls demuxer should work
just as well (if not, please report the issues) and is more complete.
To use the hls demuxer instead, simply use the direct URLs to the
m3u8 files.
@section http
HTTP (Hyper Text Transfer Protocol).
@@ -453,30 +460,7 @@ string describing the libavformat build. ("Lavf/<version>")
Set the Referer header. Include 'Referer: URL' header in HTTP request.
@item multiple_requests
Force persistent connections if set to 1, or disable if 0. Default is -1,
which means auto (implies keep-alive when using -request_size or
-initial_request_size).
@item request_size
Limit the size of requests made. This is useful for some pathological servers
that throttle unbounded range requests, as well as when expecting to seek
frequently. Disabled (set to 0) by default.
Note that if enabling this option, it's strongly recommended to also set
@option{short_seek_size} to the same value or higher. Doing so allows FFmpeg
to reuse a single HTTP connection wherever possible.
@item initial_request_size
Limit the size of initial requests. Similar to @code{request_size}, but only
used during initial format parsing. Useful for formats like MXF or MOV that
require frequent seeks during header parsing. Lasts until the demuxer makes a
read request larger than this size (without a seek in between), after which
the implementation will continue using requests as usual. Disabled (set to 0)
by default.
Note that if enabling this option, it's strongly recommended to also enable
the @option{multiple_requests} option, as well as setting
@option{short_seek_size} to the same value or higher.
Use persistent connections if set to 1, default is 0.
@item post_data
Set custom HTTP post data.
@@ -1002,11 +986,6 @@ Set TCP_NODELAY to disable Nagle's algorithm. Default value is 0.
@emph{Remark: Writing to the socket is currently not optimized to minimize system calls and reduces the efficiency / effect of TCP_NODELAY.}
@item tcp_keepalive=@var{1|0}
Enable the TCP keepalive mechanism to detect dead peers and help maintain long-lived idle connections. Default value is 0.
Only the basic keepalive option (SO_KEEPALIVE) can be enabled or disabled. Platform-specific tuning parameters such as TCP_KEEPIDLE, TCP_KEEPINTVL, or TCP_KEEPCNT are not configurable and will use the operating system's default values.
@end table
For example to read with @command{ffplay} a multimedia resource named
@@ -1178,13 +1157,9 @@ rtp://@var{hostname}[:@var{port}][?@var{options}]
@var{port} specifies the RTP port to use.
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
@var{key}=@var{val}.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
The list of supported options follows.
The following URL options are supported:
@table @option
@@ -1194,12 +1169,10 @@ Set the TTL (Time-To-Live) value (for multicast only).
@item rtcpport=@var{n}
Set the remote RTCP port to @var{n}.
@item localport, local_rtpport, localrtpport=@var{n}
@item localrtpport=@var{n}
Set the local RTP port to @var{n}.
Using the localport option name is deprecated and should not be used.
@item local_rtcpport, localrtcpport=@var{n}'
@item localrtcpport=@var{n}'
Set the local RTCP port to @var{n}.
@item pkt_size=@var{n}
@@ -1222,6 +1195,12 @@ List disallowed (blocked) source IP addresses.
Send packets to the source address of the latest received packet (if
set to 1) or to a default remote address (if set to 0).
@item localport=@var{n}
Set the local RTP port to @var{n}.
This is a deprecated option. Instead, @option{localrtpport} should be
used.
@item localaddr=@var{addr}
Local IP address of a network interface used for sending packets or joining
multicast groups.
@@ -1555,15 +1534,7 @@ The accepted URL syntax is:
sctp://@var{host}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
The list of supported options follows.
The protocol accepts the following options:
@table @option
@item listen
If set to any value, listen for an incoming connection. Outgoing connection is done by default.
@@ -1572,67 +1543,6 @@ If set to any value, listen for an incoming connection. Outgoing connection is d
Set the maximum number of streams. By default no limit is set.
@end table
@section shared
Thread-safe, persistent, cross-process cache wrapper for input streams. Caches
the input stream to a file in the specified directory. This is similar to
@ref{cache}, but with a persistent cache on disk that may be shared between
multiple processes or demuxers, even concurrently.
The filename of the cache is obtained by hashing the input URL, so there is
some risk of collision if the same URL is used for different content (e.g.
as a result of extra POST data being used to select the stream ID). To avoid
this, make sure to only use this protocol for URLs that uniquely identify
the content; otherwise you may get a garbled mix of sources.
The accepted options are:
@table @option
@item cache_dir
Path to the directory where cache files are stored. This option is required.
@item block_shift
Shift factor (log2) of the block size used for internal reads/writes. Defaults
to 15, i.e. 32KB blocks. If this does not match the value that was specified
when an existing cache file was created, the previously specified value will
be used instead.
@item read_only
If true, use the shared cache for reads but don't write any new blocks to it.
Default is false. Note that even with this option enabled, the cache file will
be initialized if it does not already exist.
@item cache_verify
If true, verify any data read from the cache against the underlying input
stream, and report any mismatches. Note that this will make the cache layer
effectively useless. This is purely a debug option.
@item cache_timeout
If set to a nonzero value, specifies the maximum time (in microseconds) to wait
for data to become available, if another process is currently trying to fetch
and cache the same block at the same time. If this timeout elapses, it's
assumed that the other process may have gotten stuck or died in the meantime.
If set to zero, no waiting is done and all processes will immediately race
to try and fetch the same missing blocks themselves. Defaults to 10000 (10 ms).
@item retry_errors
If true (the default), transient read errors from the underlying input stream
are ignored and retried again. If false, any blocks that previously failed
being read from will be treated as permanently inaccessible.
@item retry_corrupt
If true (the default), blocks whose contents fail the CRC integrity check are
re-fetched from the underlying input stream, overwriting the corrupt cached
data. If false, cache corruption is treated as a fatal read error.
@end table
URL Syntax is
@example
shared:@var{URL}
@end example
@section srt
Haivision Secure Reliable Transport Protocol via libsrt.
@@ -1643,13 +1553,18 @@ srt://@var{hostname}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
@var{key}=@var{val}.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
or
The list of supported options follows.
@example
@var{options} srt://@var{hostname}:@var{port}
@end example
@var{options} contains a list of '-@var{key} @var{val}'
options.
This protocol accepts the following options.
@table @option
@item connect_timeout=@var{milliseconds}
@@ -1921,10 +1836,6 @@ When true, use Timestamp-based Packet Delivery mode. The default behavior
depends on the transmission type: enabled in live mode, disabled in file
mode.
@item ipv6only=@var{1|0}
Accept IPv4 or not while using the IPv6 wildcard address. This should be set
when listening on a IPv6 wildcard address.
@end table
For more information see: @url{https://github.com/Haivision/srt}.
@@ -2006,11 +1917,7 @@ tcp://@var{hostname}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
@var{key}=@var{val}.
The list of supported options follows.
@@ -2065,14 +1972,8 @@ The required syntax for a TLS/SSL url is:
tls://@var{hostname}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
The list of supported options follows.
The following parameters can be set via command line options
(or in code via @code{AVOption}s):
@table @option
@@ -2083,7 +1984,7 @@ need to be specified for verification to work, but not all libraries and
setups have defaults built in.
The file must be in OpenSSL PEM format.
@item tls_verify, verify=@var{1|0}
@item tls_verify=@var{1|0}
If enabled, try to verify the peer that we are communicating with.
Note, if using OpenSSL, this currently only makes sure that the
peer certificate is signed by one of the root certificates in the CA
@@ -2091,8 +1992,8 @@ database, but it does not validate that the certificate actually
matches the host name we are trying to connect to. (With other backends,
the host name is validated as well.)
This is enabled by default. Verifying the peer requires a CA database,
which in some cases has to be provided by the caller.
This is disabled by default since it requires a CA database to be
provided by the caller in many cases.
@item cert_file, cert=@var{filename}
A file containing a certificate to use in the handshake with the peer.
@@ -2127,94 +2028,6 @@ To play back a stream from the TLS/SSL server using @command{ffplay}:
ffplay tls://@var{hostname}:@var{port}
@end example
@section dtls
Datagram Transport Layer Security (DTLS)
The required syntax for a DTLS URL is:
@example
dtls://@var{hostname}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
DTLS shares most options with TLS, but operates over UDP instead of TCP.
The list of supported options follows.
@table @option
@item ca_file, cafile=@var{filename}
A file containing certificate authority (CA) root certificates to treat
as trusted. If the linked TLS library contains a default this might not
need to be specified for verification to work, but not all libraries and
setups have defaults built in.
The file must be in OpenSSL PEM format.
@item tls_verify, verify=@var{1|0}
If enabled, try to verify the peer that we are communicating with.
Note, if using OpenSSL, this currently only makes sure that the
peer certificate is signed by one of the root certificates in the CA
database, but it does not validate that the certificate actually
matches the host name we are trying to connect to.
This is enabled by default. Verifying the peer requires a CA database,
which in some cases has to be provided by the caller.
@item cert_file, cert=@var{filename}
A file containing a certificate to use in the handshake with the peer.
(When operating as server, in listen mode, this is more often required
by the peer, while client certificates only are mandated in certain
setups.)
@item key_file, key=@var{filename}
A file containing the private key for the certificate.
@item cert_pem=@var{string}
Certificate PEM string
@item key_pem=@var{string}
Private key PEM string
@item listen=@var{1|0}
If enabled, listen for connections on the provided port, and assume
the server role in the handshake instead of the client role.
@item mtu=@var{size}
Set the Maximum Transmission Unit (MTU) for DTLS packets.
@item use_srtp=@var{1|0}
Enable the use_srtp DTLS extension.
This is used in WebRTC applications to establish SRTP encryption keys
through the DTLS handshake. Default is disabled.
@item external_sock=@var{1|0}
Use an external socket instead of creating a new one.
This option only makes sense to pass when interacting with the code via
API, enabling this from CLI will cause immediate failure.
Default is disabled.
@end table
Example command lines:
To create a DTLS server:
@example
ffmpeg -listen 1 -i dtls://@var{hostname}:@var{port} @var{output}
@end example
To create a DTLS client and send data to server:
@example
ffmpeg -i @var{input} -f @var{format} dtls://@var{hostname}:@var{port}
@end example
@section udp
User Datagram Protocol.
@@ -2224,12 +2037,7 @@ The required syntax for an UDP URL is:
udp://@var{hostname}:@var{port}[?@var{options}]
@end example
@var{options} contains a list of &-separated options of the form
@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for
space) can be used to escape keys and values.
Options can also can be specified via command line options (or in code via
@code{AVOption}s).
@var{options} contains a list of &-separated options of the form @var{key}=@var{val}.
In case threading is enabled on the system, a circular buffer is used
to store the incoming data, which allows one to reduce loss of data due to
@@ -2268,9 +2076,6 @@ Explicitly allow or disallow reusing UDP sockets.
@item ttl=@var{ttl}
Set the time to live value (for multicast only).
@item dscp=@var{dscp}
Set the 6-bit DSCP field for outgoing packets.
@item connect=@var{1|0}
Initialize the UDP socket with @code{connect()}. In this case, the
destination address can't be changed with ff_udp_set_remote_url later.
@@ -2352,17 +2157,6 @@ The following parameters can be set via command line options
Timeout in ms.
@item listen
Create the Unix socket in listening mode.
@item type
Select socket type.
@table @samp
@item stream Corresponds to SOCK_STREAM (reliable stream-oriented)
@item datagram Corresponds to SOCK_DGRAM (unreliable packet-oriented)
@item seqpacket Corresponds to SOCK_SEQPACKET (reliable packet-oriented)
@end table
@item pkt_size
Maximum packet size for packet-oriented sockets (SOCK_DGRAM and
SOCK_SEQPACKET). If greater than zero, this value is used as
@code{max_packet_size}. Ignored for SOCK_STREAM. Default is @code{0}.
@end table
@section zmq
+13 -98
View File
@@ -11,88 +11,48 @@ For programmatic use, they can be set explicitly in the
@table @option
@anchor{scaler}
@item scaler, scaler_sub
Choose the scaling algorithm to use. Default value is @samp{auto} for both.
It accepts the following values:
@table @samp
@item auto
Aumotic choice. For @samp{scaler_sub}, this means the same algorithm as
@samp{scaler}. For @samp{scaler}, this defaults to the scaler flag selected
by @samp{sws_flags}.
@item bilinear
Bilinear filter. (AKA triangle filter)
@item bicubic
2-tap cubic BC-spline (AKA Mitchell-Netravali spline). The B and C parameters
can be configured by setting @code{param0} and @code{param1}, defaulting to
0.0 and 0.6 respectively.
@item point, neighbor
Point sampling (AKA nearest neighbor).
@item area
Area averaging. Equivalent to @samp{bilinear} for upscaling.
@item gaussian
2-tap Gaussian filter approximation. The sharpness parameter can be configured
by setting @code{param0}, defaulting to 3.0.
@item sinc
Unwindowed sinc filter.
@item lanczos
Lanczos resampling (sinc windowed sinc). The number of filter taps can
be configured by setting @code{param0}, defaulting to 3.
@item spline
Unwindowed natural bicubic spline.
@end table
@anchor{sws_flags}
@item sws_flags
Set the scaler flags. This is also used to set the scaling
algorithm, though this usage is deprecated in favor of setting @samp{scaler}.
Only a single algorithm may be selected. Default value is @samp{bicubic}.
algorithm. Only a single algorithm should be selected. Default
value is @samp{bicubic}.
It accepts the following values:
@table @samp
@item fast_bilinear
Select fast bilinear scaling algorithm. (Deprecated)
Select fast bilinear scaling algorithm.
@item bilinear
Select bilinear scaling algorithm. (Deprecated)
Select bilinear scaling algorithm.
@item bicubic
Select bicubic scaling algorithm. (Deprecated)
Select bicubic scaling algorithm.
@item experimental
Select experimental scaling algorithm. (Deprecated)
Select experimental scaling algorithm.
@item neighbor
Select nearest neighbor rescaling algorithm. (Deprecated)
Select nearest neighbor rescaling algorithm.
@item area
Select averaging area rescaling algorithm. (Deprecated)
Select averaging area rescaling algorithm.
@item bicublin
Select bicubic scaling algorithm for the luma component, bilinear for
chroma components. (Deprecated)
chroma components.
@item gauss
Select Gaussian rescaling algorithm. (Deprecated)
Select Gaussian rescaling algorithm.
@item sinc
Select sinc rescaling algorithm. (Deprecated)
Select sinc rescaling algorithm.
@item lanczos
Select Lanczos rescaling algorithm. The default width (alpha) is 3 and can be
changed by setting @code{param0}. (Deprecated)
changed by setting @code{param0}.
@item spline
Select natural bicubic spline rescaling algorithm. (Deprecated)
Select natural bicubic spline rescaling algorithm.
@item print_info
Enable printing/debug logging.
@@ -108,10 +68,6 @@ Select full chroma input.
@item bitexact
Enable bitexact output.
@item unstable
Allow the use of experimental new code. May subtly affect the output or even
produce wrong results. For testing only.
@end table
@item srcw @var{(API only)}
@@ -191,47 +147,6 @@ No blending
@end table
@item sws_backends
Set the allowed swscale backends. This is a flags option, so multiple backends
may be combined.
@table @samp
@item auto
Automatic selection. Equal to either @samp{stable} or @samp{all} depending on
whether or not the @samp{unstable} flag is set. This is the default value.
@item stable
All stable backends.
@item unstable
All unstable backends.
@item all
All available backends.
@item legacy
Legacy swscale code.
@item c
Template-based reference code.
@item memcpy
Fast path using libc @code{memcpy}.
@item x86
x86 SIMD kernels.
@item aarch64
AArch64 NEON kernels.
@item spirv
Vulkan SPIR-V backend.
@item glsl
Vulkan GLSL backend.
@end table
@end table
@c man end SCALER OPTIONS
+3 -4
View File
@@ -13,9 +13,8 @@ threaded error diffusion pass following a multi-threaded scaling pass.
SwsGraph is internally recreated whenever the image format, dimensions or
settings change in any way. sws_scale_frame() is itself just a light-weight
wrapper that runs ff_sws_graph_reinit() initially and on format changes,
splits interlaced images into separate fields, and calls ff_sws_graph_run()
on each.
wrapper that runs ff_sws_graph_create() whenever the format changes, splits
interlaced images into separate fields, and calls ff_sws_graph_run() on each.
From the point of view of SwsGraph itself, all inputs are progressive.
@@ -63,7 +62,7 @@ This overall approach has a considerable number of benefits:
multiple levels of complicated, interwoven format handling code that is
legacy swscale.
2. Because most of the brains lives inside the powerful optimizer, we get
2. Because most of the brains lives inside the the powerful optimizer, we get
fast paths "for free" for any suitable format conversion, rather than having
to enumerate them one by one. SIMD code itself can be written in a very
general way and does need to be tied to specific pixel formats - subsequent
+73 -53
View File
@@ -55,8 +55,7 @@ sub get_formatting_function($$) {
# determine texinfo version
my $package_version = ff_get_conf('PACKAGE_VERSION');
$package_version =~ s/\+nc$//;
$package_version =~ s/\+?dev$//;
$package_version =~ s/\+dev$//;
my $program_version_num = version->declare($package_version)->numify;
my $program_version_6_8 = $program_version_num >= 6.008000;
@@ -120,8 +119,29 @@ sub ffmpeg_heading_command($$$$$)
}
my $heading_level;
# Never use node for heading
if ($cmdname ne 'node') {
# node is used as heading if there is nothing else.
if ($cmdname eq 'node') {
if (!$output_unit or
(((!$output_unit->{'extra'}->{'section'}
and $output_unit->{'extra'}->{'node'}
and $output_unit->{'extra'}->{'node'} eq $command)
or
((($output_unit->{'extra'}->{'unit_command'}
and $output_unit->{'extra'}->{'unit_command'} eq $command)
or
($output_unit->{'unit_command'}
and $output_unit->{'unit_command'} eq $command))
and $command->{'extra'}
and not $command->{'extra'}->{'associated_section'}))
# bogus node may not have been normalized
and defined($command->{'extra'}->{'normalized'}))) {
if ($command->{'extra'}->{'normalized'} eq 'Top') {
$heading_level = 0;
} else {
$heading_level = 3;
}
}
} else {
if (defined($command->{'extra'})
and defined($command->{'extra'}->{'section_level'})) {
$heading_level = $command->{'extra'}->{'section_level'};
@@ -133,58 +153,58 @@ sub ffmpeg_heading_command($$$$$)
}
}
if (defined($heading_level)) {
my $heading = $self->command_text($command);
# empty heading corresponds to an empty @top
if ($heading ne '') {
if ($root_commands{$cmdname}
and $sectioning_commands{$cmdname}) {
my $content_href = $self->command_contents_href($command, 'contents',
$self->{'current_filename'});
if ($content_href) {
my $this_href = $content_href =~ s/^\#toc-/\#/r;
$heading .= '<span class="pull-right">'.
'<a class="anchor hidden-xs" '.
"href=\"$this_href\" aria-hidden=\"true\">".
($ENV{"FA_ICONS"} ? '<i class="fa fa-link"></i>'
: '#').
'</a> '.
'<a class="anchor hidden-xs"'.
"href=\"$content_href\" aria-hidden=\"true\">".
($ENV{"FA_ICONS"} ? '<i class="fa fa-navicon"></i>'
: 'TOC').
'</a>'.
'</span>';
}
}
my $heading = $self->command_text($command);
# $heading not defined may happen if the command is a @node, for example
# if there is an error in the node.
if (defined($heading) and $heading ne '' and defined($heading_level)) {
my $in_preformatted;
if ($program_version_num >= 7.001090) {
$in_preformatted = $self->in_preformatted_context();
} else {
$in_preformatted = $self->in_preformatted();
if ($root_commands{$cmdname}
and $sectioning_commands{$cmdname}) {
my $content_href = $self->command_contents_href($command, 'contents',
$self->{'current_filename'});
if ($content_href) {
my $this_href = $content_href =~ s/^\#toc-/\#/r;
$heading .= '<span class="pull-right">'.
'<a class="anchor hidden-xs" '.
"href=\"$this_href\" aria-hidden=\"true\">".
($ENV{"FA_ICONS"} ? '<i class="fa fa-link"></i>'
: '#').
'</a> '.
'<a class="anchor hidden-xs"'.
"href=\"$content_href\" aria-hidden=\"true\">".
($ENV{"FA_ICONS"} ? '<i class="fa fa-navicon"></i>'
: 'TOC').
'</a>'.
'</span>';
}
if ($in_preformatted) {
$result .= $heading."\n";
} else {
# if the level was changed, set the command name right
if ($cmdname ne 'node'
and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
$cmdname
= $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
}
if ($program_version_num >= 7.000000) {
$result .= &{get_formatting_function($self,'format_heading_text')}($self,
$cmdname, [$cmdname], $heading,
$heading_level +$self->get_conf('CHAPTER_HEADER_LEVEL') -1,
$heading_id, $command);
}
} else {
$result .= &{get_formatting_function($self,'format_heading_text')}(
$self, $cmdname, $heading,
$heading_level +
$self->get_conf('CHAPTER_HEADER_LEVEL') - 1, $command);
}
my $in_preformatted;
if ($program_version_num >= 7.001090) {
$in_preformatted = $self->in_preformatted_context();
} else {
$in_preformatted = $self->in_preformatted();
}
if ($in_preformatted) {
$result .= $heading."\n";
} else {
# if the level was changed, set the command name right
if ($cmdname ne 'node'
and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
$cmdname
= $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
}
if ($program_version_num >= 7.000000) {
$result .= &{get_formatting_function($self,'format_heading_text')}($self,
$cmdname, [$cmdname], $heading,
$heading_level +$self->get_conf('CHAPTER_HEADER_LEVEL') -1,
$heading_id, $command);
} else {
$result .= &{get_formatting_function($self,'format_heading_text')}(
$self, $cmdname, $heading,
$heading_level +
$self->get_conf('CHAPTER_HEADER_LEVEL') - 1, $command);
}
}
}
+9 -17
View File
@@ -1,17 +1,14 @@
# Transforms
The basis transforms used for FFT and various other derived functions are based on the following unrollings.
The basis transforms used for FFT and various other derived functions are based
on the following unrollings.
The functions can be easily adapted to double precision floats as well.
## Parity permutation
# Parity permutation
The basis transforms described here all use the following permutation:
``` C
void ff_tx_gen_split_radix_parity_revtab(int *revtab, int len, int inv,
int basis, int dual_stride);
```
Parity means even and odd complex numbers will be split, e.g. the even
coefficients will come first, after which the odd coefficients will be
placed. For example, a 4-point transform's coefficients after reordering:
@@ -36,8 +33,7 @@ register or 0. This allows to reuse SSE functions as dual-transform
functions in AVX mode.
If length is smaller than basis/2 this function will not do anything.
## 4-point FFT transform
# 4-point FFT transform
The only permutation this transform needs is to swap the `z[1]` and `z[2]`
elements when performing an inverse transform, which in the assembly code is
hardcoded with the function itself being templated and duplicated for each
@@ -84,8 +80,7 @@ static void fft4(FFTComplex *z)
}
```
## 8-point AVX FFT transform
# 8-point AVX FFT transform
Input must be pre-permuted using the parity lookup table, generated via
`ff_tx_gen_split_radix_parity_revtab`.
@@ -198,8 +193,7 @@ This theme continues throughout the document. Note that in the actual assembly c
the paths are interleaved to improve unit saturation and CPU dependency tracking, so
to more clearly see them, you'll need to deinterleave the instructions.
## 8-point SSE/ARM64 FFT transform
# 8-point SSE/ARM64 FFT transform
Input must be pre-permuted using the parity lookup table, generated via
`ff_tx_gen_split_radix_parity_revtab`.
@@ -311,8 +305,7 @@ static void fft8(FFTComplex *z)
Most functions here are highly tuned to use x86's addsub instruction to save on
external sign mask loading.
## 16-point AVX FFT transform
# 16-point AVX FFT transform
This version expects the output of the 8 and 4-point transforms to follow the
even/odd convention established above.
@@ -452,8 +445,7 @@ static void fft16(FFTComplex *z)
}
```
## AVX split-radix synthesis
# AVX split-radix synthesis
To create larger transforms, the following unrolling of the C split-radix
function is used.
@@ -713,8 +705,8 @@ 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
# 15-point AVX FFT transform
The 15-point transform is based on the following unrolling. The input
must be permuted via the following loop:
+1 -2
View File
@@ -5,8 +5,6 @@ OBJS-$(HAVE_VFP) += $(VFP-OBJS) $(VFP-OBJS-yes)
OBJS-$(HAVE_NEON) += $(NEON-OBJS) $(NEON-OBJS-yes)
OBJS-$(HAVE_SVE) += $(SVE-OBJS) $(SVE-OBJS-yes)
OBJS-$(HAVE_SVE2) += $(SVE2-OBJS) $(SVE2-OBJS-yes)
OBJS-$(HAVE_SME) += $(SME-OBJS) $(SME-OBJS-yes)
OBJS-$(HAVE_SME2) += $(SME2-OBJS) $(SME2-OBJS-yes)
OBJS-$(HAVE_MIPSFPU) += $(MIPSFPU-OBJS) $(MIPSFPU-OBJS-yes)
OBJS-$(HAVE_MIPSDSP) += $(MIPSDSP-OBJS) $(MIPSDSP-OBJS-yes)
@@ -25,4 +23,5 @@ OBJS-$(HAVE_RV_ZVBB) += $(RVVB-OBJS) $(RVVB-OBJS-yes)
OBJS-$(HAVE_SIMD128) += $(SIMD128-OBJS) $(SIMD128-OBJS-yes)
OBJS-$(HAVE_MMX) += $(MMX-OBJS) $(MMX-OBJS-yes)
OBJS-$(HAVE_X86ASM) += $(X86ASM-OBJS) $(X86ASM-OBJS-yes)
+51 -55
View File
@@ -2,32 +2,31 @@
# common bits used by all libraries
#
DEFAULT_X86ASMD=.dbg
ifeq ($(DBG),1)
X86ASMD=$(DEFAULT_X86ASMD)
else
X86ASMD=
endif
ifndef SUBDIR
LINK = $(LD) $(1)
ifeq ($(LD),$(CC))
ifneq ($(CXX),)
LDXX := $(CXX)
LINK = $(if $(filter -lstdc++,$(1)),$(LDXX) $(filter-out -lstdc++,$(1)),$(LD) $(1))
endif
endif
BIN2CEXE = ffbuild/bin2c$(HOSTEXESUF)
BIN2C = $(BIN2CEXE)
ifndef V
Q = @
ECHO = printf "$(1)\t%s\n" $(2)
BRIEF = CC CXX OBJCC HOSTCC HOSTLD AS X86ASM AR LD LDXX STRIP CP WINDRES GLSLC NVCC BIN2C METALCC METALLIB
SILENT = DEPCC DEPCXX DEPHOSTCC DEPAS DEPX86ASM RANLIB RM
BRIEF = CC CXX OBJCC HOSTCC HOSTLD AS X86ASM AR LD STRIP CP WINDRES NVCC BIN2C METALCC METALLIB
SILENT = DEPCC DEPHOSTCC DEPAS DEPX86ASM RANLIB RM
MSG = $@
M = @$(call ECHO,$(TAG),$@);
$(foreach VAR,$(BRIEF), \
$(eval override $(VAR) = @$$(call ECHO,$(VAR),$$(MSG)); $($(VAR))))
$(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_PATH)/%=%)); $(INSTALL))
$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
endif
# Prepend to a recursively expanded variable without making it simply expanded.
@@ -43,7 +42,7 @@ OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS)
ASFLAGS := $(CPPFLAGS) $(ASFLAGS)
# Use PREPEND here so that later (target-dependent) additions to CPPFLAGS
# end up in CXXFLAGS.
$(call PREPEND,CXXFLAGS, CPPFLAGS)
$(call PREPEND,CXXFLAGS, CPPFLAGS CFLAGS)
X86ASMFLAGS += $(IFLAGS:%=%/) -I$(<D)/ -Pconfig.asm
HOSTCCFLAGS = $(IFLAGS) $(HOSTCPPFLAGS) $(HOSTCFLAGS)
@@ -60,7 +59,6 @@ COMPILE_S = $(call COMPILE,AS)
COMPILE_M = $(call COMPILE,OBJCC)
COMPILE_X86ASM = $(call COMPILE,X86ASM)
COMPILE_HOSTC = $(call COMPILE,HOSTCC)
COMPILE_GLSLC = $(call COMPILE,GLSLC)
COMPILE_NVCC = $(call COMPILE,NVCC)
COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS)
COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS)
@@ -97,6 +95,10 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS)
%_host.o: %.c
$(COMPILE_HOSTC)
%$(DEFAULT_X86ASMD).asm: %.asm
$(DEPX86ASM) $(X86ASMFLAGS) -M -o $@ $< > $(@:.asm=.d)
$(X86ASM) $(X86ASMFLAGS) -e $< | sed '/^%/d;/^$$/d;' > $@
%.o: %.asm
$(COMPILE_X86ASM)
-$(if $(ASMSTRIPFLAGS), $(STRIP) $(ASMSTRIPFLAGS) $@)
@@ -113,26 +115,6 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS)
$(BIN2CEXE): ffbuild/bin2c_host.o
$(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS)
RUN_BIN2C = $(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
RUN_GZIP = $(M)mkdir -p $(dir $@) && gzip -nc9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
RUN_MINIFY = $(M)mkdir -p $(dir $@) && sed 's!/\\*.*\\*/!!g' $< | tr '\n' ' ' | tr -s ' ' | sed 's/^ //; s/ $$//' > $@
%.gz: TAG = GZIP
%.min: TAG = MINIFY
%.spv: %.glsl
$(COMPILE_GLSLC)
ifdef CONFIG_SHADER_COMPRESSION
%.spv.gz: %.spv
$(RUN_GZIP)
%.spv.c: %.spv.gz $(BIN2CEXE)
$(RUN_BIN2C)
else
%.spv.c: %.spv $(BIN2CEXE)
$(RUN_BIN2C)
endif
%.metal.air: %.metal
$(METALCC) $< -o $@
@@ -140,52 +122,67 @@ endif
$(METALLIB) --split-module-without-linking $< -o $@
%.metallib.c: %.metallib $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
%.ptx: %.cu $(SRC_PATH)/compat/cuda/cuda_runtime.h
$(COMPILE_NVCC)
ifdef CONFIG_SHADER_COMPRESSION
ifdef CONFIG_PTX_COMPRESSION
%.ptx.gz: TAG = GZIP
%.ptx.gz: %.ptx
$(RUN_GZIP)
$(M)gzip -nc9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
%.ptx.c: %.ptx.gz $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
else
%.ptx.c: %.ptx $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
endif
# 1) Preprocess CSS to a minified version
%.css.min: TAG = SED
%.css.min: %.css
$(RUN_MINIFY)
$(M)sed 's!/\\*.*\\*/!!g' $< \
| tr '\n' ' ' \
| tr -s ' ' \
| sed 's/^ //; s/ $$//' \
> $@
ifdef CONFIG_RESOURCE_COMPRESSION
# 2) Gzip the minified CSS
%.css.min.gz: TAG = GZIP
%.css.min.gz: %.css.min
$(RUN_GZIP)
$(M)gzip -nc9 $< > $@
# 3) Convert the gzipped CSS to a .c array
%.css.c: %.css.min.gz $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
# 4) Gzip the HTML file (no minification needed)
%.html.gz: TAG = GZIP
%.html.gz: %.html
$(RUN_GZIP)
$(M)gzip -nc9 $< > $@
# 5) Convert the gzipped HTML to a .c array
%.html.c: %.html.gz $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
else # NO COMPRESSION
# 2) Convert the minified CSS to a .c array
%.css.c: %.css.min $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
# 3) Convert the plain HTML to a .c array
%.html.c: %.html $(BIN2CEXE)
$(RUN_BIN2C)
$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
endif
clean::
$(RM) $(BIN2CEXE) $(CLEANSUFFIXES:%=ffbuild/%)
%.c %.h %.S %.pc %.ver %.version: TAG = GEN
%.c %.h %.pc %.ver %.version: TAG = GEN
# Dummy rule to stop make trying to rebuild removed or renamed headers
%.h %_template.c:
@@ -205,7 +202,6 @@ OBJS += $(OBJS-yes)
SHLIBOBJS += $(SHLIBOBJS-yes)
STLIBOBJS += $(STLIBOBJS-yes)
FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS)
DEVPROGS += $(DEVPROGS-yes)
TESTPROGS += $(TESTPROGS-yes)
LDLIBS = $(FFLIBS:%=%$(BUILDSUF))
@@ -214,8 +210,7 @@ FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%=
OBJS := $(sort $(OBJS:%=$(SUBDIR)%))
SHLIBOBJS := $(sort $(SHLIBOBJS:%=$(SUBDIR)%))
STLIBOBJS := $(sort $(STLIBOBJS:%=$(SUBDIR)%))
TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) $(DEVPROGS:%=$(SUBDIR)%.o)
DEVPROGS := $(DEVPROGS:%=$(SUBDIR)%$(EXESUF))
TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o)
TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF))
HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o)
HOSTPROGS := $(HOSTPROGS:%=$(SUBDIR)%$(HOSTEXESUF))
@@ -233,11 +228,12 @@ ALLHEADERS := $(subst $(SRC_DIR)/,$(SUBDIR),$(wildcard $(SRC_DIR)/*.h $(SRC_DIR)
SKIPHEADERS += $(ARCH_HEADERS:%=$(ARCH)/%) $(SKIPHEADERS-)
SKIPHEADERS := $(SKIPHEADERS:%=$(SUBDIR)%)
HOBJS = $(filter-out $(SKIPHEADERS:.h=.h.o),$(ALLHEADERS:.h=.h.o))
SPVOBJS = $(filter %.spv.o,$(OBJS))
PTXOBJS = $(filter %.ptx.o,$(OBJS))
RESOURCEOBJS = $(filter %.css.o %.html.o,$(OBJS))
$(HOBJS): CCFLAGS += $(CFLAGS_HEADERS)
checkheaders: $(HOBJS)
.SECONDARY: $(HOBJS:.o=.c) $(SPVOBJS:.o=.c) $(SPVOBJS:.o=.gz) $(SPVOBJS:.o=) $(PTXOBJS:.o=.c) $(PTXOBJS:.o=.gz) $(PTXOBJS:.o=)
.SECONDARY: $(HOBJS:.o=.c) $(PTXOBJS:.o=.c) $(PTXOBJS:.o=.gz) $(PTXOBJS:.o=) $(RESOURCEOBJS:.o=.c) $(RESOURCEOBJS:%.css.o=%.css.min) $(RESOURCEOBJS:%.css.o=%.css.min.gz) $(RESOURCEOBJS:%.html.o=%.html.gz) $(RESOURCEOBJS:.o=)
alltools: $(TOOLS)
$(HOSTOBJS): %.o: %.c
@@ -256,14 +252,14 @@ $(TOOLOBJS): | tools
OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SHLIBOBJS) $(STLIBOBJS) $(TESTOBJS))
CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.objs *.pc *.ptx *.ptx.gz *.ptx.c *.spv *.spv.gz *.spv.c *.gen.asm *.gen.c *.gen.S *.ver *.version *.html.gz *.html.c *.css.min.gz *.css.min *.css.c *~ *.ilk *.pdb
CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.objs *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *.html.gz *.html.c *.css.gz *.css.c *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb
LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a
define RULES
clean::
$(RM) $(DEVPROGS) $(HOSTPROGS) $(TESTPROGS) $(TOOLS)
$(RM) $(HOSTPROGS) $(TESTPROGS) $(TOOLS)
endef
$(eval $(RULES))
-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SHLIBOBJS:.o=.d) $(STLIBOBJS:.o=.d) $(SPVOBJS:.spv.o=.d))
-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SHLIBOBJS:.o=.d) $(STLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d)
+9 -32
View File
@@ -14,15 +14,6 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%)
all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME) $(SUBDIR)lib$(FULLNAME).pc
all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc
# Make <4.0 does not support the built-in file function;
# versions that do support it should use it, as it's
# faster and isn't bound by command line length limits.
ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION))))
HAVE_BUILTIN_FILE := yes
else
HAVE_BUILTIN_FILE := no
endif
LIBOBJS := $(OBJS) $(SHLIBOBJS) $(STLIBOBJS) $(SUBDIR)%.h.o $(TESTOBJS)
$(LIBOBJS) $(LIBOBJS:.o=.s) $(LIBOBJS:.o=.i): CPPFLAGS += -DHAVE_AV_CONFIG_H
@@ -45,11 +36,7 @@ endif
$(SUBDIR)$(LIBNAME): $(OBJS) $(STLIBOBJS)
$(RM) $@
ifeq ($(RESPONSE_FILES),yes)
ifeq ($(HAVE_BUILTIN_FILE),yes)
$(file >$@.objs,$^)
else
$(Q)echo $^ > $@.objs
endif
$(AR) $(ARFLAGS) $(AR_O) @$@.objs
else
$(AR) $(ARFLAGS) $(AR_O) $^
@@ -64,14 +51,12 @@ install-libs-$(CONFIG_SHARED): install-lib$(NAME)-shared
define RULES
$(TOOLS): THISLIB = $(FULLNAME:%=$(LD_LIB))
$(TESTPROGS) $(DEVPROGS): THISLIB = $(SUBDIR)$(LIBNAME)
$(TESTPROGS): THISLIB = $(SUBDIR)$(LIBNAME)
$(NAME)LINK_EXE_ARGS = $(LDFLAGS) $(LDEXEFLAGS)
$(NAME)LINK_SO_ARGS = $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS)
$(NAME)LINK_EXTRA = $(FFEXTRALIBS)
$(LIBOBJS): CPPFLAGS += -DBUILDING_$(NAME)
$(DEVPROGS) $(TESTPROGS) $(TOOLS): %$(EXESUF): %.o
$$(call LINK,$$(call $(NAME)LINK_EXE_ARGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $$(call $(NAME)LINK_EXTRA) $$(EXTRALIBS-$$(*F)) $$(ELIBS))
$(TESTPROGS) $(TOOLS): %$(EXESUF): %.o
$$(LD) $(LDFLAGS) $(LDEXEFLAGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $(FFEXTRALIBS) $$(EXTRALIBS-$$(*F)) $$(ELIBS)
$(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h $(SUBDIR)version_major.h | $(SUBDIR)
$$(M) $$(SRC_PATH)/ffbuild/libversion.sh $(NAME) $$^ > $$@
@@ -86,20 +71,14 @@ $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR)
$(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME)
$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SHLIBOBJS) $(SUBDIR)lib$(NAME).ver
$(SLIB_CREATE_DEF_CMD)
ifeq ($(RESPONSE_FILES),yes)
ifeq ($(HAVE_BUILTIN_FILE),yes)
$$(file >$$@.objs,$$(filter %.o,$$^))
else
$(Q)echo $$(filter %.o,$$^) > $$@.objs
endif
endif
$(Q)$(SLIB_CREATE_DEF_CMD)
ifeq ($(RESPONSE_FILES),yes)
$$(call LINK,$$(call $(NAME)LINK_SO_ARGS) $$(LD_O) @$$@.objs $$(call $(NAME)LINK_EXTRA))
$$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) @$$@.objs $(FFEXTRALIBS)
else
$$(call LINK,$$(call $(NAME)LINK_SO_ARGS) $$(LD_O) $$(filter %.o,$$^) $$(call $(NAME)LINK_EXTRA))
$$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
endif
$(Q)$(SLIB_EXTRA_CMD)
$(SLIB_EXTRA_CMD)
-$(RM) $$@.objs
ifdef SUBDIR
@@ -113,9 +92,7 @@ clean::
install-lib$(NAME)-shared: $(SUBDIR)$(SLIBNAME)
$(Q)mkdir -p "$(SHLIBDIR)"
$$(INSTALL) -m 755 $$< "$(SHLIBDIR)/$(SLIB_INSTALL_NAME)"
ifneq ($(STRIPTYPE),nostrip)
$$(STRIP) "$(SHLIBDIR)/$(SLIB_INSTALL_NAME)"
endif
$(Q)$(foreach F,$(SLIB_INSTALL_LINKS),(cd "$(SHLIBDIR)" && $(LN_S) $(SLIB_INSTALL_NAME) $(F));)
$(if $(SLIB_INSTALL_EXTRA_SHLIB),$$(INSTALL) -m 644 $(SLIB_INSTALL_EXTRA_SHLIB:%=$(SUBDIR)%) "$(SHLIBDIR)")
$(if $(SLIB_INSTALL_EXTRA_LIB),$(Q)mkdir -p "$(LIBDIR)")
@@ -153,6 +130,6 @@ endef
$(eval $(RULES))
$(TOOLS): $(DEP_LIBS) $(SUBDIR)$($(CONFIG_SHARED:yes=S)LIBNAME)
$(TESTPROGS) $(DEVPROGS): $(DEP_LIBS) $(SUBDIR)$(LIBNAME)
$(TESTPROGS): $(DEP_LIBS) $(SUBDIR)$(LIBNAME)
testprogs: $(TESTPROGS)
-2
View File
@@ -36,7 +36,6 @@ OBJS-ffmpeg += \
fftools/textformat/tw_buffer.o \
fftools/textformat/tw_stdout.o \
$(OBJS-resman) \
$(RESOBJS) \
OBJS-ffprobe += \
fftools/textformat/avtextformat.o \
@@ -51,7 +50,6 @@ OBJS-ffprobe += \
fftools/textformat/tw_buffer.o \
fftools/textformat/tw_stdout.o \
OBJS-ffmpeg += $(COMPAT_OBJS:%=compat/%)
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
+6 -101
View File
@@ -263,7 +263,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
return AVERROR(EINVAL);
}
arg_allocated = read_file_to_string(arg);
arg_allocated = file_read(arg);
if (!arg_allocated) {
av_log(NULL, AV_LOG_FATAL,
"Error reading the value for option '%s' from file: %s\n",
@@ -275,7 +275,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt,
}
if (po->flags & OPT_FLAG_SPEC) {
const char *p = strchr(opt, ':');
char *p = strchr(opt, ':');
char *str;
sol = dst;
@@ -962,7 +962,8 @@ FILE *get_preset_file(char *filename, size_t filename_size,
datadir, desired_size, sizeof *datadir);
if (new_datadir) {
datadir = new_datadir;
strcpy(datadir + datadir_len, "/ffpresets");
datadir[datadir_len] = 0;
strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len);
base[2] = datadir;
}
}
@@ -1267,7 +1268,7 @@ unsigned stream_specifier_match(const StreamSpecifier *ss,
break;
}
}
av_fallthrough;
// fall-through
case STREAM_LIST_GROUP_IDX:
if (ss->stream_list == STREAM_LIST_GROUP_IDX &&
ss->list_id >= 0 && ss->list_id < s->nb_stream_groups)
@@ -1349,77 +1350,6 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
return ret;
}
unsigned stream_group_specifier_match(const StreamSpecifier *ss,
const AVFormatContext *s, const AVStreamGroup *stg,
void *logctx)
{
int start_stream_group = 0, nb_stream_groups;
int nb_matched = 0;
if (ss->idx >= 0)
return 0;
switch (ss->stream_list) {
case STREAM_LIST_STREAM_ID:
case STREAM_LIST_ALL:
case STREAM_LIST_PROGRAM:
return 0;
case STREAM_LIST_GROUP_ID:
// <n-th> stream with given ID makes no sense and should be impossible to request
av_assert0(ss->idx < 0);
// return early if we know for sure the stream does not match
if (stg->id != ss->list_id)
return 0;
start_stream_group = stg->index;
nb_stream_groups = stg->index + 1;
break;
case STREAM_LIST_GROUP_IDX:
start_stream_group = ss->list_id >= 0 ? 0 : stg->index;
nb_stream_groups = stg->index + 1;
break;
default: av_assert0(0);
}
for (int i = start_stream_group; i < nb_stream_groups; i++) {
const AVStreamGroup *candidate = s->stream_groups[i];
if (ss->meta_key) {
const AVDictionaryEntry *tag = av_dict_get(candidate->metadata,
ss->meta_key, NULL, 0);
if (!tag)
continue;
if (ss->meta_val && strcmp(tag->value, ss->meta_val))
continue;
}
if (ss->usable_only) {
switch (candidate->type) {
case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
const AVStreamGroupTileGrid *tg = candidate->params.tile_grid;
if (!tg->coded_width || !tg->coded_height || !tg->nb_tiles ||
!tg->width || !tg->height || !tg->nb_tiles)
continue;
break;
}
default:
continue;
}
}
if (ss->disposition &&
(candidate->disposition & ss->disposition) != ss->disposition)
continue;
if (stg == candidate)
return ss->list_id < 0 || ss->list_id == nb_matched;
nb_matched++;
}
return 0;
}
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
AVFormatContext *s, AVStream *st, const AVCodec *codec,
AVDictionary **dst, AVDictionary **opts_used)
@@ -1568,7 +1498,7 @@ double get_rotation(const int32_t *displaymatrix)
}
/* read file contents into a string */
char *read_file_to_string(const char *filename)
char *file_read(const char *filename)
{
AVIOContext *pb = NULL;
int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
@@ -1612,28 +1542,3 @@ int check_avoptions(AVDictionary *m)
return 0;
}
void dump_dictionary(void *ctx, const AVDictionary *m,
const char *name, const char *indent,
int log_level)
{
const AVDictionaryEntry *tag = NULL;
if (!m)
return;
av_log(ctx, log_level, "%s%s:\n", indent, name);
while ((tag = av_dict_iterate(m, tag))) {
const char *p = tag->value;
av_log(ctx, log_level, "%s %-16s: ", indent, tag->key);
while (*p) {
size_t len = strcspn(p, "\x8\xa\xb\xc\xd");
av_log(ctx, log_level, "%.*s", (int)(FFMIN(255, len)), p);
p += len;
if (*p == 0xd) av_log(ctx, log_level, " ");
if (*p == 0xa) av_log(ctx, log_level, "\n%s %-16s: ", indent, "");
if (*p) p++;
}
av_log(ctx, log_level, "\n");
}
}
+1 -13
View File
@@ -158,10 +158,6 @@ unsigned stream_specifier_match(const StreamSpecifier *ss,
const AVFormatContext *s, const AVStream *st,
void *logctx);
unsigned stream_group_specifier_match(const StreamSpecifier *ss,
const AVFormatContext *s, const AVStreamGroup *stg,
void *logctx);
void stream_specifier_uninit(StreamSpecifier *ss);
typedef struct SpecifierOpt {
@@ -539,7 +535,7 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems);
double get_rotation(const int32_t *displaymatrix);
/* read file contents into a string */
char *read_file_to_string(const char *filename);
char *file_read(const char *filename);
/* Remove keys in dictionary b from dictionary a */
void remove_avoptions(AVDictionary **a, AVDictionary *b);
@@ -549,12 +545,4 @@ int check_avoptions(AVDictionary *m);
int cmdutils_isalnum(char c);
/**
* This does the same as libavformat/dump.c corresponding function
* and should probably be kept in sync when the other one changes.
*/
void dump_dictionary(void *ctx, const AVDictionary *m,
const char *name, const char *indent,
int log_level);
#endif /* FFTOOLS_CMDUTILS_H */
+1 -32
View File
@@ -78,9 +78,6 @@
#include "libavdevice/avdevice.h"
#include "cmdutils.h"
#if CONFIG_MEDIACODEC
#include "compat/android/binder.h"
#endif
#include "ffmpeg.h"
#include "ffmpeg_sched.h"
#include "ffmpeg_utils.h"
@@ -216,16 +213,6 @@ void term_init(void)
#endif
#if HAVE_TERMIOS_H
/* A closed fd 0 is later reused by the first opened input file. read_key()
* would then read from that input instead of the terminal and corrupt the
* stream, so disable interaction when fd 0 is not an open descriptor.
*/
if (stdin_interaction && fcntl(0, F_GETFD) == -1) {
av_log(NULL, AV_LOG_WARNING,
"fd 0 is not an open file descriptor, stdin interaction disabled\n");
stdin_interaction = 0;
}
if (stdin_interaction) {
struct termios tty;
if (tcgetattr (0, &tty) == 0) {
@@ -263,6 +250,7 @@ void term_init(void)
/* read a key without blocking */
static int read_key(void)
{
unsigned char ch;
#if HAVE_TERMIOS_H
int n = 1;
struct timeval tv;
@@ -274,7 +262,6 @@ static int read_key(void)
tv.tv_usec = 0;
n = select(1, &rfds, NULL, NULL, &tv);
if (n > 0) {
unsigned char ch;
n = read(0, &ch, 1);
if (n == 1)
return ch;
@@ -299,7 +286,6 @@ static int read_key(void)
}
//Read it
if(nchars != 0) {
unsigned char ch;
if (read(0, &ch, 1) == 1)
return ch;
return 0;
@@ -414,7 +400,6 @@ static void frame_data_free(void *opaque, uint8_t *data)
{
FrameData *fd = (FrameData *)data;
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
avcodec_parameters_free(&fd->par_enc);
av_free(data);
@@ -444,8 +429,6 @@ static int frame_data_ensure(AVBufferRef **dst, int writable)
memcpy(fd, fd_src, sizeof(*fd));
fd->par_enc = NULL;
fd->side_data = NULL;
fd->nb_side_data = 0;
if (fd_src->par_enc) {
int ret = 0;
@@ -461,16 +444,6 @@ static int frame_data_ensure(AVBufferRef **dst, int writable)
}
}
if (fd_src->nb_side_data) {
int ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
fd_src->side_data, fd_src->nb_side_data, 0);
if (ret < 0) {
av_buffer_unref(dst);
av_buffer_unref(&src);
return ret;
}
}
av_buffer_unref(&src);
} else {
fd->dec.frame_num = UINT64_MAX;
@@ -1033,10 +1006,6 @@ int main(int argc, char **argv)
goto finish;
}
#if CONFIG_MEDIACODEC
android_binder_threadpool_init_if_required();
#endif
current_time = ti = get_benchmark_time_stamps();
ret = transcode(sch);
if (ret >= 0 && do_benchmark) {
+38 -62
View File
@@ -51,6 +51,16 @@
#include "libswresample/swresample.h"
// deprecated features
#define FFMPEG_OPT_QPHIST 1
#define FFMPEG_OPT_ADRIFT_THRESHOLD 1
#define FFMPEG_OPT_ENC_TIME_BASE_NUM 1
#define FFMPEG_OPT_TOP 1
#define FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP 1
#define FFMPEG_OPT_VSYNC_DROP 1
#define FFMPEG_OPT_VSYNC 1
#define FFMPEG_OPT_FILTER_SCRIPT 1
#define FFMPEG_ERROR_RATE_EXCEEDED FFERRTAG('E', 'R', 'E', 'D')
enum VideoSyncMethod {
@@ -59,6 +69,9 @@ enum VideoSyncMethod {
VSYNC_CFR,
VSYNC_VFR,
VSYNC_VSCFR,
#if FFMPEG_OPT_VSYNC_DROP
VSYNC_DROP,
#endif
};
enum EncTimeBase {
@@ -123,7 +136,6 @@ typedef struct StreamMap {
int disabled; /* 1 is this mapping is disabled by a negative map */
int file_index;
int stream_index;
int group_index;
char *linklabel; /* name of an output link, for mapping lavfi outputs */
ViewSpecifier vs;
@@ -205,17 +217,21 @@ typedef struct OptionsContext {
SpecifierOptList display_rotations;
SpecifierOptList display_hflips;
SpecifierOptList display_vflips;
SpecifierOptList mastering_displays;
SpecifierOptList content_lights;
SpecifierOptList rc_overrides;
SpecifierOptList intra_matrices;
SpecifierOptList inter_matrices;
SpecifierOptList chroma_intra_matrices;
#if FFMPEG_OPT_TOP
SpecifierOptList top_field_first;
#endif
SpecifierOptList metadata_map;
SpecifierOptList presets;
SpecifierOptList copy_initial_nonkeyframes;
SpecifierOptList copy_prior_start;
SpecifierOptList filters;
#if FFMPEG_OPT_FILTER_SCRIPT
SpecifierOptList filter_scripts;
#endif
SpecifierOptList reinit_filters;
SpecifierOptList drop_changed;
SpecifierOptList fix_sub_duration;
@@ -241,8 +257,6 @@ typedef struct OptionsContext {
SpecifierOptList enc_stats_pre_fmt;
SpecifierOptList enc_stats_post_fmt;
SpecifierOptList mux_stats_fmt;
int depth;
} OptionsContext;
enum IFilterFlags {
@@ -285,8 +299,6 @@ enum OFilterFlags {
// produce 24-bit audio
OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
OFILTER_FLAG_AUTOSCALE = (1 << 2),
OFILTER_FLAG_AUTOROTATE = (1 << 3),
OFILTER_FLAG_CROP = (1 << 4),
};
typedef struct OutputFilterOptions {
@@ -318,12 +330,6 @@ typedef struct OutputFilterOptions {
int height;
enum AVColorSpace color_space;
enum AVColorRange color_range;
enum AVAlphaMode alpha_mode;
unsigned crop_top;
unsigned crop_bottom;
unsigned crop_left;
unsigned crop_right;
enum VideoSyncMethod vsync_method;
AVRational frame_rate;
@@ -332,19 +338,12 @@ typedef struct OutputFilterOptions {
int sample_rate;
AVChannelLayout ch_layout;
union {
const enum AVPixelFormat *pix_fmts;
const enum AVSampleFormat *sample_fmts;
};
const int *formats;
const int *sample_rates;
const AVChannelLayout *ch_layouts;
const AVRational *frame_rates;
const enum AVColorSpace *color_spaces;
const enum AVColorRange *color_ranges;
const enum AVAlphaMode *alpha_modes;
AVFrameSideData **side_data;
int nb_side_data;
// for simple filtergraphs only, view specifier passed
// along to the decoder
@@ -401,11 +400,6 @@ typedef struct FilterGraph {
OutputFilter **outputs;
int nb_outputs;
// true when the filtergraph is created internally for
// purposes like stream group merging. Meant to be freed
// if unbound.
int is_internal;
const char *graph_desc;
struct AVBPrint graph_print_buf;
} FilterGraph;
@@ -417,6 +411,9 @@ enum DecoderFlags {
// decoder should override timestamps by fixed framerate
// from DecoderOpts.framerate
DECODER_FLAG_FRAMERATE_FORCED = (1 << 2),
#if FFMPEG_OPT_TOP
DECODER_FLAG_TOP_FIELD_FIRST = (1 << 3),
#endif
DECODER_FLAG_SEND_END_TS = (1 << 4),
// force bitexact decoding
DECODER_FLAG_BITEXACT = (1 << 5),
@@ -449,7 +446,7 @@ typedef struct Decoder {
enum AVMediaType type;
uint8_t *subtitle_header;
const uint8_t *subtitle_header;
int subtitle_header_size;
// number of frames/samples retrieved from the decoder
@@ -480,6 +477,9 @@ typedef struct InputStream {
/* framerate forced with -r */
AVRational framerate;
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
int fix_sub_duration;
@@ -489,18 +489,6 @@ typedef struct InputStream {
int nb_filters;
} InputStream;
typedef struct InputStreamGroup {
const AVClass *class;
/* parent source */
struct InputFile *file;
int index;
FilterGraph *fg;
AVStreamGroup *stg;
} InputStreamGroup;
typedef struct InputFile {
const AVClass *class;
@@ -522,10 +510,6 @@ typedef struct InputFile {
* if new streams appear dynamically during demuxing */
InputStream **streams;
int nb_streams;
/* stream groups that ffmpeg is aware of; */
InputStreamGroup **stream_groups;
int nb_stream_groups;
} InputFile;
enum forced_keyframes_const {
@@ -581,8 +565,9 @@ typedef struct EncStats {
enum {
KF_FORCE_SOURCE = 1,
// force keyframe if lavfi.scd.time metadata is set
KF_FORCE_SCD_METADATA = 3,
#if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP
KF_FORCE_SOURCE_NO_DROP = 2,
#endif
};
typedef struct KeyframeForceCtx {
@@ -637,6 +622,10 @@ typedef struct OutputStream {
Encoder *enc;
/* video only */
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
int bitexact;
int bits_per_raw_sample;
@@ -707,9 +696,6 @@ typedef struct FrameData {
int64_t wallclock[LATENCY_PROBE_NB];
AVCodecParameters *par_enc;
AVFrameSideData **side_data;
int nb_side_data;
} FrameData;
extern InputFile **input_files;
@@ -783,12 +769,12 @@ int check_avoptions_used(const AVDictionary *opts, const AVDictionary *opts_used
int assert_file_overwrite(const char *filename);
int find_codec(void *logctx, const char *name,
enum AVMediaType type, int encoder, const AVCodec **codec);
int parse_and_set_vsync(const char *arg, enum VideoSyncMethod *vsync_var, int file_idx, int st_idx);
int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global);
int filtergraph_is_simple(const FilterGraph *fg);
int fg_create_simple(FilterGraph **pfg,
InputStream *ist,
char **graph_desc,
char *graph_desc,
Scheduler *sch, unsigned sched_idx_enc,
const OutputFilterOptions *opts);
int fg_finalise_bindings(void);
@@ -811,11 +797,10 @@ int ofilter_bind_enc(OutputFilter *ofilter,
/**
* Create a new filtergraph in the global filtergraph list.
*
* @param graph_desc Pointer to graph description; an av_malloc()ed string, filtergraph
* @param graph_desc Graph description; an av_malloc()ed string, filtergraph
* takes ownership of it.
*/
int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
const OutputFilterOptions *opts);
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch);
void fg_free(FilterGraph **pfg);
@@ -942,15 +927,6 @@ void opt_match_per_stream_int64(void *logctx, const SpecifierOptList *sol,
void opt_match_per_stream_dbl(void *logctx, const SpecifierOptList *sol,
AVFormatContext *fc, AVStream *st, double *out);
void opt_match_per_stream_group_str(void *logctx, const SpecifierOptList *sol,
AVFormatContext *fc, AVStreamGroup *stg, const char **out);
void opt_match_per_stream_group_int(void *logctx, const SpecifierOptList *sol,
AVFormatContext *fc, AVStreamGroup *stg, int *out);
void opt_match_per_stream_group_int64(void *logctx, const SpecifierOptList *sol,
AVFormatContext *fc, AVStreamGroup *stg, int64_t *out);
void opt_match_per_stream_group_dbl(void *logctx, const SpecifierOptList *sol,
AVFormatContext *fc, AVStreamGroup *stg, double *out);
int view_specifier_parse(const char **pspec, ViewSpecifier *vs);
int muxer_thread(void *arg);
+11 -18
View File
@@ -136,8 +136,6 @@ void dec_free(Decoder **pdec)
av_frame_free(&dp->sub_prev[i]);
av_frame_free(&dp->sub_heartbeat);
av_freep(&dp->dec.subtitle_header);
av_freep(&dp->parent_name);
av_freep(&dp->views_requested);
@@ -387,6 +385,13 @@ fail:
static int video_frame_process(DecoderPriv *dp, AVFrame *frame,
unsigned *outputs_mask)
{
#if FFMPEG_OPT_TOP
if (dp->flags & DECODER_FLAG_TOP_FIELD_FIRST) {
av_log(dp, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n");
frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
}
#endif
if (frame->format == dp->hwaccel_pix_fmt) {
int err = hwaccel_retrieve_data(dp->dec_ctx, frame);
if (err < 0)
@@ -739,14 +744,11 @@ static int packet_decode(DecoderPriv *dp, AVPacket *pkt, AVFrame *frame)
while (1) {
FrameData *fd;
unsigned outputs_mask = 1;
unsigned flags = 0;
if (!dp->dec.frames_decoded)
flags |= AV_CODEC_RECEIVE_FRAME_FLAG_SYNCHRONOUS;
av_frame_unref(frame);
update_benchmark(NULL);
ret = avcodec_receive_frame_flags(dec, frame, flags);
ret = avcodec_receive_frame(dec, frame);
update_benchmark("decode_%s %s", type_desc, dp->parent_name);
if (ret == AVERROR(EAGAIN)) {
@@ -1005,7 +1007,7 @@ static int decoder_thread(void *arg)
ret = 0;
err_rate = (dp->dec.frames_decoded || dp->dec.decode_errors) ?
(float)dp->dec.decode_errors / (dp->dec.frames_decoded + dp->dec.decode_errors) : 0.f;
dp->dec.decode_errors / (dp->dec.frames_decoded + dp->dec.decode_errors) : 0.f;
if (err_rate > max_error_rate) {
av_log(dp, AV_LOG_FATAL, "Decode error rate %g exceeds maximum %g\n",
err_rate, max_error_rate);
@@ -1016,7 +1018,6 @@ static int decoder_thread(void *arg)
finish:
dec_thread_uninit(&dt);
avcodec_free_context(&dp->dec_ctx);
return ret;
}
@@ -1616,15 +1617,8 @@ static int dec_open(DecoderPriv *dp, AVDictionary **dec_opts,
dp->dec_ctx->extra_hw_frames = extra_frames;
}
if (dp->dec_ctx->subtitle_header) {
/* ASS code assumes this buffer is null terminated so add extra byte. */
dp->dec.subtitle_header = av_mallocz(dp->dec_ctx->subtitle_header_size + 1);
if (!dp->dec.subtitle_header)
return AVERROR(ENOMEM);
memcpy(dp->dec.subtitle_header, dp->dec_ctx->subtitle_header,
dp->dec_ctx->subtitle_header_size);
dp->dec.subtitle_header_size = dp->dec_ctx->subtitle_header_size;
}
dp->dec.subtitle_header = dp->dec_ctx->subtitle_header;
dp->dec.subtitle_header_size = dp->dec_ctx->subtitle_header_size;
if (param_out) {
if (dp->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -1641,7 +1635,6 @@ static int dec_open(DecoderPriv *dp, AVDictionary **dec_opts,
param_out->sample_aspect_ratio = dp->dec_ctx->sample_aspect_ratio;
param_out->colorspace = dp->dec_ctx->colorspace;
param_out->color_range = dp->dec_ctx->color_range;
param_out->alpha_mode = dp->dec_ctx->alpha_mode;
}
av_frame_side_data_free(&param_out->side_data, &param_out->nb_side_data);
+51 -428
View File
@@ -28,7 +28,6 @@
#include "libavutil/display.h"
#include "libavutil/error.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mastering_display_metadata.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
@@ -69,8 +68,6 @@ typedef struct DemuxStream {
int autorotate;
int apply_cropping;
int force_display_matrix;
int force_mastering_display;
int force_content_light;
int drop_changed;
@@ -99,15 +96,14 @@ typedef struct DemuxStream {
uint64_t nb_packets;
// combined size of all the packets read
uint64_t data_size;
// latest wallclock time at which packet reading resumed after a stall - used for readrate
int64_t resume_wc;
// timestamp of first packet sent after the latest stall - used for readrate
int64_t resume_pts;
// measure of how far behind packet reading is against spceified readrate
int64_t lag;
} DemuxStream;
typedef struct DemuxStreamGroup {
InputStreamGroup istg;
// name used for logging
char log_name[32];
} DemuxStreamGroup;
typedef struct Demuxer {
InputFile f;
@@ -141,13 +137,6 @@ typedef struct Demuxer {
double readrate_initial_burst;
float readrate_catchup;
// latest wallclock time at which packet reading resumed after a stall - used for readrate
int64_t resume_wc;
// relative timestamp of first packet sent after the latest stall - used for readrate
int64_t resume_progress;
// measure of how far behind packet reading is against spceified readrate
int64_t lag;
Scheduler *sch;
AVPacket *pkt_heartbeat;
@@ -518,55 +507,40 @@ static void readrate_sleep(Demuxer *d)
int64_t initial_burst = AV_TIME_BASE * d->readrate_initial_burst;
int resume_warn = 0;
DemuxStream *slowest = NULL;
int64_t progress = INT64_MAX;
for (int i = 0; i < f->nb_streams; i++) {
InputStream *ist = f->streams[i];
DemuxStream *ds = ds_from_ist(ist);
int64_t stream_ts_offset, pts, pts_diff;
if (ds->discard || ds->finished || ds->first_dts == AV_NOPTS_VALUE)
continue;
int64_t stream_ts_offset, pts, now, wc_elapsed, elapsed, lag, max_pts, limit_pts;
stream_ts_offset = FFMAX(ds->first_dts, file_start);
if (ds->discard) continue;
stream_ts_offset = FFMAX(ds->first_dts != AV_NOPTS_VALUE ? ds->first_dts : 0, file_start);
pts = av_rescale(ds->dts, 1000000, AV_TIME_BASE);
pts_diff = pts - stream_ts_offset;
if (pts_diff < progress) {
progress = pts_diff;
slowest = ds;
now = av_gettime_relative();
wc_elapsed = now - d->wallclock_start;
max_pts = stream_ts_offset + initial_burst + wc_elapsed * d->readrate;
lag = FFMAX(max_pts - pts, 0);
if ( (!ds->lag && lag > 0.3 * AV_TIME_BASE) || ( lag > ds->lag + 0.3 * AV_TIME_BASE) ) {
ds->lag = lag;
ds->resume_wc = now;
ds->resume_pts = pts;
av_log_once(ds, AV_LOG_WARNING, AV_LOG_DEBUG, &resume_warn,
"Resumed reading at pts %0.3f with rate %0.3f after a lag of %0.3fs\n",
(float)pts/AV_TIME_BASE, d->readrate_catchup, (float)lag/AV_TIME_BASE);
}
if (ds->lag && !lag)
ds->lag = ds->resume_wc = ds->resume_pts = 0;
if (ds->resume_wc) {
elapsed = now - ds->resume_wc;
limit_pts = ds->resume_pts + elapsed * d->readrate_catchup;
} else {
elapsed = wc_elapsed;
limit_pts = max_pts;
}
if (pts > limit_pts)
av_usleep(pts - limit_pts);
}
if (!slowest || progress <= initial_burst)
return;
int64_t now = av_gettime_relative();
int64_t wc_elapsed = now - d->wallclock_start;
int64_t max_prog = initial_burst + (int64_t)(wc_elapsed * d->readrate);
int64_t lag = FFMAX(max_prog - progress, 0);
int64_t limit;
if ( (!d->lag && lag > 0.3 * AV_TIME_BASE) || ( lag > d->lag + 0.3 * AV_TIME_BASE) ) {
d->lag = lag;
d->resume_wc = now;
d->resume_progress = progress;
int64_t pts = FFMAX(slowest->first_dts, file_start) + progress;
av_log_once(slowest, AV_LOG_WARNING, AV_LOG_DEBUG, &resume_warn,
"Resumed reading at pts %0.3f with rate %0.3f after a lag of %0.3fs\n",
(float)pts/AV_TIME_BASE, d->readrate_catchup, (float)lag/AV_TIME_BASE);
}
if (d->lag && !lag)
d->lag = d->resume_wc = d->resume_progress = 0;
if (d->resume_wc) {
int64_t elapsed = now - d->resume_wc;
limit = d->resume_progress + (int64_t)(elapsed * d->readrate_catchup);
} else {
limit = max_prog;
}
if (progress > limit)
av_usleep(progress - limit);
}
static int do_send(Demuxer *d, DemuxStream *ds, AVPacket *pkt, unsigned flags,
@@ -912,16 +886,6 @@ static void ist_free(InputStream **pist)
av_freep(pist);
}
static void istg_free(InputStreamGroup **pistg)
{
InputStreamGroup *istg = *pistg;
if (!istg)
return;
av_freep(pistg);
}
void ifile_close(InputFile **pf)
{
InputFile *f = *pf;
@@ -937,10 +901,6 @@ void ifile_close(InputFile **pf)
ist_free(&f->streams[i]);
av_freep(&f->streams);
for (int i = 0; i < f->nb_stream_groups; i++)
istg_free(&f->stream_groups[i]);
av_freep(&f->stream_groups);
avformat_close_input(&f->ctx);
av_packet_free(&d->pkt_heartbeat);
@@ -998,7 +958,11 @@ int ist_use(InputStream *ist, int decoding_needed,
ds->dec_opts.flags |= (!!ist->fix_sub_duration * DECODER_FLAG_FIX_SUB_DURATION) |
(!!is_unreliable * DECODER_FLAG_TS_UNRELIABLE) |
(!!(d->loop && is_audio) * DECODER_FLAG_SEND_END_TS);
(!!(d->loop && is_audio) * DECODER_FLAG_SEND_END_TS)
#if FFMPEG_OPT_TOP
| ((ist->top_field_first >= 0) * DECODER_FLAG_TOP_FIELD_FIRST)
#endif
;
if (ist->framerate.num) {
ds->dec_opts.flags |= DECODER_FLAG_FRAMERATE_FORCED;
@@ -1260,125 +1224,6 @@ static int add_display_matrix_to_stream(const OptionsContext *o,
return 0;
}
static int add_mastering_display_to_stream(const OptionsContext *o,
AVFormatContext *ctx, InputStream *ist)
{
AVStream *st = ist->st;
DemuxStream *ds = ds_from_ist(ist);
AVMasteringDisplayMetadata *master_display;
AVPacketSideData *sd;
const char *p = NULL;
const int chroma_den = 50000;
const int luma_den = 10000;
size_t size;
int ret;
opt_match_per_stream_str(ist, &o->mastering_displays, ctx, st, &p);
if (!p)
return 0;
master_display = av_mastering_display_metadata_alloc_size(&size);
if (!master_display)
return AVERROR(ENOMEM);
ret = sscanf(p,
"G(%u,%u)B(%u,%u)R(%u,%u)WP(%u,%u)L(%u,%u)",
(unsigned*)&master_display->display_primaries[1][0].num,
(unsigned*)&master_display->display_primaries[1][1].num,
(unsigned*)&master_display->display_primaries[2][0].num,
(unsigned*)&master_display->display_primaries[2][1].num,
(unsigned*)&master_display->display_primaries[0][0].num,
(unsigned*)&master_display->display_primaries[0][1].num,
(unsigned*)&master_display->white_point[0].num,
(unsigned*)&master_display->white_point[1].num,
(unsigned*)&master_display->max_luminance.num,
(unsigned*)&master_display->min_luminance.num);
if (ret != 10 ||
(unsigned)(master_display->display_primaries[1][0].num | master_display->display_primaries[1][1].num |
master_display->display_primaries[2][0].num | master_display->display_primaries[2][1].num |
master_display->display_primaries[0][0].num | master_display->display_primaries[0][1].num |
master_display->white_point[0].num | master_display->white_point[1].num) > UINT16_MAX ||
(unsigned)(master_display->max_luminance.num | master_display->min_luminance.num) > INT_MAX ||
master_display->min_luminance.num > master_display->max_luminance.num) {
av_freep(&master_display);
av_log(ist, AV_LOG_ERROR, "Failed to parse mastering display option\n");
return AVERROR(EINVAL);
}
master_display->display_primaries[1][0].den = chroma_den;
master_display->display_primaries[1][1].den = chroma_den;
master_display->display_primaries[2][0].den = chroma_den;
master_display->display_primaries[2][1].den = chroma_den;
master_display->display_primaries[0][0].den = chroma_den;
master_display->display_primaries[0][1].den = chroma_den;
master_display->white_point[0].den = chroma_den;
master_display->white_point[1].den = chroma_den;
master_display->max_luminance.den = luma_den;
master_display->min_luminance.den = luma_den;
master_display->has_primaries = 1;
master_display->has_luminance = 1;
sd = av_packet_side_data_add(&st->codecpar->coded_side_data,
&st->codecpar->nb_coded_side_data,
AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
(uint8_t *)master_display, size, 0);
if (!sd) {
av_freep(&master_display);
return AVERROR(ENOMEM);
}
ds->force_mastering_display = 1;
return 0;
}
static int add_content_light_to_stream(const OptionsContext *o,
AVFormatContext *ctx, InputStream *ist)
{
AVStream *st = ist->st;
DemuxStream *ds = ds_from_ist(ist);
AVContentLightMetadata *cll;
AVPacketSideData *sd;
const char *p = NULL;
size_t size;
int ret;
opt_match_per_stream_str(ist, &o->content_lights, ctx, st, &p);
if (!p)
return 0;
cll = av_content_light_metadata_alloc(&size);
if (!cll)
return AVERROR(ENOMEM);
ret = sscanf(p, "%u,%u",
(unsigned*)&cll->MaxCLL,
(unsigned*)&cll->MaxFALL);
if (ret != 2 || (unsigned)(cll->MaxCLL | cll->MaxFALL) > UINT16_MAX) {
av_freep(&cll);
av_log(ist, AV_LOG_ERROR, "Failed to parse content light option\n");
return AVERROR(EINVAL);
}
sd = av_packet_side_data_add(&st->codecpar->coded_side_data,
&st->codecpar->nb_coded_side_data,
AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
(uint8_t *)cll, size, 0);
if (!sd) {
av_freep(&cll);
return AVERROR(ENOMEM);
}
ds->force_content_light = 1;
return 0;
}
static const char *input_stream_item_name(void *obj)
{
const DemuxStream *ds = obj;
@@ -1432,7 +1277,6 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
const char *bsfs = NULL;
char *next;
const char *discard_str = NULL;
AVBPrint bp;
int ret;
ds = demux_stream_alloc(d, st);
@@ -1498,14 +1342,6 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
if (ret < 0)
return ret;
ret = add_mastering_display_to_stream(o, ic, ist);
if (ret < 0)
return ret;
ret = add_content_light_to_stream(o, ic, ist);
if (ret < 0)
return ret;
opt_match_per_stream_str(ist, &o->hwaccels, ic, st, &hwaccel);
opt_match_per_stream_str(ist, &o->hwaccel_output_formats, ic, st,
&hwaccel_output_format);
@@ -1623,26 +1459,15 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
av_dict_set_int(&ds->decoder_opts, "apply_cropping",
ds->apply_cropping && ds->apply_cropping != CROP_CONTAINER, 0);
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
if (ds->force_display_matrix) {
char buf[32];
if (av_dict_get(ds->decoder_opts, "side_data_prefer_packet", NULL, 0))
av_bprintf(&bp, ",");
av_bprintf(&bp, "displaymatrix");
buf[0] = ',';
else
buf[0] = '\0';
av_strlcat(buf, "displaymatrix", sizeof(buf));
av_dict_set(&ds->decoder_opts, "side_data_prefer_packet", buf, AV_DICT_APPEND);
}
if (ds->force_mastering_display) {
if (bp.len || av_dict_get(ds->decoder_opts, "side_data_prefer_packet", NULL, 0))
av_bprintf(&bp, ",");
av_bprintf(&bp, "mastering_display_metadata");
}
if (ds->force_content_light) {
if (bp.len || av_dict_get(ds->decoder_opts, "side_data_prefer_packet", NULL, 0))
av_bprintf(&bp, ",");
av_bprintf(&bp, "content_light_level");
}
if (bp.len)
av_dict_set(&ds->decoder_opts, "side_data_prefer_packet", bp.str, AV_DICT_APPEND);
av_bprint_finalize(&bp, NULL);
/* Attached pics are sparse, therefore we would not want to delay their decoding
* till EOF. */
if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
@@ -1659,6 +1484,12 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
return ret;
}
}
#if FFMPEG_OPT_TOP
ist->top_field_first = -1;
opt_match_per_stream_int(ist, &o->top_field_first, ic, st, &ist->top_field_first);
#endif
break;
case AVMEDIA_TYPE_AUDIO: {
const char *ch_layout_str = NULL;
@@ -1755,199 +1586,6 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
return 0;
}
static const char *input_stream_group_item_name(void *obj)
{
const DemuxStreamGroup *dsg = obj;
return dsg->log_name;
}
static const AVClass input_stream_group_class = {
.class_name = "InputStreamGroup",
.version = LIBAVUTIL_VERSION_INT,
.item_name = input_stream_group_item_name,
.category = AV_CLASS_CATEGORY_DEMUXER,
};
static DemuxStreamGroup *demux_stream_group_alloc(Demuxer *d, AVStreamGroup *stg)
{
InputFile *f = &d->f;
DemuxStreamGroup *dsg;
dsg = allocate_array_elem(&f->stream_groups, sizeof(*dsg), &f->nb_stream_groups);
if (!dsg)
return NULL;
dsg->istg.stg = stg;
dsg->istg.file = f;
dsg->istg.index = stg->index;
dsg->istg.class = &input_stream_group_class;
snprintf(dsg->log_name, sizeof(dsg->log_name), "istg#%d:%d/%s",
d->f.index, stg->index, avformat_stream_group_name(stg->type));
return dsg;
}
static int istg_parse_tile_grid(const OptionsContext *o, Demuxer *d, InputStreamGroup *istg)
{
InputFile *f = &d->f;
AVFormatContext *ic = d->f.ctx;
AVStreamGroup *stg = istg->stg;
const AVStreamGroupTileGrid *tg = stg->params.tile_grid;
OutputFilterOptions opts;
AVBPrint bp;
char *graph_str;
int autorotate = 1;
const char *apply_cropping = NULL;
int ret;
if (tg->nb_tiles == 1)
return 0;
if (!tg->nb_tiles) {
av_log(istg, AV_LOG_FATAL, "A demuxer exported an invalid tile group stream group. "
"This is a bug, please report it.\n");
return AVERROR_BUG;
}
memset(&opts, 0, sizeof(opts));
opt_match_per_stream_group_int(istg, &o->autorotate, ic, stg, &autorotate);
if (autorotate)
opts.flags |= OFILTER_FLAG_AUTOROTATE;
opts.flags |= OFILTER_FLAG_CROP;
opt_match_per_stream_group_str(istg, &o->apply_cropping, ic, stg, &apply_cropping);
if (apply_cropping) {
char *p;
int crop = strtol(apply_cropping, &p, 0);
if (*p)
return AVERROR(EINVAL);
if (!crop)
opts.flags &= ~OFILTER_FLAG_CROP;
}
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
for (int i = 0; i < tg->nb_tiles; i++)
av_bprintf(&bp, "[%d:g:%d:%d]", f->index, stg->index, tg->offsets[i].idx);
av_bprintf(&bp, "xstack=inputs=%d:layout=", tg->nb_tiles);
for (int i = 0; i < tg->nb_tiles - 1; i++)
av_bprintf(&bp, "%d_%d|", tg->offsets[i].horizontal,
tg->offsets[i].vertical);
av_bprintf(&bp, "%d_%d:fill=0x%02X%02X%02X@0x%02X", tg->offsets[tg->nb_tiles - 1].horizontal,
tg->offsets[tg->nb_tiles - 1].vertical,
tg->background[0], tg->background[1],
tg->background[2], tg->background[3]);
av_bprintf(&bp, "[%d:g:%d]", f->index, stg->index);
ret = av_bprint_finalize(&bp, &graph_str);
if (ret < 0)
return ret;
if (tg->coded_width != tg->width || tg->coded_height != tg->height) {
opts.crop_top = tg->vertical_offset;
opts.crop_bottom = tg->coded_height - tg->height - tg->vertical_offset;
opts.crop_left = tg->horizontal_offset;
opts.crop_right = tg->coded_width - tg->width - tg->horizontal_offset;
}
for (int i = 0; i < tg->nb_coded_side_data; i++) {
const AVPacketSideData *sd = &tg->coded_side_data[i];
ret = av_packet_side_data_to_frame(&opts.side_data, &opts.nb_side_data, sd, 0);
if (ret < 0 && ret != AVERROR(EINVAL))
goto fail;
}
ret = fg_create(NULL, &graph_str, d->sch, &opts);
if (ret < 0)
goto fail;
istg->fg = filtergraphs[nb_filtergraphs-1];
istg->fg->is_internal = 1;
ret = 0;
fail:
if (ret < 0)
av_freep(&graph_str);
return ret;
}
static int istg_add(const OptionsContext *o, Demuxer *d, AVStreamGroup *stg)
{
DemuxStreamGroup *dsg;
InputStreamGroup *istg;
int ret;
dsg = demux_stream_group_alloc(d, stg);
if (!dsg)
return AVERROR(ENOMEM);
istg = &dsg->istg;
switch (stg->type) {
case AV_STREAM_GROUP_PARAMS_TILE_GRID:
ret = istg_parse_tile_grid(o, d, istg);
if (ret < 0)
return ret;
break;
default:
break;
}
return 0;
}
static int is_windows_reserved_device_name(const char *f)
{
#if HAVE_DOS_PATHS
for (const char *p = f; p && *p; ) {
char stem[6], *s;
av_strlcpy(stem, p, sizeof(stem));
if ((s = strchr(stem, '.')))
*s = 0;
if ((s = strpbrk(stem, "123456789")))
*s = '1';
if( !av_strcasecmp(stem, "AUX") ||
!av_strcasecmp(stem, "CON") ||
!av_strcasecmp(stem, "NUL") ||
!av_strcasecmp(stem, "PRN") ||
!av_strcasecmp(stem, "COM1") ||
!av_strcasecmp(stem, "LPT1")
)
return 1;
p = strchr(p, '/');
if (p)
p++;
}
#endif
return 0;
}
static int safe_filename(const char *f, int allow_subdir)
{
const char *start = f;
if (!*f || is_windows_reserved_device_name(f))
return 0;
for (; *f; f++) {
/* A-Za-z0-9_- */
if (!((unsigned)((*f | 32) - 'a') < 26 ||
(unsigned)(*f - '0') < 10 || *f == '_' || *f == '-')) {
if (f == start)
return 0;
else if (allow_subdir && *f == '/')
start = f + 1;
else if (*f != '.')
return 0;
}
}
return 1;
}
static int dump_attachment(InputStream *ist, const char *filename)
{
AVStream *st = ist->st;
@@ -1959,13 +1597,8 @@ static int dump_attachment(InputStream *ist, const char *filename)
av_log(ist, AV_LOG_WARNING, "No extradata to dump.\n");
return 0;
}
if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0))) {
if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0)))
filename = e->value;
if (!safe_filename(filename, 0)) {
av_log(ist, AV_LOG_ERROR, "Filename %s is unsafe\n", filename);
return AVERROR(EINVAL);
}
}
if (!*filename) {
av_log(ist, AV_LOG_FATAL, "No filename specified and no 'filename' tag");
return AVERROR(EINVAL);
@@ -2084,7 +1717,6 @@ int ifile_open(const OptionsContext *o, const char *filename, Scheduler *sch)
ic = avformat_alloc_context();
if (!ic)
return AVERROR(ENOMEM);
ic->name = av_strdup(d->log_name);
if (o->audio_sample_rate.nb_opt) {
av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate.opt[o->audio_sample_rate.nb_opt - 1].u.i, 0);
}
@@ -2173,8 +1805,6 @@ int ifile_open(const OptionsContext *o, const char *filename, Scheduler *sch)
av_strlcat(d->log_name, "/", sizeof(d->log_name));
av_strlcat(d->log_name, ic->iformat->name, sizeof(d->log_name));
av_freep(&ic->name);
ic->name = av_strdup(d->log_name);
if (scan_all_pmts_set)
av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
@@ -2324,13 +1954,6 @@ int ifile_open(const OptionsContext *o, const char *filename, Scheduler *sch)
}
}
/* Add all the stream groups from the given input file to the demuxer */
for (int i = 0; i < ic->nb_stream_groups; i++) {
ret = istg_add(o, d, ic->stream_groups[i]);
if (ret < 0)
return ret;
}
/* dump the file content */
av_dump_format(ic, f->index, filename, 0);
+33 -30
View File
@@ -205,10 +205,19 @@ int enc_open(void *opaque, const AVFrame *frame)
av_assert0(frame->opaque_ref);
fd = (FrameData*)frame->opaque_ref->data;
ret = clone_side_data(&enc_ctx->decoded_side_data, &enc_ctx->nb_decoded_side_data,
fd->side_data, fd->nb_side_data, AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
if (ret < 0)
return ret;
for (int i = 0; i < frame->nb_side_data; i++) {
const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL))
continue;
ret = av_frame_side_data_clone(&enc_ctx->decoded_side_data,
&enc_ctx->nb_decoded_side_data,
frame->side_data[i],
AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
if (ret < 0)
return ret;
}
}
if (ist)
@@ -227,9 +236,6 @@ int enc_open(void *opaque, const AVFrame *frame)
frame->ch_layout.nb_channels > 0);
enc_ctx->sample_fmt = frame->format;
enc_ctx->sample_rate = frame->sample_rate;
if (!enc_ctx->frame_size && (!(enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ||
(enc_ctx->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)))
enc_ctx->frame_size = frame->nb_samples;
ret = av_channel_layout_copy(&enc_ctx->ch_layout, &frame->ch_layout);
if (ret < 0)
return ret;
@@ -260,31 +266,24 @@ int enc_open(void *opaque, const AVFrame *frame)
enc_ctx->bits_per_raw_sample = FFMIN(fd->bits_per_raw_sample,
av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth);
/**
* The video color properties should always be in sync with the user-
* requested values, since we forward them to the filter graph.
*/
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->alpha_mode = frame->alpha_mode;
/* Video properties which are not part of filter graph negotiation */
if (enc_ctx->chroma_sample_location == AVCHROMA_LOC_UNSPECIFIED) {
enc_ctx->chroma_sample_location = frame->chroma_location;
} else if (enc_ctx->chroma_sample_location != frame->chroma_location &&
frame->chroma_location != AVCHROMA_LOC_UNSPECIFIED) {
av_log(e, AV_LOG_WARNING,
"Requested chroma sample location '%s' does not match the "
"frame tagged sample location '%s'; result may be incorrect.\n",
av_chroma_location_name(enc_ctx->chroma_sample_location),
av_chroma_location_name(frame->chroma_location));
}
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)) {
int top_field_first = !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST);
(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;
@@ -722,7 +721,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
}
}
av_unreachable("encode_frame() loop should return");
av_assert0(0);
}
static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
@@ -762,9 +761,6 @@ static enum AVPictureType forced_kf_apply(void *logctx, KeyframeForceCtx *kf,
}
} else if (kf->type == KF_FORCE_SOURCE && (frame->flags & AV_FRAME_FLAG_KEY)) {
goto force_keyframe;
} else if (kf->type == KF_FORCE_SCD_METADATA &&
av_dict_get(frame->metadata, "lavfi.scd.time", NULL, 0)) {
goto force_keyframe;
}
return AV_PICTURE_TYPE_NONE;
@@ -796,6 +792,13 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
if (type == AVMEDIA_TYPE_VIDEO) {
frame->quality = e->enc_ctx->global_quality;
frame->pict_type = forced_kf_apply(e, &ost->kf, frame);
#if FFMPEG_OPT_TOP
if (ost->top_field_first >= 0) {
frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST * (!!ost->top_field_first);
}
#endif
} else {
if (!(e->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
e->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
+96 -323
View File
@@ -27,7 +27,6 @@
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/bprint.h"
@@ -41,6 +40,9 @@
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
// FIXME private header, used for mid_pred()
#include "libavcodec/mathops.h"
typedef struct FilterGraphPriv {
FilterGraph fg;
@@ -51,6 +53,8 @@ typedef struct FilterGraphPriv {
// true when the filtergraph contains only meta filters
// that do not modify the frame data
int is_meta;
// source filters are present in the graph
int have_sources;
int disable_conversions;
unsigned nb_outputs_done;
@@ -105,9 +109,6 @@ typedef struct InputFilterPriv {
// used to hold submitted input
AVFrame *frame;
// For inputs bound to a filtergraph output
OutputFilter *ofilter_src;
// source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
// same as type otherwise
enum AVMediaType type_src;
@@ -124,7 +125,6 @@ typedef struct InputFilterPriv {
AVRational sample_aspect_ratio;
enum AVColorSpace color_space;
enum AVColorRange color_range;
enum AVAlphaMode alpha_mode;
int sample_rate;
AVChannelLayout ch_layout;
@@ -189,8 +189,6 @@ typedef struct OutputFilterPriv {
void *log_parent;
char log_name[32];
int needed;
/* desired output stream properties */
int format;
int width, height;
@@ -198,12 +196,6 @@ typedef struct OutputFilterPriv {
AVChannelLayout ch_layout;
enum AVColorSpace color_space;
enum AVColorRange color_range;
enum AVAlphaMode alpha_mode;
unsigned crop_top;
unsigned crop_bottom;
unsigned crop_left;
unsigned crop_right;
AVFrameSideData **side_data;
int nb_side_data;
@@ -222,17 +214,11 @@ typedef struct OutputFilterPriv {
// those are only set if no format is specified and the encoder gives us multiple options
// They point directly to the relevant lists of the encoder.
union {
const enum AVPixelFormat *pix_fmts;
const enum AVSampleFormat *sample_fmts;
};
const int *formats;
const AVChannelLayout *ch_layouts;
const int *sample_rates;
const enum AVColorSpace *color_spaces;
const enum AVColorRange *color_ranges;
const enum AVAlphaMode *alpha_modes;
int32_t displaymatrix[9];
AVRational enc_timebase;
int64_t trim_start_us;
@@ -282,7 +268,6 @@ static int sub2video_get_blank_frame(InputFilterPriv *ifp)
frame->format = ifp->format;
frame->colorspace = ifp->color_space;
frame->color_range = ifp->color_range;
frame->alpha_mode = ifp->alpha_mode;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
@@ -401,10 +386,10 @@ static void choose_ ## name (OutputFilterPriv *ofp, AVBPrint *bprint) \
av_bprint_chars(bprint, ':', 1); \
}
DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, pix_fmts,
DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats,
AV_PIX_FMT_NONE, "%s", av_get_pix_fmt_name)
DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, sample_fmts,
DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats,
AV_SAMPLE_FMT_NONE, "%s", av_get_sample_fmt_name)
DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,
@@ -416,9 +401,6 @@ DEF_CHOOSE_FORMAT(color_spaces, enum AVColorSpace, color_space, color_spaces,
DEF_CHOOSE_FORMAT(color_ranges, enum AVColorRange, color_range, color_ranges,
AVCOL_RANGE_UNSPECIFIED, "%s", av_color_range_name);
DEF_CHOOSE_FORMAT(alpha_modes, enum AVAlphaMode, alpha_mode, alpha_modes,
AVALPHA_MODE_UNSPECIFIED, "%s", av_alpha_mode_name);
static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint)
{
if (av_channel_layout_check(&ofp->ch_layout)) {
@@ -518,7 +500,7 @@ static int filter_opt_apply(void *logctx, AVFilterContext *f,
ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN);
av_freep(&data);
} else {
char *data = read_file_to_string(val);
char *data = file_read(val);
if (!data) {
ret = AVERROR(EIO);
goto err_load;
@@ -668,7 +650,6 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type)
ofp->format = -1;
ofp->color_space = AVCOL_SPC_UNSPECIFIED;
ofp->color_range = AVCOL_RANGE_UNSPECIFIED;
ofp->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
ofilter->index = fg->nb_outputs - 1;
snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d",
@@ -821,10 +802,10 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
av_assert0(!opts->enc ||
ofilter->type == opts->enc->type);
ofp->needed = ofilter->bound = 1;
ofilter->bound = 1;
av_freep(&ofilter->linklabel);
ofp->flags |= opts->flags;
ofp->flags = opts->flags;
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = opts->output_tb;
@@ -861,7 +842,7 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
if (opts->format != AV_PIX_FMT_NONE) {
ofp->format = opts->format;
} else
ofp->pix_fmts = opts->pix_fmts;
ofp->formats = opts->formats;
if (opts->color_space != AVCOL_SPC_UNSPECIFIED)
ofp->color_space = opts->color_space;
@@ -873,11 +854,6 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
else
ofp->color_ranges = opts->color_ranges;
if (opts->alpha_mode != AVALPHA_MODE_UNSPECIFIED)
ofp->alpha_mode = opts->alpha_mode;
else
ofp->alpha_modes = opts->alpha_modes;
fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT);
ofp->fps.last_frame = av_frame_alloc();
@@ -900,7 +876,7 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
if (opts->format != AV_SAMPLE_FMT_NONE) {
ofp->format = opts->format;
} else {
ofp->sample_fmts = opts->sample_fmts;
ofp->formats = opts->formats;
}
if (opts->sample_rate) {
ofp->sample_rate = opts->sample_rate;
@@ -932,15 +908,13 @@ static int ofilter_bind_ifilter(OutputFilter *ofilter, InputFilterPriv *ifp,
av_assert0(!ofilter->bound);
av_assert0(ofilter->type == ifp->ifilter.type);
ofp->needed = ofilter->bound = 1;
ofilter->bound = 1;
av_freep(&ofilter->linklabel);
ofilter->output_name = av_strdup(opts->name);
if (!ofilter->output_name)
return AVERROR(EINVAL);
ifp->ofilter_src = ofilter;
av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofilter->output_name);
return 0;
@@ -1003,7 +977,6 @@ static InputFilter *ifilter_alloc(FilterGraph *fg)
ifp->format = -1;
ifp->color_space = AVCOL_SPC_UNSPECIFIED;
ifp->color_range = AVCOL_RANGE_UNSPECIFIED;
ifp->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
if (!ifp->frame_queue)
@@ -1037,7 +1010,6 @@ void fg_free(FilterGraph **pfg)
av_frame_free(&ifp->opts.fallback);
av_buffer_unref(&ifp->hw_frames_ctx);
av_channel_layout_uninit(&ifp->ch_layout);
av_freep(&ifilter->linklabel);
av_freep(&ifp->opts.name);
av_frame_side_data_free(&ifp->side_data, &ifp->nb_side_data);
@@ -1085,8 +1057,7 @@ static const AVClass fg_class = {
.category = AV_CLASS_CATEGORY_FILTER,
};
int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
const OutputFilterOptions *opts)
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
{
FilterGraphPriv *fgp;
FilterGraph *fg;
@@ -1097,7 +1068,7 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
fgp = av_mallocz(sizeof(*fgp));
if (!fgp) {
av_freep(graph_desc);
av_freep(&graph_desc);
return AVERROR(ENOMEM);
}
fg = &fgp->fg;
@@ -1108,7 +1079,7 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
} else {
ret = av_dynarray_add_nofree(&filtergraphs, &nb_filtergraphs, fgp);
if (ret < 0) {
av_freep(graph_desc);
av_freep(&graph_desc);
av_freep(&fgp);
return ret;
}
@@ -1117,13 +1088,11 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
}
fg->class = &fg_class;
fg->graph_desc = *graph_desc;
fg->graph_desc = graph_desc;
fgp->disable_conversions = !auto_conversion_filters;
fgp->nb_threads = -1;
fgp->sch = sch;
*graph_desc = NULL;
snprintf(fgp->log_name, sizeof(fgp->log_name), "fc#%d", fg->index);
fgp->frame = av_frame_alloc();
@@ -1143,6 +1112,16 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
if (ret < 0)
goto fail;
for (unsigned i = 0; i < graph->nb_filters; i++) {
const AVFilter *f = graph->filters[i]->filter;
if ((!avfilter_filter_pad_count(f, 0) &&
!(f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) ||
!strcmp(f->name, "apad")) {
fgp->have_sources = 1;
break;
}
}
for (AVFilterInOut *cur = inputs; cur; cur = cur->next) {
InputFilter *const ifilter = ifilter_alloc(fg);
@@ -1175,13 +1154,11 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
cur->pad_idx);
OutputFilter *const ofilter = ofilter_alloc(fg, type);
OutputFilterPriv *ofp;
if (!ofilter) {
ret = AVERROR(ENOMEM);
goto fail;
}
ofp = ofp_from_ofilter(ofilter);
ofilter->linklabel = cur->name;
cur->name = NULL;
@@ -1191,25 +1168,6 @@ int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
ret = AVERROR(ENOMEM);
goto fail;
}
// opts should only be needed in this function to fill fields from filtergraphs
// whose output is meant to be treated as if it was stream, e.g. merged HEIF
// tile groups.
if (opts) {
ofp->flags = opts->flags;
ofp->side_data = opts->side_data;
ofp->nb_side_data = opts->nb_side_data;
ofp->crop_top = opts->crop_top;
ofp->crop_bottom = opts->crop_bottom;
ofp->crop_left = opts->crop_left;
ofp->crop_right = opts->crop_right;
const AVFrameSideData *sd = av_frame_side_data_get(ofp->side_data, ofp->nb_side_data,
AV_FRAME_DATA_DISPLAYMATRIX);
if (sd)
memcpy(ofp->displaymatrix, sd->data, sizeof(ofp->displaymatrix));
}
}
if (!fg->nb_outputs) {
@@ -1237,7 +1195,7 @@ fail:
int fg_create_simple(FilterGraph **pfg,
InputStream *ist,
char **graph_desc,
char *graph_desc,
Scheduler *sch, unsigned sched_idx_enc,
const OutputFilterOptions *opts)
{
@@ -1246,7 +1204,7 @@ int fg_create_simple(FilterGraph **pfg,
FilterGraphPriv *fgp;
int ret;
ret = fg_create(pfg, graph_desc, sch, NULL);
ret = fg_create(pfg, graph_desc, sch);
if (ret < 0)
return ret;
fg = *pfg;
@@ -1262,7 +1220,7 @@ int fg_create_simple(FilterGraph **pfg,
"to have exactly 1 input and 1 output. "
"However, it had %d input(s) and %d output(s). Please adjust, "
"or use a complex filtergraph (-filter_complex) instead.\n",
*graph_desc, fg->nb_inputs, fg->nb_outputs);
graph_desc, fg->nb_inputs, fg->nb_outputs);
return AVERROR(EINVAL);
}
if (fg->outputs[0]->type != type) {
@@ -1287,7 +1245,7 @@ int fg_create_simple(FilterGraph **pfg,
return 0;
}
static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int commit)
static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
{
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
InputStream *ist = NULL;
@@ -1338,20 +1296,15 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int comm
if (!ofilter->bound && ofilter->linklabel &&
!strcmp(ofilter->linklabel, ifilter->linklabel)) {
if (commit) {
av_log(fg, AV_LOG_VERBOSE,
"Binding input with label '%s' to filtergraph output %d:%d\n",
ifilter->linklabel, i, j);
av_log(fg, AV_LOG_VERBOSE,
"Binding input with label '%s' to filtergraph output %d:%d\n",
ifilter->linklabel, i, j);
ret = ifilter_bind_fg(ifp, fg_src, j);
if (ret < 0) {
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
ifilter->linklabel);
return ret;
}
} else
ofp_from_ofilter(ofilter)->needed = 1;
return 0;
ret = ifilter_bind_fg(ifp, fg_src, j);
if (ret < 0)
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
ifilter->linklabel);
return ret;
}
}
}
@@ -1399,38 +1352,10 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int comm
}
ist = input_files[file_idx]->streams[st->index];
if (commit)
av_log(fg, AV_LOG_VERBOSE,
"Binding input with label '%s' to input stream %d:%d\n",
ifilter->linklabel, ist->file->index, ist->index);
av_log(fg, AV_LOG_VERBOSE,
"Binding input with label '%s' to input stream %d:%d\n",
ifilter->linklabel, ist->file->index, ist->index);
} else {
// try finding an unbound filtergraph output
for (int i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg_src = filtergraphs[i];
if (fg == fg_src)
continue;
for (int j = 0; j < fg_src->nb_outputs; j++) {
OutputFilter *ofilter = fg_src->outputs[j];
if (!ofilter->bound) {
if (commit) {
av_log(fg, AV_LOG_VERBOSE,
"Binding unlabeled filtergraph input to filtergraph output %d:%d\n", i, j);
ret = ifilter_bind_fg(ifp, fg_src, j);
if (ret < 0) {
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %d:%d\n", i, j);
return ret;
}
} else
ofp_from_ofilter(ofilter)->needed = 1;
return 0;
}
}
}
ist = ist_find_unused(type);
if (!ist) {
av_log(fg, AV_LOG_FATAL,
@@ -1440,27 +1365,24 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int comm
return AVERROR(EINVAL);
}
if (commit)
av_log(fg, AV_LOG_VERBOSE,
"Binding unlabeled input %d to input stream %d:%d\n",
ifilter->index, ist->file->index, ist->index);
av_log(fg, AV_LOG_VERBOSE,
"Binding unlabeled input %d to input stream %d:%d\n",
ifilter->index, ist->file->index, ist->index);
}
av_assert0(ist);
if (commit) {
ret = ifilter_bind_ist(ifilter, ist, &vs);
if (ret < 0) {
av_log(fg, AV_LOG_ERROR,
"Error binding an input stream to complex filtergraph input %s.\n",
ifilter->name);
return ret;
}
ret = ifilter_bind_ist(ifilter, ist, &vs);
if (ret < 0) {
av_log(fg, AV_LOG_ERROR,
"Error binding an input stream to complex filtergraph input %s.\n",
ifilter->name);
return ret;
}
return 0;
}
static int bind_inputs(FilterGraph *fg, int commit)
static int bind_inputs(FilterGraph *fg)
{
// bind filtergraph inputs to input streams or other filtergraphs
for (int i = 0; i < fg->nb_inputs; i++) {
@@ -1470,7 +1392,7 @@ static int bind_inputs(FilterGraph *fg, int commit)
if (ifp->bound)
continue;
ret = fg_complex_bind_input(fg, &ifp->ifilter, commit);
ret = fg_complex_bind_input(fg, &ifp->ifilter);
if (ret < 0)
return ret;
}
@@ -1483,49 +1405,27 @@ int fg_finalise_bindings(void)
int ret;
for (int i = 0; i < nb_filtergraphs; i++) {
ret = bind_inputs(filtergraphs[i], 0);
ret = bind_inputs(filtergraphs[i]);
if (ret < 0)
return ret;
}
// check that all outputs were bound
for (int i = nb_filtergraphs - 1; i >= 0; i--) {
for (int i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
FilterGraphPriv *fgp = fgp_from_fg(filtergraphs[i]);
for (int j = 0; j < fg->nb_outputs; j++) {
OutputFilter *output = fg->outputs[j];
if (!ofp_from_ofilter(output)->needed) {
if (!fg->is_internal) {
av_log(fg, AV_LOG_FATAL,
"Filter '%s' has output %d (%s) unconnected\n",
output->name, j,
output->linklabel ? (const char *)output->linklabel : "unlabeled");
return AVERROR(EINVAL);
}
av_log(fg, AV_LOG_DEBUG,
"Internal filter '%s' has output %d (%s) unconnected. Removing graph\n",
if (!output->bound) {
av_log(fg, AV_LOG_FATAL,
"Filter '%s' has output %d (%s) unconnected\n",
output->name, j,
output->linklabel ? (const char *)output->linklabel : "unlabeled");
sch_remove_filtergraph(fgp->sch, fgp->sch_idx);
fg_free(&filtergraphs[i]);
nb_filtergraphs--;
if (nb_filtergraphs > 0)
memmove(&filtergraphs[i],
&filtergraphs[i + 1],
(nb_filtergraphs - i) * sizeof(*filtergraphs));
break;
return AVERROR(EINVAL);
}
}
}
for (int i = 0; i < nb_filtergraphs; i++) {
ret = bind_inputs(filtergraphs[i], 1);
if (ret < 0)
return ret;
}
return 0;
}
@@ -1624,57 +1524,7 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
if (ret < 0)
return ret;
if (ofp->flags & OFILTER_FLAG_CROP) {
char crop_buf[64];
snprintf(crop_buf, sizeof(crop_buf), "w=iw-%u-%u:h=ih-%u-%u:x=%u:y=%u",
ofp->crop_left, ofp->crop_right,
ofp->crop_top, ofp->crop_bottom,
ofp->crop_left, ofp->crop_top);
ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf);
if (ret < 0)
return ret;
}
if (ofp->flags & OFILTER_FLAG_AUTOROTATE) {
int32_t *displaymatrix = ofp->displaymatrix;
double theta;
theta = get_rotation(displaymatrix);
if (fabs(theta - 90) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose",
displaymatrix[3] > 0 ? "cclock_flip" : "clock");
} else if (fabs(theta - 180) < 1.0) {
if (displaymatrix[0] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
if (ret < 0)
return ret;
}
if (displaymatrix[4] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
}
} else if (fabs(theta - 270) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose",
displaymatrix[3] < 0 ? "clock_flip" : "cclock");
} else if (fabs(theta) > 1.0) {
char rotate_buf[64];
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
} else if (fabs(theta) < 1.0) {
if (displaymatrix && displaymatrix[4] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
}
}
if (ret < 0)
return ret;
av_frame_side_data_remove(&ofp->side_data, &ofp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
}
if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE) &&
// skip add scale for hardware format
!(ofp->format != AV_PIX_FMT_NONE &&
av_pix_fmt_desc_get(ofp->format)->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) {
char args[255];
AVFilterContext *filter;
const AVDictionaryEntry *e = NULL;
@@ -1698,12 +1548,11 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
}
av_assert0(!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT) ||
ofp->format != AV_PIX_FMT_NONE || !ofp->pix_fmts);
ofp->format != AV_PIX_FMT_NONE || !ofp->formats);
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
choose_pix_fmts(ofp, &bprint);
choose_color_spaces(ofp, &bprint);
choose_color_ranges(ofp, &bprint);
choose_alpha_modes(ofp, &bprint);
if (!av_bprint_is_complete(&bprint))
return AVERROR(ENOMEM);
@@ -1799,8 +1648,10 @@ static int configure_output_audio_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
pad_idx = 0;
}
if (ofilter->apad)
if (ofilter->apad) {
AUTO_INSERT_FILTER("-apad", "apad", ofilter->apad);
fgp->have_sources = 1;
}
snprintf(name, sizeof(name), "trim for output %s", ofilter->output_name);
ret = insert_trim(fgp, ofp->trim_start_us, ofp->trim_duration_us,
@@ -1872,7 +1723,6 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
ifp->sample_aspect_ratio : (AVRational){ 0, 1 };
par->color_space = ifp->color_space;
par->color_range = ifp->color_range;
par->alpha_mode = ifp->alpha_mode;
par->hw_frames_ctx = ifp->hw_frames_ctx;
par->side_data = ifp->side_data;
par->nb_side_data = ifp->nb_side_data;
@@ -2150,7 +2000,6 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
ofp->height = av_buffersink_get_h(sink);
ofp->color_space = av_buffersink_get_colorspace(sink);
ofp->color_range = av_buffersink_get_color_range(sink);
ofp->alpha_mode = av_buffersink_get_alpha_mode(sink);
// If the timing parameters are not locked yet, get the tentative values
// here but don't lock them. They will only be used if no output frames
@@ -2169,11 +2018,12 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout);
if (ret < 0)
goto fail;
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
sd = av_buffersink_get_side_data(sink, &nb_sd);
if (nb_sd)
for (int j = 0; j < nb_sd; j++) {
ret = av_frame_side_data_clone(&ofp->side_data, &ofp->nb_side_data,
sd[j], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
sd[j], 0);
if (ret < 0) {
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
goto fail;
@@ -2246,7 +2096,6 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
ifp->sample_aspect_ratio = frame->sample_aspect_ratio;
ifp->color_space = frame->colorspace;
ifp->color_range = frame->color_range;
ifp->alpha_mode = frame->alpha_mode;
ifp->sample_rate = frame->sample_rate;
ret = av_channel_layout_copy(&ifp->ch_layout, &frame->ch_layout);
@@ -2268,11 +2117,8 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
}
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
if (sd) {
if (sd)
memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix));
if (ifp->opts.flags & IFILTER_FLAG_AUTOROTATE)
av_frame_side_data_remove(&ifp->side_data, &ifp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
}
ifp->displaymatrix_present = !!sd;
/* Copy downmix related side data to InputFilterPriv so it may be propagated
@@ -2291,27 +2137,6 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
return 0;
}
static int ifilter_parameters_from_ofilter(InputFilter *ifilter, OutputFilter *ofilter)
{
const OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
if (!ifp->opts.framerate.num) {
ifp->opts.framerate = ofp->fps.framerate;
if (ifp->opts.framerate.num > 0 && ifp->opts.framerate.den > 0)
ifp->opts.flags |= IFILTER_FLAG_CFR;
}
for (int i = 0; i < ofp->nb_side_data; i++) {
int ret = av_frame_side_data_clone(&ifp->side_data, &ifp->nb_side_data,
ofp->side_data[i], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
if (ret < 0)
return ret;
}
return 0;
}
int filtergraph_is_simple(const FilterGraph *fg)
{
const FilterGraphPriv *fgp = cfgp_from_cfg(fg);
@@ -2482,23 +2307,6 @@ early_exit:
return float_pts;
}
static int64_t median3(int64_t a, int64_t b, int64_t c)
{
int64_t max2, min2, m;
if (a >= b) {
max2 = a;
min2 = b;
} else {
max2 = b;
min2 = a;
}
m = (c >= max2) ? max2 : c;
return (m >= min2) ? m : min2;
}
/* Convert frame timestamps to the encoder timebase and decide how many times
* should this (and possibly previous) frame be repeated in order to conform to
* desired target framerate (if any).
@@ -2511,9 +2319,9 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
double delta0, delta, sync_ipts, duration;
if (!frame) {
*nb_frames_prev = *nb_frames = median3(fps->frames_prev_hist[0],
fps->frames_prev_hist[1],
fps->frames_prev_hist[2]);
*nb_frames_prev = *nb_frames = mid_pred(fps->frames_prev_hist[0],
fps->frames_prev_hist[1],
fps->frames_prev_hist[2]);
if (!*nb_frames && fps->last_dropped) {
atomic_fetch_add(&ofilter->nb_frames_drop, 1);
@@ -2540,7 +2348,11 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
if (delta0 < 0 &&
delta > 0 &&
fps->vsync_method != VSYNC_PASSTHROUGH) {
fps->vsync_method != VSYNC_PASSTHROUGH
#if FFMPEG_OPT_VSYNC_DROP
&& fps->vsync_method != VSYNC_DROP
#endif
) {
if (delta0 < -0.6) {
av_log(ofp, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0);
} else
@@ -2558,7 +2370,6 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
delta0 = 0;
ofp->next_pts = llrint(sync_ipts);
}
av_fallthrough;
case VSYNC_CFR:
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
if (frame_drop_threshold && delta < frame_drop_threshold && fps->frame_number) {
@@ -2579,6 +2390,9 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
ofp->next_pts = llrint(sync_ipts);
frame->duration = llrint(duration);
break;
#if FFMPEG_OPT_VSYNC_DROP
case VSYNC_DROP:
#endif
case VSYNC_PASSTHROUGH:
ofp->next_pts = llrint(sync_ipts);
frame->duration = llrint(duration);
@@ -2620,16 +2434,6 @@ finish:
fps->dropped_keyframe |= fps->last_dropped && (frame->flags & AV_FRAME_FLAG_KEY);
}
static void close_input(InputFilterPriv *ifp)
{
FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
if (!ifp->eof) {
sch_filter_receive_finish(fgp->sch, fgp->sch_idx, ifp->ifilter.index);
ifp->eof = 1;
}
}
static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
{
FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
@@ -2654,17 +2458,16 @@ static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
if (ret < 0)
return ret;
}
av_frame_side_data_free(&frame->side_data, &frame->nb_side_data);
ret = clone_side_data(&frame->side_data, &frame->nb_side_data,
ofp->side_data, ofp->nb_side_data, 0);
if (ret < 0)
return ret;
fd = frame_data(frame);
if (!fd)
return AVERROR(ENOMEM);
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
ofp->side_data, ofp->nb_side_data, 0);
if (ret < 0)
return ret;
fd->frame_rate_filter = ofp->fps.framerate;
av_assert0(!frame->buf[0]);
@@ -2819,16 +2622,6 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
return AVERROR(ENOMEM);
}
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
if (!fgt->got_frame) {
ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
ofp->side_data, ofp->nb_side_data, 0);
if (ret < 0) {
av_frame_unref(frame);
return ret;
}
}
fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
// only use bits_per_raw_sample passed through from the decoder
@@ -2860,6 +2653,7 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
AVFrame *frame)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
int did_step = 0;
// graph not configured, just select the input to request
if (!fgt->graph) {
@@ -2878,7 +2672,7 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
return AVERROR_BUG;
}
if (fgp->nb_outputs_done < fg->nb_outputs) {
while (fgp->nb_outputs_done < fg->nb_outputs) {
int ret;
/* Reap all buffers present in the buffer sinks */
@@ -2893,6 +2687,9 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
}
}
// return after one iteration, so that scheduler can rate-control us
if (did_step && fgp->have_sources)
return 0;
ret = avfilter_graph_request_oldest(fgt->graph);
if (ret == AVERROR(EAGAIN)) {
@@ -2909,8 +2706,7 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
}
fgt->next_in = fg->nb_inputs;
// return so that scheduler can rate-control us
return 0;
did_step = 1;
}
return AVERROR_EOF;
@@ -3013,7 +2809,6 @@ static int send_eof(FilterGraphThread *fgt, InputFilter *ifilter,
ifp->sample_aspect_ratio = ifp->opts.fallback->sample_aspect_ratio;
ifp->color_space = ifp->opts.fallback->colorspace;
ifp->color_range = ifp->opts.fallback->color_range;
ifp->alpha_mode = ifp->opts.fallback->alpha_mode;
ifp->time_base = ifp->opts.fallback->time_base;
ret = av_channel_layout_copy(&ifp->ch_layout,
@@ -3064,7 +2859,6 @@ static const char *unknown_if_null(const char *str)
static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
InputFilter *ifilter, AVFrame *frame)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
FrameData *fd;
AVFrameSideData *sd;
@@ -3083,8 +2877,7 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
ifp->width != frame->width ||
ifp->height != frame->height ||
ifp->color_space != frame->colorspace ||
ifp->color_range != frame->color_range ||
ifp->alpha_mode != frame->alpha_mode)
ifp->color_range != frame->color_range)
need_reinit |= VIDEO_CHANGED;
break;
}
@@ -3121,14 +2914,6 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
ret = ifilter_parameters_from_frame(ifilter, frame);
if (ret < 0)
return ret;
/* Inputs bound to a filtergraph output will have some fields unset.
* Handle them here */
if (ifp->ofilter_src) {
ret = ifilter_parameters_from_ofilter(ifilter, ifp->ofilter_src);
if (ret < 0)
return ret;
}
}
/* (re)init the graph if possible, otherwise buffer the frame and return */
@@ -3166,11 +2951,9 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
const char *pixel_format_name = av_get_pix_fmt_name(frame->format);
const char *color_space_name = av_color_space_name(frame->colorspace);
const char *color_range_name = av_color_range_name(frame->color_range);
const char *alpha_mode = av_alpha_mode_name(frame->alpha_mode);
av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, %s alpha, ",
av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, ",
unknown_if_null(pixel_format_name), unknown_if_null(color_range_name),
unknown_if_null(color_space_name), frame->width, frame->height,
unknown_if_null(alpha_mode));
unknown_if_null(color_space_name), frame->width, frame->height);
}
if (need_reinit & MATRIX_CHANGED)
av_bprintf(&reason, "display matrix changed, ");
@@ -3181,11 +2964,6 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
if (reason.len > 1)
reason.str[reason.len - 2] = '\0'; // remove last comma
av_log(fg, AV_LOG_INFO, "Reconfiguring filter graph%s%s\n", reason.len ? " because " : "", reason.str);
} else {
/* Choke all input to avoid buffering excessive frames while the
* initial filter graph is being configured, and before we have a
* preferred input */
sch_filter_choke_inputs(fgp->sch, fgp->sch_idx);
}
ret = configure_filtergraph(fg, fgt);
@@ -3323,6 +3101,8 @@ static int filter_thread(void *arg)
o = (intptr_t)fgt.frame->opaque;
o = (intptr_t)fgt.frame->opaque;
// message on the control stream
if (input_idx == fg->nb_inputs) {
FilterCommand *fc;
@@ -3354,7 +3134,7 @@ static int filter_thread(void *arg)
if (ret == AVERROR_EOF) {
av_log(fg, AV_LOG_VERBOSE, "Input %u no longer accepts new data\n",
input_idx);
close_input(ifp);
sch_filter_receive_finish(fgp->sch, fgp->sch_idx, input_idx);
continue;
}
if (ret < 0)
@@ -3373,13 +3153,6 @@ read_frames:
av_err2str(ret));
goto finish;
}
// ensure all inputs no longer accepting data are closed
for (int i = 0; fgt.graph && i < fg->nb_inputs; i++) {
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
if (av_buffersrc_get_status(ifp->ifilter.filter))
close_input(ifp);
}
}
for (unsigned i = 0; i < fg->nb_outputs; i++) {
+5
View File
@@ -139,6 +139,11 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
{
OutputStream *ost = &ms->ost;
#if FFMPEG_OPT_VSYNC_DROP
if (ost->type == AVMEDIA_TYPE_VIDEO && ms->ts_drop)
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
#endif
// rescale timestamps to the stream timebase
if (ost->type == AVMEDIA_TYPE_AUDIO && !ost->enc) {
// use av_rescale_delta() for streamcopying audio, to preserve
+3
View File
@@ -81,6 +81,9 @@ typedef struct MuxStream {
int copy_initial_nonkeyframes;
int copy_prior_start;
int streamcopy_started;
#if FFMPEG_OPT_VSYNC_DROP
int ts_drop;
#endif
AVRational frame_rate;
AVRational max_frame_rate;
+93 -102
View File
@@ -417,19 +417,45 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
OutputStream *ost, char **dst)
{
const char *filters = NULL;
#if FFMPEG_OPT_FILTER_SCRIPT
const char *filters_script = NULL;
opt_match_per_stream_str(ost, &o->filter_scripts, oc, ost->st, &filters_script);
#endif
opt_match_per_stream_str(ost, &o->filters, oc, ost->st, &filters);
if (!ost->ist) {
if (filters) {
if (
#if FFMPEG_OPT_FILTER_SCRIPT
filters_script ||
#endif
filters) {
av_log(ost, AV_LOG_ERROR,
"Filtergraph '%s' was specified for a stream fed from a complex "
"%s '%s' was specified for a stream fed from a complex "
"filtergraph. Simple and complex filtering cannot be used "
"together for the same stream.\n", filters);
"together for the same stream.\n",
#if FFMPEG_OPT_FILTER_SCRIPT
filters ? "Filtergraph" : "Filtergraph script",
filters ? filters : filters_script
#else
"Filtergraph", filters
#endif
);
return AVERROR(EINVAL);
}
return 0;
}
#if FFMPEG_OPT_FILTER_SCRIPT
if (filters_script && filters) {
av_log(ost, AV_LOG_ERROR, "Both -filter and -filter_script set\n");
return AVERROR(EINVAL);
}
if (filters_script)
*dst = file_read(filters_script);
else
#endif
if (filters)
*dst = av_strdup(filters);
else
@@ -456,9 +482,9 @@ static int parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str)
return 0;
}
static int pixfmt_in_list(const enum AVPixelFormat *formats, enum AVPixelFormat format)
static int fmt_in_list(const int *formats, int format)
{
for (; *formats != AV_PIX_FMT_NONE; formats++)
for (; *formats != -1; formats++)
if (*formats == format)
return 1;
return 0;
@@ -518,7 +544,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
* endianness by av_get_pix_fmt();
* the following code handles the case when the native endianness is not
* supported by the encoder, but the other one is */
if (fmts && !pixfmt_in_list(fmts, fmt)) {
if (fmts && !fmt_in_list(fmts, fmt)) {
const char *name_canonical = av_get_pix_fmt_name(fmt);
int len = strlen(name_canonical);
@@ -531,7 +557,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
snprintf(name_other, sizeof(name_other), "%s%ce",
name, name_canonical[len - 2] == 'l' ? 'b' : 'l');
fmt_other = av_get_pix_fmt(name_other);
if (fmt_other != AV_PIX_FMT_NONE && pixfmt_in_list(fmts, fmt_other)) {
if (fmt_other != AV_PIX_FMT_NONE && fmt_in_list(fmts, fmt_other)) {
av_log(ost, AV_LOG_VERBOSE, "Mapping pixel format %s->%s\n",
name, name_other);
fmt = fmt_other;
@@ -539,7 +565,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
}
}
if (fmts && !pixfmt_in_list(fmts, fmt))
if (fmts && !fmt_in_list(fmts, fmt))
fmt = choose_pixel_fmt(ost->enc->enc_ctx, fmt);
return fmt;
@@ -704,14 +730,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
AV_OPT_SEARCH_CHILDREN) > 0)
av_opt_set(video_enc, "stats", logfilename,
AV_OPT_SEARCH_CHILDREN);
} else if (!strcmp(video_enc->codec->name, "libx265")) {
if (av_opt_is_set_to_default_by_name(video_enc, "x265-stats",
AV_OPT_SEARCH_CHILDREN) > 0)
av_opt_set(video_enc, "x265-stats", logfilename,
AV_OPT_SEARCH_CHILDREN);
} else {
if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
char *logbuffer = read_file_to_string(logfilename);
char *logbuffer = file_read(logfilename);
if (!logbuffer) {
av_log(ost, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
@@ -735,10 +756,21 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
opt_match_per_stream_int(ost, &o->force_fps, oc, st, &ms->force_fps);
#if FFMPEG_OPT_TOP
ost->top_field_first = -1;
opt_match_per_stream_int(ost, &o->top_field_first, oc, st, &ost->top_field_first);
if (ost->top_field_first >= 0)
av_log(ost, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n");
#endif
#if FFMPEG_OPT_VSYNC
*vsync_method = video_sync_method;
#else
*vsync_method = VSYNC_AUTO;
#endif
opt_match_per_stream_str(ost, &o->fps_mode, oc, st, &fps_mode);
if (fps_mode) {
ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index);
ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index, 0);
if (ret < 0)
return ret;
}
@@ -773,6 +805,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
*vsync_method = VSYNC_VSCFR;
}
}
#if FFMPEG_OPT_VSYNC_DROP
if (*vsync_method == VSYNC_DROP)
ms->ts_drop = 1;
#endif
}
return 0;
@@ -881,7 +917,6 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
.height = enc_ctx->height,
.color_space = enc_ctx->colorspace,
.color_range = enc_ctx->color_range,
.alpha_mode = enc_ctx->alpha_mode,
.vsync_method = vsync_method,
.frame_rate = ms->frame_rate,
.max_frame_rate = ms->max_frame_rate,
@@ -908,7 +943,7 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
if (!keep_pix_fmt) {
ret = avcodec_get_supported_config(enc_ctx, NULL,
AV_CODEC_CONFIG_PIX_FORMAT, 0,
(const void **) &opts.pix_fmts, NULL);
(const void **) &opts.formats, NULL);
if (ret < 0)
return ret;
}
@@ -929,15 +964,10 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
(const void **) &opts.color_ranges, NULL);
if (ret < 0)
return ret;
ret = avcodec_get_supported_config(enc_ctx, NULL,
AV_CODEC_CONFIG_ALPHA_MODE, 0,
(const void **) &opts.alpha_modes, NULL);
if (ret < 0)
return ret;
} else {
ret = avcodec_get_supported_config(enc_ctx, NULL,
AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
(const void **) &opts.sample_fmts, NULL);
(const void **) &opts.formats, NULL);
if (ret < 0)
return ret;
ret = avcodec_get_supported_config(enc_ctx, NULL,
@@ -967,7 +997,7 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
ost->filter = ofilter;
ret = ofilter_bind_enc(ofilter, ms->sch_idx_enc, &opts);
} else {
ret = fg_create_simple(&ost->fg_simple, ost->ist, &filters,
ret = fg_create_simple(&ost->fg_simple, ost->ist, filters,
mux->sch, ms->sch_idx_enc, &opts);
if (ret >= 0)
ost->filter = ost->fg_simple->outputs[0];
@@ -999,12 +1029,28 @@ static int streamcopy_init(const OptionsContext *o, const Muxer *mux,
int ret = 0;
const char *filters = NULL;
#if FFMPEG_OPT_FILTER_SCRIPT
const char *filters_script = NULL;
opt_match_per_stream_str(ost, &o->filter_scripts, mux->fc, ost->st, &filters_script);
#endif
opt_match_per_stream_str(ost, &o->filters, mux->fc, ost->st, &filters);
if (filters) {
if (
#if FFMPEG_OPT_FILTER_SCRIPT
filters_script ||
#endif
filters) {
av_log(ost, AV_LOG_ERROR,
"Filtergraph '%s' was specified, but codec copy was selected. "
"Filtering and streamcopy cannot be used together.\n", filters);
"%s '%s' was specified, but codec copy was selected. "
"Filtering and streamcopy cannot be used together.\n",
#if FFMPEG_OPT_FILTER_SCRIPT
filters ? "Filtergraph" : "Filtergraph script",
filters ? filters : filters_script
#else
"Filtergraph", filters
#endif
);
return AVERROR(EINVAL);
}
@@ -1344,11 +1390,20 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
q = (AVRational){ ENC_TIME_BASE_FILTER, 0 };
} else {
ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL);
if (ret < 0 || q.den <= 0 || q.num < 0) {
if (ret < 0 || q.den <= 0
#if !FFMPEG_OPT_ENC_TIME_BASE_NUM
|| q.num < 0
#endif
) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base);
ret = ret < 0 ? ret : AVERROR(EINVAL);
goto fail;
}
#if FFMPEG_OPT_ENC_TIME_BASE_NUM
if (q.num < 0)
av_log(ost, AV_LOG_WARNING, "-enc_time_base -1 is deprecated,"
" use -enc_time_base demux\n");
#endif
}
enc_tb = q;
@@ -1465,8 +1520,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc)
ost->enc->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
if (oc->oformat->flags & AVFMT_FIXED_FRAMESIZE && ost->enc)
ost->enc->enc_ctx->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
opt_match_per_stream_int(ost, &o->copy_initial_nonkeyframes,
oc, st, &ms->copy_initial_nonkeyframes);
@@ -1539,7 +1592,6 @@ fail:
static int map_auto_video(Muxer *mux, const OptionsContext *o)
{
AVFormatContext *oc = mux->fc;
InputStreamGroup *best_istg = NULL;
InputStream *best_ist = NULL;
int64_t best_score = 0;
int qcr;
@@ -1551,49 +1603,14 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
for (int j = 0; j < nb_input_files; j++) {
InputFile *ifile = input_files[j];
InputStreamGroup *file_best_istg = NULL;
InputStream *file_best_ist = NULL;
int64_t file_best_score = 0;
for (int i = 0; i < ifile->nb_stream_groups; i++) {
InputStreamGroup *istg = ifile->stream_groups[i];
int64_t score = 0;
if (!istg->fg)
continue;
for (int j = 0; j < istg->stg->nb_streams; j++) {
AVStream *st = istg->stg->streams[j];
if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
score = 100000000;
break;
}
}
switch (istg->stg->type) {
case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
const AVStreamGroupTileGrid *tg = istg->stg->params.tile_grid;
score += tg->width * (int64_t)tg->height
+ 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
break;
}
default:
continue;
}
if (score > file_best_score) {
file_best_score = score;
file_best_istg = istg;
}
}
for (int i = 0; i < ifile->nb_streams; i++) {
InputStream *ist = ifile->streams[i];
const AVCodecDescriptor *desc = avcodec_descriptor_get(ist->st->codecpar->codec_id);
int64_t score;
if (ist->user_set_discard == AVDISCARD_ALL ||
ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
(desc && (desc->props & AV_CODEC_PROP_ENHANCEMENT)))
ist->st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
score = ist->st->codecpar->width * (int64_t)ist->st->codecpar->height
@@ -1607,15 +1624,6 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
continue;
file_best_score = score;
file_best_ist = ist;
file_best_istg = NULL;
}
}
if (file_best_istg) {
file_best_score -= 5000000*!!(file_best_istg->stg->disposition & AV_DISPOSITION_DEFAULT);
if (file_best_score > best_score) {
best_score = file_best_score;
best_istg = file_best_istg;
best_ist = NULL;
}
}
if (file_best_ist) {
@@ -1625,19 +1633,9 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
if (file_best_score > best_score) {
best_score = file_best_score;
best_ist = file_best_ist;
best_istg = NULL;
}
}
}
if (best_istg) {
FilterGraph *fg = best_istg->fg;
OutputFilter *ofilter = fg->outputs[0];
av_assert0(fg->nb_outputs == 1);
av_log(mux, AV_LOG_VERBOSE, "Creating output stream from stream group derived complex filtergraph %d.\n", fg->index);
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL, ofilter, NULL, NULL);
}
if (best_ist)
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
@@ -2063,8 +2061,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
nb_interleaved += IS_INTERLEAVED(type);
nb_av_enc += IS_AV_ENC(ost, type);
nb_audio_fs += (ost->enc && type == AVMEDIA_TYPE_AUDIO &&
(!(ost->enc->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) ||
(ost->enc->enc_ctx->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)));
!(ost->enc->enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE));
limit_frames |= ms->max_frames < INT64_MAX;
limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
@@ -2489,10 +2486,6 @@ static int of_map_group(Muxer *mux, AVDictionary **dict, AVBPrint *bp, const cha
}
break;
}
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_TREF:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
break;
default:
av_log(mux, AV_LOG_ERROR, "Unsupported mapped group type %d.\n", stg->type);
ret = AVERROR(EINVAL);
@@ -2515,10 +2508,6 @@ static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
{ .i64 = AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT }, .unit = "type" },
{ "iamf_mix_presentation", NULL, 0, AV_OPT_TYPE_CONST,
{ .i64 = AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION }, .unit = "type" },
{ "lcevc", NULL, 0, AV_OPT_TYPE_CONST,
{ .i64 = AV_STREAM_GROUP_PARAMS_LCEVC }, .unit = "type" },
{ "tref", NULL, 0, AV_OPT_TYPE_CONST,
{ .i64 = AV_STREAM_GROUP_PARAMS_TREF }, .unit = "type" },
{ NULL },
};
const AVClass class = {
@@ -2593,10 +2582,6 @@ static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
ret = avformat_stream_group_add_stream(stg, oc->streams[idx]);
if (ret < 0)
goto end;
OutputStream *ost = mux->of.streams[idx];
if (ost->enc && (type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT ||
type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION))
ost->enc->enc_ctx->flags2 |= AV_CODEC_FLAG2_FIXED_FRAME_SIZE;
}
while (e = av_dict_get(dict, "stg", e, 0)) {
char *endptr;
@@ -2621,6 +2606,8 @@ static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
ret = of_parse_iamf_submixes(mux, stg, ptr);
break;
default:
av_log(mux, AV_LOG_FATAL, "Unknown group type %d.\n", type);
ret = AVERROR(EINVAL);
break;
}
@@ -3227,8 +3214,12 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
// parse it only for static kf timings
} else if (!strcmp(forced_keyframes, "source")) {
ost->kf.type = KF_FORCE_SOURCE;
} else if (!strcmp(forced_keyframes, "scd_metadata")) {
ost->kf.type = KF_FORCE_SCD_METADATA;
#if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP
} else if (!strcmp(forced_keyframes, "source_no_drop")) {
av_log(ost, AV_LOG_WARNING, "The 'source_no_drop' value for "
"-force_key_frames is deprecated, use just 'source'\n");
ost->kf.type = KF_FORCE_SOURCE;
#endif
} else {
int ret = parse_forced_key_frames(ost, &ost->kf, mux, forced_keyframes);
if (ret < 0)
+111 -113
View File
@@ -56,6 +56,9 @@ char *vstats_filename;
float dts_delta_threshold = 10;
float dts_error_threshold = 3600*30;
#if FFMPEG_OPT_VSYNC
enum VideoSyncMethod video_sync_method = VSYNC_AUTO;
#endif
float frame_drop_threshold = 0;
int do_benchmark = 0;
int do_benchmark_all = 0;
@@ -239,70 +242,6 @@ OPT_MATCH_PER_STREAM(int, int, OPT_TYPE_INT, i);
OPT_MATCH_PER_STREAM(int64, int64_t, OPT_TYPE_INT64, i64);
OPT_MATCH_PER_STREAM(dbl, double, OPT_TYPE_DOUBLE, dbl);
static unsigned opt_match_per_stream_group(void *logctx, enum OptionType type,
const SpecifierOptList *sol,
AVFormatContext *fc, AVStreamGroup *stg)
{
int matches = 0, match_idx = -1;
av_assert0((type == sol->type) || !sol->nb_opt);
for (int i = 0; i < sol->nb_opt; i++) {
const StreamSpecifier *ss = &sol->opt[i].stream_spec;
if (stream_group_specifier_match(ss, fc, stg, logctx)) {
match_idx = i;
matches++;
}
}
if (matches > 1 && sol->opt_canon) {
const SpecifierOpt *so = &sol->opt[match_idx];
const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";
char namestr[128] = "";
char optval_buf[32];
const char *optval = optval_buf;
snprintf(namestr, sizeof(namestr), "-%s", sol->opt_canon->name);
if (sol->opt_canon->flags & OPT_HAS_ALT) {
const char * const *names_alt = sol->opt_canon->u1.names_alt;
for (int i = 0; names_alt[i]; i++)
av_strlcatf(namestr, sizeof(namestr), "/-%s", names_alt[i]);
}
switch (sol->type) {
case OPT_TYPE_STRING: optval = so->u.str; break;
case OPT_TYPE_INT: snprintf(optval_buf, sizeof(optval_buf), "%d", so->u.i); break;
case OPT_TYPE_INT64: snprintf(optval_buf, sizeof(optval_buf), "%"PRId64, so->u.i64); break;
case OPT_TYPE_FLOAT: snprintf(optval_buf, sizeof(optval_buf), "%f", so->u.f); break;
case OPT_TYPE_DOUBLE: snprintf(optval_buf, sizeof(optval_buf), "%f", so->u.dbl); break;
default: av_assert0(0);
}
av_log(logctx, AV_LOG_WARNING, "Multiple %s options specified for "
"stream group %d, only the last option '-%s%s%s %s' will be used.\n",
namestr, stg->index, sol->opt_canon->name, spec[0] ? ":" : "",
spec, optval);
}
return match_idx + 1;
}
#define OPT_MATCH_PER_STREAM_GROUP(name, type, opt_type, m) \
void opt_match_per_stream_group_ ## name(void *logctx, const SpecifierOptList *sol, \
AVFormatContext *fc, AVStreamGroup *stg, type *out) \
{ \
unsigned ret = opt_match_per_stream_group(logctx, opt_type, sol, fc, stg); \
if (ret > 0) \
*out = sol->opt[ret - 1].u.m; \
}
OPT_MATCH_PER_STREAM_GROUP(str, const char *, OPT_TYPE_STRING, str);
OPT_MATCH_PER_STREAM_GROUP(int, int, OPT_TYPE_INT, i);
OPT_MATCH_PER_STREAM_GROUP(int64, int64_t, OPT_TYPE_INT64, i64);
OPT_MATCH_PER_STREAM_GROUP(dbl, double, OPT_TYPE_DOUBLE, dbl);
int view_specifier_parse(const char **pspec, ViewSpecifier *vs)
{
const char *spec = *pspec;
@@ -356,17 +295,38 @@ int view_specifier_parse(const char **pspec, ViewSpecifier *vs)
return 0;
}
int parse_and_set_vsync(const char *arg, enum VideoSyncMethod *vsync_var, int file_idx, int st_idx)
int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global)
{
if (!av_strcasecmp(arg, "cfr")) *vsync_var = VSYNC_CFR;
else if (!av_strcasecmp(arg, "vfr")) *vsync_var = VSYNC_VFR;
else if (!av_strcasecmp(arg, "passthrough")) *vsync_var = VSYNC_PASSTHROUGH;
else if (!av_strcasecmp(arg, "auto")) *vsync_var = VSYNC_AUTO;
else {
#if FFMPEG_OPT_VSYNC_DROP
else if (!av_strcasecmp(arg, "drop")) {
av_log(NULL, AV_LOG_WARNING, "-vsync/fps_mode drop is deprecated\n");
*vsync_var = VSYNC_DROP;
}
#endif
else if (!is_global && !av_strcasecmp(arg, "auto")) *vsync_var = VSYNC_AUTO;
else if (!is_global) {
av_log(NULL, AV_LOG_FATAL, "Invalid value %s specified for fps_mode of #%d:%d.\n", arg, file_idx, st_idx);
return AVERROR(EINVAL);
}
#if FFMPEG_OPT_VSYNC
if (is_global && *vsync_var == VSYNC_AUTO) {
int ret;
double num;
ret = parse_number("vsync", arg, OPT_TYPE_INT, VSYNC_AUTO, VSYNC_VFR, &num);
if (ret < 0)
return ret;
video_sync_method = num;
av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated,"
" use a string argument as described in the manual.\n");
}
#endif
return 0;
}
@@ -544,10 +504,8 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
}
if (arg[0] == '[') {
ViewSpecifier vs;
/* this mapping refers to lavfi output */
const char *c = arg + 1;
char *endptr;
ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps);
if (ret < 0)
@@ -560,27 +518,6 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
ret = AVERROR(EINVAL);
goto fail;
}
arg++;
m->group_index = -1;
file_idx = strtol(arg, &endptr, 0);
if (file_idx >= nb_input_files || file_idx < 0)
goto end;
arg = endptr;
ret = stream_specifier_parse(&ss, *arg == ':' ? arg + 1 : arg, 1, NULL);
if (ret < 0)
goto end;
arg = ss.remainder ? ss.remainder : "";
ret = view_specifier_parse(&arg, &vs);
if (ret < 0 || (*arg && strcmp(arg, "]")))
goto end;
m->file_index = file_idx;
m->stream_index = ss.idx;
m->group_index = ss.stream_list == STREAM_LIST_GROUP_IDX ? ss.list_id : -1;
} else {
ViewSpecifier vs;
char *endptr;
@@ -621,9 +558,6 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
for (i = 0; i < o->nb_stream_maps; i++) {
m = &o->stream_maps[i];
if (file_idx == m->file_index &&
!m->linklabel &&
m->stream_index >= 0 &&
m->stream_index < input_files[m->file_index]->nb_streams &&
stream_specifier_match(&ss,
input_files[m->file_index]->ctx,
input_files[m->file_index]->ctx->streams[m->stream_index],
@@ -649,7 +583,6 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
m->file_index = file_idx;
m->stream_index = i;
m->group_index = ss.stream_list == STREAM_LIST_GROUP_IDX ? ss.list_id : -1;
m->vs = vs;
}
}
@@ -669,7 +602,6 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
goto fail;
}
}
end:
ret = 0;
fail:
stream_specifier_uninit(&ss);
@@ -1089,12 +1021,6 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
char filename[1000], line[1000], tmp_line[1000];
const char *codec_name = NULL;
int ret = 0;
int depth = o->depth;
if (depth > 2) {
av_log(NULL, AV_LOG_ERROR, "too deep recursion\n");
return AVERROR(EINVAL);
}
codec_name = opt_match_per_type_str(&o->codec_names, *opt);
@@ -1106,7 +1032,6 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
return AVERROR(ENOENT);
}
o->depth ++;
while (fgets(line, sizeof(line), f)) {
char *key = tmp_line, *value, *endptr;
@@ -1125,8 +1050,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
else if (!strcmp(key, "vcodec")) opt_video_codec (o, key, value);
else if (!strcmp(key, "scodec")) opt_subtitle_codec(o, key, value);
else if (!strcmp(key, "dcodec")) opt_data_codec (o, key, value);
else if ((parse_option(o, key, value, options) < 0) &&
(opt_default_new(o, key, value) < 0)) {
else if (opt_default_new(o, key, value) < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n",
filename, line, key, value);
ret = AVERROR(EINVAL);
@@ -1135,7 +1059,6 @@ static int opt_preset(void *optctx, const char *opt, const char *arg)
}
fail:
o->depth = depth;
fclose(f);
return ret;
@@ -1210,6 +1133,14 @@ static int opt_audio_filters(void *optctx, const char *opt, const char *arg)
return parse_option(o, "filter:a", arg, options);
}
#if FFMPEG_OPT_VSYNC
static int opt_vsync(void *optctx, const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_WARNING, "-vsync is deprecated. Use -fps_mode\n");
return parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1);
}
#endif
static int opt_timecode(void *optctx, const char *opt, const char *arg)
{
OptionsContext *o = optctx;
@@ -1250,6 +1181,31 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg)
return 0;
}
#if FFMPEG_OPT_FILTER_SCRIPT
static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg)
{
GlobalOptionsContext *go = optctx;
char *graph_desc;
int ret;
graph_desc = file_read(arg);
if (!graph_desc)
return AVERROR(EINVAL);
av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -/filter_complex %s instead\n",
opt, arg);
ret = GROW_ARRAY(go->filtergraphs, go->nb_filtergraphs);
if (ret < 0) {
av_freep(&graph_desc);
return ret;
}
go->filtergraphs[go->nb_filtergraphs - 1] = graph_desc;
return 0;
}
#endif
void show_help_default(const char *opt, const char *arg)
{
int show_advanced = 0, show_avoptions = 0;
@@ -1450,7 +1406,7 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch)
/* create complex filtergraphs */
for (int i = 0; i < go.nb_filtergraphs; i++) {
ret = fg_create(NULL, &go.filtergraphs[i], sch, NULL);
ret = fg_create(NULL, go.filtergraphs[i], sch);
go.filtergraphs[i] = NULL;
if (ret < 0)
goto fail;
@@ -1540,6 +1496,22 @@ int opt_timelimit(void *optctx, const char *opt, const char *arg)
return 0;
}
#if FFMPEG_OPT_QPHIST
static int opt_qphist(void *optctx, const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_WARNING, "Option -%s is deprecated and has no effect\n", opt);
return 0;
}
#endif
#if FFMPEG_OPT_ADRIFT_THRESHOLD
static int opt_adrift_threshold(void *optctx, const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_WARNING, "Option -%s is deprecated and has no effect\n", opt);
return 0;
}
#endif
static const char *const alt_channel_layout[] = { "ch_layout", NULL};
static const char *const alt_codec[] = { "c", "acodec", "vcodec", "scodec", "dcodec", NULL };
static const char *const alt_filter[] = { "af", "vf", NULL };
@@ -1746,6 +1718,11 @@ const OptionDef options[] = {
{ "filter_buffered_frames", OPT_TYPE_INT, OPT_EXPERT,
{ &filter_buffered_frames },
"maximum number of buffered frames in a filter graph" },
#if FFMPEG_OPT_FILTER_SCRIPT
{ "filter_script", OPT_TYPE_STRING, OPT_PERSTREAM | OPT_EXPERT | OPT_OUTPUT,
{ .off = OFFSET(filter_scripts) },
"deprecated, use -/filter", "filename" },
#endif
{ "reinit_filter", OPT_TYPE_INT, OPT_PERSTREAM | OPT_INPUT | OPT_EXPERT,
{ .off = OFFSET(reinit_filters) },
"reinit filtergraph on input parameter changes", "" },
@@ -1761,6 +1738,11 @@ const OptionDef options[] = {
{ "lavfi", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
{ .func_arg = opt_filter_complex },
"create a complex filtergraph", "graph_description" },
#if FFMPEG_OPT_FILTER_SCRIPT
{ "filter_complex_script", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
{ .func_arg = opt_filter_complex_script },
"deprecated, use -/filter_complex instead", "filename" },
#endif
{ "print_graphs", OPT_TYPE_BOOL, 0,
{ &print_graphs },
"print execution graph data to stderr" },
@@ -1860,12 +1842,6 @@ const OptionDef options[] = {
{ .off = OFFSET(display_vflips) },
"set display vertical flip for stream(s) "
"(overrides any display rotation if it is not set)"},
{ "mastering_display", OPT_TYPE_STRING, OPT_VIDEO | OPT_PERSTREAM | OPT_INPUT | OPT_EXPERT,
{ .off = OFFSET(mastering_displays) },
"set SMPTE2084 mastering display color volume info" },
{ "content_light", OPT_TYPE_STRING, OPT_VIDEO | OPT_PERSTREAM | OPT_INPUT | OPT_EXPERT,
{ .off = OFFSET(content_lights) },
"set SMPTE2084 Max CLL and Max FALL values" },
{ "vn", OPT_TYPE_BOOL, OPT_VIDEO | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,
{ .off = OFFSET(video_disable) },
"disable video" },
@@ -1913,7 +1889,7 @@ const OptionDef options[] = {
.u1.name_canon = "tag", },
{ "fps_mode", OPT_TYPE_STRING, OPT_VIDEO | OPT_EXPERT | OPT_PERSTREAM | OPT_OUTPUT,
{ .off = OFFSET(fps_mode) },
"set framerate mode for matching video streams" },
"set framerate mode for matching video streams; overrides vsync" },
{ "force_fps", OPT_TYPE_BOOL, OPT_VIDEO | OPT_EXPERT | OPT_PERSTREAM | OPT_OUTPUT,
{ .off = OFFSET(force_fps) },
"force the selected framerate, disable the best supported framerate selection" },
@@ -2098,5 +2074,27 @@ const OptionDef options[] = {
{ .func_arg = opt_filter_hw_device },
"set hardware device used when filtering", "device" },
// deprecated options
#if FFMPEG_OPT_ADRIFT_THRESHOLD
{ "adrift_threshold", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
{ .func_arg = opt_adrift_threshold },
"deprecated, does nothing", "threshold" },
#endif
#if FFMPEG_OPT_TOP
{ "top", OPT_TYPE_INT, OPT_VIDEO | OPT_EXPERT | OPT_PERSTREAM | OPT_INPUT | OPT_OUTPUT,
{ .off = OFFSET(top_field_first) },
"deprecated, use the setfield video filter", "" },
#endif
#if FFMPEG_OPT_QPHIST
{ "qphist", OPT_TYPE_FUNC, OPT_VIDEO | OPT_EXPERT,
{ .func_arg = opt_qphist },
"deprecated, does nothing" },
#endif
#if FFMPEG_OPT_VSYNC
{ "vsync", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT,
{ .func_arg = opt_vsync },
"set video sync method globally; deprecated, use -fps_mode", "" },
#endif
{ NULL, },
};
+94 -350
View File
@@ -32,7 +32,6 @@
#include "libavcodec/packet.h"
#include "libavutil/avassert.h"
#include "libavutil/container_fifo.h"
#include "libavutil/error.h"
#include "libavutil/fifo.h"
#include "libavutil/frame.h"
@@ -87,7 +86,6 @@ typedef struct SchDec {
unsigned nb_outputs;
SchTask task;
SchWaiter waiter;
// Queue for receiving input packets, one stream.
ThreadQueue *queue;
@@ -97,9 +95,6 @@ typedef struct SchDec {
// temporary storage used by sch_dec_send()
AVFrame *send_frame;
// internal queue of undecoded packets used by sch_dec_receive()
AVContainerFifo *overflow;
} SchDec;
typedef struct SchSyncQueue {
@@ -194,6 +189,7 @@ typedef struct PreMuxQueue {
typedef struct SchMuxStream {
SchedulerNode src;
SchedulerNode src_sched;
unsigned *sub_heartbeat_dst;
unsigned nb_sub_heartbeat_dst;
@@ -239,6 +235,7 @@ typedef struct SchMux {
typedef struct SchFilterIn {
SchedulerNode src;
SchedulerNode src_sched;
int send_finished;
int receive_finished;
} SchFilterIn;
@@ -252,7 +249,7 @@ typedef struct SchFilterGraph {
SchFilterIn *inputs;
unsigned nb_inputs;
unsigned nb_inputs_finished_send;
atomic_uint nb_inputs_finished_send;
unsigned nb_inputs_finished_receive;
SchFilterOut *outputs;
@@ -392,7 +389,7 @@ static int queue_alloc(ThreadQueue **ptq, unsigned nb_streams, unsigned queue_si
// for frames held in queues inside the ffmpeg utility. If this
// can ever dynamically change then the corresponding decode
// code needs to be updated as well.
av_assert0(queue_size <= DEFAULT_FRAME_THREAD_QUEUE_SIZE);
av_assert0(queue_size == DEFAULT_FRAME_THREAD_QUEUE_SIZE);
}
tq = tq_alloc(nb_streams, queue_size,
@@ -410,9 +407,6 @@ static int task_start(SchTask *task)
{
int ret;
if (!task->parent)
return 0;
av_log(task->func_arg, AV_LOG_VERBOSE, "Starting thread...\n");
av_assert0(!task->thread_running);
@@ -440,7 +434,7 @@ static void task_init(Scheduler *sch, SchTask *task, enum SchedulerNodeType type
task->func_arg = func_arg;
}
static int64_t trailing_dts(const Scheduler *sch)
static int64_t trailing_dts(const Scheduler *sch, int count_finished)
{
int64_t min_dts = INT64_MAX;
@@ -450,7 +444,7 @@ static int64_t trailing_dts(const Scheduler *sch)
for (unsigned j = 0; j < mux->nb_streams; j++) {
const SchMuxStream *ms = &mux->streams[j];
if (ms->source_finished)
if (ms->source_finished && !count_finished)
continue;
if (ms->last_dts == AV_NOPTS_VALUE)
return AV_NOPTS_VALUE;
@@ -462,43 +456,6 @@ static int64_t trailing_dts(const Scheduler *sch)
return min_dts == INT64_MAX ? AV_NOPTS_VALUE : min_dts;
}
static int64_t progressing_dts(const Scheduler *sch, int count_finished)
{
int64_t max_dts = INT64_MIN;
for (unsigned i = 0; i < sch->nb_mux; i++) {
const SchMux *mux = &sch->mux[i];
for (unsigned j = 0; j < mux->nb_streams; j++) {
const SchMuxStream *ms = &mux->streams[j];
if (ms->source_finished && !count_finished)
continue;
if (ms->last_dts != AV_NOPTS_VALUE)
max_dts = FFMAX(max_dts, ms->last_dts);
}
}
return max_dts == INT64_MIN ? AV_NOPTS_VALUE : max_dts;
}
void sch_remove_filtergraph(Scheduler *sch, int idx)
{
SchFilterGraph *fg = &sch->filters[idx];
av_assert0(!fg->task.thread_running);
memset(&fg->task, 0, sizeof(fg->task));
tq_free(&fg->queue);
av_freep(&fg->inputs);
fg->nb_inputs = 0;
av_freep(&fg->outputs);
fg->nb_outputs = 0;
fg->task_exited = 1;
}
void sch_free(Scheduler **psch)
{
Scheduler *sch = *psch;
@@ -553,7 +510,6 @@ void sch_free(Scheduler **psch)
tq_free(&dec->queue);
av_thread_message_queue_free(&dec->queue_end_ts);
av_container_fifo_free(&dec->overflow);
for (unsigned j = 0; j < dec->nb_outputs; j++) {
SchDecOutput *o = &dec->outputs[j];
@@ -565,8 +521,6 @@ void sch_free(Scheduler **psch)
av_freep(&dec->outputs);
av_frame_free(&dec->send_frame);
waiter_uninit(&dec->waiter);
}
av_freep(&sch->dec);
@@ -817,14 +771,6 @@ int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts)
return ret;
}
dec->overflow = av_container_fifo_alloc_avpacket(0);
if (!dec->overflow)
return AVERROR(ENOMEM);
ret = waiter_init(&dec->waiter);
if (ret < 0)
return ret;
return idx;
}
@@ -1318,128 +1264,28 @@ int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_
return 0;
}
enum {
UNCHOKE_DEMUX = (1 << 0),
UNCHOKE_FILTER = (1 << 1),
UNCHOKE_DECODE = (1 << 2),
UNCHOKE_ALL = UNCHOKE_DEMUX | UNCHOKE_FILTER | UNCHOKE_DECODE,
};
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags);
// Unchoke any filter graphs that are downstream of this node, to prevent it
// from getting stuck trying to push data to a full queue
static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
{
SchFilterGraph *fg;
SchDec *dec;
SchEnc *enc;
switch (dst->type) {
case SCH_NODE_TYPE_DEC:
dec = &sch->dec[dst->idx];
if (!dec->waiter.choked_next) {
for (int i = 0; i < dec->nb_outputs; i++)
unchoke_downstream(sch, dec->outputs[i].dst);
}
break;
case SCH_NODE_TYPE_ENC:
enc = &sch->enc[dst->idx];
for (int i = 0; i < enc->nb_dst; i++)
unchoke_downstream(sch, &enc->dst[i]);
break;
case SCH_NODE_TYPE_MUX:
// muxers are never choked
break;
case SCH_NODE_TYPE_FILTER_IN:
fg = &sch->filters[dst->idx];
if (fg->best_input == fg->nb_inputs) {
fg->waiter.choked_next = 0;
} else {
// ensure that this filter graph is not stuck waiting for
// input from a different upstream source
unchoke_for_stream(sch, fg->inputs[fg->best_input].src, UNCHOKE_ALL);
}
break;
default:
av_unreachable("Invalid destination node type?");
break;
}
}
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags)
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src)
{
while (1) {
SchFilterGraph *fg;
SchDemux *demux;
SchDec *dec;
switch (src.type) {
case SCH_NODE_TYPE_DEMUX:
// fed directly by a demuxer (i.e. not through a filtergraph)
demux = &sch->demux[src.idx];
if (demux->waiter.choked_next == 0)
return; // prevent infinite loop
if (flags & UNCHOKE_DEMUX) {
demux->waiter.choked_next = 0;
for (int i = 0; i < demux->nb_streams; i++)
unchoke_downstream(sch, demux->streams[i].dst);
}
return;
case SCH_NODE_TYPE_DEC:
dec = &sch->dec[src.idx];
if (!(flags & UNCHOKE_DECODE))
return;
dec->waiter.choked_next = 0;
src = dec->src;
continue;
case SCH_NODE_TYPE_ENC:
src = sch->enc[src.idx].src;
continue;
case SCH_NODE_TYPE_FILTER_OUT:
fg = &sch->filters[src.idx];
// the filtergraph contains internal sources and
// requested to be scheduled directly
if (fg->best_input == fg->nb_inputs) {
if (flags & UNCHOKE_FILTER)
fg->waiter.choked_next = 0;
return;
}
src = fg->inputs[fg->best_input].src;
continue;
default:
av_unreachable("Invalid source node type?");
// fed directly by a demuxer (i.e. not through a filtergraph)
if (src.type == SCH_NODE_TYPE_DEMUX) {
sch->demux[src.idx].waiter.choked_next = 0;
return;
}
}
}
static void choke_demux(const Scheduler *sch, int demux_id, int choked)
{
av_assert1(demux_id < sch->nb_demux);
SchDemux *demux = &sch->demux[demux_id];
av_assert0(src.type == SCH_NODE_TYPE_FILTER_OUT);
fg = &sch->filters[src.idx];
for (int i = 0; i < demux->nb_streams; i++) {
SchedulerNode *dst = demux->streams[i].dst;
SchFilterGraph *fg;
switch (dst->type) {
case SCH_NODE_TYPE_DEC:
tq_choke(sch->dec[dst->idx].queue, choked);
break;
case SCH_NODE_TYPE_ENC:
tq_choke(sch->enc[dst->idx].queue, choked);
break;
case SCH_NODE_TYPE_MUX:
break;
case SCH_NODE_TYPE_FILTER_IN:
fg = &sch->filters[dst->idx];
if (fg->nb_inputs == 1)
tq_choke(fg->queue, choked);
break;
default:
av_unreachable("Invalid destination node type?");
break;
// the filtergraph contains internal sources and
// requested to be scheduled directly
if (fg->best_input == fg->nb_inputs) {
fg->waiter.choked_next = 0;
return;
}
src = fg->inputs[fg->best_input].src_sched;
}
}
@@ -1453,23 +1299,17 @@ static void schedule_update_locked(Scheduler *sch)
if (atomic_load(&sch->terminate))
return;
dts = trailing_dts(sch);
dts = trailing_dts(sch, 0);
atomic_store(&sch->last_dts, progressing_dts(sch, 0));
atomic_store(&sch->last_dts, dts);
// initialize our internal state
#define RESET_WAITER(field) \
do { \
for (unsigned i = 0; i < sch->nb_##field; i++) { \
SchWaiter *w = &sch->field[i].waiter; \
w->choked_prev = atomic_load(&w->choked); \
w->choked_next = 1; \
} \
} while (0)
RESET_WAITER(demux);
RESET_WAITER(filters);
RESET_WAITER(dec);
for (unsigned type = 0; type < 2; type++)
for (unsigned i = 0; i < (type ? sch->nb_filters : sch->nb_demux); i++) {
SchWaiter *w = type ? &sch->filters[i].waiter : &sch->demux[i].waiter;
w->choked_prev = atomic_load(&w->choked);
w->choked_next = 1;
}
// figure out the sources that are allowed to proceed
for (unsigned i = 0; i < sch->nb_mux; i++) {
@@ -1480,65 +1320,39 @@ static void schedule_update_locked(Scheduler *sch)
// unblock sources for output streams that are not finished
// and not too far ahead of the trailing stream
if (ms->source_finished) {
// still allow decoders to drain
unchoke_for_stream(sch, ms->src, UNCHOKE_DECODE);
if (ms->source_finished)
continue;
}
if (dts == AV_NOPTS_VALUE && ms->last_dts != AV_NOPTS_VALUE)
continue;
if (dts != AV_NOPTS_VALUE && ms->last_dts - dts >= SCHEDULE_TOLERANCE)
continue;
// resolve the source to unchoke
unchoke_for_stream(sch, ms->src, UNCHOKE_ALL);
unchoke_for_stream(sch, ms->src_sched);
have_unchoked = 1;
}
}
// also unchoke any sources feeding into closed filter graph inputs, so
// that they can observe the downstream EOF
for (unsigned i = 0; i < sch->nb_filters; i++) {
SchFilterGraph *fg = &sch->filters[i];
for (unsigned j = 0; j < fg->nb_inputs; j++) {
SchFilterIn *fi = &fg->inputs[j];
if (fi->receive_finished && !fi->send_finished)
unchoke_for_stream(sch, fi->src, UNCHOKE_ALL);
}
}
// make sure to unchoke at least one source, if still available
#define UNCHOKE_ONCE(field) \
do { \
for (unsigned i = 0; !have_unchoked && i < sch->nb_##field; i++) { \
SchWaiter *w = &sch->field[i].waiter; \
if (!sch->field[i].task_exited) { \
w->choked_next = 0; \
have_unchoked = 1; \
break; \
} \
} \
} while (0)
for (unsigned type = 0; !have_unchoked && type < 2; type++)
for (unsigned i = 0; i < (type ? sch->nb_filters : sch->nb_demux); i++) {
int exited = type ? sch->filters[i].task_exited : sch->demux[i].task_exited;
SchWaiter *w = type ? &sch->filters[i].waiter : &sch->demux[i].waiter;
if (!exited) {
w->choked_next = 0;
have_unchoked = 1;
break;
}
}
UNCHOKE_ONCE(demux);
UNCHOKE_ONCE(filters);
#define UPDATE_WAITER(field) \
do { \
for (unsigned i = 0; i < sch->nb_##field; i++) { \
SchWaiter *w = &sch->field[i].waiter; \
if (w->choked_prev != w->choked_next) { \
waiter_set(w, w->choked_next); \
if (offsetof(Scheduler, field) == offsetof(Scheduler, demux)) \
choke_demux(sch, i, w->choked_next); \
} \
} \
} while (0)
for (unsigned type = 0; type < 2; type++)
for (unsigned i = 0; i < (type ? sch->nb_filters : sch->nb_demux); i++) {
SchWaiter *w = type ? &sch->filters[i].waiter : &sch->demux[i].waiter;
if (w->choked_prev != w->choked_next)
waiter_set(w, w->choked_next);
}
UPDATE_WAITER(demux);
UPDATE_WAITER(filters);
UPDATE_WAITER(dec);
}
enum {
@@ -1547,27 +1361,6 @@ enum {
CYCLE_NODE_DONE,
};
// Finds the filtergraph or muxer upstream of a scheduler node
static SchedulerNode src_filtergraph(const Scheduler *sch, SchedulerNode src)
{
while (1) {
switch (src.type) {
case SCH_NODE_TYPE_DEMUX:
case SCH_NODE_TYPE_FILTER_OUT:
return src;
case SCH_NODE_TYPE_DEC:
src = sch->dec[src.idx].src;
continue;
case SCH_NODE_TYPE_ENC:
src = sch->enc[src.idx].src;
continue;
default:
av_unreachable("Invalid source node type?");
return (SchedulerNode) {0};
}
}
}
static int
check_acyclic_for_output(const Scheduler *sch, SchedulerNode src,
uint8_t *filters_visited, SchedulerNode *filters_stack)
@@ -1584,23 +1377,22 @@ check_acyclic_for_output(const Scheduler *sch, SchedulerNode src,
// descend into every input, depth first
if (src.idx_stream < fg->nb_inputs) {
const SchFilterIn *fi = &fg->inputs[src.idx_stream++];
SchedulerNode node = src_filtergraph(sch, fi->src);
// connected to demuxer, no cycles possible
if (node.type == SCH_NODE_TYPE_DEMUX)
if (fi->src_sched.type == SCH_NODE_TYPE_DEMUX)
continue;
// otherwise connected to another filtergraph
av_assert0(node.type == SCH_NODE_TYPE_FILTER_OUT);
av_assert0(fi->src_sched.type == SCH_NODE_TYPE_FILTER_OUT);
// found a cycle
if (filters_visited[node.idx] == CYCLE_NODE_STARTED)
if (filters_visited[fi->src_sched.idx] == CYCLE_NODE_STARTED)
return AVERROR(EINVAL);
// place current position on stack and descend
av_assert0(nb_filters_stack < sch->nb_filters);
filters_stack[nb_filters_stack++] = src;
src = (SchedulerNode){ .idx = node.idx, .idx_stream = 0 };
src = (SchedulerNode){ .idx = fi->src_sched.idx, .idx_stream = 0 };
continue;
}
@@ -1722,7 +1514,22 @@ static int start_prepare(Scheduler *sch)
for (unsigned j = 0; j < mux->nb_streams; j++) {
SchMuxStream *ms = &mux->streams[j];
if (!ms->src.type) {
switch (ms->src.type) {
case SCH_NODE_TYPE_ENC: {
SchEnc *enc = &sch->enc[ms->src.idx];
if (enc->src.type == SCH_NODE_TYPE_DEC) {
ms->src_sched = sch->dec[enc->src.idx].src;
av_assert0(ms->src_sched.type == SCH_NODE_TYPE_DEMUX);
} else {
ms->src_sched = enc->src;
av_assert0(ms->src_sched.type == SCH_NODE_TYPE_FILTER_OUT);
}
break;
}
case SCH_NODE_TYPE_DEMUX:
ms->src_sched = ms->src;
break;
default:
av_log(mux, AV_LOG_ERROR,
"Muxer stream #%u not connected to a source\n", j);
return AVERROR(EINVAL);
@@ -1740,12 +1547,26 @@ static int start_prepare(Scheduler *sch)
for (unsigned j = 0; j < fg->nb_inputs; j++) {
SchFilterIn *fi = &fg->inputs[j];
SchDec *dec;
if (!fi->src.type) {
av_log(fg, AV_LOG_ERROR,
"Filtergraph input %u not connected to a source\n", j);
return AVERROR(EINVAL);
}
if (fi->src.type == SCH_NODE_TYPE_FILTER_OUT)
fi->src_sched = fi->src;
else {
av_assert0(fi->src.type == SCH_NODE_TYPE_DEC);
dec = &sch->dec[fi->src.idx];
switch (dec->src.type) {
case SCH_NODE_TYPE_DEMUX: fi->src_sched = dec->src; break;
case SCH_NODE_TYPE_ENC: fi->src_sched = sch->enc[dec->src.idx].src; break;
default: av_assert0(0);
}
}
}
for (unsigned j = 0; j < fg->nb_outputs; j++) {
@@ -2257,7 +2078,7 @@ int sch_mux_receive(Scheduler *sch, unsigned mux_idx, AVPacket *pkt)
av_assert0(mux_idx < sch->nb_mux);
mux = &sch->mux[mux_idx];
ret = tq_receive(mux->queue, &stream_idx, pkt, 0);
ret = tq_receive(mux->queue, &stream_idx, pkt);
pkt->stream_index = stream_idx;
return ret;
}
@@ -2341,12 +2162,6 @@ int sch_dec_receive(Scheduler *sch, unsigned dec_idx, AVPacket *pkt)
av_assert0(dec_idx < sch->nb_dec);
dec = &sch->dec[dec_idx];
retry:
// Pull a packet from the overflow FIFO while unchoked or expecting EOF ts
if (av_container_fifo_can_read(dec->overflow) &&
(!atomic_load(&dec->waiter.choked) || dec->expect_end_ts))
return av_container_fifo_read(dec->overflow, pkt, 0);
// the decoder should have given us post-flush end timestamp in pkt
if (dec->expect_end_ts) {
Timestamp ts = (Timestamp){ .ts = pkt->pts, .tb = pkt->time_base };
@@ -2357,32 +2172,14 @@ retry:
dec->expect_end_ts = 0;
}
ret = tq_receive(dec->queue, &dummy, pkt, 0);
ret = tq_receive(dec->queue, &dummy, pkt);
av_assert0(dummy <= 0);
// drain packets from overflow queue before returning EOF
if (ret == AVERROR_EOF && av_container_fifo_can_read(dec->overflow)) {
int terminate = waiter_wait(sch, &dec->waiter);
if (terminate)
return ret;
return av_container_fifo_read(dec->overflow, pkt, 0);
} else if (ret < 0)
return ret;
// got a flush packet, on the next call to this function the decoder
// should give us post-flush end timestamp (after draining overflow fifo)
if (!pkt->data && !pkt->side_data_elems && dec->queue_end_ts)
// will give us post-flush end timestamp
if (ret >= 0 && !pkt->data && !pkt->side_data_elems && dec->queue_end_ts)
dec->expect_end_ts = 1;
// we got a packet, but we're currently choked or have existing overflow
// packets; so push it to the FIFO first
if (atomic_load(&dec->waiter.choked) || av_container_fifo_can_read(dec->overflow)) {
ret = av_container_fifo_write(dec->overflow, pkt, 0);
if (ret < 0)
return ret;
goto retry;
}
return ret;
}
@@ -2392,20 +2189,14 @@ static int send_to_filter(Scheduler *sch, SchFilterGraph *fg,
if (frame)
return tq_send(fg->queue, in_idx, frame);
pthread_mutex_lock(&sch->schedule_lock);
if (!fg->inputs[in_idx].send_finished) {
fg->inputs[in_idx].send_finished = 1;
tq_send_finish(fg->queue, in_idx);
// close the control stream when all actual inputs are done
if (++fg->nb_inputs_finished_send == fg->nb_inputs)
if (atomic_fetch_add(&fg->nb_inputs_finished_send, 1) == fg->nb_inputs - 1)
tq_send_finish(fg->queue, fg->nb_inputs);
schedule_update_locked(sch);
}
pthread_mutex_unlock(&sch->schedule_lock);
return 0;
}
@@ -2516,7 +2307,7 @@ int sch_enc_receive(Scheduler *sch, unsigned enc_idx, AVFrame *frame)
av_assert0(enc_idx < sch->nb_enc);
enc = &sch->enc[enc_idx];
ret = tq_receive(enc->queue, &dummy, frame, 0);
ret = tq_receive(enc->queue, &dummy, frame);
av_assert0(dummy <= 0);
return ret;
@@ -2605,7 +2396,6 @@ int sch_filter_receive(Scheduler *sch, unsigned fg_idx,
unsigned *in_idx, AVFrame *frame)
{
SchFilterGraph *fg;
int ret, idx;
av_assert0(fg_idx < sch->nb_filters);
fg = &sch->filters[fg_idx];
@@ -2626,20 +2416,14 @@ int sch_filter_receive(Scheduler *sch, unsigned fg_idx,
}
if (*in_idx == fg->nb_inputs) {
// drain incoming frames before waiting, to avoid blocking downstream
ret = tq_receive(fg->queue, &idx, frame, THREAD_QUEUE_FLAG_NO_BLOCK);
if (ret >= 0) {
av_assert0(idx >= 0);
*in_idx = idx;
return 0;
}
int terminate = waiter_wait(sch, &fg->waiter);
return terminate ? AVERROR_EOF : AVERROR(EAGAIN);
}
while (1) {
ret = tq_receive(fg->queue, &idx, frame, 0);
int ret, idx;
ret = tq_receive(fg->queue, &idx, frame);
if (idx < 0)
return AVERROR_EOF;
else if (ret >= 0) {
@@ -2663,8 +2447,6 @@ void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx)
av_assert0(in_idx < fg->nb_inputs);
fi = &fg->inputs[in_idx];
pthread_mutex_lock(&sch->schedule_lock);
if (!fi->receive_finished) {
fi->receive_finished = 1;
tq_receive_finish(fg->queue, in_idx);
@@ -2672,18 +2454,13 @@ void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx)
// close the control stream when all actual inputs are done
if (++fg->nb_inputs_finished_receive == fg->nb_inputs)
tq_receive_finish(fg->queue, fg->nb_inputs);
schedule_update_locked(sch);
}
pthread_mutex_unlock(&sch->schedule_lock);
}
int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx, AVFrame *frame)
{
SchFilterGraph *fg;
SchedulerNode dst;
int ret;
av_assert0(fg_idx < sch->nb_filters);
fg = &sch->filters[fg_idx];
@@ -2691,16 +2468,9 @@ int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx, AVFrame *
av_assert0(out_idx < fg->nb_outputs);
dst = fg->outputs[out_idx].dst;
if (dst.type == SCH_NODE_TYPE_ENC) {
ret = send_to_enc(sch, &sch->enc[dst.idx], frame);
if (ret == AVERROR_EOF)
send_to_enc(sch, &sch->enc[dst.idx], NULL);
} else {
ret = send_to_filter(sch, &sch->filters[dst.idx], dst.idx_stream, frame);
if (ret == AVERROR_EOF)
send_to_filter(sch, &sch->filters[dst.idx], dst.idx_stream, NULL);
}
return ret;
return (dst.type == SCH_NODE_TYPE_ENC) ?
send_to_enc (sch, &sch->enc[dst.idx], frame) :
send_to_filter(sch, &sch->filters[dst.idx], dst.idx_stream, frame);
}
static int filter_done(Scheduler *sch, unsigned fg_idx)
@@ -2742,18 +2512,6 @@ int sch_filter_command(Scheduler *sch, unsigned fg_idx, AVFrame *frame)
return send_to_filter(sch, fg, fg->nb_inputs, frame);
}
void sch_filter_choke_inputs(Scheduler *sch, unsigned fg_idx)
{
SchFilterGraph *fg;
av_assert0(fg_idx < sch->nb_filters);
fg = &sch->filters[fg_idx];
pthread_mutex_lock(&sch->schedule_lock);
fg->best_input = fg->nb_inputs;
schedule_update_locked(sch);
pthread_mutex_unlock(&sch->schedule_lock);
}
static int task_cleanup(Scheduler *sch, SchedulerNode node)
{
switch (node.type) {
@@ -2762,7 +2520,7 @@ static int task_cleanup(Scheduler *sch, SchedulerNode node)
case SCH_NODE_TYPE_DEC: return dec_done (sch, node.idx);
case SCH_NODE_TYPE_ENC: return enc_done (sch, node.idx);
case SCH_NODE_TYPE_FILTER_IN: return filter_done(sch, node.idx);
default: av_unreachable("Invalid node type?");
default: av_assert0(0);
}
}
@@ -2803,9 +2561,6 @@ static int task_stop(Scheduler *sch, SchTask *task)
int ret;
void *thread_ret;
if (!task->parent)
return 0;
if (!task->thread_running)
return task_cleanup(sch, task->node);
@@ -2826,23 +2581,12 @@ int sch_stop(Scheduler *sch, int64_t *finish_ts)
atomic_store(&sch->terminate, 1);
// Ensure no other thread is currently in schedule_update_locked while
// we are choking all demuxers
pthread_mutex_lock(&sch->schedule_lock);
for (unsigned type = 0; type < 2; type++)
for (unsigned i = 0; i < (type ? sch->nb_demux : sch->nb_filters); i++) {
SchWaiter *w = type ? &sch->demux[i].waiter : &sch->filters[i].waiter;
waiter_set(w, 1);
if (type)
choke_demux(sch, i, 0); // unfreeze to allow draining
}
for (unsigned i = 0; i < sch->nb_dec; i++)
waiter_set(&sch->dec[i].waiter, 0); // unfreeze to allow draining
pthread_mutex_unlock(&sch->schedule_lock);
for (unsigned i = 0; i < sch->nb_demux; i++) {
SchDemux *d = &sch->demux[i];
@@ -2879,7 +2623,7 @@ int sch_stop(Scheduler *sch, int64_t *finish_ts)
}
if (finish_ts)
*finish_ts = progressing_dts(sch, 1);
*finish_ts = trailing_dts(sch, 1);
sch->state = SCH_STATE_STOPPED;
+1 -10
View File
@@ -205,8 +205,6 @@ int sch_add_dec_output(Scheduler *sch, unsigned dec_idx);
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs,
SchThreadFunc func, void *ctx);
void sch_remove_filtergraph(Scheduler *sch, int idx);
/**
* Add a muxer to the scheduler.
*
@@ -259,7 +257,7 @@ int sch_add_mux(Scheduler *sch, SchThreadFunc func, int (*init)(void *),
/**
* Default size of a frame thread queue.
*/
#define DEFAULT_FRAME_THREAD_QUEUE_SIZE 2
#define DEFAULT_FRAME_THREAD_QUEUE_SIZE 8
/**
* Add a muxed stream for a previously added muxer.
@@ -445,13 +443,6 @@ int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx,
int sch_filter_command(Scheduler *sch, unsigned fg_idx, struct AVFrame *frame);
/**
* Called by filtergraph tasks to choke all filter inputs, preventing them from
* receiving more frames until woken up again by the scheduler. Used during
* initial graph configuration to avoid unnecessary buffering.
*/
void sch_filter_choke_inputs(Scheduler *sch, unsigned fg_idx);
/**
* Called by encoder tasks to obtain frames for encoding. Will wait for a frame
* to become available and return it in frame.
+16 -100
View File
@@ -37,7 +37,6 @@
#include "libavutil/pixdesc.h"
#include "libavutil/dict.h"
#include "libavutil/fifo.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/bprint.h"
@@ -268,7 +267,6 @@ typedef struct VideoState {
AVComplexFloat *rdft_data;
int xpos;
double last_vis_time;
RenderParams render_params;
SDL_Texture *vis_texture;
SDL_Texture *sub_texture;
SDL_Texture *vid_texture;
@@ -352,7 +350,6 @@ static int find_stream_info = 1;
static int filter_nbthreads = 0;
static int enable_vulkan = 0;
static char *vulkan_params = NULL;
static char *video_background = NULL;
static const char *hwaccel = NULL;
/* current context */
@@ -945,11 +942,6 @@ static enum AVColorSpace sdl_supported_color_spaces[] = {
AVCOL_SPC_SMPTE170M,
};
static enum AVAlphaMode sdl_supported_alpha_modes[] = {
AVALPHA_MODE_UNSPECIFIED,
AVALPHA_MODE_STRAIGHT,
};
static void set_sdl_yuv_conversion_mode(AVFrame *frame)
{
#if SDL_VERSION_ATLEAST(2,0,8)
@@ -966,52 +958,15 @@ static void set_sdl_yuv_conversion_mode(AVFrame *frame)
#endif
}
static void draw_video_background(VideoState *is)
{
const int tile_size = VIDEO_BACKGROUND_TILE_SIZE;
SDL_Rect *rect = &is->render_params.target_rect;
SDL_BlendMode blendMode;
if (!SDL_GetTextureBlendMode(is->vid_texture, &blendMode) && blendMode == SDL_BLENDMODE_BLEND) {
switch (is->render_params.video_background_type) {
case VIDEO_BACKGROUND_TILES:
SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
fill_rectangle(rect->x, rect->y, rect->w, rect->h);
SDL_SetRenderDrawColor(renderer, 222, 222, 222, 255);
for (int x = 0; x < rect->w; x += tile_size * 2)
fill_rectangle(rect->x + x, rect->y, FFMIN(tile_size, rect->w - x), rect->h);
for (int y = 0; y < rect->h; y += tile_size * 2)
fill_rectangle(rect->x, rect->y + y, rect->w, FFMIN(tile_size, rect->h - y));
SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
for (int y = 0; y < rect->h; y += tile_size * 2) {
int h = FFMIN(tile_size, rect->h - y);
for (int x = 0; x < rect->w; x += tile_size * 2)
fill_rectangle(x + rect->x, y + rect->y, FFMIN(tile_size, rect->w - x), h);
}
break;
case VIDEO_BACKGROUND_COLOR: {
const uint8_t *c = is->render_params.video_background_color;
SDL_SetRenderDrawColor(renderer, c[0], c[1], c[2], c[3]);
fill_rectangle(rect->x, rect->y, rect->w, rect->h);
break;
}
case VIDEO_BACKGROUND_NONE:
SDL_SetTextureBlendMode(is->vid_texture, SDL_BLENDMODE_NONE);
break;
}
}
}
static void video_image_display(VideoState *is)
{
Frame *vp;
Frame *sp = NULL;
SDL_Rect *rect = &is->render_params.target_rect;
SDL_Rect rect;
vp = frame_queue_peek_last(&is->pictq);
calculate_display_rect(rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
if (vk_renderer) {
vk_renderer_display(vk_renderer, vp->frame, &is->render_params);
vk_renderer_display(vk_renderer, vp->frame);
return;
}
@@ -1060,6 +1015,7 @@ static void video_image_display(VideoState *is)
}
}
calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
set_sdl_yuv_conversion_mode(vp->frame);
if (!vp->uploaded) {
@@ -1071,16 +1027,15 @@ static void video_image_display(VideoState *is)
vp->flip_v = vp->frame->linesize[0] < 0;
}
draw_video_background(is);
SDL_RenderCopyEx(renderer, is->vid_texture, NULL, rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
set_sdl_yuv_conversion_mode(NULL);
if (sp) {
#if USE_ONEPASS_SUBTITLE_RENDER
SDL_RenderCopy(renderer, is->sub_texture, NULL, rect);
SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
#else
int i;
double xratio = (double)rect->w / (double)sp->width;
double yratio = (double)rect->h / (double)sp->height;
double xratio = (double)rect.w / (double)sp->width;
double yratio = (double)rect.h / (double)sp->height;
for (i = 0; i < sp->sub.num_rects; i++) {
SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
@@ -1951,7 +1906,6 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
par->sample_aspect_ratio = codecpar->sample_aspect_ratio;
par->color_space = frame->colorspace;
par->color_range = frame->color_range;
par->alpha_mode = frame->alpha_mode;
par->frame_rate = fr;
par->hw_frames_ctx = frame->hw_frames_ctx;
ret = av_buffersrc_parameters_set(filt_src, par);
@@ -1978,11 +1932,6 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
AV_OPT_TYPE_INT, sdl_supported_color_spaces)) < 0)
goto fail;
if ((ret = av_opt_set_array(filt_out, "alphamodes", AV_OPT_SEARCH_CHILDREN,
0, FF_ARRAY_ELEMS(sdl_supported_alpha_modes),
AV_OPT_TYPE_INT, sdl_supported_alpha_modes)) < 0)
goto fail;
ret = avfilter_init_dict(filt_out, NULL);
if (ret < 0)
goto fail;
@@ -2883,7 +2832,6 @@ static int read_thread(void *arg)
int st_index[AVMEDIA_TYPE_NB];
AVPacket *pkt = NULL;
int64_t stream_start_time;
char metadata_description[96];
int pkt_in_play_range = 0;
const AVDictionaryEntry *t;
SDL_mutex *wait_mutex = SDL_CreateMutex();
@@ -2991,10 +2939,8 @@ static int read_thread(void *arg)
is->realtime = is_realtime(ic);
if (show_status) {
fprintf(stderr, "\x1b[2K\r");
if (show_status)
av_dump_format(ic, 0, is->filename, 0);
}
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
@@ -3003,11 +2949,7 @@ static int read_thread(void *arg)
if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
st_index[type] = i;
// Clear all pre-existing metadata update flags to avoid printing
// initial metadata as update.
st->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
}
ic->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED;
for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
if (wanted_stream_spec[i] && st_index[i] == -1) {
av_log(NULL, AV_LOG_ERROR, "Stream specifier %s does not match any %s stream\n", wanted_stream_spec[i], av_get_media_type_string(i));
@@ -3175,27 +3117,6 @@ static int read_thread(void *arg)
} else {
is->eof = 0;
}
if (show_status) {
if (ic->event_flags & AVFMT_EVENT_FLAG_METADATA_UPDATED) {
fprintf(stderr, "\x1b[2K\r");
dump_dictionary(NULL, ic->metadata,
"\r New metadata", " ", AV_LOG_INFO);
}
if (ic->streams[pkt->stream_index]->event_flags &
AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
fprintf(stderr, "\x1b[2K\r");
snprintf(metadata_description,
sizeof(metadata_description),
"\r New metadata for stream %d",
pkt->stream_index);
dump_dictionary(NULL, ic->streams[pkt->stream_index]->metadata,
metadata_description, " ", AV_LOG_INFO);
}
}
ic->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED;
ic->streams[pkt->stream_index]->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
/* check if packet is in play range specified by user, then queue, otherwise discard */
stream_start_time = ic->streams[pkt->stream_index]->start_time;
pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
@@ -3277,16 +3198,6 @@ static VideoState *stream_open(const char *filename,
av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
if (startup_volume > 100)
av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
if (video_background) {
if (!strcmp(video_background, "none")) {
is->render_params.video_background_type = VIDEO_BACKGROUND_NONE;
} else if (strcmp(video_background, "tiles")) {
if (av_parse_color(is->render_params.video_background_color, video_background, -1, NULL) >= 0)
is->render_params.video_background_type = VIDEO_BACKGROUND_COLOR;
else
goto fail;
}
}
startup_volume = av_clip(startup_volume, 0, 100);
startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
is->audio_volume = startup_volume;
@@ -3800,7 +3711,6 @@ static const OptionDef options[] = {
{ "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
{ "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" },
{ "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" },
{ "video_bg", OPT_TYPE_STRING, OPT_EXPERT, { &video_background }, "set video background for transparent videos" },
{ "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" },
{ NULL, },
};
@@ -3835,9 +3745,9 @@ void show_help_default(const char *opt, const char *arg)
"c cycle program\n"
"w cycle video filters or show modes\n"
"s activate frame-step mode\n"
"left/right seek backward/forward by 10 seconds or a custom interval if -seek_interval is set\n"
"left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
"down/up seek backward/forward 1 minute\n"
"page down/page up seek to previous/next chapter or backward/forward 10 minutes if no chapters\n"
"page down/page up seek backward/forward 10 minutes\n"
"right mouse click seek to percentage in file corresponding to fraction of width\n"
"left double-click toggle full screen\n"
);
@@ -3883,6 +3793,12 @@ int main(int argc, char **argv)
flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
if (audio_disable)
flags &= ~SDL_INIT_AUDIO;
else {
/* Try to work around an occasional ALSA buffer underflow issue when the
* period size is NPOT due to ALSA resampling by forcing the buffer size. */
if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
}
if (display_disable)
flags &= ~SDL_INIT_VIDEO;
if (SDL_Init (flags)) {
+41 -57
View File
@@ -23,7 +23,9 @@
#include "ffplay_renderer.h"
#if (SDL_VERSION_ATLEAST(2, 0, 6) && CONFIG_LIBPLACEBO)
#define HAVE_VULKAN_RENDERER 1
/* Get PL_API_VER */
#include <libplacebo/config.h>
#define HAVE_VULKAN_RENDERER (PL_API_VER >= 278)
#else
#define HAVE_VULKAN_RENDERER 0
#endif
@@ -41,7 +43,6 @@
#include "libavutil/bprint.h"
#include "libavutil/mem.h"
#include "libavutil/internal.h"
#endif
@@ -52,7 +53,7 @@ struct VkRenderer {
int (*get_hw_dev)(VkRenderer *renderer, AVBufferRef **dev);
int (*display)(VkRenderer *renderer, AVFrame *frame, RenderParams *params);
int (*display)(VkRenderer *renderer, AVFrame *frame);
int (*resize)(VkRenderer *renderer, int width, int height);
@@ -103,6 +104,36 @@ static void vk_log_cb(void *log_priv, enum pl_log_level level,
av_log(log_priv, level_map[level], "%s\n", msg);
}
// Should keep sync with optional_device_exts inside hwcontext_vulkan.c
static const char *optional_device_exts[] = {
/* Misc or required by other extensions */
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,
VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,
VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,
VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,
/* Imports/exports */
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
#ifdef _WIN32
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
#endif
/* Video encoding/decoding */
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,
VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,
"VK_MESA_video_decode_av1",
};
static inline int enable_debug(const AVDictionary *opt)
{
AVDictionaryEntry *entry = av_dict_get(opt, "debug", NULL, 0);
@@ -114,22 +145,14 @@ static void hwctx_lock_queue(void *priv, uint32_t qf, uint32_t qidx)
{
AVHWDeviceContext *avhwctx = priv;
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
#if FF_API_VULKAN_SYNC_QUEUES
FF_DISABLE_DEPRECATION_WARNINGS
hwctx->lock_queue(avhwctx, qf, qidx);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
static void hwctx_unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
{
AVHWDeviceContext *avhwctx = priv;
const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
#if FF_API_VULKAN_SYNC_QUEUES
FF_DISABLE_DEPRECATION_WARNINGS
hwctx->unlock_queue(avhwctx, qf, qidx);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
static int add_instance_extension(const char **ext, unsigned num_ext,
@@ -290,11 +313,7 @@ static void placebo_lock_queue(struct AVHWDeviceContext *dev_ctx,
{
RendererContext *ctx = dev_ctx->user_opaque;
pl_vulkan vk = ctx->placebo_vulkan;
#if FF_API_VULKAN_SYNC_QUEUES
FF_DISABLE_DEPRECATION_WARNINGS
vk->lock_queue(vk, queue_family, index);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
static void placebo_unlock_queue(struct AVHWDeviceContext *dev_ctx,
@@ -303,11 +322,7 @@ static void placebo_unlock_queue(struct AVHWDeviceContext *dev_ctx,
{
RendererContext *ctx = dev_ctx->user_opaque;
pl_vulkan vk = ctx->placebo_vulkan;
#if FF_API_VULKAN_SYNC_QUEUES
FF_DISABLE_DEPRECATION_WARNINGS
vk->unlock_queue(vk, queue_family, index);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
static int get_decode_queue(VkRenderer *renderer, int *index, int *count)
@@ -359,8 +374,6 @@ static int create_vk_by_placebo(VkRenderer *renderer,
int decode_index;
int decode_count;
int ret;
const char **dev_exts;
int num_dev_exts;
ctx->get_proc_addr = SDL_Vulkan_GetVkGetInstanceProcAddr();
@@ -375,21 +388,16 @@ static int create_vk_by_placebo(VkRenderer *renderer,
}
ctx->inst = ctx->placebo_instance->instance;
dev_exts = av_vk_get_optional_device_extensions(&num_dev_exts);
if (!dev_exts)
return AVERROR(ENOMEM);
ctx->placebo_vulkan = pl_vulkan_create(ctx->vk_log, pl_vulkan_params(
.instance = ctx->placebo_instance->instance,
.get_proc_addr = ctx->placebo_instance->get_proc_addr,
.surface = ctx->vk_surface,
.allow_software = false,
.opt_extensions = dev_exts,
.num_opt_extensions = num_dev_exts,
.opt_extensions = optional_device_exts,
.num_opt_extensions = FF_ARRAY_ELEMS(optional_device_exts),
.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
.device_name = select_device(opt),
));
av_free(dev_exts);
if (!ctx->placebo_vulkan)
return AVERROR_EXTERNAL;
ctx->hw_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VULKAN);
@@ -401,12 +409,8 @@ static int create_vk_by_placebo(VkRenderer *renderer,
device_ctx->user_opaque = ctx;
vk_dev_ctx = device_ctx->hwctx;
#if FF_API_VULKAN_SYNC_QUEUES
FF_DISABLE_DEPRECATION_WARNINGS
vk_dev_ctx->lock_queue = placebo_lock_queue;
vk_dev_ctx->unlock_queue = placebo_unlock_queue;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
vk_dev_ctx->get_proc_addr = ctx->placebo_instance->get_proc_addr;
@@ -721,13 +725,11 @@ static int convert_frame(VkRenderer *renderer, AVFrame *frame)
return ret;
}
static int display(VkRenderer *renderer, AVFrame *frame, RenderParams *params)
static int display(VkRenderer *renderer, AVFrame *frame)
{
SDL_Rect *rect = &params->target_rect;
struct pl_swapchain_frame swap_frame = {0};
struct pl_frame pl_frame = {0};
struct pl_frame target = {0};
struct pl_render_params pl_params = pl_render_default_params;
RendererContext *ctx = (RendererContext *) renderer;
int ret = 0;
struct pl_color_space hint = {0};
@@ -752,26 +754,8 @@ static int display(VkRenderer *renderer, AVFrame *frame, RenderParams *params)
}
pl_frame_from_swapchain(&target, &swap_frame);
target.crop = (pl_rect2df){.x0 = rect->x, .x1 = rect->x + rect->w,
.y0 = rect->y, .y1 = rect->y + rect->h};
switch (params->video_background_type) {
case VIDEO_BACKGROUND_TILES:
pl_params.background = PL_CLEAR_TILES;
pl_params.tile_size = VIDEO_BACKGROUND_TILE_SIZE * 2;
break;
case VIDEO_BACKGROUND_COLOR:
pl_params.background = PL_CLEAR_COLOR;
for (int i = 0; i < 3; i++)
pl_params.background_color[i] = params->video_background_color[i] / 255.0;
pl_params.background_transparency = (255 - params->video_background_color[3]) / 255.0;
break;
case VIDEO_BACKGROUND_NONE:
pl_frame.repr.alpha = PL_ALPHA_NONE;
break;
}
if (!pl_render_image(ctx->renderer, &pl_frame, &target, &pl_params)) {
if (!pl_render_image(ctx->renderer, &pl_frame, &target,
&pl_render_default_params)) {
av_log(NULL, AV_LOG_ERROR, "pl_render_image failed\n");
ret = AVERROR_EXTERNAL;
goto out;
@@ -874,9 +858,9 @@ int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
return renderer->get_hw_dev(renderer, dev);
}
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame, RenderParams *render_params)
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame)
{
return renderer->display(renderer, frame, render_params);
return renderer->display(renderer, frame);
}
int vk_renderer_resize(VkRenderer *renderer, int width, int height)
+1 -15
View File
@@ -25,20 +25,6 @@
typedef struct VkRenderer VkRenderer;
#define VIDEO_BACKGROUND_TILE_SIZE 64
enum VideoBackgroundType {
VIDEO_BACKGROUND_TILES,
VIDEO_BACKGROUND_COLOR,
VIDEO_BACKGROUND_NONE,
};
typedef struct RenderParams {
SDL_Rect target_rect;
uint8_t video_background_color[4];
enum VideoBackgroundType video_background_type;
} RenderParams;
VkRenderer *vk_get_renderer(void);
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
@@ -46,7 +32,7 @@ int vk_renderer_create(VkRenderer *renderer, SDL_Window *window,
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev);
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame, RenderParams *params);
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame);
int vk_renderer_resize(VkRenderer *renderer, int width, int height);
+78 -398
View File
@@ -36,10 +36,8 @@
#include "libavutil/ambient_viewing_environment.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/avutil.h"
#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h"
#include "libavutil/downmix_info.h"
#include "libavutil/display.h"
#include "libavutil/film_grain_params.h"
#include "libavutil/hdr_dynamic_metadata.h"
@@ -132,11 +130,6 @@ static int use_byte_value_binary_prefix = 0;
static int use_value_sexagesimal_format = 0;
static int show_private_data = 1;
static const char *audio_codec_name = NULL;
static const char *data_codec_name = NULL;
static const char *subtitle_codec_name = NULL;
static const char *video_codec_name = NULL;
#define SHOW_OPTIONAL_FIELDS_AUTO -1
#define SHOW_OPTIONAL_FIELDS_NEVER 0
#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
@@ -145,7 +138,6 @@ static int show_optional_fields = SHOW_OPTIONAL_FIELDS_AUTO;
static char *output_format;
static char *stream_specifier;
static char *show_data_hash;
static char *data_dump_format;
typedef struct ReadInterval {
int id; ///< identifier
@@ -216,8 +208,6 @@ typedef enum {
SECTION_ID_STREAM_GROUP_SUBPIECE,
SECTION_ID_STREAM_GROUP_BLOCKS,
SECTION_ID_STREAM_GROUP_BLOCK,
SECTION_ID_STREAM_GROUP_SIDE_DATA_LIST,
SECTION_ID_STREAM_GROUP_SIDE_DATA,
SECTION_ID_STREAM_GROUP_STREAMS,
SECTION_ID_STREAM_GROUP_STREAM,
SECTION_ID_STREAM_GROUP_DISPOSITION,
@@ -256,7 +246,7 @@ static const char *get_stream_group_type(const void *data)
return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
}
static const AVTextFormatSection sections[] = {
static struct AVTextFormatSection sections[] = {
[SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
[SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
[SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
@@ -301,7 +291,7 @@ static const AVTextFormatSection sections[] = {
[SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
[SECTION_ID_STREAM_GROUP] = { SECTION_ID_STREAM_GROUP, "stream_group", 0, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_COMPONENTS, SECTION_ID_STREAM_GROUP_STREAMS, -1 } },
[SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
[SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SIDE_DATA_LIST, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
[SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
[SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
[SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
[SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
@@ -310,8 +300,6 @@ static const AVTextFormatSection sections[] = {
[SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
[SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
[SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
[SECTION_ID_STREAM_GROUP_SIDE_DATA_LIST] = { SECTION_ID_STREAM_GROUP_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_group_side_data_list" },
[SECTION_ID_STREAM_GROUP_SIDE_DATA] = { SECTION_ID_STREAM_GROUP_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_group_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
[SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
[SECTION_ID_STREAM_GROUP_STREAM] = { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
[SECTION_ID_STREAM_GROUP_DISPOSITION] = { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
@@ -330,13 +318,6 @@ static const AVTextFormatSection sections[] = {
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
};
typedef struct EntrySelection {
int show_all_entries;
AVDictionary *entries_to_show;
} EntrySelection;
static EntrySelection selected_entries[FF_ARRAY_ELEMS(sections)] = { 0 };
static const OptionDef *options;
/* FFprobe context */
@@ -345,11 +326,12 @@ static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
static const char *output_filename = NULL;
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
static const char unit_bit_per_second_str[] = "bit/s";
static unsigned int nb_streams;
static int nb_streams;
static uint64_t *nb_streams_packets;
static uint64_t *nb_streams_frames;
static int *selected_streams;
@@ -370,14 +352,6 @@ typedef struct LogBuffer {
static LogBuffer *log_buffer;
static int log_buffer_size;
static int is_key_selected_callback(AVTextFormatContext *tctx, const char *key)
{
const AVTextFormatSection *section = tctx->section[tctx->level];
const EntrySelection *selection = &selected_entries[section - sections];
return selection->show_all_entries || av_dict_get(selection->entries_to_show, key, NULL, 0);
}
static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
{
AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
@@ -436,8 +410,8 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_list_fmt(k, f, n, m, ...) do { \
av_bprint_clear(&pbuf); \
for (unsigned int idx = 0; idx < n; idx++) { \
for (unsigned int idx2 = 0; idx2 < m; idx2++) { \
for (int idx = 0; idx < n; idx++) { \
for (int idx2 = 0; idx2 < m; idx2++) { \
if (idx > 0 || idx2 > 0) \
av_bprint_chars(&pbuf, ' ', 1); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
@@ -455,33 +429,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_ts(k, v) avtext_print_ts(tfc, k, v, 0)
#define print_duration_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 1)
#define print_duration_ts(k, v) avtext_print_ts(tfc, k, v, 1)
#define print_val(k, v, u) avtext_print_unit_integer(tfc, k, v, AV_TEXTFORMAT_VALUE_FMT_INT, u)
#define print_int_fmt(k, v, f, u) avtext_print_unit_integer(tfc, k, v, f, u)
#define print_decibel(k, v) avtext_print_unit_double(tfc, k, v, AV_TEXTFORMAT_VALUE_FMT_DECIBEL, 0)
static void print_integers(AVTextFormatContext *tfc, const char *key,
const void *data, int size, const char *format,
int columns, int bytes, int offset_add)
{
AVBPrint bp;
unsigned offset = 0;
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
av_bprint_chars(&bp, '\n', 1);
while (size) {
av_bprintf(&bp, "%08x: ", offset);
for (int i = 0, l = FFMIN(size, columns); i < l; i++) {
if (bytes == 1) av_bprintf(&bp, format, *(const uint8_t*)data);
else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
data = (const char*)data + bytes;
size--;
}
av_bprint_chars(&bp, '\n', 1);
offset += offset_add;
}
avtext_print_string(tfc, key, bp.str, 0);
}
#define print_val(k, v, u) avtext_print_unit_integer(tfc, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -509,36 +457,12 @@ static inline int show_tags(AVTextFormatContext *tfc, AVDictionary *tags, int se
return ret;
}
static void print_downmix_info(AVTextFormatContext *tfc,
const AVDownmixInfo *downmix_info)
{
switch (downmix_info->preferred_downmix_type) {
case AV_DOWNMIX_TYPE_LORO:
print_str("preferred_downmix_type", "loro");
break;
case AV_DOWNMIX_TYPE_LTRT:
print_str("preferred_downmix_type", "ltrt");
break;
case AV_DOWNMIX_TYPE_DPLII:
print_str("preferred_downmix_type", "dplII");
break;
default:
print_str("preferred_downmix_type", "unknown");
break;
}
print_decibel("center_mix_level_db", downmix_info->center_mix_level);
print_decibel("center_mix_level_ltrt_db", downmix_info->center_mix_level_ltrt);
print_decibel("surround_mix_level_db", downmix_info->surround_mix_level);
print_decibel("surround_mix_level_ltrt_db", downmix_info->surround_mix_level_ltrt);
print_decibel("lfe_mix_level_db", downmix_info->lfe_mix_level);
}
static void print_displaymatrix(AVTextFormatContext *tfc, const int32_t matrix[9])
{
double rotation = av_display_rotation_get(matrix);
if (isnan(rotation))
rotation = 0;
print_integers(tfc, "displaymatrix", matrix, 9, " %11d", 3, 4, 1);
avtext_print_integers(tfc, "displaymatrix", (void*)matrix, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
}
@@ -831,62 +755,6 @@ static void print_dynamic_hdr10_plus(AVTextFormatContext *tfc, const AVDynamicHD
}
}
static void print_dynamic_hdr_smpte2094_app5(AVTextFormatContext *tfc, const AVDynamicHDRSmpte2094App5 *metadata)
{
if (!metadata)
return;
print_int("application_version", metadata->application_version);
print_int("minimum_application_version", metadata->minimum_application_version);
print_int("has_custom_hdr_reference_white_flag", metadata->has_custom_hdr_reference_white_flag);
print_int("has_adaptive_tone_map_flag", metadata->has_adaptive_tone_map_flag);
if (metadata->has_custom_hdr_reference_white_flag)
print_int("hdr_reference_white", metadata->hdr_reference_white);
if (!metadata->has_adaptive_tone_map_flag)
return;
print_int("baseline_hdr_headroom", metadata->baseline_hdr_headroom);
print_int("use_reference_white_tone_mapping_flag", metadata->use_reference_white_tone_mapping_flag);
if (metadata->use_reference_white_tone_mapping_flag)
return;
print_int("num_alternate_images", metadata->num_alternate_images);
print_int("gain_application_space_chromaticities_flag", metadata->gain_application_space_chromaticities_flag);
print_int("has_common_component_mix_params_flag", metadata->has_common_component_mix_params_flag);
print_int("has_common_curve_params_flag", metadata->has_common_curve_params_flag);
if (metadata->gain_application_space_chromaticities_flag == 3) {
for (int i = 0; i < 8; i++)
print_int("gain_application_space_chromaticities", metadata->gain_application_space_chromaticities[i]);
}
for (int a = 0; a < metadata->num_alternate_images; a++) {
print_int("alternate_hdr_headroom", metadata->alternate_hdr_headrooms[a]);
print_int("component_mixing_type", metadata->component_mixing_type[a]);
if (metadata->component_mixing_type[a] == 3) {
for (int k = 0; k < 6; k++) {
print_int("has_component_mixing_coefficient_flag", metadata->has_component_mixing_coefficient_flag[a][k]);
if (metadata->has_component_mixing_coefficient_flag[a][k])
print_int("component_mixing_coefficient", metadata->component_mixing_coefficient[a][k]);
}
}
print_int("gain_curve_num_control_points_minus_1", metadata->gain_curve_num_control_points_minus_1[a]);
print_int("gain_curve_use_pchip_slope_flag", metadata->gain_curve_use_pchip_slope_flag[a]);
for (int c = 0; c <= metadata->gain_curve_num_control_points_minus_1[a]; c++)
print_int("gain_curve_control_point_x", metadata->gain_curve_control_points_x[a][c]);
for (int c = 0; c <= metadata->gain_curve_num_control_points_minus_1[a]; c++)
print_int("gain_curve_control_point_y", metadata->gain_curve_control_points_y[a][c]);
if (!metadata->gain_curve_use_pchip_slope_flag[a]) {
for (int c = 0; c <= metadata->gain_curve_num_control_points_minus_1[a]; c++)
print_int("gain_curve_control_point_theta", metadata->gain_curve_control_points_theta[a][c]);
}
}
}
static void print_dynamic_hdr_vivid(AVTextFormatContext *tfc, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
@@ -1028,7 +896,7 @@ static void print_film_grain_params(AVTextFormatContext *tfc,
avtext_print_section_footer(tfc);
}
for (unsigned uv = 0; uv < 2; uv++) {
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
@@ -1094,8 +962,7 @@ static void print_film_grain_params(AVTextFormatContext *tfc,
}
static void print_pkt_side_data(AVTextFormatContext *tfc,
int width,
int height,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
@@ -1121,7 +988,7 @@ static void print_pkt_side_data(AVTextFormatContext *tfc,
print_int("padding", spherical->padding);
} else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) {
size_t l, t, r, b;
av_spherical_tile_bounds(spherical, width, height,
av_spherical_tile_bounds(spherical, par->width, par->height,
&l, &t, &r, &b);
print_int("bound_left", l);
print_int("bound_top", t);
@@ -1190,12 +1057,6 @@ static void print_pkt_side_data(AVTextFormatContext *tfc,
print_int("crop_right", AV_RL32(sd->data + 12));
} else if (sd->type == AV_PKT_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
} else if (sd->type == AV_PKT_DATA_EXIF) {
print_int("size", sd->size);
} else if (sd->type == AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL && sd->size >= 8) {
print_int("block_additional_id", AV_RB64(sd->data));
if (do_show_data)
avtext_print_data(tfc, "block_additional_data", sd->data + 8, sd->size - 8);
}
}
@@ -1287,16 +1148,6 @@ static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocatio
}
}
static void print_alpha_mode(AVTextFormatContext *tfc, enum AVAlphaMode alpha_mode)
{
const char *val = av_alpha_mode_name(alpha_mode);
if (!val || alpha_mode == AVALPHA_MODE_UNSPECIFIED) {
print_str_opt("alpha_mode", "unspecified");
} else {
print_str("alpha_mode", val);
}
}
static void clear_log(int need_lock)
{
int i;
@@ -1368,7 +1219,7 @@ static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pk
print_time("dts_time", pkt->dts, &st->time_base);
print_duration_ts("duration", pkt->duration);
print_duration_time("duration_time", pkt->duration, &st->time_base);
print_int_fmt("size", pkt->size, AV_TEXTFORMAT_VALUE_FMT_BYTE, unit_byte_str);
print_val("size", pkt->size, unit_byte_str);
if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos);
else print_str_opt("pos", "N/A");
print_fmt("flags", "%c%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_',
@@ -1392,7 +1243,7 @@ static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pk
avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
print_pkt_side_data(tfc, st->codecpar->width, st->codecpar->height, &pkt->side_data[i],
print_pkt_side_data(tfc, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
avtext_print_section_footer(tfc);
}
@@ -1428,9 +1279,6 @@ static void show_subtitle(AVTextFormatContext *tfc, AVSubtitle *sub, AVStream *s
fflush(stdout);
}
static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id);
static void print_frame_side_data(AVTextFormatContext *tfc,
const AVFrame *frame,
const AVStream *stream)
@@ -1444,9 +1292,7 @@ static void print_frame_side_data(AVTextFormatContext *tfc,
avtext_print_section_header(tfc, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DOWNMIX_INFO) {
print_downmix_info(tfc, (AVDownmixInfo *)sd->data);
} else if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
print_displaymatrix(tfc, (const int32_t*)sd->data);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -1471,9 +1317,6 @@ static void print_frame_side_data(AVTextFormatContext *tfc,
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5) {
AVDynamicHDRSmpte2094App5 *metadata = (AVDynamicHDRSmpte2094App5 *)sd->data;
print_dynamic_hdr_smpte2094_app5(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
print_context_light_level(tfc, (AVContentLightMetadata *)sd->data);
} else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) {
@@ -1493,13 +1336,6 @@ static void print_frame_side_data(AVTextFormatContext *tfc,
print_film_grain_params(tfc, fgp);
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
} else if (sd->type == AV_FRAME_DATA_EXIF) {
print_int("size", sd->size);
} else if (sd->type == AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM ||
sd->type == AV_FRAME_DATA_IAMF_DEMIXING_INFO_PARAM ||
sd->type == AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM) {
const AVIAMFParamDefinition *param = (AVIAMFParamDefinition *)sd->data;
print_iamf_param_definition(tfc, NULL, param, SECTION_ID_FRAME_SIDE_DATA);
}
avtext_print_section_footer(tfc);
}
@@ -1533,7 +1369,7 @@ static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *strea
print_duration_time("duration_time", frame->duration, &stream->time_base);
if (fd && fd->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, fd->pkt_pos);
else print_str_opt("pkt_pos", "N/A");
if (fd && fd->pkt_size != -1) print_int_fmt("pkt_size", fd->pkt_size, AV_TEXTFORMAT_VALUE_FMT_BYTE, unit_byte_str);
if (fd && fd->pkt_size != -1) print_val ("pkt_size", fd->pkt_size, unit_byte_str);
else print_str_opt("pkt_size", "N/A");
switch (stream->codecpar->codec_type) {
@@ -1564,7 +1400,6 @@ static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *strea
print_primaries(tfc, frame->color_primaries);
print_color_trc(tfc, frame->color_trc);
print_chroma_location(tfc, frame->chroma_location);
print_alpha_mode(tfc, frame->alpha_mode);
break;
case AVMEDIA_TYPE_AUDIO:
@@ -1796,10 +1631,12 @@ static int read_interval_packets(AVTextFormatContext *tfc, InputFile *ifile,
}
av_packet_unref(pkt);
//Flush remaining frames that are cached in the decoder
for (int i = 0; i < ifile->nb_streams; i++) {
for (i = 0; i < ifile->nb_streams; i++) {
pkt->stream_index = i;
if (do_read_frames) {
while (process_frame(tfc, ifile, frame, pkt, &(int){1}) > 0);
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
}
@@ -1813,33 +1650,17 @@ end:
return ret;
}
static void flush_buffers(InputFile *ifile)
{
int i;
if (!do_read_frames)
return;
for (i = 0; i < ifile->nb_streams; i++) {
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
}
static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
int64_t cur_ts = fmt_ctx->start_time;
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
ret = read_interval_packets(tfc, ifile, &interval, &cur_ts);
} else {
for (int i = 0; i < read_intervals_nb; i++) {
/* flushing buffers can reset parts of the private context which may be
* read by show_streams(), so only flush between each read_interval */
if (i)
flush_buffers(ifile);
for (i = 0; i < read_intervals_nb; i++) {
ret = read_interval_packets(tfc, ifile, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
@@ -1852,7 +1673,7 @@ static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
static void print_dispositions(AVTextFormatContext *tfc, uint32_t disposition, SectionID section_id)
{
avtext_print_section_header(tfc, NULL, section_id);
for (unsigned i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
@@ -1934,10 +1755,6 @@ static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int s
print_str("codec_tag_string", av_fourcc2str(par->codec_tag));
print_fmt("codec_tag", "0x%04"PRIx32, par->codec_tag);
av_bprint_clear(&pbuf);
if (!av_mime_codec_str(par, stream->avg_frame_rate, &pbuf))
print_str("mime_codec_string", pbuf.str);
switch (par->codec_type) {
case AVMEDIA_TYPE_VIDEO:
print_int("width", par->width);
@@ -1986,7 +1803,7 @@ static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int s
else
print_str_opt("field_order", "unknown");
if (dec_ctx && do_read_frames)
if (dec_ctx)
print_int("refs", dec_ctx->refs);
break;
@@ -2075,7 +1892,7 @@ static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int s
if (stream->codecpar->nb_coded_side_data) {
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
print_pkt_side_data(tfc, stream->codecpar->width, stream->codecpar->height, &stream->codecpar->coded_side_data[i],
print_pkt_side_data(tfc, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
avtext_print_section_footer(tfc);
}
@@ -2092,10 +1909,10 @@ static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int s
static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAMS);
for (int i = 0; i < ifile->nb_streams; i++)
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(tfc, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
@@ -2109,7 +1926,7 @@ static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
@@ -2123,7 +1940,7 @@ static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *p
goto end;
avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_STREAMS);
for (unsigned i = 0; i < program->nb_stream_indexes; i++) {
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(tfc, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
if (ret < 0)
@@ -2140,10 +1957,10 @@ end:
static int show_programs(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAMS);
for (unsigned i = 0; i < fmt_ctx->nb_programs; i++) {
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
@@ -2167,7 +1984,7 @@ static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (unsigned i = 0; i < tile_grid->nb_tiles; i++) {
for (int i = 0; i < tile_grid->nb_tiles; i++) {
avtext_print_section_header(tfc, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
@@ -2175,15 +1992,6 @@ static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup
avtext_print_section_footer(tfc);
}
avtext_print_section_footer(tfc);
if (tile_grid->nb_coded_side_data) {
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SIDE_DATA_LIST);
for (int i = 0; i < tile_grid->nb_coded_side_data; i++) {
print_pkt_side_data(tfc, tile_grid->width, tile_grid->height, &tile_grid->coded_side_data[i],
SECTION_ID_STREAM_GROUP_SIDE_DATA);
avtext_print_section_footer(tfc);
}
avtext_print_section_footer(tfc);
}
avtext_print_section_footer(tfc);
}
@@ -2191,21 +1999,12 @@ static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *na
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
if (section_id == SECTION_ID_FRAME_SIDE_DATA)
subsection_id = SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST;
else {
av_assert0(sections[section_id].children_ids[0] != -1);
subsection_id = sections[section_id].children_ids[0];
}
av_assert0(sections[subsection_id].children_ids[0] != -1);
subsection_id = sections[section_id].children_ids[0];
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
// When printing as part of side-data, skip opening a section
if (section_id != SECTION_ID_FRAME_SIDE_DATA)
avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
if (name)
print_str("name", name);
av_assert0(parameter_section_id != -1);
avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
print_int("parameter_id", param->parameter_id);
@@ -2214,7 +2013,7 @@ static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *na
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
avtext_print_section_header(tfc, NULL, subsection_id);
for (unsigned i = 0; i < param->nb_subblocks; i++) {
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
@@ -2248,24 +2047,18 @@ static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *na
}
if (param->nb_subblocks > 0)
avtext_print_section_footer(tfc); // subsection_id
if (section_id != SECTION_ID_FRAME_SIDE_DATA)
avtext_print_section_footer(tfc); // section_id
avtext_print_section_footer(tfc); // section_id
}
static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (unsigned i = 0; i < audio_element->nb_layers; i++) {
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
avtext_print_section_header(tfc, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
@@ -2274,12 +2067,8 @@ static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVSt
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
print_int("output_gain_flags", layer->output_gain_flags);
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
if (layer->ambisonics_mode == AV_IAMF_AMBISONICS_MODE_PROJECTION)
print_list_fmt("demixing_matrix", "%d/%d", layer->nb_demixing_matrix, 1, layer->demixing_matrix[idx].num,
layer->demixing_matrix[idx].den);
}
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
@@ -2290,8 +2079,6 @@ static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVSt
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
av_bprint_finalize(&pbuf, NULL);
}
static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmix *submix)
@@ -2301,7 +2088,7 @@ static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmi
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (unsigned i = 0; i < submix->nb_elements; i++) {
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
avtext_print_section_header(tfc, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
@@ -2324,7 +2111,7 @@ static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmi
if (submix->output_mix_config)
print_iamf_param_definition(tfc, "output_mix_config", submix->output_mix_config,
SECTION_ID_STREAM_GROUP_PIECE);
for (unsigned i = 0; i < submix->nb_layouts; i++) {
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
avtext_print_section_header(tfc, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
@@ -2354,7 +2141,7 @@ static void print_iamf_mix_presentation_params(AVTextFormatContext *tfc, const A
print_str(annotation->key, annotation->value);
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (unsigned i = 0; i < mix_presentation->nb_submixes; i++)
for (int i = 0; i < mix_presentation->nb_submixes; i++)
print_iamf_submix_params(tfc, mix_presentation->submixes[i]);
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
@@ -2376,7 +2163,7 @@ static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStrea
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int ret = 0;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP);
@@ -2401,7 +2188,7 @@ static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStrea
goto end;
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (unsigned i = 0; i < stg->nb_streams; i++) {
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
ret = show_stream(tfc, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
if (ret < 0)
@@ -2419,10 +2206,10 @@ end:
static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUPS);
for (unsigned i = 0; i < fmt_ctx->nb_stream_groups; i++) {
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
ret = show_stream_group(tfc, ifile, stg);
@@ -2436,10 +2223,10 @@ static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
static int show_chapters(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int ret = 0;
int i, ret = 0;
avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTERS);
for (unsigned i = 0; i < fmt_ctx->nb_chapters; i++) {
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTER);
@@ -2476,7 +2263,7 @@ static int show_format(AVTextFormatContext *tfc, InputFile *ifile)
}
print_time("start_time", fmt_ctx->start_time, &AV_TIME_BASE_Q);
print_time("duration", fmt_ctx->duration, &AV_TIME_BASE_Q);
if (size >= 0) print_int_fmt("size", size, AV_TEXTFORMAT_VALUE_FMT_BYTE, unit_byte_str);
if (size >= 0) print_val ("size", size, unit_byte_str);
else print_str_opt("size", "N/A");
if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
else print_str_opt("bit_rate", "N/A");
@@ -2497,69 +2284,10 @@ static void show_error(AVTextFormatContext *tfc, int err)
avtext_print_section_footer(tfc);
}
static int get_decoder_by_name(const char *codec_name, const AVCodec **codec)
{
if (codec_name == NULL)
return 0;
*codec = avcodec_find_decoder_by_name(codec_name);
if (*codec == NULL) {
av_log(NULL, AV_LOG_ERROR,
"No codec could be found with name '%s'\n", codec_name);
return AVERROR(EINVAL);
}
return 0;
}
static int set_decoders(AVFormatContext *fmt_ctx)
{
int ret;
#define GET_DECODER(type_) \
ret = get_decoder_by_name(type_##_codec_name, &fmt_ctx->type_##_codec); \
if (ret < 0) return ret;
GET_DECODER(audio);
GET_DECODER(data);
GET_DECODER(subtitle);
GET_DECODER(video);
return 0;
}
static const AVCodec *get_decoder_for_stream(AVFormatContext *fmt_ctx, AVStream *stream)
{
const AVCodec *codec = NULL;
switch (stream->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO: codec = fmt_ctx->video_codec; break;
case AVMEDIA_TYPE_AUDIO: codec = fmt_ctx->audio_codec; break;
case AVMEDIA_TYPE_SUBTITLE: codec = fmt_ctx->subtitle_codec; break;
case AVMEDIA_TYPE_DATA: codec = fmt_ctx->data_codec; break;
}
if (codec != NULL)
return codec;
if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
av_log(NULL, AV_LOG_WARNING,
"Failed to probe codec for input stream %d\n", stream->index);
return NULL;
}
codec = avcodec_find_decoder(stream->codecpar->codec_id);
if (codec == NULL) {
av_log(NULL, AV_LOG_WARNING,
"Unsupported codec with id %d for input stream %d\n",
stream->codecpar->codec_id, stream->index);
return NULL;
}
return codec;
}
static int open_input_file(InputFile *ifile, const char *filename,
const char *print_filename)
{
int err;
int err, i;
AVFormatContext *fmt_ctx = NULL;
const AVDictionaryEntry *t = NULL;
int scan_all_pmts_set = 0;
@@ -2568,9 +2296,6 @@ static int open_input_file(InputFile *ifile, const char *filename,
if (!fmt_ctx)
return AVERROR(ENOMEM);
err = set_decoders(fmt_ctx);
if (err < 0)
return err;
if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
scan_all_pmts_set = 1;
@@ -2600,7 +2325,7 @@ static int open_input_file(InputFile *ifile, const char *filename,
err = avformat_find_stream_info(fmt_ctx, opts);
for (int i = 0; i < orig_nb_streams; i++)
for (i = 0; i < orig_nb_streams; i++)
av_dict_free(&opts[i]);
av_freep(&opts);
@@ -2618,17 +2343,27 @@ static int open_input_file(InputFile *ifile, const char *filename,
ifile->nb_streams = fmt_ctx->nb_streams;
/* bind a decoder to each input stream */
for (unsigned i = 0; i < fmt_ctx->nb_streams; i++) {
for (i = 0; i < fmt_ctx->nb_streams; i++) {
InputStream *ist = &ifile->streams[i];
AVStream *stream = fmt_ctx->streams[i];
const AVCodec *codec;
ist->st = stream;
codec = get_decoder_for_stream(fmt_ctx, stream);
if (!codec)
if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
av_log(NULL, AV_LOG_WARNING,
"Failed to probe codec for input stream %d\n",
stream->index);
continue;
}
codec = avcodec_find_decoder(stream->codecpar->codec_id);
if (!codec) {
av_log(NULL, AV_LOG_WARNING,
"Unsupported codec with id %d for input stream %d\n",
stream->codecpar->codec_id, stream->index);
continue;
}
{
AVDictionary *opts;
@@ -2676,9 +2411,10 @@ static int open_input_file(InputFile *ifile, const char *filename,
static void close_input_file(InputFile *ifile)
{
int i;
/* close decoder for each stream */
for (int i = 0; i < ifile->nb_streams; i++)
for (i = 0; i < ifile->nb_streams; i++)
avcodec_free_context(&ifile->streams[i].dec_ctx);
av_freep(&ifile->streams);
@@ -2691,7 +2427,7 @@ static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
int ret;
int ret, i;
int section_id;
do_analyze_frames = do_analyze_frames && do_show_streams;
@@ -2711,7 +2447,7 @@ static int probe_file(AVTextFormatContext *tfc, const char *filename,
REALLOCZ_ARRAY_STREAM(streams_with_closed_captions,0,ifile.fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(streams_with_film_grain,0,ifile.fmt_ctx->nb_streams);
for (unsigned i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
for (i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
if (stream_specifier) {
ret = avformat_match_stream_specifier(ifile.fmt_ctx,
ifile.fmt_ctx->streams[i],
@@ -2774,10 +2510,6 @@ end:
av_freep(&selected_streams);
av_freep(&streams_with_closed_captions);
av_freep(&streams_with_film_grain);
av_freep(&audio_codec_name);
av_freep(&data_codec_name);
av_freep(&subtitle_codec_name);
av_freep(&video_codec_name);
return ret;
}
@@ -2914,24 +2646,23 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
EntrySelection *selection = &selected_entries[section_id];
struct AVTextFormatSection *section = &sections[section_id];
selection->show_all_entries = show_all_entries;
section->show_all_entries = show_all_entries;
if (show_all_entries) {
const AVTextFormatSection *section = &sections[section_id];
for (const int *id = section->children_ids; *id != -1; id++)
mark_section_show_entries(*id, show_all_entries, entries);
} else {
av_dict_copy(&selection->entries_to_show, entries, 0);
av_dict_copy(&section->entries_to_show, entries, 0);
}
}
static int match_section(const char *section_name,
int show_all_entries, AVDictionary *entries)
{
int ret = 0;
int i, ret = 0;
for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
const struct AVTextFormatSection *section = &sections[i];
if (!strcmp(section_name, section->name) ||
(section->unique_name && !strcmp(section_name, section->unique_name))) {
@@ -3233,36 +2964,6 @@ static int opt_sections(void *optctx, const char *opt, const char *arg)
return 0;
}
static int opt_codec(void *optctx, const char *opt, const char *arg)
{
const char *spec = strchr(opt, ':');
const char **name;
if (!spec) {
av_log(NULL, AV_LOG_ERROR,
"No media specifier was specified for '%s' in option '%s'. Use -%s:<media_spec> "
"where <media_spec> can be one of: 'a' (audio), 'v' (video), 's' (subtitle), 'd' (data)\n",
arg, opt, opt);
return AVERROR(EINVAL);
}
spec++;
switch (spec[0]) {
case 'a' : name = &audio_codec_name; break;
case 'd' : name = &data_codec_name; break;
case 's' : name = &subtitle_codec_name; break;
case 'v' : name = &video_codec_name; break;
default:
av_log(NULL, AV_LOG_ERROR,
"Invalid media specifier '%s' in option '%s'. "
"Must be one of: 'a' (audio), 'v' (video), 's' (subtitle), 'd' (data)\n", spec, opt);
return AVERROR(EINVAL);
}
av_freep(name);
*name = av_strdup(arg);
return *name ? 0 : AVERROR(ENOMEM);
}
static int opt_show_versions(void *optctx, const char *opt, const char *arg)
{
mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL);
@@ -3306,7 +3007,6 @@ static const OptionDef real_options[] = {
{ "of", OPT_TYPE_STRING, 0, { &output_format }, "alias for -output_format", "format" },
{ "select_streams", OPT_TYPE_STRING, 0, { &stream_specifier }, "select the specified streams", "stream_specifier" },
{ "sections", OPT_TYPE_FUNC, OPT_EXIT, {.func_arg = opt_sections}, "print sections structure and section information, and exit" },
{ "data_dump_format", OPT_TYPE_STRING, 0, { &data_dump_format }, "set data dump format (available formats are: xxd, base64)" },
{ "show_data", OPT_TYPE_BOOL, 0, { &do_show_data }, "show packets data" },
{ "show_data_hash", OPT_TYPE_STRING, 0, { &show_data_hash }, "show packets data hash" },
{ "show_error", OPT_TYPE_FUNC, 0, { .func_arg = &opt_show_error }, "show probing error" },
@@ -3339,19 +3039,14 @@ static const OptionDef real_options[] = {
{ "print_filename", OPT_TYPE_FUNC, OPT_FUNC_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"},
{ "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info },
"read and decode the streams to fill missing information with heuristics" },
{ "c", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
{ "codec", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "alias for -c (force decoder)", "decoder_name" },
{ NULL, },
};
static inline int check_section_show_entries(int section_id)
{
const EntrySelection *selection = &selected_entries[section_id];
if (selection->show_all_entries || selection->entries_to_show)
struct AVTextFormatSection *section = &sections[section_id];
if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
return 1;
const AVTextFormatSection *section = &sections[section_id];
for (const int *id = section->children_ids; *id != -1; id++)
if (check_section_show_entries(*id))
return 1;
@@ -3370,8 +3065,7 @@ int main(int argc, char **argv)
AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
int ret, input_ret;
AVTextFormatDataDump data_dump_format_id = AV_TEXTFORMAT_DATADUMP_XXD;
int ret, input_ret, i;
init_dynload();
@@ -3456,18 +3150,6 @@ int main(int argc, char **argv)
goto end;
}
if (data_dump_format) {
if (!strcmp(data_dump_format, "xxd")) {
data_dump_format_id = AV_TEXTFORMAT_DATADUMP_XXD;
} else if (!strcmp(data_dump_format, "base64")) {
data_dump_format_id = AV_TEXTFORMAT_DATADUMP_BASE64;
} else {
av_log(NULL, AV_LOG_ERROR, "Unknown data dump format with name '%s'\n", data_dump_format);
ret = AVERROR(EINVAL);
goto end;
}
}
if (output_filename) {
ret = avtextwriter_create_file(&wctx, output_filename);
} else
@@ -3477,13 +3159,11 @@ int main(int argc, char **argv)
goto end;
AVTextFormatOptions tf_options = {
.is_key_selected = is_key_selected_callback,
.show_optional_fields = show_optional_fields,
.show_value_unit = show_value_unit,
.use_value_prefix = use_value_prefix,
.use_byte_value_binary_prefix = use_byte_value_binary_prefix,
.use_value_sexagesimal_format = use_value_sexagesimal_format,
.data_dump_format = data_dump_format_id,
};
if ((ret = avtext_context_open(&tctx, f, wctx, f_args, sections, FF_ARRAY_ELEMS(sections), tf_options, show_data_hash)) >= 0) {
@@ -3535,8 +3215,8 @@ end:
av_freep(&read_intervals);
uninit_opts();
for (size_t i = 0; i < FF_ARRAY_ELEMS(selected_entries); ++i)
av_dict_free(&selected_entries[i].entries_to_show);
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
av_dict_free(&(sections[i].entries_to_show));
avformat_network_deinit();
+29 -10
View File
@@ -33,7 +33,6 @@
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "libavutil/dict.h"
#include "libavutil/common.h"
@@ -75,7 +74,7 @@ typedef enum {
SECTION_ID_ENCODER,
} SectionID;
static const AVTextFormatSection sections[] = {
static struct AVTextFormatSection sections[] = {
[SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER, { SECTION_ID_FILTERGRAPHS, SECTION_ID_INPUTFILES, SECTION_ID_OUTPUTFILES, SECTION_ID_DECODERS, SECTION_ID_ENCODERS, SECTION_ID_STREAMLINKS, -1 } },
[SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
@@ -141,7 +140,7 @@ typedef struct GraphPrintContext {
#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
#define print_str_opt(k, v) avtext_print_string(tfc, k, v, gpc->opt_flags)
#define print_val(k, v, u) avtext_print_unit_integer(tfc, k, v, AV_TEXTFORMAT_VALUE_FMT_INT, u)
#define print_val(k, v, u) avtext_print_unit_integer(tfc, k, v, u)
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&gpc->pbuf); \
@@ -272,7 +271,7 @@ static void print_link(GraphPrintContext *gpc, AVFilterLink *link)
}
if (link->w && link->h) {
if (tfc->opts.show_value_unit) {
if (tfc->show_value_unit) {
print_fmt("size", "%dx%d", link->w, link->h);
} else {
print_int("width", link->w);
@@ -293,7 +292,7 @@ static void print_link(GraphPrintContext *gpc, AVFilterLink *link)
////print_str("format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
if (link->w && link->h) {
if (tfc->opts.show_value_unit) {
if (tfc->show_value_unit) {
print_fmt("size", "%dx%d", link->w, link->h);
} else {
print_int("width", link->w);
@@ -307,7 +306,7 @@ static void print_link(GraphPrintContext *gpc, AVFilterLink *link)
av_channel_layout_describe(&link->ch_layout, layout_string, sizeof(layout_string));
print_str("channel_layout", layout_string);
print_val("channels", link->ch_layout.nb_channels, "ch");
if (tfc->opts.show_value_unit)
if (tfc->show_value_unit)
print_fmt("sample_rate", "%d.1 kHz", link->sample_rate / 1000);
else
print_val("sample_rate", link->sample_rate, "Hz");
@@ -471,6 +470,12 @@ static void print_filter(GraphPrintContext *gpc, const AVFilterContext *filter,
avtext_print_section_footer(tfc); // SECTION_ID_FILTER
}
static void init_sections(void)
{
for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++)
sections[i].show_all_entries = 1;
}
static void print_filtergraph_single(GraphPrintContext *gpc, FilterGraph *fg, AVFilterGraph *graph)
{
AVTextFormatContext *tfc = gpc->tfc;
@@ -871,6 +876,7 @@ static int init_graphprint(GraphPrintContext **pgpc, AVBPrint *target_buf)
GraphPrintContext *gpc = NULL;
int ret;
init_sections();
*pgpc = NULL;
av_bprint_init(target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
@@ -913,8 +919,8 @@ static int init_graphprint(GraphPrintContext **pgpc, AVBPrint *target_buf)
gpc->id_prefix_num = atomic_fetch_add(&prefix_num, 1);
gpc->is_diagram = !!(tfc->formatter->flags & AV_TEXTFORMAT_FLAG_IS_DIAGRAM_FORMATTER);
if (gpc->is_diagram) {
tfc->opts.show_value_unit = 1;
tfc->opts.show_optional_fields = -1;
tfc->show_value_unit = 1;
tfc->show_optional_fields = -1;
gpc->opt_flags = AV_TEXTFORMAT_PRINT_STRING_OPTIONAL;
gpc->skip_buffer_filters = 1;
////} else {
@@ -947,13 +953,16 @@ fail:
int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
{
av_assert2(fg);
GraphPrintContext *gpc = NULL;
AVTextFormatContext *tfc;
AVBPrint *target_buf = &fg->graph_print_buf;
int ret;
if (!fg) {
av_log(NULL, AV_LOG_ERROR, "Invalid filter graph provided\n");
return AVERROR(EINVAL);
}
if (target_buf->len)
av_bprint_finalize(target_buf, NULL);
@@ -961,6 +970,11 @@ int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
if (ret)
return ret;
if (!gpc) {
av_log(NULL, AV_LOG_ERROR, "Failed to initialize graph print context\n");
return AVERROR(ENOMEM);
}
tfc = gpc->tfc;
// Due to the threading model each graph needs to print itself into a buffer
@@ -997,6 +1011,11 @@ static int print_filtergraphs_priv(FilterGraph **graphs, int nb_graphs, InputFil
if (ret)
goto cleanup;
if (!gpc) {
ret = AVERROR(ENOMEM);
goto cleanup;
}
tfc = gpc->tfc;
avtext_print_section_header(tfc, NULL, SECTION_ID_ROOT);
+12 -25
View File
@@ -23,7 +23,6 @@
#include <stdio.h>
#include "cmdutils.h"
#include "fopen_utf8.h"
#include "opt_common.h"
#include "libavutil/avassert.h"
@@ -68,11 +67,6 @@ enum show_muxdemuxers {
SHOW_MUXERS,
};
enum show_codec {
SHOW_DECODER,
SHOW_ENCODER,
};
static FILE *report_file;
static int report_file_level = AV_LOG_DEBUG;
@@ -326,12 +320,6 @@ static void print_codec(const AVCodec *c)
printf("hardware ");
if (c->capabilities & AV_CODEC_CAP_HYBRID)
printf("hybrid ");
if (c->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)
printf("reorderedopaque ");
if (c->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)
printf("flush ");
if (c->capabilities & AV_CODEC_CAP_ENCODER_RECON_FRAME)
printf("reconframe ");
if (!c->capabilities)
printf("none");
printf("\n");
@@ -602,9 +590,9 @@ int show_help(void *optctx, const char *opt, const char *arg)
if (!*topic) {
show_help_default(topic, par);
} else if (!strcmp(topic, "decoder")) {
show_help_codec(par, SHOW_DECODER);
show_help_codec(par, 0);
} else if (!strcmp(topic, "encoder")) {
show_help_codec(par, SHOW_ENCODER);
show_help_codec(par, 1);
} else if (!strcmp(topic, "demuxer")) {
show_help_demuxer(par);
} else if (!strcmp(topic, "muxer")) {
@@ -719,16 +707,16 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
/* print decoders/encoders when there's more than one or their
* names are different from codec name */
while ((codec = next_codec_for_id(desc->id, &iter, SHOW_DECODER))) {
while ((codec = next_codec_for_id(desc->id, &iter, 0))) {
if (strcmp(codec->name, desc->name)) {
print_codecs_for_id(desc->id, SHOW_DECODER);
print_codecs_for_id(desc->id, 0);
break;
}
}
iter = NULL;
while ((codec = next_codec_for_id(desc->id, &iter, SHOW_ENCODER))) {
while ((codec = next_codec_for_id(desc->id, &iter, 1))) {
if (strcmp(codec->name, desc->name)) {
print_codecs_for_id(desc->id, SHOW_ENCODER);
print_codecs_for_id(desc->id, 1);
break;
}
}
@@ -785,12 +773,12 @@ static int print_codecs(int encoder)
int show_decoders(void *optctx, const char *opt, const char *arg)
{
return print_codecs(SHOW_DECODER);
return print_codecs(0);
}
int show_encoders(void *optctx, const char *opt, const char *arg)
{
return print_codecs(SHOW_ENCODER);
return print_codecs(1);
}
int show_bsfs(void *optctx, const char *opt, const char *arg)
@@ -820,8 +808,7 @@ int show_filters(void *optctx, const char *opt, const char *arg)
" A = Audio input/output\n"
" V = Video input/output\n"
" N = Dynamic number and/or type of input/output\n"
" | = Source or sink filter\n"
" ------\n");
" | = Source or sink filter\n");
while ((filter = av_filter_iterate(&opaque))) {
descr_cur = descr;
for (i = 0; i < 2; i++) {
@@ -887,7 +874,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
const char *name = NULL;
const char *long_name = NULL;
if (muxdemuxers != SHOW_DEMUXERS) {
if (muxdemuxers !=SHOW_DEMUXERS) {
ofmt_opaque = NULL;
while ((ofmt = av_muxer_iterate(&ofmt_opaque))) {
is_dev = is_device(ofmt->priv_class);
@@ -1003,7 +990,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg)
#endif
while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) {
av_unused enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
printf("%c%c%c%c%c %-16s %d %3d %d",
sws_isSupportedInput (pix_fmt) ? 'I' : '.',
sws_isSupportedOutput(pix_fmt) ? 'O' : '.',
@@ -1217,7 +1204,7 @@ int init_report(const char *env, FILE **file)
if (!envlevel)
report_file_level = FFMAX(report_file_level, prog_loglevel);
report_file = fopen_utf8(filename.str, "w");
report_file = fopen(filename.str, "w");
if (!report_file) {
int ret = AVERROR(errno);
av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
+2 -3
View File
@@ -41,9 +41,9 @@ int show_sources(void *optctx, const char *opt, const char *arg);
#if CONFIG_AVDEVICE
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \
{ "sources" , OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_sources }, \
{ "sources" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sources }, \
"list sources of the input device", "device" }, \
{ "sinks" , OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_sinks }, \
{ "sinks" , OPT_TYPE_FUNC, OPT_EXIT | OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = show_sinks }, \
"list sinks of the output device", "device" }, \
#else
@@ -198,7 +198,6 @@ int opt_cpucount(void *optctx, const char *opt, const char *arg);
#define CMDUTILS_COMMON_OPTIONS \
{ "L", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_license }, "show license" }, \
{ "license", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_license }, "show license" }, \
{ "h", OPT_TYPE_FUNC, OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
{ "?", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \
{ "help", OPT_TYPE_FUNC, OPT_EXIT | OPT_EXPERT, { .func_arg = show_help }, "show help", "topic" }, \

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