Compare commits

...

39 Commits

Author SHA1 Message Date
James Almer a5faeca88f 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)
2026-06-10 15:12:24 +01:00
Frank Plowman 920871999a lavc/vvc: Stricter bound on pps_exp_slice_height_in_ctus_minus1
When pps_num_exp_slices_in_tile[i] is nonzero, the ith tile is made up
of pps_num_exp_slices_in_tile[i] slices stacked atop one another, where
the height of the jth slice in the ith tile is given by
pps_exp_slice_height_in_ctus_minus1[i][j].  The sum of the heights of
the slices in the tile should not exceed the height of the tile itself.

Signed-off-by: Frank Plowman <post@frankplowman.com>

(cherry-picked from commit 20a6eb1ca3)
2026-06-10 15:12:24 +01:00
Michael Niedermayer 1516faadef 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)
2026-06-10 15:12:24 +01:00
Frank Plowman 83c2f4b81d lavc/vvc: Use second definition of MinQtLog2SizeIntraC if relevant
MinQtLog2SizeIntraC is usually (eq. (51) from VVCv3) defined as

sps_log2_diff_min_qt_min_cb_intra_slice_chroma + MinCbLog2SizeY

However, in the case ph_log2_diff_min_qt_min_cb_intra_slice_chroma is
present, it is instead (eq. (83) from VVCv3) defined as

ph_log2_diff_min_qt_min_cb_intra_slice_chroma + MinCbLog2SizeY

When ph_log2_diff_max_bt_min_qt_intra_slice_chroma and
ph_log2_diff_max_tt_min_qt_intra_slice_chroma are present, so is
ph_log2_diff_min_qt_min_cb_intra_slice_chroma, and so we should use the
second definition of MinQtLog2SizeIntraC, rather than the first, when
calculating the bounds for these syntax elements.

Signed-off-by: Frank Plowman <post@frankplowman.com>

(cherry-picked from commit 9221cb0443)
2026-06-10 15:12:23 +01:00
牟凡 72a46d7802 avcodec/cbs_h266: fix wrong condition for chroma MTT depth in PH
In the picture header parser, the chroma branch incorrectly tested
sps_max_mtt_hierarchy_depth_intra_slice_chroma to decide whether to
parse ph_log2_diff_max_{bt,tt}_min_qt_intra_slice_chroma.

Per ITU-T H.266 (V4, 01/2026) section 7.3.2.8 "Picture header
structure syntax", the condition is on the just-parsed
ph_max_mtt_hierarchy_depth_intra_slice_chroma, exactly mirroring the
luma branch a few lines above and the inter-slice branch below.
sps_partition_constraints_override_enabled_flag allows the picture
header to override the SPS values, so testing the SPS field is
incorrect and desynchronises the parser whenever the PH override
changes the chroma MTT depth from/to zero.

Signed-off-by: Mou Fan <moufan17@126.com>

(cherry-picked from commit 28ecb07e55)
2026-06-10 15:12:23 +01:00
Frank Plowman a72a11d8be lavc/vvc: Fix unchecked error codes from add_reconstructed_area
(cherry-picked from commit 364d5dda91)
2026-06-10 15:12:23 +01:00
Frank Plowman b10e9a5369 lavc/vvc: Fix unchecked error codes from set_qp_y
Fixes: clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VVC_fuzzer-4957602162475008

(cherry-picked from commit f9740eb969)
2026-06-10 15:12:23 +01:00
Frank Plowman bb69554165 lavc/vvc: Error on inter slice with no reference pics
The semantics of sh_num_ref_idx_active_minus1[ i ] state that

When the current slice is a P slice, the value of NumRefIdxActive[ 0 ] shall be greater than 0.
When the current slice is a B slice, both NumRefIdxActive[ 0 ] and NumRefIdxActive[ 1 ] shall be greater than 0.

Fixes: use of uninitialized memory
Fixes: 449549597/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VVC_fuzzer-5600497089445888

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Reported-by: Michael Niedermayer michael@niedermayer.cc
(cherry picked from commit 90f1f797aa)
2026-06-10 15:12:23 +01:00
Frank Plowman 07e3329458 lavc/vvc: Mark SPS used if multiple CLVSSs use it
Consider the following sequence of NALUs (with some PPSs etc. omitted
for brevity):
1. SPS (ID=0, content=A)
2. IDR (SPS=0)
3. IDR (SPS=0)
4. SPS (ID=0, content=B)
5. TRAIL (SPS=0)

When decode_sps is called for NALU 3., ps->sps_id_used is cleared as
IDRs are one way of forming a CLVSS.  Then, old_sps is non-NULL
containing the result of calling decode_sps for NALU 2.  We haven't
received any SPSs between NALUs 2. and 3., therefore old_sps and rsps
are identical and the function returns.  The issue is that, at this
point, ps->sps_id_used is still zero despite the SPS being used for IDR
3.  This results in the check for conflicting SPSs not working properly
when decode_sps is called for NALU 5., allowing prediction between
pictures with different SPSs and probably all sorts of other
shenanigans.

Patch addresses the problem outlined above by also setting
ps->sps_id_used in the early return case.

(cherry picked from commit f82748d5e0)
2026-06-10 15:12:23 +01:00
Frank Plowman f0cf73f421 lavc/vvc: Fix divide-by-zero in LMCS param derivation
Add three missing requirements on bitstream conformance from 7.4.3.19 of
H.266 (V3).  Issue found using fuzzing.

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 0382291811)
2026-06-10 15:12:23 +01:00
Frank Plowman e43f666a23 lavc/vvc: Detect subpic overlaps at CTU level
In d5dbcc00d8, it was hoped that detection
of subpicture overlaps could be performed at the tile level, so as to
avoid introducing per-CTU checks. Unfortunately since that patch,
fuzzing has indicated there are some structures involving
pps_subpic_one_or_more_tiles_slice where tile-level checking is not
sufficient.  Performing the check at the CTU level should (touch wood)
be the be-all and and-all of this, as CTUs are the lowest common
denominator of the picture partitioning.

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit a18b2c2696)
2026-06-10 15:12:22 +01:00
Frank Plowman 6e5d93b466 lavc/vvc: Fix pps_single_slice_picture
Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 600ad36949)
2026-06-10 15:12:22 +01:00
Frank Plowman 8c2bda5f61 lavc/vvc: Ensure subpictures don't overlap
This is essentially a re-implementation of
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20241005223955.54158-1-post@frankplowman.com/

That patch was not applied last time.  Instead we opted to identify
issues which could be caused by invalid subpicture layouts and remedy
those issues where they manifest, either through error detection or code
hardening.  This was primarily implemented in the set
https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=13381.

This has worked to some degree, however issues with subpicture layouts
continue to crop up from the fuzzer and I've fixed a number of bugs
related to subpicture layouts since then.  I think it's best to return
to the initial plan and simply check if the subpicture layout is valid
initially.

This implementation is also lighter than the first time -- by doing a
bit more logic in pps_subpic_less_than_one_tile_slice, we are able to
store a tile_in_subpic map rather than a ctu_in_subpic map.  This
reduces the size of the map to the point it becomes possible to allocate
it on the stack.  Similar to 8bd66a8c95,
the layout is also validated in the slice map construction code, rather
than in the CBS, which avoids duplicating some logic.

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit d5dbcc00d8)
2026-06-10 15:12:22 +01:00
Frank Plowman e2288cc6c0 lavc/vvc: Fix slice map construction for small subpics
In the case pps_subpic_less_than_one_tile_slice is called, the
subpicture is smaller than the tile and so there are multiple
subpictures in the tile.  Of course, then, not all the
subpictures can start in the top-left corner as the code before the
patch does.  Patch fixes this, so each subpicture starts at the
signalled location as is specified in section 6.5.1 of H.266(V3).

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 93aae172ea)
2026-06-10 15:12:22 +01:00
Frank Plowman 0c816d8b89 lavc/vvc: Fix derivation of inverse LMCS idx
The clamping of idxYInv from H.266(V3) section 8.8.2.3 was missing.
This could lead to OOB reads from lmcs->pivot or input_pivot.

