mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
decoder: h264: fix detection of access unit boundaries.
In order to have a stricter conforming implementation, we need to carefully detect access unit boundaries. Additional operations could be necessary to perform at those boundaries.
This commit is contained in:
parent
a6215a0757
commit
ae1d8267d9
1 changed files with 93 additions and 2 deletions
|
@ -57,6 +57,27 @@ typedef struct _GstVaapiPictureH264 GstVaapiPictureH264;
|
||||||
/* --- H.264 Parser Info --- */
|
/* --- H.264 Parser Info --- */
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extended decoder unit flags:
|
||||||
|
*
|
||||||
|
* @GST_VAAPI_DECODER_UNIT_AU_START: marks the start of an access unit.
|
||||||
|
* @GST_VAAPI_DECODER_UNIT_AU_END: marks the end of an access unit.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
/* This flag does not strictly follow the definitions (7.4.1.2.3)
|
||||||
|
for detecting the start of an access unit as we are only
|
||||||
|
interested in knowing if the current slice is the first one or
|
||||||
|
the last one in the current access unit */
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_AU_START = (
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_LAST << 0),
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_AU_END = (
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_LAST << 1),
|
||||||
|
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAGS_AU = (
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_AU_END),
|
||||||
|
};
|
||||||
|
|
||||||
#define GST_VAAPI_PARSER_INFO_H264(obj) \
|
#define GST_VAAPI_PARSER_INFO_H264(obj) \
|
||||||
((GstVaapiParserInfoH264 *)(obj))
|
((GstVaapiParserInfoH264 *)(obj))
|
||||||
|
|
||||||
|
@ -70,6 +91,7 @@ struct _GstVaapiParserInfoH264 {
|
||||||
GstH264SliceHdr slice_hdr;
|
GstH264SliceHdr slice_hdr;
|
||||||
} data;
|
} data;
|
||||||
guint state;
|
guint state;
|
||||||
|
guint flags; // Same as decoder unit flags (persistent)
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -124,6 +146,10 @@ gst_vaapi_parser_info_h264_new(void)
|
||||||
* Extended picture flags:
|
* Extended picture flags:
|
||||||
*
|
*
|
||||||
* @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
|
* @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
|
||||||
|
* @GST_VAAPI_PICTURE_FLAG_AU_START: flag that marks the start of an
|
||||||
|
* access unit (AU)
|
||||||
|
* @GST_VAAPI_PICTURE_FLAG_AU_END: flag that marks the end of an
|
||||||
|
* access unit (AU)
|
||||||
* @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
|
* @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
|
||||||
* "used for short-term reference"
|
* "used for short-term reference"
|
||||||
* @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
|
* @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
|
||||||
|
@ -134,6 +160,8 @@ gst_vaapi_parser_info_h264_new(void)
|
||||||
enum {
|
enum {
|
||||||
GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
|
GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
|
||||||
GST_VAAPI_PICTURE_FLAG_REFERENCE2 = (GST_VAAPI_PICTURE_FLAG_LAST << 1),
|
GST_VAAPI_PICTURE_FLAG_REFERENCE2 = (GST_VAAPI_PICTURE_FLAG_LAST << 1),
|
||||||
|
GST_VAAPI_PICTURE_FLAG_AU_START = (GST_VAAPI_PICTURE_FLAG_LAST << 4),
|
||||||
|
GST_VAAPI_PICTURE_FLAG_AU_END = (GST_VAAPI_PICTURE_FLAG_LAST << 5),
|
||||||
|
|
||||||
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
|
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
|
||||||
GST_VAAPI_PICTURE_FLAG_REFERENCE),
|
GST_VAAPI_PICTURE_FLAG_REFERENCE),
|
||||||
|
@ -453,6 +481,25 @@ struct _GstVaapiDecoderH264Class {
|
||||||
static gboolean
|
static gboolean
|
||||||
exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
|
exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
|
||||||
|
|
||||||
|
/* Determines the view order index (VOIdx) from the supplied view_id */
|
||||||
|
static gint
|
||||||
|
get_view_order_index(GstH264SPS *sps, guint16 view_id)
|
||||||
|
{
|
||||||
|
GstH264SPSExtMVC *mvc;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (!sps || sps->extension_type != GST_H264_NAL_EXTENSION_MVC)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mvc = &sps->extension.mvc;
|
||||||
|
for (i = 0; i <= mvc->num_views_minus1; i++) {
|
||||||
|
if (mvc->view[i].view_id == view_id)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
GST_ERROR("failed to find VOIdx from view_id (%d)", view_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
|
@ -2698,6 +2745,33 @@ is_new_picture(GstVaapiParserInfoH264 *pi, GstVaapiParserInfoH264 *prev_pi)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Detection of a new access unit, assuming we are already in presence
|
||||||
|
of a new picture */
|
||||||
|
static gboolean
|
||||||
|
is_new_access_unit(GstVaapiParserInfoH264 *pi, GstVaapiParserInfoH264 *prev_pi)
|
||||||
|
{
|
||||||
|
GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
|
||||||
|
GstH264SliceHdr *prev_slice_hdr;
|
||||||
|
GstH264NalUnitExtensionMVC *mvc, *prev_mvc;
|
||||||
|
gint voc, prev_voc;
|
||||||
|
|
||||||
|
g_return_val_if_fail(is_new_picture(pi, prev_pi), FALSE);
|
||||||
|
|
||||||
|
if (!prev_pi)
|
||||||
|
return TRUE;
|
||||||
|
prev_slice_hdr = &prev_pi->data.slice_hdr;
|
||||||
|
|
||||||
|
mvc = &pi->nalu.extension.mvc;
|
||||||
|
prev_mvc = &prev_pi->nalu.extension.mvc;
|
||||||
|
if (mvc->view_id == prev_mvc->view_id)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
voc = get_view_order_index(slice_hdr->pps->sequence, mvc->view_id);
|
||||||
|
prev_voc = get_view_order_index(prev_slice_hdr->pps->sequence,
|
||||||
|
prev_mvc->view_id);
|
||||||
|
return voc < prev_voc;
|
||||||
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
decode_picture(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
decode_picture(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
||||||
{
|
{
|
||||||
|
@ -2954,6 +3028,12 @@ decode_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check wether this is the first/last slice in the current access unit */
|
||||||
|
if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_START)
|
||||||
|
GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_AU_START);
|
||||||
|
if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_END)
|
||||||
|
GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_AU_END);
|
||||||
|
|
||||||
slice = GST_VAAPI_SLICE_NEW(H264, decoder,
|
slice = GST_VAAPI_SLICE_NEW(H264, decoder,
|
||||||
(map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
|
(map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
|
||||||
gst_buffer_unmap(buffer, &map_info);
|
gst_buffer_unmap(buffer, &map_info);
|
||||||
|
@ -3259,6 +3339,7 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
flags = 0;
|
flags = 0;
|
||||||
switch (pi->nalu.type) {
|
switch (pi->nalu.type) {
|
||||||
case GST_H264_NAL_AU_DELIMITER:
|
case GST_H264_NAL_AU_DELIMITER:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case GST_H264_NAL_FILLER_DATA:
|
case GST_H264_NAL_FILLER_DATA:
|
||||||
|
@ -3269,11 +3350,13 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case GST_H264_NAL_SEQ_END:
|
case GST_H264_NAL_SEQ_END:
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
|
||||||
break;
|
break;
|
||||||
case GST_H264_NAL_SPS:
|
case GST_H264_NAL_SPS:
|
||||||
case GST_H264_NAL_SUBSET_SPS:
|
case GST_H264_NAL_SUBSET_SPS:
|
||||||
case GST_H264_NAL_PPS:
|
case GST_H264_NAL_PPS:
|
||||||
case GST_H264_NAL_SEI:
|
case GST_H264_NAL_SEI:
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
break;
|
break;
|
||||||
case GST_H264_NAL_SLICE_EXT:
|
case GST_H264_NAL_SLICE_EXT:
|
||||||
|
@ -3285,8 +3368,11 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
case GST_H264_NAL_SLICE_IDR:
|
case GST_H264_NAL_SLICE_IDR:
|
||||||
case GST_H264_NAL_SLICE:
|
case GST_H264_NAL_SLICE:
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
|
||||||
if (is_new_picture(pi, priv->prev_slice_pi))
|
if (is_new_picture(pi, priv->prev_slice_pi)) {
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
|
if (is_new_access_unit(pi, priv->prev_slice_pi))
|
||||||
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
|
||||||
|
}
|
||||||
gst_vaapi_parser_info_h264_replace(&priv->prev_slice_pi, pi);
|
gst_vaapi_parser_info_h264_replace(&priv->prev_slice_pi, pi);
|
||||||
break;
|
break;
|
||||||
case GST_H264_NAL_SPS_EXT:
|
case GST_H264_NAL_SPS_EXT:
|
||||||
|
@ -3297,17 +3383,22 @@ gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
|
||||||
case GST_H264_NAL_PREFIX_UNIT:
|
case GST_H264_NAL_PREFIX_UNIT:
|
||||||
/* skip Prefix NAL units for now */
|
/* skip Prefix NAL units for now */
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP |
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP |
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
|
||||||
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (pi->nalu.type >= 14 && pi->nalu.type <= 18)
|
if (pi->nalu.type >= 14 && pi->nalu.type <= 18)
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
|
||||||
|
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((flags & GST_VAAPI_DECODER_UNIT_FLAGS_AU) && priv->prev_slice_pi)
|
||||||
|
priv->prev_slice_pi->flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
|
||||||
GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
|
GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
|
||||||
|
|
||||||
pi->nalu.data = NULL;
|
pi->nalu.data = NULL;
|
||||||
pi->state = priv->parser_state;
|
pi->state = priv->parser_state;
|
||||||
|
pi->flags = flags;
|
||||||
gst_vaapi_parser_info_h264_replace(&priv->prev_pi, pi);
|
gst_vaapi_parser_info_h264_replace(&priv->prev_pi, pi);
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue