mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
h264: detect new pictures from decode-units.
Update is_new_picture() to cope with GstVaapiDecoderUnitH264, instead of assuming frame boundaries when first_mb_in_slice is zero.
This commit is contained in:
parent
d9ec93fe46
commit
f8a9e49fd8
1 changed files with 16 additions and 24 deletions
|
@ -448,6 +448,7 @@ G_DEFINE_TYPE(GstVaapiDecoderH264,
|
||||||
struct _GstVaapiDecoderH264Private {
|
struct _GstVaapiDecoderH264Private {
|
||||||
GstH264NalParser *parser;
|
GstH264NalParser *parser;
|
||||||
GstVaapiPictureH264 *current_picture;
|
GstVaapiPictureH264 *current_picture;
|
||||||
|
GstVaapiDecoderUnitH264 *prev_slice_unit;
|
||||||
GstVaapiFrameStore *prev_frame;
|
GstVaapiFrameStore *prev_frame;
|
||||||
GstVaapiFrameStore *dpb[16];
|
GstVaapiFrameStore *dpb[16];
|
||||||
guint dpb_count;
|
guint dpb_count;
|
||||||
|
@ -796,6 +797,7 @@ gst_vaapi_decoder_h264_close(GstVaapiDecoderH264 *decoder)
|
||||||
GstVaapiDecoderH264Private * const priv = decoder->priv;
|
GstVaapiDecoderH264Private * const priv = decoder->priv;
|
||||||
|
|
||||||
gst_vaapi_picture_replace(&priv->current_picture, NULL);
|
gst_vaapi_picture_replace(&priv->current_picture, NULL);
|
||||||
|
gst_vaapi_decoder_unit_replace(&priv->prev_slice_unit, NULL);
|
||||||
|
|
||||||
dpb_clear(decoder);
|
dpb_clear(decoder);
|
||||||
|
|
||||||
|
@ -2510,25 +2512,17 @@ fill_picture(GstVaapiDecoderH264 *decoder,
|
||||||
|
|
||||||
/* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
|
/* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
|
||||||
static gboolean
|
static gboolean
|
||||||
is_new_picture(
|
is_new_picture(GstVaapiDecoderUnitH264 *unit,
|
||||||
GstVaapiDecoderH264 *decoder,
|
GstVaapiDecoderUnitH264 *prev_unit)
|
||||||
GstH264NalUnit *nalu,
|
|
||||||
GstH264SliceHdr *slice_hdr
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
GstVaapiDecoderH264Private * const priv = decoder->priv;
|
GstH264SliceHdr * const slice_hdr = &unit->data.slice_hdr;
|
||||||
GstH264PPS * const pps = slice_hdr->pps;
|
GstH264PPS * const pps = slice_hdr->pps;
|
||||||
GstH264SPS * const sps = pps->sequence;
|
GstH264SPS * const sps = pps->sequence;
|
||||||
GstVaapiSliceH264 *slice;
|
|
||||||
GstH264SliceHdr *prev_slice_hdr;
|
GstH264SliceHdr *prev_slice_hdr;
|
||||||
|
|
||||||
if (!priv->current_picture)
|
if (!prev_unit)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
prev_slice_hdr = &prev_unit->data.slice_hdr;
|
||||||
slice = gst_vaapi_picture_h264_get_last_slice(priv->current_picture);
|
|
||||||
if (!slice)
|
|
||||||
return FALSE;
|
|
||||||
prev_slice_hdr = &slice->slice_hdr;
|
|
||||||
|
|
||||||
#define CHECK_EXPR(expr, field_name) do { \
|
#define CHECK_EXPR(expr, field_name) do { \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
|
@ -2554,8 +2548,8 @@ is_new_picture(
|
||||||
CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
|
CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
|
||||||
|
|
||||||
/* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
|
/* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
|
||||||
CHECK_EXPR(((GST_VAAPI_PICTURE_IS_REFERENCE(priv->current_picture) ^
|
CHECK_EXPR((unit->nalu.ref_idc != 0) ==
|
||||||
(nalu->ref_idc != 0)) == 0), "nal_ref_idc");
|
(prev_unit->nalu.ref_idc != 0), "nal_ref_idc");
|
||||||
|
|
||||||
/* POC type is 0 for both and either pic_order_cnt_lsb differs in
|
/* POC type is 0 for both and either pic_order_cnt_lsb differs in
|
||||||
value or delta_pic_order_cnt_bottom differs in value */
|
value or delta_pic_order_cnt_bottom differs in value */
|
||||||
|
@ -2573,11 +2567,10 @@ is_new_picture(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IdrPicFlag differs in value */
|
/* IdrPicFlag differs in value */
|
||||||
CHECK_EXPR(((GST_VAAPI_PICTURE_IS_IDR(priv->current_picture) ^
|
CHECK_VALUE(&unit->nalu, &prev_unit->nalu, idr_pic_flag);
|
||||||
(nalu->type == GST_H264_NAL_SLICE_IDR)) == 0), "IdrPicFlag");
|
|
||||||
|
|
||||||
/* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
|
/* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
|
||||||
if (GST_VAAPI_PICTURE_IS_IDR(priv->current_picture))
|
if (unit->nalu.idr_pic_flag)
|
||||||
CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
|
CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
|
||||||
|
|
||||||
#undef CHECK_EXPR
|
#undef CHECK_EXPR
|
||||||
|
@ -2789,8 +2782,10 @@ decode_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnitH264 *unit)
|
||||||
|
|
||||||
GST_DEBUG("slice (%u bytes)", nalu->size);
|
GST_DEBUG("slice (%u bytes)", nalu->size);
|
||||||
|
|
||||||
if (!priv->got_sps || !priv->got_pps)
|
if (!priv->got_sps || !priv->got_pps) {
|
||||||
|
GST_ERROR("not initialized yet");
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
unit->base.buffer = gst_buffer_create_sub(
|
unit->base.buffer = gst_buffer_create_sub(
|
||||||
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
|
GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
|
||||||
|
@ -3082,12 +3077,9 @@ 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;
|
||||||
/* XXX: assume we got a new frame if first_mb_in_slice is set
|
if (is_new_picture(unit, priv->prev_slice_unit))
|
||||||
to zero, thus ignoring Arbitrary Slice Order (ASO) feature
|
|
||||||
from Baseline profile */
|
|
||||||
if (unit->nalu.offset + 2 <= unit->nalu.size &&
|
|
||||||
(unit->nalu.data[unit->nalu.offset + 1] & 0x80))
|
|
||||||
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
|
||||||
|
gst_vaapi_decoder_unit_replace(&priv->prev_slice_unit, unit);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (unit->nalu.type >= 14 && unit->nalu.type <= 18)
|
if (unit->nalu.type >= 14 && unit->nalu.type <= 18)
|
||||||
|
|
Loading…
Reference in a new issue