[FFmpeg-cvslog] lavc/vvc: Error if SPS ID is duplicated within CVS

Frank Plowman git at videolan.org
Sun Apr 7 05:38:42 EEST 2024


ffmpeg | branch: master | Frank Plowman <post at frankplowman.com> | Sat Apr  6 13:46:09 2024 +0000| [2d79ae3f8a3306d24afe43ba505693a8dbefd21b] | committer: Nuo Mi

lavc/vvc: Error if SPS ID is duplicated within CVS

Key line from the spec is:

"All SPS NAL units with a particular value of sps_seq_parameter_set_id
in a CVS shall have the same content."

Prior to this patch, the VVC decoder's behaviour on encountering a
duplicated SPS ID (within the entire bitstream, not restricted to
a CVS) was simply to replace the entry in the SPS lookup table with the
new data.  Illegal bitstreams with multiple SPSs in the same CVS sharing
an ID but differing elsewhere could cause all manner of issues.

The patch tracks which SPS IDs have been used in the given CVS using the
new sps_id_used field of VVCParamSets.  If it encounters an SPS with an
ID already in use and whose content differs from the previous SPS, it
throws an AVERROR_INVALIDDATA.

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

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=2d79ae3f8a3306d24afe43ba505693a8dbefd21b
---

 libavcodec/vvc/ps.c | 28 ++++++++++++++++++++--------
 libavcodec/vvc/ps.h |  3 +++
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c
index 0365feab47..3c71c34bae 100644
--- a/libavcodec/vvc/ps.c
+++ b/libavcodec/vvc/ps.c
@@ -219,14 +219,22 @@ fail:
     return NULL;
 }
 
-static int decode_sps(VVCParamSets *ps, const H266RawSPS *rsps, void *log_ctx)
+static int decode_sps(VVCParamSets *ps, const H266RawSPS *rsps, void *log_ctx, int is_clvss)
 {
     const int sps_id        = rsps->sps_seq_parameter_set_id;
     const VVCSPS *old_sps   = ps->sps_list[sps_id];
     const VVCSPS *sps;
 
-    if (old_sps && old_sps->r == rsps)
-        return 0;
+    if (is_clvss) {
+        ps->sps_id_used = 0;
+    }
+
+    if (old_sps) {
+        if (old_sps->r == rsps || !memcmp(old_sps->r, rsps, sizeof(*old_sps->r)))
+            return 0;
+        else if (ps->sps_id_used & (1 << sps_id))
+            return AVERROR_INVALIDDATA;
+    }
 
     sps = sps_alloc(rsps, log_ctx);
     if (!sps)
@@ -234,6 +242,7 @@ static int decode_sps(VVCParamSets *ps, const H266RawSPS *rsps, void *log_ctx)
 
     ff_refstruct_unref(&ps->sps_list[sps_id]);
     ps->sps_list[sps_id] = sps;
+    ps->sps_id_used |= (1 << sps_id);
 
     return 0;
 }
@@ -610,7 +619,7 @@ static int decode_pps(VVCParamSets *ps, const H266RawPPS *rpps)
     return ret;
 }
 
-static int decode_ps(VVCParamSets *ps, const CodedBitstreamH266Context *h266, void *log_ctx)
+static int decode_ps(VVCParamSets *ps, const CodedBitstreamH266Context *h266, void *log_ctx, int is_clvss)
 {
     const H266RawPictureHeader *ph = h266->ph;
     const H266RawPPS *rpps;
@@ -628,7 +637,7 @@ static int decode_ps(VVCParamSets *ps, const CodedBitstreamH266Context *h266, vo
     if (!rsps)
         return AVERROR_INVALIDDATA;
 
-    ret = decode_sps(ps, rsps, log_ctx);
+    ret = decode_sps(ps, rsps, log_ctx, is_clvss);
     if (ret < 0)
         return ret;
 
@@ -867,13 +876,16 @@ int ff_vvc_decode_frame_ps(VVCFrameParamSets *fps, struct VVCContext *s)
     int ret = 0;
     VVCParamSets *ps                        = &s->ps;
     const CodedBitstreamH266Context *h266   = s->cbc->priv_data;
+    int is_clvss;
+
+    decode_recovery_flag(s);
+    is_clvss = IS_CLVSS(s);
 
-    ret = decode_ps(ps, h266, s->avctx);
+    ret = decode_ps(ps, h266, s->avctx, is_clvss);
     if (ret < 0)
         return ret;
 
-    decode_recovery_flag(s);
-    ret = decode_frame_ps(fps, ps, h266, s->poc_tid0, IS_CLVSS(s));
+    ret = decode_frame_ps(fps, ps, h266, s->poc_tid0, is_clvss);
     decode_recovery_poc(s, &fps->ph);
     return ret;
 }
diff --git a/libavcodec/vvc/ps.h b/libavcodec/vvc/ps.h
index 3efb097b41..78f1687fef 100644
--- a/libavcodec/vvc/ps.h
+++ b/libavcodec/vvc/ps.h
@@ -214,6 +214,9 @@ typedef struct VVCParamSets {
     const VVCALF            *alf_list[VVC_MAX_ALF_COUNT];       ///< RefStruct reference
     const H266RawAPS        *lmcs_list[VVC_MAX_LMCS_COUNT];     ///< RefStruct reference
     const VVCScalingList    *scaling_list[VVC_MAX_SL_COUNT];    ///< RefStruct reference
+
+    // Bit field of SPS IDs used in the current CVS
+    uint16_t                 sps_id_used;
 } VVCParamSets;
 
 typedef struct VVCFrameParamSets {



More information about the ffmpeg-cvslog mailing list