mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
libs: decoder: h264: push frames as soon as possible
Push frames downstream as soon as possible instead of waiting until they are ejected from the DPB. This patch makes the decoder not comply with the H.264 specification, but it is required for some video cameras. https://bugzilla.gnome.org/show_bug.cgi?id=762509 Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
This commit is contained in:
parent
11f461fb10
commit
66d26da39f
1 changed files with 68 additions and 5 deletions
|
@ -800,17 +800,31 @@ dpb_find_nearest_prev_poc (GstVaapiDecoderH264 * decoder,
|
|||
|
||||
/* Finds the picture with the lowest POC that needs to be output */
|
||||
static gint
|
||||
dpb_find_lowest_poc (GstVaapiDecoderH264 * decoder,
|
||||
GstVaapiPictureH264 * picture, GstVaapiPictureH264 ** found_picture_ptr)
|
||||
dpb_find_lowest_poc_for_output (GstVaapiDecoderH264 * decoder,
|
||||
GstVaapiPictureH264 * picture, GstVaapiPictureH264 ** found_picture_ptr,
|
||||
gboolean * can_be_output)
|
||||
{
|
||||
GstVaapiDecoderH264Private *const priv = &decoder->priv;
|
||||
GstVaapiPictureH264 *found_picture = NULL;
|
||||
guint i, j, found_index = -1;
|
||||
guint i, j, found_index = -1, found_poc = -1;
|
||||
gboolean is_first = TRUE;
|
||||
gint last_output_poc = -1;
|
||||
|
||||
for (i = 0; i < priv->dpb_count; i++) {
|
||||
GstVaapiFrameStore *const fs = priv->dpb[i];
|
||||
if (!fs->output_needed)
|
||||
if (!fs->output_needed) {
|
||||
/* find the maximum poc of any previously output frames that are
|
||||
* still held in the DPB. */
|
||||
if (can_be_output != NULL) {
|
||||
for (j = 0; j < fs->num_buffers; j++) {
|
||||
if (is_first || fs->buffers[j]->base.poc > last_output_poc) {
|
||||
is_first = FALSE;
|
||||
last_output_poc = fs->buffers[j]->base.poc;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (picture && picture->base.view_id != fs->view_id)
|
||||
continue;
|
||||
for (j = 0; j < fs->num_buffers; j++) {
|
||||
|
@ -820,7 +834,27 @@ dpb_find_lowest_poc (GstVaapiDecoderH264 * decoder,
|
|||
if (!found_picture || found_picture->base.poc > pic->base.poc ||
|
||||
(found_picture->base.poc == pic->base.poc &&
|
||||
found_picture->base.voc > pic->base.voc))
|
||||
found_picture = pic, found_index = i;
|
||||
found_picture = pic, found_index = i, found_poc = pic->base.poc;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_be_output != NULL) {
|
||||
/* found_picture can be output if it's the first frame in the DPB,
|
||||
* or if there's no gap between it and the most recently output
|
||||
* frame. */
|
||||
*can_be_output = FALSE;
|
||||
if (found_picture &&
|
||||
gst_vaapi_frame_store_is_complete (priv->dpb[found_index])) {
|
||||
if (is_first) {
|
||||
*can_be_output = TRUE;
|
||||
} else if (((int) (found_poc)) > ((int) (last_output_poc))) {
|
||||
*can_be_output = (found_poc - last_output_poc) <= 2;
|
||||
} else {
|
||||
/* A frame with a higher poc has already been sent. No choice
|
||||
* now but to drop this frame */
|
||||
GST_WARNING ("dropping out-of-sequence frame");
|
||||
priv->dpb[found_index]->output_needed = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,6 +863,16 @@ dpb_find_lowest_poc (GstVaapiDecoderH264 * decoder,
|
|||
return found_index;
|
||||
}
|
||||
|
||||
/* Finds the picture with the lowest POC that needs to be output */
|
||||
static gint
|
||||
dpb_find_lowest_poc (GstVaapiDecoderH264 * decoder,
|
||||
GstVaapiPictureH264 * picture, GstVaapiPictureH264 ** found_picture_ptr)
|
||||
{
|
||||
return dpb_find_lowest_poc_for_output (decoder, picture, found_picture_ptr,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Finds the picture with the lowest VOC that needs to be output */
|
||||
static gint
|
||||
dpb_find_lowest_voc (GstVaapiDecoderH264 * decoder,
|
||||
|
@ -908,6 +952,22 @@ dpb_bump (GstVaapiDecoderH264 * decoder, GstVaapiPictureH264 * picture)
|
|||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
dpb_output_ready_frames (GstVaapiDecoderH264 * decoder)
|
||||
{
|
||||
GstVaapiDecoderH264Private *const priv = &decoder->priv;
|
||||
gboolean can_output = FALSE;
|
||||
gint found_index;
|
||||
|
||||
while (TRUE) {
|
||||
found_index = dpb_find_lowest_poc_for_output (decoder,
|
||||
priv->current_picture, NULL, &can_output);
|
||||
if (found_index < 0 || !can_output)
|
||||
break;
|
||||
dpb_output (decoder, priv->dpb[found_index]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dpb_clear (GstVaapiDecoderH264 * decoder, GstVaapiPictureH264 * picture)
|
||||
{
|
||||
|
@ -1662,6 +1722,9 @@ decode_current_picture (GstVaapiDecoderH264 * decoder)
|
|||
goto error;
|
||||
if (!dpb_add (decoder, picture))
|
||||
goto error;
|
||||
|
||||
if (priv->force_low_latency)
|
||||
dpb_output_ready_frames (decoder);
|
||||
gst_vaapi_picture_replace (&priv->current_picture, NULL);
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
|
||||
|
|
Loading…
Reference in a new issue