plugins: factor out support for raw YUV buffers on sink pads.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 17 Dec 2013 17:52:23 +0000 (18:52 +0100)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 18 Dec 2013 15:38:57 +0000 (16:38 +0100)
Factor out propose_allocation() hooks, creation of video buffer pool
for the sink pad, conversion from raw YUV buffers to VA surface backed
buffers. Update vaapidecode, vaapiencode and vaapipostproc to cope
with the new GstVaapiPluginBase abilities.

gst/vaapi/gstvaapiencode.c
gst/vaapi/gstvaapiencode.h
gst/vaapi/gstvaapipluginbase.c
gst/vaapi/gstvaapipluginbase.h
gst/vaapi/gstvaapipostproc.c
gst/vaapi/gstvaapipostproc.h
gst/vaapi/gstvaapisink.c
gst/vaapi/gstvaapisink.h

index 87fadc0..d1afc44 100644 (file)
@@ -61,33 +61,10 @@ ensure_display (GstVaapiEncode * encode)
 static gboolean
 ensure_uploader (GstVaapiEncode * encode)
 {
-#if !GST_CHECK_VERSION(1,0,0)
   if (!ensure_display (encode))
     return FALSE;
-
-  if (!encode->uploader) {
-    encode->uploader = gst_vaapi_uploader_new (
-        GST_VAAPI_PLUGIN_BASE_DISPLAY (encode));
-    if (!encode->uploader)
-      return FALSE;
-  }
-
-  if (!gst_vaapi_uploader_ensure_display (encode->uploader,
-           GST_VAAPI_PLUGIN_BASE_DISPLAY (encode)))
-    return FALSE;
-#endif
-  return TRUE;
-}
-
-static gboolean
-ensure_uploader_caps (GstVaapiEncode * encode)
-{
-#if !GST_CHECK_VERSION(1,0,0)
-  if (GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info) &&
-      !gst_vaapi_uploader_ensure_caps (encode->uploader, encode->sinkpad_caps,
-          NULL))
+  if (!gst_vaapi_plugin_base_ensure_uploader (GST_VAAPI_PLUGIN_BASE (encode)))
     return FALSE;
-#endif
   return TRUE;
 }
 
