va: deinterlace: Push the forgotten leading frames if forward reference > 0

The current code forgets to push the first several frames if the forward
reference > 0. They are just cached in history array and will never be
deinterlaced and pushed.
For the first several frames, even the forward reference frames are not
enough, we still need to deinterlace them as normal and push them after that.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7348>
This commit is contained in:
He Junyan 2024-08-13 22:41:00 +08:00 committed by GStreamer Marge Bot
parent 2447cf1077
commit 11a0b40b6e

View file

@ -93,6 +93,7 @@ struct _GstVaDeinterlace
VAProcDeinterlacingType method; VAProcDeinterlacingType method;
guint num_backward_references; guint num_backward_references;
guint num_forward_references;
GstBuffer *history[8]; GstBuffer *history[8];
gint hcount; gint hcount;
@ -126,8 +127,10 @@ _reset_history (GstVaDeinterlace * self)
gint i; gint i;
for (i = 0; i < self->hcount; i++) for (i = 0; i < self->hcount; i++)
gst_buffer_unref (self->history[i]); gst_clear_buffer (&self->history[i]);
self->hcount = 0; self->hcount = 0;
self->hcurr = -1;
} }
static void static void
@ -215,6 +218,8 @@ gst_va_deinterlace_submit_input_buffer (GstBaseTransform * trans,
gst_buffer_unref (buf); gst_buffer_unref (buf);
self->hcurr = MIN (self->hcount, self->num_forward_references);
if (self->hcount < self->hdepth) { if (self->hcount < self->hdepth) {
self->history[self->hcount++] = inbuf; self->history[self->hcount++] = inbuf;
} else { } else {
@ -224,7 +229,7 @@ gst_va_deinterlace_submit_input_buffer (GstBaseTransform * trans,
self->history[i] = inbuf; self->history[i] = inbuf;
} }
if (self->history[self->hcurr]) g_assert (self->history[self->hcurr]);
self->curr_field = FIRST_FIELD; self->curr_field = FIRST_FIELD;
return ret; return ret;
@ -236,7 +241,6 @@ _build_filter (GstVaDeinterlace * self)
GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self); GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self);
guint i, num_caps; guint i, num_caps;
VAProcFilterCapDeinterlacing *caps; VAProcFilterCapDeinterlacing *caps;
guint32 num_forward_references;
caps = gst_va_filter_get_filter_caps (btrans->filter, caps = gst_va_filter_get_filter_caps (btrans->filter,
VAProcFilterDeinterlacing, &num_caps); VAProcFilterDeinterlacing, &num_caps);
@ -248,16 +252,18 @@ _build_filter (GstVaDeinterlace * self)
continue; continue;
if (gst_va_filter_add_deinterlace_buffer (btrans->filter, self->method, if (gst_va_filter_add_deinterlace_buffer (btrans->filter, self->method,
&num_forward_references, &self->num_backward_references)) { &self->num_forward_references, &self->num_backward_references)) {
self->hdepth = num_forward_references + self->num_backward_references + 1; self->hdepth =
self->num_forward_references + self->num_backward_references + 1;
if (self->hdepth > 8) { if (self->hdepth > 8) {
GST_ELEMENT_ERROR (self, STREAM, FAILED, GST_ELEMENT_ERROR (self, STREAM, FAILED,
("Pipeline requires too many references: (%u forward, %u backward)", ("Pipeline requires too many references: (%u forward, %u backward)",
num_forward_references, self->num_backward_references), (NULL)); self->num_forward_references, self->num_backward_references),
(NULL));
} }
GST_INFO_OBJECT (self, "References for method: %u forward / %u backward", GST_INFO_OBJECT (self, "References for method: %u forward / %u backward",
num_forward_references, self->num_backward_references); self->num_forward_references, self->num_backward_references);
self->hcurr = num_forward_references; self->hcurr = -1;
return; return;
} }
} }
@ -454,6 +460,8 @@ gst_va_deinterlace_generate_output (GstBaseTransform * trans,
*outbuf = NULL; *outbuf = NULL;
g_assert (self->hcurr >= 0 && self->hcurr <= self->num_forward_references);
if (self->curr_field == FINISHED) if (self->curr_field == FINISHED)
return GST_FLOW_OK; return GST_FLOW_OK;
@ -461,7 +469,8 @@ gst_va_deinterlace_generate_output (GstBaseTransform * trans,
if (!inbuf) if (!inbuf)
return GST_FLOW_OK; return GST_FLOW_OK;
if (!self->history[self->hdepth - 1]) g_assert (self->hcurr + self->num_backward_references <= self->hdepth - 1);
if (!self->history[self->hcurr + self->num_backward_references])
return GST_FLOW_OK; return GST_FLOW_OK;
ret = GST_BASE_TRANSFORM_CLASS (parent_class)->prepare_output_buffer (trans, ret = GST_BASE_TRANSFORM_CLASS (parent_class)->prepare_output_buffer (trans,