vaapipostproc: get "interlaced" attribute from surface proxy.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 28 Mar 2012 13:16:17 +0000 (15:16 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 28 Mar 2012 15:59:19 +0000 (17:59 +0200)
Add new "interlaced" attribute to GstVaapiSurfaceProxy. Use this in
vaapipostproc so that to handles cases where bitstream is interlaced
but almost only frame pictures are generated. In this case, we should
not be alternating between top/bottom fields.

gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c
gst-libs/gst/vaapi/gstvaapisurfaceproxy.c
gst-libs/gst/vaapi/gstvaapisurfaceproxy.h
gst/vaapi/gstvaapipostproc.c

index 6309ed8..2d4d550 100644 (file)
@@ -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;
 }
index 9b01ac3..3c2f229 100644 (file)
@@ -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;
@@ -162,6 +170,15 @@ gst_vaapi_surface_proxy_class_init(GstVaapiSurfaceProxyClass *klass)
 
     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,
          g_param_spec_boolean("tff",
                               "Top-Field-First",
@@ -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;
 }
 
@@ -352,6 +370,39 @@ gst_vaapi_surface_proxy_set_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;
 }
 
 /**
index a6d9630..b32458c 100644 (file)
@@ -73,6 +73,15 @@ G_BEGIN_DECLS
     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
  *
@@ -144,6 +153,12 @@ gst_vaapi_surface_proxy_set_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);
 
 void
index e0f9f67..31a46e2 100644 (file)
@@ -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;