mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-06-16 04:32:47 +02:00
lavc/vvc: Store RefStruct references to referenced PSs/headers in slice
This loosens the coupling between CBS and the decoder by no longer using CodedBitstreamH266Context (containing the most recently parsed PSs & PH) to retrieve the PSs & PH in the decoder. Doing so is beneficial in two ways: 1. It improves robustness to the case in which an AVPacket doesn't contain precisely one PU. 2. It allows the decoder parameter set manager to properly handle the case in which a single PU (erroneously) contains conflicting parameter sets. Signed-off-by: Frank Plowman <post@frankplowman.com>
This commit is contained in:
+23
-5
@@ -1086,6 +1086,7 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
|
||||
{
|
||||
GetBitContext gbc;
|
||||
int err;
|
||||
CodedBitstreamH266Context *h266 = ctx->priv_data;
|
||||
|
||||
err = init_get_bits8(&gbc, unit->data, unit->data_size);
|
||||
if (err < 0)
|
||||
@@ -1201,7 +1202,13 @@ static int cbs_h266_read_nal_unit(CodedBitstreamContext *ctx,
|
||||
err = cbs_h266_replace_ph(ctx, unit, &slice->header.sh_picture_header);
|
||||
if (err < 0)
|
||||
return err;
|
||||
slice->ph_ref = NULL;
|
||||
} else {
|
||||
slice->ph_ref = av_refstruct_ref(h266->ph_ref);
|
||||
}
|
||||
slice->ph = h266->ph;
|
||||
slice->pps = av_refstruct_ref(h266->pps[slice->ph->ph_pic_parameter_set_id]);
|
||||
slice->sps = av_refstruct_ref(h266->sps[slice->pps->pps_seq_parameter_set_id]);
|
||||
|
||||
slice->header_size = pos / 8;
|
||||
slice->data_size = len - pos / 8;
|
||||
@@ -2037,6 +2044,16 @@ static const CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = {
|
||||
CBS_UNIT_TYPE_END_OF_LIST
|
||||
};
|
||||
|
||||
static void cbs_h266_free_slice(AVRefStructOpaque unused, void *content)
|
||||
{
|
||||
H266RawSlice *slice = content;
|
||||
av_buffer_unref(&slice->data_ref);
|
||||
av_refstruct_unref(&slice->sps);
|
||||
av_refstruct_unref(&slice->pps);
|
||||
av_refstruct_unref(&slice->ph_ref);
|
||||
}
|
||||
|
||||
|
||||
static void cbs_h266_free_sei(AVRefStructOpaque unused, void *content)
|
||||
{
|
||||
H266RawSEI *sei = content;
|
||||
@@ -2065,11 +2082,12 @@ static const CodedBitstreamUnitTypeDescriptor cbs_h266_unit_types[] = {
|
||||
CBS_UNIT_TYPE_POD(VVC_PH_NUT , H266RawPH),
|
||||
CBS_UNIT_TYPE_POD(VVC_AUD_NUT, H266RawAUD),
|
||||
|
||||
CBS_UNIT_RANGE_INTERNAL_REF(VVC_TRAIL_NUT, VVC_RASL_NUT,
|
||||
H266RawSlice, data),
|
||||
|
||||
CBS_UNIT_RANGE_INTERNAL_REF(VVC_IDR_W_RADL, VVC_GDR_NUT,
|
||||
H266RawSlice, data),
|
||||
CBS_UNIT_TYPES_COMPLEX((VVC_TRAIL_NUT, VVC_STSA_NUT, VVC_RADL_NUT),
|
||||
H266RawSlice, cbs_h266_free_slice),
|
||||
CBS_UNIT_TYPES_COMPLEX((VVC_RASL_NUT, VVC_IDR_W_RADL, VVC_IDR_N_LP),
|
||||
H266RawSlice, cbs_h266_free_slice),
|
||||
CBS_UNIT_TYPES_COMPLEX((VVC_CRA_NUT, VVC_GDR_NUT),
|
||||
H266RawSlice, cbs_h266_free_slice),
|
||||
|
||||
CBS_UNIT_TYPES_COMPLEX((VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT),
|
||||
H266RawSEI, cbs_h266_free_sei),
|
||||
|
||||
@@ -848,6 +848,11 @@ typedef struct H266RawSlice {
|
||||
size_t header_size;
|
||||
size_t data_size;
|
||||
int data_bit_start;
|
||||
|
||||
H266RawSPS *sps; ///< RefStruct reference to referred-to SPS
|
||||
H266RawPPS *pps; ///< RefStruct reference to referred-to PPS
|
||||
H266RawPictureHeader *ph;
|
||||
void *ph_ref; ///< RefStruct reference backing referred-to PH above
|
||||
} H266RawSlice;
|
||||
|
||||
typedef struct H266RawSEI {
|
||||
|
||||
@@ -852,8 +852,6 @@ static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
av_refstruct_replace(&sc->ref, unit->content_ref);
|
||||
|
||||
if (is_first_slice) {
|
||||
ret = frame_start(s, fc, sc);
|
||||
if (ret < 0)
|
||||
@@ -927,7 +925,7 @@ static int export_frame_params(VVCContext *s, const VVCFrameContext *fc)
|
||||
|
||||
static int frame_setup(VVCFrameContext *fc, VVCContext *s)
|
||||
{
|
||||
int ret = ff_vvc_decode_frame_ps(&fc->ps, s);
|
||||
int ret = ff_vvc_decode_frame_ps(fc, s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -954,6 +952,7 @@ static int decode_slice(VVCContext *s, VVCFrameContext *fc, AVBufferRef *buf_ref
|
||||
return ret;
|
||||
|
||||
sc = fc->slices[fc->nb_slices];
|
||||
av_refstruct_replace(&sc->ref, unit->content_ref);
|
||||
|
||||
s->vcl_unit_type = nal->type;
|
||||
if (is_first_slice) {
|
||||
|
||||
+14
-18
@@ -743,21 +743,16 @@ static int decode_pps(VVCParamSets *ps, const H266RawPPS *rpps)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int decode_ps(VVCParamSets *ps, AVCodecContext *c, const CodedBitstreamH266Context *h266, int is_clvss)
|
||||
static int decode_ps(VVCParamSets *ps, AVCodecContext *c, const SliceContext *sc, int is_clvss)
|
||||
{
|
||||
const H266RawPictureHeader *ph = h266->ph;
|
||||
const H266RawPPS *rpps;
|
||||
const H266RawSPS *rsps;
|
||||
const H266RawSlice *sl = sc->ref;
|
||||
const H266RawPPS *rpps = sl->pps;
|
||||
const H266RawSPS *rsps = sl->sps;
|
||||
int ret;
|
||||
|
||||
if (!ph)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
rpps = h266->pps[ph->ph_pic_parameter_set_id];
|
||||
if (!rpps)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
rsps = h266->sps[rpps->pps_seq_parameter_set_id];
|
||||
if (!rsps)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
@@ -1005,23 +1000,23 @@ static int decode_ph(VVCFrameParamSets *fps, const H266RawPictureHeader *rph, vo
|
||||
}
|
||||
|
||||
static int decode_frame_ps(VVCFrameParamSets *fps, const VVCParamSets *ps,
|
||||
const CodedBitstreamH266Context *h266, const int poc_tid0, const int is_clvss)
|
||||
const SliceContext *sc, const int poc_tid0, const int is_clvss, const VVCContext *s)
|
||||
{
|
||||
const H266RawPictureHeader *ph = h266->ph;
|
||||
const H266RawPPS *rpps;
|
||||
const H266RawSlice *sl = sc->ref;
|
||||
const H266RawPictureHeader *ph = sl->ph;
|
||||
const H266RawPPS *rpps = sl->pps;
|
||||
int ret;
|
||||
|
||||
if (!ph)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
rpps = h266->pps[ph->ph_pic_parameter_set_id];
|
||||
if (!rpps)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
av_refstruct_replace(&fps->sps, ps->sps_list[rpps->pps_seq_parameter_set_id]);
|
||||
av_refstruct_replace(&fps->pps, ps->pps_list[rpps->pps_pic_parameter_set_id]);
|
||||
|
||||
ret = decode_ph(fps, ph, h266->ph_ref, poc_tid0, is_clvss);
|
||||
ret = decode_ph(fps, ph, sl->ph_ref, poc_tid0, is_clvss);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1058,21 +1053,22 @@ static void decode_recovery_poc(VVCContext *s, const VVCPH *ph)
|
||||
}
|
||||
}
|
||||
|
||||
int ff_vvc_decode_frame_ps(VVCFrameParamSets *fps, struct VVCContext *s)
|
||||
int ff_vvc_decode_frame_ps(struct VVCFrameContext *fc, struct VVCContext *s)
|
||||
{
|
||||
int ret = 0;
|
||||
VVCFrameParamSets *fps = &fc->ps;
|
||||
VVCParamSets *ps = &s->ps;
|
||||
const CodedBitstreamH266Context *h266 = s->cbc->priv_data;
|
||||
const SliceContext *sc = fc->slices[0];
|
||||
int is_clvss;
|
||||
|
||||
decode_recovery_flag(s);
|
||||
is_clvss = IS_CLVSS(s);
|
||||
|
||||
ret = decode_ps(ps, s->avctx, h266, is_clvss);
|
||||
ret = decode_ps(ps, s->avctx, sc, is_clvss);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = decode_frame_ps(fps, ps, h266, s->poc_tid0, is_clvss);
|
||||
ret = decode_frame_ps(fps, ps, sc, s->poc_tid0, is_clvss, s);
|
||||
decode_recovery_poc(s, &fps->ph);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+2
-1
@@ -266,8 +266,9 @@ typedef struct VVCSH {
|
||||
} VVCSH;
|
||||
|
||||
struct VVCContext;
|
||||
struct VVCFrameContext;
|
||||
|
||||
int ff_vvc_decode_frame_ps(VVCFrameParamSets *fps, struct VVCContext *s);
|
||||
int ff_vvc_decode_frame_ps(struct VVCFrameContext *fc, struct VVCContext *s);
|
||||
int ff_vvc_decode_aps(VVCParamSets *ps, const CodedBitstreamUnit *unit);
|
||||
int ff_vvc_decode_sh(VVCSH *sh, const VVCFrameParamSets *ps, const CodedBitstreamUnit *unit);
|
||||
void ff_vvc_frame_ps_free(VVCFrameParamSets *fps);
|
||||
|
||||
Reference in New Issue
Block a user