@@ -283,7 +260,7 @@ gst_vaapiencode_get_caps_impl (GstVideoEncoder * venc)
     caps = gst_caps_from_string (GST_VAAPI_SURFACE_CAPS);
 
     if (caps && ensure_uploader (encode)) {
-      GstCaps *const yuv_caps = gst_vaapi_uploader_get_caps (encode->uploader);
+      GstCaps *const yuv_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS (encode);
       if (yuv_caps) {
         caps = gst_caps_make_writable (caps);
         gst_caps_append (caps, gst_caps_copy (yuv_caps));
@@ -316,10 +293,6 @@ static gboolean
 gst_vaapiencode_destroy (GstVaapiEncode * encode)
 {
   gst_vaapi_encoder_replace (&encode->encoder, NULL);
-#if GST_CHECK_VERSION(1,0,0)
-  g_clear_object (&encode->video_buffer_pool);
-#endif
-  g_clear_object (&encode->uploader);
   gst_caps_replace (&encode->sinkpad_caps, NULL);
   gst_caps_replace (&encode->srcpad_caps, NULL);
   return TRUE;
@@ -332,12 +305,8 @@ ensure_encoder (GstVaapiEncode * encode)
 
   g_return_val_if_fail (klass->create_encoder, FALSE);
 
-  if (!ensure_display (encode))
-    return FALSE;
   if (!ensure_uploader (encode))
     return FALSE;
-  if (!ensure_uploader_caps (encode))
-    return FALSE;
 
   encode->encoder = klass->create_encoder (encode,
       GST_VAAPI_PLUGIN_BASE_DISPLAY (encode));
@@ -378,18 +347,6 @@ gst_vaapiencode_update_sink_caps (GstVaapiEncode * encode,
     GstVideoCodecState * state)
 {
   gst_caps_replace (&encode->sinkpad_caps, state->caps);
-  encode->sink_video_info = state->info;
-
-#if !GST_CHECK_VERSION(1,0,0)
-  if (GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info)) {
-    /* Ensure the uploader is set up for upstream allocated buffers */
-    GstVaapiUploader *const uploader = encode->uploader;
-    if (!gst_vaapi_uploader_ensure_display (uploader, GST_VAAPI_PLUGIN_BASE_DISPLAY (encode)))
-      return FALSE;
-    if (!gst_vaapi_uploader_ensure_caps (uploader, state->caps, NULL))
-      return FALSE;
-  }
-#endif
   return TRUE;
 }
 
@@ -451,81 +408,12 @@ gst_vaapiencode_update_src_caps (GstVaapiEncode * encode,
 }
 
 static gboolean
-gst_vaapiencode_ensure_video_buffer_pool (GstVaapiEncode * encode,
-    GstCaps * caps)
-{
-#if GST_CHECK_VERSION(1,0,0)
-  GstBufferPool *pool;
-  GstCaps *pool_caps;
-  GstStructure *config;
-  GstVideoInfo vi;
-  gboolean need_pool;
-
-  if (!ensure_display (encode))
-    return FALSE;
-
-  if (encode->video_buffer_pool) {
-    config = gst_buffer_pool_get_config (encode->video_buffer_pool);
-    gst_buffer_pool_config_get_params (config, &pool_caps, NULL, NULL, NULL);
-    need_pool = !gst_caps_is_equal (caps, pool_caps);
-    gst_structure_free (config);
-    if (!need_pool)
-      return TRUE;
-    g_clear_object (&encode->video_buffer_pool);
-    encode->video_buffer_size = 0;
-  }
-
-  pool = gst_vaapi_video_buffer_pool_new (GST_VAAPI_PLUGIN_BASE_DISPLAY (encode));
-  if (!pool)
-    goto error_create_pool;
-
-  gst_video_info_init (&vi);
-  gst_video_info_from_caps (&vi, caps);
-  if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) {
-    GST_DEBUG ("assume video buffer pool format is NV12");
-    gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_NV12,
-        GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi));
-  }
-  encode->video_buffer_size = vi.size;
-
-  config = gst_buffer_pool_get_config (pool);
-  gst_buffer_pool_config_set_params (config, caps, encode->video_buffer_size,
-      0, 0);
-  gst_buffer_pool_config_add_option (config,
-      GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
-  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
-  if (!gst_buffer_pool_set_config (pool, config))
-    goto error_pool_config;
-  encode->video_buffer_pool = pool;
-  return TRUE;
-
-  /* ERRORS */
-error_create_pool:
-  {
-    GST_ERROR ("failed to create buffer pool");
-    return FALSE;
-  }
-error_pool_config:
-  {
-    GST_ERROR ("failed to reset buffer pool config");
-    gst_object_unref (pool);
-    return FALSE;
-  }
-#else
-  return TRUE;
-#endif
-}
-
-static gboolean
 gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
 {
   GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
 
   g_return_val_if_fail (state->caps != NULL, FALSE);
 
-  if (!gst_vaapiencode_ensure_video_buffer_pool (encode, state->caps))
-    return FALSE;
-
   if (!ensure_encoder (encode))
     return FALSE;
   if (!gst_vaapiencode_update_sink_caps (encode, state))
@@ -533,6 +421,10 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
   if (!gst_vaapiencode_update_src_caps (encode, state))
     return FALSE;
 
+  if (!gst_vaapi_plugin_base_set_caps (GST_VAAPI_PLUGIN_BASE (encode),
+          encode->sinkpad_caps, encode->srcpad_caps))
+    return FALSE;
+
 #if GST_CHECK_VERSION(1,0,0)
   if (encode->out_caps_done && !gst_video_encoder_negotiate (venc)) {
     GST_ERROR ("failed to negotiate with caps %" GST_PTR_FORMAT,
@@ -558,114 +450,6 @@ gst_vaapiencode_reset (GstVideoEncoder * venc, gboolean hard)
 }
 
 static GstFlowReturn
-get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer,
-    GstBuffer ** out_buffer_ptr)
-{
-  GstVaapiVideoMeta *meta;
-  GstBuffer *out_buffer;
-#if GST_CHECK_VERSION(1,0,0)
-  GstVideoFrame src_frame, out_frame;
-  gboolean success;
-#endif
-
-  meta = gst_buffer_get_vaapi_video_meta (src_buffer);
-  if (meta) {
-    *out_buffer_ptr = gst_buffer_ref (src_buffer);
-    return GST_FLOW_OK;
-  }
-
-#if GST_CHECK_VERSION(1,0,0)
-  if (!GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info))
-    goto error_invalid_buffer;
-
-  if (!encode->video_buffer_pool)
-    goto error_no_pool;
-
-  if (!gst_buffer_pool_set_active (encode->video_buffer_pool, TRUE))
-    goto error_activate_pool;
-
-  out_buffer = NULL;
-  success = gst_buffer_pool_acquire_buffer (encode->video_buffer_pool,
-      &out_buffer, NULL) == GST_FLOW_OK;
-  if (!success)
-    goto error_create_buffer;
-
-  if (!gst_video_frame_map (&src_frame, &encode->sink_video_info, src_buffer,
-          GST_MAP_READ))
-    goto error_map_src_buffer;
-
-  if (!gst_video_frame_map (&out_frame, &encode->sink_video_info, out_buffer,
-          GST_MAP_WRITE))
-    goto error_map_dst_buffer;
-
-  success = gst_video_frame_copy (&out_frame, &src_frame);
-  gst_video_frame_unmap (&out_frame);
-  gst_video_frame_unmap (&src_frame);
-  if (!success)
-    goto error_copy_buffer;
-
-  gst_buffer_copy_into (out_buffer, src_buffer, GST_BUFFER_COPY_TIMESTAMPS, 0,
-      -1);
-
-  *out_buffer_ptr = out_buffer;
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-error_invalid_buffer:
-  {
-    GST_ERROR ("unsupported video buffer");
-    return GST_FLOW_EOS;
-  }
-error_no_pool:
-  {
-    GST_ERROR ("no buffer pool was negotiated");
-    return GST_FLOW_ERROR;
-  }
-error_activate_pool:
-  {
-    GST_ERROR ("failed to activate buffer pool");
-    return GST_FLOW_ERROR;
-  }
-error_map_dst_buffer:
-  {
-    gst_video_frame_unmap (&src_frame);
-    // fall-through
-  }
-error_map_src_buffer:
-  {
-    GST_WARNING ("failed to map buffer. Skipping this frame");
-    gst_buffer_unref (out_buffer);
-    return GST_FLOW_OK;
-  }
-#else
-  out_buffer = gst_vaapi_uploader_get_buffer (encode->uploader);
-  if (!out_buffer)
-    goto error_create_buffer;
-  if (!gst_vaapi_uploader_process (encode->uploader, src_buffer, out_buffer))
-    goto error_copy_buffer;
-
-  gst_buffer_copy_metadata (out_buffer, src_buffer,
-      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
-
-  *out_buffer_ptr = out_buffer;
-  return GST_FLOW_OK;
-#endif
-
-  /* ERRORS */
-error_create_buffer:
-  {
-    GST_WARNING ("failed to create buffer. Skipping this frame");
-    return GST_FLOW_OK;
-  }
-error_copy_buffer:
-  {
-    GST_WARNING ("failed to upload buffer to VA surface. Skipping this frame");
-    gst_buffer_unref (out_buffer);
-    return GST_FLOW_OK;
-  }
-}
-
-static GstFlowReturn
 gst_vaapiencode_handle_frame (GstVideoEncoder * venc,
     GstVideoCodecFrame * frame)
 {
@@ -677,7 +461,8 @@ gst_vaapiencode_handle_frame (GstVideoEncoder * venc,
   GstBuffer *buf;
 
   buf = NULL;
-  ret = get_source_buffer (encode, frame->input_buffer, &buf);
+  ret = gst_vaapi_plugin_base_get_input_buffer (GST_VAAPI_PLUGIN_BASE (encode),
+      frame->input_buffer, &buf);
   if (ret != GST_FLOW_OK)
     goto error_buffer_invalid;
 
@@ -759,31 +544,11 @@ gst_vaapiencode_finish (GstVideoEncoder * venc)
 static gboolean
 gst_vaapiencode_propose_allocation (GstVideoEncoder * venc, GstQuery * query)
 {
-  GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
-  GstCaps *caps = NULL;
-  gboolean need_pool;
-
-  gst_query_parse_allocation (query, &caps, &need_pool);
-
-  if (need_pool) {
-    if (!caps)
-      goto error_no_caps;
-    if (!gst_vaapiencode_ensure_video_buffer_pool (encode, caps))
-      return FALSE;
-    gst_query_add_allocation_pool (query, encode->video_buffer_pool,
-        encode->video_buffer_size, 0, 0);
-  }
+  GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (venc);
 
-  gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL);
-  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
-  return TRUE;
-
-  /* ERRORS */
-error_no_caps:
-  {
-    GST_ERROR ("no caps specified");
+  if (!gst_vaapi_plugin_base_propose_allocation (plugin, query))
     return FALSE;
-  }
+  return TRUE;
 }
 #endif
 
@@ -864,7 +629,6 @@ gst_vaapiencode_init (GstVaapiEncode * encode)
   encode->sinkpad = GST_VIDEO_ENCODER_SINK_PAD (encode);
   encode->sinkpad_query = GST_PAD_QUERYFUNC (encode->sinkpad);
   gst_pad_set_query_function (encode->sinkpad, gst_vaapiencode_query);
-  gst_video_info_init (&encode->sink_video_info);
 
   /* src pad */
   encode->srcpad = GST_VIDEO_ENCODER_SRC_PAD (encode);
index 1bf0dbc..401913f 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "gstvaapipluginbase.h"
 #include <gst/vaapi/gstvaapiencoder.h>
-#include "gstvaapiuploader.h"
 
 G_BEGIN_DECLS
 
@@ -54,19 +53,12 @@ struct _GstVaapiEncode
   GstPad *sinkpad;
   GstCaps *sinkpad_caps;
   GstPadQueryFunction sinkpad_query;
-  GstVideoInfo sink_video_info;
 
   GstPad *srcpad;
   GstCaps *srcpad_caps;
   GstPadQueryFunction srcpad_query;
 
   GstVaapiEncoder *encoder;
-  GstVaapiUploader *uploader;
-
-#if GST_CHECK_VERSION(1,0,0)
-  GstBufferPool *video_buffer_pool;
-#endif
-  guint video_buffer_size;
 
   GstVaapiRateControl rate_control;
   guint32 bitrate;              /* kbps */
index 7339210..e1ff740 100644 (file)
 #include "gstvaapipluginbase.h"
 #include "gstvaapipluginutil.h"
 #include "gstvaapivideocontext.h"
+#include "gstvaapivideometa.h"
+#if GST_CHECK_VERSION(1,0,0)
+#include "gstvaapivideobufferpool.h"
+#endif
 
 /* Default debug category is from the subclass */
 #define GST_CAT_DEFAULT (plugin->debug_category)
@@ -174,11 +178,18 @@ gst_vaapi_plugin_base_open (GstVaapiPluginBase * plugin)
 void
 gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin)
 {
+  g_clear_object (&plugin->uploader);
   gst_vaapi_display_replace (&plugin->display, NULL);
 
   gst_caps_replace (&plugin->sinkpad_caps, NULL);
   plugin->sinkpad_caps_changed = FALSE;
   gst_video_info_init (&plugin->sinkpad_info);
+#if GST_CHECK_VERSION(1,0,0)
+  if (plugin->sinkpad_buffer_pool) {
+    gst_object_unref (plugin->sinkpad_buffer_pool);
+    plugin->sinkpad_buffer_pool = NULL;
+  }
+#endif
 
   gst_caps_replace (&plugin->srcpad_caps, NULL);
   plugin->srcpad_caps_changed = FALSE;
@@ -228,6 +239,104 @@ gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin)
 }
 
 /**
+ * gst_vaapi_plugin_base_ensure_uploader:
+ * @plugin: a #GstVaapiPluginBase
+ *
+ * Makes sure the built-in #GstVaapiUploader object is created, or
+ * that it was successfully notified of any VA display change.
+ *
+ * Returns: %TRUE if the uploader was successfully created, %FALSE otherwise.
+ */
+gboolean
+gst_vaapi_plugin_base_ensure_uploader (GstVaapiPluginBase * plugin)
+{
+  if (plugin->uploader) {
+    if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
+      return FALSE;
+  } else {
+    plugin->uploader = gst_vaapi_uploader_new (plugin->display);
+    if (!plugin->uploader)
+      return FALSE;
+  }
+  return TRUE;
+}
+
+/**
+ * ensure_sinkpad_buffer_pool:
+ * @plugin: a #GstVaapiPluginBase
+ * @caps: the initial #GstCaps for the resulting buffer pool
+ *
+ * Makes sure the sink pad video buffer pool is created with the
+ * appropriate @caps.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ */
+static gboolean
+ensure_sinkpad_buffer_pool (GstVaapiPluginBase * plugin, GstCaps * caps)
+{
+#if GST_CHECK_VERSION(1,0,0)
+  GstBufferPool *pool;
+  GstCaps *pool_caps;
+  GstStructure *config;
+  GstVideoInfo vi;
+  gboolean need_pool;
+
+  if (!gst_vaapi_plugin_base_ensure_display (plugin))
+    return FALSE;
+
+  if (plugin->sinkpad_buffer_pool) {
+    config = gst_buffer_pool_get_config (plugin->sinkpad_buffer_pool);
+    gst_buffer_pool_config_get_params (config, &pool_caps, NULL, NULL, NULL);
+    need_pool = !gst_caps_is_equal (caps, pool_caps);
+    gst_structure_free (config);
+    if (!need_pool)
+      return TRUE;
+    g_clear_object (&plugin->sinkpad_buffer_pool);
+    plugin->sinkpad_buffer_size = 0;
+  }
+
+  pool = gst_vaapi_video_buffer_pool_new (plugin->display);
+  if (!pool)
+    goto error_create_pool;
+
+  gst_video_info_init (&vi);
+  gst_video_info_from_caps (&vi, caps);
+  if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) {
+    GST_DEBUG ("assume video buffer pool format is NV12");
+    gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_NV12,
+        GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi));
+  }
+  plugin->sinkpad_buffer_size = vi.size;
+
+  config = gst_buffer_pool_get_config (pool);
+  gst_buffer_pool_config_set_params (config, caps,
+      plugin->sinkpad_buffer_size, 0, 0);
+  gst_buffer_pool_config_add_option (config,
+      GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
+  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
+  if (!gst_buffer_pool_set_config (pool, config))
+    goto error_pool_config;
+  plugin->sinkpad_buffer_pool = pool;
+  return TRUE;
+
+  /* ERRORS */
+error_create_pool:
+  {
+    GST_ERROR ("failed to create buffer pool");
+    return FALSE;
+  }
+error_pool_config:
+  {
+    GST_ERROR ("failed to reset buffer pool config");
+    gst_object_unref (pool);
+    return FALSE;
+  }
+#else
+  return TRUE;
+#endif
+}
+
+/**
  * gst_vaapi_plugin_base_set_caps:
  * @plugin: a #GstVaapiPluginBase
  * @incaps: the sink pad (input) caps
@@ -255,5 +364,227 @@ gst_vaapi_plugin_base_set_caps (GstVaapiPluginBase * plugin, GstCaps * incaps,
       return FALSE;
     plugin->srcpad_caps_changed = TRUE;
   }
+
+  if (plugin->uploader && GST_VIDEO_INFO_IS_YUV (&plugin->sinkpad_info)) {
+    if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
+      return FALSE;
+    if (!gst_vaapi_uploader_ensure_caps (plugin->uploader,
+            plugin->sinkpad_caps, plugin->srcpad_caps))
+      return FALSE;
+  }
+
+  if (!ensure_sinkpad_buffer_pool (plugin, plugin->sinkpad_caps))
+    return FALSE;
   return TRUE;
 }
+
+/**
+ * gst_vaapi_plugin_base_propose_allocation:
+ * @plugin: a #GstVaapiPluginBase
+ * @query: the allocation query to configure
+ *
+ * Proposes allocation parameters to the upstream elements.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ */
+#if GST_CHECK_VERSION(1,0,0)
+gboolean
+gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
+    GstQuery * query)
+{
+  GstCaps *caps = NULL;
+  gboolean need_pool;
+
+  gst_query_parse_allocation (query, &caps, &need_pool);
+
+  if (need_pool) {
+    if (!caps)
+      goto error_no_caps;
+    if (!ensure_sinkpad_buffer_pool (plugin, caps))
+      return FALSE;
+    gst_query_add_allocation_pool (query, plugin->sinkpad_buffer_pool,
+        plugin->sinkpad_buffer_size, 0, 0);
+  }
+
+  gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL);
+  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
+  return TRUE;
+
+  /* ERRORS */
+error_no_caps:
+  {
+    GST_ERROR ("no caps specified");
+    return FALSE;
+  }
+}
+#endif
+
+/**
+ * gst_vaapi_plugin_base_allocate_input_buffer:
+ * @plugin: a #GstVaapiPluginBase
+ * @caps: the buffer caps constraints to honour
+ * @outbuf_ptr: the pointer location to the newly allocated buffer
+ *
+ * Creates a buffer that holds a VA surface memory for the sink pad to
+ * use it as the result for buffer_alloc() impementations.
+ *
+ * Return: #GST_FLOW_OK if the buffer could be created.
+ */
+GstFlowReturn
+gst_vaapi_plugin_base_allocate_input_buffer (GstVaapiPluginBase * plugin,
+    GstCaps * caps, GstBuffer ** outbuf_ptr)
+{
+  GstBuffer *outbuf;
+
+  *outbuf_ptr = NULL;
+
+  if (!plugin->sinkpad_caps_changed) {
+    if (!gst_video_info_from_caps (&plugin->sinkpad_info, caps))
+      return GST_FLOW_NOT_SUPPORTED;
+    plugin->sinkpad_caps_changed = TRUE;
+  }
+
+  if (!GST_VIDEO_INFO_IS_YUV (&plugin->sinkpad_info))
+    return GST_FLOW_OK;
+
+  if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
+    return GST_FLOW_NOT_SUPPORTED;
+  if (!gst_vaapi_uploader_ensure_caps (plugin->uploader, caps, NULL))
+    return GST_FLOW_NOT_SUPPORTED;
+
+  outbuf = gst_vaapi_uploader_get_buffer (plugin->uploader);
+  if (!outbuf) {
+    GST_WARNING ("failed to allocate resources for raw YUV buffer");
+    return GST_FLOW_NOT_SUPPORTED;
+  }
+
+  *outbuf_ptr = outbuf;
+  return GST_FLOW_OK;
+}
+
+/**
+ * gst_vaapi_plugin_base_get_input_buffer:
+ * @plugin: a #GstVaapiPluginBase
+ * @incaps: the sink pad (input) buffer
+ * @outbuf_ptr: the pointer to location to the VA surface backed buffer
+ *
+ * Acquires the sink pad (input) buffer as a VA surface backed
+ * buffer. This is mostly useful for raw YUV buffers, as source
+ * buffers that are already backed as a VA surface are passed
+ * verbatim.
+ *
+ * Returns: #GST_FLOW_OK if the buffer could be acquired
+ */
+GstFlowReturn
+gst_vaapi_plugin_base_get_input_buffer (GstVaapiPluginBase * plugin,
+    GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
+{
+  GstVaapiVideoMeta *meta;
+  GstBuffer *outbuf;
+#if GST_CHECK_VERSION(1,0,0)
+  GstVideoFrame src_frame, out_frame;
+  gboolean success;
+#endif
+
+  g_return_val_if_fail (inbuf != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (outbuf_ptr != NULL, GST_FLOW_ERROR);
+
+  meta = gst_buffer_get_vaapi_video_meta (inbuf);
+#if GST_CHECK_VERSION(1,0,0)
+  if (meta) {
+    *outbuf_ptr = gst_buffer_ref (inbuf);
+    return GST_FLOW_OK;
+  }
+
+  if (!GST_VIDEO_INFO_IS_YUV (&plugin->sinkpad_info))
+    goto error_invalid_buffer;
+
+  if (!plugin->sinkpad_buffer_pool)
+    goto error_no_pool;
+
+  if (!gst_buffer_pool_set_active (plugin->sinkpad_buffer_pool, TRUE))
+    goto error_active_pool;
+
+  outbuf = NULL;
+  if (gst_buffer_pool_acquire_buffer (plugin->sinkpad_buffer_pool,
+          &outbuf, NULL) != GST_FLOW_OK)
+    goto error_create_buffer;
+
+  if (!gst_video_frame_map (&src_frame, &plugin->sinkpad_info, inbuf,
+          GST_MAP_READ))
+    goto error_map_src_buffer;
+
+  if (!gst_video_frame_map (&out_frame, &plugin->sinkpad_info, outbuf,
+          GST_MAP_WRITE))
+    goto error_map_dst_buffer;
+
+  success = gst_video_frame_copy (&out_frame, &src_frame);
+  gst_video_frame_unmap (&out_frame);
+  gst_video_frame_unmap (&src_frame);
+  if (!success)
+    goto error_copy_buffer;
+
+  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
+  *outbuf_ptr = outbuf;
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+error_no_pool:
+  {
+    GST_ERROR ("no buffer pool was negotiated");
+    return GST_FLOW_ERROR;
+  }
+error_active_pool:
+  {
+    GST_ERROR ("failed to activate buffer pool");
+    return GST_FLOW_ERROR;
+  }
+error_map_dst_buffer:
+  {
+    gst_video_frame_unmap (&src_frame);
+    // fall-through
+  }
+error_map_src_buffer:
+  {
+    GST_WARNING ("failed to map buffer");
+    gst_buffer_unref (outbuf);
+    return GST_FLOW_NOT_SUPPORTED;
+  }
+#else
+  if (meta)
+    outbuf = gst_buffer_ref (inbuf);
+  else if (GST_VIDEO_INFO_IS_YUV (&plugin->sinkpad_info)) {
+    outbuf = gst_vaapi_uploader_get_buffer (plugin->uploader);
+    if (!outbuf)
+      goto error_create_buffer;
+    gst_buffer_copy_metadata (outbuf, inbuf,
+        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
+  } else
+    goto error_invalid_buffer;
+
+  if (GST_VIDEO_INFO_IS_YUV (&plugin->sinkpad_info) &&
+      !gst_vaapi_uploader_process (plugin->uploader, inbuf, outbuf))
+    goto error_copy_buffer;
+
+  *outbuf_ptr = outbuf;
+  return GST_FLOW_OK;
+#endif
+
+  /* ERRORS */
+error_invalid_buffer:
+  {
+    GST_ERROR ("failed to validate source buffer");
+    return GST_FLOW_ERROR;
+  }
+error_create_buffer:
+  {
+    GST_ERROR ("failed to create buffer");
+    return GST_FLOW_ERROR;
+  }
+error_copy_buffer:
+  {
+    GST_WARNING ("failed to upload buffer to VA surface");
+    gst_buffer_unref (outbuf);
+    return GST_FLOW_NOT_SUPPORTED;
+  }
+}
index 68ed6c8..6c8abcf 100644 (file)
@@ -30,6 +30,7 @@
 #include <gst/video/gstvideoencoder.h>
 #include <gst/video/gstvideosink.h>
 #include <gst/vaapi/gstvaapidisplay.h>
+#include "gstvaapiuploader.h"
 
 G_BEGIN_DECLS
 
@@ -96,6 +97,13 @@ typedef struct _GstVaapiPluginBaseClass GstVaapiPluginBaseClass;
   (gst_vaapi_display_replace(&GST_VAAPI_PLUGIN_BASE_DISPLAY(plugin), \
        (new_display)))
 
+#define GST_VAAPI_PLUGIN_BASE_UPLOADER(plugin) \
+  (GST_VAAPI_PLUGIN_BASE(plugin)->uploader)
+#define GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS(plugin) \
+  (gst_vaapi_uploader_get_caps(GST_VAAPI_PLUGIN_BASE_UPLOADER(plugin)))
+#define GST_VAAPI_PLUGIN_BASE_UPLOADER_USED(plugin) \
+  (GST_VAAPI_PLUGIN_BASE(plugin)->uploader_used)
+
 struct _GstVaapiPluginBase
 {
   /*< private >*/
@@ -115,6 +123,10 @@ struct _GstVaapiPluginBase
   gboolean sinkpad_caps_changed;
   GstVideoInfo sinkpad_info;
   GstPadQueryFunction sinkpad_query;
+#if GST_CHECK_VERSION(1,0,0)
+  GstBufferPool *sinkpad_buffer_pool;
+  guint sinkpad_buffer_size;
+#endif
 
   GstPad *srcpad;
   GstCaps *srcpad_caps;
@@ -125,6 +137,9 @@ struct _GstVaapiPluginBase
   GstVaapiDisplay *display;
   GstVaapiDisplayType display_type;
   GstVaapiDisplayType display_type_req;
+
+  GstVaapiUploader *uploader;
+  gboolean uploader_used;
 };
 
 struct _GstVaapiPluginBaseClass
@@ -179,9 +194,28 @@ gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin);
 
 G_GNUC_INTERNAL
 gboolean
+gst_vaapi_plugin_base_ensure_uploader (GstVaapiPluginBase * plugin);
+
+G_GNUC_INTERNAL
+gboolean
 gst_vaapi_plugin_base_set_caps (GstVaapiPluginBase * plugin, GstCaps * incaps,
     GstCaps * outcaps);
 
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
+    GstQuery * query);
+
+G_GNUC_INTERNAL
+GstFlowReturn
+gst_vaapi_plugin_base_allocate_input_buffer (GstVaapiPluginBase * plugin,
+    GstCaps * caps, GstBuffer ** outbuf_ptr);
+
+G_GNUC_INTERNAL
+GstFlowReturn
+gst_vaapi_plugin_base_get_input_buffer (GstVaapiPluginBase * plugin,
+    GstBuffer * inbuf, GstBuffer ** outbuf_ptr);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_PLUGIN_BASE_H */
index fb61a0c..58fff7a 100755 (executable)
@@ -212,29 +212,8 @@ gst_vaapipostproc_ensure_uploader(GstVaapiPostproc *postproc)
 {
     if (!gst_vaapipostproc_ensure_display(postproc))
         return FALSE;
-
-    if (!postproc->uploader) {
-        postproc->uploader = gst_vaapi_uploader_new(
-            GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc));
-        if (!postproc->uploader)
-            return FALSE;
-    }
-
-    if (!gst_vaapi_uploader_ensure_display(postproc->uploader,
-            GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc)))
-        return FALSE;
-    return TRUE;
-}
-
-static gboolean
-gst_vaapipostproc_ensure_uploader_caps(GstVaapiPostproc *postproc)
-{
-#if !GST_CHECK_VERSION(1,0,0)
-    GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(postproc);
-    if (postproc->is_raw_yuv && !gst_vaapi_uploader_ensure_caps(
-            postproc->uploader, plugin->sinkpad_caps, NULL))
+    if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(postproc)))
         return FALSE;
-#endif
     return TRUE;
 }
 
@@ -279,8 +258,6 @@ gst_vaapipostproc_create(GstVaapiPostproc *postproc)
         return FALSE;
     if (!gst_vaapipostproc_ensure_uploader(postproc))
         return FALSE;
-    if (!gst_vaapipostproc_ensure_uploader_caps(postproc))
-        return FALSE;
     if (gst_vaapipostproc_ensure_filter(postproc))
         postproc->use_vpp = TRUE;
     return TRUE;
@@ -306,10 +283,6 @@ static void
 gst_vaapipostproc_destroy(GstVaapiPostproc *postproc)
 {
     ds_reset(&postproc->deinterlace_state);
-#if GST_CHECK_VERSION(1,0,0)
-    g_clear_object(&postproc->sinkpad_buffer_pool);
-#endif
-    g_clear_object(&postproc->uploader);
     gst_vaapipostproc_destroy_filter(postproc);
 
     gst_caps_replace(&postproc->allowed_sinkpad_caps, NULL);
@@ -791,16 +764,6 @@ gst_vaapipostproc_update_sink_caps(GstVaapiPostproc *postproc, GstCaps *caps,
         (1 + deinterlace) * GST_VIDEO_INFO_FPS_N(&vi));
 
     postproc->is_raw_yuv = GST_VIDEO_INFO_IS_YUV(&vi);
-#if !GST_CHECK_VERSION(1,0,0)
-    if (postproc->is_raw_yuv) {
-        /* Ensure the uploader is set up for upstream allocated buffers */
-        GstVaapiUploader * const uploader = postproc->uploader;
-        if (!gst_vaapi_uploader_ensure_display(uploader, GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc)))
-            return FALSE;
-        if (!gst_vaapi_uploader_ensure_caps(uploader, caps, NULL))
-            return FALSE;
-    }
-#endif
     return TRUE;
 }
 
@@ -849,7 +812,7 @@ ensure_allowed_sinkpad_caps(GstVaapiPostproc *postproc)
 
     /* Append YUV caps */
     if (gst_vaapipostproc_ensure_uploader(postproc)) {
-        yuv_caps = gst_vaapi_uploader_get_caps(postproc->uploader);
+        yuv_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS(postproc);
         if (yuv_caps) {
             out_caps = gst_caps_make_writable(out_caps);
             gst_caps_append(out_caps, gst_caps_copy(yuv_caps));
@@ -1117,107 +1080,6 @@ gst_vaapipostproc_transform_size(GstBaseTransform *trans,
     return TRUE;
 }
 
-static GstBuffer *
-get_source_buffer(GstVaapiPostproc *postproc, GstBuffer *inbuf)
-{
-    GstVaapiVideoMeta *meta;
-    GstBuffer *outbuf;
-#if GST_CHECK_VERSION(1,0,0)
-    GstVideoFrame src_frame, out_frame;
-#endif
-
-    meta = gst_buffer_get_vaapi_video_meta(inbuf);
-    if (meta)
-        return gst_buffer_ref(inbuf);
-
-#if GST_CHECK_VERSION(1,0,0)
-    if (!postproc->is_raw_yuv)
-        goto error_invalid_buffer;
-
-    if (!postproc->sinkpad_buffer_pool)
-        goto error_no_pool;
-
-    if (!gst_buffer_pool_set_active(postproc->sinkpad_buffer_pool, TRUE))
-        goto error_active_pool;
-
-    outbuf = NULL;
-    if (gst_buffer_pool_acquire_buffer(postproc->sinkpad_buffer_pool,
-            &outbuf, NULL) != GST_FLOW_OK)
-        goto error_create_buffer;
-
-    if (!gst_video_frame_map(&src_frame, &postproc->sinkpad_info, inbuf,
-            GST_MAP_READ))
-        goto error_map_src_buffer;
-
-    if (!gst_video_frame_map(&out_frame, &postproc->sinkpad_info, outbuf,
-            GST_MAP_WRITE))
-        goto error_map_dst_buffer;
-
-    if (!gst_video_frame_copy(&out_frame, &src_frame))
-        goto error_copy_buffer;
-
-    gst_video_frame_unmap(&out_frame);
-    gst_video_frame_unmap(&src_frame);
-    gst_buffer_copy_into(outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
-    return outbuf;
-
-    /* ERRORS */
-error_invalid_buffer:
-    {
-        GST_ERROR("failed to validate source buffer");
-        return NULL;
-    }
-error_no_pool:
-    {
-        GST_ERROR("no buffer pool was negotiated");
-        return NULL;
-    }
-error_active_pool:
-    {
-        GST_ERROR("failed to activate buffer pool");
-        return NULL;
-    }
-error_map_dst_buffer:
-    {
-        gst_video_frame_unmap(&src_frame);
-        // fall-through
-    }
-error_map_src_buffer:
-    {
-        GST_ERROR("failed to map buffer");
-        gst_buffer_unref(outbuf);
-        return NULL;
-    }
-#else
-    outbuf = gst_vaapi_uploader_get_buffer(postproc->uploader);
-    if (!outbuf)
-        goto error_create_buffer;
-    if (!gst_vaapi_uploader_process(postproc->uploader, inbuf, outbuf))
-        goto error_copy_buffer;
-
-    gst_buffer_copy_metadata(outbuf, inbuf,
-        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
-    return outbuf;
-#endif
-
-    /* ERRORS */
-error_create_buffer:
-    {
-        GST_ERROR("failed to create buffer");
-        return NULL;
-    }
-error_copy_buffer:
-    {
-        GST_ERROR("failed to upload buffer to VA surface");
-#if GST_CHECK_VERSION(1,0,0)
-        gst_video_frame_unmap(&out_frame);
-        gst_video_frame_unmap(&src_frame);
-#endif
-        gst_buffer_unref(outbuf);
-        return NULL;
-    }
-}
-
 static GstFlowReturn
 gst_vaapipostproc_transform(GstBaseTransform *trans, GstBuffer *inbuf,
     GstBuffer *outbuf)
@@ -1226,8 +1088,9 @@ gst_vaapipostproc_transform(GstBaseTransform *trans, GstBuffer *inbuf,
     GstBuffer *buf;
     GstFlowReturn ret;
 
-    buf = get_source_buffer(postproc, inbuf);
-    if (!buf)
+    ret = gst_vaapi_plugin_base_get_input_buffer(
+        GST_VAAPI_PLUGIN_BASE(postproc), inbuf, &buf);
+    if (ret != GST_FLOW_OK)
         return GST_FLOW_ERROR;
 
     ret = GST_FLOW_NOT_SUPPORTED;
@@ -1273,73 +1136,6 @@ gst_vaapipostproc_prepare_output_buffer(GstBaseTransform *trans,
 }
 
 static gboolean
-ensure_sinkpad_buffer_pool(GstVaapiPostproc *postproc, GstCaps *caps)
-{
-#if GST_CHECK_VERSION(1,0,0)
-    GstBufferPool *pool;
-    GstCaps *pool_caps;
-    GstStructure *config;
-    GstVideoInfo vi;
-    gboolean need_pool;
-
-    if (!gst_vaapipostproc_ensure_display(postproc))
-        return FALSE;
-
-    if (postproc->sinkpad_buffer_pool) {
-        config = gst_buffer_pool_get_config(postproc->sinkpad_buffer_pool);
-        gst_buffer_pool_config_get_params(config, &pool_caps, NULL, NULL, NULL);
-        need_pool = !gst_caps_is_equal(caps, pool_caps);
-        gst_structure_free(config);
-        if (!need_pool)
-            return TRUE;
-        g_clear_object(&postproc->sinkpad_buffer_pool);
-        postproc->sinkpad_buffer_size = 0;
-    }
-
-    pool = gst_vaapi_video_buffer_pool_new(
-        GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc));
-    if (!pool)
-        goto error_create_pool;
-
-    gst_video_info_init(&vi);
-    gst_video_info_from_caps(&vi, caps);
-    if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED) {
-        GST_DEBUG("assume sink pad buffer pool format is NV12");
-        gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
-            GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
-    }
-    postproc->sinkpad_buffer_size = vi.size;
-
-    config = gst_buffer_pool_get_config(pool);
-    gst_buffer_pool_config_set_params(config, caps,
-        postproc->sinkpad_buffer_size, 0, 0);
-    gst_buffer_pool_config_add_option(config,
-        GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
-    gst_buffer_pool_config_add_option(config,
-        GST_BUFFER_POOL_OPTION_VIDEO_META);
-    if (!gst_buffer_pool_set_config(pool, config))
-        goto error_pool_config;
-    postproc->sinkpad_buffer_pool = pool;
-    return TRUE;
-
-    /* ERRORS */
-error_create_pool:
-    {
-        GST_ERROR("failed to create buffer pool");
-        return FALSE;
-    }
-error_pool_config:
-    {
-        GST_ERROR("failed to reset buffer pool config");
-        gst_object_unref(pool);
-        return FALSE;
-    }
-#else
-    return TRUE;
-#endif
-}
-
-static gboolean
 ensure_srcpad_buffer_pool(GstVaapiPostproc *postproc, GstCaps *caps)
 {
     GstVideoInfo vi;
@@ -1378,15 +1174,13 @@ gst_vaapipostproc_set_caps(GstBaseTransform *trans, GstCaps *caps,
 
     if (caps_changed) {
         gst_vaapipostproc_destroy(postproc);
+        if (!gst_vaapipostproc_create(postproc))
+            return FALSE;
         if (!gst_vaapi_plugin_base_set_caps(GST_VAAPI_PLUGIN_BASE(trans),
                 caps, out_caps))
             return FALSE;
-        if (!gst_vaapipostproc_create(postproc))
-            return FALSE;
     }
 
-    if (!ensure_sinkpad_buffer_pool(postproc, caps))
-        return FALSE;
     if (!ensure_srcpad_buffer_pool(postproc, out_caps))
         return FALSE;
     return TRUE;
@@ -1415,40 +1209,14 @@ gst_vaapipostproc_propose_allocation(GstBaseTransform *trans,
     GstQuery *decide_query, GstQuery *query)
 {
     GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
-    GstCaps *caps = NULL;
-    gboolean need_pool;
+    GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(trans);
 
     /* Let vaapidecode allocate the video buffers */
     if (!postproc->is_raw_yuv)
         return FALSE;
-
-    gst_query_parse_allocation(query, &caps, &need_pool);
-
-    if (need_pool) {
-        if (!caps)
-            goto error_no_caps;
-        if (!ensure_sinkpad_buffer_pool(postproc, caps))
-            return FALSE;
-        gst_query_add_allocation_pool(query, postproc->sinkpad_buffer_pool,
-            postproc->sinkpad_buffer_size, 0, 0);
-    }
-
-    gst_query_add_allocation_meta(query,
-        GST_VAAPI_VIDEO_META_API_TYPE, NULL);
-    gst_query_add_allocation_meta(query,
-        GST_VIDEO_META_API_TYPE, NULL);
-    gst_query_add_allocation_meta(query,
-        GST_VIDEO_CROP_META_API_TYPE, NULL);
-    gst_query_add_allocation_meta(query,
-        GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
-    return TRUE;
-
-    /* ERRORS */
-error_no_caps:
-    {
-        GST_ERROR("no caps specified");
+    if (!gst_vaapi_plugin_base_propose_allocation(plugin, query))
         return FALSE;
-    }
+    return TRUE;
 }
 #endif
 
index fe04947..93b4495 100755 (executable)
@@ -27,7 +27,6 @@
 #include <gst/vaapi/gstvaapisurface.h>
 #include <gst/vaapi/gstvaapisurfacepool.h>
 #include <gst/vaapi/gstvaapifilter.h>
-#include "gstvaapiuploader.h"
 
 G_BEGIN_DECLS
 
@@ -136,7 +135,6 @@ struct _GstVaapiPostproc {
     /*< private >*/
     GstVaapiPluginBase          parent_instance;
 
-    GstVaapiUploader           *uploader;
     GstVaapiFilter             *filter;
     GPtrArray                  *filter_ops;
     GstVaapiVideoPool          *filter_pool;
@@ -149,10 +147,6 @@ struct _GstVaapiPostproc {
 
     GstCaps                    *allowed_sinkpad_caps;
     GstVideoInfo                sinkpad_info;
-#if GST_CHECK_VERSION(1,0,0)
-    GstBufferPool              *sinkpad_buffer_pool;
-#endif
-    guint                       sinkpad_buffer_size;
     GstCaps                    *allowed_srcpad_caps;
     GstVideoInfo                srcpad_info;
 
index e219753..3b7f8d7 100644 (file)
@@ -239,10 +239,7 @@ gst_vaapisink_destroy(GstVaapiSink *sink)
 #if USE_GLX
     gst_vaapi_texture_replace(&sink->texture, NULL);
 #endif
-    g_clear_object(&sink->uploader);
-
     gst_caps_replace(&sink->caps, NULL);
-    gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(sink));
 }
 
 #if USE_X11
@@ -341,13 +338,8 @@ gst_vaapisink_ensure_uploader(GstVaapiSink *sink)
 {
     if (!gst_vaapisink_ensure_display(sink))
         return FALSE;
-
-    if (!sink->uploader) {
-        sink->uploader = gst_vaapi_uploader_new(
-            GST_VAAPI_PLUGIN_BASE_DISPLAY(sink));
-        if (!sink->uploader)
-            return FALSE;
-    }
+    if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(sink)))
+        return FALSE;
     return TRUE;
 }
 
@@ -606,72 +598,6 @@ end:
 }
 
 static gboolean
-gst_vaapisink_ensure_video_buffer_pool(GstVaapiSink *sink, GstCaps *caps)
-{
-#if GST_CHECK_VERSION(1,0,0)
-    GstBufferPool *pool;
-    GstCaps *pool_caps;
-    GstStructure *config;
-    GstVideoInfo vi;
-    gboolean need_pool;
-
-    if (!gst_vaapisink_ensure_display(sink))
-        return FALSE;
-
-    if (sink->video_buffer_pool) {
-        config = gst_buffer_pool_get_config(sink->video_buffer_pool);
-        gst_buffer_pool_config_get_params(config, &pool_caps, NULL, NULL, NULL);
-        need_pool = !gst_caps_is_equal(caps, pool_caps);
-        gst_structure_free(config);
-        if (!need_pool)
-            return TRUE;
-        g_clear_object(&sink->video_buffer_pool);
-        sink->video_buffer_size = 0;
-    }
-
-    pool = gst_vaapi_video_buffer_pool_new(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink));
-    if (!pool)
-        goto error_create_pool;
-
-    gst_video_info_init(&vi);
-    gst_video_info_from_caps(&vi, caps);
-    if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED) {
-        GST_DEBUG("assume video buffer pool format is NV12");
-        gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
-            GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
-    }
-    sink->video_buffer_size = vi.size;
-
-    config = gst_buffer_pool_get_config(pool);
-    gst_buffer_pool_config_set_params(config, caps, sink->video_buffer_size,
-        0, 0);
-    gst_buffer_pool_config_add_option(config,
-        GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
-    gst_buffer_pool_config_add_option(config,
-        GST_BUFFER_POOL_OPTION_VIDEO_META);
-    if (!gst_buffer_pool_set_config(pool, config))
-        goto error_pool_config;
-    sink->video_buffer_pool = pool;
-    return TRUE;
-
-    /* ERRORS */
-error_create_pool:
-    {
-        GST_ERROR("failed to create buffer pool");
-        return FALSE;
-    }
-error_pool_config:
-    {
-        GST_ERROR("failed to reset buffer pool config");
-        gst_object_unref(pool);
-        return FALSE;
-    }
-#else
-    return TRUE;
-#endif
-}
-
-static gboolean
 gst_vaapisink_start(GstBaseSink *base_sink)
 {
     GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
@@ -691,7 +617,7 @@ gst_vaapisink_stop(GstBaseSink *base_sink)
     g_clear_object(&sink->video_buffer_pool);
 #endif
     gst_vaapi_window_replace(&sink->window, NULL);
-    g_clear_object(&sink->uploader);
+
     gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(sink));
     return TRUE;
 }
@@ -711,7 +637,7 @@ gst_vaapisink_get_caps_impl(GstBaseSink *base_sink)
         return NULL;
 
     if (gst_vaapisink_ensure_uploader(sink)) {
-        yuv_caps = gst_vaapi_uploader_get_caps(sink->uploader);
+        yuv_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS(sink);
         if (yuv_caps) {
             out_caps = gst_caps_make_writable(out_caps);
             gst_caps_append(out_caps, gst_caps_copy(yuv_caps));
@@ -745,7 +671,7 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps)
 {
     GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(base_sink);
     GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
-    GstVideoInfo * const vip = &sink->video_info;
+    GstVideoInfo * const vip = GST_VAAPI_PLUGIN_BASE_SINK_PAD_INFO(sink);
     GstVaapiDisplay *display;
     guint win_width, win_height;
 
@@ -761,12 +687,6 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps)
     if (!gst_vaapi_plugin_base_set_caps(plugin, caps, NULL))
         return FALSE;
 
-    if (!gst_vaapisink_ensure_video_buffer_pool(sink, caps))
-        return FALSE;
-
-    if (!gst_video_info_from_caps(vip, caps))
-        return FALSE;
-    sink->use_video_raw = GST_VIDEO_INFO_IS_YUV(vip);
     sink->video_width   = GST_VIDEO_INFO_WIDTH(vip);
     sink->video_height  = GST_VIDEO_INFO_HEIGHT(vip);
     sink->video_par_n   = GST_VIDEO_INFO_PAR_N(vip);
@@ -776,16 +696,6 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps)
 
     gst_caps_replace(&sink->caps, caps);
 
-#if !GST_CHECK_VERSION(1,0,0)
-    if (sink->use_video_raw) {
-        /* Ensure the uploader is set up for upstream allocated buffers */
-        if (!gst_vaapi_uploader_ensure_display(sink->uploader, display))
-            return FALSE;
-        if (!gst_vaapi_uploader_ensure_caps(sink->uploader, caps, NULL))
-            return FALSE;
-    }
-#endif
-
     gst_vaapisink_ensure_rotation(sink, FALSE);
 
     gst_vaapisink_ensure_window_size(sink, &win_width, &win_height);
@@ -1029,116 +939,6 @@ gst_vaapisink_put_surface(
     return TRUE;
 }
 
-#if GST_CHECK_VERSION(1,0,0)
-static GstFlowReturn
-gst_vaapisink_get_render_buffer(GstVaapiSink *sink, GstBuffer *src_buffer,
-    GstBuffer **out_buffer_ptr)
-{
-    GstVaapiVideoMeta *meta;
-    GstBuffer *out_buffer;
-    GstBufferPoolAcquireParams params = { 0, };
-    GstVideoFrame src_frame, out_frame;
-    GstFlowReturn ret;
-
-    meta = gst_buffer_get_vaapi_video_meta(src_buffer);
-    if (meta) {
-        *out_buffer_ptr = gst_buffer_ref(src_buffer);
-        return GST_FLOW_OK;
-    }
-
-    if (!sink->use_video_raw) {
-        GST_ERROR("unsupported video buffer");
-        return GST_FLOW_EOS;
-    }
-
-    GST_DEBUG("buffer %p not from our pool, copying", src_buffer);
-
-    *out_buffer_ptr = NULL;
-    if (!sink->video_buffer_pool)
-        goto error_no_pool;
-
-    if (!gst_buffer_pool_set_active(sink->video_buffer_pool, TRUE))
-        goto error_activate_pool;
-
-    params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
-    ret = gst_buffer_pool_acquire_buffer(sink->video_buffer_pool, &out_buffer,
-        &params);
-    if (ret != GST_FLOW_OK)
-        goto error_create_buffer;
-
-    if (!gst_video_frame_map(&src_frame, &sink->video_info, src_buffer,
-            GST_MAP_READ))
-        goto error_map_src_buffer;
-
-    if (!gst_video_frame_map(&out_frame, &sink->video_info, out_buffer,
-            GST_MAP_WRITE))
-        goto error_map_dst_buffer;
-
-    gst_video_frame_copy(&out_frame, &src_frame);
-    gst_video_frame_unmap(&out_frame);
-    gst_video_frame_unmap(&src_frame);
-
-    *out_buffer_ptr = out_buffer;
-    return GST_FLOW_OK;
-
-    /* ERRORS */
-error_no_pool:
-    GST_ERROR("no buffer pool was negotiated");
-    return GST_FLOW_ERROR;
-error_activate_pool:
-    GST_ERROR("failed to activate buffer pool");
-    return GST_FLOW_ERROR;
-error_create_buffer:
-    GST_WARNING("failed to create image. Skipping this frame");
-    return GST_FLOW_OK;
-error_map_dst_buffer:
-    gst_video_frame_unmap(&src_frame);
-    // fall-through
-error_map_src_buffer:
-    GST_WARNING("failed to map buffer. Skipping this frame");
-    gst_buffer_unref(out_buffer);
-    return GST_FLOW_OK;
-}
-#else
-static GstFlowReturn
-gst_vaapisink_get_render_buffer(GstVaapiSink *sink, GstBuffer *src_buffer,
-    GstBuffer **out_buffer_ptr)
-{
-    GstVaapiVideoMeta *meta;
-    GstBuffer *out_buffer;
-
-    *out_buffer_ptr = NULL;
-    meta = gst_buffer_get_vaapi_video_meta(src_buffer);
-    if (meta)
-        out_buffer = gst_buffer_ref(src_buffer);
-    else if (sink->use_video_raw) {
-        out_buffer = gst_vaapi_uploader_get_buffer(sink->uploader);
-        if (!out_buffer)
-            goto error_create_buffer;
-    }
-    else {
-        GST_ERROR("unsupported video buffer");
-        return GST_FLOW_EOS;
-    }
-
-    if (sink->use_video_raw &&
-        !gst_vaapi_uploader_process(sink->uploader, src_buffer, out_buffer))
-        goto error_copy_buffer;
-
-    *out_buffer_ptr = out_buffer;
-    return GST_FLOW_OK;
-
-    /* ERRORS */
-error_create_buffer:
-    GST_WARNING("failed to create buffer. Skipping this frame");
-    return GST_FLOW_OK;
-error_copy_buffer:
-    GST_WARNING("failed to copy buffers. Skipping this frame");
-    gst_buffer_unref(out_buffer);
-    return GST_FLOW_OK;
-}
-#endif
-
 static GstFlowReturn
 gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *src_buffer)
 {
@@ -1166,8 +966,9 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *src_buffer)
     }
 #endif
 
-    ret = gst_vaapisink_get_render_buffer(sink, src_buffer, &buffer);
-    if (ret != GST_FLOW_OK || !buffer)
+    ret = gst_vaapi_plugin_base_get_input_buffer(GST_VAAPI_PLUGIN_BASE(sink),
+        src_buffer, &buffer);
+    if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_SUPPORTED)
         return ret;
 
     meta = gst_buffer_get_vaapi_video_meta(buffer);
@@ -1249,78 +1050,23 @@ error:
 static gboolean
 gst_vaapisink_propose_allocation(GstBaseSink *base_sink, GstQuery *query)
 {
-    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
-    GstCaps *caps = NULL;
-    gboolean need_pool;
-
-    gst_query_parse_allocation(query, &caps, &need_pool);
+    GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(base_sink);
 
-    if (need_pool) {
-        if (!caps)
-            goto error_no_caps;
-        if (!gst_vaapisink_ensure_video_buffer_pool(sink, caps))
-            return FALSE;
-        gst_query_add_allocation_pool(query, sink->video_buffer_pool,
-            sink->video_buffer_size, 0, 0);
-    }
+    if (!gst_vaapi_plugin_base_propose_allocation(plugin, query))
+        return FALSE;
 
-    gst_query_add_allocation_meta(query,
-        GST_VAAPI_VIDEO_META_API_TYPE, NULL);
-    gst_query_add_allocation_meta(query,
-        GST_VIDEO_META_API_TYPE, NULL);
-    gst_query_add_allocation_meta(query,
-        GST_VIDEO_CROP_META_API_TYPE, NULL);
+    gst_query_add_allocation_meta(query, GST_VIDEO_CROP_META_API_TYPE, NULL);
     gst_query_add_allocation_meta(query,
         GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
     return TRUE;
-
-    /* ERRORS */
-error_no_caps:
-    {
-        GST_ERROR("no caps specified");
-        return FALSE;
-    }
 }
 #else
 static GstFlowReturn
-gst_vaapisink_buffer_alloc(
-    GstBaseSink        *base_sink,
-    guint64             offset,
-    guint               size,
-    GstCaps            *caps,
-    GstBuffer         **pbuf
-)
+gst_vaapisink_buffer_alloc(GstBaseSink *base_sink, guint64 offset, guint size,
+    GstCaps *caps, GstBuffer **outbuf_ptr)
 {
-    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
-    GstVideoInfo vi;
-    GstBuffer *buf;
-
-    *pbuf = NULL;
-
-    if (!sink->use_video_raw) {
-        /* Note: this code path is rarely used but for raw YUV formats
-           from custom pipeline. Otherwise, GstBaseSink::set_caps() is
-           called first, and GstBaseSink::buffer_alloc() is not called
-           in VA surface format mode */
-        if (!gst_video_info_from_caps(&vi, caps))
-            return GST_FLOW_NOT_SUPPORTED;
-        if (!GST_VIDEO_INFO_IS_YUV(&vi))
-            return GST_FLOW_OK;
-    }
-
-    if (!gst_vaapi_uploader_ensure_display(sink->uploader, GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)))
-        return GST_FLOW_NOT_SUPPORTED;
-    if (!gst_vaapi_uploader_ensure_caps(sink->uploader, caps, NULL))
-        return GST_FLOW_NOT_SUPPORTED;
-
-    buf = gst_vaapi_uploader_get_buffer(sink->uploader);
-    if (!buf) {
-        GST_WARNING("failed to allocate resources for raw YUV buffer");
-        return GST_FLOW_NOT_SUPPORTED;
-    }
-
-    *pbuf = buf;
-    return GST_FLOW_OK;
+    return gst_vaapi_plugin_base_allocate_input_buffer(
+        GST_VAAPI_PLUGIN_BASE(base_sink), caps, outbuf_ptr);
 }
 #endif
 
index 8aae2ff..bcabe08 100644 (file)
@@ -31,7 +31,6 @@
 #include <gst/vaapi/gstvaapitexture.h>
 #endif
 #include "gstvaapipluginutil.h"
-#include "gstvaapiuploader.h"
 
 G_BEGIN_DECLS
 
@@ -69,7 +68,6 @@ struct _GstVaapiSink {
     /*< private >*/
     GstVaapiPluginBase  parent_instance;
 
-    GstVaapiUploader   *uploader;
     GstCaps            *caps;
     GstVaapiWindow     *window;
     guint               window_width;
@@ -96,7 +94,6 @@ struct _GstVaapiSink {
     guint               use_overlay     : 1;
     guint               use_rotation    : 1;
     guint               keep_aspect     : 1;
-    guint               use_video_raw   : 1;
 };
 
 struct _GstVaapiSinkClass {