This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit ef533ef3a3ea063eb72edbf510d006684f260f7f Author: Wu Jianhua <[email protected]> AuthorDate: Thu Aug 27 04:08:10 2026 +0800 Commit: jianhuaw <[email protected]> CommitDate: Sun Sep 6 20:55:01 2026 +0000 avcodec/vvc/ps: allow out-of-range ph_recovery_poc_cnt in non-strict mode The GDR stream in ticket #24265 carries ph_recovery_poc_cnt equal to 128 even though MaxPicOrderCntLsb is 16. H.266 7.4.3.8 requires the value to be in the range [0, MaxPicOrderCntLsb - 1]. CBS currently rejects it before the decoder can proceed. The former CBS upper bound also admitted MaxPicOrderCntLsb itself. The syntax element does not affect entropy decoding, however, so treating it as a fatal error in normal operation prevents decoding a stream beyond this non-conforming value. Store the raw ue(v) value as uint32_t and defer the conformance check until the recovery POC is derived. In non-strict mode, accept values whose derived POC is representable as an int and emit a warning. In strict mode, reject values above MaxPicOrderCntLsb - 1. Fixes #24265. Signed-off-by: Wu Jianhua <[email protected]> --- libavcodec/cbs_h266.h | 2 +- libavcodec/cbs_h266_syntax_template.c | 9 ++++++++- libavcodec/vvc/ps.c | 38 ++++++++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h index 0dc7d96828..d315f6b64a 100644 --- a/libavcodec/cbs_h266.h +++ b/libavcodec/cbs_h266.h @@ -681,7 +681,7 @@ typedef struct H266RawPictureHeader { uint8_t ph_intra_slice_allowed_flag; uint8_t ph_pic_parameter_set_id; uint16_t ph_pic_order_cnt_lsb; - uint8_t ph_recovery_poc_cnt; + uint32_t ph_recovery_poc_cnt; uint8_t ph_extra_bit[16]; uint8_t ph_poc_msb_cycle_present_flag; uint8_t ph_poc_msb_cycle_val; diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index fa90aba1de..55178db1ea 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2687,9 +2687,16 @@ static int FUNC(picture_header) (CodedBitstreamContext *ctx, RWContext *rw, } ub(sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4, ph_pic_order_cnt_lsb); - if (current->ph_gdr_pic_flag) + if (current->ph_gdr_pic_flag) { +#ifdef READ + // H.266 7.4.3.8: ph_recovery_poc_cnt shall be in [0, MaxPicOrderCntLsb - 1]. + // The range check is deferred to decode_recovery_poc(). + ue(ph_recovery_poc_cnt, 0, UINT32_MAX - 1); +#else ue(ph_recovery_poc_cnt, 0, (1 << (sps->sps_log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1); +#endif + } for (i = 0; i < sps->sps_num_extra_ph_bytes * 8; i++) { if (sps->sps_extra_ph_bit_present_flag[i]) diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c index a591851238..c27c8a43c2 100644 --- a/libavcodec/vvc/ps.c +++ b/libavcodec/vvc/ps.c @@ -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 <limits.h> #include <stdbool.h> #include "libavcodec/cbs_h266.h" @@ -1045,14 +1046,39 @@ static void decode_recovery_flag(VVCContext *s) s->no_output_before_recovery_flag = s->last_eos; } -static void decode_recovery_poc(VVCContext *s, const VVCPH *ph) +static int decode_recovery_poc(VVCContext *s, const VVCFrameParamSets *fps) { + const VVCPH *ph = &fps->ph; + + if (IS_GDR(s)) { + const uint32_t recovery_poc_cnt = ph->r->ph_recovery_poc_cnt; + const uint32_t max_recovery_poc_cnt = fps->sps->max_pic_order_cnt_lsb - 1; + + const int64_t recovery_poc = (int64_t)ph->poc + recovery_poc_cnt; + if (recovery_poc < INT_MIN || recovery_poc > INT_MAX) { + av_log(s->avctx, AV_LOG_ERROR, "Recovery point POC out of range: %"PRId64".\n", recovery_poc); + return AVERROR_INVALIDDATA; + } + + if (recovery_poc_cnt > max_recovery_poc_cnt) { + const int strict = s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; + av_log(s->avctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, + "ph_recovery_poc_cnt out of range: %"PRIu32 + ", expected [0, %"PRIu32"].\n", recovery_poc_cnt, max_recovery_poc_cnt); + if (strict) + return AVERROR_INVALIDDATA; + } + + if (s->no_output_before_recovery_flag) + s->gdr_recovery_point_poc = recovery_poc; + } + if (s->no_output_before_recovery_flag) { - if (IS_GDR(s)) - s->gdr_recovery_point_poc = ph->poc + ph->r->ph_recovery_poc_cnt; if (!GDR_IS_RECOVERED(s) && s->gdr_recovery_point_poc <= ph->poc) GDR_SET_RECOVERED(s); } + + return 0; } int ff_vvc_decode_frame_ps(struct VVCFrameContext *fc, struct VVCContext *s) @@ -1071,8 +1097,10 @@ int ff_vvc_decode_frame_ps(struct VVCFrameContext *fc, struct VVCContext *s) return ret; ret = decode_frame_ps(fps, ps, sc, s->poc_tid0, is_clvss, s); - decode_recovery_poc(s, &fps->ph); - return ret; + if (ret < 0) + return ret; + + return decode_recovery_poc(s, fps); } void ff_vvc_frame_ps_free(VVCFrameParamSets *fps) -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
