mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
decoder: h264: fix closure of "other-field" gap.
When a dummy "other-field" is inserted, it is assumed to inherit the reference flags from the first field, and the sliding window decoded reference picture marking process is also executed so that corrupted frames are moved out as early as possible. While doing so, we also try to output frames that now contain a single valid field picture, prior to inserting any other picture into the DPB. Note: this may be superfluous currently based on the fact that dpb_add() combines the two most recent pairable fields, but this process would be further simplified later on.
This commit is contained in:
parent
80a7ab0959
commit
d4ccae8398
1 changed files with 29 additions and 6 deletions
|
@ -307,6 +307,7 @@ struct _GstVaapiFrameStore {
|
|||
GstVaapiPictureH264 *buffers[2];
|
||||
guint num_buffers;
|
||||
guint output_needed;
|
||||
guint output_called;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -340,6 +341,7 @@ gst_vaapi_frame_store_new(GstVaapiPictureH264 *picture)
|
|||
fs->buffers[1] = NULL;
|
||||
fs->num_buffers = 1;
|
||||
fs->output_needed = 0;
|
||||
fs->output_called = 0;
|
||||
|
||||
if (picture->output_flag) {
|
||||
picture->output_needed = TRUE;
|
||||
|
@ -728,6 +730,7 @@ dpb_output(GstVaapiDecoderH264 *decoder, GstVaapiFrameStore *fs)
|
|||
|
||||
g_return_val_if_fail(fs != NULL, FALSE);
|
||||
|
||||
fs->output_called++;
|
||||
if (!gst_vaapi_frame_store_is_complete(fs))
|
||||
return TRUE;
|
||||
|
||||
|
@ -740,6 +743,7 @@ dpb_output(GstVaapiDecoderH264 *decoder, GstVaapiFrameStore *fs)
|
|||
}
|
||||
|
||||
fs->output_needed = 0;
|
||||
fs->output_called = 0;
|
||||
if (!picture)
|
||||
return TRUE;
|
||||
return gst_vaapi_picture_output(GST_VAAPI_PICTURE_CAST(picture));
|
||||
|
@ -1059,6 +1063,12 @@ dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
|
|||
}
|
||||
}
|
||||
|
||||
// Try to output the previous frame again if it was not submitted yet
|
||||
// e.g. delayed while waiting for the next field, or a field gap was closed
|
||||
fs = priv->prev_frames[picture->base.voc];
|
||||
if (fs && fs->output_called)
|
||||
dpb_output(decoder, fs);
|
||||
|
||||
// Create new frame store, and split fields if necessary
|
||||
fs = gst_vaapi_frame_store_new(picture);
|
||||
if (!fs)
|
||||
|
@ -3088,8 +3098,9 @@ static GstVaapiPictureH264 *
|
|||
fill_picture_other_field_gap(GstVaapiDecoderH264 *decoder,
|
||||
GstVaapiPictureH264 *f0)
|
||||
{
|
||||
GstVaapiDecoderH264Private * const priv = &decoder->priv;
|
||||
GstVaapiPictureH264 *prev_picture, *f1;
|
||||
gint prev_picture_index;
|
||||
gint prev_frame_index;
|
||||
guint picture_structure;
|
||||
|
||||
picture_structure = f0->base.structure;
|
||||
|
@ -3106,10 +3117,10 @@ fill_picture_other_field_gap(GstVaapiDecoderH264 *decoder,
|
|||
}
|
||||
GST_VAAPI_PICTURE_FLAG_SET(f0, GST_VAAPI_PICTURE_FLAG_ONEFIELD);
|
||||
|
||||
prev_picture_index = dpb_find_nearest_prev_poc(decoder, f0,
|
||||
prev_frame_index = dpb_find_nearest_prev_poc(decoder, f0,
|
||||
picture_structure, &prev_picture);
|
||||
if (prev_picture_index < 0)
|
||||
return NULL;
|
||||
if (prev_frame_index < 0)
|
||||
goto error_find_field;
|
||||
|
||||
f1 = gst_vaapi_picture_h264_new_field(f0);
|
||||
if (!f1)
|
||||
|
@ -3126,18 +3137,30 @@ fill_picture_other_field_gap(GstVaapiDecoderH264 *decoder,
|
|||
(GST_VAAPI_PICTURE_FLAG_SKIPPED |
|
||||
GST_VAAPI_PICTURE_FLAG_GHOST));
|
||||
|
||||
gst_vaapi_picture_h264_set_reference(f1, 0, FALSE);
|
||||
gst_vaapi_picture_replace(&priv->current_picture, f1);
|
||||
gst_vaapi_picture_unref(f1);
|
||||
|
||||
init_picture_ref_lists(decoder, f1);
|
||||
init_picture_refs_pic_num(decoder, f1, NULL);
|
||||
if (!exec_ref_pic_marking_sliding_window(decoder))
|
||||
goto error_exec_ref_pic_marking;
|
||||
if (!dpb_add(decoder, f1))
|
||||
goto error_append_field;
|
||||
gst_vaapi_picture_unref(f1);
|
||||
return f1;
|
||||
|
||||
/* ERRORS */
|
||||
error_find_field:
|
||||
GST_ERROR("failed to find field with POC nearest to %d", f0->base.poc);
|
||||
return NULL;
|
||||
error_allocate_field:
|
||||
GST_ERROR("failed to allocate missing field for previous frame store");
|
||||
return NULL;
|
||||
error_exec_ref_pic_marking:
|
||||
GST_ERROR("failed to execute reference picture marking process");
|
||||
return NULL;
|
||||
error_append_field:
|
||||
GST_ERROR("failed to add missing field into previous frame store");
|
||||
gst_vaapi_picture_unref(f1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue