mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
d3d11: d3d11desktopdupsrc: Add support for non-D3D11 downstream element
By this commit, application doesn't need to configure d3d11download element for software pipeline which will make things simpler Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1082>
This commit is contained in:
parent
b590511146
commit
7286c8e302
1 changed files with 201 additions and 46 deletions
|
@ -61,7 +61,8 @@ static GParamSpec *properties[PROP_LAST];
|
||||||
|
|
||||||
static GstStaticCaps template_caps =
|
static GstStaticCaps template_caps =
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||||
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, "BGRA"));
|
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, "BGRA") ";"
|
||||||
|
GST_VIDEO_CAPS_MAKE ("BGRA"));
|
||||||
|
|
||||||
struct _GstD3D11DesktopDupSrc
|
struct _GstD3D11DesktopDupSrc
|
||||||
{
|
{
|
||||||
|
@ -74,6 +75,8 @@ struct _GstD3D11DesktopDupSrc
|
||||||
GstD3D11Device *device;
|
GstD3D11Device *device;
|
||||||
GstD3D11DesktopDup *dupl;
|
GstD3D11DesktopDup *dupl;
|
||||||
|
|
||||||
|
GstBufferPool *pool;
|
||||||
|
|
||||||
gint adapter;
|
gint adapter;
|
||||||
gint monitor_index;
|
gint monitor_index;
|
||||||
gboolean show_cursor;
|
gboolean show_cursor;
|
||||||
|
@ -81,6 +84,8 @@ struct _GstD3D11DesktopDupSrc
|
||||||
gboolean flushing;
|
gboolean flushing;
|
||||||
GstClockTime min_latency;
|
GstClockTime min_latency;
|
||||||
GstClockTime max_latency;
|
GstClockTime max_latency;
|
||||||
|
|
||||||
|
gboolean downstream_supports_d3d11;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_d3d11_desktop_dup_src_dispose (GObject * object);
|
static void gst_d3d11_desktop_dup_src_dispose (GObject * object);
|
||||||
|
@ -264,13 +269,11 @@ gst_d3d11_desktop_dup_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
caps =
|
caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
|
||||||
gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "BGRA",
|
caps = gst_caps_make_writable (caps);
|
||||||
"width", G_TYPE_INT, width,
|
|
||||||
"height", G_TYPE_INT, height,
|
gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
|
||||||
"framerate", GST_TYPE_FRACTION_RANGE, 1, 1, G_MAXINT, 1, NULL);
|
G_TYPE_INT, height, nullptr);
|
||||||
gst_caps_set_features (caps, 0,
|
|
||||||
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
|
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
GstCaps *tmp =
|
GstCaps *tmp =
|
||||||
|
@ -286,25 +289,63 @@ gst_d3d11_desktop_dup_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_d3d11_desktop_dup_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
|
gst_d3d11_desktop_dup_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstStructure *structure;
|
guint size;
|
||||||
|
GstCaps *d3d11_caps = nullptr;
|
||||||
|
|
||||||
caps = gst_caps_make_writable (caps);
|
caps = gst_caps_make_writable (caps);
|
||||||
|
size = gst_caps_get_size (caps);
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
for (guint i = 0; i < size; i++) {
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
|
s = gst_caps_get_structure (caps, i);
|
||||||
|
gst_structure_fixate_field_nearest_fraction (s, "framerate", 30, 1);
|
||||||
|
|
||||||
return GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
|
if (!d3d11_caps) {
|
||||||
|
GstCapsFeatures *features;
|
||||||
|
features = gst_caps_get_features (caps, i);
|
||||||
|
|
||||||
|
if (features && gst_caps_features_contains (features,
|
||||||
|
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
|
||||||
|
|
||||||
|
d3d11_caps = gst_caps_new_empty ();
|
||||||
|
gst_caps_append_structure (d3d11_caps, gst_structure_copy (s));
|
||||||
|
|
||||||
|
gst_caps_set_features (d3d11_caps, 0,
|
||||||
|
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
|
||||||
|
nullptr));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d3d11_caps) {
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
caps = d3d11_caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gst_caps_fixate (caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_d3d11_desktop_dup_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
gst_d3d11_desktop_dup_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstD3D11DesktopDupSrc *self = GST_D3D11_DESKTOP_DUP_SRC (bsrc);
|
GstD3D11DesktopDupSrc *self = GST_D3D11_DESKTOP_DUP_SRC (bsrc);
|
||||||
|
GstCapsFeatures *features;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Set caps %" GST_PTR_FORMAT, caps);
|
GST_DEBUG_OBJECT (self, "Set caps %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
features = gst_caps_get_features (caps, 0);
|
||||||
|
if (features && gst_caps_features_contains (features,
|
||||||
|
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
|
||||||
|
self->downstream_supports_d3d11 = TRUE;
|
||||||
|
} else {
|
||||||
|
self->downstream_supports_d3d11 = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gst_video_info_from_caps (&self->video_info, caps);
|
gst_video_info_from_caps (&self->video_info, caps);
|
||||||
|
gst_base_src_set_blocksize (bsrc, GST_VIDEO_INFO_SIZE (&self->video_info));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -322,6 +363,11 @@ gst_d3d11_desktop_dup_src_decide_allocation (GstBaseSrc * bsrc,
|
||||||
gboolean update_pool;
|
gboolean update_pool;
|
||||||
GstVideoInfo vinfo;
|
GstVideoInfo vinfo;
|
||||||
|
|
||||||
|
if (self->pool) {
|
||||||
|
gst_buffer_pool_set_active (self->pool, FALSE);
|
||||||
|
gst_clear_object (&self->pool);
|
||||||
|
}
|
||||||
|
|
||||||
gst_query_parse_allocation (query, &caps, NULL);
|
gst_query_parse_allocation (query, &caps, NULL);
|
||||||
|
|
||||||
if (!caps) {
|
if (!caps) {
|
||||||
|
@ -341,7 +387,7 @@ gst_d3d11_desktop_dup_src_decide_allocation (GstBaseSrc * bsrc,
|
||||||
update_pool = FALSE;
|
update_pool = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool) {
|
if (pool && self->downstream_supports_d3d11) {
|
||||||
if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
|
if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
|
||||||
gst_clear_object (&pool);
|
gst_clear_object (&pool);
|
||||||
} else {
|
} else {
|
||||||
|
@ -351,14 +397,53 @@ gst_d3d11_desktop_dup_src_decide_allocation (GstBaseSrc * bsrc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pool)
|
if (!pool) {
|
||||||
|
if (self->downstream_supports_d3d11)
|
||||||
pool = gst_d3d11_buffer_pool_new (self->device);
|
pool = gst_d3d11_buffer_pool_new (self->device);
|
||||||
|
else
|
||||||
|
pool = gst_video_buffer_pool_new ();
|
||||||
|
}
|
||||||
|
|
||||||
config = gst_buffer_pool_get_config (pool);
|
config = gst_buffer_pool_get_config (pool);
|
||||||
|
|
||||||
gst_buffer_pool_config_set_params (config, caps, size, min, max);
|
gst_buffer_pool_config_set_params (config, caps, size, min, max);
|
||||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||||
|
|
||||||
|
if (self->downstream_supports_d3d11) {
|
||||||
|
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
||||||
|
if (!d3d11_params) {
|
||||||
|
d3d11_params = gst_d3d11_allocation_params_new (self->device, &vinfo,
|
||||||
|
(GstD3D11AllocationFlags) 0,
|
||||||
|
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||||
|
} else {
|
||||||
|
d3d11_params->desc[0].BindFlags |= D3D11_BIND_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
||||||
|
gst_d3d11_allocation_params_free (d3d11_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to set config");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->downstream_supports_d3d11) {
|
||||||
|
/* d3d11 buffer pool will update buffer size based on allocated texture,
|
||||||
|
* get size from config again */
|
||||||
|
config = gst_buffer_pool_get_config (pool);
|
||||||
|
gst_buffer_pool_config_get_params (config,
|
||||||
|
nullptr, &size, nullptr, nullptr);
|
||||||
|
gst_structure_free (config);
|
||||||
|
} else {
|
||||||
|
self->pool = gst_d3d11_buffer_pool_new (self->device);
|
||||||
|
|
||||||
|
config = gst_buffer_pool_get_config (self->pool);
|
||||||
|
|
||||||
|
gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
|
||||||
|
gst_buffer_pool_config_add_option (config,
|
||||||
|
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||||
|
|
||||||
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
|
||||||
if (!d3d11_params) {
|
if (!d3d11_params) {
|
||||||
d3d11_params = gst_d3d11_allocation_params_new (self->device, &vinfo,
|
d3d11_params = gst_d3d11_allocation_params_new (self->device, &vinfo,
|
||||||
|
@ -370,13 +455,16 @@ gst_d3d11_desktop_dup_src_decide_allocation (GstBaseSrc * bsrc,
|
||||||
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
|
||||||
gst_d3d11_allocation_params_free (d3d11_params);
|
gst_d3d11_allocation_params_free (d3d11_params);
|
||||||
|
|
||||||
gst_buffer_pool_set_config (pool, config);
|
if (!gst_buffer_pool_set_config (self->pool, config)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to set config for internal pool");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* d3d11 buffer pool will update buffer size based on allocated texture,
|
if (!gst_buffer_pool_set_active (self->pool, TRUE)) {
|
||||||
* get size from config again */
|
GST_ERROR_OBJECT (self, "Failed to activate internal pool");
|
||||||
config = gst_buffer_pool_get_config (pool);
|
goto error;
|
||||||
gst_buffer_pool_config_get_params (config, nullptr, &size, nullptr, nullptr);
|
}
|
||||||
gst_structure_free (config);
|
}
|
||||||
|
|
||||||
if (update_pool)
|
if (update_pool)
|
||||||
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
|
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
|
||||||
|
@ -386,6 +474,12 @@ gst_d3d11_desktop_dup_src_decide_allocation (GstBaseSrc * bsrc,
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
gst_clear_object (&self->pool);
|
||||||
|
gst_clear_object (&pool);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -450,6 +544,11 @@ gst_d3d11_desktop_dup_src_stop (GstBaseSrc * bsrc)
|
||||||
{
|
{
|
||||||
GstD3D11DesktopDupSrc *self = GST_D3D11_DESKTOP_DUP_SRC (bsrc);
|
GstD3D11DesktopDupSrc *self = GST_D3D11_DESKTOP_DUP_SRC (bsrc);
|
||||||
|
|
||||||
|
if (self->pool) {
|
||||||
|
gst_buffer_pool_set_active (self->pool, FALSE);
|
||||||
|
gst_clear_object (&self->pool);
|
||||||
|
}
|
||||||
|
|
||||||
gst_clear_object (&self->dupl);
|
gst_clear_object (&self->dupl);
|
||||||
gst_clear_object (&self->device);
|
gst_clear_object (&self->device);
|
||||||
|
|
||||||
|
@ -535,6 +634,7 @@ gst_d3d11_desktop_dup_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
|
||||||
/* Just magic number... */
|
/* Just magic number... */
|
||||||
gint unsupported_retry_count = 100;
|
gint unsupported_retry_count = 100;
|
||||||
GstBuffer *buffer = NULL;
|
GstBuffer *buffer = NULL;
|
||||||
|
GstBuffer *sysmem_buf = NULL;
|
||||||
|
|
||||||
if (!self->dupl) {
|
if (!self->dupl) {
|
||||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||||
|
@ -624,29 +724,40 @@ again:
|
||||||
GST_OBJECT_UNLOCK (self);
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ret =
|
if (self->downstream_supports_d3d11) {
|
||||||
GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, size, &buffer);
|
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc,
|
||||||
|
offset, size, &buffer);
|
||||||
|
} else {
|
||||||
|
if (!self->pool) {
|
||||||
|
GST_ERROR_OBJECT (self, "Internal pool wasn't configured");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_buffer_pool_acquire_buffer (self->pool, &buffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: handle fallback case
|
|
||||||
* (e.g., texture belongs to other device, RTV is unavailable) */
|
|
||||||
mem = gst_buffer_peek_memory (buffer, 0);
|
mem = gst_buffer_peek_memory (buffer, 0);
|
||||||
|
if (!gst_is_d3d11_memory (mem)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Not a D3D11 memory");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
dmem = (GstD3D11Memory *) mem;
|
dmem = (GstD3D11Memory *) mem;
|
||||||
draw_mouse = self->show_cursor;
|
draw_mouse = self->show_cursor;
|
||||||
rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
|
rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
|
||||||
if (draw_mouse && !rtv) {
|
if (draw_mouse && !rtv) {
|
||||||
GST_ERROR_OBJECT (self, "Render target view is unavailable");
|
GST_ERROR_OBJECT (self, "Render target view is unavailable");
|
||||||
ret = GST_FLOW_ERROR;
|
goto error;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_memory_map (mem, &info,
|
if (!gst_memory_map (mem, &info,
|
||||||
(GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
|
(GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to map d3d11 memory");
|
GST_ERROR_OBJECT (self, "Failed to map d3d11 memory");
|
||||||
ret = GST_FLOW_ERROR;
|
goto error;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
texture = (ID3D11Texture2D *) info.data;
|
texture = (ID3D11Texture2D *) info.data;
|
||||||
|
@ -654,10 +765,6 @@ again:
|
||||||
ret = gst_d3d11_desktop_dup_capture (self->dupl, texture, rtv, draw_mouse);
|
ret = gst_d3d11_desktop_dup_capture (self->dupl, texture, rtv, draw_mouse);
|
||||||
gst_memory_unmap (mem, &info);
|
gst_memory_unmap (mem, &info);
|
||||||
|
|
||||||
GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
|
|
||||||
GST_BUFFER_PTS (buffer) = next_capture_ts;
|
|
||||||
GST_BUFFER_DURATION (buffer) = dur;
|
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case GST_D3D11_DESKTOP_DUP_FLOW_EXPECTED_ERROR:
|
case GST_D3D11_DESKTOP_DUP_FLOW_EXPECTED_ERROR:
|
||||||
GST_WARNING_OBJECT (self, "Got expected error, try again");
|
GST_WARNING_OBJECT (self, "Got expected error, try again");
|
||||||
|
@ -667,10 +774,9 @@ again:
|
||||||
GST_WARNING_OBJECT (self, "Got DXGI_ERROR_UNSUPPORTED error");
|
GST_WARNING_OBJECT (self, "Got DXGI_ERROR_UNSUPPORTED error");
|
||||||
unsupported_retry_count--;
|
unsupported_retry_count--;
|
||||||
|
|
||||||
if (unsupported_retry_count < 0) {
|
if (unsupported_retry_count < 0)
|
||||||
ret = GST_FLOW_ERROR;
|
goto error;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
gst_clear_object (&clock);
|
gst_clear_object (&clock);
|
||||||
goto again;
|
goto again;
|
||||||
case GST_D3D11_DESKTOP_DUP_FLOW_SIZE_CHANGED:
|
case GST_D3D11_DESKTOP_DUP_FLOW_SIZE_CHANGED:
|
||||||
|
@ -688,6 +794,48 @@ again:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!self->downstream_supports_d3d11) {
|
||||||
|
GstVideoFrame src_frame, dst_frame;
|
||||||
|
gboolean copy_ret;
|
||||||
|
|
||||||
|
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc,
|
||||||
|
offset, size, &sysmem_buf);
|
||||||
|
if (ret != GST_FLOW_OK) {
|
||||||
|
gst_clear_buffer (&buffer);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&src_frame, &self->video_info, buffer,
|
||||||
|
GST_MAP_READ)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to map d3d11 buffer");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&dst_frame, &self->video_info, sysmem_buf,
|
||||||
|
GST_MAP_WRITE)) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to map sysmem buffer");
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_ret = gst_video_frame_copy (&dst_frame, &src_frame);
|
||||||
|
gst_video_frame_unmap (&dst_frame);
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
|
||||||
|
if (!copy_ret) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to copy frame");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
buffer = sysmem_buf;
|
||||||
|
sysmem_buf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
|
||||||
|
GST_BUFFER_PTS (buffer) = next_capture_ts;
|
||||||
|
GST_BUFFER_DURATION (buffer) = dur;
|
||||||
|
|
||||||
after_capture = gst_clock_get_time (clock);
|
after_capture = gst_clock_get_time (clock);
|
||||||
latency = after_capture - before_capture;
|
latency = after_capture - before_capture;
|
||||||
if (!GST_CLOCK_TIME_IS_VALID (self->min_latency)) {
|
if (!GST_CLOCK_TIME_IS_VALID (self->min_latency)) {
|
||||||
|
@ -714,4 +862,11 @@ out:
|
||||||
*buf = buffer;
|
*buf = buffer;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
gst_clear_buffer (&buffer);
|
||||||
|
gst_clear_buffer (&sysmem_buf);
|
||||||
|
gst_clear_object (&clock);
|
||||||
|
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue