Compare commits

..

304 Commits

Author SHA1 Message Date
nyanmisaka ce3c09c101 avutil/hwcontext_cuda: fix yuv420p V/U plane overlap in cuda_get_buffer()
Odd-height yuv420p result in incorrect calculations of the U-plane
address offset. The last row of the V-plane overlapped with and was
overwritten by the first row of the U-plane, leading to chroma artifacts.

```
ffmpeg -init_hw_device cuda=cu -filter_hw_device cu -f lavfi -i \
testsrc=s=1920x1081,format=yuv420p -vf hwupload -c:v hevc_nvenc \
-vframes 1 -y <OUTPUT>
```

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
(cherry picked from commit 3f6bf150cb)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 17:41:14 +02:00
Niklas Haas 584952257a avfilter/vf_scale_cuda: fix inverted downscaling check
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 6baf561303)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:57:01 +02:00
Niklas Haas 1f463e44dc avfilter/vf_scale_cuda: allocate inter buffer with correct subsampling
Since the input and output format can differ (e.g. 444 -> 420), we need to
reference the correct subsampling for the partially applied filter.

Keep track of this in the CUDATex itself.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 01972b4f85)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:56:38 +02:00
Niklas Haas 578c2dbf1d avfilter/vf_scale_cuda: allocate intermediate buffer directly
Instead of going via an AVFrame at all. This will allow us to fix the
intermediate chroma plane size for split downscaling.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 420a9e90b8)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:56:12 +02:00
Niklas Haas 1166148417 avfilter/vf_scale_cuda: use persistent intermediate CUDATex
Instead of re-creating this object every frame.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit e79e9f06ba)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:55:48 +02:00
Niklas Haas b7d139be74 avfilter/vf_scale_cuda: defer buffer allocation to setup_filters()
At this point, s->hwctx and CudaFunctions * are available.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 4289a29bb0)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:55:10 +02:00
Niklas Haas c69542aa9b avfilter/vf_scale_cuda: introduce CUDATex and mapping helper
I want to disentangle the internal logic from AVFrame, because some
intermediate states (e.g. for partially subsampled chroma with simultaneous
scaling) may not directly map to a valid AVPixelFormat.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit fef976b197)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:54:37 +02:00
Niklas Haas 45179413ee avfilter/vf_scale_cuda: add fail: label (cosmetic)
Make the next commit a bit easier to review.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 61750318db)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:54:12 +02:00
Niklas Haas eac505e3e8 avfilter/vf_scale_cuda: eliminate redundant context push/pop
This is already done by cudascale_filter_frame().

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 0c3f04a97c)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:53:50 +02:00
Diego de Souza 90b5fc8479 avfilter/cuda: support P012/P212 and MSB 4:4:4 in scale/transpose/thumbnail
NVDEC and CUVID now output AV_PIX_FMT_P012 (12-bit 4:2:0), AV_PIX_FMT_P212
(12-bit 4:2:2) and AV_PIX_FMT_YUV444P10MSB / AV_PIX_FMT_YUV444P12MSB
(10/12-bit 4:4:4) for high-bit-depth content, but these CUDA filters
rejected the formats in their supported-format lists, breaking pipelines
such as "-hwaccel cuda ... -vf scale_cuda" on 12-bit input.

These formats use 16-bit sample storage, and the filters select their CUDA
kernel by byte-storage size and plane layout, not by the number of valid
bits, so they can reuse the existing 16-bit kernels:

- scale_cuda: P012/P212 -> "semiplanar16", YUV444P10MSB/YUV444P12MSB ->
  "planar16".
- transpose_cuda: the ushort/ushort2 kernels are chosen from the pixel
  descriptor (byte size + channel count); just allow the new formats.
- thumbnail_cuda: P012 reuses the P010/P016 path and the MSB 4:4:4 formats
  reuse the YUV444P16 path; P012 is added to the 4:2:0 chroma-histogram
  scaling as well. (thumbnail has no 4:2:2 path, so P212 is not added.)

The CUDA deinterlacers (bwdif_cuda, yadif_cuda) already accept any format
with <= 2 bytes per sample and <= 2 channels, so they need no change. The
8-bit-only filters (overlay_cuda, pad_cuda, bilateral_cuda, chromakey_cuda,
colorspace_cuda) do not support high bit depths and are left untouched.

Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
(cherry-picked from commit df94900c98)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:53:21 +02:00
Niklas Haas 93aeb8edd3 avfilter/vf_scale_cuda: re-indent after previous change
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 9420146e6d)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:52:38 +02:00
Niklas Haas c9fc3f79d0 avfilter/vf_scale_cuda: add use_filters option
This may be faster or slower than the existing specialized kernels,
so I opted not to prefer it by default. I also deliberately didn't expose
additional filter function capabilites yet.

The main motivating reason here is to get correct anti-aliasing behavior
when downscaling, which is currently completely broken.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 5d0748243f)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:52:14 +02:00
Niklas Haas f99a022cbf avfilter/vf_scale_cuda: add generic 1D filter kernel
This can be useful for any sort of separable filtering with arbitrary
weights.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 469281fa50)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:51:52 +02:00
Niklas Haas d215ba76a0 avfilter/vf_scale_cuda: generalize kernel signature to accept weights
Ignored for now by the existing fixed function kernels.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit d98cc462f6)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:51:32 +02:00
Niklas Haas 6d00e599fd avfilter/scale_filters: add internal copy of libswscale/filters.c
Useful for GPU-based filters, which may also need to compute filter weights.
Since we cannot cross-link to internal functions, we need to recompile this
helper inside libavfilter.c.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit b400791442)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:51:11 +02:00
Niklas Haas 53a987a274 swscale/filters: add ability to set a virtual output size
Odd-size luma planes are not exact multiples of the chroma plane; but the
sample grid is still matched as though it were. We need to account for this
when translating a luma sample to the corresponding chroma sample coordinates.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit fa1ca69a8b)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:50:44 +02:00
Niklas Haas f866705d4d swscale/filters: add option for adding an input pixel offset
This is needed for chroma subsampling, which requires a different filter
offset for chroma subsamples (according to the frame's chroma location).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 8215e9bbea)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 15:49:48 +02:00
Niklas Haas 792cde9879 swscale/filters: write new filter LUT generation code
This is a complete rewrite of the math in swscale/utils.c initFilter(), using
floating point math and with a bit more polished UI and internals. I have
also included a substantial number of improvements, including a method to
numerically compute the true filter support size from the parameters, and a
more robust logic for the edge conditions. The upshot of these changes is
that the filter weight computation is now much simpler and faster, and with
fewer edge cases.

I copy/pasted the actual underlying kernel functions from libplacebo, so this
math is already quite battle-tested. I made some adjustments to the defaults
to align with the existing defaults in libswscale, for backwards compatibility.

Note that this commit introduces a lot more filter kernels than what we
actually expose; but they are cheap to carry around, don't take up binary
space, and will probably save some poor soul from incorrectly reimplementing
them in the future. Plus, I have plans to expand the list of functions down
the line, so it makes sense to just define them all, even if we don't
necessarily use them yet.

Backported-from: 475b11b2e0

Since this depended on changes to the public swscale API, I have instead
added the necessary enums/defines to filters.h itself for now.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-29 15:31:21 +02:00
Niklas Haas dba917bab5 fftools/ffmpeg_demux: only throttle readrate on the slowest stream
If streams are badly interleaved, then the readrate logic can end up
accumulating an ever-growing lag. Rather than looping over each stream
and sleeping for each stream individually based on the local DTS and lag
logic, pull the sleep out of the loop and only sleep once based on the
furthest-behind stream (i.e. the stream contributing the lowest sleep
duration).

To reproduce:

$ ./ffmpeg -re -i fallbeatcaptiontest.mp4 -c copy -f null -t 10 -

Before this commit, this would run at ~0.7x and accumulate an infinitely
growing lag in one stream. After this commit, both streams run at ~1x as
expected, after an initial burst period due to the bad (1s granularity)
interleaving.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry picked from commit de6bcf5c05)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 12:34:07 +02:00
Niklas Haas 9193beee0d fftools/ffmpeg_demux: remove unused variable
This is a dead assignment except on a single branch, so just define it
locally.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry picked from commit e7be06c8bd)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 12:34:07 +02:00
Niklas Haas eb98bef9d2 fftools/ffmpeg_demux: skip finished/unstarted streams in readrate_sleep()
This shouldn't affect the actual behavior, as the initialization of ds->dts
(implicitly zero'd) and the previous calculation of stream_ts_offset
guarantees that the `if (pts <= stream_ts_offset) continue;` branch fires.

Mainly a minor clarification of the code for the upcoming refactor.

Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry picked from commit 5c877416a5)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-06-29 12:34:07 +02:00
Michael Niedermayer 38b88335f9 Bump for 8.1.2
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:33:35 +02:00
Michael Niedermayer 241723a2ac Changelog: update
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:09:47 +02:00
Michael Niedermayer b8ae2fb714 swscale/x86/rgb_2_rgb: fix uyvytoyuv422 overwrite on odd width
uyvytoyuv422 converts packed UYVY, whose macroblocks are pixel pairs, and
the SIMD code only handled even widths. On an odd width the trailing half
macroblock made the kernel write past the end of the Y/U/V destinations:
the AVX512ICL masked tail dropped the odd pixel and the fall-through
re-entered the SIMD loop, writing a full mmsize*2 chunk past the planes
(127 bytes of Y, 63 of U and 63 of V); the sse2/avx/avx2 scalar tail
wrote one byte past the Y plane.

Process only whole pairs and emit the trailing odd column from a small
per-row epilogue that matches uyvytoyuv422_c (ydst[w-1] = src[2w-1],
udst[cw-1] = src[2w-2], vdst[cw-1] = src[2w]).

All four SIMD variants are now bit-exact with the C reference for even and
odd widths and no longer overwrite the destination. Verified on AVX512ICL
hardware (Ryzen 9 9950X) with checkasm.

Found-by: Claude (Anthropic). Human-verified and reported by Omkhar Arasaratnam <omkhar@linkedin.com>.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 21782b7b31)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:08:30 +02:00
Michael Niedermayer 86590257a5 swscale/aarch64: fix uyvy/yuyv to yuv420p/yuv422p on odd width
interleaved_yuv_to_planar, shared by uyvytoyuv422, uyvytoyuv420,
yuyvtoyuv422 and yuyvtoyuv420, only handled even widths. The packed
UYVY/YUYV macroblocks are pixel pairs and the trailing half macroblock of
an odd width was mishandled:

- the slow path (width <= 31) decrements its pixel counter by two from an
  odd value, so it never reaches zero and the loop runs far past the line,
  overwriting the destination (observed as a crash in checkasm);
- the fast path (width >= 32) shifts the tail pointers back by width-32 and
  reprocesses an overlapping, misaligned tuple, producing wrong samples and
  dropping the last chroma column.

Process only whole pixel pairs and emit the trailing odd column from a
per-line epilogue that matches the C reference: for yuv422 one Y, U and V
sample; for yuv420 the Y of both lines of the pair with the chroma averaged
across them, and luma only for the final line when the height is odd. The
empty even part (width 0 or 1) is guarded so the slow path no longer enters
its run-past loop.

All four variants are now bit-exact with the C reference for even and odd
widths. Verified with checkasm under qemu-aarch64.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit a554d0aa8a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:08:30 +02:00
Bogdan Lisman f7bbcb91b7 avcodec/snowenc: fix SIGFPE in get_dc() when a block lies outside the plane
get_dc() divides the accumulated, OBMC-weighted DC by aa, the sum of the
squared OBMC weights taken over the in-plane pixels.  When an OBMC block
falls entirely outside the plane - e.g. a tiny chroma plane after mcdeint
splits a frame into fields - no pixel contributes, aa stays 0 and the
ROUNDED_DIV() divides by zero (SIGFPE).  ab is 0 in exactly the same case,
so the result degenerates to 0; return it directly.

Reproducible with the GPL mcdeint filter in slow/extra_slow mode, e.g.

    ffmpeg -f lavfi -i testsrc=s=128x2 -vf mcdeint=mode=slow -f null -

Add a self-contained lavfi-based FATE regression test for the slow mode,
which previously crashed and is therefore not covered by the existing
sample-based fast/medium tests.

Fixes trac ticket #7779.

Signed-off-by: Bogdan Lisman <bogdan@pydevsolutions.com>
(cherry picked from commit a62d996927)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:08:30 +02:00
Michael Niedermayer 8c2e27e7bc avcodec/snowenc: fix out-of-bounds OBMC read in get_dc() for narrow planes
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 30c6667dad)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-17 04:08:30 +02:00
Aditya Banavi 4d786a8648 avformat/tls_gnutls:fix crash when connecting to peer
When ffmpeg whip client takes up dtls_active role when using gnutls,
it tries to connect to the server over udp and intermittently crashes.
This is because s->host is NULL, and ffmpeg is in ice controlling mode.
The gnutls api - gnutls_server_name_set() crashes if the hostname is NULL.

This commit assigns valid value to s->host in such scenarios.

Signed-off-by: Aditya Banavi <adityabanavi@gmail.com>
(cherry picked from commit 28b92b9b2e)

The upstream fix calls ff_tls_parse_host(), which was introduced after this
branch point by commit df3511db5bdf; its host-parsing is inlined here rather
than backporting that refactor.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 17:52:37 +00:00
Michael Niedermayer d82bcad879 Changelog: update
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 19:51:36 +02:00
Michael Niedermayer ad3e1ef726 libavcodec/jpeg2000htdec: remove trailing whitespace
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 19:49:27 +02:00
Romain Beauxis 68c4d7ec8c libavdevice/alsa.c: fix NULL pointer dereference
(cherry picked from commit 82d7e375f1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 06:10:02 +02:00
Leo Izen 3c0b18a3a6 avcodec/libjxlenc: check orientation tag metadata before reading
We need to check that entry->count is nonzero and that entry->type is
AV_TIFF_SHORT before reading from the buffer, in case a maliciously
constructed IFD uses a zero-count or an unusual type (e.g. IFD) for it.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
(cherry picked from commit 05b5add006)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 06:05:42 +02:00
Franciszek Kalinowski cb112ece1c avformat/icecast: reject CR/LF in metadata header values
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit 99e1ecca36)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 06:01:29 +02:00
Andreas Rheinhardt 269201a990 avfilter/avf_showspectrum: Fix allocation check
If s->stop is set, the return value would be overwritten
before being checked. This bug was introduced in the switch
to AV_TX in 014ace8f98.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit 0992c19c30)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 05:59:45 +02:00
bird 5c56b48dbe avformat/sctp: add size check in sctp_read() matching sctp_write()
Commit 5b98cea4 added a size < 2 guard to sctp_write() to prevent
out-of-bounds access when max_streams is enabled, but the identical
pattern in sctp_read() was not addressed.

When max_streams is non-zero, sctp_read() passes (buf + 2, size - 2)
to ff_sctp_recvmsg(). If size < 2, size - 2 wraps to a large value
on the implicit cast to size_t in the callee.

Add the same guard.

Signed-off-by: bird <6666242+bird@users.noreply.github.com>
(cherry picked from commit 5c3602abaa)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 05:52:32 +02:00
Osamu Watanabe b94b712611 avcodec/jpeg2000: Fix undefined behavior on ROI shift-up
(cherry picked from commit 8490363634)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 05:49:18 +02:00
Lynne e33bbfbee6 aacdec_usac_mps212: reject reserved freq_res value
(cherry picked from commit 7c79c79a50)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 05:45:35 +02:00
Gil Portnoy f9d7f434c0 avcodec/aac/aacdec_usac_mps212: Off-by-one bounds check in ff_aac_ec_data_deci()
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

No testcase, the check seems redundant

(cherry picked from commit 8b9851b005)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-16 05:41:47 +02:00
Michael Niedermayer 29616f5919 Update for 8.1.2 2026-06-15 23:59:22 +02:00
Bogdan Lisman 223764a43e avcodec/snowenc: fix out-of-bounds memcpy in get_block_rd() for narrow planes
For an edge block, get_block_rd() copies the full-OBMC-weight central
region directly from cur[] into the reconstruction.  It moved one
boundary to block_w/block_h but overwrote the in-plane clip (x0/x1/y0/y1
computed earlier from the plane size) instead of intersecting with it.
When a plane is narrower than block_w - e.g. a tiny field/chroma plane
produced by the mcdeint filter - the right-edge case left x0 = block_w
while x1 stayed clipped to w - sx < block_w, so x1 - x0 became negative
and was passed to memcpy() as a huge size_t, crashing with SIGSEGV.

Intersect the moved boundaries with the existing clip so the copy region
stays inside the plane and the memcpy length can never be negative.

Reproducible with the GPL mcdeint filter in slow/extra_slow mode, e.g.

    ffmpeg -f lavfi -i testsrc=s=5x32 -vf mcdeint=mode=slow -f null -

This is a separate crash from the get_dc() SIGFPE (ticket #7779) reached
through the same iterative_me() path.  Add a lavfi-based FATE regression
test.

Signed-off-by: Bogdan Lisman <bogdan@pydevsolutions.com>
(cherry picked from commit 1168447626)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:25 +02:00
Bogdan Lisman 213b6561ba avutil/eval: apply unary sign to print, squish, gauss and lerp
The leading sign of a (sub)expression is stored as +-1 in each node's
value field (parse_factor) and every other function multiplies its
result by it. print, squish, gauss and lerp ignored it, so e.g.
-print(1) evaluated to 1 instead of -1 and -gauss(0) to 0.398942
instead of -0.398942, while -1*print(1) was correct.

Fixes: ticket #9833
Reported-by: Player701
Signed-off-by: Bogdan Lisman <bogdan@pydevsolutions.com>
(cherry picked from commit 3d1d546f70)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:24 +02:00
Michael Niedermayer b9dc787d28 avcodec/cbs_av1_syntax_template: reset seen_frame_header on sequence
headers

With this change CBS and the decoder appear to be in sync.

Fixes: division by 0

Fixes: 501794431/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AV1_fuzzer-4792576644546560
Fixes: 501898692/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AV1_fuzzer-4772278394224640
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 fd290e2fcd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:24 +02:00
Michael Niedermayer b6fcd2919d avfilter/convolution: compute user matrix products in unsigned
Fixes: integer overflow

Found-by: Kery (Qi Kery <qikeyu2001@outlook.com>)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 44d082edc8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:24 +02:00
Michael Niedermayer 55db63567d avformat/mpegts: use av_fast_realloc() for prg
Fixes: Timeout
Fixes: 514855073/clusterfuzz-testcase-minimized-ffmpeg_dem_MPEGTS_fuzzer-5074757044469760
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 f7e6a8ade5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:24 +02:00
jiale yao af681f61b7 avfilter/avf_showcwt: fix DIRECTION_DU EOF fill clearing the wrong rows
Fixes: out of array read

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0d0eadd8ed)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:24 +02:00
Michael Niedermayer 68a3f37058 avfilter/avf_showcwt: fix DIRECTION_RL EOF fill clearing the wrong columns
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 5f13df1b51)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
Michael Niedermayer 8db78165b3 avfilter/avf_showcwt: avoid undefined float to int conversion of nb_consumed_samples
Reproduced with:
ffmpeg -f lavfi -i "sine=frequency=440" -filter_complex \
 "[0:a]showcwt=size=32x32:deviation=0[v]" -map "[v]" -f null -

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b276ac07e8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
Michael Niedermayer 5541caa9d6 avfilter/avf_showcwt: fix out of array read in compute_kernel
Reproduced with a small output (e.g. size=2x2) under ASan.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d133b4a231)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
Michael Niedermayer 48cdd6b6aa avfilter/v360: compute remap table offsets in 64bit
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit a55a8c9a68)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
Michael Niedermayer 3c51be6c26 avfilter/v360: reject out-of-range dimensions
Fixes: integer overflow

Found-by: Kery (Qi Kery <qikeyu2001@outlook.com>)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit fd6b3fa423)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
Michael Niedermayer 0e43e30cda swresample/x86/resample: write only int16 in the int16 resampler
The resample asm code as it is currently handles 1 sample at a time

The asm code should be redesigned and handle more than 1 sample at a
time. That is the whole purpose of SIMD. There is also multiple samples
available that need identical handling like from several channels or
similar handling from other points in time.

Such redesign would make the resampler faster and would change the
requirements of padding and maybe memory layout. So it seems simpler
to just avoid overwriting in the asm as it is today than to have
the allocation handle specific overallocation for asm code that
ideally should be redesigned

Fixes writing 16bits over the end of the array

This is an alternative fix for https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23053

Found-by: Ivan Grigorev <ivangrigoriev@meta.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4171581953)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:23 +02:00
jiale yao faa81d0b18 avformat/rtpenc_amr: Check input size
Fixes: heap buffer overflow

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 71478d1165)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:22 +02:00
Scott Boudreaux 733cce258b swscale/ppc: fix ASAN stack-buffer-overflow in yuv2planeX
Fix two buffer overreads in the PowerPC yuv2planeX SIMD paths
that cause daily FATE checkasm-sw_scale ASAN failures on both
ppc64 (G5, altivec) and ppc64le (POWER9, VSX):

1. VSX LOAD_FILTER: vec_vsx_ld(joffset, filter) reads 16 bytes
   at the given byte offset.  When joffset >= filterSize*2 - 14
   (e.g. joffset=30 for filterSize=16), this reads up to 14 bytes
   past the 32-byte filter array.  Fix by replacing the vector
   load with vec_splats(f[j]) which only reads the single int16_t
   element needed (the result is splatted to all lanes anyway).

2. GET_LS look-ahead overread: yuv2planeX_8_16 calls
   yuv2planeX_8 twice per filter tap.  Each call's GET_LS macro
   speculatively loads the next 16-byte vector for pipelining.
   On the second call, this look-ahead reads 16 bytes past the
   last valid source element.  Fix by tightening the SIMD loop
   bound from (dstW - 15) to (dstW - 23), ensuring the farthest
   speculative load stays within src[j][0..dstW-1].  The scalar
   fallback handles the remaining 16-23 trailing pixels.

The ASAN reports from FATE:
  ppc64 (altivec): stack-buffer-overflow in yuv2planeX_8_16_altivec
                   at swscale_ppc_template.c:56
  ppc64le (VSX):   unknown-crash in yuv2planeX_8_16_vsx
                   at swscale_ppc_template.c:52

Signed-off-by: Scott Boudreaux <scott@elyanlabs.com>
(cherry picked from commit d4673a97ac)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:22 +02:00
Scott Boudreaux 9825a8af1d swscale/ppc: fix LOAD_FILTER overread in VSX path
Part of the yuv2planeX ASAN fix - replace vec_vsx_ld with vec_splats
to avoid reading past the filter array.

Signed-off-by: Scott Boudreaux <scott@elyanlabs.com>
(cherry picked from commit dddc703cc1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:22 +02:00
Michael Niedermayer 874de02d87 avcodec/sanm: reject codec37 frames taller than the allocated buffer
No testcase

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit ab5043f055)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:22 +02:00
Michael Niedermayer 79b1d1e1aa avcodec/sanm: reject codec47 frames taller than the allocated buffer
Fixes: 513469519/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SANM_fuzzer-5024854725427200
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 b2695bcbb3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:22 +02:00
Michael Niedermayer ae9dd27979 avfilter: use ff_slice_pos() for per-slice boundary computation
This is a behavior preserving change for all non-overflowing cases.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit f7368f97b9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:21 +02:00
Michael Niedermayer 2cf7bb6089 avfilter: add ff_slice_pos() helper for slice boundaries
Slice based filter workers compute their per-thread row/sample/channel
boundaries as total * jobnr / nb_jobs. The total * jobnr product is
evaluated in int and overflows signed int for large dimensions and many
slice threads, before the division by nb_jobs brings it back in range.

(cherry picked from commit 218b4771a3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-15 23:57:21 +02:00
James Almer 1034b144ff avformat/iamf_writer: reject muxing PCM streams
Supporting PCM streams requires API changes present in newer releases that
can't be backported, so don't create invalid files.

Signed-off-by: James Almer <jamrial@gmail.com>
2026-06-14 10:06:31 -03:00
Michael Niedermayer 7aecd49777 avfilter/estdif: avoid signed overflow in slice boundary calculation
deinterlace_slice() computed per-thread row boundaries with int
multiplication height * (jobnr + 1). With a tall frame and many filter
threads the product overflows signed int before the division by nb_jobs.

Use int64_t for the intermediate product before converting back to int
row indices.

Found-by: Kery (Qi Kery <qikeyu2001@outlook.com>)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 200e0cba67)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:08 +02:00
Michael Niedermayer 352f6dfbe1 swscale: support sliced input with cascaded scaling contexts
Previously scale_cascaded() assumed the whole source frame arrived in a
single sws_scale() call, and the dispatcher only routed full-frame calls
to it. A partial input slice fell through to ff_swscale() on the parent
dispatcher context, whose scaler state (c->desc) is never initialized in
cascade mode, causing a NULL dereference / crash.

Top-down sliced output is bit-exact with full-frame scaling; bottom-up
matches swscale's pre-existing (non-cascade) slice behaviour for
subsampled intermediate formats.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 10f2abc41f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:08 +02:00
Michael Niedermayer 2dfc8f3919 avformat/rtspdec: bound Content-Length in the ANNOUNCE handler to SDP_MAX_SIZE
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit 6049b4d7bc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:07 +02:00
James Almer 84087839af avcodec/cbs_h266_syntax_template: reject subpic info with res_change_in_clvs
Found-by: Anthony Hurtado
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0cf9169c85)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:07 +02:00
Michael Niedermayer 4b32214900 avcodec/misc4: Check nb channels
Found-by: Forgejo Fairy
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7b717fe50d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:07 +02:00
Michael Niedermayer 52af067ac2 avcodec/rv10, rv34: check init_get_bits8() before RealVideo bit access
Found-by: Samarth Kumbla <samarthk@cantina.security>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0c662529f6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:07 +02:00
haoyuLiu 8280545165 avformat/http: reject request-line tokens not terminated by whitespace
Fixes out of array access

Found-by: Cloud-LHY (@Clouditera-lhy) / VulnForge Security Research Team
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit dd9083cb89)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:07 +02:00
Michael Niedermayer 31a192f5dd avformat/mov: reject out of range ispe dimensions, avoid overflow summing HEIF tile dimensions
ispe width/height are read as uint32 but stored in int HEIFItem fields;
values above INT_MAX became negative, and read_image_grid() summing such
widths into coded_width overflowed int:
libavformat/mov.c:10404:33: runtime error: signed integer overflow: -2147483647 + -2147483647 cannot be represented in type 'int'

Also accumulate the grid tile dimensions and running offsets in 64bit
and validate the totals, as up to 256 tile columns of individually
valid widths can still overflow int.

Found-by: 51511
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 2cc7b87bdb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:06 +02:00
David Korczynski a4152636b8 avcodec/agm: validate actual src_y against prev plane in decode_inter_plane
Found-by: Anthropic agents; validated and reported by Ada Logics.

Signed-off-by: David Korczynski <david@adalogics.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4527854281)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:06 +02:00
David Korczynski a0e7ee5468 avformat/dhav: Fix second integer overflow in get_duration()
Fixes: ada-2-poc.dhav

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects, and I am from Ada Logics helping validate the found issues and report to maintainers.
(cherry picked from commit 50e65074f5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:06 +02:00
Zhen Yan ee25d8ec07 fftools/ffmpeg_dec: deep-copy subtitle_header to fix use-after-free
Found-by: Zhen Yan
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit fa391e90fb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:06 +02:00
Michael Niedermayer e3ce59ba68 avcodec/hevc/ps: Check window parameters
Fixes: signed integer overflow: -1094995529 * 2 cannot be represented in type 'int'
Fixes: 484567435/clusterfuzz-testcase-minimized-ffmpeg_dem_HXVS_fuzzer-5628836988649472

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 82f097c825)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:06 +02:00
Michael Niedermayer bcee8b9f0b avcodec/hevc/ps: Factor window reading out
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 8c868a1fd2)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
David Korczynski e3d0fca1bb avcodec/truespeech: reject iterations count whose * 240 product overflows 32-bit
Found-by: Anthropic agents; validated and reported by Ada Logics.
Signed-off-by: David Korczynski <david@adalogics.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d30dead35e)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
Robert Nagy 101bb4c249 libavcodec/options_table: gamma22 and gamma28 aliases
(cherry picked from commit 06e11c87c6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
David Korczynski 797cbc7413 avcodec/on2avc: reject subframe count whose * SUBFRAME_SIZE product overflows 32-bit
Found-by: Anthropic agents; validated and reported by Ada Logics.
Signed-off-by: David Korczynski <david@adalogics.com>
(cherry picked from commit 331b3e9dea)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
haoyuLiu 3a9a2f13de avfilter/zmq: initialize send_buf before shared cleanup on parse failure
Found-by: VulnForge Security Research Team
Reported-by: Cloud-LHY <haoyuliu@clouditera.com>
(cherry picked from commit 6028720d70)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
Michael Niedermayer 849ed5f176 avcodec/adpcm: fix signed integer overflow in get_nb_samples()
Fixes: signed integer overflow: 314572800 * 8 cannot be represented in type 'int'

Tighten the guard to INT_MAX/14, which covers the largest expansion
factor used in the function currently.

Found-by: Jiale Yao <19888972804@163.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 04e2341056)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:05 +02:00
Michael Niedermayer e15ede87a3 avformat/matroskadec: avoid signed overflow in DASH cue time differences
Fixes: 493466409/clusterfuzz-testcase-minimized-ffmpeg_dem_WEBM_DASH_MANIFEST_fuzzer-6150181551931392
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 0a8d961388)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:04 +02:00
David Korczynski 417061746d avcodec/fastaudio: reject subframes count whose * 256 product overflows 32-bit
fastaudio_decode() computes
    subframes = pkt->size / (40 * channels);
    frame->nb_samples = subframes * 256;
both as 32-bit signed multiplications. When pkt->size is large enough
to make subframes >= 2^24, the second multiplication overflows the
signed int range and frame->nb_samples wraps to a small value.
ff_get_buffer() then sizes the audio plane for that wrapped sample
count, while the decoder loop at line 152 still iterates the full
(unwrapped) subframes count, performing a 1024-byte memcpy per
subframe per channel. The 27th iteration (or first iteration with
nb_samples=0) writes one byte past the per-plane allocation,
yielding the ASan heap-buffer-overflow WRITE at libavcodec/fastaudio
.c:171 reported as ANT-2026-03891.

Reject the subframes value whose *256 product would overflow before
performing the multiplication. The bound INT_MAX / 256 (= 8388607)
keeps the existing two's-complement semantics of every reachable
input and rejects only the configurations that would have wrapped.

Reproducer: a crafted AVI declaring one mono audio chunk of
671_088_680 bytes (sparse) with the decoder forced via
'ffmpeg -c:a fastaudio -i evil.avi'.

Found-by: Anthropic agents; validated and reported by Ada Logics.

Signed-off-by: David Korczynski <david@adalogics.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 1e9984772b)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:04 +02:00
Michael Niedermayer 31be6491d2 avcodec/vc2enc_dwt: avoid signed overflow in the 9/7 DWT lifting
Fixes: 490488944/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VC2_fuzzer-5310290362433536
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 5f91556215)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:04 +02:00
Michael Niedermayer cb55da3768 avcodec/vc2enc_dwt: avoid signed overflow in the 5/3 and Haar DWT
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7c7ca349bc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:04 +02:00
Michael Niedermayer d4175fe20d avformat/dashdec: Fail with any inner stream count being 0
Fixes: ada-3-poc.mpd

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects, and I am from Ada Logics helping validate the found issues and report to maintainers.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b99c6fc8c3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:04 +02:00
Michael Niedermayer d5ac401940 avcodec/mjpegdec: require progress in AVRn interlaced field loop
Fixes: Timeout
Fixes: 500554625/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MEDIA100_fuzzer-5094103347167232
Fixes: 511253447/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SMVJPEG_fuzzer-5780722463080448
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 b355200263)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer 08597a382e avcodec/mwsc: do not dereference a missing reference frame
Fixes: 493841393/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MWSC_fuzzer-5079884677578752
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 ba825ce85f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer b77508937f avcodec/misc4: reject invalid sample rate
Fixes: AVERROR_BUG

Fixes: 493055111/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MISC4_fuzzer-5752676962074624
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 32eb07bb83)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer 9006342109 swscale/output: avoid signed overflow in yuv2rgba64_1 alpha
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0ab097fb34)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer 28c0fda2cd swscale/output: avoid signed overflow in yuv2rgba64_full_1 alpha
Fixes: 493055112/clusterfuzz-testcase-minimized-ffmpeg_SWS_fuzzer-5823995319746560
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 ad84fc9b7d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer 6a25c9adfc tools/target_dem_fuzzer: do not exit on io_buffer allocation failure
Failure to allocate a randomly sized buffer should not count as a anomaly in the fuzzer
there is nothing to fix in that case

Fixes: 490112574/clusterfuzz-testcase-minimized-ffmpeg_dem_TMV_fuzzer-6600485921685504
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 2cce6ad030)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:03 +02:00
Michael Niedermayer 46a66b2ccc avformat/gxfenc: Check timecode and propagate error
Fixes: ./ffmpeg   -f lavfi -i testsrc=duration=0.1:size=720x480:rate=30   -c:v mpeg2video -frames:v 1   -metadata timecode="999999999:00:00:00"   -f gxf output.gxf

Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0ea090e09f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:02 +02:00
Michael Niedermayer 5da47b2752 swscale/rgb2rgb_template: use unsigned for <<24
Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit dbe78ffdb8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:02 +02:00
Michael Niedermayer e61c9faabd avformat/iamf_parse: bound substream count by remaining OBU size
also check for nb_substreams == 0

Fixes: 472641765/clusterfuzz-testcase-minimized-ffmpeg_dem_IAMF_fuzzer-6390897173659648
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 fe2dabbbf4)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:02 +02:00
Michael Niedermayer a6740266e0 avformat/matroskadec: bound TRACKENTRY parsing by max_streams
After the fix the reproducer finishes in 43 ms instead of OOM-ing at the
2 GB limit. Legitimate .mkv/.webm fate samples still parse cleanly.

Fixes: 471604245/clusterfuzz-testcase-minimized-ffmpeg_dem_WEBM_DASH_MANIFEST_fuzzer-6662979358883840
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 c7e0bac050)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:02 +02:00
Anthony Hurtado b7f3a666ca avcodec/diracdec: fix heap buffer overflow in edge_emu_buffer
Fixes: poc_dirac_v2_*
(cherry picked from commit 495b402f27)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:02 +02:00
Michael Niedermayer 363435f591 avformat/rtmppkt: Check recursion depth
Based on flvdec.c

Fixes: out of array access

Found-by: Xueqing
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 92804c9e25)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
Michael Niedermayer ea01723885 avcodec/tdsc: propagate max_pixels to the JPEG tile decoder
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 47f3996bdd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
Michael Niedermayer 36beb07e57 avcodec/imm5: propagate max_pixels to the H264/HEVC sub-decoders
Fixes: 501794495/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IMM5_fuzzer-5192457796255744
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 c1d3e8c46f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
Michael Niedermayer e569af76bc avcodec/cri: propagate max_pixels to the JPEG tile decoder
Fixes: 489941776/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CRI_fuzzer-4845035614175232
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 cdba2d76dc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
Michael Niedermayer 5ff3913787 avcodec/jpeglsdec: only apply color transform to decoded rows
Fixes: Timeout
Fixes: 503996733/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MJPEG_DEC_fuzzer-4948713016721408
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 3669a742dd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
David Korczynski cbc62ea2c8 avcodec/adpcm: require block_align to be a multiple of channels in ADPCM_PSXC init
The ADPCM_PSXC block loop in adpcm_decode_frame() (libavcodec/adpcm.c:
2770) iterates 'block < avpkt->size / block_align' times and, for
each block, consumes
    channels * (1 + (block_align - 1) / channels)
input bytes via the *unchecked* bytestream2_get_byteu() reader. The
loop divides avpkt->size by block_align, so the loop bound is sound
only when the per-block consumption equals block_align — i.e. when
block_align is an exact multiple of channels. For any other
combination (e.g. block_align=9 with channels=8), each block consumes
more than block_align bytes; iterating avpkt->size/block_align
blocks then walks the input bytestream past avpkt->data +
avpkt->size, producing the heap-buffer-overflow READ at
libavcodec/bytestream.h:99 reported as ANT-2026-04052.

adpcm_decode_init() previously only enforced 'channels > 0' and
'block_align > 0' for PSXC. Tighten the init check to additionally
require 'block_align % channels == 0', which is the precise
invariant the decode loop depends on.

Reproducer: a crafted WAV header declaring channels=8, block_align=9
with the decoder forced via 'ffmpeg -c:a adpcm_psxc -i evil.wav'.

Found-by: Anthropic agents; validated and reported by Ada Logics.

Signed-off-by: David Korczynski <david@adalogics.com>
(cherry picked from commit 6d8f7882ae)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:01 +02:00
jiale yao 9906b38d1d avfilter/avf_showcwt: fix out-of-bounds read in du scroll
Fixes: out of array access
Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit e8031e5b9a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:00 +02:00
Michael Niedermayer 41e1b6d817 avfilter/f_ebur128: avoid signed-int wrap when sizing per-channel cache
Fixes: integer overflow
Fixes: out of array access

