mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
h265decoder: Calculate DPB size based on level
As specified in "A.4 Tiers and levels", calculate DPB size based on level in order to avoid over preallocated DPB Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4840>
This commit is contained in:
parent
b687e19e10
commit
e422a991f3
1 changed files with 74 additions and 15 deletions
|
@ -424,23 +424,68 @@ gst_h265_decoder_set_latency (GstH265Decoder * self, const GstH265SPS * sps,
|
||||||
gst_video_decoder_set_latency (GST_VIDEO_DECODER (self), min, max);
|
gst_video_decoder_set_latency (GST_VIDEO_DECODER (self), min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
typedef struct
|
||||||
gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
|
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
const gchar *level_name;
|
||||||
gint max_dpb_size;
|
guint8 level_idc;
|
||||||
gint prev_max_dpb_size;
|
guint32 MaxLumaPs;
|
||||||
gint MaxLumaPS;
|
} GstH265LevelLimits;
|
||||||
const gint MaxDpbPicBuf = 6;
|
|
||||||
gint PicSizeInSamplesY;
|
/* *INDENT-OFF* */
|
||||||
guint8 field_seq_flag = 0;
|
/* Table A.8 - General tier and level limits */
|
||||||
guint8 progressive_source_flag = 0;
|
static const GstH265LevelLimits level_limits[] = {
|
||||||
guint8 interlaced_source_flag = 0;
|
/* level idc MaxLumaPs */
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
{ "1", 30, 36864 },
|
||||||
|
{ "2", 60, 122880 },
|
||||||
|
{ "2.1", 63, 245760 },
|
||||||
|
{ "3", 90, 552960 },
|
||||||
|
{ "3.1", 93, 983040 },
|
||||||
|
{ "4", 120, 2228224 },
|
||||||
|
{ "4.1", 123, 2228224 },
|
||||||
|
{ "5", 150, 8912896 },
|
||||||
|
{ "5.1", 153, 8912896 },
|
||||||
|
{ "5.2", 156, 8912896 },
|
||||||
|
{ "6", 180, 35651584 },
|
||||||
|
{ "6.1", 183, 35651584 },
|
||||||
|
{ "6.2", 186, 35651584 },
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
static gint
|
||||||
|
gst_h265_decoder_get_max_dpb_size_from_sps (GstH265Decoder * self,
|
||||||
|
GstH265SPS * sps)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
guint PicSizeInSamplesY;
|
||||||
|
/* Default is the worst case level 6.2 */
|
||||||
|
guint32 MaxLumaPS = G_MAXUINT32;
|
||||||
|
const gint MaxDpbPicBuf = 6;
|
||||||
|
gint max_dpb_size;
|
||||||
|
|
||||||
|
/* Unknown level */
|
||||||
|
if (sps->profile_tier_level.level_idc == 0)
|
||||||
|
return 16;
|
||||||
|
|
||||||
/* A.4.1 */
|
|
||||||
MaxLumaPS = 35651584;
|
|
||||||
PicSizeInSamplesY = sps->width * sps->height;
|
PicSizeInSamplesY = sps->width * sps->height;
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (level_limits); i++) {
|
||||||
|
if (sps->profile_tier_level.level_idc <= level_limits[i].level_idc) {
|
||||||
|
if (PicSizeInSamplesY <= level_limits[i].MaxLumaPs) {
|
||||||
|
MaxLumaPS = level_limits[i].MaxLumaPs;
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (self,
|
||||||
|
"%u (%dx%d) exceeds allowed max luma sample for level \"%s\" %u",
|
||||||
|
PicSizeInSamplesY, sps->width, sps->height,
|
||||||
|
level_limits[i].level_name, level_limits[i].MaxLumaPs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unknown level */
|
||||||
|
if (MaxLumaPS == G_MAXUINT32)
|
||||||
|
return 16;
|
||||||
|
|
||||||
|
/* A.4.2 */
|
||||||
if (PicSizeInSamplesY <= (MaxLumaPS >> 2))
|
if (PicSizeInSamplesY <= (MaxLumaPS >> 2))
|
||||||
max_dpb_size = MaxDpbPicBuf * 4;
|
max_dpb_size = MaxDpbPicBuf * 4;
|
||||||
else if (PicSizeInSamplesY <= (MaxLumaPS >> 1))
|
else if (PicSizeInSamplesY <= (MaxLumaPS >> 1))
|
||||||
|
@ -450,7 +495,21 @@ gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
|
||||||
else
|
else
|
||||||
max_dpb_size = MaxDpbPicBuf;
|
max_dpb_size = MaxDpbPicBuf;
|
||||||
|
|
||||||
max_dpb_size = MIN (max_dpb_size, 16);
|
return MIN (max_dpb_size, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
|
||||||
|
{
|
||||||
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
|
gint max_dpb_size;
|
||||||
|
gint prev_max_dpb_size;
|
||||||
|
guint8 field_seq_flag = 0;
|
||||||
|
guint8 progressive_source_flag = 0;
|
||||||
|
guint8 interlaced_source_flag = 0;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
max_dpb_size = gst_h265_decoder_get_max_dpb_size_from_sps (self, sps);
|
||||||
|
|
||||||
if (sps->vui_parameters_present_flag)
|
if (sps->vui_parameters_present_flag)
|
||||||
field_seq_flag = sps->vui_params.field_seq_flag;
|
field_seq_flag = sps->vui_params.field_seq_flag;
|
||||||
|
|
Loading…
Reference in a new issue