Nellymoser expects the caller to set the samplerate, as it
doesn't read it from the bitstream. However the generic check
for this is bypassed as it has the AV_CODEC_CAP_CHANNEL_CONF
capability because it does set the channel configuration,
however that cap also bypasses the generic samplerate check.
This is mostly harmless as nellymoser doesn't care about the
samplerate, but since f566032bfd it would cause an AVERROR_BUG
to be returned to the caller, so better reject it outright in
the decoder.
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
(cherry picked from commit 23918b3200)
During USAC decoding (ff_aac_usac_decode_frame), configuration elements
can be mapped and instantiated via che_configure(). For newly allocated
ChannelElement structs, che_configure calls sbr_ctx_alloc_init() which
dynamically allocates ac->che[type][id]. However, che_configure did not
subsequently map the output pointer of the nested SingleChannelElement
elements back to their statically-sized internal ret_buf arrays, causing
a null pointer dereference during IMDCT windowing.
The fix explicitly initializes these pointers following allocation.
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
(cherry picked from commit 8319541103)
ff_dxva2_common_end_frame() adds a reference to the decoder to
frame->buf[], so that the decoder outlives the frames decoded with it.
It is called from the hwaccel end_frame() callback, which with frame
threading may run after ff_thread_finish_setup(). From that point on,
other threads may copy the frame: the H.264 decoder keeps a separate
AVFrame per picture in each thread and synchronizes them in
update_thread_context() with av_frame_replace(), which reads
frame->buf[] while the decoding thread may be writing to it. As noted
in fa77cb258b ("avcodec/h264dec: Fix data race when updating
decode_error_flags"), a decoding thread must not modify any field that
av_frame_ref() copies after ff_thread_finish_setup().
This has been observed as an intermittent access violation in
av_buffer_replace() when decoding H.264 with D3D11VA and frame
threading on Windows on Arm: the copying thread read a non-NULL
frame->buf[1] entry, but saw the fields of the AVBufferRef it points
to as zero, and dereferenced the NULL buffer pointer when incrementing
the reference count.
Store the decoder reference in FrameDecodeData.hwaccel_priv instead,
as nvdec does for its per-frame state. The decode data is attached to
frame->private_ref when the buffer is allocated, before
ff_thread_finish_setup(), and all references to the frame share it, so
update_thread_context() only takes a new reference to it. The decoder
reference is added to frame->buf[] by hwaccel_priv_post_process(),
which runs in the caller's thread when the frame is returned, so
returned frames keep the decoder alive. Since the decode data
is shared, the second field of a field pair no longer adds a second
decoder reference to the frame.
Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
(cherry picked from commit 538d10d187)
Leave the existing one for non decoder-specific, post processing usage.
With this, scenarios like nvdec decoding can work algonside lcevc enhancement application.
Signed-off-by: James Almer <jamrial@gmail.com>
ff_vk_find_struct returns const void *, so storing it in const void *drm_create_pnext
fixes the initialization warning but then dpb_hwfc->create_pnext = drm_create_pnext
assigns const void * to void *, triggering the same warning at that line. The right
fix is a (void *) cast at the call site, same as done for buf_pnext.
Also restrict the GetPhysicalDeviceImageFormatProperties2 verbose log in
try_export_flags to the DRM modifier path only: when has_mods is false the log
always printed mod[0]=0x0, which is misleading since no DRM modifier is involved.
Signed-off-by: Tymur Boiko <tboiko@nvidia.com>
(cherry picked from commit f7ca6f7481)
Assisted-by: Fairy
When mapping Vulkan Video frames to DMA-BUF, synchronize using an exportable
binary semaphore and sync_fd where supported. Submit a lightweight exec that
waits on each plane's timeline semaphore at the current value, signals a
SYNC_FD-exportable binary semaphore, then export with vkGetSemaphoreFdKHR.
Store that binary semaphore in AVVkFrameInternal and reuse it across maps
instead of creating and destroying each time: for
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, copy transference means a
successful vkGetSemaphoreFdKHR unsignals the semaphore like a wait, so it can
be signaled again on the next map submit. If export is unavailable, fall back
to vkWaitSemaphores.
Moved drm_sync_sem destroy to vulkan_free_internal
Export dma-buf fds with GetMemoryFdKHR for each populated f->mem[i], iterating
up to the sw_format plane count instead of stopping at the image count, so
multi-memory bindings are not skipped. Describe DRM layers using
max(sw planes, image count) and query subresource layout with the correct
aspect and image index when one VkImage backs multiple planes. Reference the
source hw_frames_ctx on the mapped frame and close dma-buf fds on failure paths.
For DMA-BUF-capable pools, honor VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT
from format export queries when binding memory. With DRM modifiers and a
video profile in create_pnext, preserve caller usage and image flags instead of
overwriting them from generic supported_usage probing; use the modifier list
create info when probing export flags for modifier tiling.
Include VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR from the output frames
context's usage together with DST (fixes
VUID-VkVideoBeginCodingInfoKHR-slotIndex-07245) instead of adding DPB usage
only when !is_current.
In ff_vk_decode_add_slice, pass VkVideoProfileListInfoKHR (from the output
frames context's create_pnext) as the pNext argument to
ff_vk_get_pooled_buffer instead of the full create_pnext chain. In
ff_vk_frame_params, set tiling to OPTIMAL only when it is not already
DRM_FORMAT_MODIFIER_EXT. In ff_vk_decode_init, when the output pool's
create_pnext includes VkImageDrmFormatModifierListCreateInfoEXT, initialize the
DPB pool with that modifier-list pNext and DRM_FORMAT_MODIFIER_EXT tiling;
otherwise use VkVideoProfileListInfoKHR and OPTIMAL as before. When
VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR is unset, the output
and DPB pools cannot use different layouts or tiling, so the DPB pool must
match the output pool.
Also fix av_hwframe_map ioctl sync_fd export, multi-planar semaphore handling,
and related failure-path cleanup.
Signed-off-by: Tymur Boiko <tboiko@nvidia.com>
(cherry picked from commit 25e187f849)
Assisted-by: Fairy
The decoder can't know where a seek landed, so the "delay_samples" way to
discard the decoder delay in the first frame is not truly viable, so it needs
to be removed.
Add a call to aacDecoder_DecodeFrame() with the AACDEC_CLRHIST flag set, as the
call to aacDecoder_SetParam() with the AAC_TPDEC_CLEAR_BUFFER setting was
seemingly not enough to truly flush all the fdkaac internal buffers.
Should fix issue #24527.
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit b894a6f7c1)
Shift timestamps when available, and take into account the caller requested
samples to be discarded alongside the decoder delay.
Should fix issue #24526.
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit c8595be8e6)
The code reads a mask afer this check, meaning it expects NATIVE order, not
others.
Signed-off-by: James Almer <jamrial@gmail.com>
(cherry picked from commit 7755d264bd)
H265RawVPS embedded hrd_parameters as an inline array of
HEVC_MAX_LAYER_SETS (1024) H265RawHRDParameters, making the structure
roughly 7.9 MB. CBS allocates the whole content structure for every VPS
NAL unit before parsing it, so a packet consisting of many tiny VPS NALs
forces gigabytes of allocations and triggers an out-of-memory condition.
Allocate hrd_parameters separately, sized to vps_num_hrd_parameters,
backed by an AVBufferRef registered as a second internal reference
offset on the VPS unit type. This shrinks the resident structure to tens
of kilobytes and bounds the hrd_parameters allocation by the amount that
is actually parsed.
Fixes: 472754452/clusterfuzz-testcase-minimized-ffmpeg_BSF_HEVC_METADATA_fuzzer-6379024978083840
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 d2dd0a0a8f)
This fixes overreads with libdav1d, because it provides
non-padded data in violation to the requirements of
the GetBits API.
Furthermore, using the GetBits API here is wasteful,
as the offsets here are known and the actual data to be copied
is even byte-aligned, allowing to use memcpy.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit f2e5eff3ff)
decode_zbuf() inflates zTXt (compressed text) and iCCP (ICC profile) chunk
payloads into an AVBPrint created with AV_BPRINT_SIZE_UNLIMITED and never
checks the decompressed size. A ~100 KB zTXt chunk of compressed zeros
expands to 100 MB; larger ratios or multiple chunks can exhaust memory.
Abort with AVERROR_INVALIDDATA once the decompressed output crosses a hard
cap (16 MiB).
Verified with a crafted PNG (1 KB compressed -> 100 MB decompressed): without
the patch the chunk fully decompresses, taking >100 MB; with the patch the
inflate loop aborts and the decoder logs "Compressed PNG chunk expands
beyond 16777216 bytes" / "Broken zTXt chunk" while the rest of the image
decodes normally.
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.
(cherry picked from commit 69bdb05f36)
The encoded session parameters buffer was never freed, and both
GetEncodedVideoSessionParametersKHR error paths returned err, which
is always 0 at that point, reporting success on failure.
(cherry picked from commit b672ae3905)
Co-Authored-by: Fable 5
Fixes: out of array access
Fixes: Af5rtPnOunVT
Found-by: Umar Pathan (Umar0x)
Signed-off-by: Umar Pathan <hello@umar.ac>
(cherry picked from commit a809a784ec)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes: out of array write
Found-by: Michael Niedermayer with Forgejo Fairy
(cherry picked from commit 68845e26f7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes: out of array write
Fixes: 9vZSLhhnp3ps
Found-by: Kai Martin, KG3N Research
(cherry picked from commit e058af88ab)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
At the time that this code was introduced into FFmpeg in April 2022 by commit
b9a25963f7, it was correct as written. The latest release of
lcms2 at the time was 2.13.1 in which `cmsDeleteContext(NULL)` was a no-op.
Since lcms2 version 2.15, released Mar 2023, the same call is no longer a no-op and
instead means destroy the global context. The new behavior is justifiable as being
consistent with the rest of lcms2's API, where passing NULL for a cmsContext argument
means operate on the global context. For example `cmsDupContext(NULL, ...)` constructs a
context duplicated from the global context; `cmsPluginTHR(NULL, ...)` registers a plugin
into the global context.
The upstream commit that introduced the behavior change for `cmsDeleteContext` is:
a9e4601ceb
In FFmpeg, the new behavior leads to a memory leak if `ff_icc_context_uninit` is ever
called on an `FFIccContext` without `ff_icc_context_init`. Here is why that can happen,
and here is how it leads to a memory leak.
Naively, uninitializing something which was never initialized seems like it shouldn't
happen, but in this case these contexts are *lazily* initialized and *unconditionally*
deinitialized. `FFIccContext` is a member of `AVCodecInternal`:
// libavcodec/internal.h:148-150
#if CONFIG_LCMS2
FFIccContext icc; /* used to read and write embedded ICC profiles */
#endif
It is initialized conditionally by the snippet of `detect_colorspace` shown below, or by
similary shaped code in libavcodec/encode.c. The `avci->icc.avctx` guards "has it already
been initialized". The early returns beforehand are codepaths for which `icc` will not be
initialized, and will remain all-zero as allocated by `av_mallocz` in
`ff_decode_internal_alloc`.
// libavcodec/decode.c:534-542
if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES))
return 0;
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
if (!sd || !sd->size)
return 0;
if (!avci->icc.avctx) {
ret = ff_icc_context_init(&avci->icc, avctx);
Later, `avci->icc` is uninitialized unconditionally by `ff_codec_close`:
// libavcodec/avcodec.c:447-480
if (avcodec_is_open(avctx)) {
...
#if CONFIG_LCMS2
ff_icc_context_uninit(&avci->icc);
#endif
So every codec closed without `AV_CODEC_FLAGS2_ICC_PROFILES`, or without an ICC side-data
packet, reaches `ff_icc_context_uninit` on a never-initialized context.
As part of `cmsDeleteContext(NULL)` destroying lcms2's global context, it runs
`cmsUnregisterPlugins()` and destroys `globalContext.MemPool`. Since the global context is
shared by every user of lcms2 in the process, closing an FFmpeg codec silently tears down
unrelated libraries' lcms2 state. The most visible symptom is that
`_cmsRegisterMutexPlugin(NULL, NULL)` nulls out the mutex callbacks, after which
`cmsCloseProfile()` leaks each profile's `UsrMutex` and profiles opened later are left
without any locking at all.
The fix is to delete only contexts created by FFmpeg.
Signed-off-by: David Tolnay <dtolnay@gmail.com>
(cherry picked from commit 705286a8a7)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
When the first slice of a picture is skipped, an undecodable RASL
after a seek or avctx->skip_frame, the remaining slices were still
parsed against the stale context and failed the PPS change, dependent
slice, or missing first slice checks, logging a decoding error per
slice. Drop them before parsing instead.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit e5eb7581dd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
In VVC, there are two schemes for addressing reference pictures in
the DPB:
1. Normally, the POC of the reference picture is signaled using a delta
from the current picture POC.
2. In the case of long-term reference pictures (LTRPs), which may be far
away from the current POC, the absolute value of the LTRP POC is
signalled. This scheme has two sub-schemes:
a. Signalling the entirety of the absolute value of the LTRP
POC would be expensive, so in most cases we only signal the
sps_log2_max_pic_order_cnt_lsb_minus4 + 4 least-significant bits
of the LTRP POC.
b. In the case of a collision in the least-significant bits,
the full POC is signalled.
Both schemes are implemented in find_ref_idx. The use_msb parameter
of find_ref_idx is nonzero in the case of schemes 1 and 2b, and zero in
the case of scheme 2a.
This commit fixes a bug in scheme 2a. The issue arises from the fact
that the current picture is stored in the DPB at the time find_ref_idx
is invoked in FFmpeg's implementation, whereas in the specification the
current picture is not yet considered part of the DPB. The current
picture may have a POC which shares least-significant bits with an LTRP.
The specification does not identify this as a collision however (see the
condition in 7.4.10, under the semantics of
delta_poc_msb_cycle_present_flag), and so scheme 2a is used rather than
scheme 2b. If the current frame precedes the correct LTRP in the DPB,
FFmpeg's implementation then interprets the signalling to mean a frame
which references itself. The problematic callsite identifies this as an
issue and returns an AVERROR_INVALIDDATA, but this scenario can occur in
valid bitstreams. For example, the conformance bitstream
LTRP_A_ERICSSON_3 has one such instance. FFmpeg gets away with decoding
it currently because the LTRP precedes the current picture in the DPB,
but this is by chance rather than design.
The commit addresses this issue by skipping over the current picture
inside the main loop of find_ref_idx. An unambiguous reference to the
current picture is still syntactically possible but illegal when using
scheme 2b. The handling of this case is moved from find_ref_idx to the
caller, which allows for simplifying find_ref_idx.
Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 2b3609ab61)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The VC-1 mc prediction for combined horizontal and vertical offset
involves first a vertical 4-tap filter, followed by shifting,
followed by a horizontal 4-tap filter, followed by shifting by 7.
Both passes involve negative coefficients and therefore the
intermediate values for the >> 7 can exceed the range of
0..255*128 a bit in both directions. Therefore one can not simply
use either a logical or an arithmetic right shift. But one can use
them after having added a certain bias to ensure that one is in
the proper range. This is what this commit does.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit 0056dd32fd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Broken in ba56a300a9,
ba56a300a9 and again
in 38b8ae4112.
This means that no has compiled git master on mips
since 2024-06-04. And no one complained.
Hint: One still needs to pass -flax-vector-conversions
here in order to compile this file.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit d5b8439bdd)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The P- and B-picture per-MB guards added in 2a8785966c bail out of the loop
to error concealment when get_bits_left() <= 1, but P- and B-picture MBs can
legitimately cost exactly 1 bit in certain cases. This patch relaxes the guards
to accommodate those cases.
## Explanation
With the SKIPMB bitplane in Raw mode a skipped macroblock is a single SKIPMBBIT
(SMPTE ST 421:2013, 7.1.3.7, p.109) and then "may only contain the HYBRIDPRED
syntax element" (8.3.4.4, p.140), which is only read when predictors A and C
are in-bounds and the predicted vector differs from A or C by more than 32
quarter-pels (8.3.5.3.5, Figure 55, pp.149-150). That condition isn't met in a
static region so such a MB costs just 1 bit. A direct+skipped B-picture MB
likewise reads nothing beyond its raw flag (Table 30, p.86).
In Simple/Main profile a picture is byte-aligned with no stop bit, so if a
picture ends with a 1-bit skipped macroblock and its last coded bit lands on a
byte boundary, the final MB is reached with exactly one bit left. The guard
then conceals a valid macroblock, sets FF_DECODE_ERROR_CONCEALMENT_ACTIVE
on an undamaged frame, and the damage propagates to every frame up to the next
keyframe. (Advanced Profile BDUs end in a trailing '1' bit per Annex E.2/E.3
p.437, so they always have at least two bit left and are therefore unaffected.)
## Reproducing
Reproducible with an existing sample (prior to this patch):
$ ffmpeg -i https://samples.ffmpeg.org/V-codecs/WMV9/wmv-samples/sample-wmv9-simple-SP@ML.wmv -map 0:v -f null - 2>&1 | grep -A1 concealing
[wmv3 @ 0x122605430] concealing 75 DC, 75 AC, 75 MV errors in P frame
[vist#0:0/wmv3 @ 0x122604080] [dec:wmv3 @ 0x122604df0] corrupt decoded frame
[wmv3 @ 0x122605430] concealing 50 DC, 50 AC, 50 MV errors in P frame
[vist#0:0/wmv3 @ 0x122604080] [dec:wmv3 @ 0x122604df0] corrupt decoded frame
[wmv3 @ 0x122605430] concealing 100 DC, 100 AC, 100 MV errors in P frame
[vist#0:0/wmv3 @ 0x122604080] [dec:wmv3 @ 0x122604df0] corrupt decoded frame
## References
- SMPTE ST 421:2013 spec: https://pub.smpte.org/doc/st421/20131008-pub/
Signed-off-by: J. Brandt Buckley <brandt@runlevel1.com>
(cherry picked from commit ec8411e854)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
ef167512ab changed to parse RPU forward as far as we can go, but also
removed zero padding trimming, so the ext block size check on files with
big padding could trigger now. Restore the trailing zero strip. Note
that this does care only about zero padded NALs, while we have seen some
files with garbage padding, they are not considered here.
The only real way to find the end of RPU is to compute CRC32, as the
0x80 byte may be ambiguous. But we don't want that, and most (all) files
don't need that.
Also adjust the ext block remaining size check to minimal possible
(block with 0 size).
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24428
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
(cherry picked from commit 22b96de803)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The tile count limit was only checked once on entry, but tileCount is
incremented by ff_vk_decode_add_slice() inside the loop, so a stream
carrying more than MAX_TILES tiles writes past the end of the
MAX_TILES-element tile_sizes array.
Check the limit on each iteration, and reject at MAX_TILES rather than
above it, since tileCount is used as the write index.
(cherry picked from commit d29ff88422)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Found during triage of the security report
Fixes: NULL pointer dereference
Fixes: 5cNIJSj1u1Lc/input-format-after-header.bin / gen-format-after-header.py
Fixes: 5cNIJSj1u1Lc
(cherry picked from commit 400912007a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Found during review of the fix for the security report
Fixes: NULL pointer dereference
Fixes: 5cNIJSj1u1Lc/input-frameindex-path.bin / gen-frameindex-path.py
Fixes: 5cNIJSj1u1Lc
(cherry picked from commit d66ee0411c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes: reallocation of the IBC virtual buffers on every frame
(cherry picked from commit 5c161e1a62)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
automated reviews otherwise treat this flag as a argument to
demand that any random subset of frames can be skiped and still
all extract their parameters correctly
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 3369578ba4)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Found-by: Umar Pathan (Umar0x)
Signed-off-by: Umar Pathan <hello@umar.ac>
Fixes: out of array access
Fixes: signed integer overflow: 2147482624 + 1024 cannot be represented in type 'int'
Fixes: hHqW0dFoQwHN
(cherry picked from commit e15ddb7f9a)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The luma interpolation filters read two lines above and three lines
below a block, so rv34_mc() needs 8 * height + 5 reference lines, but it
had emulated_edge_mc() copy one more.
Fixes: data race between rv40_loop_filter() and rv34_mc() under frame threading
(cherry picked from commit 709f8fecec)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes: unsynchronized cross-thread read of reference frame rows
Fixes: IFu1maPxsZFJ
Found-by: Mozilla's AI bot, reviewed and reported by Chun-Min Chang <cchang@mozilla.com>
(cherry picked from commit 9e17d6c9f1)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
vp9_decode_flush() releases s->s.frames[], s->s.refs[] and s->s.ref_frames[]
but leaves s->next_refs[] referenced. Under frame threading,
vp9_decode_update_thread_context() seeds a worker's s->s.refs[] from the source
worker's next_refs[] (not from its refs[]). The pre-flush next_refs therefore
survive a flush and can be resurrected into a worker's refs[] afterwards,
letting a subsequent inter frame pass the reference-availability check and
decode against references that no longer exist.
Unref s->next_refs[] alongside s->s.refs[] so that flushing fully drops the
decoder's reference state.
Fixes: heap out-of-bounds read and write after avcodec_flush_buffers()
Fixes: 34c2zQaUquOl
Found-by: Mozilla's bugmon automation, reviewed and reported by Chun-Min Chang <cchang@mozilla.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit a024f8c541)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
vp8_mc_luma()/vp8_mc_chroma() derive the reference row to await from y_off,
which includes the block's motion vector, and never floor it at 0, so a vector
pointing above the frame makes the awaited row negative.
For a 16x16 block the expression still bottoms out at 0 for any vector inside
clamp_mv()'s +-16 px margin, which is why the omission is easy to miss. The
split modes, however, predict 8- and 4-row blocks, where a much smaller vector
suffices: at mb_y 0 with block_h 8, y_off -12 gives (3 - 12 + 8) >> 4 == -1,
and with block_h 4, y_off -8 does. SPLITMV sub-vectors are moreover never
clamped, and NEWMV deltas are applied after clamp_mv(), so larger vectors are
reachable too.
ff_thread_progress_await() returns as soon as progress >= n, and progress is
initialised to -1 under frame threading, so a negative row is treated as
already reached and no happens-before edge with the thread decoding the
reference frame is established. emulated_edge_mc() nevertheless clamps the
source rectangle and reads row 0 of the reference plane, i.e. the row is read
without waiting for it to be written.
Floor the awaited row at 0, the lowest row the subsequent read can touch. The
floor only ever raises a negative row to 0, never above a row already awaited
on the same frame, so it cannot introduce a stall.
Fixes: unsynchronized cross-thread read of reference frame rows
Fixes: IFu1maPxsZFJ
Found-by: Mozilla's AI bot, reviewed and reported by Chun-Min Chang <cchang@mozilla.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b772f5033c)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>