mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
decoder: h264: dynamically allocate the DPB.
Dynamically allocate the Decoded Picture Buffer (DPB) and add provisions for supporting the MVC allocation requirements.
This commit is contained in:
parent
ae1d8267d9
commit
42b112f8bd
1 changed files with 80 additions and 16 deletions
|
@ -424,9 +424,11 @@ struct _GstVaapiDecoderH264Private {
|
||||||
GstVaapiParserInfoH264 *prev_pi;
|
GstVaapiParserInfoH264 *prev_pi;
|
||||||
GstVaapiParserInfoH264 *prev_slice_pi;
|
GstVaapiParserInfoH264 *prev_slice_pi;
|
||||||
GstVaapiFrameStore *prev_frame;
|
GstVaapiFrameStore *prev_frame;
|
||||||
GstVaapiFrameStore *dpb[16];
|
GstVaapiFrameStore **dpb;
|
||||||
guint dpb_count;
|
guint dpb_count;
|
||||||
guint dpb_size;
|
guint dpb_size;
|
||||||
|
guint dpb_size_max;
|
||||||
|
guint max_views;
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
GstVaapiEntrypoint entrypoint;
|
GstVaapiEntrypoint entrypoint;
|
||||||
GstVaapiChromaType chroma_type;
|
GstVaapiChromaType chroma_type;
|
||||||
|
@ -481,6 +483,14 @@ struct _GstVaapiDecoderH264Class {
|
||||||
static gboolean
|
static gboolean
|
||||||
exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
|
exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
|
||||||
|
|
||||||
|
/* Determines if the supplied profile is one of the MVC set */
|
||||||
|
static gboolean
|
||||||
|
is_mvc_profile(GstH264Profile profile)
|
||||||
|
{
|
||||||
|
return profile == GST_H264_PROFILE_MULTIVIEW_HIGH ||
|
||||||
|
profile == GST_H264_PROFILE_STEREO_HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determines the view order index (VOIdx) from the supplied view_id */
|
/* Determines the view order index (VOIdx) from the supplied view_id */
|
||||||
static gint
|
static gint
|
||||||
get_view_order_index(GstH264SPS *sps, guint16 view_id)
|
get_view_order_index(GstH264SPS *sps, guint16 view_id)
|
||||||
|
@ -500,10 +510,19 @@ get_view_order_index(GstH264SPS *sps, guint16 view_id)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determines NumViews */
|
||||||
|
static guint
|
||||||
|
get_num_views(GstH264SPS *sps)
|
||||||
|
{
|
||||||
|
return 1 + (sps->extension_type == GST_H264_NAL_EXTENSION_MVC ?
|
||||||
|
sps->extension.mvc.num_views_minus1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get number of reference frames to use */
|
/* Get number of reference frames to use */
|
||||||
static guint
|
static guint
|
||||||
get_max_dec_frame_buffering(GstH264SPS *sps)
|
get_max_dec_frame_buffering(GstH264SPS *sps)
|
||||||
{
|
{
|
||||||
|
guint num_views, max_dpb_frames;
|
||||||
guint max_dec_frame_buffering, PicSizeMbs;
|
guint max_dec_frame_buffering, PicSizeMbs;
|
||||||
GstVaapiLevelH264 level;
|
GstVaapiLevelH264 level;
|
||||||
const GstVaapiH264LevelLimits *level_limits;
|
const GstVaapiH264LevelLimits *level_limits;
|
||||||
|
@ -514,13 +533,18 @@ get_max_dec_frame_buffering(GstH264SPS *sps)
|
||||||
else
|
else
|
||||||
level = gst_vaapi_utils_h264_get_level(sps->level_idc);
|
level = gst_vaapi_utils_h264_get_level(sps->level_idc);
|
||||||
level_limits = gst_vaapi_utils_h264_get_level_limits(level);
|
level_limits = gst_vaapi_utils_h264_get_level_limits(level);
|
||||||
if (!level_limits)
|
if (G_UNLIKELY(!level_limits)) {
|
||||||
return 16;
|
GST_FIXME("unsupported level_idc value (%d)", sps->level_idc);
|
||||||
|
max_dec_frame_buffering = 16;
|
||||||
|
}
|
||||||
|
else {
|
||||||
PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
|
PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
|
||||||
(sps->pic_height_in_map_units_minus1 + 1) *
|
(sps->pic_height_in_map_units_minus1 + 1) *
|
||||||
(sps->frame_mbs_only_flag ? 1 : 2));
|
(sps->frame_mbs_only_flag ? 1 : 2));
|
||||||
max_dec_frame_buffering = level_limits->MaxDpbMbs / PicSizeMbs;
|
max_dec_frame_buffering = level_limits->MaxDpbMbs / PicSizeMbs;
|
||||||
|
}
|
||||||
|
if (is_mvc_profile(sps->profile_idc))
|
||||||
|
max_dec_frame_buffering <<= 1;
|
||||||
|
|
||||||
/* VUI parameters */
|
/* VUI parameters */
|
||||||
if (sps->vui_parameters_present_flag) {
|
if (sps->vui_parameters_present_flag) {
|
||||||
|
@ -542,8 +566,10 @@ get_max_dec_frame_buffering(GstH264SPS *sps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_dec_frame_buffering > 16)
|
num_views = get_num_views(sps);
|
||||||
max_dec_frame_buffering = 16;
|
max_dpb_frames = 16 * (num_views > 1 ? g_bit_storage(num_views - 1) : 1);
|
||||||
|
if (max_dec_frame_buffering > max_dpb_frames)
|
||||||
|
max_dec_frame_buffering = max_dpb_frames;
|
||||||
else if (max_dec_frame_buffering < sps->num_ref_frames)
|
else if (max_dec_frame_buffering < sps->num_ref_frames)
|
||||||
max_dec_frame_buffering = sps->num_ref_frames;
|
max_dec_frame_buffering = sps->num_ref_frames;
|
||||||
return MAX(1, max_dec_frame_buffering);
|
return MAX(1, max_dec_frame_buffering);
|
||||||
|
@ -760,13 +786,30 @@ dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static gboolean
|
||||||
dpb_reset(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
|
dpb_reset(GstVaapiDecoderH264 *decoder, guint dpb_size)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderH264Private * const priv = &decoder->priv;
|
GstVaapiDecoderH264Private * const priv = &decoder->priv;
|
||||||
|
|
||||||
priv->dpb_size = get_max_dec_frame_buffering(sps);
|
if (dpb_size < priv->dpb_count)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (dpb_size > priv->dpb_size_max) {
|
||||||
|
priv->dpb = g_try_realloc_n(priv->dpb, dpb_size, sizeof(*priv->dpb));
|
||||||
|
if (!priv->dpb)
|
||||||
|
return FALSE;
|
||||||
|
memset(&priv->dpb[priv->dpb_size_max], 0,
|
||||||
|
(dpb_size - priv->dpb_size_max) * sizeof(*priv->dpb));
|
||||||
|
priv->dpb_size_max = dpb_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->dpb_size < dpb_size)
|
||||||
|
priv->dpb_size = dpb_size;
|
||||||
|
else if (dpb_size < priv->dpb_count)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
GST_DEBUG("DPB size %u", priv->dpb_size);
|
GST_DEBUG("DPB size %u", priv->dpb_size);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
|
@ -831,6 +874,10 @@ gst_vaapi_decoder_h264_destroy(GstVaapiDecoder *base_decoder)
|
||||||
|
|
||||||
gst_vaapi_decoder_h264_close(decoder);
|
gst_vaapi_decoder_h264_close(decoder);
|
||||||
|
|
||||||
|
g_free(priv->dpb);
|
||||||
|
priv->dpb = NULL;
|
||||||
|
priv->dpb_size = 0;
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(priv->pps); i++)
|
for (i = 0; i < G_N_ELEMENTS(priv->pps); i++)
|
||||||
gst_vaapi_parser_info_h264_replace(&priv->pps[i], NULL);
|
gst_vaapi_parser_info_h264_replace(&priv->pps[i], NULL);
|
||||||
gst_vaapi_parser_info_h264_replace(&priv->active_pps, NULL);
|
gst_vaapi_parser_info_h264_replace(&priv->active_pps, NULL);
|
||||||
|
@ -965,7 +1012,13 @@ ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
GstVaapiChromaType chroma_type;
|
GstVaapiChromaType chroma_type;
|
||||||
gboolean reset_context = FALSE;
|
gboolean reset_context = FALSE;
|
||||||
guint mb_width, mb_height;
|
guint mb_width, mb_height, dpb_size;
|
||||||
|
|
||||||
|
dpb_size = get_max_dec_frame_buffering(sps);
|
||||||
|
if (priv->dpb_size < dpb_size) {
|
||||||
|
GST_DEBUG("DPB size increased");
|
||||||
|
reset_context = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
profile = get_profile(decoder, sps);
|
profile = get_profile(decoder, sps);
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
|
@ -1022,14 +1075,15 @@ ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
|
||||||
info.chroma_type = priv->chroma_type;
|
info.chroma_type = priv->chroma_type;
|
||||||
info.width = sps->width;
|
info.width = sps->width;
|
||||||
info.height = sps->height;
|
info.height = sps->height;
|
||||||
info.ref_frames = get_max_dec_frame_buffering(sps);
|
info.ref_frames = dpb_size;
|
||||||
|
|
||||||
if (!gst_vaapi_decoder_ensure_context(GST_VAAPI_DECODER(decoder), &info))
|
if (!gst_vaapi_decoder_ensure_context(GST_VAAPI_DECODER(decoder), &info))
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||||
priv->has_context = TRUE;
|
priv->has_context = TRUE;
|
||||||
|
|
||||||
/* Reset DPB */
|
/* Reset DPB */
|
||||||
dpb_reset(decoder, sps);
|
if (!dpb_reset(decoder, dpb_size))
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1153,6 +1207,9 @@ parse_sps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
||||||
if (result != GST_H264_PARSER_OK)
|
if (result != GST_H264_PARSER_OK)
|
||||||
return get_status(result);
|
return get_status(result);
|
||||||
|
|
||||||
|
/* Reset defaults */
|
||||||
|
priv->max_views = 1;
|
||||||
|
|
||||||
priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SPS;
|
priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SPS;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1231,6 +1288,7 @@ parse_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
||||||
GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
|
GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
|
||||||
GstH264NalUnit * const nalu = &pi->nalu;
|
GstH264NalUnit * const nalu = &pi->nalu;
|
||||||
GstH264ParserResult result;
|
GstH264ParserResult result;
|
||||||
|
guint num_views;
|
||||||
|
|
||||||
GST_DEBUG("parse slice");
|
GST_DEBUG("parse slice");
|
||||||
|
|
||||||
|
@ -1275,6 +1333,12 @@ parse_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
||||||
if (result != GST_H264_PARSER_OK)
|
if (result != GST_H264_PARSER_OK)
|
||||||
return get_status(result);
|
return get_status(result);
|
||||||
|
|
||||||
|
num_views = get_num_views(slice_hdr->pps->sequence);
|
||||||
|
if (priv->max_views < num_views) {
|
||||||
|
priv->max_views = num_views;
|
||||||
|
GST_DEBUG("maximum number of views changed to %u", num_views);
|
||||||
|
}
|
||||||
|
|
||||||
priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SLICE;
|
priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SLICE;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue