plugins: factor out support for raw YUV buffers on sink pads.

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.
This commit is contained in:
Gwenole Beauchesne 2013-12-17 18:52:23 +01:00
parent b324fc6add
commit e3dcd33114
8 changed files with 402 additions and 776 deletions

View 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)
if (!gst_vaapi_plugin_base_ensure_uploader (GST_VAAPI_PLUGIN_BASE (encode)))
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))
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;
}
@ -450,72 +407,6 @@ gst_vaapiencode_update_src_caps (GstVaapiEncode * encode,
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)
{
@ -523,9 +414,6 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
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,
@ -557,114 +449,6 @@ gst_vaapiencode_reset (GstVideoEncoder * venc, gboolean hard)
return TRUE;
}
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;
GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (venc);
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))
if (!gst_vaapi_plugin_base_propose_allocation (plugin, query))
return FALSE;
gst_query_add_allocation_pool (query, encode->video_buffer_pool,
encode->video_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
@ -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);

View 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 */

View file

@ -26,6 +26,10 @@
#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;
@ -227,6 +238,104 @@ gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin)
return TRUE;
}
/**
* 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
@ -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;
}
}

View 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
@ -177,11 +192,30 @@ G_GNUC_INTERNAL
gboolean
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 */

View file

@ -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)
if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(postproc)))
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))
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;
@ -1272,73 +1135,6 @@ gst_vaapipostproc_prepare_output_buffer(GstBaseTransform *trans,
return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR;
}
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)
{
@ -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))
if (!gst_vaapi_plugin_base_propose_allocation(plugin, query))
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");
return FALSE;
}
}
#endif

View file

@ -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;

View 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)
if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(sink)))
return FALSE;
}
return TRUE;
}
@ -605,72 +597,6 @@ end:
return success;
}
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)
{
@ -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;
GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(base_sink);
gst_query_parse_allocation(query, &caps, &need_pool);
if (need_pool) {
if (!caps)
goto error_no_caps;
if (!gst_vaapisink_ensure_video_buffer_pool(sink, caps))
if (!gst_vaapi_plugin_base_propose_allocation(plugin, query))
return FALSE;
gst_query_add_allocation_pool(query, sink->video_buffer_pool,
sink->video_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_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

View 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 {