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;
}
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));
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;
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));
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;
}
}
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))
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,
}
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)
{
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;
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
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);
#include "gstvaapipluginbase.h"
#include <gst/vaapi/gstvaapiencoder.h>
-#include "gstvaapiuploader.h"
G_BEGIN_DECLS
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 */
#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)
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;
}
/**
+ * 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
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;
+ }
+}
#include <gst/video/gstvideoencoder.h>
#include <gst/video/gstvideosink.h>
#include <gst/vaapi/gstvaapidisplay.h>
+#include "gstvaapiuploader.h"
G_BEGIN_DECLS
(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 >*/
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;
GstVaapiDisplay *display;
GstVaapiDisplayType display_type;
GstVaapiDisplayType display_type_req;
+
+ GstVaapiUploader *uploader;
+ gboolean uploader_used;
};
struct _GstVaapiPluginBaseClass
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 */
{
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;
}
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;
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);
(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;
}
/* 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));
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)
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;
}
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;
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;
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
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/gstvaapisurfacepool.h>
#include <gst/vaapi/gstvaapifilter.h>
-#include "gstvaapiuploader.h"
G_BEGIN_DECLS
/*< private >*/
GstVaapiPluginBase parent_instance;
- GstVaapiUploader *uploader;
GstVaapiFilter *filter;
GPtrArray *filter_ops;
GstVaapiVideoPool *filter_pool;
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;
#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
{
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;
}
}
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);
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;
}
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));
{
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;
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);
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);
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,
- ¶ms);
- 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)
{
}
#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);
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
#include <gst/vaapi/gstvaapitexture.h>
#endif
#include "gstvaapipluginutil.h"
-#include "gstvaapiuploader.h"
G_BEGIN_DECLS
/*< private >*/
GstVaapiPluginBase parent_instance;
- GstVaapiUploader *uploader;
GstCaps *caps;
GstVaapiWindow *window;
guint window_width;
guint use_overlay : 1;
guint use_rotation : 1;
guint keep_aspect : 1;
- guint use_video_raw : 1;
};
struct _GstVaapiSinkClass {