Found-by: Claude (Anthropic), reported by Omkhar Arasaratnam <omkhar@linkedin.com>.
(cherry picked from commit 537e87e3c2)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:00 +02:00
Omkhar Arasaratnam 89d9ad0345 avformat/mov: cap HEIF ICC profile copies via c*max_streams to bound CPU and memory
Found-by: Claude (Anthropic). Human-verified and reported by
Omkhar Arasaratnam <omkhar@linkedin.com>.
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
(cherry picked from commit 711cdae64f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:00 +02:00
Michael Niedermayer a153f5f2fa avcodec/aac/aacdec_usac: reject explicit usacSamplingFrequency of 0
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 263374ac7d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:00 +02:00
Michael Niedermayer a8a7a2afa1 avcodec/aac/aacdec_usac: avoid signed overflow in decode_tsd
decode_tsd() computes the binomial coefficient c = C(k, p) incrementally.
this commit makes it less overflow prone

Fixes: 515703905/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AAC_DEC_fuzzer-4890954254581760
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 69c9f1158c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:41:00 +02:00
Michael Niedermayer 2b81143984 avcodec/aac/aacdec: reject decoded frame without a valid sample rate
Later code will turn this into AVERROR_BUG

When returning sample_rate == 0 samples is considered a bug, we have no
nice choice but to error out cleanly

Fixes: assertion failure
Fixes: ffmpeg_AV_CODEC_ID_AAC_DEC_fuzzer crash-0a86d46fef2442b222ee34403c21f7f582ffccb0
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit e711e60827)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:59 +02:00
Michael Niedermayer 36abe87a0b avformat/iff: check av_get_packet() result in ANIM branch
Fixes: 494958338/clusterfuzz-testcase-minimized-ffmpeg_dem_IFF_fuzzer-6265824670449664
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 43f712d917)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:59 +02:00
James Almer b3a15b4ee1 avcodec/cbs_h266_syntax_template: Fix pps_exp_slice_height_in_ctus_minus1 range
Found-by: Claude (Anthropic). Human-verified and reported by Omkhar Arasaratnam <omkhar@linkedin.com>.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit bf608f16fd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:59 +02:00
Michael Niedermayer 2834b438ec avfilter/vf_scale: split rational multiply
Fixes: integer overflow in SAR
Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 97ea5da419)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:59 +02:00
Michael Niedermayer 532063e7ff avcodec/bsf/dts2pts: fix binary tree invariant violation on selective dec_poc
Modifying the keys of a sorted structure, be that a tree or other
can lead to changes in the ordering and undefined behavior.
It can also lead to collisions with existing keys.

All these cases need to be handled unless there is a bug elsewhere
that would prevent them.

Fixes: out of array access
Fixes: 504281984/clusterfuzz-testcase-minimized-ffmpeg_BSF_DTS2PTS_fuzzer-6032368162111488

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 054dffd133)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:59 +02:00
Michael Niedermayer b0570f35cf avfilter/vf_drawtext: Avoid double free in glyph_enu_border_free()
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 073c44b8bc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
Michael Niedermayer 5a409e87b7 avfilter/vf_drawtext: plug error-path leaks in measure_text/draw_text
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 47c503c6a9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
Michael Niedermayer 734b17cb98 avfilter/vf_drawtext: shape_text_hb() free allocated things on error
Fixes: memleak
Found-by: Fairy

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 77554d85d7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
Michael Niedermayer 2fd0577bc9 avfilter/vf_drawtext: avoid double-free of aliased FT_Glyph in glyph_enu_free
For glyphs whose source is already in bitmap form (color emoji fonts such
as NotoColorEmoji.ttf), FT_Glyph_To_Bitmap(..., destroy=0) returns the
input pointer unchanged. The result is that glyph->bglyph[idx] aliases
glyph->glyph (and analogously border_bglyph[t] may alias border_glyph).
glyph_enu_free then called FT_Done_Glyph on both, double-freeing the
underlying object.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9efca1d946)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
Michael Niedermayer 23b50185c6 avfilter/vf_drawtext: don't double-free glyph that has been cached in tree
Reproducer:
  ffmpeg -f lavfi -i color=s=640x120:d=1 \
      -vf "drawtext=fontfile=/usr/share/fonts/truetype/noto/NotoColorEmoji.ttf:\
text='FFmpeg':fontsize=109:fontcolor=white:x=20:y=35" \
      -frames:v 1 out.png

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c51789b052)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
Michael Niedermayer f80ccca187 avfilter/vf_drawtext: always check pixel_mode == FT_PIXEL_MODE_MONO
The code as written can add such glyphs in the cache so we need to check
glyphs from the cache too.
This should be the most robust and simple solution

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c8c4e2d2a5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:58 +02:00
David Korczynski 0bbf29dee3 avcodec/cook: bound subpacket channel sum against channel count
Fixes: out of array read
Fixes: evil.rm

Found-by: Anthropic agents; validated and reported by Ada Logics.

Signed-off-by: David Korczynski <david@adalogics.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 1152139b48)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:57 +02:00
Michael Niedermayer af81aaae76 avcodec/apv_decode: avoid using apv_cbc
Fixes: out of array access
Fixes: evil.apv

Found-by: Claude (Anthropic). Human-verified and reported by Omkhar Arasaratnam <omkhar@linkedin.com>. on 05-20
Found-by: Anthropic agents; validated and reported by Ada Logics. on 05-26
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7a2424eb43)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:57 +02:00
Michael Niedermayer 61218852d1 avformat/mxfdec: Remove unneeded check
size is 16bit only

Found-by: Tomas Härdin
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit aaac0989e6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:57 +02:00
Michael Niedermayer 0cda9f02e7 avformat/ftp: Check string used for RNTO
Found-by: Forgejo Fairy
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4d24cb1c39)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:57 +02:00
Michael Niedermayer bdcec7edb8 avformat/ftp: Check for Telnet IAC characters and other non printable ASCII chars
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 090838497c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:57 +02:00
Franciszek Kalinowski 643048daef avformat/ftp: reject CR/LF in the URL path to prevent FTP command injection
ftp_connect() interpolates the URL path into SIZE/RETR/STOR/CWD/DELE/RMD/RNFR
commands without checking for CR/LF, although it already rejects CR/LF in the
user and password fields. Reject CR/LF in s->path the same way.

Reported and reviewed by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Śmigielski.

(cherry picked from commit 640f32b1b6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
Michael Niedermayer 27766a8f74 avcodec/jpeg2000dec: Clear header derived variables
Fixes: NULL pointer dereference

Found-by: Oguzhan Akkaya with AFL++ fuzzing (May 2026)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 6631bbc5d4)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
Michael Niedermayer 8b45f41791 avcodec/bsf/smpte436m_to_eia608: properly frees stuff on errors in ff_smpte436m_to_eia608_filter()
Fixes: memleaks
Fixes: 501913473/clusterfuzz-testcase-minimized-ffmpeg_BSF_SMPTE436M_TO_EIA608_fuzzer-5607133705207808

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 0834dbed1c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
James Almer 96f9a6e28c tests/checkasm/crc: retain offset values between calls
Should fix buffer overflows as reported by clang-asan and use of uninitialized
values as reported by valgrind.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 224659360a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
James Almer 2812a5b8d7 avformat/avc: Adjust get_ue_golomb() to handle 32 bit
Fixes: assertion failure
Fixes: PR-009/bad_extra_idr_only.avi

Found-by: mosskappa
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 93512bc2fd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
Omkhar Arasaratnam eb588c4f78 avformat/whip: require remote DTLS fingerprint in SDP answer
WHIP relies on the SDP a=fingerprint to bind the peer identity to
the SRTP keying material (RFC 8842 §§ 5.1, 5.3). parse_answer()
walks the SDP body looking for `a=ice-lite`, `a=ice-ufrag:`,
`a=ice-pwd:`, and `a=candidate:` lines and ignores everything else,
including `a=fingerprint`. WHIP intentionally runs the OpenSSL DTLS
backend with s->verify=0 (DTLS-SRTP uses self-signed certs by
design, so a CA chain check would be meaningless); the peer cert is
accepted regardless of identity. The spec's compensating identity
control — verifying the DTLS peer cert against the SDP a=fingerprint
hash — is missing, so the SRTP keys are derived from a session
whose peer identity was never authenticated. Any on-path attacker,
or a malicious WHIP server URL, can substitute their own DTLS
material and the publisher's RTP stream will be encrypted to them.

The full fix is a two-step process:
  (a) Require a=fingerprint to be present in the SDP answer
      (RFC 8842 § 5.3 MUST).
  (b) After DTLS handshake, compute the peer-cert hash and compare
      against the stored fingerprint (RFC 8842 § 5.1 MUST); tear
      down the session on mismatch.
This patch implements step (a) only; step (b) requires plumbing
the cert hash out of dtls_start() through the openssl TLS context
and is left as a follow-up.

Add a remote_fingerprint field to WHIPContext, extract the
a=fingerprint value from the SDP answer in parse_answer(), and
return AVERROR(EINVAL) when it is absent. This raises the bar from
"no fingerprint required" to "any fingerprint required"; the
follow-up patch will raise it again to "fingerprint MUST hash-match
the DTLS peer cert."

Found-by: Claude (Anthropic). Human-verified and reported by
Omkhar Arasaratnam <omkhar@linkedin.com>.
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
(cherry picked from commit 7b46c6a2a3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:56 +02:00
Hassan Hany 2196cd43dc avcodec/x86/vorbisdsp: change cmpleps to cmpltps in inverse coupling
Changed the comparison from cmpleps to strictly less than
(cmpltps) to strictly follow the Vorbis spec

Fixes https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/21501

(cherry picked from commit 9288681068)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:55 +02:00
Soham Kute 9318eb0a98 avcodec/liboapvenc: derive and validate APV profile from pixel format
(cherry picked from commit 8885116f4d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:55 +02:00
Michael Niedermayer 1c871a90bf avformat/dashdec: bound manifest reloads and fragment-open retries
Mirror the HLS demuxer's max_reload pattern

Reported as a DoS finding by Xueqing. Verified with the supplied PoC
server: a 30s ffmpeg run that previously generated ~10000 requests
without termination now exits in ~100ms after exactly max_reload
fragment-open failures.

(cherry picked from commit 4945e33e98)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:55 +02:00
Franciszek Kalinowski 64fd93e361 avfilter/af_join: fix wrong loop bound in buffer dedup (use-after-free)
try_push_frame() decides whether an input buffer is already tracked by testing
`j == i` (the channel index) instead of `j == nb_buffers`. Once an earlier
channel shared a buffer, nb_buffers falls behind i and a genuinely new buffer is
never referenced, so it is freed while the output frame still points at it.

Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit 461fb22053)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:55 +02:00
Diego de Souza 83853cf1e8 avcodec/nvenc: fix compatibility with Video Codec SDK 13.1
NV_ENC_CLOCK_TIMESTAMP_SET was changed in SDK 13.1: countingType was
replaced by countingTypeLSB and countingTypeMSB.

Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
(cherry picked from commit 0a7c5e507b)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:55 +02:00
Omkhar Arasaratnam 86dd0a3adf avformat/mov: validate APV access unit length before passing to decoder
libavformat/mov.c read the APV AU length field directly from the
sample without sanity-checking against the remaining sample size or
a documented maximum. The patch validates that au_size is bounded by
the remaining sample bytes and that the AU envelope (4 bytes plus
au_size) fits inside the declared sample size.

Validate the access unit length at the demuxer boundary so that the
decoder is not handed an attacker-controllable buffer size. Returns
AVERROR_INVALIDDATA on the bound failure with an explicit log line.

Found-by: Claude (Anthropic). Human-verified and reported by
Omkhar Arasaratnam <omkhar@linkedin.com>.
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
(cherry picked from commit 387ad6d102)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Franciszek Kalinowski d7ceb10bfe avcodec/h264_slice: guard color_frame() against chroma-width underflow
In the >= 9 bit path, color_frame() does
`av_memcpy_backptr(dst + 2, 2, bytes - 2)`. When the effective chroma width
is 1 pixel (bytes == 1) the count becomes -1 and the underlying fill16()
loop runs roughly 2^32 times, producing a heap overflow. The original count
was also wrong in units (pixels rather than bytes); fix that at the same
time so the 2-pixel case still fills both pixels.

Confirmed via a standalone harness reproducing av_memcpy_backptr's fill16
loop with cnt = -1; reaching the call from a crafted H.264 bitstream
requires Hi10P plus a frame_num gap on a frame whose effective chroma width
is 1 pixel, which is hard to express but is reachable via mid-stream SPS
changes. Compiles cleanly; no regressions seen running existing crafted
H.264 PoCs and trivial transcodes.

Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit c79dfd29e6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Ori Hollander 9516e6900a avcodec/magicyuv: reject slice_height misaligned with chroma vshift
Fixes: poc_magicyuv.avi
Fixes: out of array access

Found-by: Ori Hollander of the JFrog Vulnerability Research team
(cherry picked from commit 374b726ffa)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Michael Niedermayer e302bafe79 avcodec/magicyuv: Expand the s->interlaced slice-height sanity check
Fixes: poc_magicyuv.avi
Fixes: out of array access

Found-by: Ori Hollander of the JFrog Vulnerability Research team
(cherry picked from commit 5806e8b9f3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Michael Niedermayer a991b3e110 avcodec/magicyuv: Fix 1 line MEDIAN slices
No testcase

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c23d4da312)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Michael Niedermayer 167c14a418 avformat/mxfdec: zero-init Sony MPEG-4 extradata and add padding
Found-by: Calm (AI security-research agent, for John Bradley / Credex)
(cherry picked from commit 8f1769703c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:54 +02:00
Michael Niedermayer e9b3388dcb avformat/soxdec: Check sample_rate for nan
Found-by: iceray-Li
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d2d79dca9a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:53 +02:00
Balling 07d615e903 tests/tiny_ssim: fixed mistake in ssim_c1 calculation
Reporter uses this code in production.

Signed-off-by: Valerii Zapodovnikov <val.zapod.vz@gmail.com>
(cherry picked from commit 8cd7465565)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:53 +02:00
Michael Niedermayer 69ca310fb7 avformat/hls: Check TIME-OFFSET value
Fixes: UB with out of range values
Fixes: poc_overflow.m3u8

Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 59094859a8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:53 +02:00
Michael Niedermayer 61ffafe95b avformat/hls: Check url_offset and size
Fixes: integer overflow

Found-by: jiale yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c2047918e6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:53 +02:00
amhurtado 621d35023a avcodec/prores_raw: reject invalid tile alignment values
Fixes: out of array access

Regression since d8cb567 ("prores_raw: fix tile alignment
issues").

Found-by: amhurtado <amhurtado@pm.me>
Signed-off-by: amhurtado <amhurtado@pm.me>
(cherry picked from commit d3f59f9b7f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:53 +02:00
Michael Niedermayer 16474a560e avformat/ty: check rec_size
Fixes: ada-4-poc.ty

change is based on the suggested fix

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 4492ad7228)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Dale Curtis 507d8e8284 avformat/ogg: Fix overflow and stale oggvorbis_private values
- Prevent integer overflow when summing header lengths; add bounds check.
- Re-initialize priv->vp with the new stream's extradata once all chained
  stream headers are collected.

Signed-off-by: Dale Curtis <dalecurtis@chromium.org>
(cherry picked from commit 6e0e13b0bf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Franciszek Kalinowski ccae7f536b avformat/rtpenc_xiph: bail out when the max payload size underflows
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit 0857141823)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Franciszek Kalinowski 88c482d7b7 avformat/rtpenc_aac: reject packets smaller than the ADTS header
When extradata_size == 0, ff_rtp_send_aac() does `size -= 7` to skip the
ADTS header without checking size >= 7. A short packet makes size negative,
and the value is later passed to memcpy() as size_t, reading past the buffer
end. Bail out instead.

The vulnerable branch is not reached when using the built-in AAC encoder
(which always emits extradata), but an application that feeds raw
ADTS-stripped AAC packets through the libavformat RTP muxer can hit it. The
fix is a one-line lower-bound check and compiles/runs cleanly; see audit
PoC for the static analysis and reachable-by-API write-up.

Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit a44cae9025)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Michael Niedermayer d14ea0d715 avcodec/jpeg2000dec: compute mask in decode_clnpass() like in decode_sigpass()
Fixes: integer overflow

Found by: Jiale Yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 59367afc3d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Michael Niedermayer 182bc42768 avformat/flvdec: Check size at the top of the main loop
Fixes: signed integer overflow
Fixes: ffmpeg_flv_read_packet_libavformat_flvdec.c_1900_26.poc

Found-by: iceray-Li
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit cc1459ed85)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:52 +02:00
Michael Niedermayer 96d5d4c75d avformat/vividas: fix misaligned access
Fixes: ffmpeg_xor_block_libavformat_vividas.c_134_15.poc

Found-by: iceray-Li
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 84a48165f0)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:51 +02:00
Michael Niedermayer 377fb77be3 avformat/mccdec: dont pass NULL to bytestream2_put_buffer()
Fixes: passing NULL pointer

Found-by: iceray-Li
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 2bfc7ce3ec)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:51 +02:00
David Korczynski cba36a17af avcodec/g2meet: The stack is EPIC_PIX_STACK_SIZE
Fixes: out of array access
Fixes: ada-5-poc.avi

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects, and I am from Ada Logics helping validate the found issues and report to maintainers.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 989e621bcd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:51 +02:00
Michael Niedermayer 5e1a71ce13 avcodec/h2645_sei: Initialize side data before deallocation
Fixes: use after free
Fixes: poc_hvcc_modified.mp4

Found by: Jiale Yao
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit f435ce22e1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:51 +02:00
David Korczynski cb2f4b4f5f avfilter/boxblur: Fix off by one errors
Fixes: ada-2-poc.mkv

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects, and I am from Ada Logics helping validate the found issues and report to maintainers.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 444f2cf047)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:51 +02:00
David Korczynski d7e1d91762 avformat/assenc: Add the missing parentheses
Fixes: ada-1-poc.mkv

Found-by: Claude and Ada Logics. This issue was found by Anthropic from using agents to study security of open source projects, and I am from Ada Logics helping validate the found issues and report to maintainers.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 08d7646abf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
Thai Duong f966d1eea6 avcodec/diracdec: Enlarge mctmp to cover the worst-case blheight·ybsep + yblen rows, and break the MC loop when no output rows remain
Fixes: ffmpeg_ANT-2026-02842_dirac-mctmp-heap-overflow

Discovered by Claude (Anthropic). Confirmed and reported by Thai Duong (Calif.io).

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit bbdce45fda)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
James Almer 874cd67a3c tools/zmqsend: free the AVBprint buffer after using it
Fixes CVE-2026-30999

Fixes: memleak
Found-by: Xinghang Lv
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 144af8f81a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
Dale Curtis 022642e3ad [Wave] Fix issues with unaligned metadata chunks.
Fixes corruption issues with the sample in this PR.

Signed-off-by: Dale Curtis <dalecurtis@chromium.org>
(cherry picked from commit 5bbc00c05d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
Michael Niedermayer bda47c505f avformat/mpegts: Dont assume fc->priv_data is a MpegTSContext
Fixes: out of array access
Fixes: 508365271/clusterfuzz-testcase-minimized-ffmpeg_dem_WTV_fuzzer-6219535958212608

Regression since: b9cb948ec1

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 188461be10)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
Yong Yu 27561c4e39 fftools/graph: Add missing include "libavutil/mem.h" for fftools/graph/graphprint.c
when HAVE_AV_CONFIG_H is defined, include libavutil/mem.h
is skipped in libavutil/common.h.
Need this header file to build successfully.

(cherry picked from commit 9ab345b2d1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:50 +02:00
Michael Niedermayer ce82410ef8 avcodec/cbs_h266_syntax_template: tighten sh_num_tiles_in_slice_minus1 upper bound
Fixes: out of array access

Found-by: Vishal Panchani
Fix suggested by: Vishal Panchani
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b5c7c7d273)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:49 +02:00
Zhao Zhili bcdca173aa avcodec/hevc: limit missing-ref fill to coded planes
generate_missing_ref walked frame->f->data[] until a NULL slot, which
on alpha-video frames extended to data[3] and read
sps->hshift[3]/vshift[3] out of bounds.

The alpha plane is produced by the alpha layer via
replace_alpha_plane; the base decoder path never reads or writes it.
Bound the fill loop by the SPS coded plane count. This both removes
the out-of-bounds shift access and avoids an unnecessary full-frame
memset of the alpha plane.

Fixes: out of array read
Fixes: 500770604/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-6157374833623040

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
(cherry picked from commit 3b939ced79)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:49 +02:00
Dale Curtis 56e8d17d9b avformat/mov: Fix negative index given to can_seek_to_key_sample()
The potentially negative return value of av_index_search_timestamp()
wasn't being handled before passing it to can_seek_to_key_sample().

Found by Wongi Lee (@_qwerty_po) of Theori with Xint Code,
Jungwoo Lee (@physicube).

Signed-off-by: Dale Curtis <dalecurtis@chromium.org>
(cherry picked from commit 256d93413f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:49 +02:00
João Neves 56f758b8b4 avcodec/hdrdec: fix pixel count decrement in RLE decompress loop
The w variable counts pixels, not bytes. The non-RLE path correctly
uses w-- (one pixel = 4 bytes), but the RLE path uses w -= 4, causing
the loop to terminate after roughly 1/4 of the expected pixels.

The w -= 4 was introduced in 14e99cb472 which moved the decrement
inside the loop to fix an OOB write (clusterfuzz-5423041009549312).
The move was correct, but the decrement value should have been 1 to
match the non-RLE path.

Signed-off-by: João Neves <joaocns0@protonmail.com>
(cherry picked from commit 2c71a28bf0)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-14 04:40:49 +02:00
Timo Rothenpieler 83e8541aa6 forgejo/workflows: update test workflow for 8.1 release 2026-06-12 15:07:35 +02:00
Martin Storsjö e0e38acd2f aarch64: vp9lpf: Fix GCS violations
The aarch64 VP9 loopfilters actually violate aarch64 GCS
(Guarded Control Stack), even though we marked the code as GCS
compliant in 846746be4b.

This means that builds with GCS enabled, after that commit,
will crash when decoding VP9, on future hardware (or current
QEMU) that supports GCS. This also goes for ffmpeg version 8.1.1
where the GCS enabling was backported.

This matches the fix that was done for hevcdsp in
1f7ed8a78d.

This issue wasn't observed if running checkasm in QEMU - therefore,
I thought all GCS issues had been fixed by
846746be4b. (If I would have
tested the full "make fate" with QEMU, the issue would
have appeared though.)

However with the new checkasm, some of the GCS violations
do appear even in checkasm.

The reason is that the checkasm vp9 test intentionally craft
input pixels that attempt to trigger all the individual
separate cases in each input buffer (in
randomize_loopfilter_buffers). This means that the checkasm
tests actually never test or exercise the early exit cases,
which are the ones that violate GCS.

With the new checkasm, the call to "bench_new" always test
running the code at least once, even if not benchmarking.

As the input buffers weren't reinitialized between the test
and "bench_new", the pixel differences now differ from the
initial setup, so that the code now some times (often) would
end up hitting the early exit cases.

Ideally, the vp9 checkasm test would be repeated to cover all
cases of input buffers that allow early exits, in addition to
covering the case with all different cases in one block.

(cherry picked from commit d05786cf23)
2026-06-10 21:05:42 +03:00
James Almer e4c7fbf6c0 avformat/mov: don't abort on unsupported or invalid chnl boxes
They are optional and just define a channel layout, which may also be defined
by the underlying codec.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 95fe0658d7)
2026-06-01 11:25:05 -03:00
James Almer 9eb9f4799f avformat/mov_chan: keep the layout untouched on chan/chnl box failure
Needed to keep the process going if some issue was found while parsing these boxes.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit fd1c8fa0e6)
2026-06-01 11:24:49 -03:00
Romain Beauxis 58d4114d36 avformat/oggparsevorbis.c: Prevent integer overflow when summing header lengths; add bounds check.
Cherry-picked from 6e0e13b0bf

Signed-off-by: Romain Beauxis <romain.beauxis@gmail.com>
2026-05-26 16:49:12 -05:00
Franciszek Kalinowski b21e00eda5 avformat/oggparsecelt: bound extra_headers to avoid an effectively infinite loop
celt_header() reads a uint32 `extra_headers` field from the CELT identification
header and stores `1 + extra_headers` into the signed int extra_headers_left.
With extra_headers = 0x7FFFFFFE this becomes INT_MAX and the OGG parser
consumes every subsequent page as a CELT "extra header" without ever reaching
audio data, hanging on any streaming input. A value of 0xFFFFFFFE wraps the
signed addition negative, with the same family of consequences.

Reject any extra_headers count above a small fixed cap (16, well above any
real CELT-over-Ogg stream).

Verified with the audit PoC (a crafted file plus an infinite-page FIFO):
without the patch, ffmpeg consumes pages forever; with the patch it logs
"Too many CELT extra headers (...)" and exits in ~70 ms with
AVERROR_INVALIDDATA.

Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.

(cherry picked from commit 87439ed619)
2026-05-21 09:36:30 -05:00
Kacper Michajłow 3728de467d avformat/demux: use correct close function for custom io
You may look and think `AVFMT_FLAG_CUSTOM_IO` check is enough, but this
is not what it seems. This flag means that user provided custom
AVIOContext, before creating AVFormatContext and it should not be
closed. However nested sub-demuxers may still open an temporary io, and
those have to be closed and use correct io_close2 function.

You can see 0dcac9c3f0 and
ef01061225 where this flag is cleared for
nested opens to avoid leaking those.

lavf micro version bumped so API users can know if it is safe to use
custom io.

(cherry picked from commit dc74fe70b2)

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-05-16 18:08:07 +02:00
Kacper Michajłow da9dd86bdc avformat/hlsenc: use correct close function for custom io
This is open by s->io_open().

(cherry picked from commit 200cbaeb5a)

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-05-16 18:07:19 +02:00
Kacper Michajłow 8c31bbbb37 avformat/hlsenc: respect io_open set in AVFormatContext
io_open_default() will call internal impl if needed, don't call it
directly.

(cherry picked from commit 06ef9a74ea)

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-05-16 17:30:43 +02:00
Kacper Michajłow 470685bd1d avformat/dashenc: respect io_open set in AVFormatContext
io_open_default() will call internal impl if needed, don't call it
directly.

(cherry picked from commit 4cf687b3b1)

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-05-16 17:26:51 +02:00
Kacper Michajłow 6f746f57d8 avformat/dashdec: respect io_open set in AVFormatContext
io_open_default() will call internal impl if needed, don't call it
directly.

(cherry picked from commit fbc4003642)

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-05-16 17:25:56 +02:00
nyanmisaka fb216b5fac vulkan: fix using encode caps before querying
Fix using enc_caps.supportedEncodeFeedbackFlags before
calling vkGetPhysicalDeviceVideoCapabilitiesKHR().

Otherwise the check will never pass and will fail with ENOTSUP.

Fixes 3f9e04b

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
(cherry picked from commit d01d18ad71)
2026-05-15 04:30:53 +09:00
Marvin Scholz 1068a26663 avformat/rtpdec_av1: fix buffer overflow due to variable confusion
The pktpos denotes the position in the output packet buffer, while
buf_ptr is the position in the input buffer. As this payload is ignored,
nothing is written to the output packet so increasing the pktpos does
not make sense here, instead the buf_ptr has to be increased to advance
the input buffer to the correct position after this OBU.

This incorrect increment here could result in pktpos exceeding the whole
size of the output packet and the later call to memcpy to write to that
buffer would start its write way past the end of the packet buffer.

Fix #22812

Reported-By: fre3dm4n
(cherry picked from commit 18761f9fb5)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-05-12 16:15:10 +02:00
Michael Niedermayer 239f2c733d Bump micro for 8.1.1
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-04 00:07:35 +02:00
James Almer 6266867e7b avcodec/av1dec: check that primary_ref_frame is within range
Fixes CVE-2026-30997

Fixes: Out-of-Bounds Access
Found-by: Xinghang Lv
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 1a2c16fe51)
2026-05-03 15:58:37 -03:00
Michael Niedermayer 2c28491579 Preparing 8.1.1 release
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:42:27 +02:00
Michael Niedermayer 140d581786 avcodec/aac/aacdec_usac_mps212: fix attach_lsb() OOB after huff_decode
Fixes: VS-FF-2026-0001/poc.wav

Reported-by: Vuln Seeker Cyber Security Team
(cherry picked from commit 2e32276872)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:01 +02:00
Michael Niedermayer e2c6836694 avcodec/dfpwmdec: Check nb_samples
Fixes: integer overflow

Found-by: Dhiraj Mishra <mishra.dhiraj95@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 118bddf0ce)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:01 +02:00
Michael Niedermayer d2597ecda6 avcodec/alsdec: do not set nbits invalidly
note that the spec actually disallows the 0 case too but we are
a little lenient here so the full 24bit twos-complement range can be handled

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7ae36ceba9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:00 +02:00
Michael Niedermayer 0a69adf4ee swscale/swscale_unscaled: adjust last line copy
Fixes: out of array access
Fixes: DFVULN-694

*Reporter: Zhenpeng (Leo) Lin at depthfirst*

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 43a0715e30)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:00 +02:00
Michael Niedermayer 1d24758bd1 swscale/swscale: Check srcSliceY and srcSliceH
Obviously noone should pass negative values, they make no sense, but better to
explicitly check

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7d0837a742)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:00 +02:00
Michael Niedermayer 0a752b7913 avformat/avidec: check LIST size in avi_load_index()
This avoids an unsigned integer underflow and passing that large value to ff_read_riff_info()

(cherry picked from commit 2678bce860)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:00 +02:00
depthfirst-dev[bot] 847b2afc9c avformat/avidec: validate INFO list size before parsing
Reject INFO list chunks that are too small to contain the expected
4-byte list type field before calling ff_read_riff_info().

The parser subtracts 4 from the list size when handing the remaining
payload to ff_read_riff_info(). If the chunk is smaller than 4 bytes,
that underflows the expected structure and should be treated as invalid
input.

Fixes: DFVULN-607

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

(cherry picked from commit f1c3f1cae1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:25:00 +02:00
Michael Niedermayer bad324bd68 avformat/matroskadec: Check audio.sub_packet_h * audio.frame_size
Fixes: out of array access
Fixes: poc_matroska.mkv

This issue requires manually increasing the malloc limit
(-max_alloc 4294967296)

Found-by: Guanni Qu <qguanni@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit f47ca0a5e6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Michael Niedermayer eaf5015aa8 libavformat/xwma: fix overflow in seek position
Fixes: signed integer overflow

Found-by: Marius Momeu <marius.momeu@berkeley.edu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 2d4ec46345)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Michael Niedermayer e483eb921d avformat/pcm: Use 64bit for byte_rate
Fixes: integer overflow

Found-by: Marius Momeu <marius.momeu@berkeley.edu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9d9250e5da)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Michael Niedermayer 76dddbc961 avcodec/adpcm: signed integer overflow in ADPCM_N64
Fixes: signed integer overflow

Found-by: Marius Momeu <marius.momeu@berkeley.edu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b45a6d3f76)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Michael Niedermayer af2a176fd2 avcodec/hevc/ps: validate rep_format dimensions in multi-layer SPS
When an SPS uses the multi-layer extension (nuh_layer_id > 0 with
sps_max_sub_layers_minus1 == 7), width and height are taken from the
VPS rep_format without the av_image_check_size() validation that the
direct path performs.  HEVC F.7.4.3.1.1 requires rep_format pic
dimensions to satisfy the constraints in 7.4.3.2.1, including
"pic_width_in_luma_samples shall not be equal to 0".

Run the same av_image_check_size() check in the multi-layer-extension
path so the SPS is rejected before it reaches setup_pps().

Fixes: VS-FF-2026-0003/poc.flv
Fixes: out of array access

Found-by: Vuln Seeker Cyber Security Team
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 0f5705959d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Marius Momeu 698000f5bd avfilter/vf_kerndeint: Check for minimum height
Fixes: out of array access

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit e32b2c8886)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:59 +02:00
Marius Momeu f6dd450a26 avcodec/ralf: Add the missing return statement after the error log
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit ff3223b5d6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:58 +02:00
Michael Niedermayer 31855e032c avfilter/vf_codecview: Clamp block to the visible frame region
Fixes: write into the padding area of the frame

Found-by: Marius Momeu <marius.momeu@berkeley.edu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c568f40597)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:58 +02:00
Michael Niedermayer 77f2c227c2 avcodec/zmbv: reject XOR data that overruns the decompression buffer
Add a per-block bounds check at the start of each XOR block so the
read is rejected before src crosses decomp_len, and propagate the
error from decode_frame().

Fixes: out of array read

Found-by: Seung Min Shin
(cherry picked from commit 2a991a3475)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:58 +02:00
Michael Niedermayer 102c590a5f avcodec/rasc: fix heap use-after-free in decode_move()
Use a separate scratch buffer (s->mv_scratch) for the type-0 pixel
copy so s->delta and mc are not disturbed for the lifetime of
decode_move().  The new buffer is freed in decode_close().

Found-by: Seung Min Shin
Patch based on suggsted fix by Seung Min Shin

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 2f60af465a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:58 +02:00
depthfirst-dev[bot] ad62419fb8 avformat/rtpdec_mpeg4: reject zero-length AU header sections
Reject AU header sections with a signaled length of zero in
rtp_parse_mp4_au().

The AU-headers-length field specifies the length in bits of the AU header
section that immediately follows. A zero-length section is not useful input
for this parser and can lead to invalid downstream state, so reject it
up front together with oversized values.

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

Fixes: OOB read
(cherry picked from commit 8010aa2193)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:58 +02:00
Niels Provos 874f26fe96 avcodec/hevc/refs: Check multiplication in alloc_frame()
Fixes: integer overflow on 32bit
(cherry picked from commit fd5023053a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
depthfirst-dev[bot] dc3742fd7f fftools/ffmpeg_opt: validate stream index in negative map handling
Negative -map processing iterates previously parsed stream map entries
and dereferences input_files[m->file_index]->ctx->streams[m->stream_index]
without validating that stream_index is in range.

A malformed earlier map can leave m->stream_index negative, which causes
an out-of-bounds read when a later negative map walks existing entries.
Check that stream_index is non-negative and below nb_streams before
calling stream_specifier_match().

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

Fixes: DFVULN-695
(cherry picked from commit 25a98586cc)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
Flavio Milan cdd6df0104 avformat/rtmpproto: prevent integer overflow accumulating FLV buffer size
Fixes: out of array access
(cherry picked from commit a45a91b23b)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
depthfirst-dev[bot] 2d646e5584 avformat/rtmpproto: validate compressed SWF header length
Reject truncated compressed SWF input before attempting to read the
8-byte header in rtmp_calc_swfhash().

Compressed SWF data identified by the "CWS" signature must be at least
8 bytes long to contain the fixed header. Bail out early when the input
is shorter to avoid operating on malformed data.

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

Fixes: DFVULN-612
(cherry picked from commit 52b78cd3fe)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
depthfirst-dev[bot] 62a87e5516 avformat/rtsp: Fix out-of-bounds read in SDP parser when control_url is empty
Guard against empty string before reading the last byte in control_url.
When parsing relative a=control: paths, if no base control URL was set,
the code would access control_url[strlen(control_url)-1] which on an
empty string causes a size_t underflow and out-of-bounds read.

Now compute the length first and check for len == 0 before array access.

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

Fixes: DFVULN-611
(cherry picked from commit 1a00ea51cb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
depthfirst-dev[bot] 19fc59fde6 avformat/rtpdec_latm: avoid integer overflow in LATM length parsing
latm_parse_packet() accumulated attacker-controlled AU length bytes in
a signed int and later checked data->pos + cur_len against data->len.
That addition could overflow, allowing malformed packets to bypass the
bounds check and drive memcpy() far past the end of the LATM buffer.

Reject length-byte accumulation that would exceed the remaining packet
size, and compare cur_len against the remaining buffer space using
subtraction so the bounds check cannot overflow.

Fixes: DFVULN-610

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

(cherry picked from commit 664d44a825)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:57 +02:00
Michael Niedermayer 0ba002f92d avcodec/h264: recompute per-slice direct mode state for every slice
Regression since: 7f05c5cea0
Fixes: poc10
Fixes: null pointer dereference

Reported-by: Dale Curtis <dalecurtis@chromium.org>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 1772386392)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:56 +02:00
Michael Niedermayer 8462c37595 avcodec/h264_refs: Clear stale pointers from ref_list
Testcase: poc10.bin

Reported-by: Dale Curtis <dalecurtis@chromium.org>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 1886c3269d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:56 +02:00
Michael Niedermayer 6c2e9930b2 avcodec/pdvdec: Check input space before buffer allocation
this rejects packets whose claimed decompressed frame would require a deflate ratio beyond the format's theoretical 1032:1 limit

Fixes: Timeout
Fixes: 474457186/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PDV_fuzzer-5366108782919680

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 b801f1fe6d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:56 +02:00
Kacper Michajłow 5bb3c22021 avformat/concat: guard total_size overflow
Fixes: 466797413/clusterfuzz-testcase-minimized-fuzzer_options_parser-6015183727427584
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit 702b0784b7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:56 +02:00
Michael Niedermayer d26ce3ec60 avformat/iamf_parse.c: Fix potential integer overflow in opus_decoder_config()
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 016a241102)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:56 +02:00
Michael Niedermayer d1b0069077 avcodec/wmaenc: Fix missing padding in extradata
Reported-by: Kenan Alghythee <kalghy2@uic.edu>
(cherry picked from commit 23227a444d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
Michael Niedermayer 7d612d27ae avformat: Fix various extradata padding issues
Reported-by: Kenan Alghythee <kalghy2@uic.edu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 8439e02037)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
Michael Niedermayer 031fae5c41 avcodec/tdsc: remove double stride adjustment
Fixes: out of array access

