diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c index 6309ed8d18..2d4d55017a 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c @@ -496,8 +496,8 @@ render_frame(GstVaapiDecoderFfmpeg *decoder, AVFrame *frame) return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE; gst_vaapi_surface_proxy_set_timestamp(proxy, frame->pts); - if (frame->interlaced_frame) - gst_vaapi_surface_proxy_set_tff(proxy, frame->top_field_first); + gst_vaapi_surface_proxy_set_interlaced(proxy, !!frame->interlaced_frame); + gst_vaapi_surface_proxy_set_tff(proxy, frame->top_field_first); gst_vaapi_decoder_push_surface_proxy(base_decoder, g_object_ref(proxy)); return GST_VAAPI_DECODER_STATUS_SUCCESS; } diff --git a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c index 9b01ac34d6..3c2f2299ce 100644 --- a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c +++ b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c @@ -43,7 +43,8 @@ struct _GstVaapiSurfaceProxyPrivate { GstVaapiContext *context; GstVaapiSurface *surface; GstClockTime timestamp; - gboolean tff; + guint is_interlaced : 1; + guint tff : 1; }; enum { @@ -52,6 +53,7 @@ enum { PROP_CONTEXT, PROP_SURFACE, PROP_TIMESTAMP, + PROP_INTERLACED, PROP_TFF }; @@ -86,6 +88,9 @@ gst_vaapi_surface_proxy_set_property( case PROP_TIMESTAMP: gst_vaapi_surface_proxy_set_timestamp(proxy, g_value_get_uint64(value)); break; + case PROP_INTERLACED: + gst_vaapi_surface_proxy_set_interlaced(proxy, g_value_get_boolean(value)); + break; case PROP_TFF: gst_vaapi_surface_proxy_set_tff(proxy, g_value_get_boolean(value)); break; @@ -115,6 +120,9 @@ gst_vaapi_surface_proxy_get_property( case PROP_TIMESTAMP: g_value_set_uint64(value, gst_vaapi_surface_proxy_get_timestamp(proxy)); break; + case PROP_INTERLACED: + g_value_set_boolean(value, gst_vaapi_surface_proxy_get_interlaced(proxy)); + break; case PROP_TFF: g_value_set_boolean(value, gst_vaapi_surface_proxy_get_tff(proxy)); break; @@ -160,6 +168,15 @@ gst_vaapi_surface_proxy_class_init(GstVaapiSurfaceProxyClass *klass) 0, G_MAXUINT64, GST_CLOCK_TIME_NONE, G_PARAM_READWRITE)); + g_object_class_install_property + (object_class, + PROP_INTERLACED, + g_param_spec_boolean("interlaced", + "Interlaced", + "Flag indicating whether surface is interlaced", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_TFF, @@ -180,6 +197,7 @@ gst_vaapi_surface_proxy_init(GstVaapiSurfaceProxy *proxy) priv->context = NULL; priv->surface = NULL; priv->timestamp = GST_CLOCK_TIME_NONE; + priv->is_interlaced = FALSE; priv->tff = FALSE; } @@ -351,6 +369,39 @@ gst_vaapi_surface_proxy_set_timestamp( proxy->priv->timestamp = timestamp; } +/** + * gst_vaapi_surface_proxy_get_interlaced: + * @proxy: a #GstVaapiSurfaceProxy + * + * Returns whether the @proxy holds an interlaced #GstVaapiSurface or not. + * + * Return value: %TRUE if the underlying surface is interlaced, %FALSE + * otherwise. + */ +gboolean +gst_vaapi_surface_proxy_get_interlaced(GstVaapiSurfaceProxy *proxy) +{ + g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), FALSE); + + return proxy->priv->is_interlaced; +} + +/** + * gst_vaapi_surface_proxy_set_interlaced: + * @proxy: a #GstVaapiSurfaceProxy + * @b: a boolean value + * + * Sets whether the underlying #GstVaapiSurface for @proxy is interlaced + * or not. + */ +void +gst_vaapi_surface_proxy_set_interlaced(GstVaapiSurfaceProxy *proxy, gboolean b) +{ + g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy)); + + proxy->priv->is_interlaced = b; +} + /** * gst_vaapi_surface_proxy_get_tff: * @proxy: a #GstVaapiSurfaceProxy @@ -364,7 +415,7 @@ gst_vaapi_surface_proxy_get_tff(GstVaapiSurfaceProxy *proxy) { g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), FALSE); - return proxy->priv->tff; + return proxy->priv->is_interlaced && proxy->priv->tff; } /** diff --git a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h index a6d963081f..b32458c76b 100644 --- a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h +++ b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h @@ -72,6 +72,15 @@ G_BEGIN_DECLS #define GST_VAAPI_SURFACE_PROXY_TIMESTAMP(surface) \ gst_vaapi_surface_proxy_get_timestamp(surface) +/** + * GST_VAAPI_SURFACE_PROXY_INTERLACED: + * @surface: a #GstVaapiSurfaceProxy + * + * Macro that evaluates to %TRUE if the @surface is interlaced. + */ +#define GST_VAAPI_SURFACE_PROXY_INTERLACED(surface) \ + gst_vaapi_surface_proxy_get_interlaced(surface) + /** * GST_VAAPI_SURFACE_PROXY_TFF: * @surface: a #GstVaapiSurfaceProxy @@ -143,6 +152,12 @@ gst_vaapi_surface_proxy_set_timestamp( GstClockTime timestamp ); +gboolean +gst_vaapi_surface_proxy_get_interlaced(GstVaapiSurfaceProxy *proxy); + +void +gst_vaapi_surface_proxy_set_interlaced(GstVaapiSurfaceProxy *proxy, gboolean b); + gboolean gst_vaapi_surface_proxy_get_tff(GstVaapiSurfaceProxy *proxy); diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c index e0f9f67914..31a46e250c 100644 --- a/gst/vaapi/gstvaapipostproc.c +++ b/gst/vaapi/gstvaapipostproc.c @@ -239,8 +239,10 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf) GstClockTime timestamp; GstFlowReturn ret; GstBuffer *outbuf = NULL; - guint outbuf_flags, flags = 0; - gboolean tff; + guint outbuf_flags, flags; + gboolean interlaced, tff; + + flags = gst_vaapi_video_buffer_get_render_flags(vbuf); /* Deinterlacing disabled, push frame */ if (!postproc->deinterlace) { @@ -251,9 +253,13 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf) return GST_FLOW_OK; } - timestamp = GST_BUFFER_TIMESTAMP(buf); - proxy = gst_vaapi_video_buffer_get_surface_proxy(vbuf); - tff = gst_vaapi_surface_proxy_get_tff(proxy); + timestamp = GST_BUFFER_TIMESTAMP(buf); + proxy = gst_vaapi_video_buffer_get_surface_proxy(vbuf); + interlaced = gst_vaapi_surface_proxy_get_interlaced(proxy); + tff = gst_vaapi_surface_proxy_get_tff(proxy); + + flags &= ~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD| + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD); /* First field */ outbuf = gst_vaapi_video_buffer_new_with_surface_proxy(proxy); @@ -262,9 +268,11 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf) vbuf = GST_VAAPI_VIDEO_BUFFER(outbuf); outbuf_flags = flags; - outbuf_flags |= tff ? + outbuf_flags |= interlaced ? ( + tff ? GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD : - GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD) : + GST_VAAPI_PICTURE_STRUCTURE_FRAME; gst_vaapi_video_buffer_set_render_flags(vbuf, outbuf_flags); GST_BUFFER_TIMESTAMP(outbuf) = timestamp; @@ -281,9 +289,11 @@ gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf) vbuf = GST_VAAPI_VIDEO_BUFFER(outbuf); outbuf_flags = flags; - outbuf_flags |= tff ? + outbuf_flags |= interlaced ? ( + tff ? GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD : - GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; + GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD) : + GST_VAAPI_PICTURE_STRUCTURE_FRAME; gst_vaapi_video_buffer_set_render_flags(vbuf, outbuf_flags); GST_BUFFER_TIMESTAMP(outbuf) = timestamp + postproc->field_duration;