h265decoder: Fix DPB size calculation

MaxDpbSize specified in A.4.2 tells upper bound of decoded picture
buffer size but does not tell actual required size.
Use max_dec_pic_buffering value as a dpb size. Some backends
such as DXVA and NVDEC might require pre-allocated DPB buffer
and unnecessary large DPB size will result in waste of GPU memory.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6101>
This commit is contained in:
Seungha Yang 2024-02-12 23:51:12 +09:00 committed by GStreamer Marge Bot
parent 144657dc0d
commit d98c922995

View file

@ -462,9 +462,18 @@ gst_h265_decoder_get_max_dpb_size_from_sps (GstH265Decoder * self,
guint PicSizeInSamplesY;
/* Default is the worst case level 6.2 */
guint32 MaxLumaPS = G_MAXUINT32;
const gint MaxDpbPicBuf = 6;
gint MaxDpbPicBuf = 6;
gint max_dpb_size;
/* A.4.2, maxDpbPicBuf is equal to 6 for all profiles where the value of
* sps_curr_pic_ref_enabled_flag is required to be equal to 0 and 7 for all
* profiles where the value of sps_curr_pic_ref_enabled_flag is not required
* to be equal to 0 */
if (sps->sps_scc_extension_flag) {
/* sps_curr_pic_ref_enabled_flag could be non-zero only if profile is SCC */
MaxDpbPicBuf = 7;
}
/* Unknown level */
if (sps->profile_tier_level.level_idc == 0)
return 16;
@ -498,7 +507,25 @@ gst_h265_decoder_get_max_dpb_size_from_sps (GstH265Decoder * self,
else
max_dpb_size = MaxDpbPicBuf;
return MIN (max_dpb_size, 16);
max_dpb_size = MIN (max_dpb_size, 16);
/* MaxDpbSize is not an actual maximum required buffer size.
* Instead, it indicates upper bound for other syntax elements, such as
* sps_max_dec_pic_buffering_minus1. If this bitstream can satisfy
* the requirement, use this as our dpb size */
if (sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] + 1 <=
max_dpb_size) {
GST_DEBUG_OBJECT (self, "max_dec_pic_buffering_minus1 %d < MaxDpbSize %d",
sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1],
max_dpb_size);
max_dpb_size =
sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] + 1;
} else {
/* not reliable values, use 16 */
max_dpb_size = 16;
}
return max_dpb_size;
}
static GstFlowReturn
@ -1793,12 +1820,28 @@ gst_h265_decoder_dpb_init (GstH265Decoder * self, const GstH265Slice * slice,
}
}
} else {
/* TODO: According to 7.4.3.3.3, TwoVersionsOfCurrDecPicFlag
* should be considered.
*
* NOTE: (See 8.1.3) if TwoVersionsOfCurrDecPicFlag is 1,
* current picture requires two picture buffers allocated in DPB storage,
* one is decoded picture *after* in-loop filter, and the other is
* decoded picture *before* in-loop filter, so that current picture
* can be used as a reference of the current picture
* (e.g., intra block copy method in SCC).
* Here TwoVersionsOfCurrDecPicFlag takes effect in order to ensure
* at least two empty DPB buffer before starting current picture decoding.
*
* However, two DPB picture allocation is not implemented
* in current baseclass (which would imply that we are doing reference
* picture management wrongly in case of SCC).
* Let's ignore TwoVersionsOfCurrDecPicFlag for now */
guint max_dec_pic_buffering =
sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] + 1;
gst_h265_dpb_delete_unused (priv->dpb);
while (gst_h265_dpb_needs_bump (priv->dpb,
sps->max_num_reorder_pics[sps->max_sub_layers_minus1],
priv->SpsMaxLatencyPictures,
sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] +
1)) {
priv->SpsMaxLatencyPictures, max_dec_pic_buffering)) {
to_output = gst_h265_dpb_bump (priv->dpb, FALSE);
/* Something wrong... */