Found-by: Seung Min Shin
Patch based on suggested fix by Seung Min Shin
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 242ff799c7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
depthfirst-dev[bot] f9a9fae557 avformat/cafdec: fix negative index use in read_seek
av_index_search_timestamp() returns a negative value when a seek target
cannot be resolved from the stream index. Bail out before using that
result as an index into sti->index_entries to avoid out-of-bounds reads.

Fixes: Buffer underflow

Fixes: DFVULN-608

*Vulnerability reported by Zhenpeng (Leo) Lin at depthfirst*
*Patch validated by Zheng Yu at depthfirst*

(cherry picked from commit 5408059eb7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
Michael Niedermayer 3e57f240cc avcodec/notchlc: Check 255 loops
Fixes: integer overflow

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 05817dc7dd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
Michael Niedermayer b5489087f3 avformat/rtpdec_jpeg: check qtable_len
Fixes: out of array access
Fixes: 605/pc.py

Based-on patch by depthfirst

*Reporter: Zhenpeng (Leo) Lin at depthfirst*

(cherry picked from commit 91d29be49a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:55 +02:00
ASTRA 66d96bd65e avformat/vividas: use-of-uninitialized-value in keybuffer
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 26732641fb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:54 +02:00
Michael Niedermayer cdfa960ddf avcodec/tdsc: Check jpeg size
Fixes: out of array read
Fixes: tdsc_tile_dim_mismatch.avi

Found-by: Ante Silovic <asilovic155@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit bb69a090a7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:54 +02:00
Michael Niedermayer ee35cdda74 avcodec/tdsc: Better input size check
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit bf4eb194cf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:54 +02:00
Michael Niedermayer e9fc881384 avcodec/tdsc: Check tile_size
Fixes: out of array read
Fixes: tdsc_war_groom_far4096.avi

Found by: Ante Silovic <asilovic155@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit e9e6fb8798)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:54 +02:00
Michael Niedermayer df197112c2 avcodec/decode: Better documentation for ff_set_dimensions()
Clarify what is checked and that it avoids explicit generic overflow checks

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9572ab7f45)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:54 +02:00
Dale Curtis 76fd415fce avformat/mov: Limit maximum box size for mov_read_lhvc()
Signed-off-by: Dale Curtis <dalecurtis@chromium.org>
(cherry picked from commit a7d42bfba8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:53 +02:00
depthfirst-dev[bot] dd2a960971 avformat/mov: reject dimg references with zero entries
Reject dimg entries with a zero reference count in mov_read_iref_dimg().
This is the earliest point where the parser learns how many input images
a derived HEIF item references, so it is the right place to enforce the
invariant.

If entries == 0 is accepted here, the value is stored in HEIFGrid.nb_tiles,
later propagated by read_image_iovl() into AVStreamGroupTileGrid.nb_tiles,
and finally consumed in istg_parse_tile_grid(), which assumes at least one
tile and reads tg->offsets[tg->nb_tiles - 1]. With zero tiles, that
assumption breaks and leads to the out-of-bounds access seen in ASan.

Fixing the problem at the parser boundary is preferable to adding a later
workaround because it prevents creation of an invalid derived-image state
and stops that malformed state from reaching downstream consumers.

This is also consistent with the HEIF specification. Both iovl and grid
derived images are formed from one or more input images, and for grid the
dimg reference count must equal rows * columns; since rows and columns are
encoded as *_minus_one + 1, that count cannot be zero. A zero dimg entry
count is therefore invalid input and should be rejected when parsed.

(cherry picked from commit 68ea660d83)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:53 +02:00
Michael Niedermayer 9e5a493d71 avformat/mov: check extradata in mov_read_dops()
We do want to limit an attackers ability to change once parsed structures.
So once extradata (or another array) is finished and possibly has been used we do not
want to allow an attacker to change it.

This reduces the attack surface

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 7c67748537)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:53 +02:00
Ted Meyer 797504295b avformat/mov: Check read size for opus extradata
in mov_read_dops, `size` bytes is allocated for
`st->codecpar->extradata`, but ff_alloc_extradata doesn't memset, so the
contents of that buffer are just old heap data. If `avio_read` reads
fewer bytes than were requested, uninitialized data can still be left in
the extradata buffer, which is operated on by AV_WL16A and AV_WL32A.

I think the best solution here is to just check the read size and ensure
it's filling the extradata buffer in it's entirety, or erroring out if
there isn't enough data left.

(cherry picked from commit 53cd2c9f2a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:53 +02:00
depthfirst-dev[bot] a3abd79fde avformat/rtspdec: reject non-positive ANNOUNCE Content-Length
rtsp_read_announce() treated any non-zero Content-Length as valid,
including negative values parsed via strtol(). This could send invalid
sizes into allocation, body reads and trailing NUL writes.

Accept only strictly positive SDP body lengths and reject invalid
Content-Length values with AVERROR_INVALIDDATA.

Found-by: Seung Min Shin (was reported to us on 10th April)
CC: 신승민 <guncraft2000@naver.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit eec78bdac1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:53 +02:00
ASTRA 01d380bdb2 avformat/wavdec: Fix use-of-uninitialized-value in find_guid()
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 163ba704b7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Marvin Scholz 9cbd7e2589 lavfi: vf_drawtext: check memory allocation
Switch to av_calloc and check the allocation.

Fix #22867

(cherry picked from commit 69072fe8d8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Michael Niedermayer 9601014f1e avcodec/svq1dec: Check input space for minimum
We reject inputs that are significantly smaller than the smallest frame.
This check raises the minimum input needed before time consuming computations are performed
it thus improves the computation per input byte and reduces the potential DoS impact

Fixes: Timeout
Fixes: 472769364/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SVQ1_DEC_fuzzer-5519737145851904

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 d538a71ad5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Paul Adenot 5fe5d2a13b avcodec/vp9: Rollback dimensions when format is rejected
Fixes: BMO#2029296

Found-by: Mozilla Security Team, Paul Adenot for the write variant
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 6c114bd6fa)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Michael Niedermayer 44fe8891c8 avformat/rtpdec_qdm2: Check block_size
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 29a0973855)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Zhao Zhili 5a1dc812b1 avfilter/vf_ssim360: fix integer overflow in tape_length allocation
tape_length * 8 overflows 32-bit int for large input widths. Then
av_malloc_array() allocates a tiny buffer while the subsequent
loop writes tape_length*8 BilinearMap entries, causing
heap-buffer-overflow.

Validate the value in float before converting to int and left
shifting, to avoid both float-to-int and signed left shift
overflow UB. Also split av_malloc_array() arguments to avoid
the multiplication overflow.

Fixes: #21511

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit b62ae766c1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:52 +02:00
Michael Niedermayer fa1ac7bd8a avcodec/escape130: Initialize old_y_avg
Fixes: use of uninitialized memory

Found-by: Carl Sampson <carl.sampson@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d0761626cf)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:51 +02:00
Michael Niedermayer ea84befff6 avutil/samplefmt: Dont claim that av_get_sample_fmt_string checks sample_fmt
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b11729f154)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:51 +02:00
Hankang Li d5d2f063ff swscale: fix signed integer overflow in color conversion arithmetic
Fixes: #22331

Signed-off-by: Hankang Li <hankang201222@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit e33b3962e5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:51 +02:00
Sankalpa Sarkar 08a31e67af avformat: check avio_read() return values in dss/dtshd/mlv
Multiple demuxers call avio_read() without checking its return
value. When input is truncated, destination buffers remain
uninitialized but are still used for offset calculations, memcmp,
and metadata handling. This results in undefined behavior
(detectable with Valgrind/MSan).

Fix this by checking the return value of avio_read() in:
- dss.c: dss_read_seek() — check before using header buffer
- dtshddec.c: FILEINFO chunk — check before using value buffer
- mlvdec.c: check_file_header() — check before memcmp on version

Fixes: #21520
(cherry picked from commit 65eed0732c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:51 +02:00
Ruikai Peng 8c7ec4b4b5 avformat/whip: check RTP history packet size before RTX retransmission
handle_rtx_packet() constructs an RTX packet by shifting the payload
of a history entry to insert the original sequence number. It uses
memmove with length (ori_size - 12), but never checks that ori_size
is at least 12 bytes (the minimum RTP header size).

Zero-initialized history slots have seq == 0 and size == 0.
rtp_history_find() only compares sequence numbers, so an RTCP NACK
requesting seq 0 early in a session matches such a slot. The
subtraction then wraps to a huge value when converted to size_t,
causing a stack buffer overflow in memmove().

Add a little size check to reject history entries smaller than and
valid RTP header before any arithmetic on their size.

Found-by: Pwno
(cherry picked from commit 7466d8a850)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:51 +02:00
Michael Niedermayer 0b0a2d236d avcodec/aac/aacdec_usac: Implement missing bits of otts_bands_phase and residual_bands computation
Fixes: out of array access
Fixes: matejsmycka/poc.mp4

Introducing commit: `baad75cafa6bac298b72c177f657a2eb8e31cff1` — "aacdec_usac: add support for parsing Mpsp212 (MPEG surround)", 2025-11-17.

Found-by: Matěj Smyčka <matejsmycka@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit ddcb9dd3b5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Priyanshu Thapliyal 71818d86ae avcodec/alsdec: preserve full float value in zero-truncated samples
Signed-off-by: Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.com>
(cherry picked from commit d1bcaab230)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Priyanshu Thapliyal e927c11cfc avcodec/alsdec: propagate read_diff_float_data() errors in read_frame_data()
The return value of read_diff_float_data() was previously ignored,
allowing decode to continue silently with partially transformed samples
on malformed floating ALS input. Check and propagate the error.

All failure paths in read_diff_float_data() already return
AVERROR_INVALIDDATA, so the caller fix is sufficient without
any normalization inside the function.

Signed-off-by: Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.com>
(cherry picked from commit febc82690d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Priyanshu Thapliyal f5e4bf6dbd avcodec/alsdec: fix mantissa unpacking in compressed Part A path
Signed-off-by: Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.com>
(cherry picked from commit ae6f233988)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Zhao Zhili c47b33c61c avfilter/vf_drawtext: fix newline rendered as .notdef glyph
GET_UTF8 advances the pointer past the newline byte before the
newline check, so shape_text_hb receives text that includes the
newline character. Since HarfBuzz does not treat U+000A as
default-ignorable, it gets shaped into a .notdef glyph.

Fixes #21565

Reported-by: scriptituk <info@scriptit.uk>
Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit fd9f1e9c52)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Priyanshu Thapliyal f7103aa69e avcodec/pngdec: fix dead overflow check in decode_text_to_exif()
The expression (exif_len & ~SIZE_MAX) is always 0 for size_t,
making the overflow guard permanently dead code.

Reported-by: Guanni Qu <qguanni@gmail.com>
Signed-off-by: Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.com>
(cherry picked from commit e7b4ddc9d6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:50 +02:00
Kacper Michajłow b81bc90e0c avcodec/vp9: fix cbs fragment leak on error
Fixes: c0bf1382a7
Fixes: 490257166/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VP9_fuzzer-6185031050788864
Fixes: 490131106/clusterfuzz-testcase-minimized-fuzzer_loadfile-5438205762797568
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit e17d84ac8a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:49 +02:00
marcos ashton c3fa0d869b libavfilter/vf_v360: fix operator precedence in stereo loop condition
The loop condition in the DEFINE_REMAP macro:

  stereo < 1 + s->out_stereo > STEREO_2D

is parsed by C as:

  (stereo < (1 + s->out_stereo)) > STEREO_2D

Since STEREO_2D is 0 and relational operators return 0 or 1, the
outer comparison against 0 is a no-op for STEREO_2D and STEREO_SBS.
But for STEREO_TB (value 2) the loop runs 3 iterations instead of 2,
producing an out-of-bounds stereo pass.

Add parentheses so the comparison is evaluated first:

  stereo < 1 + (s->out_stereo > STEREO_2D)

This gives 1 iteration for 2D and 2 for any stereo format (SBS or TB),
matching the actual number of stereo views.

Signed-off-by: marcos ashton <marcosashiglesias@gmail.com>
(cherry picked from commit 9559a6036d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:49 +02:00
Priyanshu Thapliyal ff129c8f04 avcodec/alsdec: fix abs(INT_MIN) UB in read_diff_float_data()
Replace abs() with FFABSU() to avoid undefined behavior when
raw_samples[c][i] == INT_MIN. Per libavutil/common.h, FFABS()
has the same INT_MIN UB as abs(); FFABSU() is the correct
helper as it casts to unsigned before negation.

Reported-by: Guanni Qu <qguanni@gmail.com>
Signed-off-by: Priyanshu Thapliyal <priyanshuthapliyal2005@gmail.com>
(cherry picked from commit 1853c80e20)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:49 +02:00
Weidong Wang 097668f94c avformat/rsd: reject short ADPCM_THP extradata reads
Use ffio_read_size() to enforce exact-length reads of the per-channel
ADPCM_THP coefficient tables. Previously the return value of
avio_read() was unchecked, silently accepting truncated extradata.

(cherry picked from commit 06d19d000d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:49 +02:00
Ted Meyer 355269a9f0 avformat/mov: Handle integer overflow in MOV parser
A chromium UBSAN fuzzer caught this instance.

(cherry picked from commit fc7cab6be3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:49 +02:00
Michael Niedermayer 059489977b avcodec/dvdsub_parser: Fix buf_size check
Fixes: signed integer overflow
Fixes: out of array access
Fixes: dvdsub_int_overflow_mixed_ps.mpg

Found-by: Quang Luong of Calif.io in collaboration with OpenAI Codex
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 1bde76da89)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:48 +02:00
marcos ashton 93b8ad91bf avfilter/af_pan: fix sscanf() return value checks in parse_channel_name
sscanf() returns EOF (-1) on input failure, which is non-zero and
passes a bare truthy check. When this happens, the %n directive is
never processed, so len stays uninitialized. Using that value to
advance the arg pointer causes an out-of-bounds read and crash.

Check for >= 1 instead, matching the fix applied to the other
sscanf() call in init() by commit b5b6391d64.

Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22451
Signed-off-by: marcos ashton <marcosashiglesias@gmail.com>
(cherry picked from commit a43ea8bff7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:48 +02:00
marcos ashton ff47e29b10 avutil/bswap: fix implicit conversion warning in av_bswap64
Explicitly cast uint64_t arguments to uint32_t before passing them
to av_bswap32(). The truncation is intentional (extracting low and
high halves), but clang on macOS 26 warns about it.

Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/22453
Signed-off-by: marcos ashton <marcosashiglesias@gmail.com>
(cherry picked from commit dfa53aae5f)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:48 +02:00
James Almer 3127b0db72 avcodec/h2645_sei: don't use provider_code uninitialized
Regression since 8172be423e.
Fixes Coverity issue CID 1689618.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit e22a1ed712)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-05-03 19:24:48 +02:00
AdityaTeltia 75d37c499d avformat/hls_sample_encryption: add missing padding for audio setup buffer
Fixes ticket #22890.

The ff_hls_senc_parse_audio_setup_info function passes setup_data to
parsers like avpriv_ac3_parse_header and init_get_bits8 which require
the buffer to be padded with AV_INPUT_BUFFER_PADDING_SIZE bytes at the end.

(cherry picked from commit 71d5fa8d4d)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-04-28 11:41:32 +02:00
Jun Zhao 7f5c90f77e lavc/videotoolbox_vp9: fix vpcC flags offset
Write the 24-bit vpcC flags field at the current cursor position after
the version byte. The previous code wrote to p+1 instead of p, leaving
one byte uninitialized between version and flags and shifting all
subsequent fields (profile, level, bitdepth, etc.) by one byte.

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
(cherry picked from commit 19c4bcae68a16ea893b0558d720dd4a2ecd58f0f)
2026-04-15 23:13:24 +08:00
Jun Zhao 0fa756d03d lavc/videotoolboxenc: return SEI parse errors
Return the actual find_sei_end() error when SEI appending fails instead of
reusing the previous status code. This preserves the real parse failure for
callers instead of reporting malformed SEI handling as success.

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
(cherry picked from commit f7c04283367269c7aef2505a1839fb3ea9362330)
2026-04-15 23:13:24 +08:00
Stéphane Cerveau 735c84b57f vulkan: fix encode feedback query handling
Check that the driver supports both BUFFER_OFFSET and BYTES_WRITTEN
encode feedback flags before creating the query pool, failing with
EINVAL if either is missing.

Set these flags explicitly instead of masking off HAS_OVERRIDES with a
bitwise NOT, which could pass unrecognized bits from newer drivers to
vkCreateQueryPool causing validation errors and
crashes.

(cherry picked from commit 3f9e04b489)
2026-04-14 23:32:41 +02:00
James Almer a3475e2554 avcodec/cbs_lcevc: fix writing process blocks with size 6
6 is an undefined value for payload_size_type. For those, 7 is used to signal
a custom_byte_size synxtax element.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 35a1e43a6a)
2026-03-24 18:06:22 -03:00
James Almer bd7f101bda avformat/mov: don't try to create an LCEVC group if there's a single track
In this scenario, as it's the case with DASH segments, the lcevc track will be
alone but potentially have a sbas tref entry referencing itself, which will
make avformat_stream_group_add_stream() fail.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit e1158301f0)
2026-03-23 10:51:59 -03:00
Martin Storsjö 3ec48e4bc6 aarch64: Add Armv9.3-A GCS (Guarded Control Stack) support
Signal that our assembly is compliant with the GCS feature, if
the GCS feature is enabled in the compiler (available since Clang
18 and GCC 15) - this is enabled by -mbranch-protection=standard
with a new enough compiler.

GCS doesn't require any specific modifications to the assembly
code, but requires that all functions return to the expected call
address (checked through a shadow stack).

(cherry picked from commit 846746be4b)
2026-03-20 13:12:08 +02:00
Martin Storsjö 2bb6264105 aarch64: hevcdsp: Make returns match the call site
For cases when returning early without updating any pixels, we
previously returned to return address in the caller's scope,
bypassing one function entirely. While this may seem like a neat
optimization, it makes the return stack predictor mispredict
the returns - which potentially can cost more performance than
it gains.

Secondly, if the armv9.3 feature GCS (Guarded Control Stack) is
enabled, then returns _must_ match the expected value; this feature
is being enabled across linux distributions, and by fixing the
hevc assembly, we can enable the security feature on ffmpeg as well.

(cherry picked from commit 1f7ed8a78d)
2026-03-20 13:12:04 +02:00
James Almer 9abdfda6f2 avcodec/lcevcdec: don't try to derive final dimensions from SAR
Not only do some sources not provide an aspect ratio, as is the case of
MPEG-TS, but also some enhanced streams have no change in dimensions, and this
heuristic would generate bugus values.
Instead, we need to parse the LCEVC bitstream for a Global Config process block
in order to get the actual dimensions. This add a little overhead, but it can't
be avoided.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 49d75d81f6)
2026-03-18 13:35:56 -03:00
James Almer 395dc6fa27 avcodec/lcevc_parser: move the resolution type table to a header
Will be useful in the following commit.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit c5aa31d252)
2026-03-18 13:35:56 -03:00
James Almer a2e15f15b0 avcodec/cbs_lcevc: don't look for process blocks if the unit was not decomposed
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit ce7375fc17)
2026-03-18 13:35:56 -03:00
Marvin Scholz 9047fa1b08 avutil: attributes: fix AV_HAS_STD_ATTRIBUTE checks
Attributes with the language-supported [[attr]] style are only supported
since C++11 and C23 respectively, so this needs to be accounted for in
these checks.

This solves a huge amount of warning spam of:
  warning: [[]] attributes are a C23 extension [-Wc23-extensions]
when using --enable-extra-warnings.

(cherry picked from commit cce545a74b)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-03-16 18:46:24 +01:00
Michael Niedermayer e1a84cd003 doc/Doxyfile: set version to 8.1
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 17:24:34 +01:00
Michael Niedermayer 5c923e26ab avformat/wsddec: Use ffio_read_size() in get_metadata()
Fixes: use of uninitialized memory
Fixes: 492587173/clusterfuzz-testcase-minimized-ffmpeg_dem_WSD_fuzzer-6596163492184064

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 4b83833087)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 17:23:47 +01:00
Nicholas Carlini c471fce2bf avformat/mpegts: fix descriptor accounting across multiple IOD descriptors
pmt_cb() passes mp4_descr + mp4_descr_count as the output base but
MAX_MP4_DESCR_COUNT (16) as the capacity, not the remaining capacity.
init_MP4DescrParseContext() resets d->descr_count to 0 on every call,
so the bounds check at parse_MP4ESDescrTag compares a fresh 0 against
16 regardless of the shifted base.

A PMT with two IOD descriptors of 16 ESDescrs each will crash. The first
fills the buffer mp4_descr[0..15], and then the second writes
mp4_descr[16..31] -- 1152 bytes past the end of the stack.

This change passes the remaining capacity instead of always passing 16.
The writeback in mp4_read_iods is incremented so the caller's running
count is preserved.

Fixes: stack-buffer-overflow

Found-by: Nicholas Carlini <nicholas@carlini.com>
(cherry picked from commit 3e8bec7871)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 17:23:47 +01:00
Weidong Wang 5f3122760f avcodec/xxan: zero-initialize y_buffer
Fixes ticket #22420.

When the first decoded frame is type 1, xan_decode_frame_type1() reads y_buffer as prior-frame state before any data has been written to it.
Since y_buffer is allocated with av_malloc(), this may propagate uninitialized heap data into the decoded luma output.

Allocate y_buffer with av_mallocz() instead.

(cherry picked from commit 236dbc9f82)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 17:23:47 +01:00
Anton Khirnov 43a4771cd0 opus/dec_celt: avoid emph_coeff becoming a subnormal
This happens for silence frames, which on many CPUs massively slows down
processing the decoded output.

Cf. https://github.com/Genymobile/scrcpy/issues/6715

(cherry picked from commit 5b112b17c0)
2026-03-16 11:53:14 +01:00
Michael Niedermayer 8a8881d226 RELEASE: prepare for 8.1
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 03:42:03 +01:00
Michael Niedermayer 7dad4d2cb5 Changelog, remove "version <next>" 2026-03-16 03:42:03 +01:00
Michael Niedermayer a5a1653a9e RELEASE_NOTES: Based on the version from 8.0
Name suggested by 2 people on ML, all other suggestions had only 1 supporter

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-16 03:42:03 +01:00
James Almer 0a8bf5fcaa avcodec/bsf/extract_extradata: don't use a NULL pointer to initialize an empty PutByteContext
Fixes UB in the form or adding a 0 offset to a NULL pointer, and substracting a
NULL pointer from another.

Signed-off-by: James Almer <jamrial@gmail.com>
2026-03-15 19:44:21 -03:00
James Almer 29e0d0ef13 avcodec/h2645_sei: fix parsing payloads for UK country_code
The correct syntax after country_code is:

t35_uk_country_code_second_octet      b(8)
t35_uk_manufacturer_code_first_octet  b(8)
t35_uk_manufacturer_code_second_octet b(8)

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 8172be423e)
2026-03-15 17:46:51 -03:00
James Almer 93c915a572 avcodec/h2645_sei: reindent after the previous change
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 3af824a540)
2026-03-15 17:46:51 -03:00
James Almer fcbbd8b394 avcodec/h2645_sei: refactor decode_registered_user_data()
Switch statements are cleaner and will be useful for an upcoming change.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 64edbb37f1)
2026-03-15 17:46:51 -03:00
Zhao Zhili 7df9a56f0d avformat/rtmpproto: fix listen_timeout conversion for special negative values
rtmpproto converts listen_timeout to milliseconds by multiplying it
by 1000 before passing it to TCP. However, negative values are special
sentinels (e.g., -1 for infinite wait) and should not be multiplied.

This worked prior to commit 49c6e6cc44 because there was no range
validation. Since that commit, ff_parse_opts_from_query_string
validates option values against their declared ranges, causing these
multiplied negative values to fail.

Fixes ticket #22469.

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit f189657ec6)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-03-15 03:15:37 +00:00
Michael Niedermayer 6f890cb104 avcodec/exr: Check input space before reverse_lut()
Fixes: use of uninitialized memory
Fixes: 490707906/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EXR_DEC_fuzzer-6310933506097152

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 70286d59f1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:58 +01:00
Nicholas Carlini 42692d0f57 avformat/mpegts: remove JPEG-XS early return on invalid header_size
new_pes_packet() moves a buffer with pkt->buf = pes->buffer before
JPEG-XS validation. If header_size > pkt->size, an early return leaves
pes->buffer as a stale alias of pkt->buf with refcount 1. Later,
mpegts_read_packet() calls av_packet_unref(), freeing the buffer
through pkt->buf. The flush loop then re-enters new_pes_packet() and
dereferences the dangling pes->buffer; a second path hits it via
av_buffer_unref() in handle_packets() after a seek.

Drop the early return. The packet is delivered with AV_PKT_FLAG_CORRUPT
set, matching the PES-size-mismatch case above, and the function falls
through to the normal cleanup path. The else guards the header trim so
pkt->data/pkt->size stay valid for the memset.

Fixes: use after free
Fixes regression since 16f89d342e.

Found-by: Nicholas Carlini <nicholas@carlini.com>
(cherry picked from commit 55bf0e6cd5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:58 +01:00
Michael Niedermayer 259ee609ac avcodec/aac/aacdec_usac_mps212: Introduce a temporary array for ff_aac_ec_data_dec()
This also reverts: c2364e9222

Fixes: out of array access (testcase exists but did not replicate for me)

Founbd-by: Gil Portnoy <dddhkts1@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 770bc1c23a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:58 +01:00
Michael Niedermayer b6a617c8bf avcodec/cbs_h266_syntax_template: Check tile_y
Fixes: invalid state leading to out of array access
Fixes: 490615782/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VVC_fuzzer-4711353817563136

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 12303cd922)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:58 +01:00
Nicholas Carlini a5696b44a6 avcodec/h264_slice: reject slice_num >= 0xFFFF
An H.264 picture with 65536 slices makes slice_num collide with the
slice_table sentinel. slice_table is uint16_t, initialized via
memset(..., -1, ...) so spare entries (one per row, mb_stride =
mb_width + 1) stay 0xFFFF. slice_num is an uncapped ++h->current_slice.
At slice 65535 the collision makes slice_table[spare] == slice_num
pass, defeating the deblock_topleft check in xchg_mb_border and the
top_type zeroing in fill_decode_caches.

With both guards bypassed at mb_x = 0, top_borders[top_idx][-1]
underflows 96 bytes and XCHG writes at -88 below the allocation
(plus -72 and -56 for chroma in the non-444 path).

Fixes: heap-buffer-overflow

Found-by: Nicholas Carlini <nicholas@carlini.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 39e1969303)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Jun Zhao 5bc4a9898c lavfi/bwdif: fix heap-buffer-overflow with small height videos
Reproduce:
  ffmpeg -i /tmp/bwdif_test_input_160x4_gray16.jpg -vf "bwdif" -f null -

filter_intra accesses rows 3 lines away via cur[mrefs3] and cur[prefs3].
For small height videos (h <= 4), this causes heap-buffer-overflow.

Add boundary check for filter_intra when YADIF_FIELD_END is set.
The boundary condition (y < 3) or (y + 3 >= td->h) precisely matches
filter_intra's 3-line context requirement.

Test file: 160x4 gray16 JPEG
https://code.ffmpeg.org/attachments/db2ace24-bc00-4af6-a53a-5df6b0d51b15

fix #21570

Reviewed-by: Thomas Mundt <tmundt75@gmail.com>
Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
(cherry picked from commit 795bccdaf5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Michael Niedermayer b6faea362a avcodec/wmv2dec: More Checks about reading skip bits
Fixes: out of array read with --disable-safe-bitstream-reader
Fixes: poc_wmv2.avi

Note, this requires the safe bitstream reader to be turned off by the user and the user disregarding the security warning

Change suggested by: Guanni Qu <qguanni@gmail.com>
Found-by: Guanni Qu <qguanni@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit f73849887c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Gil Portnoy ca6e0ee7aa avcodec/cbs_h266_syntax_template: Fix w/h typo
Fixes: out of array access
Fixes: vvc_poc_subpic_wh_bug.h266

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 26dd9f9b56)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Oliver Chang f851191ce6 aacdec_usac: skip FD-specific decoding for LPD channels
`spectrum_decode` currently executes Frequency Domain (FD) decoding steps
for all channels, regardless of their `core_mode`. When a channel is in
Linear Prediction Domain (LPD) mode (`core_mode == 1`), FD-specific
parameters such as scalefactor offsets (`sfo`) and individual channel
stream (`ics`) information are not parsed.

This causes a global-buffer-overflow in `dequant_scalefactors`. Because
`spectrum_scale` is called on LPD channels, it uses stale or
uninitialized `sfo` values to index `ff_aac_pow2sf_tab`. In the reported
crash, a stale `sfo` value of 240 resulted in an index of 440
(240 + POW_SF2_ZERO), exceeding the table's size of 428.

Fix this by ensuring `spectrum_scale` and `imdct_and_windowing` are only
called for channels where `core_mode == 0` (FD).

Co-authored-by: CodeMender <codemender-patching@google.com>
Fixes: https://issues.oss-fuzz.com/486160985
(cherry picked from commit d519ab8993)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Michael Niedermayer 60f3904718 avformat/dhav: Fix handling or slightly larger files
Fixes: integer overflow
Fixes: 490241718/clusterfuzz-testcase-minimized-ffmpeg_dem_DHAV_fuzzer-4902512932225024

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 c5d5fb2309)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:57 +01:00
Michael Niedermayer 56217dccd6 avutil/timecode: Check for integer overflow in av_timecode_init_from_components()
Fixes: integer overflow
Fixes: testcase that calls av_timecode_init_from_components() with hh set explicitly to INT_MAX

Found-by: Youngjae Choi, Mingyoung Ban, Seunghoon Woo
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit eb5d607861)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:56 +01:00
Gil Portnoy 4f72addce1 avcodec/cbs_h266_syntax_template: Fix rows vs columns
Fixes: out of array access
Fixes: vvc_poc_cbs_divergence_max.h266

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 51606de0e9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:56 +01:00
Ted Meyer 1f217b4b7d avformat/mov: do not allocate out-of-range buffers
There's a possibility here with a well-crafted MP4 file containing only
the nested boxes in order: MOOV.TRAK.MDIA.MINF.STBL.SDTP where the
header size uses the 64 bit large size, and the ending stdp box has some
size value >= 0x100000014.

On a 32 bit build of ffmpeg, av_malloc's size parameter drops the high
order bits of `entries`, and and the allocation is now a controlled size
that is significantly smaller than `entries`. The following loop will
then write off the ended of allocated memory with data that follows the
box fourcc.

(cherry picked from commit 86f53f9ffb)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:56 +01:00
Karl Mogensen 0ce7bd66a7 avfilter/af_lv2: call lilv_instance_activate before lilv_instance_run
Why: the change is done to comply with lilv expectations of hosts.

Added call lilv_instance_activate in the config_output function to abide by lilv documentation that states it must be called before lilv_instance_run:
"This MUST be called before calling lilv_instance_run()" - documentation source (https://github.com/lv2/lilv/blob/main/include/lilv/lilv.h)

Added call lilv_instance_deactivate in the uninit function to abide by lv2 documentation:
"If a host calls activate(), it MUST call deactivate() at some point in the future" - documentation source (https://gitlab.com/lv2/lv2/-/blob/main/include/lv2/core/lv2.h)

Added instance_activated integer to LV2Context struct to track if instance was activated and only do lilv_instance_deactivate if was activated to abide by lv2 documentation:
"Hosts MUST NOT call deactivate() unless activate() was previously called." - documentation source (https://gitlab.com/lv2/lv2/-/blob/main/include/lv2/core/lv2.h)

Regarding the patcheck warning (possibly constant :instance_activated):
This is a false positive since the struct member is zero-initialized.

Fixes: trac issue #11661 (https://trac.ffmpeg.org/ticket/11661)
Reported-by: Dave Flater
Signed-off-by: Karl Mogensen <karlmogensen0@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit fa281d1394)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:56 +01:00
Zhao Zhili 2803bcd5d5 avformat/rtmpproto: fix listen_timeout conversion for special negative values
rtmpproto converts listen_timeout to milliseconds by multiplying it
by 1000 before passing it to TCP. However, negative values are special
sentinels (e.g., -1 for infinite wait) and should not be multiplied.

This worked prior to commit 49c6e6cc44 because there was no range
validation. Since that commit, ff_parse_opts_from_query_string
validates option values against their declared ranges, causing these
multiplied negative values to fail.

Fixes ticket #22469.

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit f189657ec6)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:56 +01:00
Michael Niedermayer 2cf15d3fc0 avcodec/aom_film_grain: Remove impossible check
fgp is freshly allocated so it cannot be equal to ref

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b4b569f922)
2026-03-15 00:49:55 +01:00
Michael Niedermayer c9cf8cf9c3 avcodec/aom_film_grain: avoid duplicate indexes in ff_aom_parse_film_grain_sets()
Fixes: use after free
Fixes: 478301106/clusterfuzz-testcase-minimized-ffmpeg_dem_HEVC_fuzzer-6155792247226368

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 ebb6ac1bc7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:55 +01:00
Michael Niedermayer 21719ece26 avformat/hxvs: Do not allow backward steps in hxvs_probe()
Fixes: infinite loop
Fixes: 487632033/clusterfuzz-testcase-minimized-ffmpeg_dem_IMAGE2_fuzzer-4565877872984064

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 4ccad70d57)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:55 +01:00
Michael Niedermayer b842218402 swscale/output: fix integer overflows in chroma in yuv2rgba64_X_c_template()
Fixes: signed integer overflow: 130489 * 16525 cannot be represented in type 'int'
Fixes: 488950053/clusterfuzz-testcase-minimized-ffmpeg_SWS_fuzzer-4627272670969856

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 3b98e29da8)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:55 +01:00
Michael Niedermayer c88ae59e31 avcodec/lcldec: Fixes uqvq overflow
Fixes: integer overflow
Fixes: 490241717/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ZLIB_DEC_fuzzer-4560518961758208

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 7241b80422)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:55 +01:00
Olivier Laflamme 711b69c615 fftools/ffprobe: Initialize data_dump_format_id
This was used uninitialized previously

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 10d36e5d3d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:55 +01:00
Michael Niedermayer 511387e49a avformat/aiffdec: Check for partial read
Fixes: read of uninitialized memory
Fixes: 490305404/clusterfuzz-testcase-minimized-ffmpeg_dem_AIFF_fuzzer-6406386140643328

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 ba0f8083fd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-03-15 00:49:54 +01:00
Lynne c9a5f7c6ca hwcontext_vulkan: deprecate AVVulkanDeviceContext.lock/unlock_queue
Without replacement, as VK_KHR_internally_synchronized_queues will be required.

(cherry picked from commit c102e89448)
2026-03-14 18:54:46 +01:00
James Almer 680ac1aa32 avcodec/lcevc_parser: check return value of init_get_bits8()
Fixes coverity issue CID 1684198.

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit a9984fec81)
2026-03-13 09:06:53 -03:00
James Almer b013bbf092 avcodec/lcevc_parser: Check that block_size is not negative
Based on 248b481c33

Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 125bb2e045)
2026-03-13 09:06:53 -03:00
Michael Niedermayer d8d4a96414 avcodec/bsf/extract_extradata: Replace incorrect size accounting
Fixes: out of array writes
Fixes: 492054712/clusterfuzz-testcase-minimized-ffmpeg_BSF_EXTRACT_EXTRADATA_fuzzer-5705993148497920

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 f84c859ec5)
2026-03-12 23:17:53 -03:00
Lynne b1da475805 ffv1enc_vulkan: fix typo
Fixes a segfault when host mapping is unsupported.

(cherry picked from commit 215e22d1f1)
2026-03-10 19:32:38 +01:00
nyanmisaka b6db764c86 fftools/ffmpeg: fix read_key() always return 255 when there was no input
fixup 08d327e

When an uchar is set to -1, it will become 255 when read as an int.
Duplicate variables for two terminal types can also avoid unused variable warnings.