I also changed the derivation of the forward LMCS idx to use a shift
rather than a division for speed and as this is actually how the
variable is declared in the specification (8.7.5.2).

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 392aa9daf2)
2026-06-10 15:12:22 +01:00
Frank Plowman 8e9c768416 lavc/vvc: Set fc->ref to NULL at top of decode_nal_units
In the fail: block of decode_nal_units, a check as to whether fc->ref is
nonzero is used.  Before this patch, fc->ref was set to NULL in
frame_context_setup.  The issue is that, by the time frame_context_setup
is called, falliable functions (namely slices_realloc and
ff_vvc_decode_frame_ps) have already been called.  Therefore, there
could arise a situation in which the fc->ref test of decode_nal_units'
fail: block is performed while fc->ref has an invalid value.  This seems
to be particularly prevalent in situations where the FrameContexts are
being reused.  The patch resolves the issue by moving the assignment of
fc->ref to NULL to the very top of decode_nal_units, before any falliable
functions are called.

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit e417f939da)
2026-06-10 15:12:22 +01:00
Nuo Mi 02aad54e2c lavc/vvcdec: ensure slices contain nonzero CTUs
fixes https://github.com/ffvvc/tests/tree/main/fuzz/passed/000323.bit

Co-authored-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit ca3550948c)
2026-06-10 15:12:22 +01:00
Zhao Zhili 7134d5b996 avcodec/vvc: Add support for output_corrupt/showall flags
(cherry picked from commit ea381285e7)
2026-06-10 15:12:21 +01:00
Frank Plowman 43e9c091dd lavc/vvc: Check slice structure
The criteria for slice structure validity is similar to that of
subpicture structure validity that we saw not too long ago [1].
The relationship between tiles and slices must satisfy the following
properties:

* Exhaustivity.  All tiles in a picture must belong to a slice.  The
  tiles cover the picture, so this implies the slices must cover the
  picture.
* Mutual exclusivity.  No tile may belong to more than one slice, i.e.
  slices may not overlap.

In most cases these properties are guaranteed by the syntax.  There is
one noticable exception however: when pps_tile_idx_delta_present_flag is
equal to one, each slice is associated with a syntax element
pps_tile_idx_delta_val[i] which "specifies the difference between the
tile index of the tile containing the first CTU in the ( i + 1 )-th
rectangular slice and the tile index of the tile containing the first
CTU in the i-th rectangular slice" [2].  When these syntax elements are
present, the i-th slice can begin anywhere and the usual guarantees
provided by the syntax are lost.

The patch detects slice structures which violate either of the two
properties above, and are therefore invalid, while building the
slice map.  Should the slice map be determined to be invalid, an
AVERROR_INVALIDDATA is returned.  This prevents issues including
segmentation faults when trying to decode,  invalid bitstreams.

[1]: https://ffmpeg.org//pipermail/ffmpeg-devel/2024-October/334470.html
[2]: H.266 (V3) Section 7.4.3.5, Picture parameter set RBSP semantics

Signed-off-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 8bd66a8c95)
2026-06-10 15:12:21 +01:00
Chris Warrington efd787107e avcodec/vvc decode: ALF filtering without CC-ALF
When a stream has ALF filtering enabled but not CC-ALF, the CC-ALF set indexes alf->ctb_cc_idc are being read uninitialized during ALF filtering.

This change initializes alf->ctb_cc_idc whenever ALF is enabled.

Ref. https://trac.ffmpeg.org/ticket/11325

(cherry picked from commit f80af3657f)
2026-06-10 15:12:21 +01:00
Alexander Strasser 912e77ba04 avcodec/cbs_h266: Fix typo
Introduced in commit 98698ed3c2

Fixes: CID1635788 CID1635789
Signed-off-by: Alexander Strasser <eclipse7@gmx.net>

(cherry picked from commit a280e2e646)
2026-06-10 15:12:21 +01:00
Nuo Mi 263ebe4ed2 avcodec/vvcdec: return error if CTU size > 128
The v3 spec reserves CTU size 256. Currently, we use an uint8_t* table to hold cb_width and cb_height.
If a CTU size of 256 is not split, cb_width and cb_height will overflow to 0.
To avoid switching to uint16_t, rejecting CTU size 256 provides a simple solution.

(cherry picked from commit 4de67e8746)
2026-06-10 15:12:21 +01:00
Nuo Mi 2e5801fd82 avcodec/cbs_h266: stricter validation for subpicture's max width and height
Co-authored-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 98698ed3c2)
2026-06-10 15:12:21 +01:00
Nuo Mi ff3725aa6d avcodec/cbs_h266: improve readability in subpicture parser
(cherry picked from commit e06515b092)
2026-06-10 15:12:20 +01:00
Nuo Mi eaee3cf584 avcodec/vvcdec: schedule next stage only if the current stage reports no error
If the current stage reports an error, some variables may not be correctly initialized.
Scheduling the next stage could lead to the use of uninitialized variables.

(cherry picked from commit eb67e60cb0)
2026-06-10 15:12:20 +01:00
Nuo Mi 78eabd954e avcodec/vvcdec: inter_data, check the return value from hls_merge_data
Reported-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit ba89c5b989)
2026-06-10 15:12:20 +01:00
Nuo Mi e8fc0e76b9 avcodec/vvcdec: ensure every CTU belongs to a slice
According to section 6.3.3 "Spatial or component-wise partitionings,"
CTUs should fully cover slices with no overlaps, gaps, or additions.
No overlaps are ensured by task_init_parse.
No gaps and no additions are ensured by this patch.

Co-authored-by: Frank Plowman <post@frankplowman.com>
(cherry picked from commit 5c5a08ecb5)
2026-06-10 15:12:20 +01:00
Fei Wang 1b835805c7 lavc/vvc_refs: Define VVC_FRAME_FLAG* to h header
So that hardware decoder can use the flags too.

Signed-off-by: Fei Wang <fei.w.wang@intel.com>
(cherry picked from commit 15a75e8e04)
2026-06-10 15:12:20 +01:00
Nuo Mi 3faa8b9cc0 avcodec/vvc/thread: Check frame to be non NULL
Fixes: NULL pointer dereference
Fixes: 71303/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_VVC_fuzzer-4875859050168320

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Reported-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit b611410569)
2026-06-10 15:12:20 +01:00
Zhao Zhili c0bf41a774 avcodec/vvc: Don't use large array on stack
tmp_array in dmvr_hv takes 33024 bytes on stack, which can be
dangerous.

