plugins: factor out decide_allocation() hook.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Thu, 21 Aug 2014 12:10:36 +0000 (14:10 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 22 Aug 2014 13:54:32 +0000 (15:54 +0200)
Add a default decide_allocation() hook to GstVaapiPluginBase. The caps
feature argument can be used to force a bufferpool with a specific kind
of memory.

gst/vaapi/gstvaapidecode.c
gst/vaapi/gstvaapipluginbase.c
gst/vaapi/gstvaapipluginbase.h

index 4f716c6..989f7a1 100644 (file)
@@ -522,40 +522,26 @@ gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
 {
     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
     GstCaps *caps = NULL;
-    GstBufferPool *pool;
-    GstStructure *config;
-    GstVideoInfo vi;
-    guint size, min, max;
-    gboolean need_pool, update_pool;
-    gboolean has_video_meta = FALSE;
-    gboolean has_video_alignment = FALSE;
-#if GST_CHECK_VERSION(1,1,0) && USE_GLX
-    gboolean has_texture_upload_meta = FALSE;
-#endif
+    gboolean need_pool;
     GstVideoCodecState *state;
+    GstVaapiCapsFeature feature;
 
     gst_query_parse_allocation(query, &caps, &need_pool);
 
-    if (!caps)
-        goto error_no_caps;
-
-    state = gst_video_decoder_get_output_state(vdec);
-
     decode->has_texture_upload_meta = FALSE;
-    has_video_meta = gst_query_find_allocation_meta(query,
-        GST_VIDEO_META_API_TYPE, NULL);
-
 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
-    has_texture_upload_meta = gst_query_find_allocation_meta(query,
-        GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
-
     decode->has_texture_upload_meta =
         gst_vaapi_find_preferred_caps_feature(GST_VIDEO_DECODER_SRC_PAD(vdec),
             GST_VIDEO_FORMAT_ENCODED) ==
         GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META;
 #endif
 
+    feature = decode->has_texture_upload_meta ?
+        GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META :
+        GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE;
+
     /* Update src caps if feature is not handled downstream */
+    state = gst_video_decoder_get_output_state(vdec);
     if (!gst_caps_is_always_compatible(caps, state->caps)) {
         if (decode->has_texture_upload_meta)
             gst_video_info_set_format(&state->info, GST_VIDEO_FORMAT_RGBA,
@@ -565,95 +551,8 @@ gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
     }
     gst_video_codec_state_unref(state);
 
-    gst_video_info_init(&vi);
-    gst_video_info_from_caps(&vi, caps);
-    if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED)
-        gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_I420,
-            GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
-
-    g_return_val_if_fail(GST_VAAPI_PLUGIN_BASE_DISPLAY(decode) != NULL, FALSE);
-
-    if (gst_query_get_n_allocation_pools(query) > 0) {
-        gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min, &max);
-        size = MAX(size, vi.size);
-        update_pool = TRUE;
-
-        /* Check whether downstream element proposed a bufferpool but did
-           not provide a correct propose_allocation() implementation */
-        has_video_alignment = gst_buffer_pool_has_option(pool,
-            GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
-    }
-    else {
-        pool = NULL;
-        size = vi.size;
-        min = max = 0;
-        update_pool = FALSE;
-    }
-
-    if (!pool || !gst_buffer_pool_has_option(pool,
-            GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
-        GST_INFO("no pool or doesn't support GstVaapiVideoMeta, "
-            "making new pool");
-        if (pool)
-            gst_object_unref(pool);
-        pool = gst_vaapi_video_buffer_pool_new(
-            GST_VAAPI_PLUGIN_BASE_DISPLAY(decode));
-        if (!pool)
-            goto error_create_pool;
-
-        config = gst_buffer_pool_get_config(pool);
-        gst_buffer_pool_config_set_params(config, caps, size, min, max);
-        gst_buffer_pool_config_add_option(config,
-            GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
-        gst_buffer_pool_set_config(pool, config);
-    }
-
-    if (has_video_meta) {
-        config = gst_buffer_pool_get_config(pool);
-        gst_buffer_pool_config_add_option(config,
-            GST_BUFFER_POOL_OPTION_VIDEO_META);
-#if GST_CHECK_VERSION(1,1,0) && USE_GLX
-        if (has_texture_upload_meta)
-            gst_buffer_pool_config_add_option(config,
-                GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
-#endif
-        gst_buffer_pool_set_config(pool, config);
-    }
-    else if (has_video_alignment) {
-        config = gst_buffer_pool_get_config(pool);
-        gst_buffer_pool_config_add_option(config,
-            GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
-        gst_buffer_pool_set_config(pool, config);
-    }
-
-#if GST_CHECK_VERSION(1,1,0) && USE_GLX
-    if (decode->has_texture_upload_meta && !has_texture_upload_meta) {
-        config = gst_buffer_pool_get_config(pool);
-        gst_buffer_pool_config_add_option(config,
-            GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
-        gst_buffer_pool_set_config(pool, config);
-    }
-#endif
-
-    if (update_pool)
-        gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max);
-    else
-        gst_query_add_allocation_pool(query, pool, size, min, max);
-    if (pool)
-        gst_object_unref(pool);
-    return TRUE;
-
-    /* ERRORS */
-error_no_caps:
-    {
-        GST_ERROR("no caps specified");
-        return FALSE;
-    }
-error_create_pool:
-    {
-        GST_ERROR("failed to create buffer pool");
-        return FALSE;
-    }
+    return gst_vaapi_plugin_base_decide_allocation(GST_VAAPI_PLUGIN_BASE(vdec),
+        query, feature);
 }
 #endif
 
index ad254f2..f69f84b 100644 (file)
@@ -206,6 +206,7 @@ gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin)
     gst_object_unref (plugin->sinkpad_buffer_pool);
     plugin->sinkpad_buffer_pool = NULL;
   }
+  g_clear_object (&plugin->srcpad_buffer_pool);
 #endif
 
   gst_caps_replace (&plugin->srcpad_caps, NULL);
@@ -454,6 +455,146 @@ error_no_caps:
 #endif
 
 /**
+ * gst_vaapi_plugin_base_decide_allocation:
+ * @plugin: a #GstVaapiPluginBase
+ * @query: the allocation query to parse
+ * @feature: the desired #GstVaapiCapsFeature, or zero to find the
+ *   preferred one
+ *
+ * Decides allocation parameters for the downstream elements.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ */
+#if GST_CHECK_VERSION(1,0,0)
+gboolean
+gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin,
+    GstQuery * query, guint feature)
+{
+  GstCaps *caps = NULL;
+  GstBufferPool *pool;
+  GstStructure *config;
+  GstVideoInfo vi;
+  guint size, min, max;
+  gboolean need_pool, update_pool;
+  gboolean has_video_meta = FALSE;
+  gboolean has_video_alignment = FALSE;
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+  gboolean has_texture_upload_meta = FALSE;
+#endif
+
+  g_return_val_if_fail (plugin->display != NULL, FALSE);
+
+  gst_query_parse_allocation (query, &caps, &need_pool);
+
+  if (!caps)
+    goto error_no_caps;
+
+  if (!feature)
+    feature =
+        gst_vaapi_find_preferred_caps_feature (plugin->srcpad,
+        GST_VIDEO_FORMAT_ENCODED);
+
+  has_video_meta = gst_query_find_allocation_meta (query,
+      GST_VIDEO_META_API_TYPE, NULL);
+
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+  has_texture_upload_meta = gst_query_find_allocation_meta (query,
+      GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
+#endif
+
+  gst_video_info_init (&vi);
+  gst_video_info_from_caps (&vi, caps);
+  if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED)
+    gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_I420,
+        GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi));
+
+  if (gst_query_get_n_allocation_pools (query) > 0) {
+    gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
+    size = MAX (size, vi.size);
+    update_pool = TRUE;
+
+    /* Check whether downstream element proposed a bufferpool but did
+       not provide a correct propose_allocation() implementation */
+    has_video_alignment = gst_buffer_pool_has_option (pool,
+        GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
+  } else {
+    pool = NULL;
+    size = vi.size;
+    min = max = 0;
+    update_pool = FALSE;
+  }
+
+  /* GstVaapiVideoMeta is mandatory, and this implies VA surface memory */
+  if (!pool || !gst_buffer_pool_has_option (pool,
+          GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
+    GST_INFO_OBJECT (plugin, "no pool or doesn't support GstVaapiVideoMeta, "
+        "making new pool");
+    if (pool)
+      gst_object_unref (pool);
+    pool = gst_vaapi_video_buffer_pool_new (plugin->display);
+    if (!pool)
+      goto error_create_pool;
+
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_set_params (config, caps, size, min, max);
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
+    gst_buffer_pool_set_config (pool, config);
+  }
+
+  /* Check whether GstVideoMeta, or GstVideoAlignment, is needed (raw video) */
+  if (has_video_meta) {
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_META);
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+    if (has_texture_upload_meta)
+      gst_buffer_pool_config_add_option (config,
+          GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
+#endif
+    gst_buffer_pool_set_config (pool, config);
+  } else if (has_video_alignment) {
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
+    gst_buffer_pool_set_config (pool, config);
+  }
+
+  /* GstVideoGLTextureUploadMeta (OpenGL) */
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+  if (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META
+      && !has_texture_upload_meta) {
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
+    gst_buffer_pool_set_config (pool, config);
+  }
+#endif
+
+  if (update_pool)
+    gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
+  else
+    gst_query_add_allocation_pool (query, pool, size, min, max);
+
+  g_clear_object (&plugin->srcpad_buffer_pool);
+  plugin->srcpad_buffer_pool = pool;
+  return TRUE;
+
+  /* ERRORS */
+error_no_caps:
+  {
+    GST_ERROR_OBJECT (plugin, "no caps specified");
+    return FALSE;
+  }
+error_create_pool:
+  {
+    GST_ERROR_OBJECT (plugin, "failed to create buffer pool");
+    return FALSE;
+  }
+}
+#endif
+
+/**
  * gst_vaapi_plugin_base_allocate_input_buffer:
  * @plugin: a #GstVaapiPluginBase
  * @caps: the buffer caps constraints to honour
index 76413b3..e7426cb 100644 (file)
@@ -136,6 +136,9 @@ struct _GstVaapiPluginBase
   gboolean srcpad_caps_changed;
   GstVideoInfo srcpad_info;
   GstPadQueryFunction srcpad_query;
+#if GST_CHECK_VERSION(1,0,0)
+  GstBufferPool *srcpad_buffer_pool;
+#endif
 
   GstVaapiDisplay *display;
   GstVaapiDisplayType display_type;
@@ -216,6 +219,11 @@ gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
     GstQuery * query);
 
 G_GNUC_INTERNAL
+gboolean
+gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin,
+    GstQuery * query, guint feature);
+
+G_GNUC_INTERNAL
 GstFlowReturn
 gst_vaapi_plugin_base_allocate_input_buffer (GstVaapiPluginBase * plugin,
     GstCaps * caps, GstBuffer ** outbuf_ptr);