(cherry picked from commit 3f10a054dc)

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-03-09 17:17:17 +01:00
Michael Niedermayer 0ab823b47a avcodec/bsf/extract_extradata: Check that block_size is not negative
Fixes: out of array access
Fixes: 490576036/clusterfuzz-testcase-minimized-ffmpeg_BSF_EXTRACT_EXTRADATA_fuzzer-4605696279904256

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 248b481c33)
Signed-off-by: James Almer <jamrial@gmail.com>
2026-03-08 20:36:52 -03:00
1584 changed files with 32274 additions and 86291 deletions
-24
View File
@@ -57,7 +57,6 @@ libavcodec/.*png.* @Traneptora
libavcodec/.*prores.* @lynne
libavcodec/rangecoder.* @michaelni
libavcodec/ratecontrol.* @michaelni
libavcodec/rkmpp* @quink
libavcodec/rv60.* @pross
libavcodec/sgirle.* @pross
libavcodec/.*siren.* @lynne
@@ -110,7 +109,6 @@ 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
@@ -141,8 +139,6 @@ 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
@@ -157,7 +153,6 @@ 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
@@ -198,7 +193,6 @@ libavutil/aarch64/.* @lynne @mstorsjo
libavutil/arm/.* @mstorsjo
libavutil/ppc/.* @sean_mcg
libavutil/riscv/.* @Courmisch
libavutil/wasm/.* @quink
libavutil/x86/.* @lynne
# swresample
@@ -232,26 +226,8 @@ doc/.* @GyanD
# 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
# =======
-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()
+4 -19
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
@@ -29,15 +20,9 @@ repos:
- 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$
- id: aarch64-asm-indent
name: fix aarch64 assembly indentation
files: ^.*/aarch64/.*\.S$
language: script
entry: ./tools/check_arm_indent.sh --apply
pass_filenames: false
@@ -48,4 +33,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
-1
View File
@@ -22,7 +22,6 @@ jobs:
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
with:
-2
View File
@@ -16,8 +16,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Rebase onto target branch
uses: ./.forgejo/actions/rebase-pr
- name: Install pre-commit CI
id: install
run: |
+6 -33
View File
@@ -3,7 +3,7 @@ name: Test
on:
push:
branches:
- master
- release/8.1
pull_request:
concurrency:
@@ -29,8 +29,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Rebase onto target branch
uses: ./.forgejo/actions/rebase-pr
- name: Configure
run: |
./configure --enable-gpl --enable-nonfree --enable-memory-poisoning --assert-level=2 \
@@ -60,42 +58,26 @@ jobs:
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 }})
strategy:
fail-fast: false
matrix:
image: ['ghcr.io/btbn/ffmpeg-builds/win64-gpl:latest']
image: ['ghcr.io/btbn/ffmpeg-builds/win64-gpl-8.1:latest']
target_exec: ['wine']
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
- 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" \
@@ -105,7 +87,7 @@ jobs:
cat ffbuild/config.log
exit ${CFGRES:-0}
- name: Build
run: make -C build -j$(nproc)
run: make -j$(nproc)
- name: Restore Cached Fate-Suite
id: cache
uses: actions/cache/restore@v5
@@ -117,7 +99,7 @@ jobs:
- name: Sync Fate-Suite
id: fate
run: |
make -C build fate-rsync SAMPLES=$PWD/fate-suite
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
- name: Cache Fate-Suite
uses: actions/cache/save@v5
@@ -125,21 +107,12 @@ jobs:
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=$?
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
-6
View File
@@ -26,9 +26,6 @@
*.spv
*.spv.c
*.spv.gz
*.gen.asm
*.gen.c
*.gen.S
*.ptx
*.ptx.c
*.ptx.gz
@@ -40,9 +37,6 @@
/ffmpeg
/ffplay
/ffprobe
/checkasm_config_generated.asm
/checkasm_config_generated.h
/checkasm_header_config_generated.h
/config.asm
/config.h
/config_components.asm
-1
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**.
See [https://ffmpeg.org/developer.html#Contributing](https://ffmpeg.org/developer.html#Contributing) for more information.
+237 -24
View File
@@ -1,32 +1,245 @@
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 8.1.2:
swscale/x86/rgb_2_rgb: fix uyvytoyuv422 overwrite on odd width
swscale/aarch64: fix uyvy/yuyv to yuv420p/yuv422p on odd width
avcodec/snowenc: fix SIGFPE in get_dc() when a block lies outside the plane
avcodec/snowenc: fix out-of-bounds OBMC read in get_dc() for narrow planes
(fforge/pr/23505) avformat/tls_gnutls:fix crash when connecting to peer
libavcodec/jpeg2000htdec: remove trailing whitespace
libavdevice/alsa.c: fix NULL pointer dereference
avcodec/libjxlenc: check orientation tag metadata before reading
avformat/icecast: reject CR/LF in metadata header values
avfilter/avf_showspectrum: Fix allocation check
avformat/sctp: add size check in sctp_read() matching sctp_write()
avcodec/jpeg2000: Fix undefined behavior on ROI shift-up
aacdec_usac_mps212: reject reserved freq_res value
avcodec/aac/aacdec_usac_mps212: Off-by-one bounds check in ff_aac_ec_data_deci()
Update for 8.1.2
avcodec/snowenc: fix out-of-bounds memcpy in get_block_rd() for narrow planes
avutil/eval: apply unary sign to print, squish, gauss and lerp
avcodec/cbs_av1_syntax_template: reset seen_frame_header on sequence headers
avfilter/convolution: compute user matrix products in unsigned
avformat/mpegts: use av_fast_realloc() for prg
avfilter/avf_showcwt: fix DIRECTION_DU EOF fill clearing the wrong rows
avfilter/avf_showcwt: fix DIRECTION_RL EOF fill clearing the wrong columns
avfilter/avf_showcwt: avoid undefined float to int conversion of nb_consumed_samples
avfilter/avf_showcwt: fix out of array read in compute_kernel
avfilter/v360: compute remap table offsets in 64bit
avfilter/v360: reject out-of-range dimensions
swresample/x86/resample: write only int16 in the int16 resampler
avformat/rtpenc_amr: Check input size
swscale/ppc: fix ASAN stack-buffer-overflow in yuv2planeX
swscale/ppc: fix LOAD_FILTER overread in VSX path
avcodec/sanm: reject codec37 frames taller than the allocated buffer
avcodec/sanm: reject codec47 frames taller than the allocated buffer
avfilter: use ff_slice_pos() for per-slice boundary computation
avfilter: add ff_slice_pos() helper for slice boundaries
(origin/release/8.1, fforge/release/8.1) avformat/iamf_writer: reject muxing PCM streams
avfilter/estdif: avoid signed overflow in slice boundary calculation
swscale: support sliced input with cascaded scaling contexts
avformat/rtspdec: bound Content-Length in the ANNOUNCE handler to SDP_MAX_SIZE
avcodec/cbs_h266_syntax_template: reject subpic info with res_change_in_clvs
avcodec/misc4: Check nb channels
avcodec/rv10, rv34: check init_get_bits8() before RealVideo bit access
avformat/http: reject request-line tokens not terminated by whitespace
avformat/mov: reject out of range ispe dimensions, avoid overflow summing HEIF tile dimensions
avcodec/agm: validate actual src_y against prev plane in decode_inter_plane
avformat/dhav: Fix second integer overflow in get_duration()
fftools/ffmpeg_dec: deep-copy subtitle_header to fix use-after-free
avcodec/hevc/ps: Check window parameters
avcodec/hevc/ps: Factor window reading out
avcodec/truespeech: reject iterations count whose * 240 product overflows 32-bit
libavcodec/options_table: gamma22 and gamma28 aliases
avcodec/on2avc: reject subframe count whose * SUBFRAME_SIZE product overflows 32-bit
avfilter/zmq: initialize send_buf before shared cleanup on parse failure
avcodec/adpcm: fix signed integer overflow in get_nb_samples()
avformat/matroskadec: avoid signed overflow in DASH cue time differences
avcodec/fastaudio: reject subframes count whose * 256 product overflows 32-bit
avcodec/vc2enc_dwt: avoid signed overflow in the 9/7 DWT lifting
avcodec/vc2enc_dwt: avoid signed overflow in the 5/3 and Haar DWT
avformat/dashdec: Fail with any inner stream count being 0
avcodec/mjpegdec: require progress in AVRn interlaced field loop
avcodec/mwsc: do not dereference a missing reference frame
avcodec/misc4: reject invalid sample rate
swscale/output: avoid signed overflow in yuv2rgba64_1 alpha
swscale/output: avoid signed overflow in yuv2rgba64_full_1 alpha
tools/target_dem_fuzzer: do not exit on io_buffer allocation failure
avformat/gxfenc: Check timecode and propagate error
swscale/rgb2rgb_template: use unsigned for <<24
avformat/iamf_parse: bound substream count by remaining OBU size
avformat/matroskadec: bound TRACKENTRY parsing by max_streams
avcodec/diracdec: fix heap buffer overflow in edge_emu_buffer
avformat/rtmppkt: Check recursion depth
avcodec/tdsc: propagate max_pixels to the JPEG tile decoder
avcodec/imm5: propagate max_pixels to the H264/HEVC sub-decoders
avcodec/cri: propagate max_pixels to the JPEG tile decoder
avcodec/jpeglsdec: only apply color transform to decoded rows
avcodec/adpcm: require block_align to be a multiple of channels in ADPCM_PSXC init
avfilter/avf_showcwt: fix out-of-bounds read in du scroll
avfilter/f_ebur128: avoid signed-int wrap when sizing per-channel cache
avformat/mov: cap HEIF ICC profile copies via c*max_streams to bound CPU and memory
avcodec/aac/aacdec_usac: reject explicit usacSamplingFrequency of 0
avcodec/aac/aacdec_usac: avoid signed overflow in decode_tsd
avcodec/aac/aacdec: reject decoded frame without a valid sample rate
avformat/iff: check av_get_packet() result in ANIM branch
avcodec/cbs_h266_syntax_template: Fix pps_exp_slice_height_in_ctus_minus1 range
avfilter/vf_scale: split rational multiply
avcodec/bsf/dts2pts: fix binary tree invariant violation on selective dec_poc
avfilter/vf_drawtext: Avoid double free in glyph_enu_border_free()
avfilter/vf_drawtext: plug error-path leaks in measure_text/draw_text
avfilter/vf_drawtext: shape_text_hb() free allocated things on error
avfilter/vf_drawtext: avoid double-free of aliased FT_Glyph in glyph_enu_free
avfilter/vf_drawtext: don't double-free glyph that has been cached in tree
avfilter/vf_drawtext: always check pixel_mode == FT_PIXEL_MODE_MONO
avcodec/cook: bound subpacket channel sum against channel count
avcodec/apv_decode: avoid using apv_cbc
avformat/mxfdec: Remove unneeded check
avformat/ftp: Check string used for RNTO
avformat/ftp: Check for Telnet IAC characters and other non printable ASCII chars
avformat/ftp: reject CR/LF in the URL path to prevent FTP command injection
avcodec/jpeg2000dec: Clear header derived variables
avcodec/bsf/smpte436m_to_eia608: properly frees stuff on errors in ff_smpte436m_to_eia608_filter()
tests/checkasm/crc: retain offset values between calls
avformat/avc: Adjust get_ue_golomb() to handle 32 bit
avformat/whip: require remote DTLS fingerprint in SDP answer
avcodec/x86/vorbisdsp: change cmpleps to cmpltps in inverse coupling
avcodec/liboapvenc: derive and validate APV profile from pixel format
avformat/dashdec: bound manifest reloads and fragment-open retries
avfilter/af_join: fix wrong loop bound in buffer dedup (use-after-free)
avcodec/nvenc: fix compatibility with Video Codec SDK 13.1
avformat/mov: validate APV access unit length before passing to decoder
avcodec/h264_slice: guard color_frame() against chroma-width underflow
avcodec/magicyuv: reject slice_height misaligned with chroma vshift
avcodec/magicyuv: Expand the s->interlaced slice-height sanity check
avcodec/magicyuv: Fix 1 line MEDIAN slices
avformat/mxfdec: zero-init Sony MPEG-4 extradata and add padding
avformat/soxdec: Check sample_rate for nan
tests/tiny_ssim: fixed mistake in ssim_c1 calculation
avformat/hls: Check TIME-OFFSET value
avformat/hls: Check url_offset and size
avcodec/prores_raw: reject invalid tile alignment values
avformat/ty: check rec_size
avformat/ogg: Fix overflow and stale oggvorbis_private values
avformat/rtpenc_xiph: bail out when the max payload size underflows
avformat/rtpenc_aac: reject packets smaller than the ADTS header
avcodec/jpeg2000dec: compute mask in decode_clnpass() like in decode_sigpass()
avformat/flvdec: Check size at the top of the main loop
avformat/vividas: fix misaligned access
avformat/mccdec: dont pass NULL to bytestream2_put_buffer()
avcodec/g2meet: The stack is EPIC_PIX_STACK_SIZE
avcodec/h2645_sei: Initialize side data before deallocation
avfilter/boxblur: Fix off by one errors
avformat/assenc: Add the missing parentheses
avcodec/diracdec: Enlarge `mctmp` to cover the worst-case `blheight·ybsep + yblen` rows, and break the MC loop when no output rows remain
tools/zmqsend: free the AVBprint buffer after using it
[Wave] Fix issues with unaligned metadata chunks.
avformat/mpegts: Dont assume fc->priv_data is a MpegTSContext
fftools/graph: Add missing include "libavutil/mem.h" for fftools/graph/graphprint.c
avcodec/cbs_h266_syntax_template: tighten sh_num_tiles_in_slice_minus1 upper bound
avcodec/hevc: limit missing-ref fill to coded planes
avformat/mov: Fix negative index given to can_seek_to_key_sample()
avcodec/hdrdec: fix pixel count decrement in RLE decompress loop
(fforge/pr/23464) forgejo/workflows: update test workflow for 8.1 release
(fforge/pr/23445) aarch64: vp9lpf: Fix GCS violations
(fforge/pr/23303) avformat/mov: don't abort on unsupported or invalid chnl boxes
avformat/mov_chan: keep the layout untouched on chan/chnl box failure
(fforge/pr/23240) avformat/oggparsevorbis.c: Prevent integer overflow when summing header lengths; add bounds check.
(fforge/pr/23187) avformat/oggparsecelt: bound extra_headers to avoid an effectively infinite loop
(fforge/pr/23111) avformat/demux: use correct close function for custom io
avformat/hlsenc: use correct close function for custom io
avformat/hlsenc: respect io_open set in AVFormatContext
avformat/dashenc: respect io_open set in AVFormatContext
avformat/dashdec: respect io_open set in AVFormatContext
vulkan: fix using encode caps before querying
avformat/rtpdec_av1: fix buffer overflow due to variable confusion
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.1:
avcodec/aac/aacdec_usac_mps212: fix attach_lsb() OOB after huff_decode
avcodec/dfpwmdec: Check nb_samples
avcodec/alsdec: do not set nbits invalidly
swscale/swscale_unscaled: adjust last line copy
swscale/swscale: Check srcSliceY and srcSliceH
avformat/avidec: check LIST size in avi_load_index()
avformat/avidec: validate INFO list size before parsing
avformat/matroskadec: Check audio.sub_packet_h * audio.frame_size
libavformat/xwma: fix overflow in seek position
avformat/pcm: Use 64bit for byte_rate
avcodec/adpcm: signed integer overflow in ADPCM_N64
avcodec/hevc/ps: validate rep_format dimensions in multi-layer SPS
avfilter/vf_kerndeint: Check for minimum height
avcodec/ralf: Add the missing return statement after the error log
avfilter/vf_codecview: Clamp block to the visible frame region
avcodec/zmbv: reject XOR data that overruns the decompression buffer
avcodec/rasc: fix heap use-after-free in decode_move()
avformat/rtpdec_mpeg4: reject zero-length AU header sections
avcodec/hevc/refs: Check multiplication in alloc_frame()
fftools/ffmpeg_opt: validate stream index in negative map handling
avformat/rtmpproto: prevent integer overflow accumulating FLV buffer size
avformat/rtmpproto: validate compressed SWF header length
avformat/rtsp: Fix out-of-bounds read in SDP parser when control_url is empty
avformat/rtpdec_latm: avoid integer overflow in LATM length parsing
avcodec/h264: recompute per-slice direct mode state for every slice
avcodec/h264_refs: Clear stale pointers from ref_list
avcodec/pdvdec: Check input space before buffer allocation
avformat/concat: guard total_size overflow
avformat/iamf_parse.c: Fix potential integer overflow in opus_decoder_config()
avcodec/wmaenc: Fix missing padding in extradata
avformat: Fix various extradata padding issues
avcodec/tdsc: remove double stride adjustment
avformat/cafdec: fix negative index use in read_seek
avcodec/notchlc: Check 255 loops
avformat/rtpdec_jpeg: check qtable_len
avformat/vividas: use-of-uninitialized-value in keybuffer
avcodec/tdsc: Check jpeg size
avcodec/tdsc: Better input size check
avcodec/tdsc: Check tile_size
avcodec/decode: Better documentation for ff_set_dimensions()
avformat/mov: Limit maximum box size for mov_read_lhvc()
avformat/mov: reject dimg references with zero entries
avformat/mov: check extradata in mov_read_dops()
avformat/mov: Check read size for opus extradata
avformat/rtspdec: reject non-positive ANNOUNCE Content-Length
avformat/wavdec: Fix use-of-uninitialized-value in find_guid()
lavfi: vf_drawtext: check memory allocation
avcodec/svq1dec: Check input space for minimum
avcodec/vp9: Rollback dimensions when format is rejected
avformat/rtpdec_qdm2: Check block_size
avfilter/vf_ssim360: fix integer overflow in tape_length allocation
avcodec/escape130: Initialize old_y_avg
avutil/samplefmt: Dont claim that av_get_sample_fmt_string checks sample_fmt
swscale: fix signed integer overflow in color conversion arithmetic
avformat: check avio_read() return values in dss/dtshd/mlv
avformat/whip: check RTP history packet size before RTX retransmission
avcodec/aac/aacdec_usac: Implement missing bits of otts_bands_phase and residual_bands computation
avcodec/alsdec: preserve full float value in zero-truncated samples
avcodec/alsdec: propagate read_diff_float_data() errors in read_frame_data()
avcodec/alsdec: fix mantissa unpacking in compressed Part A path
avfilter/vf_drawtext: fix newline rendered as .notdef glyph
avcodec/pngdec: fix dead overflow check in decode_text_to_exif()
avcodec/vp9: fix cbs fragment leak on error
libavfilter/vf_v360: fix operator precedence in stereo loop condition
avcodec/alsdec: fix abs(INT_MIN) UB in read_diff_float_data()
avformat/rsd: reject short ADPCM_THP extradata reads
avformat/mov: Handle integer overflow in MOV parser
avcodec/dvdsub_parser: Fix buf_size check
avfilter/af_pan: fix sscanf() return value checks in parse_channel_name
avutil/bswap: fix implicit conversion warning in av_bswap64
avcodec/h2645_sei: don't use provider_code uninitialized
(fforge/pr/22943) avformat/hls_sample_encryption: add missing padding for audio setup buffer
(fforge/pr/22826) lavc/videotoolbox_vp9: fix vpcC flags offset
lavc/videotoolboxenc: return SEI parse errors
vulkan: fix encode feedback query handling
avcodec/cbs_lcevc: fix writing process blocks with size 6
avformat/mov: don't try to create an LCEVC group if there's a single track
(fforge/pr/22563) aarch64: Add Armv9.3-A GCS (Guarded Control Stack) support
aarch64: hevcdsp: Make returns match the call site
(fforge/pr/22545) avcodec/lcevcdec: don't try to derive final dimensions from SAR
avcodec/lcevc_parser: move the resolution type table to a header
avcodec/cbs_lcevc: don't look for process blocks if the unit was not decomposed
version 8.1:
- ffprobe -codec option
+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.
+8 -17
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
@@ -159,7 +158,7 @@ Codecs:
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
@@ -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
@@ -318,10 +317,6 @@ libavfilter
===========
Generic parts:
Framework and orphaned filters Nicolas George
(except hardware acceleration)
graphdump.c Nicolas George
motion_estimation.c Davinder Singh
@@ -353,9 +348,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 +406,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 +442,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
+4 -7
View File
@@ -106,7 +106,7 @@ 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 \
@@ -143,10 +143,8 @@ 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))
@@ -189,8 +187,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.* 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 +202,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.1.2
+15
View File
@@ -0,0 +1,15 @@
┌──────────────────────────────────────┐
│ RELEASE NOTES for FFmpeg 8.1 "Hoare" │
└──────────────────────────────────────┘
The FFmpeg Project proudly presents FFmpeg 8.1 "Hoare", about 7
months after the release of FFmpeg 8.0.
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.
-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); }
-5
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
Vendored
+111 -298
View File
File diff suppressed because it is too large Load Diff
+2 -68
View File
@@ -1,77 +1,11 @@
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
2026-03-14 - xxxxxxxxxx - lavu 60.26.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.
-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
+1 -1
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.1.2
# 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
+3 -3
View File
@@ -54,7 +54,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 +69,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)
-27
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
+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.
-2
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})
+8
View File
@@ -307,6 +307,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.
-41
View File
@@ -1181,51 +1181,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 -33
View File
@@ -225,25 +225,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,
@@ -387,7 +368,7 @@ symbols. If in doubt, just avoid names starting with @code{_} altogether.
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.
Where applicable, SI units shall be used. For example timeouts should use seconds as the fundamental unit not micro seconds.
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
@@ -488,25 +469,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
-4
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
+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 -6
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;
}
@@ -233,10 +232,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 -3
View File
@@ -430,9 +430,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);
+13 -28
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}
@@ -2388,19 +2367,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 +2415,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.
-1
View File
@@ -357,7 +357,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>
+317 -254
View File
@@ -7743,11 +7743,6 @@ The file path of the downloaded whisper.cpp model (mandatory).
The language to use for transcription ('auto' for auto-detect).
Default value: @code{"auto"}
@item translate
If enabled, translate the transcription from the source language to English. A
multilingual model is required to enable this option.
Default value: @code{"false"}
@item queue
The maximum size that will be queued into the filter before processing the audio
with whisper. Using a small value the audio stream will be processed more often,
@@ -7780,8 +7775,8 @@ Default value: @code{"text"}
@item max_len
Maximum segment length in characters. When set to a value greater than 0,
transcription segments will be split by word to not exceed this length. This is
useful for generating subtitles with shorter lines.
transcription segments will be split to not exceed this length. This is useful
for generating subtitles with shorter lines.
Default value: @code{"0"}
@item vad_model
@@ -8611,24 +8606,21 @@ Same as the @ref{subtitles} filter, except that it doesn't require libavcodec
and libavformat to work. On the other hand, it is limited to ASS (Advanced
Substation Alpha) subtitles files.
This filter accepts @option{filename}/@option{f}, @option{original_size},
@option{fontsdir}, and @option{alpha} from the @ref{subtitles} filter, plus the
following option:
This filter accepts the following option in addition to the common options from
the @ref{subtitles} filter:
@table @option
@item shaping
Set the shaping engine.
Set the shaping engine
Available values are:
@table @samp
@item auto
The default libass shaping engine, which is the best available.
@item simple
Fast, font-agnostic shaper that can do only substitutions.
Fast, font-agnostic shaper that can do only substitutions
@item complex
Slower shaper using OpenType for substitutions and positioning. Required
for correct rendering of complex scripts such as Arabic, Hebrew, Devanagari
and Thai. Requires libass to be built with HarfBuzz.
Slower shaper using OpenType for substitutions and positioning
@end table
The default is @code{auto}.
@@ -12224,42 +12216,18 @@ and configure FFmpeg with @code{--enable-libtorch
--extra-cflags=-I/libtorch_root/libtorch/include/torch/csrc/api/include
--extra-ldflags=-L/libtorch_root/libtorch/lib/}
@item onnx
ONNX Runtime backend. To enable this backend you need to install the
ONNX Runtime library (see @url{https://onnxruntime.ai/}) and configure
FFmpeg with @code{--enable-libonnxruntime}.
The current ONNX Runtime backend expects 4-D input and output tensors
with NCHW layout and 32-bit floating-point element type (ONNX
@code{FLOAT}); models with integer or other element types (e.g.
@code{UINT8}) are not supported and will be rejected at load time.
Models using NHWC layout or other ranks are not yet
supported. Only single-input models are supported; the backend binds
exactly one input tensor when running the model.
The @option{input} and @option{output} options are optional for the
ONNX Runtime backend; when they are omitted the backend resolves the
tensor names from the session.
The ONNX Runtime backend runs inference synchronously using a single
inference request. The shared @option{async} and @option{nireq} options
therefore have no effect for @code{dnn_backend=onnx}; inference always
runs synchronously regardless of their values.
@end table
@item model
Set path to model file specifying network architecture and its parameters.
Note that different backends use different file formats. TensorFlow, OpenVINO,
Libtorch, and ONNX Runtime backends can load files for only their respective formats.
Note that different backends use different file formats. TensorFlow, OpenVINO
and Libtorch backend can load files for only its format.
@item input
Set the input name of the dnn network. Required for the TensorFlow backend;
optional for the ONNX Runtime backend.
Set the input name of the dnn network.
@item output
Set the output name of the dnn network. Required for the TensorFlow backend;
optional for the ONNX Runtime backend.
Set the output name of the dnn network.
@item backend_configs
Set the configs to be passed into backend. To use async execution, set async (default: set).
@@ -12268,20 +12236,6 @@ Roll back to sync execution if the backend does not support async.
For tensorflow backend, you can set its configs with @option{sess_config} options,
please use tools/python/tf_sess_config.py to get the configs of TensorFlow backend for your system.
@item device
Set the device to run the model. For the ONNX Runtime backend this selects the
execution provider: @code{cpu} (default), @code{cuda} (NVIDIA GPU),
@code{dml} (DirectML, Windows only) or @code{vitisai} (AMD Ryzen AI NPU).
@item device_id
Set the device index used by GPU execution providers (e.g. @code{cuda} or
@code{dml}) for the ONNX Runtime backend. Default is 0.
@item threads_per_operation
ONNX Runtime backend only. Set the number of CPU threads used per ONNX
Runtime operator when running with @code{device=cpu}. Default is 0 (let
ONNX Runtime choose automatically). Has no effect for GPU/NPU providers.
@end table
@subsection Examples
@@ -14790,73 +14744,6 @@ This flag is enabled by default.
@end table
@end table
@section frc_amf
Double the frame rate, using Frame Rate Converter (FRC) provided by
AMD Advanced Media Framework library for hardware acceleration.
The filter accepts the following options:
@table @option
@item engine_type
Specify the engine used to run shaders.
@table @samp
@item dx11
DirectX 11.
@item dx12
DirectX 12 (Default value).
@end table
@item enable
Boolean value: enable/disable FRC. Dynamic value, can be altered at a runtime
without re-initializing the filter. (Default value: enabled).
@item fallback_mode
Fallback behavior in case of low interpolation confidence.
@table @samp
@item duplicate
Duplicate frame.
@item blend
Blend two frames together (Default value).
@end table
@item indicator
Boolean value: show FRC indicator square in the top left corner of the video
(Default value: disabled).
@item profile
Level of hierarchical motion search.
@table @samp
@item low
Less levels of hierarchical motion search.
Only recommended for extremely low resolutions.
@item high
Recommended for any resolution up to 1440p. (Default value)
@item super
More levels of hierarchical motion search. Recommended for resolutions 1440p
or higher.
@end table
@item mv_search_mode
Performance mode of the motion search.
@table @samp
@item native
Conduct motion search on the full resolution of source images.
@item performance
Conduct motion search on the down scaled source images.
Recommended for APU or low end GPU for better performance.
@end table
@item use_future_frame
Boolean value: enable dependency on future frame, improves quality for the cost
of latency (Default value: enabled).
@end table
@section framestep
Select one frame every N-th frame.
@@ -23392,23 +23279,6 @@ at least libass release 0.17.0 (or LIBASS_VERSION 0x01600010), @emph{and} libass
have been built with libunibreak.
The option is enabled by default except for native ASS.
@item shaping
Set the shaping engine.
Available values are:
@table @samp
@item auto
The default libass shaping engine, which is the best available.
@item simple
Fast, font-agnostic shaper that can do only substitutions.
@item complex
Slower shaper using OpenType for substitutions and positioning. Required
for correct rendering of complex scripts such as Arabic, Hebrew, Devanagari
and Thai. Requires libass to be built with HarfBuzz.
@end table
The default is @code{auto}.
@end table
If the first key is not specified, it is assumed that the first value
@@ -23777,9 +23647,9 @@ The value must be between @code{0} and @var{nb_frames - 1}. Default is @code{0}.
@item
Produce 8x8 PNG tiles of all keyframes (@option{-skip_frame nokey}) in a movie:
@example
ffmpeg -skip_frame nokey -i file.avi -vf 'scale=128:72,tile=8x8' -an -fps_mode passthrough keyframes%03d.png
ffmpeg -skip_frame nokey -i file.avi -vf 'scale=128:72,tile=8x8' -an -vsync 0 keyframes%03d.png
@end example
The @option{-fps_mode passthrough} is necessary to prevent @command{ffmpeg} from
The @option{-vsync 0} is necessary to prevent @command{ffmpeg} from
duplicating each output frame to accommodate the originally detected frame
rate.
@@ -25778,22 +25648,6 @@ Work the same as the identical @ref{scale} filter options.
@item reset_sar
Works the same as the identical @ref{scale} filter option.
@item in_color_range
Override input color range.
@item out_color_range
Specify output color range.
The accepted values for in_trc and out_trc are:
@table @samp
@item studio
Studio (or restricted, or MPEG) color range.
@item full
Full (or JPEG) color range.
@end table
@anchor{color_profile}
@item color_profile
Specify all color properties at once.
@@ -25811,13 +25665,10 @@ BT.2020
@end table
@item in_trc
Override input transfer characteristics.
@item out_trc
@item trc
Specify output transfer characteristics.
The accepted values for in_trc and out_trc are:
The accepted values are:
@table @samp
@item bt709
BT.709
@@ -25869,13 +25720,10 @@ ARIB_STD_B67
@end table
@item in_primaries
Override input color primaries.
@item out_primaries
@item primaries
Specify output color primaries.
The accepted values for in_primaries and out_primaries are:
The accepted values are:
@table @samp
@item bt709
BT.709
@@ -25927,13 +25775,6 @@ Upscale to 4K and change color profile to bt2020.
@example
vpp_amf=4096:2160:color_profile=bt2020
@end example
@item
Override input primaries and input transfer characteristics, change both to bt709.
@example
vpp_amf=color_profile=bt2020:in_trc=smpte2084:in_primaries=bt2020:out_trc=bt709:out_primaries=bt709
@end example
@end itemize
@anchor{vstack}
@@ -27115,19 +26956,7 @@ value.
@chapter CUDA Video Filters
@c man begin CUDA Video Filters
Below is a description of the currently available Nvidia CUDA video filters.
Prerequisites:
@itemize
@item Install Nvidia CUDA Toolkit
@end itemize
Note: If FFmpeg detects the Nvidia CUDA Toolkit during configuration, it will enable CUDA filters automatically without requiring any additional flags. If you want to explicitly enable them, use the following options:
@itemize
@item Configure FFmpeg with @code{--enable-cuda-nvcc --enable-nonfree}.
@item Configure FFmpeg with @code{--enable-cuda-llvm}. Additional requirement: @code{llvm} lib must be installed.
@end itemize
To enable CUDA and/or NPP filters please refer to configuration guidelines for @ref{CUDA} and for @ref{CUDA NPP} filters.
Running CUDA filters requires you to initialize a hardware device and to pass that device to all filters in any filter graph.
@table @option
@@ -27162,7 +26991,23 @@ Since CUDA filters operate exclusively on GPU memory, frame data must sometimes
@end itemize
Note that @ref{hwupload} uploads data to a surface with the same layout as the software frame, so it may be necessary to add a @ref{format} filter immediately before @ref{hwupload} to ensure the input is in the correct format. Similarly, @ref{hwdownload} may not support all output formats, so an additional @ref{format} filter may need to be inserted immediately after @ref{hwdownload} in the filter graph to ensure compatibility.
@section bilateral_cuda
@anchor{CUDA}
@section CUDA
Below is a description of the currently available Nvidia CUDA video filters.
Prerequisites:
@itemize
@item Install Nvidia CUDA Toolkit
@end itemize
Note: If FFmpeg detects the Nvidia CUDA Toolkit during configuration, it will enable CUDA filters automatically without requiring any additional flags. If you want to explicitly enable them, use the following options:
@itemize
@item Configure FFmpeg with @code{--enable-cuda-nvcc --enable-nonfree}.
@item Configure FFmpeg with @code{--enable-cuda-llvm}. Additional requirement: @code{llvm} lib must be installed.
@end itemize
@subsection bilateral_cuda
CUDA accelerated bilateral filter, an edge preserving filter.
This filter is mathematically accurate thanks to the use of GPU acceleration.
For best output quality, use one to one chroma subsampling, i.e. yuv444p format.
@@ -27182,7 +27027,7 @@ Set window size of the bilateral function to determine the number of neighbours
If the number entered is even, one will be added automatically.
Allowed range is 1 to 255. Default is 1.
@end table
@subsection Examples
@subsubsection Examples
@itemize
@item
@@ -27201,7 +27046,7 @@ Apply the bilateral filter on a video.
@end itemize
@section bwdif_cuda
@subsection bwdif_cuda
Deinterlace the input video using the @ref{bwdif} algorithm, but implemented
in CUDA so that it can work as part of a GPU accelerated pipeline with nvdec
@@ -27253,13 +27098,13 @@ Only deinterlace frames marked as interlaced.
The default value is @code{all}.
@end table
@section chromakey_cuda
@subsection chromakey_cuda
CUDA accelerated YUV colorspace color/chroma keying.
This filter works like normal chromakey filter but operates on CUDA frames.
for more details and parameters see @ref{chromakey}.
@subsection Examples
@subsubsection Examples
@itemize
@item
@@ -27295,7 +27140,7 @@ Process two software sources, explicitly uploading the frames:
@end itemize
@section colorspace_cuda
@subsection colorspace_cuda
CUDA accelerated implementation of the colorspace filter.
@@ -27328,7 +27173,7 @@ JPEG (full) range
@end table
@anchor{overlay_cuda}
@section overlay_cuda
@subsection overlay_cuda
Overlay one video on top of another.
@@ -27407,13 +27252,13 @@ This filter also supports the @ref{framesync} options.
@anchor{pad_cuda}
@section pad_cuda
@subsection pad_cuda
Add paddings to an input video stream using CUDA.
This filter is the CUDA-accelerated version of the @ref{pad} filter. It accepts the same options and expressions and provides the same core functionality.
For a detailed description of available options, please see the documentation for the @ref{pad} filter.
@subsection Examples
@subsubsection Examples
@itemize
@item
@@ -27430,7 +27275,7 @@ ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf "pad_cuda=w=ih
@end itemize
@anchor{scale_cuda}
@section scale_cuda
@subsection scale_cuda
Scale (resize) and convert (pixel format) the input video, using accelerated CUDA kernels.
Setting the output width and height works in the same way as for the @ref{scale} filter.
@@ -27499,7 +27344,7 @@ Works the same as the identical @ref{scale} filter option.
@end table
@subsection Examples
@subsubsection Examples
@itemize
@item
@@ -27523,7 +27368,7 @@ scale_cuda=passthrough=0
@end example
@end itemize
@section thumbnail_cuda
@subsection thumbnail_cuda
Select the most representative frame in a given sequence of consecutive frames using CUDA.
@@ -27539,7 +27384,7 @@ the end. Default is @code{100}.
Since the filter keeps track of the whole frames sequence, a bigger @var{n}
value will result in a higher memory usage, so a high value is not recommended.
@subsection Example
@subsubsection Example
@itemize
@@ -27551,57 +27396,7 @@ Thumbnails are extracted from every @var{n}=150-frame batch, selecting one per b
@end itemize
@section transpose_cuda
Transpose rows with columns in the input video and optionally flip it.
For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options.
It accepts the following parameters:
@table @option
@item dir
Specify the transposition direction.
Can assume the following values:
@table @samp
@item cclock_flip
Rotate by 90 degrees counterclockwise and vertically flip. (default)
@item clock
Rotate by 90 degrees clockwise.
@item cclock
Rotate by 90 degrees counterclockwise.
@item clock_flip
Rotate by 90 degrees clockwise and vertically flip.
@item reversal
Rotate by 180 degrees.
@item hflip
Flip horizontally.
@item vflip
Flip vertically.
@end table
@item passthrough
Do not apply the transposition if the input geometry matches the one
specified by the specified value. It accepts the following values:
@table @samp
@item none
Always apply transposition. (default)
@item portrait
Preserve portrait geometry (when @var{height} >= @var{width}).
@item landscape
Preserve landscape geometry (when @var{width} >= @var{height}).
@end table
@end table
@section yadif_cuda
@subsection yadif_cuda
Deinterlace the input video using the @ref{yadif} algorithm, but implemented
in CUDA so that it can work as part of a GPU accelerated pipeline with nvdec
@@ -27659,6 +27454,274 @@ Only deinterlace frames marked as interlaced.
The default value is @code{all}.
@end table
@anchor{CUDA NPP}
@section CUDA NPP
Below is a description of the currently available NVIDIA Performance Primitives (libnpp) video filters.
Prerequisites:
@itemize
@item Install Nvidia CUDA Toolkit
@item Install libnpp
@end itemize
To enable CUDA NPP filters:
@itemize
@item Configure FFmpeg with @code{--enable-nonfree --enable-libnpp}.
@end itemize
@anchor{scale_npp}
@subsection scale_npp
Use the NVIDIA Performance Primitives (libnpp) to perform scaling and/or pixel
format conversion on CUDA video frames. Setting the output width and height
works in the same way as for the @var{scale} filter.
The following additional options are accepted:
@table @option
@item format
The pixel format of the output CUDA frames. If set to the string "same" (the
default), the input format will be kept. Note that automatic format negotiation
and conversion is not yet supported for hardware frames
@item interp_algo
The interpolation algorithm used for resizing. One of the following:
@table @option
@item nn
Nearest neighbour.
@item linear
@item cubic
@item cubic2p_bspline
2-parameter cubic (B=1, C=0)
@item cubic2p_catmullrom
2-parameter cubic (B=0, C=1/2)
@item cubic2p_b05c03
2-parameter cubic (B=1/2, C=3/10)
@item super
Supersampling
@item lanczos
@end table
@item force_original_aspect_ratio
Enable decreasing or increasing output video width or height if necessary to
keep the original aspect ratio. Possible values:
@table @samp
@item disable
Scale the video as specified and disable this feature.
@item decrease
The output video dimensions will automatically be decreased if needed.
@item increase
The output video dimensions will automatically be increased if needed.
@end table
One useful instance of this option is that when you know a specific device's
maximum allowed resolution, you can use this to limit the output video to
that, while retaining the aspect ratio. For example, device A allows
1280x720 playback, and your video is 1920x800. Using this option (set it to
decrease) and specifying 1280x720 to the command line makes the output
1280x533.
Please note that this is a different thing than specifying -1 for @option{w}
or @option{h}, you still need to specify the output resolution for this option
to work.
@item force_divisible_by
Ensures that both the output dimensions, width and height, are divisible by the
given integer when used together with @option{force_original_aspect_ratio}. This
works similar to using @code{-n} in the @option{w} and @option{h} options.
This option respects the value set for @option{force_original_aspect_ratio},
increasing or decreasing the resolution accordingly. The video's aspect ratio
may be slightly modified.
This option can be handy if you need to have a video fit within or exceed
a defined resolution using @option{force_original_aspect_ratio} but also have
encoder restrictions on width or height divisibility.
@item reset_sar
Works the same as the identical @ref{scale} filter option.
@item eval
Specify when to evaluate @var{width} and @var{height} expression. It accepts the following values:
@table @samp
@item init
Only evaluate expressions once during the filter initialization or when a command is processed.
@item frame
Evaluate expressions for each incoming frame.
@end table
@end table
The values of the @option{w} and @option{h} options are expressions
containing the following constants:
@table @var
@item in_w
@item in_h
The input width and height
@item iw
@item ih
These are the same as @var{in_w} and @var{in_h}.
@item out_w
@item out_h
The output (scaled) width and height
@item ow
@item oh
These are the same as @var{out_w} and @var{out_h}
@item a
The same as @var{iw} / @var{ih}
@item sar
input sample aspect ratio
@item dar
The input display aspect ratio. Calculated from @code{(iw / ih) * sar}.
@item n
The (sequential) number of the input frame, starting from 0.
Only available with @code{eval=frame}.
@item t
The presentation timestamp of the input frame, expressed as a number of
seconds. Only available with @code{eval=frame}.
@item pos
The position (byte offset) of the frame in the input stream, or NaN if
this information is unavailable and/or meaningless (for example in case of synthetic video).
Only available with @code{eval=frame}.
Deprecated, do not use.
@end table
@subsection scale2ref_npp
Use the NVIDIA Performance Primitives (libnpp) to scale (resize) the input
video, based on a reference video.
See the @ref{scale_npp} filter for available options, scale2ref_npp supports the same
but uses the reference video instead of the main input as basis. scale2ref_npp
also supports the following additional constants for the @option{w} and
@option{h} options:
@table @var
@item main_w
@item main_h
The main input video's width and height
@item main_a
The same as @var{main_w} / @var{main_h}
@item main_sar
The main input video's sample aspect ratio
@item main_dar, mdar
The main input video's display aspect ratio. Calculated from
@code{(main_w / main_h) * main_sar}.
@item main_n
The (sequential) number of the main input frame, starting from 0.
Only available with @code{eval=frame}.
@item main_t
The presentation timestamp of the main input frame, expressed as a number of
seconds. Only available with @code{eval=frame}.
@item main_pos
The position (byte offset) of the frame in the main input stream, or NaN if
this information is unavailable and/or meaningless (for example in case of synthetic video).
Only available with @code{eval=frame}.
@end table
@subsubsection Examples
@itemize
@item
Scale a subtitle stream (b) to match the main video (a) in size before overlaying
@example
'scale2ref_npp[b][a];[a][b]overlay_cuda'
@end example
@item
Scale a logo to 1/10th the height of a video, while preserving its display aspect ratio.
@example
[logo-in][video-in]scale2ref_npp=w=oh*mdar:h=ih/10[logo-out][video-out]
@end example
@end itemize
@subsection sharpen_npp
Use the NVIDIA Performance Primitives (libnpp) to perform image sharpening with
border control.
The following additional options are accepted:
@table @option
@item border_type
Type of sampling to be used ad frame borders. One of the following:
@table @option
@item replicate
Replicate pixel values.
@end table
@end table
@subsection transpose_npp
Transpose rows with columns in the input video and optionally flip it.
For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options.
It accepts the following parameters:
@table @option
@item dir
Specify the transposition direction.
Can assume the following values:
@table @samp
@item cclock_flip
Rotate by 90 degrees counterclockwise and vertically flip. (default)
@item clock
Rotate by 90 degrees clockwise.
@item cclock
Rotate by 90 degrees counterclockwise.
@item clock_flip
Rotate by 90 degrees clockwise and vertically flip.
@end table
@item passthrough
Do not apply the transposition if the input geometry matches the one
specified by the specified value. It accepts the following values:
@table @samp
@item none
Always apply transposition. (default)
@item portrait
Preserve portrait geometry (when @var{height} >= @var{width}).
@item landscape
Preserve landscape geometry (when @var{width} >= @var{height}).
@end table
@end table
@c man end CUDA Video Filters
@chapter OpenCL Video Filters
@@ -32276,7 +32339,7 @@ select=n=2:e='mod(n, 2)+1' [odd][even]; [odd] pad=h=2*ih [tmp]; [tmp][even] over
Select useful frames from an ffconcat file which is using inpoints and
outpoints but where the source files are not intra frame only.
@example
ffmpeg -copyts -segment_time_metadata 1 -i input.ffconcat -fps_mode passthrough -vf select=concatdec_select -af aselect=concatdec_select output.avi
ffmpeg -copyts -vsync 0 -segment_time_metadata 1 -i input.ffconcat -vf select=concatdec_select -af aselect=concatdec_select output.avi
@end example
@end itemize
-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 -33
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
@@ -1328,6 +1295,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
+1 -2
View File
@@ -52,8 +52,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:
+4 -195
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,10 +3951,6 @@ 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.
+6 -1
View File
@@ -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)
+8 -76
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
@@ -453,16 +451,15 @@ 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).
Use persistent connections if set to 1, default is 0.
@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
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. Doing so allows FFmpeg
to reuse a single HTTP connection wherever possible.
@@ -1572,67 +1569,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.
@@ -1921,10 +1857,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}.
@@ -2091,8 +2023,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.
@@ -2163,8 +2095,8 @@ 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.
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.
+13 -94
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.
@@ -191,47 +151,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
+2 -3
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.
+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:
+20 -10
View File
@@ -2,6 +2,14 @@
# common bits used by all libraries
#
DEFAULT_X86ASMD=.dbg
ifeq ($(DBG),1)
X86ASMD=$(DEFAULT_X86ASMD)
else
X86ASMD=
endif
ifndef SUBDIR
LINK = $(LD) $(1)
@@ -27,7 +35,7 @@ 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.
@@ -97,6 +105,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) $@)
@@ -114,8 +126,8 @@ $(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/ $$//' > $@
RUN_GZIP = $(M)gzip -nc9 $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) >$@
RUN_MINIFY = $(M)sed 's!/\\*.*\\*/!!g' $< | tr '\n' ' ' | tr -s ' ' | sed 's/^ //; s/ $$//' > $@
%.gz: TAG = GZIP
%.min: TAG = MINIFY
@@ -185,7 +197,7 @@ 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 +217,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 +225,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))
@@ -256,14 +266,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 *.spv *.spv.gz *.spv.c *.ver *.version *.html.gz *.html.c *.css.min.gz *.css.min *.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) $(SPVOBJS:.spv.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d)
+7 -26
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,13 +51,15 @@ install-libs-$(CONFIG_SHARED): install-lib$(NAME)-shared
define RULES
$(TOOLS): THISLIB = $(FULLNAME:%=$(LD_LIB))
$(TESTPROGS) $(DEVPROGS): THISLIB = $(SUBDIR)$(LIBNAME)
$(TESTPROGS): THISLIB = $(SUBDIR)$(LIBNAME)
$(LIBOBJS): CPPFLAGS += -DBUILDING_$(NAME)
$(NAME)LINK_EXE_ARGS = $(LDFLAGS) $(LDEXEFLAGS)
$(NAME)LINK_SO_ARGS = $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS)
$(NAME)LINK_EXTRA = $(FFEXTRALIBS)
$(DEVPROGS) $(TESTPROGS) $(TOOLS): %$(EXESUF): %.o
$(TESTPROGS) $(TOOLS): %$(EXESUF): %.o
$$(call LINK,$$(call $(NAME)LINK_EXE_ARGS) $$(LD_O) $$(filter %.o,$$^) $$(THISLIB) $$(call $(NAME)LINK_EXTRA) $$(EXTRALIBS-$$(*F)) $$(ELIBS))
$(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h $(SUBDIR)version_major.h | $(SUBDIR)
@@ -86,20 +75,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))
else
$$(call LINK,$$(call $(NAME)LINK_SO_ARGS) $$(LD_O) $$(filter %.o,$$^) $$(call $(NAME)LINK_EXTRA))
endif
$(Q)$(SLIB_EXTRA_CMD)
$(SLIB_EXTRA_CMD)
-$(RM) $$@.objs
ifdef SUBDIR
@@ -113,9 +96,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 +134,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)
+1 -1
View File
@@ -1267,7 +1267,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)
-10
View File
@@ -216,16 +216,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) {
+33 -3
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 {
@@ -205,17 +218,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;
@@ -417,6 +434,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),
@@ -480,6 +500,9 @@ typedef struct InputStream {
/* framerate forced with -r */
AVRational framerate;
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
int fix_sub_duration;
@@ -581,6 +604,9 @@ typedef struct EncStats {
enum {
KF_FORCE_SOURCE = 1,
#if FFMPEG_OPT_FORCE_KF_SOURCE_NO_DROP
KF_FORCE_SOURCE_NO_DROP = 2,
#endif
// force keyframe if lavfi.scd.time metadata is set
KF_FORCE_SCD_METADATA = 3,
};
@@ -637,6 +663,10 @@ typedef struct OutputStream {
Encoder *enc;
/* video only */
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
int bitexact;
int bits_per_raw_sample;
@@ -783,7 +813,7 @@ 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, enum VideoSyncMethod *vsync_var, int file_idx, int st_idx, int is_global);
int filtergraph_is_simple(const FilterGraph *fg);
int fg_create_simple(FilterGraph **pfg,
+7
View File
@@ -387,6 +387,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)
+17 -154
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;
@@ -998,7 +995,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 +1261,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 +1314,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 +1379,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 +1496,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 +1521,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;
@@ -1804,11 +1672,6 @@ static int istg_parse_tile_grid(const OptionsContext *o, Demuxer *d, InputStream
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));
+18 -5
View File
@@ -227,9 +227,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;
@@ -283,8 +280,17 @@ int enc_open(void *opaque, const AVFrame *frame)
}
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;
@@ -796,6 +802,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) {
+37 -21
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"
@@ -51,6 +50,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;
@@ -1037,7 +1038,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);
@@ -1143,6 +1143,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);
@@ -1671,10 +1681,7 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
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;
@@ -1799,8 +1806,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,
@@ -2257,7 +2266,8 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
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))
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL) ||
frame->side_data[i]->type == AV_FRAME_DATA_DISPLAYMATRIX)
continue;
ret = av_frame_side_data_clone(&ifp->side_data,
@@ -2268,11 +2278,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
@@ -2540,7 +2547,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 +2569,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 +2589,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);
@@ -2823,10 +2836,8 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
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);
if (ret < 0)
return ret;
}
}
fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
@@ -2860,6 +2871,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 +2890,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 +2905,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 +2924,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;
@@ -3167,7 +3181,7 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
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, %s alpha,",
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));
@@ -3323,6 +3337,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;
+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;
+83 -24
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 = read_file_to_string(filters_script);
else
#endif
if (filters)
*dst = av_strdup(filters);
else
@@ -735,10 +761,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 +810,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;
@@ -999,12 +1040,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 +1401,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 +1531,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);
@@ -2063,8 +2127,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 +2552,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 +2574,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 +2648,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 +2672,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,6 +3280,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;
#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 if (!strcmp(forced_keyframes, "scd_metadata")) {
ost->kf.type = KF_FORCE_SCD_METADATA;
} else {
+109 -11
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;
@@ -356,17 +359,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, enum VideoSyncMethod *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;
}
@@ -621,7 +645,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,
@@ -1210,6 +1233,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 +1281,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 = read_file_to_string(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;
@@ -1540,6 +1596,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 +1818,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 +1838,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 +1942,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 +1989,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 +2174,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, },
};
+53 -164
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 {
@@ -440,7 +435,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 +445,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,26 +457,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];
@@ -553,7 +528,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 +539,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 +789,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,15 +1282,7 @@ 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);
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src);
// Unchoke any filter graphs that are downstream of this node, to prevent it
// from getting stuck trying to push data to a full queue
@@ -1338,10 +1294,8 @@ static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
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);
}
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];
@@ -1357,8 +1311,8 @@ static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
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);
// input from a different upstream demuxer
unchoke_for_stream(sch, fg->inputs[fg->best_input].src);
}
break;
default:
@@ -1367,30 +1321,23 @@ static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
}
}
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);
}
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;
src = sch->dec[src.idx].src;
continue;
case SCH_NODE_TYPE_ENC:
src = sch->enc[src.idx].src;
@@ -1400,8 +1347,7 @@ static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags)
// 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;
fg->waiter.choked_next = 0;
return;
}
src = fg->inputs[fg->best_input].src;
@@ -1453,23 +1399,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,18 +1420,15 @@ 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);
have_unchoked = 1;
}
}
@@ -1504,41 +1441,33 @@ static void schedule_update_locked(Scheduler *sch)
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);
unchoke_for_stream(sch, fi->src);
}
}
// 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);
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);
if (!type)
choke_demux(sch, i, w->choked_next);
}
}
}
#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)
UPDATE_WAITER(demux);
UPDATE_WAITER(filters);
UPDATE_WAITER(dec);
}
enum {
@@ -2257,7 +2186,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 +2270,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 +2280,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;
}
@@ -2516,7 +2421,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 +2510,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 +2530,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) {
@@ -2826,10 +2724,6 @@ 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;
@@ -2838,11 +2732,6 @@ int sch_stop(Scheduler *sch, int64_t *finish_ts)
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 +2768,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;
+15 -18
View File
@@ -3007,7 +3007,6 @@ static int read_thread(void *arg)
// 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));
@@ -3176,24 +3175,16 @@ static int read_thread(void *arg)
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);
}
if (show_status && 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 */
@@ -3883,6 +3874,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)) {
+3 -1
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
+54 -187
View File
@@ -39,7 +39,6 @@
#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"
@@ -216,8 +215,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,
@@ -301,7 +298,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 +307,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" },
@@ -345,11 +340,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;
@@ -436,8 +432,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,9 +451,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)
#define print_val(k, v, u) avtext_print_unit_integer(tfc, k, v, u)
static void print_integers(AVTextFormatContext *tfc, const char *key,
const void *data, int size, const char *format,
@@ -509,30 +503,6 @@ 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);
@@ -831,62 +801,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 +942,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 +1008,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 +1034,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);
@@ -1368,7 +1281,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 +1305,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 +1341,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 +1354,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 +1379,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) {
@@ -1495,11 +1400,6 @@ static void print_frame_side_data(AVTextFormatContext *tfc,
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 +1433,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) {
@@ -1796,10 +1696,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 +1715,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 +1738,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)
@@ -2075,7 +1961,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 +1978,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 +1995,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 +2009,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 +2026,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 +2053,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 +2061,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 +2068,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 +2082,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,9 +2116,7 @@ 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,
@@ -2265,7 +2131,7 @@ static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVSt
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);
@@ -2301,7 +2167,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 +2190,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 +2220,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 +2242,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 +2267,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 +2285,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 +2302,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 +2342,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");
@@ -2559,7 +2425,7 @@ static const AVCodec *get_decoder_for_stream(AVFormatContext *fmt_ctx, AVStream
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;
@@ -2600,7 +2466,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,7 +2484,7 @@ 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;
@@ -2676,9 +2542,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 +2558,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 +2578,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],
@@ -2929,9 +2796,9 @@ static inline void mark_section_show_entries(SectionID section_id,
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))) {
+1 -1
View File
@@ -141,7 +141,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); \
+9 -20
View File
@@ -68,11 +68,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 +321,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 +591,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 +708,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 +774,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)
@@ -887,7 +876,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);
+17 -38
View File
@@ -18,21 +18,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "libavutil/mem.h"
#include "libavutil/avassert.h"
#include "libavutil/avutil.h"
#include "libavutil/base64.h"
#include "libavutil/bprint.h"
#include "libavutil/common.h"
#include "libavutil/error.h"
#include "libavutil/hash.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/macros.h"
#include "libavutil/opt.h"
#include "avtextformat.h"
@@ -240,7 +238,12 @@ fail:
return ret;
}
/* Temporary definitions during refactoring */
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";
void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id)
{
@@ -364,30 +367,24 @@ struct unit_value {
int64_t i;
} val;
AVTextFormatValueFormat fmt;
const char *unit;
};
static const char float_fmt_full[] = "%f";
static const char float_fmt_singledigit[] = "%.1f";
static char *value_string(const AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
{
double vald;
int64_t vali = 0;
const char *float_fmt = 0;
int show_float = 0;
if (uv.fmt == AV_TEXTFORMAT_VALUE_FMT_DECIBEL) {
vald = 20 * log10(uv.val.d);
float_fmt = float_fmt_singledigit;
} else if (uv.fmt >= AV_TEXTFORMAT_VALUE_FMT_DOUBLE) {
if (uv.unit == unit_second_str) {
vald = uv.val.d;
float_fmt = float_fmt_full;
show_float = 1;
} else {
vald = (double)uv.val.i;
vali = uv.val.i;
}
if (uv.fmt == AV_TEXTFORMAT_VALUE_FMT_SECOND && tctx->opts.use_value_sexagesimal_format) {
if (uv.unit == unit_second_str && tctx->opts.use_value_sexagesimal_format) {
double secs;
int hours, mins;
secs = vald;
@@ -402,7 +399,7 @@ static char *value_string(const AVTextFormatContext *tctx, char *buf, int buf_si
if (tctx->opts.use_value_prefix && vald > 1) {
int64_t index;
if (uv.fmt == AV_TEXTFORMAT_VALUE_FMT_BYTE && tctx->opts.use_byte_value_binary_prefix) {
if (uv.unit == unit_byte_str && tctx->opts.use_byte_value_binary_prefix) {
index = (int64_t)(log2(vald) / 10);
index = av_clip64(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
vald /= si_prefixes[index].bin_val;
@@ -416,46 +413,29 @@ static char *value_string(const AVTextFormatContext *tctx, char *buf, int buf_si
vali = (int64_t)vald;
}
if (float_fmt || (tctx->opts.use_value_prefix && vald != (int64_t)vald))
snprintf(buf, buf_size, float_fmt ? float_fmt : "%f", vald);
if (show_float || (tctx->opts.use_value_prefix && vald != (int64_t)vald))
snprintf(buf, buf_size, "%f", vald);
else
snprintf(buf, buf_size, "%"PRId64, vali);
av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->opts.show_value_unit && uv.unit && *uv.unit ? " " : "",
prefix_string, tctx->opts.show_value_unit && uv.unit ? uv.unit : "");
av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->opts.show_value_unit ? " " : "",
prefix_string, tctx->opts.show_value_unit ? uv.unit : "");
}
return buf;
}
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, AVTextFormatValueFormat fmt, const char *unit)
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, const char *unit)
{
char val_str[128];
struct unit_value uv;
av_assert0(fmt < AV_TEXTFORMAT_VALUE_FMT_DOUBLE);
uv.val.i = val;
uv.fmt = fmt;
uv.unit = unit;
avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
}
void avtext_print_unit_double(AVTextFormatContext *tctx, const char *key, double val, AVTextFormatValueFormat fmt, const char *unit)
{
char val_str[128];
struct unit_value uv;
av_assert0(fmt >= AV_TEXTFORMAT_VALUE_FMT_DOUBLE);
uv.val.d = val;
uv.fmt = fmt;
uv.unit = unit;
avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
}
int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
{
const AVTextFormatSection *section;
@@ -515,7 +495,6 @@ void avtext_print_time(AVTextFormatContext *tctx, const char *key,
double d = av_q2d(*time_base) * ts;
struct unit_value uv;
uv.val.d = d;
uv.fmt = AV_TEXTFORMAT_VALUE_FMT_SECOND;
uv.unit = unit_second_str;
value_string(tctx, buf, sizeof(buf), uv);
avtext_print_string(tctx, key, buf, 0);
+1 -11
View File
@@ -161,14 +161,6 @@ struct AVTextFormatContext {
unsigned int string_validation_utf8_flags;
};
typedef enum {
AV_TEXTFORMAT_VALUE_FMT_INT,
AV_TEXTFORMAT_VALUE_FMT_BYTE,
AV_TEXTFORMAT_VALUE_FMT_DOUBLE = 0x100,
AV_TEXTFORMAT_VALUE_FMT_SECOND,
AV_TEXTFORMAT_VALUE_FMT_DECIBEL,
} AVTextFormatValueFormat;
#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
@@ -186,9 +178,7 @@ void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t va
int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags);
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, AVTextFormatValueFormat fmt, const char *unit);
void avtext_print_unit_double(AVTextFormatContext *tctx, const char *key, double val, AVTextFormatValueFormat fmt, const char *unit);
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, const char *unit);
void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep);
+2 -2
View File
@@ -18,13 +18,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
#include "libavutil/avutil.h"
#include "libavutil/bprint.h"
#include "libavutil/error.h"
#include "libavutil/opt.h"
+1 -2
View File
@@ -18,14 +18,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
#include "libavutil/avutil.h"
#include "libavutil/bprint.h"
#include "libavutil/opt.h"
#include "tf_internal.h"
+2 -1
View File
@@ -18,9 +18,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
+4 -3
View File
@@ -18,13 +18,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
#include "libavutil/attributes.h"
#include "libavutil/bprint.h"
#include "libavutil/opt.h"
#include "tf_internal.h"
@@ -73,7 +74,7 @@ static char *ini_escape_str(AVBPrint *dst, const char *src)
case '=':
case ':':
av_bprint_chars(dst, '\\', 1);
av_fallthrough;
/* fallthrough */
default:
if ((unsigned char)c < 32)
av_bprintf(dst, "\\x00%02x", (unsigned char)c);
+2 -1
View File
@@ -18,9 +18,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
+2 -1
View File
@@ -18,9 +18,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "avtextformat.h"
+2 -2
View File
@@ -18,8 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "avtextformat.h"
#include "libavutil/bprint.h"
+2 -2
View File
@@ -194,7 +194,7 @@ static int receive_locked(ThreadQueue *tq, int *stream_idx,
return nb_finished == tq->nb_streams ? AVERROR_EOF : AVERROR(EAGAIN);
}
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data, int flags)
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
{
int ret;
@@ -211,7 +211,7 @@ int tq_receive(ThreadQueue *tq, int *stream_idx, void *data, int flags)
if (can_read != av_container_fifo_can_read(tq->fifo))
pthread_cond_broadcast(&tq->cond);
if (ret == AVERROR(EAGAIN) && !(flags & THREAD_QUEUE_FLAG_NO_BLOCK)) {
if (ret == AVERROR(EAGAIN)) {
pthread_cond_wait(&tq->cond, &tq->lock);
continue;
}
+1 -10
View File
@@ -26,12 +26,6 @@ enum ThreadQueueType {
THREAD_QUEUE_PACKETS,
};
enum ThreadQueueFlags {
/* When set, tq_receive() will return AVERROR(EAGAIN) instead of blocking
* when the queue is empty or choked. */
THREAD_QUEUE_FLAG_NO_BLOCK = (1 << 0),
};
typedef struct ThreadQueue ThreadQueue;
/**
@@ -80,8 +74,6 @@ void tq_choke(ThreadQueue *tq, int choked);
* written here
* @param data the data item will be written here on success using the
* callback provided to tq_alloc()
* @param flags combination of THREAD_QUEUE_FLAG_*
*
* @return
* - 0 a data item was successfully read; *stream_idx contains a non-negative
* stream index
@@ -89,8 +81,7 @@ void tq_choke(ThreadQueue *tq, int choked);
* side has marked the given stream as finished. This will happen at most once
* for each stream. When *stream_idx is -1, all streams are done.
*/
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data, int flags);
int tq_receive(ThreadQueue *tq, int *stream_idx, void *data);
/**
* Mark the given stream finished from the receiving side.
*/
+15 -14
View File
@@ -115,9 +115,10 @@ OBJS-$(CONFIG_H264PARSE) += h264_parse.o h264_ps.o h264data.o \
h2645data.o h2645_parse.o h2645_vui.o
OBJS-$(CONFIG_H264PRED) += h264pred.o
OBJS-$(CONFIG_H264QPEL) += h264qpel.o
OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o
OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o aom_film_grain.o
OBJS-$(CONFIG_HEVCPARSE) += h2645data.o h2645_parse.o h2645_vui.o
OBJS-$(CONFIG_HEVC_SEI) += h2645_sei.o
OBJS-$(CONFIG_HEVC_SEI) += h2645_sei.o aom_film_grain.o \
dynamic_hdr_vivid.o
OBJS-$(CONFIG_HPELDSP) += hpeldsp.o
OBJS-$(CONFIG_HUFFMAN) += huffman.o
OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o
@@ -125,12 +126,11 @@ OBJS-$(CONFIG_HUFFYUVENCDSP) += huffyuvencdsp.o
OBJS-$(CONFIG_IDCTDSP) += idctdsp.o simple_idct.o jrevdct.o
OBJS-$(CONFIG_INFLATE_WRAPPER) += zlib_wrapper.o
OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4_vc1_data.o
OBJS-$(CONFIG_ITUT_T35) += itut35.o aom_film_grain.o dynamic_hdr_vivid.o
OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o
OBJS-$(CONFIG_JNI) += ffjni.o jni.o
OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o
OBJS-$(CONFIG_LCMS2) += fflcms2.o
OBJS-$(CONFIG_LIBLCEVC_DEC) += lcevcdec.o lcevctab.o
OBJS-$(CONFIG_LIBLCEVC_DEC) += lcevcdec.o
OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o
OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o
OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o
@@ -203,7 +203,7 @@ OBJS-$(CONFIG_AAC_FIXED_DECODER) += aactab.o \
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o \
$(if $(!CONFIG_HARDCODED_TABLES), cbrt_tablegen_common.o)
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
aacpsy.o aactab.o aacencdsp.o \
aacpsy.o aactab.o \
aacenc_is.o \
aacenc_tns.o \
psymodel.o kbdwin.o \
@@ -252,7 +252,6 @@ OBJS-$(CONFIG_APTX_HD_ENCODER) += aptxenc.o aptx.o
OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o
OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o
OBJS-$(CONFIG_APV_DECODER) += apv_decode.o apv_entropy.o apv_dsp.o
OBJS-$(CONFIG_APV_VULKAN_ENCODER) += apv_encode_vulkan.o
OBJS-$(CONFIG_ARBC_DECODER) += arbc.o
OBJS-$(CONFIG_ARGO_DECODER) += argo.o
OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o
@@ -443,6 +442,7 @@ OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o nvenc.o
OBJS-$(CONFIG_H264_OH_DECODER) += ohcodec.o ohdec.o
OBJS-$(CONFIG_H264_OH_ENCODER) += ohcodec.o ohenc.o
OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o
OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o
OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o
OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o
@@ -461,7 +461,7 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
OBJS-$(CONFIG_HEVC_DECODER) += h274.o
OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
OBJS-$(CONFIG_HEVC_AMF_DECODER) += amfdec.o
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
@@ -587,6 +587,7 @@ OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o
OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_MPEG4_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o
OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o
@@ -625,7 +626,6 @@ OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o
OBJS-$(CONFIG_PCX_DECODER) += pcx.o
OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o
OBJS-$(CONFIG_PDV_DECODER) += pdvdec.o
OBJS-$(CONFIG_PDV_ENCODER) += pdvenc.o
OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o
OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o
@@ -723,6 +723,9 @@ OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o
h263data.o ituh263enc.o \
motion_est.o ratecontrol.o
OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o
OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o
OBJS-$(CONFIG_SPEEDHQ_DECODER) += speedhqdec.o speedhq.o mpeg12.o \
mpeg12data.o
OBJS-$(CONFIG_SPEEDHQ_ENCODER) += speedhq.o mpeg12data.o mpeg12enc.o speedhqenc.o
@@ -833,7 +836,7 @@ OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
OBJS-$(CONFIG_VQC_DECODER) += vqcdec.o
OBJS-$(CONFIG_VVC_DECODER) += executor.o h2645data.o
OBJS-$(CONFIG_VVC_SEI) += h2645_sei.o h274.o
OBJS-$(CONFIG_VVC_SEI) += h2645_sei.o aom_film_grain.o h274.o
OBJS-$(CONFIG_WADY_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_WAVARC_DECODER) += wavarc.o
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o
@@ -842,7 +845,6 @@ OBJS-$(CONFIG_WBMP_DECODER) += wbmpdec.o
OBJS-$(CONFIG_WBMP_ENCODER) += wbmpenc.o
OBJS-$(CONFIG_WCMV_DECODER) += wcmv.o
OBJS-$(CONFIG_WEBP_DECODER) += webp.o
OBJS-$(CONFIG_WEBP_ANIM_DECODER) += webp.o
OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o ass.o
OBJS-$(CONFIG_WEBVTT_ENCODER) += webvttenc.o ass_split.o
OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o
@@ -1044,7 +1046,6 @@ OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o
OBJS-$(CONFIG_VDPAU) += vdpau.o
OBJS-$(CONFIG_VULKAN) += vulkan.o vulkan_video.o
OBJS-$(CONFIG_APV_VULKAN_HWACCEL) += vulkan_decode.o vulkan_apv.o
OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o
OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o
OBJS-$(CONFIG_AV1_D3D12VA_HWACCEL) += dxva2_av1.o d3d12va_av1.o
@@ -1126,7 +1127,7 @@ OBJS-$(CONFIG_FITS_DEMUXER) += fits.o
OBJS-$(CONFIG_TAK_DEMUXER) += tak.o
# libavformat dependencies for static builds
STLIBOBJS-$(CONFIG_AVFORMAT) += h2645_parse.o lcevctab.o to_upper4.o
STLIBOBJS-$(CONFIG_AVFORMAT) += to_upper4.o
STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o
STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o
STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o
@@ -1170,6 +1171,7 @@ OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
OBJS-$(CONFIG_LIBCODEC2_DECODER) += libcodec2.o
OBJS-$(CONFIG_LIBCODEC2_ENCODER) += libcodec2.o
OBJS-$(CONFIG_LIBDAV1D_DECODER) += libdav1d.o av1_parse.o
@@ -1328,7 +1330,6 @@ SKIPHEADERS += %_tablegen.h \
%_tables.h \
tableprint.h \
tableprint_vlc.h \
aaccoder_nmr.h \
aaccoder_twoloop.h \
aaccoder_trellis.h \
aacenc_quantization.h \
@@ -1366,7 +1367,6 @@ TESTPROGS = avcodec \
bitstream_be \
bitstream_le \
codec_desc \
encinfo \
htmlsubtitles \
jpeg2000dwt \
mathops \
@@ -1379,6 +1379,7 @@ TESTPROGS-$(CONFIG_GOLOMB) += golomb
TESTPROGS-$(CONFIG_IDCTDSP) += dct
TESTPROGS-$(CONFIG_DXV_ENCODER) += hashtable
TESTPROGS-$(CONFIG_MJPEG_ENCODER) += mjpegenc_huffman
TESTPROGS-$(HAVE_MMX) += motion
TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate
TESTPROGS-$(CONFIG_H264_METADATA_BSF) += h264_levels
TESTPROGS-$(CONFIG_HEVC_METADATA_BSF) += h265_levels
+17 -104
View File
@@ -676,7 +676,6 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id)
ac->tags_mapped++;
return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
}
av_fallthrough;
case 13:
if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) ||
(type == TYPE_SCE && elem_id < 6) ||
@@ -684,20 +683,17 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id)
ac->tags_mapped++;
return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
}
av_fallthrough;
case 12:
case 7:
if (ac->tags_mapped == 3 && type == TYPE_CPE) {
ac->tags_mapped++;
return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
}
av_fallthrough;
case 11:
if (ac->tags_mapped == 3 && type == TYPE_SCE) {
ac->tags_mapped++;
return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
}
av_fallthrough;
case 6:
/* Some streams incorrectly code 5.1 audio as
* SCE[0] CPE[0] CPE[1] SCE[1]
@@ -715,13 +711,11 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id)
ac->tags_mapped++;
return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
}
av_fallthrough;
case 5:
if (ac->tags_mapped == 2 && type == TYPE_CPE) {
ac->tags_mapped++;
return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
}
av_fallthrough;
case 4:
/* Some streams incorrectly code 4.0 audio as
* SCE[0] CPE[0] LFE[0]
@@ -745,7 +739,6 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id)
ac->tags_mapped++;
return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
}
av_fallthrough;
case 3:
case 2:
if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) &&
@@ -757,13 +750,11 @@ ChannelElement *ff_aac_get_che(AACDecContext *ac, int type, int elem_id)
ac->tags_mapped++;
return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
}
av_fallthrough;
case 1:
if (!ac->tags_mapped && type == TYPE_SCE) {
ac->tags_mapped++;
return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
}
av_fallthrough;
default:
return NULL;
}
@@ -831,8 +822,8 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
sampling_index = get_bits(gb, 4);
if (m4ac->sampling_index != sampling_index)
av_log(avctx, AV_LOG_WARNING,
"Sample rate index (%d) in program config element does not "
"match the sample rate index (%d) configured by the container.\n", sampling_index, m4ac->sampling_index);
"Sample rate index in program config element does not "
"match the sample rate index configured by the container.\n");
num_front = get_bits(gb, 4);
num_side = get_bits(gb, 4);
@@ -875,91 +866,6 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
return AVERROR_INVALIDDATA;
}
// Height extension
int height_ext = 0;
if (comment_len >= 16 + (num_front * 2 + num_side * 2 + num_back * 2))
height_ext = show_bits(gb, 8) == 0xAC;
if (height_ext) {
uint8_t height_map[4 /* ChannelPosition */][16 /* Channel */]; // 0 == base, 1 == top, 2 == bottom.
uint8_t tag[6 /* ChannelPosition */ ][16 /* Channel */][3];
int i, invalid = 0, height_tags = 0;
skip_bits(gb, 8);
// Read height extension bits to height_map, which define which layer each element belongs to.
// Also make a copy of layout_map that will then be used to rearrange it.
for (i = 0; i < num_front; i++) {
int height = get_bits(gb, 2);
invalid |= height > 2;
height_map [AAC_CHANNEL_FRONT][i] = height;
memcpy(&tag[AAC_CHANNEL_FRONT][i], layout_map + height_tags, sizeof(*layout_map));
height_tags++;
}
for (i = 0; i < num_side; i++) {
int height = get_bits(gb, 2);
invalid |= height > 2;
height_map [AAC_CHANNEL_SIDE][i] = height;
memcpy(&tag[AAC_CHANNEL_SIDE][i], layout_map + height_tags, sizeof(*layout_map));
height_tags++;
}
for (i = 0; i < num_back; i++) {
int height = get_bits(gb, 2);
invalid |= height > 2;
height_map [AAC_CHANNEL_BACK][i] = height;
memcpy(&tag[AAC_CHANNEL_BACK][i], layout_map + height_tags, sizeof(*layout_map));
height_tags++;
}
for (i = 0; i < num_lfe; i++) {
memcpy(&tag[AAC_CHANNEL_LFE][i], layout_map + height_tags, sizeof(*layout_map));
height_tags++;
}
for (i = 0; i < num_cc; i++) {
memcpy(&tag[AAC_CHANNEL_CC][i], layout_map + height_tags, sizeof(*layout_map));
height_tags++;
}
av_assert0(height_tags == tags);
if (!invalid) {
height_tags = 0;
// For each height layer, check that an element belongs to it and copy it back to layout_map.
// We need to take into account LFE and CC elements that may be present.
for (i = 0; i < 3; i++) {
for (int j = 0; j < num_front; j++) {
if (height_map[AAC_CHANNEL_FRONT][j] == i) {
memcpy(layout_map + height_tags, &tag[AAC_CHANNEL_FRONT][j], sizeof(*layout_map));
height_tags++;
}
}
for (int j = 0; j < num_side; j++) {
if (height_map[AAC_CHANNEL_SIDE][j] == i) {
memcpy(layout_map + height_tags, &tag[AAC_CHANNEL_SIDE][j], sizeof(*layout_map));
height_tags++;
}
}
for (int j = 0; j < num_back; j++) {
if (height_map[AAC_CHANNEL_BACK][j] == i) {
memcpy(layout_map + height_tags, &tag[AAC_CHANNEL_BACK][j], sizeof(*layout_map));
height_tags++;
}
}
if (i == 0) { // Base height, copy LFE and CC elements before moving to Top and Bottom
for (int j = 0; j < num_lfe; j++) {
memcpy(layout_map + height_tags, &tag[AAC_CHANNEL_LFE][j], sizeof(*layout_map));
height_tags++;
}
for (int j = 0; j < num_cc; j++) {
memcpy(layout_map + height_tags, &tag[AAC_CHANNEL_CC][j], sizeof(*layout_map));
height_tags++;
}
}
}
av_assert0(height_tags == tags);
}
comment_len -= 8 + (num_front * 2 + num_side * 2 + num_back * 2);
}
skip_bits_long(gb, comment_len);
return tags;
}
@@ -983,6 +889,12 @@ static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
int tags = 0;
m4ac->frame_length_short = get_bits1(gb);
if (m4ac->frame_length_short && m4ac->sbr == 1) {
avpriv_report_missing_feature(avctx, "SBR with 960 frame length");
if (ac) ac->warned_960_sbr = 1;
m4ac->sbr = 0;
m4ac->ps = 0;
}
if (get_bits1(gb)) // dependsOnCoreCoder
skip_bits(gb, 14); // coreCoderDelay
@@ -1334,7 +1246,7 @@ av_cold int ff_aac_decode_init(AVCodecContext *avctx)
ac->oc[1].m4ac.chan_config = i;
if (ac->oc[1].m4ac.chan_config) {
ret = ff_aac_set_default_channel_config(ac, avctx, layout_map,
int ret = ff_aac_set_default_channel_config(ac, avctx, layout_map,
&layout_map_tags,
ac->oc[1].m4ac.chan_config);
if (!ret)
@@ -2034,11 +1946,17 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
switch (type) { // extension type
case EXT_SBR_DATA_CRC:
crc_flag++;
av_fallthrough;
case EXT_SBR_DATA:
if (!che) {
av_log(ac->avctx, AV_LOG_ERROR, "SBR was found before the first channel element.\n");
return res;
} else if (ac->oc[1].m4ac.frame_length_short) {
if (!ac->warned_960_sbr)
avpriv_report_missing_feature(ac->avctx,
"SBR with 960 frame length");
ac->warned_960_sbr = 1;
skip_bits_long(gb, 8 * cnt - 4);
return res;
} else if (!ac->oc[1].m4ac.sbr) {
av_log(ac->avctx, AV_LOG_ERROR, "SBR signaled to be not-present but was found in the bitstream.\n");
skip_bits_long(gb, 8 * cnt - 4);
@@ -2059,8 +1977,7 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
ac->avctx->profile = AV_PROFILE_AAC_HE;
}
ac->proc.sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type,
ac->oc[1].m4ac.frame_length_short);
ac->proc.sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
if (ac->oc[1].m4ac.ps == 1 && !ac->warned_he_aac_mono) {
av_log(ac->avctx, AV_LOG_VERBOSE, "Treating HE-AAC mono as stereo.\n");
@@ -2170,7 +2087,6 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
if (ac->oc[1].m4ac.sbr > 0) {
ac->proc.sbr_apply(ac, che, type,
ac->oc[1].m4ac.frame_length_short,
che->ch[0].output,
che->ch[1].output);
}
@@ -2648,9 +2564,6 @@ static const AVOption options[] = {
{ "coded", "order in which the channels are coded in the bitstream",
0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
{ "target_level", "Target output loudness in dBFS for xHE-AAC normalization (0 = disabled)",
OFF(target_level), AV_OPT_TYPE_INT, { .i64 = 0 }, -70, 0, AACDEC_FLAGS },
{NULL},
};
+4 -31
View File
@@ -98,12 +98,6 @@ enum AACUSACLoudnessExt {
UNIDRCLOUDEXT_EQ = 0x1,
};
enum AACUSACDRCExt {
UNIDRCCONFEXT_TERM = 0x0,
UNIDRCCONFEXT_PARAM_DRC = 0x1,
UNIDRCCONFEXT_V1 = 0x2,
};
// Supposed to be equal to AAC_RENAME() in case of USE_FIXED.
#define RENAME_FIXED(name) name ## _fixed
@@ -308,7 +302,6 @@ typedef struct ChannelElement {
typedef struct AACUSACLoudnessInfo {
uint8_t drc_set_id : 6;
uint8_t eq_set_id : 6; /* loudnessInfoV1() only, 0 otherwise */
uint8_t downmix_id : 7;
struct {
uint16_t lvl : 12;
@@ -384,13 +377,6 @@ typedef struct AACUsacElemConfig {
uint32_t pl_data_offset;
uint8_t *pl_buf;
} ext;
struct {
struct {
int lower;
int upper;
} loudness;
} drc;
} AACUsacElemConfig;
typedef struct AACUSACConfig {
@@ -406,13 +392,6 @@ typedef struct AACUSACConfig {
AACUSACLoudnessInfo album_info[64];
uint8_t nb_info;
AACUSACLoudnessInfo info[64];
/**
* Raw bsMethodValue (μ) of the program/anchor-loudness measurement
* selected for normalization at config time. -1 == none found.
* L_LKFS = -57.75 + 0.25 * input_method_val.
*/
int input_method_val;
} loudness;
} AACUSACConfig;
@@ -454,9 +433,9 @@ typedef struct AACDecProc {
int (*sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int id_aac);
int (*sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
GetBitContext *gb, int crc, int cnt, int id_aac, int fl960);
void (*sbr_apply)(AACDecContext *ac, ChannelElement *che, int id_aac, int fl960,
void /* INTFLOAT */ *L, void /* INTFLOAT */ *R);
GetBitContext *gb, int crc, int cnt, int id_aac);
void (*sbr_apply)(AACDecContext *ac, ChannelElement *che,
int id_aac, void /* INTFLOAT */ *L, void /* INTFLOAT */ *R);
void (*sbr_ctx_close)(ChannelElement *che);
} AACDecProc;
@@ -576,15 +555,9 @@ struct AACDecContext {
enum AACOutputChannelOrder output_channel_order;
/**
* Target output loudness in dBFS, used for xHE-AAC loudness normalization
* based on the parsed loudnessInfoSet() metadata. 0 disables normalization.
*/
int target_level;
int warned_loudness_missing;
OutputConfiguration oc[2];
int warned_num_aac_frames;
int warned_960_sbr;
unsigned warned_71_wide;
int warned_gain_control;
int warned_he_aac_mono;
+1 -1
View File
@@ -75,7 +75,7 @@ const uint8_t ff_aac_channel_layout_map[16][16][3] = {
const int16_t ff_aac_channel_map[3][4][6] = {
{
{ AV_CHAN_FRONT_CENTER, AV_CHAN_FRONT_LEFT_OF_CENTER, AV_CHAN_FRONT_RIGHT_OF_CENTER, AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
{ AV_CHAN_UNUSED, AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, AV_CHAN_BACK_CENTER },
{ AV_CHAN_LOW_FREQUENCY, AV_CHAN_LOW_FREQUENCY_2, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE, AV_CHAN_NONE },
},
+20 -251
View File
@@ -49,7 +49,7 @@ static inline uint32_t get_escaped_value(GetBitContext *gb, int nb1, int nb2, in
return val;
}
/* ISO/IEC 23003-3, Table 74: bsOutputChannelPos */
/* ISO/IEC 23003-3, Table 74 bsOutputChannelPos */
static const enum AVChannel usac_ch_pos_to_av[64] = {
[0] = AV_CHAN_FRONT_LEFT,
[1] = AV_CHAN_FRONT_RIGHT,
@@ -85,23 +85,10 @@ static const enum AVChannel usac_ch_pos_to_av[64] = {
[31] = AV_CHAN_TOP_SURROUND_RIGHT, ///< -110 degrees, Rvs, TpRS
};
/* ISO/IEC 23003-4, Table A.48: bit width of bsMethodValue depends on methodDef. */
static int methodvalue_width(int method_def)
{
switch (method_def) {
case 7: return 5; /* mixing level */
case 8: return 2; /* room type */
default: return 8; /* loudness (0..6, 9) + reserved */
}
}
/* ISO/IEC 23003-4, Table 58/60: loudnessInfo(), loudnessInfoV1().
* The only difference in V1 is the added eqSetId field. */
static int decode_loudness_info(AACDecContext *ac, AACUSACLoudnessInfo *info,
GetBitContext *gb, int v1)
GetBitContext *gb)
{
info->drc_set_id = get_bits(gb, 6);
info->eq_set_id = v1 ? get_bits(gb, 6) : 0;
info->downmix_id = get_bits(gb, 7);
if ((info->sample_peak.present = get_bits1(gb))) /* samplePeakLevelPresent */
@@ -116,8 +103,7 @@ static int decode_loudness_info(AACDecContext *ac, AACUSACLoudnessInfo *info,
info->nb_measurements = get_bits(gb, 4);
for (int i = 0; i < info->nb_measurements; i++) {
info->measurements[i].method_def = get_bits(gb, 4);
info->measurements[i].method_val =
get_bits(gb, methodvalue_width(info->measurements[i].method_def));
info->measurements[i].method_val = get_unary(gb, 0, 8);
info->measurements[i].measurement = get_bits(gb, 4);
info->measurements[i].reliability = get_bits(gb, 2);
}
@@ -125,56 +111,6 @@ static int decode_loudness_info(AACDecContext *ac, AACUSACLoudnessInfo *info,
return 0;
}
/* ISO/IEC 23003-4, Table 61: loudnessInfoSetExtension(), UNIDRCLOUDEXT_EQ */
static int decode_loudness_set_v1(AACDecContext *ac, AACUSACConfig *usac,
GetBitContext *gb)
{
int ret;
int nb_album = get_bits(gb, 6); /* loudnessInfoV1AlbumCount */
int nb_info = get_bits(gb, 6); /* loudnessInfoV1Count */
for (int i = 0; i < nb_album; i++) {
AACUSACLoudnessInfo tmp;
ret = decode_loudness_info(ac, &tmp, gb, 1);
if (ret < 0)
return ret;
if (usac->loudness.nb_album < FF_ARRAY_ELEMS(usac->loudness.album_info))
usac->loudness.album_info[usac->loudness.nb_album++] = tmp;
}
for (int i = 0; i < nb_info; i++) {
AACUSACLoudnessInfo tmp;
ret = decode_loudness_info(ac, &tmp, gb, 1);
if (ret < 0)
return ret;
if (usac->loudness.nb_info < FF_ARRAY_ELEMS(usac->loudness.info))
usac->loudness.info[usac->loudness.nb_info++] = tmp;
}
return 0;
}
/* Pick the bsMethodValue of a program- or anchor-loudness measurement.
* Per ISO/IEC 23003-4 6.1.2.5, downmixId, drcSetId and eqSetId identify the
* signal a loudnessInfo() applies to; only downmixId == 0 (base layout)
* together with drcSetId == 0 and eqSetId == 0 (no DRC/EQ) describes the
* unprocessed signal we output, so measurements for any other
* downmix/DRC/EQ set must not be used. */
static int select_loudness_measurement(const AACUSACConfig *usac)
{
for (int i = 0; i < usac->loudness.nb_info; i++) {
const AACUSACLoudnessInfo *info = &usac->loudness.info[i];
if (info->downmix_id != 0 || info->drc_set_id != 0 || info->eq_set_id != 0)
continue;
for (int j = 0; j < info->nb_measurements; j++) {
int method = info->measurements[j].method_def;
if (method == 1 || method == 2)
return info->measurements[j].method_val;
}
}
return -1;
}
static int decode_loudness_set(AACDecContext *ac, AACUSACConfig *usac,
GetBitContext *gb)
{
@@ -184,13 +120,13 @@ static int decode_loudness_set(AACDecContext *ac, AACUSACConfig *usac,
usac->loudness.nb_info = get_bits(gb, 6); /* loudnessInfoCount */
for (int i = 0; i < usac->loudness.nb_album; i++) {
ret = decode_loudness_info(ac, &usac->loudness.album_info[i], gb, 0);
ret = decode_loudness_info(ac, &usac->loudness.album_info[i], gb);
if (ret < 0)
return ret;
}
for (int i = 0; i < usac->loudness.nb_info; i++) {
ret = decode_loudness_info(ac, &usac->loudness.info[i], gb, 0);
ret = decode_loudness_info(ac, &usac->loudness.info[i], gb);
if (ret < 0)
return ret;
}
@@ -198,25 +134,16 @@ static int decode_loudness_set(AACDecContext *ac, AACUSACConfig *usac,
if (get_bits1(gb)) { /* loudnessInfoSetExtPresent */
enum AACUSACLoudnessExt type;
while ((type = get_bits(gb, 4)) != UNIDRCLOUDEXT_TERM) {
uint8_t size_bits = get_bits(gb, 4) + 4; /* bitSizeLen */
uint32_t bit_size = get_bits_long(gb, size_bits) + 1; /* bitSize */
int start = get_bits_count(gb);
int skip;
uint8_t size_bits = get_bits(gb, 4) + 4;
uint8_t bit_size = get_bits(gb, size_bits) + 1;
switch (type) {
case UNIDRCLOUDEXT_EQ:
ret = decode_loudness_set_v1(ac, usac, gb);
if (ret < 0)
return ret;
break;
avpriv_report_missing_feature(ac->avctx, "loudnessInfoV1");
return AVERROR_PATCHWELCOME;
default:
break;
for (int i = 0; i < bit_size; i++)
skip_bits1(gb);
}
/* The extension size is explicit, so unparsed (or unknown)
* data can be skipped without desynchronizing. */
skip = bit_size - (get_bits_count(gb) - start);
if (skip < 0)
return AVERROR_INVALIDDATA;
skip_bits_long(gb, skip);
}
}
@@ -300,7 +227,7 @@ static int decode_usac_element_pair(AACDecContext *ac,
e->mps.phase_coding = get_bits1(gb); /* bsPhaseCoding */
e->mps.otts_bands_phase_present = get_bits1(gb);
int otts_bands_phase = ((int[]){0,10,10,7,5,3,2,2})[e->mps.freq_res]; // Table 109: Default value of bsOttBandsPhase
int otts_bands_phase = ((int[]){0,10,10,7,5,3,2,2})[e->mps.freq_res]; // Table 109 Default value of bsOttBandsPhase
if (e->mps.otts_bands_phase_present) { /* bsOttBandsPhasePresent */
otts_bands_phase = get_bits(gb, 5); /* bsOttBandsPhase */
if (otts_bands_phase > numBands)
@@ -326,114 +253,6 @@ static int decode_usac_element_pair(AACDecContext *ac,
return 0;
}
/* ISO/IEC 23003-4, Table 62: channelLayout() */
static int decode_drc_channel_layout(GetBitContext *gb)
{
int base_channel_count = get_bits(gb, 7); /* baseChannelCount */
if (get_bits1(gb)) { /* layoutSignallingPresent */
if (get_bits(gb, 8) == 0) /* definedLayout == 0 */
for (int i = 0; i < base_channel_count; i++)
skip_bits(gb, 7); /* speakerPosition */
}
return base_channel_count;
}
/* ISO/IEC 23003-4, Table 63: downmixInstructions() */
static void skip_drc_downmix_instructions(GetBitContext *gb, int base_channel_count)
{
int target_channel_count;
skip_bits(gb, 7); /* downmixId */
target_channel_count = get_bits(gb, 7); /* targetChannelCount */
skip_bits(gb, 8); /* targetLayout */
if (get_bits1(gb)) /* downmixCoefficientsPresent */
skip_bits_long(gb, 4 * target_channel_count * base_channel_count);
}
/* ISO/IEC 23003-4, Table 70: drcInstructionsBasic(), common with the
* uniDrc variant up to the loudness-target fields. */
static void decode_drc_instructions_basic(AACUsacElemConfig *e, GetBitContext *gb)
{
int set_effects;
skip_bits(gb, 6); /* drcSetId */
skip_bits(gb, 4); /* drcLocation */
skip_bits(gb, 7); /* downmixId */
if (get_bits1(gb)) { /* additionalDownmixIdPresent */
int add_downmix_cnt = get_bits(gb, 3); /* additionalDownmixIdCount */
for (int j = 0; j < add_downmix_cnt; j++)
skip_bits(gb, 7); /* additionalDownmixId */
}
set_effects = get_bits(gb, 16); /* drcSetEffect */
if ((set_effects & (3 << 10)) == 0) {
if (get_bits1(gb)) /* limiterPeakTargetPresent */
skip_bits(gb, 8); /* bsLimiterPeakTarget */
}
if (get_bits1(gb)) { /* drcSetTargetLoudnessPresent */
e->drc.loudness.upper = get_bits(gb, 6); /* bsDrcSetTargetLoudnessValueUpper */
if (get_bits1(gb)) /* drcSetTargetLoudnessValueLowerPresent */
e->drc.loudness.lower = get_bits(gb, 6); /* bsDrcSetTargetLoudnessValueLower */
}
}
/* ISO/IEC 23003-4, Table 57: uniDrcConfig() */
static int decode_drc_config(AACDecContext *ac, AACUsacElemConfig *e,
GetBitContext *gb)
{
int nb_downmix_instr, nb_coeff_basic = 0, nb_instr_basic = 0;
int nb_coeff_uni, nb_instr_uni;
int base_channel_count;
e->drc.loudness.lower = -1;
e->drc.loudness.upper = -1;
if (get_bits1(gb)) /* sampleRatePresent */
skip_bits(gb, 18); /* bsSampleRate */
nb_downmix_instr = get_bits(gb, 7); /* downmixInstructionsCount */
if (get_bits1(gb)) { /* drcDescriptionBasicPresent */
nb_coeff_basic = get_bits(gb, 3); /* drcCoefficientsBasicCount */
nb_instr_basic = get_bits(gb, 4); /* drcInstructionsBasicCount */
}
nb_coeff_uni = get_bits(gb, 3); /* drcCoefficientsUniDrcCount */
nb_instr_uni = get_bits(gb, 6); /* drcInstructionsUniDrcCount */
if (nb_coeff_uni || nb_instr_uni) {
avpriv_report_missing_feature(ac->avctx,
"AAC USAC uniDrc DRC processing");
return AVERROR_PATCHWELCOME;
}
base_channel_count = decode_drc_channel_layout(gb);
for (int i = 0; i < nb_downmix_instr; i++)
skip_drc_downmix_instructions(gb, base_channel_count);
for (int i = 0; i < nb_coeff_basic; i++)
skip_bits(gb, 4 + 7); /* drcLocation, drcCharacteristic */
for (int i = 0; i < nb_instr_basic; i++)
decode_drc_instructions_basic(e, gb);
if (get_bits1(gb)) { /* uniDrcConfigExtPresent */
enum AACUSACDRCExt type;
while ((type = get_bits(gb, 4)) != UNIDRCCONFEXT_TERM) {
uint8_t size_bits = get_bits(gb, 4) + 4; /* bitSizeLen */
uint32_t bit_size = get_bits_long(gb, size_bits) + 1; /* extBitSize */
switch (type) {
default:
skip_bits_long(gb, bit_size);
break;
}
}
}
return 0;
}
static int decode_usac_extension(AACDecContext *ac, AACUsacElemConfig *e,
GetBitContext *gb)
{
@@ -457,25 +276,9 @@ static int decode_usac_extension(AACDecContext *ac, AACUsacElemConfig *e,
break;
case ID_EXT_ELE_SAOC:
break;
#endif
case ID_EXT_ELE_UNI_DRC: {
int start = get_bits_count(gb);
int ret = decode_drc_config(ac, e, gb);
int skip = 8*ext_config_len - (get_bits_count(gb) - start);
if (ret == AVERROR_PATCHWELCOME) {
/* Unsupported uniDrcConfig(): ignore the DRC metadata and treat
* the element as fill so the stream stays decodable. */
e->ext.type = ID_EXT_ELE_FILL;
ret = 0;
}
if (ret < 0)
return ret;
if (skip < 0)
return AVERROR_INVALIDDATA;
/* The config is byte-padded to usacExtElementConfigLength */
skip_bits_long(gb, skip);
case ID_EXT_ELE_UNI_DRC:
break;
}
#endif
case ID_EXT_ELE_FILL:
break; /* This is what the spec does */
case ID_EXT_ELE_AUDIOPREROLL:
@@ -570,7 +373,6 @@ int ff_aac_usac_config_decode(AACDecContext *ac, AVCodecContext *avctx,
return AVERROR_PATCHWELCOME;
memset(usac, 0, sizeof(*usac));
usac->loudness.input_method_val = -1;
freq_idx = get_bits(gb, 5); /* usacSamplingFrequencyIndex */
if (freq_idx == 0x1f) {
@@ -770,13 +572,6 @@ int ff_aac_usac_config_decode(AACDecContext *ac, AVCodecContext *avctx,
ac->avctx->profile = AV_PROFILE_AAC_USAC;
usac->loudness.input_method_val = select_loudness_measurement(usac);
if (usac->loudness.input_method_val >= 0)
av_log(avctx, AV_LOG_VERBOSE,
"USAC input loudness: %.2f LKFS (bsMethodValue=%d)\n",
-57.75f + 0.25f * usac->loudness.input_method_val,
usac->loudness.input_method_val);
ret = ff_aac_usac_reset_state(ac, oc);
if (ret < 0)
return ret;
@@ -1549,13 +1344,13 @@ static void spectrum_decode(AACDecContext *ac, AACUSACConfig *usac,
/* Save coefficients and alpha values for prediction reasons */
if (nb_channels > 1) {
AACUsacStereo *us2 = &cpe->us;
AACUsacStereo *us = &cpe->us;
for (int ch = 0; ch < nb_channels; ch++) {
SingleChannelElement *sce = &cpe->ch[ch];
memcpy(sce->prev_coeffs, sce->coeffs, sizeof(sce->coeffs));
}
memcpy(us2->prev_alpha_q_re, us2->alpha_q_re, sizeof(us2->alpha_q_re));
memcpy(us2->prev_alpha_q_im, us2->alpha_q_im, sizeof(us2->alpha_q_im));
memcpy(us->prev_alpha_q_re, us->alpha_q_re, sizeof(us->alpha_q_re));
memcpy(us->prev_alpha_q_im, us->alpha_q_im, sizeof(us->alpha_q_im));
}
for (int ch = 0; ch < nb_channels; ch++) {
@@ -1877,7 +1672,7 @@ static int decode_usac_core_coder(AACDecContext *ac, AACUSACConfig *usac,
spectrum_decode(ac, usac, che, core_nb_channels);
if (ac->oc[1].m4ac.sbr > 0) {
ac->proc.sbr_apply(ac, che, nb_channels == 2 ? TYPE_CPE : TYPE_SCE, 0,
ac->proc.sbr_apply(ac, che, nb_channels == 2 ? TYPE_CPE : TYPE_SCE,
che->ch[0].output,
che->ch[1].output);
}
@@ -1941,8 +1736,8 @@ static int parse_audio_preroll(AACDecContext *ac, GetBitContext *gb)
}
/* Byte alignment is not guaranteed. */
for (int j = 0; j < au_len; j++)
tmp_buf[j] = get_bits(gb, 8);
for (int i = 0; i < au_len; i++)
tmp_buf[i] = get_bits(gb, 8);
ret = init_get_bits8(&gbc, tmp_buf, au_len);
if (ret < 0)
@@ -2033,10 +1828,6 @@ static int parse_ext_ele(AACDecContext *ac, AACUsacElemConfig *e,
case ID_EXT_ELE_AUDIOPREROLL:
ret = parse_audio_preroll(ac, gb2);
break;
case ID_EXT_ELE_UNI_DRC:
/* uniDrcGain() payload: DRC is not applied, just consume the
* bits via skip_bits_long below. */
break;
default:
/* This should never happen */
av_assert0(0);
@@ -2171,28 +1962,6 @@ int ff_aac_usac_decode_frame(AVCodecContext *avctx, AACDecContext *ac,
*got_frame_ptr = 0;
}
if (samples && ac->target_level) {
int method_val = usac->loudness.input_method_val;
if (method_val < 0) {
if (!ac->warned_loudness_missing) {
av_log(avctx, AV_LOG_WARNING,
"target_level set but no program/anchor loudness "
"measurement available; normalization skipped\n");
ac->warned_loudness_missing = 1;
}
} else {
/* Per ISO/IEC 23003-4 Table A.48: L = -57.75 + 0.25 * μ */
float input_loudness = -57.75f + 0.25f * method_val;
float gain_dB = (float)ac->target_level - input_loudness;
float gain = powf(10.0f, gain_dB / 20.0f);
for (int ch = 0; ch < frame->ch_layout.nb_channels; ch++)
ac->fdsp->vector_fmul_scalar((float *)frame->extended_data[ch],
(float *)frame->extended_data[ch],
gain, frame->nb_samples);
}
}
/* for dual-mono audio (SCE + SCE) */
is_dmono = ac->dmono_mode && elem_id[0] == 2 &&
!av_channel_layout_compare(&ac->oc[1].ch_layout,
+2 -2
View File
@@ -240,7 +240,7 @@ static void huff_data_2d(GetBitContext *gb, int16_t *part0_data[2], int16_t (*da
0, 2*esc_cnt, 0, (2*lav + 1));
for (i = 0; i < esc_cnt; i++) {
data[esc_idx[i]][0] = esc_data[0][i] - lav;
data[esc_idx[i]][1] = esc_data[1][i] - lav;
data[esc_idx[i]][0] = esc_data[0][i] - lav;
}
}
}
@@ -858,7 +858,7 @@ int ff_aac_map_index_data(AACMPSLosslessData *ld,
for (int i = 0; i < nb_param_sets; i++) {
if (ld->coarse_quant_no[i] == 1) {
coarse_to_fine(tmp_idx_data[i], data_type, start_band,
stop_band);
stop_band - start_band);
ld->coarse_quant_no[i] = 0;
}
}
+36 -23
View File
@@ -59,7 +59,6 @@
#define NOISE_LAMBDA_REPLACE 1.948f
#include "libavcodec/aaccoder_trellis.h"
#include "libavcodec/aaccoder_nmr.h"
typedef float (*quantize_and_encode_band_func)(struct AACEncContext *s, PutBitContext *pb,
const float *in, float *quant, const float *scaled,
@@ -503,12 +502,25 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
const float dist_bias = av_clipf(4.f * 120 / lambda, 0.25f, 4.0f);
const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);
int prev = -1000, prev_sf = -1;
int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);
/** Keep this in sync with twoloop's cutoff selection */
float rate_bandwidth_multiplier = 1.5f;
int prev = -1000, prev_sf = -1;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->ch_layout.nb_channels);
frame_bit_rate *= 1.15f;
if (avctx->cutoff > 0) {
bandwidth = avctx->cutoff;
} else {
bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
}
/* PNS candidacy must use the coder's actual coding bandwidth (s->bandwidth,
* fixed at init), not a separate heuristic, or it evaluates a different band
* range than the coder later codes. */
bandwidth = s->bandwidth;
cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
@@ -627,10 +639,24 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme
const float spread_threshold = FFMIN(0.75f, NOISE_SPREAD_THRESHOLD*FFMAX(0.5f, lambda/100.f));
const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);
/* PNS candidacy must use the coder's actual coding bandwidth (s->bandwidth,
* fixed at init), not a separate heuristic, or it evaluates a different band
* range than the coder later codes (NMR relies on this output directly). */
bandwidth = s->bandwidth;
int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);
/** Keep this in sync with twoloop's cutoff selection */
float rate_bandwidth_multiplier = 1.5f;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->ch_layout.nb_channels);
frame_bit_rate *= 1.15f;
if (avctx->cutoff > 0) {
bandwidth = avctx->cutoff;
} else {
bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
}
cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
@@ -841,17 +867,4 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
search_for_ms,
ff_aac_search_for_is,
},
[AAC_CODER_NMR] = {
search_for_quantizers_nmr,
codebook_trellis_rate,
quantize_and_encode_band,
ff_aac_encode_tns_info,
ff_aac_apply_tns,
set_special_band_scalefactors,
NULL, /* PNS decided in the trellis (search_for_quantizers_nmr) */
mark_pns,
ff_aac_search_for_tns,
NULL,
NULL,
},
};
-700
View File
@@ -1,700 +0,0 @@
/*
* AAC encoder NMR (noise-to-mask ratio) scalefactor coder
* Copyright (c) 2026 Lynne <dev@lynne.ee>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* AAC encoder NMR scalefactor coder.
*
* Optimizes the same noise-to-mask objective as the two-loop coder, but with an
* optimal Viterbi search over scalefactors instead of a heuristic loop. For each
* coded band the per-scalefactor distortion/bits curve is precomputed, then a
* trellis over the (window-group, band) coding sequence minimizes
* sum_g = dist_g(sf_g)/threshold_g +
* lambda * (spectral_bits_g(sf_g) + scalefactor_differential_bits)
* with |sf_g - sf_{g-1}| <= SCALE_MAX_DIFF as a constraint, and lambda
* binary-searched so the coded size meets the per-frame bit budget
*
* Perceptual noise substitution (PNS) is integrated into the same objective: once
* the trellis settles on its operating lambda, each noise-like band (flagged by
* mark_pns) is offered a terminal "code as noise" candidate whose cost is
* nmr_pns + lambda*NMR_PNS_BITS. Because NMR_PNS_BITS is far below a band's spectral bit
* count, this candidate only wins when lambda is large, i.e. when the encoder is
* struggling to hold the bitrate. The bits freed by the chosen PNS bands are
* then re-spent by a second trellis pass over the remaining bands.
*/
#ifndef AVCODEC_AACCODER_NMR_H
#define AVCODEC_AACCODER_NMR_H
#include <float.h>
#include <string.h>
#include "libavutil/mathematics.h"
#include "mathops.h"
#include "avcodec.h"
#include "put_bits.h"
#include "aac.h"
#include "aacenc.h"
#include "aactab.h"
#include "aacenctab.h"
/* differential scalefactor coding cost, clamped to the legal delta range */
#define NMR_SFBITS(d) ff_aac_scalefactor_bits[av_clip((d) + SCALE_DIFF_ZERO, 0, 2*SCALE_MAX_DIFF)]
#define NMR_ITERS 14 /* lambda binary-search iters */
#define NMR_IFINE 9 /* fine-pass lambda iters */
#define NMR_CITERS 7 /* coarse-pass lambda iters */
#define NMR_CWARM 5 /* coarse-pass iters when warm-started off the previous frame's
* lambda: the bracket spans 10 octaves instead of ~43, so fewer
* bisection steps reach the same resolution */
#define NMR_COARSE 8 /* two-pass coarse->fine grid step, cuts the Viterbi ncand^2 with no
* quality loss, 0 disables it (single full-resolution pass) */
#define NMR_STEP 1 /* fine-pass scalefactor candidate granularity */
#define NMR_PNS_BITS 9 /* approx cost in bits of signalling PNS */
/* Spectral-hole fill: noise-like bands the trellis left mostly empty are filled with
* energy-matched noise (PNS); an audible hole sounds worse than matched noise. */
#define NMR_PNS_HOLE_FRAC 0.5f
#define NMR_PNS_HOLE_SPREAD 0.5f
/* RC servo gain: scale the corridor centre by exp2(-K*fill/R) each frame to hold
* the long-run mean rate; without it a bad centre drifts for dozens of frames. */
#define NMR_RC_K_CBR 0.5f
#define NMR_RC_ITERS 8 /* lambda bisection iters when clamping an over-cap frame */
/* Corridor: bisect within [lam_rc/NMR_RC_CORR, lam_rc*NMR_RC_CORR] so quality stays
* smooth while per-frame demand is tracked; 1.5 cuts lambda jitter ~25%. */
#define NMR_RC_CORR 1.5f
/* Leaky-bucket half-depth (bits/ch); 512 is the sweet spot — tighter rebounds as
* frames cannot hit the narrow window. Clamped to the 6144 bits/ch decoder buffer. */
#define NMR_CBR_BUF 512
#define NMR_RC_CITERS 3 /* corridor coarse-pass iters */
/* Transient bit-burst: an isolated onset (preceded by >= NMR_BURST_GAP long frames)
* is coded NMR_BURST_GAIN x finer, held uniform across the run, repaid from steady stretches. */
#define NMR_BURST_GAP 10
#define NMR_BURST_GAIN 8.0f
#define NMR_RC_FITERS 4 /* corridor fine-pass iters */
#define NMR_RC_TRACK 0.1f /* per-frame pull of the corridor centre toward the realized lambda */
/* PNS noise-distortion gate: only bands coded well above the masking floor become noise. */
#define NMR_PNS_NDGATE 4.0f
/* Energy/threshold cap for PNS: loud bands (energy >> mask) yield clipping random peaks;
* only near-masked bands are safe substitution targets. */
#define NMR_PNS_MAX_ET 8.0f
/* Operating-lambda floor for PNS: below it the encoder is not struggling, so
* substituting real texture for 9 signalling bits is net-negative. */
#define NMR_PNS_LAM 100.0f
/**
* Viterbi over the coding sequence act[0..nact-1] (indices into the per-band
* curves nd/nb), with lambda binary-searched so the coded size ~ destbits.
* Fills chosen[band] for every band referenced by act. Returns the operating
* lambda. node cost = dist/threshold + lambda*spectral_bits;
* edge cost = lambda*sf_differential_bits; |delta sf| <= SCALE_MAX_DIFF hard.
*/
static float nmr_solve(AACEncContext *s,
const float (*nd)[NMR_NCAND], const int (*nb)[NMR_NCAND],
const int *blo, const int *bnc, int step,
const int *act, int nact, int destbits, int *chosen,
float lo_l, float hi_l, int iters)
{
float dp[NMR_NCAND], dpp[NMR_NCAND], node[NMR_NCAND];
float lamsf[2*SCALE_MAX_DIFF + 1]; /* lam*sfdiff bit cost, per lambda */
uint8_t bp[128][NMR_NCAND];
float lam = 1.0f;
if (nact <= 0)
return lam;
for (int it = 0; it < iters; it++) {
lam = sqrtf(lo_l * hi_l);
for (int i = 0; i <= 2*SCALE_MAX_DIFF; i++)
lamsf[i] = lam * ff_aac_scalefactor_bits[i]; /* edge cost for this lambda */
int b0 = act[0];
for (int o = 0; o < bnc[b0]; o++)
dp[o] = nd[b0][o] + lam * nb[b0][o]; /* anchor band node cost */
for (int k = 1; k < nact; k++) {
int b = act[k], pb = act[k-1];
memcpy(dpp, dp, sizeof(dp));
for (int o = 0; o < bnc[b]; o++)
node[o] = nd[b][o] + lam * nb[b][o];
/* dp[o] = node[o] + min_op(dpp[op] + edge cost) */
s->aacdsp.nmr_trellis_step(dp, bp[k], dpp, node, lamsf,
bnc[b], bnc[pb], blo[b] - blo[pb], step,
SCALE_MAX_DIFF);
}
/* backtrack */
int beo = 0, b = act[nact-1];
float bec = FLT_MAX;
for (int o = 0; o < bnc[b]; o++)
if (dp[o] < bec) { bec = dp[o]; beo = o; }
chosen[b] = beo;
for (int k = nact-1; k > 0; k--)
chosen[act[k-1]] = bp[k][chosen[act[k]]];
/* calc cost */
int total = 0;
for (int k = 0; k < nact; k++)
total += nb[act[k]][chosen[act[k]]];
for (int k = 1; k < nact; k++)
total += NMR_SFBITS((blo[act[k]]+chosen[act[k]]*step) - (blo[act[k-1]]+chosen[act[k-1]]*step));
if (it == iters - 1)
break;
/* check if we went over budget, go coarser if we did */
if (total > destbits)
lo_l = lam;
else
hi_l = lam;
}
return lam;
}
/* Build one coded band's (dist/threshold, bits) cost curve, candidates sf = lo + o*step
* for o in [0,maxn), stopping when the band would drop (cb <= 0). Returns the bit count. */
static int nmr_band_curve(AACEncContext *s, SingleChannelElement *sce, int w, int g,
int start, int lo, int step, int maxn, float invthr,
float maxval, float *nd_row, int *nb_row)
{
int ncand = 0;
for (int o = 0; o < maxn && lo + o*step <= SCALE_MAX_POS; o++) {
int sf = lo + o*step, btot = 0, cb = find_min_book(maxval, sf);
float dist = 0.0f;
if (cb <= 0)
break;
for (int w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int bb;
dist += quantize_band_cost_cached(s, w + w2, g, sce->coeffs + start + w2*128,
s->scoefs + start + w2*128, sce->ics.swb_sizes[g],
sf, cb, 1.0f, INFINITY, &bb, NULL, 0);
btot += bb;
}
nd_row[ncand] = (dist - btot) * invthr;
nb_row[ncand] = btot;
ncand++;
}
return ncand;
}
static void search_for_quantizers_nmr(AVCodecContext *avctx,
AACEncContext *s,
SingleChannelElement *sce,
const float lambda)
{
int bch = ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels);
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / bch * (lambda / 120.f);
int allz = 0, cutoff = 1024, nbnd = 0;
float thr[128]; /* allocation-law effective threshold (drives the trellis) */
float thr_real[128]; /* real masking threshold (perceptual gates: PNS) */
float pener[128]; /* band energy (for PNS noise target) */
float pspread[128]; /* band tonality spread (1 = noise) */
int minsf[128];
float maxvals[128];
/* coded-band trellis state (indexed 0..nbnd-1) */
int bidx[128]; /* sce band index (w*16+g) */
int bw[128], bg[128], bst[128]; /* window group, swb, coef start per coded band */
int blo[128]; /* finest candidate scalefactor */
int bnc[128]; /* number of candidates */
int chosen[128];
int act[128]; /* active (non-PNS) band coding order */
uint8_t is_pns[128]; /* trellis band coded as noise */
float (*nd)[NMR_NCAND] = s->nmr->nd; /* dist / threshold per candidate (heap) */
int (*nb)[NMR_NCAND] = s->nmr->nb; /* spectral bits per candidate (heap) */
/* two-pass coarse->fine grid step (see NMR_COARSE), the lambda search runs on
* the cheap coarse grid, PASS 2 refines the winner at NMR_STEP granularity */
const int cstep = NMR_COARSE > 0 ? NMR_COARSE : NMR_STEP;
s->nmr->counted[s->cur_channel] = 0;
/* Global-lambda RC: one solve per frame at a servoed centre lambda; the reservoir
* holds the long-run mean rate. Bypassed for VBR (-q:a) and the bootstrap frame. */
int rc_eligible = !(avctx->flags & AV_CODEC_FLAG_QSCALE) && avctx->bit_rate > 0 &&
avctx->bit_rate_tolerance != 0;
/* Leaky-bucket reservoir: rc_fill (signed +-rc_bmax); the spend-floor/cap below force
* lambda so no frame banks past +rc_bmax or borrows past -rc_bmax. */
int rc_rate_frame = avctx->bit_rate * 1024.0 / avctx->sample_rate;
int rc_bmax = FFMIN(FFMAX(6144 * s->channels - rc_rate_frame, 256), NMR_CBR_BUF * s->channels);
if (rc_eligible && avctx->frame_num != s->nmr->rc_frame_num) {
if (s->nmr->rc_frame_num > 0 && s->nmr->lam_rc > 0.0f)
s->nmr->rc_fill = av_clip(s->nmr->rc_fill + rc_rate_frame - s->last_frame_pb_count,
-rc_bmax, rc_bmax);
s->nmr->rc_frame_num = avctx->frame_num;
/* Transient burst run state: set at run start and held across the run so
* coding stays uniform; repaid from the reservoir's steady stretches. */
int is_short = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE;
if (is_short) {
if (!s->nmr->prev_was_short) /* run start */
s->nmr->run_burst = s->nmr->frames_since_short >= NMR_BURST_GAP
? NMR_BURST_GAIN : 1.0f;
s->nmr->frames_since_short = 0;
} else {
s->nmr->run_burst = 1.0f;
s->nmr->frames_since_short++;
}
s->nmr->prev_was_short = is_short;
}
int rc_global = rc_eligible && s->nmr->lam_rc > 0.0f;
if (s->psy.bitres.alloc >= 0)
destbits = s->psy.bitres.alloc *
(lambda / (avctx->global_quality ? avctx->global_quality : 120));
if (rc_global && s->psy.bitres.alloc >= 0)
/* uniform CBR target: nominal rate plus fast reservoir repayment */
destbits = (avctx->bit_rate * 1024.0 / avctx->sample_rate
+ s->nmr->rc_fill / 2.0) / s->channels;
destbits = FFMIN(destbits, 5800);
/* honest budget: subtract the measured non-trellis overhead (section data, ICS,
* sf/PNS signalling), which is rate-dependent hence adaptive. */
if (s->nmr->side_inited)
destbits = av_clip(destbits - (int)(s->nmr->side_ema / s->channels), 64, 5800);
/* Apply the held transient burst factor (set in the run-state machine above). */
if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE && s->nmr->run_burst > 1.0f)
destbits = av_clip((int)(destbits * s->nmr->run_burst), 64, 6800);
/* band cutoff index for this frame's window size; the bandwidth is fixed
* at init and shared with the psy model */
cutoff = s->bandwidth * 2 * (1024 / sce->ics.num_windows) / avctx->sample_rate;
/* Short-block transient noise shaping (pairs with short-block TNS): temporal
* premasking clamps each window's threshold toward the preceding windows'
* (Apple's preEchoReduction), and flat-residual flattens each window's thresholds
* to their per-window mean so TNS synthesis has a white floor to concentrate. */
if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
const float pm_p1 = 0.1f, pm_p2 = 2.0f, pm_p3 = 4.0f;
for (int g = 0; g < sce->ics.num_swb; g++) {
float t1 = FLT_MAX, t2 = FLT_MAX; /* original thr of w-1, w-2 */
for (int w = 0; w < sce->ics.num_windows; w++) {
FFPsyBand *b = &s->psy.ch[s->cur_channel].psy_bands[w*16+g];
float t = b->threshold;
float c = FFMIN(t, FFMIN(t1*pm_p2, t2*pm_p3));
b->threshold = FFMAX(c, t*pm_p1);
t2 = t1; t1 = t;
}
}
{
for (int w = 0; w < sce->ics.num_windows; w++) {
float sum = 0.0f; int n = 0;
for (int g = 0; g < sce->ics.num_swb; g++) {
FFPsyBand *b = &s->psy.ch[s->cur_channel].psy_bands[w*16+g];
if (b->energy > b->threshold && b->threshold > 0.0f) { sum += b->threshold; n++; }
}
if (n > 0) {
float mean = sum / n;
for (int g = 0; g < sce->ics.num_swb; g++) {
FFPsyBand *b = &s->psy.ch[s->cur_channel].psy_bands[w*16+g];
if (b->energy > b->threshold && b->threshold > 0.0f)
b->threshold = mean;
}
}
}
}
}
/* Allocation curve to favour high frequencies */
const float a_ae = 0.443f, a_at = 0.111f;
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
int start = 0;
for (int g = 0; g < sce->ics.num_swb; start += sce->ics.swb_sizes[g++]) {
float uplim = 0.0f, ener = 0.0f, spread = 2.0f;
int nz = 0;
if (sce->band_type[w*16+g] == INTENSITY_BT ||
sce->band_type[w*16+g] == INTENSITY_BT2) {
/* pre-decided intensity band (right channel): keep its
* signalling, it is not trellis-coded */
for (int w2 = 0; w2 < sce->ics.group_len[w]; w2++)
sce->zeroes[(w+w2)*16+g] = 0;
continue;
}
for (int w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
ener += band->energy;
spread = FFMIN(spread, band->spread);
if (start >= cutoff || band->energy <= band->threshold || band->threshold == 0.0f) {
sce->zeroes[(w+w2)*16+g] = 1;
continue;
}
uplim += band->threshold;
nz = 1;
}
sce->zeroes[w*16+g] = !nz;
thr_real[w*16+g] = uplim; /* real mask, before the allocation law (PNS gate) */
if (nz && ener > 0.0f && uplim > 0.0f)
uplim = expf(a_ae * logf(ener) + a_at * logf(uplim));
thr[w*16+g] = uplim;
pener[w*16+g] = ener;
pspread[w*16+g] = spread;
allz |= nz;
}
}
if (!allz)
goto bail;
s->aacdsp.abs_pow34(s->scoefs, sce->coeffs, 1024);
ff_quantize_band_cost_cache_init(s);
/* finest codeable scalefactor and max value per band */
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
int start = w*128;
for (int g = 0; g < sce->ics.num_swb; g++) {
maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], s->scoefs + start);
minsf[w*16+g] = maxvals[w*16+g] > 0 ? coef2minsf(maxvals[w*16+g]) : 0;
start += sce->ics.swb_sizes[g];
}
}
/* PASS 1:
* precompute each coded band's cost curve at the coarse candidate step
* (the lambda search runs on this cheap grid, PASS 2 refines the winner) */
{
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
int start = w*128;
for (int g = 0; g < sce->ics.num_swb; g++) {
if (!sce->zeroes[w*16+g] && maxvals[w*16+g] > 0 && nbnd < 128) {
int lo = av_clip(minsf[w*16+g], 0, SCALE_MAX_POS);
float invthr = 1.0f / FFMAX(thr[w*16+g], 1e-9f);
int ncand = nmr_band_curve(s, sce, w, g, start, lo, cstep, NMR_NCAND,
invthr, maxvals[w*16+g], nd[nbnd], nb[nbnd]);
if (ncand == 0) {
/* nothing codeable -> drop the whole group band. The
* subwindow flags must be cleared too: the encoder later
* re-derives the group flag by ANDing them, which would
* resurrect the band with a never-assigned scalefactor. */
for (int w2 = 0; w2 < sce->ics.group_len[w]; w2++)
sce->zeroes[(w+w2)*16+g] = 1;
} else {
bidx[nbnd] = w*16+g;
bw[nbnd] = w;
bg[nbnd] = g;
bst[nbnd] = start;
blo[nbnd] = lo;
bnc[nbnd] = ncand;
nbnd++;
}
}
start += sce->ics.swb_sizes[g];
}
}
}
if (!nbnd)
goto bail;
/* solve the trellis over all coded bands, then offer PNS at the operating
* lambda and re-solve over the survivors with the freed budget */
{
int nact = nbnd, pns_count = 0;
float lam0 = s->nmr->lam[s->cur_channel];
float lam;
for (int b = 0; b < nbnd; b++) {
act[b] = b;
is_pns[b] = 0;
}
if (rc_global) {
/* bisect to this frame's bit demand within the corridor around the
* servoed lambda: per-frame psy demand is tracked, but lambda cannot
* jump, which keeps quality smooth across frames */
float lo = s->nmr->lam_rc / NMR_RC_CORR;
/* Transient burst: widen the lower lambda bound so the bisection can actually
* pour the boosted destbits into an onset frame (finer coding kills the
* pre-echo); reservoir servo repays it from the steady frames. run_burst==1 on
* non-onset frames leaves the corridor unchanged. */
if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE && s->nmr->run_burst > 1.0f)
lo /= s->nmr->run_burst;
lam = nmr_solve(s, nd, nb, blo, bnc, cstep, act, nact, destbits, chosen,
lo, s->nmr->lam_rc * NMR_RC_CORR,
NMR_RC_CITERS);
int tot = 0;
for (int k = 0; k < nact; k++)
tot += nb[act[k]][chosen[act[k]]];
for (int k = 1; k < nact; k++)
tot += NMR_SFBITS((blo[act[k]]+chosen[act[k]]*cstep) - (blo[act[k-1]]+chosen[act[k-1]]*cstep));
int hardcap = av_clip((int)(5800.f * FFMIN(1.f, lambda / 120.f)), 256, 5800);
/* leaky-bucket window: don't borrow past -rc_bmax (cap) or bank past +rc_bmax (floor) */
int rc_cap = FFMIN(hardcap, (s->nmr->rc_fill + rc_rate_frame + rc_bmax) / s->channels);
int rc_floor = FFMAX(0, (s->nmr->rc_fill + rc_rate_frame - rc_bmax) / s->channels);
if (tot > rc_cap)
lam = nmr_solve(s, nd, nb, blo, bnc, cstep, act, nact, rc_cap, chosen,
lam, 1e4f, NMR_CITERS);
else if (tot < rc_floor)
lam = nmr_solve(s, nd, nb, blo, bnc, cstep, act, nact, rc_floor, chosen,
1e-9f, lam, NMR_CITERS);
} else if (NMR_COARSE > 0 && lam0 > 0.0f) {
/* per-frame bisection; lambda is strongly frame-correlated, so when a
* previous frame's operating lambda exists, bisect a narrow bracket
* around it. A result near the bracket edge means the budget crossing
* lies outside (hard content transition) == redo the full search. */
lam = nmr_solve(s, nd, nb, blo, bnc, cstep, act, nact, destbits, chosen,
lam0/32.0f, lam0*32.0f, NMR_CWARM);
if (lam < lam0/16.0f || lam > lam0*16.0f)
lam0 = 0.0f;
}
if (!rc_global && lam0 <= 0.0f)
lam = nmr_solve(s, nd, nb, blo, bnc, cstep, act, nact, destbits, chosen,
1e-9f, 1e4f, NMR_COARSE > 0 ? NMR_CITERS : NMR_ITERS);
/* PASS 2:
* refine each band at full granularity (NMR_STEP) in a +/-cstep window
* around the coarse pick, then re-solve. Recovers single-pass quality while the
* lambda search stayed cheap on the coarse grid. */
if (NMR_COARSE > 0) {
/* nmr_speed, 0 = slowest/best, higher = faster. It narrows the fine
* refine +/-window (scalefactors) below NMR_COARSE: at speed 0 the window
* spans the whole coarse-grid gap, so the two-pass result matches the
* exhaustive single-pass search.
* Each speed level shaves one sf off the window.
* At @64k mono (Zim / xRT): speed 0 -> 0.00095/15x,
* 2 -> 0.00096/18x, 3 -> 0.00100/20x, 4 -> 0.00103/22x */
int win = NMR_COARSE - av_clip(s->options.nmr_speed, 0, 4);
for (int b = 0; b < nbnd; b++) {
int center = blo[b] + chosen[b]*cstep;
int flo = av_clip(center - win, av_clip(minsf[bidx[b]], 0, SCALE_MAX_POS), SCALE_MAX_POS);
int maxn = FFMIN(NMR_NCAND, 2*win/NMR_STEP + 1);
float invthr = 1.0f / FFMAX(thr[bidx[b]], 1e-9f);
int ncand = nmr_band_curve(s, sce, bw[b], bg[b], bst[b], flo, NMR_STEP, maxn,
invthr, maxvals[bidx[b]], nd[b], nb[b]);
blo[b] = flo;
bnc[b] = FFMAX(1, ncand);
}
/* fine pass: narrow corridor around the coarse solve */
if (rc_global)
lam = nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, destbits, chosen,
lam/2.0f, lam*2.0f, NMR_RC_FITERS);
else
lam = nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, destbits, chosen,
lam/16.0f, lam*16.0f, NMR_IFINE);
}
if (rc_global) {
/* leaky-bucket clamp: keep the frame within [rc_floor, rc_cap] so the reservoir
* stays in +-rc_bmax -- clamp lambda UP if it would borrow past the cap, DOWN if it
* would bank past the floor (spend-floor). The hard cap follows the encoder's outer
* lambda so the (rare) hard-overflow re-encode -- which shrinks that lambda -- always
* converges; on the first pass lambda is nominal and this is 5800. */
int hardcap = av_clip((int)(5800.f * FFMIN(1.f, lambda / 120.f)), 256, 5800);
int tot = 0;
for (int k = 0; k < nact; k++)
tot += nb[act[k]][chosen[act[k]]];
for (int k = 1; k < nact; k++)
tot += NMR_SFBITS((blo[act[k]]+chosen[act[k]]*NMR_STEP) - (blo[act[k-1]]+chosen[act[k-1]]*NMR_STEP));
int rc_cap = FFMIN(hardcap, (s->nmr->rc_fill + rc_rate_frame + rc_bmax) / s->channels);
int rc_floor = FFMAX(0, (s->nmr->rc_fill + rc_rate_frame - rc_bmax) / s->channels);
if (tot > rc_cap)
lam = nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, rc_cap, chosen,
lam, 1e4f, NMR_RC_ITERS);
else if (tot < rc_floor)
lam = nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, rc_floor, chosen,
1e-9f, lam, NMR_RC_ITERS);
}
s->nmr->lam[s->cur_channel] = lam; /* warm start for the next frame */
if (rc_global) {
/* drag the corridor centre toward the realized lambda so it follows
* content drift faster than the reservoir term alone */
float c = s->nmr->lam_rc * powf(lam / s->nmr->lam_rc, NMR_RC_TRACK);
/* then servo the centre off the reservoir error so the long-run rate
* returns to nominal. rc_fill>0 = bits banked (undershooting) -> lower
* lambda to spend them; <0 -> raise it. This is what holds the mean;
* the corridor tracking alone has no rate authority and a bad centre
* would otherwise drift for dozens of frames, starving each one. */
float R = avctx->bit_rate * 1024.0 / avctx->sample_rate;
c *= exp2f(-NMR_RC_K_CBR * s->nmr->rc_fill / R);
s->nmr->lam_rc = av_clipf(c, 1e-6f, 1e4f);
} else if (rc_eligible && nbnd >= 8) {
/* bootstrap the servo off the first substantive frame; near-silent
* lead-in frames have degenerate budgets that rail the bisection to
* a nonsense lambda and would poison the whole stream */
s->nmr->lam_rc = av_clipf(lam, 1e-4f, 10.0f);
}
{ /* PNS */
const float pns_lam = NMR_PNS_LAM;
/* band 0 (lowest freq) is kept as the global-gain / sf-chain anchor */
for (int b = 1; b < nbnd; b++) {
int bi = bidx[b];
float spread = pspread[bi];
float nmr_pns, cost_keep, cost_pns, frac;
if (!sce->can_pns[bi])
continue;
/* Loud-band guard: never substitute a band whose energy is far above the
* masking threshold -- energy-matched noise on a dominant band clips/pops
* (and is audibly wrong). PNS is for near-masked noise only. */
if (pener[bi] > NMR_PNS_MAX_ET * thr_real[bi])
continue;
/* Struggle gate: no PNS at all unless the encoder is genuinely under bit
* pressure (high operating lambda). */
if (lam <= pns_lam)
continue;
/* Spectral-hole fill: a noise-like band the trellis left mostly empty */
frac = nd[b][chosen[b]] * thr[bi] / FFMAX(pener[bi], 1e-9f);
if (spread > NMR_PNS_HOLE_SPREAD && frac > NMR_PNS_HOLE_FRAC) {
is_pns[b] = 1;
pns_count++;
continue;
}
/* Only replace a band that is being coded audibly badly */
if (nd[b][chosen[b]] * thr[bi] <= NMR_PNS_NDGATE * thr_real[bi])
continue;
/* perceptual cost of replacing the band with energy-matched noise:
* the non-noise-like fraction of its energy, in dist/threshold units */
nmr_pns = FFMAX(0.0f, pener[bi] * (1.0f - spread*spread))
/ FFMAX(thr[bi], 1e-9f);
cost_keep = nd[b][chosen[b]] + lam * nb[b][chosen[b]];
cost_pns = nmr_pns + lam * NMR_PNS_BITS;
if (cost_pns < cost_keep) {
is_pns[b] = 1;
pns_count++;
}
}
if (pns_count) {
int budget2 = destbits - pns_count * NMR_PNS_BITS;
nact = 0;
for (int b = 0; b < nbnd; b++)
if (!is_pns[b])
act[nact++] = b;
/* re-solve over the survivors: at fixed lambda the allocation is
* the same except for the repaired sf-delta chain; in bisection
* mode re-spend the freed budget */
if (rc_global)
nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, budget2, chosen,
lam, lam, 1);
else
nmr_solve(s, nd, nb, blo, bnc, NMR_STEP, act, nact, budget2, chosen,
1e-9f, 1e4f, NMR_ITERS);
}
}
for (int b = 0; b < nbnd; b++) {
int bi = bidx[b];
if (is_pns[b]) {
sce->band_type[bi] = NOISE_BT;
sce->zeroes[bi] = 0;
sce->pns_ener[bi] = pener[bi] * FFMIN(1.0f, pspread[bi]*pspread[bi]);
} else {
sce->sf_idx[bi] = av_clip(blo[b] + chosen[b]*NMR_STEP, 0, SCALE_MAX_POS);
}
}
{ /* record the bits this solve accounted for; the encoder compares them
* against the channel's real output to keep the budget honest */
int tot = 0, prevb = -1;
for (int b = 0; b < nbnd; b++) {
if (is_pns[b])
continue;
tot += nb[b][chosen[b]];
if (prevb >= 0)
tot += NMR_SFBITS((blo[b]+chosen[b]*NMR_STEP) - (blo[prevb]+chosen[prevb]*NMR_STEP));
prevb = b;
}
s->nmr->counted[s->cur_channel] = tot;
}
}
/* SCALE_MAX_DIFF condition:
* re-clamp, codebook fixup, drop uncodeable, set global gain
* NOISE_BT bands keep their own scalefactor chain via set_special_band_scalefactors) */
{
uint8_t nextband[128];
int prev = -1;
ff_init_nextband_map(sce, nextband);
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
for (int g = 0; g < sce->ics.num_swb; g++) {
if (sce->band_type[w*16+g] == NOISE_BT ||
sce->band_type[w*16+g] == INTENSITY_BT ||
sce->band_type[w*16+g] == INTENSITY_BT2)
continue;
if (sce->zeroes[w*16+g]) {
sce->band_type[w*16+g] = 0;
continue;
}
if (prev != -1)
sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], prev - SCALE_MAX_DIFF, prev + SCALE_MAX_DIFF);
sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
if (sce->band_type[w*16+g] <= 0) {
if (!ff_sfdelta_can_remove_band(sce, nextband, prev, w*16+g)) {
sce->band_type[w*16+g] = 1;
} else {
/* drop subwindow flags too, see the PASS 1 drop above */
for (int w2 = 0; w2 < sce->ics.group_len[w]; w2++)
sce->zeroes[(w+w2)*16+g] = 1;
sce->band_type[w*16+g] = 0;
continue;
}
}
if (prev == -1)
sce->sf_idx[0] = sce->sf_idx[w*16+g]; /* global gain */
prev = sce->sf_idx[w*16+g];
}
}
/* Every band, coded or not, must carry a chain-legal scalefactor: the
* codebook trellis (encode_window_bands_info) may later absorb a dropped
* band into a nonzero section, resurrecting it, and its sf then gets
* coded. Forward-fill with the previous coded sf (delta 0, cheapest);
* leading bands get the global gain. */
if (prev != -1) {
int last = sce->sf_idx[0];
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
for (int g = 0; g < sce->ics.num_swb; g++) {
if (!sce->zeroes[w*16+g] && sce->band_type[w*16+g] != NOISE_BT &&
sce->band_type[w*16+g] < RESERVED_BT)
last = sce->sf_idx[w*16+g];
else if (sce->band_type[w*16+g] < RESERVED_BT && (w*16+g) > 0)
sce->sf_idx[w*16+g] = last;
}
}
}
}
return;
bail:
/* Nothing codeable in this channel. Leave a fully consistent state: any
* stale nonzero band_type acts as a codebook lower bound in the encoder's
* section trellis (encode_window_bands_info), which would forbid the zero
* section and resurrect the band with a stale, chain-illegal scalefactor.
* Pre-decided intensity bands keep their signalling. */
for (int i = 0; i < 128; i++) {
if (sce->band_type[i] == INTENSITY_BT || sce->band_type[i] == INTENSITY_BT2)
continue;
sce->zeroes[i] = 1;
sce->band_type[i] = 0;
}
}
#endif /* AVCODEC_AACCODER_NMR_H */
+27 -2
View File
@@ -71,6 +71,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);
int refbits = destbits;
int toomanybits, toofewbits;
char nzs[128];
uint8_t nextband[128];
@@ -171,8 +172,32 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
/** and zero out above cutoff frequency */
{
int wlen = 1024 / sce->ics.num_windows;
/* the bandwidth is fixed at init and shared with the psy model */
cutoff = s->bandwidth * 2 * wlen / avctx->sample_rate;
int bandwidth;
/**
* Scale, psy gives us constant quality, this LP only scales
* bitrate by lambda, so we save bits on subjectively unimportant HF
* rather than increase quantization noise. Adjust nominal bitrate
* to effective bitrate according to encoding parameters,
* AAC_CUTOFF_FROM_BITRATE is calibrated for effective bitrate.
*/
float rate_bandwidth_multiplier = 1.5f;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->ch_layout.nb_channels);
/** Compensate for extensions that increase efficiency */
if (s->options.pns || s->options.intensity_stereo)
frame_bit_rate *= 1.15f;
if (avctx->cutoff > 0) {
bandwidth = avctx->cutoff;
} else {
bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
s->psy.cutoff = bandwidth;
}
cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
pns_start_pos = NOISE_LOW_LIMIT * 2 * wlen / avctx->sample_rate;
}
+148 -496
View File
@@ -123,40 +123,40 @@ static const AACPCEInfo aac_pce_configs[] = {
{
.layout = AV_CHANNEL_LAYOUT_SURROUND,
.num_ele = { 2, 0, 0, 0 },
.pairing = { { 0, 1 }, },
.pairing = { { 1, 0 }, },
.index = { { 0, 0 }, },
.config_map = { 2, TYPE_SCE, TYPE_CPE },
.reorder_map = { 2, 0, 1 },
.config_map = { 2, TYPE_CPE, TYPE_SCE, },
.reorder_map = { 0, 1, 2 },
},
{
.layout = AV_CHANNEL_LAYOUT_3POINT1,
.num_ele = { 2, 0, 0, 1 },
.pairing = { { 0, 1 }, },
.pairing = { { 1, 0 }, },
.index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },
.config_map = { 3, TYPE_SCE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 3 },
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },
.reorder_map = { 0, 1, 2, 3 },
},
{
.layout = AV_CHANNEL_LAYOUT_4POINT0,
.num_ele = { 2, 0, 1, 0 },
.pairing = { { 0, 1 }, { 0 }, { 0 }, },
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
.index = { { 0, 0 }, { 0 }, { 1 } },
.config_map = { 3, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 2, 0, 1, 3 },
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3 },
},
{
.layout = AV_CHANNEL_LAYOUT_4POINT1,
.num_ele = { 2, 0, 1, 1 },
.pairing = { { 0, 1 }, { 0 }, { 0 }, },
.index = { { 0, 0 }, { 0 }, { 1 }, { 0 } },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 4, 3 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
.index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4 },
},
{
.layout = AV_CHANNEL_LAYOUT_2_2,
.num_ele = { 1, 0, 1, 0 },
.pairing = { { 1 }, { 0 }, { 1 }, },
.index = { { 0 }, { 0 }, { 1 } },
.num_ele = { 1, 1, 0, 0 },
.pairing = { { 1 }, { 1 }, },
.index = { { 0 }, { 1 }, },
.config_map = { 2, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3 },
},
@@ -170,131 +170,158 @@ static const AACPCEInfo aac_pce_configs[] = {
},
{
.layout = AV_CHANNEL_LAYOUT_5POINT0,
.num_ele = { 2, 0, 1, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1 } },
.index = { { 0, 0 }, { 0 }, { 1 } },
.config_map = { 3, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 2, 0, 1, 3, 4 },
.num_ele = { 2, 1, 0, 0 },
.pairing = { { 1, 0 }, { 1 }, },
.index = { { 0, 0 }, { 1 } },
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4 },
},
{
.layout = AV_CHANNEL_LAYOUT_5POINT1,
.num_ele = { 2, 0, 1, 1 },
.pairing = { { 0, 1 }, { 0 }, { 1 }, },
.index = { { 0, 0 }, { 0 }, { 1 }, { 0 } },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 4, 5, 3 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
.index = { { 0, 0 }, { 1 }, { 1 } },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5 },
},
{
.layout = AV_CHANNEL_LAYOUT_5POINT0_BACK,
.num_ele = { 2, 0, 1, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1 } },
.pairing = { { 1, 0 }, { 0 }, { 1 } },
.index = { { 0, 0 }, { 0 }, { 1 } },
.config_map = { 3, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 2, 0, 1, 3, 4 },
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4 },
},
{
.layout = AV_CHANNEL_LAYOUT_5POINT1_BACK,
.num_ele = { 2, 0, 1, 1 },
.pairing = { { 0, 1 }, { 0 }, { 1 }, },
.index = { { 0, 0 }, { 0 }, { 1 }, { 0 } },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 4, 5, 3 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
.index = { { 0, 0 }, { 1 }, { 1 } },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5 },
},
{
.layout = AV_CHANNEL_LAYOUT_6POINT0,
.num_ele = { 2, 0, 2, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1, 0 } },
.index = { { 0, 0 }, { 0 }, { 1, 1 } },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 2, 0, 1, 4, 5, 3 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 1 }, { 0 }, },
.index = { { 0, 0 }, { 1 }, { 1 } },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5 },
},
{
.layout = AV_CHANNEL_LAYOUT_6POINT0_FRONT,
.num_ele = { 2, 0, 1, 0 },
.pairing = { { 1, 1 }, { 0 }, { 1 } },
.index = { { 0, 1 }, { 0 }, { 2 }, },
.num_ele = { 2, 1, 0, 0 },
.pairing = { { 1, 1 }, { 1 } },
.index = { { 1, 0 }, { 2 }, },
.config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },
.reorder_map = { 2, 3, 0, 1, 4, 5 },
.reorder_map = { 0, 1, 2, 3, 4, 5 },
},
{
.layout = AV_CHANNEL_LAYOUT_HEXAGONAL,
.num_ele = { 2, 0, 2, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1, 0 } },
.index = { { 0, 0 }, { 0 }, { 1, 1 } },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 2, 0, 1, 3, 4, 5 },
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
.index = { { 0, 0 },{ 0 },{ 1, 1 } },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },
.reorder_map = { 0, 1, 2, 3, 4, 5 },
},
{
.layout = AV_CHANNEL_LAYOUT_6POINT1,
.num_ele = { 2, 0, 2, 1 },
.pairing = { { 0, 1 }, { 0 }, { 1, 0 }, },
.index = { { 0, 0 }, { 0 }, { 1, 1 }, { 0 } },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 5, 6, 4, 3 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
.index = { { 0, 0 },{ 1 },{ 1, 2 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
},
{
.layout = AV_CHANNEL_LAYOUT_6POINT1_BACK,
.num_ele = { 2, 0, 2, 1 },
.pairing = { { 0, 1 },{ 0 },{ 1, 0 }, },
.index = { { 0, 0 },{ 0 },{ 1, 1 },{ 0 } },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 4, 5, 6, 3 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
},
{
.layout = AV_CHANNEL_LAYOUT_6POINT1_FRONT,
.num_ele = { 2, 0, 1, 1 },
.pairing = { { 1, 1 }, { 0 }, { 1 }, },
.index = { { 0, 1 }, { 0 }, { 2 }, { 0 }, },
.config_map = { 4, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_LFE, },
.reorder_map = { 3, 4, 0, 1, 5, 6, 2 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
},
{
.layout = AV_CHANNEL_LAYOUT_7POINT0,
.num_ele = { 2, 0, 2, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1, 1 }, },
.index = { { 0, 0 }, { 0 }, { 2, 1 }, },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 2, 0, 1, 3, 4, 5, 6 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
.index = { { 0, 0 }, { 1 }, { 2 }, },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
},
{
.layout = AV_CHANNEL_LAYOUT_7POINT0_FRONT,
.num_ele = { 3, 0, 1, 0 },
.pairing = { { 0, 1, 1 }, { 0 }, { 1 }, },
.index = { { 0, 0, 1 }, { 0 }, { 2 }, },
.config_map = { 4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 2, 3, 4, 0, 1, 5, 6 },
.num_ele = { 2, 1, 1, 0 },
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
.index = { { 0, 0 }, { 1 }, { 2 }, },
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
},
{
.layout = AV_CHANNEL_LAYOUT_7POINT1,
.num_ele = { 2, 0, 2, 1 },
.pairing = { { 0, 1 }, { 0 }, { 1, 1 }, },
.index = { { 0, 0 }, { 0 }, { 2, 1 }, { 0 } },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 0, 1, 4, 5, 6, 7, 3 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
},
{
.layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE,
.num_ele = { 3, 0, 1, 1 },
.pairing = { { 0, 1, 1 }, { 0 }, { 1 }, },
.index = { { 0, 0, 1 }, { 0 }, { 2 }, { 0 }, },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 4, 5, 0, 1, 6, 7, 3 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 0 },{ 1, 1 }, },
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
},
{
.layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
.num_ele = { 3, 0, 1, 1 },
.pairing = { { 0, 1, 1 }, { 0 }, { 1 } },
.index = { { 0, 0, 1 }, { 0 }, { 2 }, { 0 } },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_LFE },
.reorder_map = { 2, 6, 7, 0, 1, 4, 5, 3 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
},
{
.layout = AV_CHANNEL_LAYOUT_OCTAGONAL,
.num_ele = { 2, 0, 3, 0 },
.pairing = { { 0, 1 }, { 0 }, { 1, 1, 0 }, },
.index = { { 0, 0 }, { 0 }, { 1, 2, 1 }, },
.config_map = { 5, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 2, 0, 1, 6, 7, 3, 4, 5 },
.num_ele = { 2, 1, 2, 0 },
.pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },
.index = { { 0, 0 }, { 1 }, { 2, 1 } },
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
},
{ /* Meant for order 2/mixed ambisonics */
.layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 9,
.u.mask = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER },
.num_ele = { 2, 2, 2, 0 },
.pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },
.index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },
.config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
},
{ /* Meant for order 2/mixed ambisonics */
.layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 10,
.u.mask = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER |
AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER },
.num_ele = { 2, 2, 2, 0 },
.pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },
.index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },
.config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
},
{
.layout = AV_CHANNEL_LAYOUT_HEXADECAGONAL,
.num_ele = { 4, 2, 4, 0 },
.pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },
.index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },
.config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
},
};
@@ -339,10 +366,11 @@ static void put_pce(PutBitContext *pb, AVCodecContext *avctx)
* Make AAC audio config object.
* @see 1.6.2.1 "Syntax - AudioSpecificConfig"
*/
static int put_audio_specific_config(AVCodecContext *avctx, int chcfg)
static int put_audio_specific_config(AVCodecContext *avctx)
{
PutBitContext pb;
AACEncContext *s = avctx->priv_data;
int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));
const int max_size = 32;
avctx->extradata = av_mallocz(max_size);
@@ -352,7 +380,7 @@ static int put_audio_specific_config(AVCodecContext *avctx, int chcfg)
init_put_bits(&pb, avctx->extradata, max_size);
put_bits(&pb, 5, s->profile+1); //profile
put_bits(&pb, 4, s->samplerate_index); //sample rate index
put_bits(&pb, 4, chcfg);
put_bits(&pb, 4, channels);
//GASpecificConfig
put_bits(&pb, 1, 0); //frame length - 1024 samples
put_bits(&pb, 1, 0); //does not depend on core coder
@@ -577,222 +605,6 @@ static void apply_intensity_stereo(ChannelElement *cpe)
}
}
/* Intensity stereo is only allowed when its irreducible image error */
#define NMR_IS_IMG_GATE 0.5f
/* Frequency in Hz for the lower limit of intensity stereo */
#define NMR_IS_LOW_LIMIT 6100
/* Rate ceiling (bits/sample/channel) above which intensity is skipped, ~145kbps */
#define NMR_IS_MAXBPS 1.52f
/* The rate ceiling is lifted on hard-to-code frames. The signal is the bit
* reservoir going into deficit: a negative fill means the trellis is spending
* more than the nominal rate to hold quality (operating lambda has climbed). */
#define NMR_IS_FILLGAIN 0.27f
#define NMR_IS_FILLMAX 0.40f
/* M/S thresholds: a band is recoded as mid+side when the side is negligible */
#define NMR_MS_EQUIV 0.01f
#define NMR_MS_MASK 0.0f
/* PNS-stereo decorrelation gate: a band may be noise-substituted in a CPE only if its
* side energy is at least this fraction of its mid energy, i.e. the image is genuinely
* wide (channels decorrelated). PNS renders uncorrelated noise per channel, so it only
* preserves the image on already-wide bands; a much stricter bar than I/S (which can
* collapse correlated bands). Lower = more PNS / more imaging risk. */
#define NMR_PNS_STEREO_DECORR 0.6f
/* Recode one band's window group as mid+side in place, updating the psy band
* energies/thresholds to the M/S spectra. The threshold is halved as a coarse guard
* against L/R unmasking of the independently-quantized M/S noise (M/S is a lossless
* rotation but lossy coding). Used for the M/S decision and the intensity fallback. */
static void nmr_apply_ms_band(AACEncContext *s, ChannelElement *cpe,
int w, int g, int start, int len, int gl)
{
SingleChannelElement *sce0 = &cpe->ch[0];
SingleChannelElement *sce1 = &cpe->ch[1];
cpe->ms_mask[w*16+g] = 1;
for (int w2 = 0; w2 < gl; w2++) {
FFPsyBand *b0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
FFPsyBand *b1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
float *L = sce0->coeffs + start + (w+w2)*128;
float *R = sce1->coeffs + start + (w+w2)*128;
float em = 0.0f, es = 0.0f;
for (int i = 0; i < len; i++) {
float m = (L[i] + R[i]) * 0.5f;
R[i] = m - R[i]; L[i] = m;
em += L[i]*L[i]; es += R[i]*R[i];
}
b0->threshold = b1->threshold = FFMIN(b0->threshold, b1->threshold) * 0.5f;
b0->energy = em; b1->energy = es;
}
}
/* Intensity-stereo perceptual test for one band's window group: collapse the pair
* to a single carrier (L + p*R)*scale that the decoder rescales per channel, and
* check that the irreducible image error, which no bit budget can reduce, is
* masked in both channels. On success returns 1 and fills the carrier scale, the
* decoder's R/carrier ratio sr_, and the phase p. The caller restricts this to HF
* bands with energy in both channels. */
static int nmr_is_image_masked(AACEncContext *s, ChannelElement *cpe,
int w, int g, int start, int len, int gl,
float ener0, float ener1, float dot,
float minthr0, float minthr1,
float *scale_out, float *sr_out, int *p_out)
{
int p = dot >= 0.0f ? 1 : -1;
float ener01 = ener0 + ener1 + 2*p*dot; /* energy of L + p*R */
if (ener01 <= FLT_MIN)
return 0;
float scale = sqrtf(ener0 / ener01); /* carrier = (L + p*R)*scale */
float sr_ = sqrtf(ener1 / ener0); /* decoder: R = p*sr_*carrier */
float img0 = 0.0f, img1 = 0.0f;
for (int w2 = 0; w2 < gl; w2++) {
const float *L = cpe->ch[0].coeffs + start + (w+w2)*128;
const float *R = cpe->ch[1].coeffs + start + (w+w2)*128;
for (int i = 0; i < len; i++) {
float c = (L[i] + p*R[i]) * scale;
float dl = L[i] - c, dr = R[i] - p*sr_*c;
img0 += dl*dl; img1 += dr*dr;
}
}
if (img0 >= NMR_IS_IMG_GATE * minthr0 * gl ||
img1 >= NMR_IS_IMG_GATE * minthr1 * gl)
return 0;
*scale_out = scale; *sr_out = sr_; *p_out = p;
return 1;
}
/* Recode one band's window group as intensity stereo in place: replace L with the
* carrier, zero R, signal the phase via the side channel's band type, and fold the
* pair's masking into the surviving (carrier) channel. */
static void nmr_apply_is_band(AACEncContext *s, ChannelElement *cpe,
int w, int g, int start, int len, int gl,
float scale, float sr_, int p,
float ener0, float ener1)
{
cpe->is_mask[w*16+g] = 1;
cpe->ch[0].is_ener[w*16+g] = scale;
cpe->ch[1].is_ener[w*16+g] = ener0 / ener1;
cpe->ch[1].band_type[w*16+g] = p > 0 ? INTENSITY_BT : INTENSITY_BT2;
for (int w2 = 0; w2 < gl; w2++) {
FFPsyBand *b0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
FFPsyBand *b1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
float *L = cpe->ch[0].coeffs + start + (w+w2)*128;
float *R = cpe->ch[1].coeffs + start + (w+w2)*128;
float ec = 0.0f;
for (int i = 0; i < len; i++) {
L[i] = (L[i] + p*R[i]) * scale;
R[i] = 0.0f;
ec += L[i]*L[i];
}
b0->threshold = FFMIN(b0->threshold, b1->threshold / FFMAX(sr_*sr_, 1e-9f));
b0->energy = ec; b1->energy = 0.0f;
}
}
/*
* Per-band stereo-mode decision (L/R vs M/S vs intensity) for the NMR coder,
* made before quantization from the psychoacoustic model alone, so the
* quantizer search allocates natively on the spectra that are actually coded.
*/
static void nmr_decide_stereo(AACEncContext *s, ChannelElement *cpe)
{
SingleChannelElement *sce0 = &cpe->ch[0];
SingleChannelElement *sce1 = &cpe->ch[1];
IndividualChannelStream *ics = &sce0->ics;
const AVCodecContext *avctx = s->psy.avctx;
const float freq_mult = avctx->sample_rate / (1024.0f / ics->num_windows) / 2.0f;
const float bps = avctx->bit_rate > 0 ?
(float)avctx->bit_rate / avctx->sample_rate / avctx->ch_layout.nb_channels : 0.0f;
int is_count = 0;
/* Stereo decision, with no bitrate dependence. Start from full L/R and depart from
* it only where the change is inaudible. M/S and I/S differ in what they trade:
* M/S recodes the pair as mid+side -- an invertible rotation, but the M and S
* are quantized independently, so it is lossy coding whose noise un-mixes
* back to L/R. Used where it barely changes the result (the side is
* negligible vs the mid, so it is ~equivalent to L/R at the same rate) --
* OR where the doubled side energy is masked.
* I/S drops the side phase and keeps its energy, where the residual image error
* is masked. Used for the decorrelated HF that M/S cannot help.
* Both tests are content/perceptual and frame-stable, so the image holds. */
/* I/S rate gate: eligible at/below ~128 kbps, with the ceiling lifted on hard
* frames (bit reservoir in deficit) so a starved high-rate passage can still
* call on intensity. Where an I/S candidate is found but IS is not eligible, fall
* back to M/S: not free, but ~equivalent to L/R there and it lets the energy
* compact into the mid. */
const float rate_frame = avctx->bit_rate * 1024.0f / FFMAX(avctx->sample_rate, 1);
const float deficit = (s->nmr && rate_frame > 0.0f)
? FFMAX(0.0f, -(float)s->nmr->rc_fill / rate_frame) : 0.0f;
const float is_bonus = FFMIN(NMR_IS_FILLMAX, NMR_IS_FILLGAIN * deficit);
const int allow_is = s->options.intensity_stereo && bps < NMR_IS_MAXBPS + is_bonus;
for (int w = 0; w < ics->num_windows; w += ics->group_len[w]) {
int start = 0;
for (int g = 0; g < ics->num_swb; start += ics->swb_sizes[g++]) {
int len = ics->swb_sizes[g], gl = ics->group_len[w];
float ener0 = 0.0f, ener1 = 0.0f, dot = 0.0f, es_tot = 0.0f, em_tot = 0.0f;
float minthr0 = FLT_MAX, minthr1 = FLT_MAX;
cpe->is_mask[w*16+g] = 0;
cpe->ms_mask[w*16+g] = 0;
for (int w2 = 0; w2 < gl; w2++) {
FFPsyBand *b0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
FFPsyBand *b1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
const float *L = sce0->coeffs + start + (w+w2)*128;
const float *R = sce1->coeffs + start + (w+w2)*128;
float el = 0.0f, er = 0.0f, em = 0.0f, es = 0.0f, d = 0.0f;
for (int i = 0; i < len; i++) {
float m = (L[i] + R[i]) * 0.5f;
float sv = m - R[i];
el += L[i]*L[i]; er += R[i]*R[i];
em += m*m; es += sv*sv; d += L[i]*R[i];
}
ener0 += el; ener1 += er; dot += d; es_tot += es; em_tot += em;
minthr0 = FFMIN(minthr0, b0->threshold);
minthr1 = FFMIN(minthr1, b1->threshold);
}
float thr_g = FFMIN(minthr0, minthr1) * gl; /* group masking budget */
/* PNS-stereo reservation. Reserve a band for noise substitution only if it
* is noise-like in both channels (intersected can_pns) and clearly
* decorrelated (wide image). */
if (cpe->ch[0].can_pns[w*16+g] && cpe->ch[1].can_pns[w*16+g] &&
es_tot > NMR_PNS_STEREO_DECORR * em_tot)
continue;
cpe->ch[0].can_pns[w*16+g] = cpe->ch[1].can_pns[w*16+g] = 0;
int ms_ok = s->options.mid_side &&
(s->options.mid_side == 1 ||
es_tot < NMR_MS_EQUIV * em_tot ||
es_tot < NMR_MS_MASK * thr_g);
float scale, sr_; int p;
int is_ok = !ms_ok &&
start * freq_mult > NMR_IS_LOW_LIMIT &&
ener0 > FLT_MIN && ener1 > FLT_MIN &&
nmr_is_image_masked(s, cpe, w, g, start, len, gl,
ener0, ener1, dot, minthr0, minthr1,
&scale, &sr_, &p);
if (ms_ok) {
nmr_apply_ms_band(s, cpe, w, g, start, len, gl);
} else if (is_ok && allow_is) {
nmr_apply_is_band(s, cpe, w, g, start, len, gl,
scale, sr_, p, ener0, ener1);
is_count++;
} else if (is_ok && s->options.mid_side) {
nmr_apply_ms_band(s, cpe, w, g, start, len, gl);
}
/* else: keep full L/R stereo */
}
}
cpe->is_mode = !!is_count;
}
static void apply_mid_side_stereo(ChannelElement *cpe)
{
int w, w2, g, i;
@@ -1166,6 +978,12 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->psy.bitres.alloc /= chans;
}
s->cur_type = tag;
for (ch = 0; ch < chans; ch++) {
s->cur_channel = start_ch + ch;
if (s->options.pns && s->coder->mark_pns)
s->coder->mark_pns(s, avctx, &cpe->ch[ch]);
s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda);
}
if (chans > 1
&& wi[0].window_type[0] == wi[1].window_type[0]
&& wi[0].window_shape == wi[1].window_shape) {
@@ -1178,75 +996,26 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
}
}
}
const int use_tns = s->options.tns && s->coder->search_for_tns &&
s->coder->apply_tns_filt;
/* The NMR coder rate-controls itself and never re-quantizes, so TNS must run
* before the quantizer */
const int tns_first = s->options.coder == AAC_CODER_NMR;
if (tns_first && use_tns) {
for (ch = 0; ch < chans; ch++) {
sce = &cpe->ch[ch];
s->cur_channel = start_ch + ch;
/* mono: mark_pns before TNS so the region cap sees PNS bands. Stereo
* PNS is marked in its own block (below) after the stereo decision. */
if (chans == 1 && s->options.pns && s->coder->mark_pns)
s->coder->mark_pns(s, avctx, sce);
s->coder->search_for_tns(s, sce);
s->coder->apply_tns_filt(s, sce);
if (sce->tns.present)
tns_mode = 1;
}
}
/* NMR stereo PNS (imaging-safe). Mark each channel's noise-like bands on the
* original L/R psy, then keep PNS only where BOTH channels are noise-like. */
if (chans == 2 && cpe->common_window && tns_first &&
s->options.pns && s->coder->mark_pns) {
s->cur_channel = start_ch; s->coder->mark_pns(s, avctx, &cpe->ch[0]);
s->cur_channel = start_ch + 1; s->coder->mark_pns(s, avctx, &cpe->ch[1]);
for (int b = 0; b < 128; b++)
if (!cpe->ch[0].can_pns[b] || !cpe->ch[1].can_pns[b])
cpe->ch[0].can_pns[b] = cpe->ch[1].can_pns[b] = 0;
}
/* The NMR coder decides I/S and M/S BEFORE quantization, from the psy model,
* and the trellis then allocates natively on the coeffs actually coded. */
if (chans == 2 && cpe->common_window && s->options.coder == AAC_CODER_NMR &&
(s->options.mid_side || s->options.intensity_stereo)) {
s->cur_channel = start_ch;
nmr_decide_stereo(s, cpe);
}
for (ch = 0; ch < chans; ch++) {
s->cur_channel = start_ch + ch;
/* NMR PNS is mono-only */
if (s->options.pns && s->coder->mark_pns && !tns_first)
s->coder->mark_pns(s, avctx, &cpe->ch[ch]);
s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda);
}
for (ch = 0; ch < chans; ch++) { /* TNS (non-NMR) and PNS */
for (ch = 0; ch < chans; ch++) { /* TNS and PNS */
sce = &cpe->ch[ch];
s->cur_channel = start_ch + ch;
if (!tns_first && use_tns) {
if (s->options.tns && s->coder->search_for_tns)
s->coder->search_for_tns(s, sce);
if (s->options.tns && s->coder->apply_tns_filt)
s->coder->apply_tns_filt(s, sce);
if (sce->tns.present)
tns_mode = 1;
}
if (sce->tns.present)
tns_mode = 1;
if (s->options.pns && s->coder->search_for_pns)
s->coder->search_for_pns(s, avctx, sce);
}
s->cur_channel = start_ch;
if (s->options.intensity_stereo) { /* Intensity Stereo */
if (s->options.coder != AAC_CODER_NMR) { /* NMR: decided pre-search */
if (s->coder->search_for_is)
s->coder->search_for_is(s, avctx, cpe);
apply_intensity_stereo(cpe);
}
if (s->coder->search_for_is)
s->coder->search_for_is(s, avctx, cpe);
if (cpe->is_mode) is_mode = 1;
apply_intensity_stereo(cpe);
}
if (s->options.mid_side && s->options.coder != AAC_CODER_NMR) { /* Mid/Side stereo */
if (s->options.mid_side) { /* Mid/Side stereo */
if (s->options.mid_side == -1 && s->coder->search_for_ms)
s->coder->search_for_ms(s, cpe);
else if (cpe->common_window)
@@ -1274,19 +1043,11 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
break;
}
frame_bits = put_bits_count(&s->pb);
/* The NMR coder rate-controls itself (global-lambda reservoir servo):
* per-frame bits intentionally float around the nominal rate, so skip
* the lambda rate loop and only intervene on a hard overflow. */
if (s->options.coder == AAC_CODER_NMR && avctx->bit_rate_tolerance != 0 &&
frame_bits < 6144 * s->channels - 3)
break;
/* rate control stuff
* allow between the nominal bitrate, and what psy's bit reservoir says to target
* but drift towards the nominal bitrate always
*/
frame_bits = put_bits_count(&s->pb);
rate_bits = avctx->bit_rate * 1024 / avctx->sample_rate;
rate_bits = FFMIN(rate_bits, 6144 * s->channels - 3);
too_many_bits = FFMAX(target_bits, rate_bits);
@@ -1350,80 +1111,18 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
}
} while (1);
/* tool-usage stats over the final per-band decisions of this frame */
for (i = 0; i < s->chan_map[0]; i++) {
int etag = s->chan_map[i + 1], echans = etag == TYPE_CPE ? 2 : 1;
ChannelElement *ce = &s->cpe[i];
IndividualChannelStream *ics = &ce->ch[0].ics;
for (ch = 0; ch < echans; ch++) { /* per-channel frame stats */
int is_short = ce->ch[ch].ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE;
s->stat_chans++;
if (is_short)
s->stat_short++;
if (ce->ch[ch].tns.present) {
if (is_short) s->stat_tns_short++;
else s->stat_tns_long++;
}
}
for (w = 0; w < ics->num_windows; w += ics->group_len[w]) {
for (int g = 0; g < ics->num_swb; g++) {
int idx = w*16 + g, coded = 0;
for (ch = 0; ch < echans; ch++) {
SingleChannelElement *sce = &ce->ch[ch];
if (sce->zeroes[idx] && sce->band_type[idx] == 0)
continue;
s->stat_ch_bands++;
if (sce->band_type[idx] == NOISE_BT)
s->stat_pns++;
coded = 1;
}
if (etag == TYPE_CPE && coded) {
s->stat_cpe_bands++;
if (ce->ms_mask[idx]) s->stat_ms++;
if (ce->is_mask[idx]) s->stat_is++;
}
}
}
}
put_bits(&s->pb, 3, TYPE_END);
flush_put_bits(&s->pb);
s->last_frame_pb_count = put_bits_count(&s->pb);
/* NMR rate accounting: how many bits the frame really took beyond what the
* trellis counted; feeds the next frame's budget correction */
if (s->nmr) {
int counted = 0;
for (i = 0; i < s->channels; i++)
counted += s->nmr->counted[i];
if (counted > 0) {
float side = (float)s->last_frame_pb_count - counted;
if (s->nmr->side_inited) {
s->nmr->side_ema += 0.125f * (side - s->nmr->side_ema);
} else {
s->nmr->side_ema = side;
s->nmr->side_inited = 1;
}
}
}
avpkt->size = put_bytes_output(&s->pb);
s->lambda_sum += (s->nmr && s->nmr->lam_rc > 0.0f) ? s->nmr->lam_rc : s->lambda;
s->lambda_sum += s->lambda;
s->lambda_count++;
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
int discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
if (discard_padding > 0) {
uint8_t *side_data =
av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
AV_WL32(side_data + 4, discard_padding);
}
avpkt->flags |= AV_PKT_FLAG_KEY;
*got_packet_ptr = 1;
@@ -1434,15 +1133,7 @@ static av_cold int aac_encode_end(AVCodecContext *avctx)
{
AACEncContext *s = avctx->priv_data;
av_log(avctx, AV_LOG_INFO,
"Qavg: %.3f Tr: %.1f%% TNS(L): %.1f%% TNS(S): %.1f%% M/S: %.1f%% I/S: %.1f%% PNS: %.1f%%\n",
s->lambda_count ? s->lambda_sum / s->lambda_count : NAN,
s->stat_chans ? 100.0 * s->stat_short / s->stat_chans : 0.0,
s->stat_chans - s->stat_short ? 100.0 * s->stat_tns_long / (s->stat_chans - s->stat_short) : 0.0,
s->stat_short ? 100.0 * s->stat_tns_short / s->stat_short : 0.0,
s->stat_cpe_bands ? 100.0 * s->stat_ms / s->stat_cpe_bands : 0.0,
s->stat_cpe_bands ? 100.0 * s->stat_is / s->stat_cpe_bands : 0.0,
s->stat_ch_bands ? 100.0 * s->stat_pns / s->stat_ch_bands : 0.0);
av_log(avctx, AV_LOG_INFO, "Qavg: %.3f\n", s->lambda_count ? s->lambda_sum / s->lambda_count : NAN);
av_tx_uninit(&s->mdct1024);
av_tx_uninit(&s->mdct128);
@@ -1451,7 +1142,6 @@ static av_cold int aac_encode_end(AVCodecContext *avctx)
av_freep(&s->buffer.samples);
av_freep(&s->cpe);
av_freep(&s->fdsp);
av_freep(&s->nmr);
ff_af_queue_close(&s->afq);
return 0;
}
@@ -1485,12 +1175,6 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s)
for(ch = 0; ch < s->channels; ch++)
s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch;
if (s->options.coder == AAC_CODER_NMR) {
s->nmr = av_mallocz(sizeof(*s->nmr));
if (!s->nmr)
return AVERROR(ENOMEM);
}
return 0;
}
@@ -1498,7 +1182,6 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
{
AACEncContext *s = avctx->priv_data;
int i, ret = 0;
int chcfg;
const uint8_t *sizes[2];
uint8_t grouping[AAC_MAX_CHANNELS];
int lengths[2];
@@ -1513,8 +1196,8 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
s->channels = avctx->ch_layout.nb_channels;
s->needs_pce = 1;
for (chcfg = 1; chcfg < FF_ARRAY_ELEMS(aac_normal_chan_layouts); chcfg++) {
if (!av_channel_layout_compare(&avctx->ch_layout, &aac_normal_chan_layouts[chcfg])) {
for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) {
if (!av_channel_layout_compare(&avctx->ch_layout, &aac_normal_chan_layouts[i])) {
s->needs_pce = s->options.pce;
break;
}
@@ -1534,10 +1217,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
s->pce = aac_pce_configs[i];
s->reorder_map = s->pce.reorder_map;
s->chan_map = s->pce.config_map;
chcfg = 0;
} else {
s->reorder_map = aac_chan_maps[chcfg - 1];
s->chan_map = aac_chan_configs[chcfg - 1];
s->reorder_map = aac_chan_maps[s->channels - 1];
s->chan_map = aac_chan_configs[s->channels - 1];
}
if (!avctx->bit_rate) {
@@ -1587,34 +1269,6 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (s->channels > 3)
s->options.mid_side = 0;
/* Coding bandwidth, fixed at init time */
if (avctx->cutoff > 0) {
s->bandwidth = avctx->cutoff;
} else {
int frame_br = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
(avctx->bit_rate / 2.0f * (s->lambda / 120.f) * 1.5f) :
(avctx->bit_rate / avctx->ch_layout.nb_channels);
/* For NMR, the rate to bandwidth conversion was tuned to maximize metrics
* over a variable cutoff x bitrate combo */
if (s->options.coder == AAC_CODER_NMR && frame_br >= 32000) {
static const int rates[] = { 32000, 48000, 64000, 96000, 192000 };
static const int bws[] = { 14000, 15000, 16000, 18000, 20000 };
int bw_i = 0;
for (; bw_i < FF_ARRAY_ELEMS(rates) - 2 && frame_br > rates[bw_i + 1]; bw_i++);
s->bandwidth = bws[bw_i] + (int)((int64_t)(bws[bw_i + 1] - bws[bw_i]) *
(frame_br - rates[bw_i]) / (rates[bw_i + 1] - rates[bw_i]));
s->bandwidth = FFMIN3(s->bandwidth, 22000, avctx->sample_rate / 2);
} else {
if (s->options.pns || s->options.intensity_stereo)
frame_br *= 1.15f;
s->bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_br, 1,
avctx->sample_rate));
}
s->bandwidth = FFMIN(FFMAX(s->bandwidth, 8000), avctx->sample_rate / 2);
}
// Initialize static tables
ff_aac_float_common_init();
@@ -1624,7 +1278,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if ((ret = alloc_buffers(avctx, s)) < 0)
return ret;
if ((ret = put_audio_specific_config(avctx, chcfg)))
if ((ret = put_audio_specific_config(avctx)))
return ret;
sizes[0] = ff_aac_swb_size_1024[s->samplerate_index];
@@ -1634,7 +1288,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
for (i = 0; i < s->chan_map[0]; i++)
grouping[i] = s->chan_map[i + 1] == TYPE_CPE;
if ((ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths,
s->chan_map[0], grouping, s->bandwidth)) < 0)
s->chan_map[0], grouping)) < 0)
return ret;
ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON);
s->random_state = 0x1f2e3d4c;
@@ -1648,16 +1302,14 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
static const AVOption aacenc_options[] = {
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_NMR}, 0, AAC_CODER_NB-1, AACENC_FLAGS, .unit = "coder"},
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, .unit = "coder"},
{"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"fast", "Fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"nmr", "Noise-to-mask ratio scalefactor trellis", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_NMR}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "coder"},
{"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS},
{"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
{"aac_nmr_speed", "NMR coder speed level: 0 = slowest/best, higher trades quality for speed", offsetof(AACEncContext, options.nmr_speed), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, AACENC_FLAGS},
FF_AAC_PROFILE_OPTS
{NULL}
};
+3 -35
View File
@@ -44,7 +44,6 @@
typedef enum AACCoder {
AAC_CODER_TWOLOOP,
AAC_CODER_FAST,
AAC_CODER_NMR,
AAC_CODER_NB,
}AACCoder;
@@ -70,7 +69,6 @@ typedef struct AACEncOptions {
int pce;
int mid_side;
int intensity_stereo;
int nmr_speed; ///< NMR coder speed level: 0 = slowest/best, higher is faster
} AACEncOptions;
/**
@@ -167,33 +165,11 @@ typedef struct AACQuantizeBandCostCacheEntry {
uint16_t generation;
} AACQuantizeBandCostCacheEntry;
/** per-band scalefactor candidates above the finest codeable sf (NMR coder) */
#define NMR_NCAND 96
/**
* NMR coder per-band candidate cost curves (~96 KiB) and rate-control carry-over
*/
typedef struct AACNMRCurves {
float nd[128][NMR_NCAND]; ///< dist / threshold per candidate
int nb[128][NMR_NCAND]; ///< spectral bits per candidate
float lam[16]; ///< per-channel operating lambda of the previous frame, 0 = none yet
int counted[16]; ///< per-channel bits the trellis accounted for in the last solve
float side_ema; ///< running estimate of real-minus-counted bits per frame
int side_inited; ///< side_ema holds a measurement
int64_t rc_frame_num; ///< frame the reservoir was last advanced for
float lam_rc; ///< global-lambda rate control: operating lambda, 0 until bootstrapped
int rc_fill; ///< virtual bit reservoir fill, + = bits saved vs nominal
int frames_since_short; ///< long-block frames since the last short run (the "gap"): large = isolated transient
int prev_was_short; ///< previous frame was a short block (for run-start detection)
float run_burst; ///< transient bit-burst factor, set at run start and held across the short run
} AACNMRCurves;
typedef struct AACPCEInfo {
AVChannelLayout layout;
uint8_t num_ele[4]; ///< front, side, back, lfe
uint8_t pairing[3][8]; ///< front, side, back
uint8_t index[4][8]; ///< front, side, back, lfe
int num_ele[4]; ///< front, side, back, lfe
int pairing[3][8]; ///< front, side, back
int index[4][8]; ///< front, side, back, lfe
uint8_t config_map[16]; ///< configs the encoder's channel specific settings
uint8_t reorder_map[16]; ///< maps channels from lavc to aac order
} AACPCEInfo;
@@ -218,7 +194,6 @@ typedef struct AACEncContext {
LPCContext lpc; ///< used by TNS
int samplerate_index; ///< MPEG-4 samplerate index
int channels; ///< channel count
int bandwidth; ///< coding bandwidth in Hz, fixed at init; the psy model and the coders' band cutoff agree on it
const uint8_t *reorder_map; ///< lavc to aac reorder map
const uint8_t *chan_map; ///< channel configuration map
@@ -231,12 +206,6 @@ typedef struct AACEncContext {
int last_frame_pb_count; ///< number of bits for the previous frame
float lambda_sum; ///< sum(lambda), for Qvg reporting
int lambda_count; ///< count(lambda), for Qvg reporting
/* tool-usage stats, reported at close: per-coded-band for PNS (channel bands),
* per-coded-pair-band for M/S and I/S (CPE bands) */
uint64_t stat_ch_bands, stat_pns; ///< coded channel-bands, of which PNS
uint64_t stat_cpe_bands, stat_ms, stat_is; ///< coded CPE pair-bands, of which M/S, I/S
uint64_t stat_chans, stat_short; ///< coded channels, of which short-block (transient)
uint64_t stat_tns_long, stat_tns_short; ///< TNS-active channels among long / short blocks
enum RawDataBlockType cur_type; ///< channel group type cur_channel belongs to
AudioFrameQueue afq;
@@ -247,7 +216,6 @@ typedef struct AACEncContext {
AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost
AACEncDSPContext aacdsp;
AACNMRCurves *nmr; ///< NMR coder scratch (NULL unless coder == nmr)
struct {
float *samples;
+52 -135
View File
@@ -41,13 +41,9 @@
/* We really need the bits we save here elsewhere */
#define TNS_ENABLE_COEF_COMPRESSION
/* Apple-derived TNS: weighted-spectrum predictor, accepted only if the measured
* post-quantization prediction gain clears a block-type-dependent bar (Apple RE). */
#define TNS_PREDGAIN_GATE 1.4f /* first gate: predicted LPC gain */
#define TNS_PG_C1_LONG 1.4f /* min measured gain, long blocks */
#define TNS_PG_C1_SHORT 3.2f /* min measured gain, short blocks */
#define TNS_PG_CLAMP 6.0f /* upper bound: poles near unit circle → noise blowup */
#define TNS_WEIGHT_FLOOR 0.01f /* per-bin masking floor for the weighted spectrum */
/* TNS will only be used if the LPC gain is within these margins */
#define TNS_GAIN_THRESHOLD_LOW 1.4f
#define TNS_GAIN_THRESHOLD_HIGH 1.16f*TNS_GAIN_THRESHOLD_LOW
static inline int compress_coeffs(int *coef, int order, int c_bits)
{
@@ -66,7 +62,11 @@ static inline int compress_coeffs(int *coef, int order, int c_bits)
return 1;
}
/** Encode TNS data. */
/**
* Encode TNS data.
* Coefficient compression is simply not lossless as it should be
* on any decoder tested and as such is not active.
*/
void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce)
{
TemporalNoiseShaping *tns = &sce->tns;
@@ -98,28 +98,15 @@ void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce)
}
}
/* Cap the TNS band range at the first PNS band to avoid TNS+PNS conflicts. */
static int tns_max_nonpns(const SingleChannelElement *sce, int mmm)
{
for (int w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w])
for (int g = 0; g < mmm; g++)
if (sce->band_type[w*16+g] == NOISE_BT) { mmm = g; break; }
return mmm;
}
/* Apply TNS filter */
void ff_aac_apply_tns(AACEncContext *s, SingleChannelElement *sce)
{
TemporalNoiseShaping *tns = &sce->tns;
IndividualChannelStream *ics = &sce->ics;
int w, filt, m, i, top, order, bottom, start, end, size, inc;
const int mmm = tns_max_nonpns(sce, FFMIN(ics->tns_max_bands, ics->max_sfb));
const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
float lpc[TNS_MAX_ORDER];
/* TNS predicts from the post-M/S and post-I/S coefficients. */
float hist[1024];
memcpy(hist, sce->coeffs, sizeof(hist));
for (w = 0; w < ics->num_windows; w++) {
bottom = ics->num_swb;
for (filt = 0; filt < tns->n_filt[w]; filt++) {
@@ -147,7 +134,7 @@ void ff_aac_apply_tns(AACEncContext *s, SingleChannelElement *sce)
/* AR filter */
for (m = 0; m < size; m++, start += inc) {
for (i = 1; i <= FFMIN(m, order); i++) {
sce->coeffs[start] += lpc[i-1]*hist[start - i*inc];
sce->coeffs[start] += lpc[i-1]*sce->pcoeffs[start - i*inc];
}
}
}
@@ -174,8 +161,9 @@ static inline void quantize_coefs(double *coef, int *idx, float *lpc, int order,
void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce)
{
TemporalNoiseShaping *tns = &sce->tns;
int w, count = 0;
const int mmm = tns_max_nonpns(sce, FFMIN(sce->ics.tns_max_bands, sce->ics.max_sfb));
int w, g, count = 0;
double gain, coefs[MAX_LPC_ORDER];
const int mmm = FFMIN(sce->ics.tns_max_bands, sce->ics.max_sfb);
const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE;
const int c_bits = is8 ? TNS_Q_BITS_IS8 == 4 : TNS_Q_BITS == 4;
const int sfb_start = av_clip(tns_min_sfb[is8][s->samplerate_index], 0, mmm);
@@ -186,127 +174,56 @@ void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce)
const int sfb_len = sfb_end - sfb_start;
const int coef_len = sce->ics.swb_offset[sfb_end] - sce->ics.swb_offset[sfb_start];
const int n_filt = is8 ? 1 : order != TNS_MAX_ORDER ? 2 : 3;
const int ord_g = order / n_filt;
/* Apple's accept bar (minimum measured prediction gain): higher on short blocks,
* where a weak filter's shaped-noise tail spreads across the 50% overlap. */
const float c1 = is8 ? TNS_PG_C1_SHORT : TNS_PG_C1_LONG;
FFPsyBand *const psy_bands = &s->psy.ch[s->cur_channel].psy_bands[0];
if (coef_len <= 0 || sfb_len <= 0) {
sce->tns.present = 0;
return;
}
/* time-domain window length backing one coding window: a long MDCT block is
* fed 2048 windowed samples (current 1024 + overlap), each short block 256. */
const int tlen = is8 ? 256 : 2048;
for (w = 0; w < sce->ics.num_windows; w++) {
int filt, any = 0;
float en[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int oc_start = 0;
int coef_start = sce->ics.swb_offset[sfb_start];
/* The filter gets ran in the direction of the signal's *temporal* energy,
* so the quantization noise stays in the loud masked part rather than spilling
* into the quiet part. */
const float *tw = sce->ret_buf + w*tlen;
float e_early = 0.0f, e_late = 0.0f;
int ti;
for (ti = 0; ti < tlen/2; ti++)
e_early += tw[ti]*tw[ti];
for (; ti < tlen; ti++)
e_late += tw[ti]*tw[ti];
const int tdir = e_early > e_late;
/* Walk the frequency regions exactly as the decoder does: filter 0 is the
* topmost band region, each subsequent filter covers the next region down,
* clamped to mmm. Each filter gets its own LPC over its own region. */
int top_sfb = sce->ics.num_swb;
for (filt = 0; filt < n_filt; filt++) {
double coefs[MAX_LPC_ORDER];
float wspec[1024], tmp[1024], lpc_q[TNS_MAX_ORDER];
int len_sfb = (filt == n_filt - 1) ? sfb_len - filt*(sfb_len/n_filt)
: sfb_len/n_filt;
int bot_sfb = FFMAX(0, top_sfb - len_sfb);
int g_lo = FFMIN(bot_sfb, mmm), g_hi = FFMIN(top_sfb, mmm);
int c_lo = sce->ics.swb_offset[g_lo];
int c_hi = sce->ics.swb_offset[g_hi];
int clen = c_hi - c_lo;
const int dir = slant != 2 ? slant : tdir;
float gain, orig_e = 0.0f, filt_e = 0.0f;
int m, i, g, inc, st;
tns->length[w][filt] = len_sfb;
tns->order[w][filt] = 0; /* default: region carries no filter */
top_sfb = bot_sfb;
if (clen <= 2*ord_g) /* too short for a stable order-ord_g LPC */
continue;
/* Fit LPC on the perceptually-weighted spectrum X/sqrt(thr), floored
* to avoid a near-zero threshold blowing up a single bin (Apple). */
{
float maxrms = 0.0f, floorrms;
int k;
for (g = g_lo; g < g_hi; g++) {
int s0 = sce->ics.swb_offset[g], s1 = sce->ics.swb_offset[g+1];
float rms = sqrtf(FFMAX(psy_bands[w*16 + g].threshold, 0.0f) /
FFMAX(s1 - s0, 1));
maxrms = FFMAX(maxrms, rms);
}
floorrms = FFMAX(maxrms * TNS_WEIGHT_FLOOR, 1e-9f);
for (g = g_lo; g < g_hi; g++) {
int s0 = sce->ics.swb_offset[g], s1 = sce->ics.swb_offset[g+1];
float rms = sqrtf(FFMAX(psy_bands[w*16 + g].threshold, 0.0f) /
FFMAX(s1 - s0, 1));
float wgt = 1.0f / FFMAX(rms, floorrms);
for (k = s0; k < s1; k++)
wspec[k - c_lo] = sce->coeffs[w*128 + k] * wgt;
}
/* Short blocks: unwindowed fit; Hann window zeros the edges of the
* tiny region, wrecking the LPC. Long blocks keep the window. */
gain = ff_lpc_calc_ref_coefs_f(&s->lpc, wspec, clen, ord_g, coefs, !is8);
if (n_filt == 2) {
for (g = sfb_start; g < sce->ics.num_swb && g <= sfb_end; g++) {
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[w*16+g];
if (g > sfb_start + (sfb_len/2))
en[1] += band->energy; /* End */
else
en[0] += band->energy; /* Start */
}
/* Reject below the first gate and above the clamp (poles near unit circle). */
if (!isfinite(gain) || gain < TNS_PREDGAIN_GATE || gain > TNS_PG_CLAMP)
continue;
/* Negate: ff_lpc_calc_ref_coefs_f sign convention is opposite to what
* ff_aac_apply_tns's MA filter needs; fed unnegated, it anti-whitens. */
for (i = 0; i < ord_g; i++)
coefs[i] = -coefs[i];
/* Quantize, then build the decoder's direct-form LPC. */
quantize_coefs(coefs, tns->coef_idx[w][filt], tns->coef[w][filt],
ord_g, c_bits);
compute_lpc_coefs(tns->coef[w][filt], 0, ord_g, lpc_q, 0, 0, 0, NULL);
/* Apply the quantized filter to the weighted spectrum and measure gain. */
const float *msrc = wspec;
inc = dir ? -1 : 1;
st = dir ? clen - 1 : 0;
for (m = 0; m < clen; m++) {
int idx = st + m*inc;
float acc = msrc[idx];
for (i = 1; i <= FFMIN(m, ord_g); i++)
acc += lpc_q[i-1] * msrc[idx - i*inc];
tmp[idx] = acc;
en[2] = en[0];
} else {
for (g = sfb_start; g < sce->ics.num_swb && g <= sfb_end; g++) {
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[w*16+g];
if (g > sfb_start + (sfb_len/2) + (sfb_len/4))
en[2] += band->energy; /* End */
else if (g > sfb_start + (sfb_len/2) - (sfb_len/4))
en[1] += band->energy; /* Middle */
else
en[0] += band->energy; /* Start */
}
for (m = 0; m < clen; m++) {
orig_e += msrc[m]*msrc[m];
filt_e += tmp[m]*tmp[m];
}
filt_e = FFMAX(filt_e, 1e-9f);
/* Keep only if measured post-quantization gain clears C1 (Apple's outcome gate). */
if (orig_e < c1*filt_e)
continue;
tns->order[w][filt] = ord_g;
tns->direction[w][filt] = dir;
any = 1;
en[3] = en[0];
}
tns->n_filt[w] = any ? n_filt : 0;
if (any)
count++;
/* LPC */
gain = ff_lpc_calc_ref_coefs_f(&s->lpc, &sce->coeffs[w*128 + coef_start],
coef_len, order, coefs);
if (!order || !isfinite(gain) || gain < TNS_GAIN_THRESHOLD_LOW || gain > TNS_GAIN_THRESHOLD_HIGH)
continue;
tns->n_filt[w] = n_filt;
for (g = 0; g < tns->n_filt[w]; g++) {
tns->direction[w][g] = slant != 2 ? slant : en[g] < en[g + 1];
tns->order[w][g] = order/tns->n_filt[w];
tns->length[w][g] = sfb_len/tns->n_filt[w];
quantize_coefs(&coefs[oc_start], tns->coef_idx[w][g], tns->coef[w][g],
tns->order[w][g], c_bits);
oc_start += tns->order[w][g];
}
count++;
}
sce->tns.present = !!count;
}

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