(cherry picked from commit 240c16bbc6)
2026-06-10 15:12:16 +01:00
James Almer c06af95f12 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:29:03 -03:00
James Almer 06f659b6d7 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:28:55 -03:00
Romain Beauxis adcf20da26 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:50:10 -05:00
Franciszek Kalinowski 181cfa1008 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:49 -05:00
Kacper Michajłow ed860ef7d9 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:12:17 +02:00
Kacper Michajłow 939eff8718 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:11:56 +02:00
Kacper Michajłow 9315150f9d 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 18:11:56 +02:00
Kacper Michajłow 24a6c067c3 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 18:11:56 +02:00
Kacper Michajłow 5814ad356a 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 18:11:55 +02:00
18 changed files with 331 additions and 167 deletions
+62 -58
View File
@@ -1057,7 +1057,7 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
H266RawSPS *current)
{
CodedBitstreamH266Context *h266 = ctx->priv_data;
int err, i, j;
int err, i, j, max_width_minus1, max_height_minus1;
unsigned int ctb_log2_size_y, min_cb_log2_size_y,
min_qt_log2_size_intra_y, min_qt_log2_size_inter_y,
ctb_size_y, max_num_merge_cand, tmp_width_val, tmp_height_val;
@@ -1130,6 +1130,8 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
ctb_log2_size_y);
tmp_height_val = AV_CEIL_RSHIFT(current->sps_pic_height_max_in_luma_samples,
ctb_log2_size_y);
max_width_minus1 = tmp_width_val - 1;
max_height_minus1 = tmp_height_val - 1;
flag(sps_subpic_info_present_flag);
if (current->sps_subpic_info_present_flag) {
@@ -1145,13 +1147,13 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
infer(sps_subpic_ctu_top_left_x[0], 0);
infer(sps_subpic_ctu_top_left_y[0], 0);
if (current->sps_pic_width_max_in_luma_samples > ctb_size_y)
ubs(wlen, sps_subpic_width_minus1[0], 1, 0);
us(wlen, sps_subpic_width_minus1[0], 0, max_width_minus1, 1, 0);
else
infer(sps_subpic_width_minus1[0], tmp_width_val - 1);
infer(sps_subpic_width_minus1[0], max_width_minus1);
if (current->sps_pic_height_max_in_luma_samples > ctb_size_y)
ubs(hlen, sps_subpic_height_minus1[0], 1, 0);
us(hlen, sps_subpic_height_minus1[0], 0, max_height_minus1, 1, 0);
else
infer(sps_subpic_height_minus1[0], tmp_height_val - 1);
infer(sps_subpic_height_minus1[0], max_height_minus1);
if (!current->sps_independent_subpics_flag) {
flags(sps_subpic_treated_as_pic_flag[0], 1, 0);
flags(sps_loop_filter_across_subpic_enabled_flag[0], 1, 0);
@@ -1161,58 +1163,54 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
}
for (i = 1; i <= current->sps_num_subpics_minus1; i++) {
if (!current->sps_subpic_same_size_flag) {
if (current->sps_pic_width_max_in_luma_samples > ctb_size_y) {
const int win_right_edge =
current->sps_pic_width_max_in_luma_samples
- current->sps_conf_win_right_offset * sub_width_c;
us(wlen, sps_subpic_ctu_top_left_x[i], 0,
AV_CEIL_RSHIFT(win_right_edge, ctb_log2_size_y) - 1,
1, i);
} else
const int win_right_edge =
current->sps_pic_width_max_in_luma_samples -
current->sps_conf_win_right_offset * sub_width_c;
const int win_bottom_edge =
current->sps_pic_height_max_in_luma_samples -
current->sps_conf_win_bottom_offset * sub_height_c;
const int win_left_edge =
current->sps_conf_win_left_offset * sub_width_c;
const int win_top_edge =
current->sps_conf_win_top_offset * sub_height_c;
const int win_left_edge_ctus =
AV_CEIL_RSHIFT(win_left_edge, ctb_log2_size_y);
const int win_right_edge_ctus =
AV_CEIL_RSHIFT(win_right_edge, ctb_log2_size_y);
const int win_top_edge_ctus =
AV_CEIL_RSHIFT(win_top_edge, ctb_log2_size_y);
const int win_bottom_edge_ctus =
AV_CEIL_RSHIFT(win_bottom_edge, ctb_log2_size_y);
const int min_width =
FFMAX(win_left_edge_ctus - current->sps_subpic_ctu_top_left_x[i], 0);
const int min_height =
FFMAX(win_top_edge_ctus - current->sps_subpic_ctu_top_left_y[i], 0);
if (current->sps_pic_width_max_in_luma_samples > ctb_size_y)
us(wlen, sps_subpic_ctu_top_left_x[i], 0, win_right_edge_ctus - 1, 1, i);
else
infer(sps_subpic_ctu_top_left_x[i], 0);
if (current->sps_pic_height_max_in_luma_samples >
ctb_size_y) {
const int win_bottom_edge =
current->sps_pic_height_max_in_luma_samples
- current->sps_conf_win_bottom_offset * sub_height_c;
us(hlen, sps_subpic_ctu_top_left_y[i], 0,
AV_CEIL_RSHIFT(win_bottom_edge, ctb_log2_size_y) - 1,
1, i);
} else
if (current->sps_pic_height_max_in_luma_samples > ctb_size_y)
us(hlen, sps_subpic_ctu_top_left_y[i], 0, win_bottom_edge_ctus - 1, 1, i);
else
infer(sps_subpic_ctu_top_left_y[i], 0);
max_width_minus1 = tmp_width_val - current->sps_subpic_ctu_top_left_x[i] - 1;
max_height_minus1 = tmp_height_val - current->sps_subpic_ctu_top_left_y[i] - 1;
if (i < current->sps_num_subpics_minus1 &&
current->sps_pic_width_max_in_luma_samples >
ctb_size_y) {
const int win_left_edge =
current->sps_conf_win_left_offset * sub_width_c;
const int win_left_edge_ctus =
AV_CEIL_RSHIFT(win_left_edge, ctb_log2_size_y);
us(wlen, sps_subpic_width_minus1[i],
win_left_edge_ctus > current->sps_subpic_ctu_top_left_x[i]
? win_left_edge_ctus - current->sps_subpic_ctu_top_left_x[i]
: 0,
MAX_UINT_BITS(wlen), 1, i);
current->sps_pic_width_max_in_luma_samples > ctb_size_y) {
us(wlen, sps_subpic_width_minus1[i], min_width, max_width_minus1, 1, i);
} else {
infer(sps_subpic_width_minus1[i],
tmp_width_val -
current->sps_subpic_ctu_top_left_x[i] - 1);
infer(sps_subpic_width_minus1[i], max_width_minus1);
}
if (i < current->sps_num_subpics_minus1 &&
current->sps_pic_height_max_in_luma_samples >
ctb_size_y) {
const int win_top_edge =
current->sps_conf_win_top_offset * sub_height_c;
const int win_top_edge_ctus =
AV_CEIL_RSHIFT(win_top_edge, ctb_log2_size_y);
us(hlen, sps_subpic_height_minus1[i],
win_top_edge_ctus > current->sps_subpic_ctu_top_left_y[i]
? win_top_edge_ctus - current->sps_subpic_ctu_top_left_y[i]
: 0,
MAX_UINT_BITS(hlen), 1, i);
current->sps_pic_height_max_in_luma_samples > ctb_size_y) {
us(hlen, sps_subpic_height_minus1[i], min_height, max_height_minus1, 1, i);
} else {
infer(sps_subpic_height_minus1[i],
tmp_height_val -
current->sps_subpic_ctu_top_left_y[i] - 1);
infer(sps_subpic_height_minus1[i], max_height_minus1);
}
} else {
int num_subpic_cols = tmp_width_val /
@@ -1245,8 +1243,8 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
} else {
infer(sps_subpic_ctu_top_left_x[0], 0);
infer(sps_subpic_ctu_top_left_y[0], 0);
infer(sps_subpic_width_minus1[0], tmp_width_val - 1);
infer(sps_subpic_height_minus1[0], tmp_height_val - 1);
infer(sps_subpic_width_minus1[0], max_width_minus1);
infer(sps_subpic_height_minus1[0], max_height_minus1);
}
ue(sps_subpic_id_len_minus1, 0, 15);
if ((1 << (current->sps_subpic_id_len_minus1 + 1)) <
@@ -1273,8 +1271,8 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
infer(sps_subpic_id_mapping_explicitly_signalled_flag, 0);
infer(sps_subpic_ctu_top_left_x[0], 0);
infer(sps_subpic_ctu_top_left_y[0], 0);
infer(sps_subpic_width_minus1[0], tmp_width_val - 1);
infer(sps_subpic_height_minus1[0], tmp_height_val - 1);
infer(sps_subpic_width_minus1[0], max_width_minus1);
infer(sps_subpic_height_minus1[0], max_height_minus1);
}
@@ -2024,7 +2022,7 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw,
for (j = 0; j < current->pps_num_exp_slices_in_tile[i];
j++) {
ues(pps_exp_slice_height_in_ctus_minus1[i][j], 0,
current->row_height_val[tile_y] - 1, 2,
remaining_height_in_ctbs_y - (current->pps_num_exp_slices_in_tile[i] - j), 2,
i, j);
slice_height_in_ctus =
current->
@@ -2810,9 +2808,9 @@ static int FUNC(picture_header) (CodedBitstreamContext *ctx, RWContext *rw,
0, FFMIN(6, ctb_log2_size_y) - min_cb_log2_size_y);
ue(ph_max_mtt_hierarchy_depth_intra_slice_chroma,
0, 2 * (ctb_log2_size_y - min_cb_log2_size_y));
if (sps->sps_max_mtt_hierarchy_depth_intra_slice_chroma != 0) {
if (current->ph_max_mtt_hierarchy_depth_intra_slice_chroma != 0) {
unsigned int min_qt_log2_size_intra_c =
sps->sps_log2_diff_min_qt_min_cb_intra_slice_chroma +
current->ph_log2_diff_min_qt_min_cb_intra_slice_chroma +
min_cb_log2_size_y;
ue(ph_log2_diff_max_bt_min_qt_intra_slice_chroma,
0, FFMIN(6, ctb_log2_size_y) - min_qt_log2_size_intra_c);
@@ -3136,7 +3134,7 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw,
if (!pps->pps_rect_slice_flag &&
pps->num_tiles_in_pic - current->sh_slice_address > 1)
ue(sh_num_tiles_in_slice_minus1, 0, pps->num_tiles_in_pic - 1);
ue(sh_num_tiles_in_slice_minus1, 0, pps->num_tiles_in_pic - 1 - current->sh_slice_address);
else
infer(sh_num_tiles_in_slice_minus1, 0);
@@ -3254,6 +3252,12 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw,
FFMIN(ref_pic_lists->rpl_ref_list[i].num_ref_entries,
pps->pps_num_ref_idx_default_active_minus1[i] + 1);
}
if (current->num_ref_idx_active[i] <= 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR,
"Inter slice but no reference pictures available for RPL%d.\n", i);
return AVERROR_INVALIDDATA;
}
} else {
current->num_ref_idx_active[i] = 0;
}
+10 -4
View File
@@ -1136,8 +1136,11 @@ static int skipped_transform_tree_unit(VVCLocalContext *lc)
const CodingUnit *cu = lc->cu;
int ret;
if (cu->tree_type != DUAL_TREE_CHROMA)
set_qp_y(lc, cu->x0, cu->y0, 0);
if (cu->tree_type != DUAL_TREE_CHROMA) {
ret = set_qp_y(lc, cu->x0, cu->y0, 0);
if (ret < 0)
return ret;
}
if (rsps->sps_chroma_format_idc && cu->tree_type != DUAL_TREE_LUMA)
set_qp_c(lc);
ret = skipped_transform_tree(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
@@ -1778,13 +1781,16 @@ static int inter_data(VVCLocalContext *lc)
pu->general_merge_flag = ff_vvc_general_merge_flag(lc);
if (pu->general_merge_flag) {
hls_merge_data(lc);
ret = hls_merge_data(lc);
} else if (cu->pred_mode == MODE_IBC){
ret = mvp_data_ibc(lc);
} else {
ret = mvp_data(lc);
}
if (ret)
return ret;
if (cu->pred_mode == MODE_IBC)
{
ff_vvc_update_hmvp(lc, mi);
@@ -2286,6 +2292,7 @@ static void alf_params(VVCLocalContext *lc, const int rx, const int ry)
ALFParams *alf = &CTB(fc->tab.alf, rx, ry);
alf->ctb_flag[LUMA] = alf->ctb_flag[CB] = alf->ctb_flag[CR] = 0;
alf->ctb_cc_idc[0] = alf->ctb_cc_idc[1] = 0;
if (sh->sh_alf_enabled_flag) {
alf->ctb_flag[LUMA] = ff_vvc_alf_ctb_flag(lc, rx, ry, LUMA);
if (alf->ctb_flag[LUMA]) {
@@ -2316,7 +2323,6 @@ static void alf_params(VVCLocalContext *lc, const int rx, const int ry)
const uint8_t cc_enabled[] = { sh->sh_alf_cc_cb_enabled_flag, sh->sh_alf_cc_cr_enabled_flag };
const uint8_t cc_aps_id[] = { sh->sh_alf_cc_cb_aps_id, sh->sh_alf_cc_cr_aps_id };
for (int i = 0; i < 2; i++) {
alf->ctb_cc_idc[i] = 0;
if (cc_enabled[i]) {
const VVCALF *aps = fc->ps.alf_list[cc_aps_id[i]];
alf->ctb_cc_idc[i] = ff_vvc_alf_ctb_cc_idc(lc, rx, ry, i, aps->num_cc_filters[i]);
+2 -3
View File
@@ -672,8 +672,6 @@ static int frame_context_setup(VVCFrameContext *fc, VVCContext *s)
{
int ret;
fc->ref = NULL;
// copy refs from the last frame
if (s->nb_frames && s->nb_fcs > 1) {
VVCFrameContext *prev = get_frame_context(s, fc, -1);
@@ -877,6 +875,7 @@ static int decode_nal_units(VVCContext *s, VVCFrameContext *fc, AVPacket *avpkt)
int ret = 0;
s->last_eos = s->eos;
s->eos = 0;
fc->ref = NULL;
ff_cbs_fragment_reset(frame);
ret = ff_cbs_read_packet(s->cbc, frame, avpkt);
@@ -1000,7 +999,7 @@ static int vvc_decode_frame(AVCodecContext *avctx, AVFrame *output,
if (ret < 0)
return ret;
if (!fc->ft)
if (!fc->ft || !fc->ref)
return avpkt->size;
ret = submit_frame(s, fc, output, got_output);
+18 -15
View File
@@ -472,6 +472,9 @@ static void FUNC(apply_bdof)(uint8_t *_dst, const ptrdiff_t _dst_stride, const i
(filter[0] * src[x] + \
filter[1] * src[x + stride])
#define DMVR_FILTER2(filter, src0, src1) \
(filter[0] * src0 + filter[1] * src1)
//8.5.3.2.2 Luma sample bilinear interpolation process
static void FUNC(dmvr)(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride,
const int height, const intptr_t mx, const intptr_t my, const int width)
@@ -541,31 +544,31 @@ static void FUNC(dmvr_v)(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src
static void FUNC(dmvr_hv)(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride,
const int height, const intptr_t mx, const intptr_t my, const int width)
{
int16_t tmp_array[(MAX_PB_SIZE + BILINEAR_EXTRA) * MAX_PB_SIZE];
int16_t *tmp = tmp_array;
int16_t tmp_array[MAX_PB_SIZE * 2];
int16_t *tmp0 = tmp_array;
int16_t *tmp1 = tmp_array + MAX_PB_SIZE;
const pixel *src = (const pixel*)_src;
const ptrdiff_t src_stride = _src_stride / sizeof(pixel);
const int8_t *filter = ff_vvc_inter_luma_dmvr_filters[mx];
const int8_t *filter_x = ff_vvc_inter_luma_dmvr_filters[mx];
const int8_t *filter_y = ff_vvc_inter_luma_dmvr_filters[my];
const int shift1 = BIT_DEPTH - 6;
const int offset1 = 1 << (shift1 - 1);
const int shift2 = 4;
const int offset2 = 1 << (shift2 - 1);
src -= BILINEAR_EXTRA_BEFORE * src_stride;
for (int y = 0; y < height + BILINEAR_EXTRA; y++) {
for (int x = 0; x < width; x++)
tmp[x] = (DMVR_FILTER(src, 1) + offset1) >> shift1;
src += src_stride;
tmp += MAX_PB_SIZE;
}
for (int x = 0; x < width; x++)
tmp0[x] = (DMVR_FILTER2(filter_x, src[x], src[x + 1]) + offset1) >> shift1;
src += src_stride;
tmp = tmp_array + BILINEAR_EXTRA_BEFORE * MAX_PB_SIZE;
filter = ff_vvc_inter_luma_dmvr_filters[my];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
dst[x] = (DMVR_FILTER(tmp, MAX_PB_SIZE) + offset2) >> shift2;
tmp += MAX_PB_SIZE;
for (int y = 1; y < height + BILINEAR_EXTRA; y++) {
for (int x = 0; x < width; x++) {
tmp1[x] = (DMVR_FILTER2(filter_x, src[x], src[x + 1]) + offset1) >> shift1;
dst[x] = (DMVR_FILTER2(filter_y, tmp0[x], tmp1[x]) + offset2) >> shift2;
}
src += src_stride;
dst += MAX_PB_SIZE;
FFSWAP(int16_t *, tmp0, tmp1);
}
}
+25 -11
View File
@@ -243,21 +243,23 @@ static int get_chroma_predict_unit(const CodingUnit *cu, const TransformUnit *tu
}
//8.4.5.1 General decoding process for intra blocks
static void predict_intra(VVCLocalContext *lc, const TransformUnit *tu, const int idx, const int target_ch_type)
static int predict_intra(VVCLocalContext *lc, const TransformUnit *tu, const int idx, const int target_ch_type)
{
const VVCFrameContext *fc = lc->fc;
const CodingUnit *cu = lc->cu;
const VVCTreeType tree_type = cu->tree_type;
int x0, y0, w, h;
int x0, y0, w, h, ret;
if (cu->pred_mode != MODE_INTRA) {
add_reconstructed_area(lc, target_ch_type, tu->x0, tu->y0, tu->width, tu->height);
return;
ret = add_reconstructed_area(lc, target_ch_type, tu->x0, tu->y0, tu->width, tu->height);
return ret;
}
if (!target_ch_type && tree_type != DUAL_TREE_CHROMA) {
if (get_luma_predict_unit(cu, tu, idx, &x0, &y0, &w, &h)) {
ff_vvc_set_neighbour_available(lc, x0, y0, w, h);
fc->vvcdsp.intra.intra_pred(lc, x0, y0, w, h, 0);
add_reconstructed_area(lc, 0, x0, y0, w, h);
ret = add_reconstructed_area(lc, 0, x0, y0, w, h);
if (ret < 0)
return ret;
}
}
if (target_ch_type && tree_type != DUAL_TREE_LUMA) {
@@ -269,9 +271,12 @@ static void predict_intra(VVCLocalContext *lc, const TransformUnit *tu, const in
fc->vvcdsp.intra.intra_pred(lc, x0, y0, w, h, 1);
fc->vvcdsp.intra.intra_pred(lc, x0, y0, w, h, 2);
}
add_reconstructed_area(lc, 1, x0, y0, w, h);
ret = add_reconstructed_area(lc, 1, x0, y0, w, h);
if (ret < 0)
return ret;
}
}
return 0;
}
static void scale_clip(int *coeff, const int nzw, const int w, const int h,
@@ -571,11 +576,14 @@ static int reconstruct(VVCLocalContext *lc)
CodingUnit *cu = lc->cu;
const int start = cu->tree_type == DUAL_TREE_CHROMA;
const int end = fc->ps.sps->r->sps_chroma_format_idc && (cu->tree_type != DUAL_TREE_LUMA);
int ret;
for (int ch_type = start; ch_type <= end; ch_type++) {
TransformUnit *tu = cu->tus.head;
for (int i = 0; tu; i++) {
predict_intra(lc, tu, i, ch_type);
ret = predict_intra(lc, tu, i, ch_type);
if (ret < 0)
return ret;
itransform(lc, tu, i, ch_type);
tu = tu->next;
}
@@ -681,10 +689,16 @@ int ff_vvc_reconstruct(VVCLocalContext *lc, const int rs, const int rx, const in
if (cu->coded_flag) {
ret = reconstruct(lc);
} else {
if (cu->tree_type != DUAL_TREE_CHROMA)
add_reconstructed_area(lc, LUMA, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
if (sps->r->sps_chroma_format_idc && cu->tree_type != DUAL_TREE_LUMA)
add_reconstructed_area(lc, CHROMA, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
if (cu->tree_type != DUAL_TREE_CHROMA) {
ret = add_reconstructed_area(lc, LUMA, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
if (ret < 0)
return ret;
}
if (sps->r->sps_chroma_format_idc && cu->tree_type != DUAL_TREE_LUMA) {
ret = add_reconstructed_area(lc, CHROMA, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
if (ret < 0)
return ret;
}
}
if (sps->r->sps_ibc_enabled_flag)
ibc_fill_vir_buf(lc, cu);
+129 -37
View File
@@ -20,6 +20,7 @@
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdbool.h>
#include "libavcodec/cbs_h266.h"
#include "libavutil/mem.h"
@@ -238,9 +239,10 @@ static int decode_sps(VVCParamSets *ps, const H266RawSPS *rsps, void *log_ctx, i
}
if (old_sps) {
if (old_sps->r == rsps || !memcmp(old_sps->r, rsps, sizeof(*old_sps->r)))
if (old_sps->r == rsps || !memcmp(old_sps->r, rsps, sizeof(*old_sps->r))) {
ps->sps_id_used |= (1 << sps_id);
return 0;
else if (ps->sps_id_used & (1 << sps_id))
} else if (ps->sps_id_used & (1 << sps_id))
return AVERROR_INVALIDDATA;
}
@@ -358,6 +360,8 @@ static int pps_add_ctus(VVCPPS *pps, int *off, const int rx, const int ry,
int start = *off;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (*off >= pps->ctb_count)
return AVERROR_INVALIDDATA;
pps->ctb_addr_in_slice[*off] = ctu_rs(rx + x, ry + y, pps);
(*off)++;
}
@@ -365,15 +369,21 @@ static int pps_add_ctus(VVCPPS *pps, int *off, const int rx, const int ry,
return *off - start;
}
static void pps_single_slice_picture(VVCPPS *pps, int *off)
static int pps_single_slice_picture(VVCPPS *pps, int *off)
{
pps->num_ctus_in_slice[0] = 0;
for (int j = 0; j < pps->r->num_tile_rows; j++) {
for (int i = 0; i < pps->r->num_tile_columns; i++) {
pps->num_ctus_in_slice[0] = pps_add_ctus(pps, off,
const int ret = pps_add_ctus(pps, off,
pps->col_bd[i], pps->row_bd[j],
pps->r->col_width_val[i], pps->r->row_height_val[j]);
if (ret < 0)
return ret;
pps->num_ctus_in_slice[0] += ret;
}
}
return 0;
}
static void subpic_tiles(int *tile_x, int *tile_y, int *tile_x_end, int *tile_y_end,
@@ -400,25 +410,36 @@ static void subpic_tiles(int *tile_x, int *tile_y, int *tile_x_end, int *tile_y_
(*tile_y_end)++;
}
static void pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off)
static int pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off)
{
pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off,
pps->col_bd[tx], pps->row_bd[ty],
pps->r->col_width_val[tx], sps->r->sps_subpic_height_minus1[i] + 1);
const int ret = pps_add_ctus(pps, off,
sps->r->sps_subpic_ctu_top_left_x[i], sps->r->sps_subpic_ctu_top_left_y[i],
sps->r->sps_subpic_width_minus1[i] + 1, sps->r->sps_subpic_height_minus1[i] + 1);
if (ret < 0)
return ret;
pps->num_ctus_in_slice[i] = ret;
return 0;
}
static void pps_subpic_one_or_more_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end, const int i, int *off)
static int pps_subpic_one_or_more_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end,
const int i, int *off)
{
for (int ty = tile_y; ty < y_end; ty++) {
for (int tx = tile_x; tx < x_end; tx++) {
pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off,
const int ret = pps_add_ctus(pps, off,
pps->col_bd[tx], pps->row_bd[ty],
pps->r->col_width_val[tx], pps->r->row_height_val[ty]);
if (ret < 0)
return ret;
pps->num_ctus_in_slice[i] += ret;
}
}
return 0;
}
static void pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off)
static int pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off)
{
int tx, ty, x_end, y_end;
@@ -427,19 +448,27 @@ static void pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *o
subpic_tiles(&tx, &ty, &x_end, &y_end, sps, pps, i);
if (ty + 1 == y_end && sps->r->sps_subpic_height_minus1[i] + 1 < pps->r->row_height_val[ty])
pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off);
return pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off);
else
pps_subpic_one_or_more_tiles_slice(pps, tx, ty, x_end, y_end, i, off);
return pps_subpic_one_or_more_tiles_slice(pps, tx, ty, x_end, y_end, i, off);
}
static void pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off)
static int pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off)
{
int ret;
if (!sps->r->sps_subpic_info_present_flag) {
pps_single_slice_picture(pps, off);
ret = pps_single_slice_picture(pps, off);
if (ret < 0)
return ret;
} else {
for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++)
pps_subpic_slice(pps, sps, i, off);
for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++) {
const int ret = pps_subpic_slice(pps, sps, i, off);
if (ret < 0)
return ret;
}
}
return 0;
}
static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off)
@@ -451,16 +480,20 @@ static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off)
ctu_xy(&rx, &ry, tile_x, tile_y, pps);
ctu_y_end = ry + r->row_height_val[tile_y];
while (ry < ctu_y_end) {
int ret;
pps->slice_start_offset[i] = *off;
pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off, rx, ry,
ret = pps_add_ctus(pps, off, rx, ry,
r->col_width_val[tile_x], r->slice_height_in_ctus[i]);
if (ret < 0)
return ret;
pps->num_ctus_in_slice[i] = ret;
ry += r->slice_height_in_ctus[i++];
}
i--;
return i;
}
static void pps_multi_tiles_slice(VVCPPS *pps, const int tile_idx, const int i, int *off)
static int pps_multi_tiles_slice(VVCPPS *pps, const int tile_idx, const int i, int *off, bool *tile_in_slice)
{
const H266RawPPS *r = pps->r;
int rx, ry, tile_x, tile_y;
@@ -470,57 +503,91 @@ static void pps_multi_tiles_slice(VVCPPS *pps, const int tile_idx, const int i,
pps->num_ctus_in_slice[i] = 0;
for (int ty = tile_y; ty <= tile_y + r->pps_slice_height_in_tiles_minus1[i]; ty++) {
for (int tx = tile_x; tx <= tile_x + r->pps_slice_width_in_tiles_minus1[i]; tx++) {
int ret;
const int idx = ty * r->num_tile_columns + tx;
if (tile_in_slice[idx])
return AVERROR_INVALIDDATA;
tile_in_slice[idx] = true;
ctu_xy(&rx, &ry, tx, ty, pps);
pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off, rx, ry,
ret = pps_add_ctus(pps, off, rx, ry,
r->col_width_val[tx], r->row_height_val[ty]);
if (ret < 0)
return ret;
pps->num_ctus_in_slice[i] += ret;
}
}
return 0;
}
static void pps_rect_slice(VVCPPS *pps, const VVCSPS *sps)
static int pps_rect_slice(VVCPPS *pps, const VVCSPS *sps)
{
const H266RawPPS *r = pps->r;
int tile_idx = 0, off = 0;
bool tile_in_slice[VVC_MAX_TILES_PER_AU] = {false};
int tile_idx = 0, off = 0, ret;
if (r->pps_single_slice_per_subpic_flag) {
pps_single_slice_per_subpic(pps, sps, &off);
return;
return pps_single_slice_per_subpic(pps, sps, &off);
}
for (int i = 0; i < r->pps_num_slices_in_pic_minus1 + 1; i++) {
if (!r->pps_slice_width_in_tiles_minus1[i] &&
!r->pps_slice_height_in_tiles_minus1[i]) {
i = pps_one_tile_slices(pps, tile_idx, i, &off);
if (tile_in_slice[tile_idx])
return AVERROR_INVALIDDATA;
tile_in_slice[tile_idx] = true;
ret = pps_one_tile_slices(pps, tile_idx, i, &off);
if (ret < 0)
return ret;
i = ret;
} else {
pps_multi_tiles_slice(pps, tile_idx, i, &off);
ret = pps_multi_tiles_slice(pps, tile_idx, i, &off, tile_in_slice);
if (ret < 0)
return ret;
}
tile_idx = next_tile_idx(tile_idx, i, r);
}
for (int i = 0; i < r->num_tiles_in_pic; i++) {
if (!tile_in_slice[i])
return AVERROR_INVALIDDATA;
}
return 0;
}
static void pps_no_rect_slice(VVCPPS* pps)
static int pps_no_rect_slice(VVCPPS* pps)
{
const H266RawPPS* r = pps->r;
int rx, ry, off = 0;
for (int tile_y = 0; tile_y < r->num_tile_rows; tile_y++) {
for (int tile_x = 0; tile_x < r->num_tile_columns; tile_x++) {
int ret;
ctu_xy(&rx, &ry, tile_x, tile_y, pps);
pps_add_ctus(pps, &off, rx, ry, r->col_width_val[tile_x], r->row_height_val[tile_y]);
ret = pps_add_ctus(pps, &off, rx, ry, r->col_width_val[tile_x], r->row_height_val[tile_y]);
if (ret < 0)
return ret;
}
}
return 0;
}
static int pps_slice_map(VVCPPS *pps, const VVCSPS *sps)
{
int ret;
pps->ctb_addr_in_slice = av_calloc(pps->ctb_count, sizeof(*pps->ctb_addr_in_slice));
if (!pps->ctb_addr_in_slice)
return AVERROR(ENOMEM);
if (pps->r->pps_rect_slice_flag)
pps_rect_slice(pps, sps);
else
pps_no_rect_slice(pps);
return pps_rect_slice(pps, sps);
ret = pps_no_rect_slice(pps);
if (ret < 0)
return ret;
return 0;
}
@@ -649,6 +716,12 @@ static int decode_ps(VVCParamSets *ps, const CodedBitstreamH266Context *h266, vo
if (ret < 0)
return ret;
if (rsps->sps_log2_ctu_size_minus5 > 2) {
// CTU > 128 are reserved in vvc spec v3
av_log(log_ctx, AV_LOG_ERROR, "CTU size > 128. \n");
return AVERROR_PATCHWELCOME;
}
ret = decode_pps(ps, rpps);
if (ret < 0)
return ret;
@@ -728,7 +801,7 @@ static int lmcs_derive_lut(VVCLMCS *lmcs, const H266RawAPS *rlmcs, const H266Raw
uint16_t input_pivot[LMCS_MAX_BIN_SIZE];
uint16_t scale_coeff[LMCS_MAX_BIN_SIZE];
uint16_t inv_scale_coeff[LMCS_MAX_BIN_SIZE];
int i, delta_crs;
int i, delta_crs, sum_cw = 0;
if (bit_depth > LMCS_MAX_BIT_DEPTH)
return AVERROR_PATCHWELCOME;
@@ -739,8 +812,12 @@ static int lmcs_derive_lut(VVCLMCS *lmcs, const H266RawAPS *rlmcs, const H266Raw
lmcs->max_bin_idx = LMCS_MAX_BIN_SIZE - 1 - rlmcs->lmcs_min_bin_idx;
memset(cw, 0, sizeof(cw));
for (int i = lmcs->min_bin_idx; i <= lmcs->max_bin_idx; i++)
for (int i = lmcs->min_bin_idx; i <= lmcs->max_bin_idx; i++) {
cw[i] = org_cw + (1 - 2 * rlmcs->lmcs_delta_sign_cw_flag[i]) * rlmcs->lmcs_delta_abs_cw[i];
sum_cw += cw[i];
}
if (sum_cw > (1 << bit_depth) - 1)
return AVERROR_INVALIDDATA;
delta_crs = (1 - 2 * rlmcs->lmcs_delta_sign_crs_flag) * rlmcs->lmcs_delta_abs_crs;
@@ -748,19 +825,26 @@ static int lmcs_derive_lut(VVCLMCS *lmcs, const H266RawAPS *rlmcs, const H266Raw
for (i = 0; i < LMCS_MAX_BIN_SIZE; i++) {
input_pivot[i] = i * org_cw;
lmcs->pivot[i + 1] = lmcs->pivot[i] + cw[i];
if (i >= lmcs->min_bin_idx && i <= lmcs->max_bin_idx &&
lmcs->pivot[i] % (1 << (bit_depth - 5)) != 0 &&
lmcs->pivot[i] >> (bit_depth - 5) == lmcs->pivot[i + 1] >> (bit_depth - 5))
return AVERROR_INVALIDDATA;
scale_coeff[i] = (cw[i] * (1 << 11) + off) >> shift;
if (cw[i] == 0) {
inv_scale_coeff[i] = 0;
lmcs->chroma_scale_coeff[i] = (1 << 11);
} else {
const int cw_plus_d = cw[i] + delta_crs;
if (cw_plus_d < (org_cw >> 3) || cw_plus_d > ((org_cw << 3) - 1))
return AVERROR_INVALIDDATA;
inv_scale_coeff[i] = org_cw * (1 << 11) / cw[i];
lmcs->chroma_scale_coeff[i] = org_cw * (1 << 11) / (cw[i] + delta_crs);
lmcs->chroma_scale_coeff[i] = org_cw * (1 << 11) / cw_plus_d;
}
}
//derive lmcs_fwd_lut
for (uint16_t sample = 0; sample < max; sample++) {
const int idx_y = sample / org_cw;
const int idx_y = sample >> shift;
const uint16_t fwd_sample = lmcs_derive_lut_sample(sample, lmcs->pivot,
input_pivot, scale_coeff, idx_y, max);
if (bit_depth > 8)
@@ -776,6 +860,7 @@ static int lmcs_derive_lut(VVCLMCS *lmcs, const H266RawAPS *rlmcs, const H266Raw
uint16_t inv_sample;
while (i <= lmcs->max_bin_idx && sample >= lmcs->pivot[i + 1])
i++;
i = FFMIN(i, LMCS_MAX_BIN_SIZE - 1);
inv_sample = lmcs_derive_lut_sample(sample, input_pivot, lmcs->pivot,
inv_scale_coeff, i, max);
@@ -1198,7 +1283,7 @@ static int sh_alf_aps(const VVCSH *sh, const VVCFrameParamSets *fps)
return 0;
}
static void sh_slice_address(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps)
static int sh_slice_address(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps)
{
const int slice_address = sh->r->sh_slice_address;
@@ -1222,6 +1307,11 @@ static void sh_slice_address(VVCSH *sh, const H266RawSPS *sps, const VVCPPS *pps
sh->num_ctus_in_curr_slice += pps->r->row_height_val[tile_y] * pps->r->col_width_val[tile_x];
}
}
if (!sh->num_ctus_in_curr_slice)
return AVERROR_INVALIDDATA;
return 0;
}
static void sh_qp_y(VVCSH *sh, const H266RawPPS *pps, const H266RawPictureHeader *ph)
@@ -1318,7 +1408,9 @@ static int sh_derive(VVCSH *sh, const VVCFrameParamSets *fps)
const H266RawPictureHeader *ph = fps->ph.r;
int ret;
sh_slice_address(sh, sps, fps->pps);
ret = sh_slice_address(sh, sps, fps->pps);
if (ret < 0)
return ret;
ret = sh_alf_aps(sh, fps);
if (ret < 0)
return ret;
+20 -5
View File
@@ -21,6 +21,7 @@
*/
#include <stdatomic.h>
#include <stdbool.h>
#include "libavutil/mem.h"
#include "libavutil/thread.h"
@@ -29,10 +30,6 @@
#include "refs.h"
#define VVC_FRAME_FLAG_OUTPUT (1 << 0)
#define VVC_FRAME_FLAG_SHORT_REF (1 << 1)
#define VVC_FRAME_FLAG_LONG_REF (1 << 2)
#define VVC_FRAME_FLAG_BUMPING (1 << 3)
typedef struct FrameProgress {
atomic_int progress[VVC_PROGRESS_LAST];
@@ -50,6 +47,8 @@ void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
return;
frame->flags &= ~flags;
if (!(frame->flags & ~VVC_FRAME_FLAG_CORRUPT))
frame->flags = 0;
if (!frame->flags) {
av_frame_unref(frame->frame);
ff_refstruct_unref(&frame->sps);
@@ -246,6 +245,9 @@ int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const
if (nb_output) {
VVCFrame *frame = &fc->DPB[min_idx];
if (frame->flags & VVC_FRAME_FLAG_CORRUPT)
frame->frame->flags |= AV_FRAME_FLAG_CORRUPT;
ret = av_frame_ref(out, frame->frame);
if (frame->flags & VVC_FRAME_FLAG_BUMPING)
ff_vvc_unref_frame(fc, frame, VVC_FRAME_FLAG_OUTPUT | VVC_FRAME_FLAG_BUMPING);
@@ -355,7 +357,7 @@ static VVCFrame *generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int po
frame->poc = poc;
frame->sequence = s->seq_decode;
frame->flags = 0;
frame->flags = VVC_FRAME_FLAG_CORRUPT;
ff_vvc_report_frame_finished(frame);
@@ -390,6 +392,19 @@ static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *lis
if (ref == fc->ref || list->nb_refs >= VVC_MAX_REF_ENTRIES)
return AVERROR_INVALIDDATA;
if (!IS_CVSS(s)) {
const bool ref_corrupt = !ref || (ref->flags & VVC_FRAME_FLAG_CORRUPT);
const bool recovering = s->no_output_before_recovery_flag && !GDR_IS_RECOVERED(s);
if (ref_corrupt && !recovering) {
if (!(s->avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) &&
!(s->avctx->flags2 & AV_CODEC_FLAG2_SHOW_ALL))
return AVERROR_INVALIDDATA;
fc->ref->flags |= VVC_FRAME_FLAG_CORRUPT;
}
}
if (!ref) {
ref = generate_missing_ref(s, fc, poc);
if (!ref)
+6
View File
@@ -25,6 +25,12 @@
#include "dec.h"
#define VVC_FRAME_FLAG_OUTPUT (1 << 0)
#define VVC_FRAME_FLAG_SHORT_REF (1 << 1)
#define VVC_FRAME_FLAG_LONG_REF (1 << 2)
#define VVC_FRAME_FLAG_BUMPING (1 << 3)
#define VVC_FRAME_FLAG_CORRUPT (1 << 4)
int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, struct AVFrame *out, int no_output_of_prior_pics_flag, int flush);
void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc);
int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, struct AVFrame **frame);
+9 -2
View File
@@ -655,9 +655,9 @@ static void task_run_stage(VVCTask *t, VVCContext *s, VVCLocalContext *lc)
"frame %5d, %s(%3d, %3d) failed with %d\r\n",
(int)fc->decode_order, task_name[stage], t->rx, t->ry, ret);
}
if (!ret)
task_stage_done(t, s);
}
task_stage_done(t, s);
return;
}
@@ -822,6 +822,13 @@ int ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc)
}
}
}
for (int rs = 0; rs < ft->ctu_count; rs++) {
const VVCTask *t = ft->tasks + rs;
if (!t->sc) {
av_log(s->avctx, AV_LOG_ERROR, "frame %5d, CTU(%d, %d) not belong to any slice\r\n", (int)fc->decode_order, t->rx, t->ry);
return AVERROR_INVALIDDATA;
}
}
frame_thread_add_score(s, ft, 0, 0, VVC_TASK_STAGE_INIT);
return 0;
+3 -3
View File
@@ -446,7 +446,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
av_freep(pb);
av_dict_copy(&tmp, *opts, 0);
av_dict_copy(&tmp, opts2, 0);
ret = ffio_open_whitelist(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp, s->protocol_whitelist, s->protocol_blacklist);
ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
if (ret >= 0) {
// update cookies on http response with setcookies.
char *new_cookies = NULL;
@@ -1242,7 +1242,7 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
close_in = 1;
av_dict_copy(&opts, c->avio_opts, 0);
ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist);
ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts);
av_dict_free(&opts);
if (ret < 0)
return ret;
@@ -1385,7 +1385,7 @@ cleanup:
av_bprint_finalize(&buf, NULL);
if (close_in) {
avio_close(in);
ff_format_io_close(s, &in);
}
return ret;
}
+2 -2
View File
@@ -619,7 +619,7 @@ static void dash_free(AVFormatContext *s)
if (!c->single_file)
ffio_free_dyn_buf(&os->ctx->pb);
else
avio_close(os->ctx->pb);
ff_format_io_close(s, &os->ctx->pb);
}
ff_format_io_close(s, &os->out);
avformat_free_context(os->ctx);
@@ -1586,7 +1586,7 @@ static int dash_init(AVFormatContext *s)
ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
} else {
ctx->url = av_strdup(filename);
ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
ret = s->io_open(s, &ctx->pb, filename, AVIO_FLAG_WRITE, &opts);
}
av_dict_free(&opts);
if (ret < 0)
+1 -1
View File
@@ -364,7 +364,7 @@ fail:
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
av_dict_free(&tmp);
if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
avio_closep(&s->pb);
ff_format_io_close(s, &s->pb);
avformat_free_context(s);
*ps = NULL;
return ret;
+3 -5
View File
@@ -777,7 +777,7 @@ static int do_encrypt(AVFormatContext *s, VariantStream *vs)
return ret;
avio_seek(pb, 0, SEEK_CUR);
avio_write(pb, key, KEYSIZE);
avio_close(pb);
ff_format_io_close(s, &pb);
}
return 0;
}
@@ -1215,9 +1215,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs
const char *end;
double discont_program_date_time = 0;
if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
&s->interrupt_callback, NULL,
s->protocol_whitelist, s->protocol_blacklist)) < 0)
if ((ret = s->io_open(s, &in, url, AVIO_FLAG_READ, NULL)) < 0)
return ret;
ff_get_chomp_line(in, line, sizeof(line));
@@ -1313,7 +1311,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs
}
fail:
avio_close(in);
ff_format_io_close(s, &in);
return ret;
}
+4 -6
View File
@@ -1196,15 +1196,13 @@ static int mov_read_chnl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
version = avio_r8(pb);
flags = avio_rb24(pb);
if (version != 0 || flags != 0) {
av_log(c->fc, AV_LOG_ERROR,
"Unsupported 'chnl' box with version %d, flags: %#x",
av_log(c->fc, AV_LOG_WARNING,
"Unsupported 'chnl' box with version %d, flags: %#x\n",
version, flags);
return AVERROR_INVALIDDATA;
return 0;
}
ret = ff_mov_read_chnl(c->fc, pb, st);
if (ret < 0)
return ret;
ff_mov_read_chnl(c->fc, pb, st);
if (avio_tell(pb) != end) {
av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data inside chnl\n",
+23 -13
View File
@@ -375,6 +375,7 @@ static int mov_get_channel_layout(AVChannelLayout *ch_layout, uint32_t tag, uint
/* find the channel layout for the specified layout tag */
layout_map = find_layout_map(tag, map);
if (layout_map) {
AVChannelLayout tmp = { 0 };
int ret;
int map_layout_nb_channels = tag & 0xFFFF;
int nb_channels = ch_layout->nb_channels;
@@ -383,19 +384,23 @@ static int mov_get_channel_layout(AVChannelLayout *ch_layout, uint32_t tag, uint
if (omitted_channel_map >> map_layout_nb_channels)
return AVERROR_INVALIDDATA;
av_channel_layout_uninit(ch_layout);
ret = av_channel_layout_custom_init(ch_layout, nb_channels);
ret = av_channel_layout_custom_init(&tmp, nb_channels);
if (ret < 0)
return ret;
for (int i = 0, idx = 0; i < map_layout_nb_channels && idx < nb_channels; i++, omitted_channel_map >>= 1) {
if (!(omitted_channel_map & 1)) {
enum AVChannel id = layout_map[i].id;
ch_layout->u.map[idx++].id = (id != AV_CHAN_NONE ? id : AV_CHAN_UNKNOWN);
tmp.u.map[idx++].id = (id != AV_CHAN_NONE ? id : AV_CHAN_UNKNOWN);
}
}
return av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
if (ret < 0)
return ret;
av_channel_layout_uninit(ch_layout);
*ch_layout = tmp;
}
return 0;
}
@@ -543,6 +548,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
return 0;
if (layout_tag == MOV_CH_LAYOUT_USE_DESCRIPTIONS) {
AVChannelLayout tmp = { 0 };
int nb_channels = ch_layout->nb_channels;
if (!num_descr || num_descr < nb_channels) {
@@ -562,8 +568,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
num_descr = nb_channels;
}
av_channel_layout_uninit(ch_layout);
ret = av_channel_layout_custom_init(ch_layout, nb_channels);
ret = av_channel_layout_custom_init(&tmp, nb_channels);
if (ret < 0)
goto out;
@@ -580,12 +585,15 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
avio_rl32(pb); // mCoordinates[1]
avio_rl32(pb); // mCoordinates[2]
size -= 20;
ch_layout->u.map[i].id = mov_get_channel_id(label);
tmp.u.map[i].id = mov_get_channel_id(label);
}
ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
if (ret < 0)
goto out;
av_channel_layout_uninit(ch_layout);
*ch_layout = tmp;
} else if (layout_tag == MOV_CH_LAYOUT_USE_BITMAP) {
if (!ch_layout->nb_channels || av_popcount(bitmap) == ch_layout->nb_channels) {
if (bitmap < 0x40000) {
@@ -737,11 +745,10 @@ int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st)
av_log(s, AV_LOG_TRACE, "'chnl' layout %d\n", layout);
if (!layout) {
AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
AVChannelLayout tmp = { 0 }, *ch_layout = &st->codecpar->ch_layout;
int nb_channels = ch_layout->nb_channels;
av_channel_layout_uninit(ch_layout);
ret = av_channel_layout_custom_init(ch_layout, nb_channels);
ret = av_channel_layout_custom_init(&tmp, nb_channels);
if (ret < 0)
return ret;
@@ -762,12 +769,15 @@ int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st)
channel = AV_CHAN_UNKNOWN;
}
ch_layout->u.map[i].id = channel;
tmp.u.map[i].id = channel;
}
ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
if (ret < 0)
return ret;
av_channel_layout_uninit(ch_layout);
*ch_layout = tmp;
} else {
uint64_t omitted_channel_map = avio_rb64(pb);
ret = ff_mov_get_channel_layout_from_config(layout, &st->codecpar->ch_layout, omitted_channel_map);
+9
View File
@@ -27,6 +27,9 @@
#include "internal.h"
#include "oggdec.h"
/* CELT-over-Ogg streams use at most a couple of vorbiscomment "extra" headers. */
#define CELT_MAX_EXTRA_HEADERS 16
struct oggcelt_private {
int extra_headers_left;
};
@@ -62,6 +65,12 @@ static int celt_header(AVFormatContext *s, int idx)
overlap = AV_RL32(p + 48);
/* unused bytes per packet field skipped */
extra_headers = AV_RL32(p + 56);
if (extra_headers > CELT_MAX_EXTRA_HEADERS) {
av_log(s, AV_LOG_ERROR,
"Too many CELT extra headers (%u)\n", extra_headers);
av_free(priv);
return AVERROR_INVALIDDATA;
}
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_CELT;
st->codecpar->sample_rate = sample_rate;
+4 -1
View File
@@ -224,8 +224,11 @@ static int fixup_vorbis_headers(AVFormatContext *as,
int i, offset, len, err;
int buf_len;
unsigned char *ptr;
uint64_t total_len = (uint64_t)priv->len[0] + priv->len[1] + priv->len[2];
if (total_len + total_len / 255 + 64 > INT_MAX)
return AVERROR_INVALIDDATA;
len = priv->len[0] + priv->len[1] + priv->len[2];
len = total_len;
buf_len = len + len / 255 + 64;
if (*buf)
+1 -1
View File
@@ -32,7 +32,7 @@
#include "version_major.h"
#define LIBAVFORMAT_VERSION_MINOR 7
#define LIBAVFORMAT_VERSION_MICRO 102
#define LIBAVFORMAT_VERSION_MICRO 103
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \