mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
d3dvideosink: Implement a buffer pool that shares D3D surfaces with upstream
This commit is contained in:
parent
abede65bbc
commit
81304a7956
4 changed files with 665 additions and 129 deletions
|
@ -37,8 +37,8 @@ static gboolean d3d_init_swap_chain (GstD3DVideoSink * sink, HWND hWnd);
|
|||
static gboolean d3d_release_swap_chain (GstD3DVideoSink * sink);
|
||||
static gboolean d3d_resize_swap_chain (GstD3DVideoSink * sink);
|
||||
static gboolean d3d_present_swap_chain (GstD3DVideoSink * sink);
|
||||
static gboolean d3d_copy_buffer_to_surface (GstD3DVideoSink * sink,
|
||||
LPDIRECT3DSURFACE9 surface, GstBuffer * buffer);
|
||||
static gboolean d3d_copy_buffer (GstD3DVideoSink * sink,
|
||||
GstBuffer * from, GstBuffer * to);
|
||||
static gboolean d3d_stretch_and_copy (GstD3DVideoSink * sink,
|
||||
LPDIRECT3DSURFACE9 back_buffer);
|
||||
static HWND d3d_create_internal_window (GstD3DVideoSink * sink);
|
||||
|
@ -315,6 +315,392 @@ d3d_format_comp_compare (gconstpointer a, gconstpointer b)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define GST_D3D_SURFACE_MEMORY_NAME "D3DSurface"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstMemory mem;
|
||||
|
||||
GstD3DVideoSink *sink;
|
||||
|
||||
GMutex lock;
|
||||
gint map_count;
|
||||
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
D3DLOCKED_RECT lr;
|
||||
gint x, y, width, height;
|
||||
} GstD3DSurfaceMemory;
|
||||
|
||||
static GstMemory *
|
||||
gst_d3d_surface_memory_allocator_alloc (GstAllocator * allocator, gsize size,
|
||||
GstAllocationParams * params)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d_surface_memory_allocator_free (GstAllocator * allocator,
|
||||
GstMemory * mem)
|
||||
{
|
||||
GstD3DSurfaceMemory *dmem = (GstD3DSurfaceMemory *) mem;
|
||||
|
||||
/* If this is a sub-memory, do nothing */
|
||||
if (mem->parent)
|
||||
return;
|
||||
|
||||
if (dmem->lr.pBits)
|
||||
g_warning ("d3dvideosink: Freeing memory that is still mapped");
|
||||
|
||||
IDirect3DSurface9_Release (dmem->surface);
|
||||
gst_object_unref (dmem->sink);
|
||||
g_mutex_clear (&dmem->lock);
|
||||
g_slice_free (GstD3DSurfaceMemory, dmem);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gst_d3d_surface_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
|
||||
{
|
||||
GstD3DSurfaceMemory *parent;
|
||||
gpointer ret = NULL;
|
||||
gint d3d_flags = ((flags & GST_MAP_WRITE) == 0) ? D3DLOCK_READONLY : 0;
|
||||
|
||||
/* find the real parent */
|
||||
if ((parent = (GstD3DSurfaceMemory *) mem->parent) == NULL)
|
||||
parent = (GstD3DSurfaceMemory *) mem;
|
||||
|
||||
g_mutex_lock (&parent->lock);
|
||||
if (!parent->map_count
|
||||
&& IDirect3DSurface9_LockRect (parent->surface, &parent->lr, NULL,
|
||||
d3d_flags) != D3D_OK) {
|
||||
ret = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = parent->lr.pBits;
|
||||
parent->map_count++;
|
||||
|
||||
done:
|
||||
g_mutex_unlock (&parent->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d_surface_memory_unmap (GstMemory * mem)
|
||||
{
|
||||
GstD3DSurfaceMemory *parent;
|
||||
|
||||
/* find the real parent */
|
||||
if ((parent = (GstD3DSurfaceMemory *) mem->parent) == NULL)
|
||||
parent = (GstD3DSurfaceMemory *) mem;
|
||||
|
||||
g_mutex_lock (&parent->lock);
|
||||
parent->map_count--;
|
||||
if (parent->map_count == 0) {
|
||||
IDirect3DSurface9_UnlockRect (parent->surface);
|
||||
memset (&parent->lr, 0, sizeof (parent->lr));
|
||||
}
|
||||
|
||||
g_mutex_unlock (&parent->lock);
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_d3d_surface_memory_share (GstMemory * mem, gssize offset, gssize size)
|
||||
{
|
||||
GstD3DSurfaceMemory *sub;
|
||||
GstD3DSurfaceMemory *parent;
|
||||
|
||||
/* find the real parent */
|
||||
if ((parent = (GstD3DSurfaceMemory *) mem->parent) == NULL)
|
||||
parent = (GstD3DSurfaceMemory *) mem;
|
||||
|
||||
if (size == -1)
|
||||
size = mem->size - offset;
|
||||
|
||||
sub = g_slice_new0 (GstD3DSurfaceMemory);
|
||||
/* the shared memory is always readonly */
|
||||
gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) |
|
||||
GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->allocator,
|
||||
GST_MEMORY_CAST (parent), mem->maxsize, mem->align, mem->offset + offset,
|
||||
size);
|
||||
|
||||
return GST_MEMORY_CAST (sub);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstAllocator parent;
|
||||
} GstD3DSurfaceMemoryAllocator;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstAllocatorClass parent_class;
|
||||
} GstD3DSurfaceMemoryAllocatorClass;
|
||||
|
||||
GType gst_d3d_surface_memory_allocator_get_type (void);
|
||||
G_DEFINE_TYPE (GstD3DSurfaceMemoryAllocator, gst_d3d_surface_memory_allocator,
|
||||
GST_TYPE_ALLOCATOR);
|
||||
|
||||
#define GST_TYPE_D3D_SURFACE_MEMORY_ALLOCATOR (gst_d3d_surface_memory_allocator_get_type())
|
||||
#define GST_IS_D3D_SURFACE_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_D3D_SURFACE_MEMORY_ALLOCATOR))
|
||||
|
||||
static void
|
||||
gst_d3d_surface_memory_allocator_class_init (GstD3DSurfaceMemoryAllocatorClass *
|
||||
klass)
|
||||
{
|
||||
GstAllocatorClass *allocator_class;
|
||||
|
||||
allocator_class = (GstAllocatorClass *) klass;
|
||||
|
||||
allocator_class->alloc = gst_d3d_surface_memory_allocator_alloc;
|
||||
allocator_class->free = gst_d3d_surface_memory_allocator_free;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d_surface_memory_allocator_init (GstD3DSurfaceMemoryAllocator * allocator)
|
||||
{
|
||||
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
|
||||
|
||||
alloc->mem_type = GST_D3D_SURFACE_MEMORY_NAME;
|
||||
alloc->mem_map = gst_d3d_surface_memory_map;
|
||||
alloc->mem_unmap = gst_d3d_surface_memory_unmap;
|
||||
alloc->mem_share = gst_d3d_surface_memory_share;
|
||||
/* fallback copy */
|
||||
|
||||
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (GstD3DSurfaceBufferPool, gst_d3dsurface_buffer_pool,
|
||||
GST_TYPE_VIDEO_BUFFER_POOL);
|
||||
|
||||
GstBufferPool *
|
||||
gst_d3dsurface_buffer_pool_new (GstD3DVideoSink * sink)
|
||||
{
|
||||
GstD3DSurfaceBufferPool *pool;
|
||||
|
||||
pool = g_object_new (GST_TYPE_D3DSURFACE_BUFFER_POOL, NULL);
|
||||
pool->sink = gst_object_ref (sink);
|
||||
|
||||
GST_LOG_OBJECT (pool, "new buffer pool %p", pool);
|
||||
|
||||
return GST_BUFFER_POOL_CAST (pool);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3dsurface_buffer_pool_finalize (GObject * object)
|
||||
{
|
||||
GstD3DSurfaceBufferPool *pool = GST_D3DSURFACE_BUFFER_POOL_CAST (object);
|
||||
|
||||
GST_LOG_OBJECT (pool, "finalize buffer pool %p", pool);
|
||||
|
||||
gst_object_unref (pool->sink);
|
||||
if (pool->allocator)
|
||||
gst_object_unref (pool->allocator);
|
||||
|
||||
G_OBJECT_CLASS (gst_d3dsurface_buffer_pool_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const gchar **
|
||||
gst_d3dsurface_buffer_pool_get_options (GstBufferPool * pool)
|
||||
{
|
||||
static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3dsurface_buffer_pool_set_config (GstBufferPool * bpool,
|
||||
GstStructure * config)
|
||||
{
|
||||
GstD3DSurfaceBufferPool *pool = GST_D3DSURFACE_BUFFER_POOL_CAST (bpool);
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
|
||||
if (!GST_BUFFER_POOL_CLASS
|
||||
(gst_d3dsurface_buffer_pool_parent_class)->set_config (bpool, config)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)
|
||||
|| !caps) {
|
||||
GST_ERROR_OBJECT (pool, "Buffer pool configuration without caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* now parse the caps from the config */
|
||||
if (!gst_video_info_from_caps (&info, caps)) {
|
||||
GST_ERROR_OBJECT (pool, "Failed to parse caps %" GST_PTR_FORMAT, caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gst_video_format_to_d3d_format (GST_VIDEO_INFO_FORMAT (&info)) ==
|
||||
D3DFMT_UNKNOWN) {
|
||||
GST_ERROR_OBJECT (pool, "Unsupported video format in caps %" GST_PTR_FORMAT,
|
||||
caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height,
|
||||
caps);
|
||||
|
||||
pool->info = info;
|
||||
|
||||
pool->add_metavideo =
|
||||
gst_buffer_pool_config_has_option (config,
|
||||
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
if (pool->add_metavideo)
|
||||
pool->allocator =
|
||||
g_object_new (GST_TYPE_D3D_SURFACE_MEMORY_ALLOCATOR, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3dsurface_buffer_pool_alloc (GstBufferPool * bpool, GstBuffer ** buffer,
|
||||
GstBufferPoolAcquireParams * params)
|
||||
{
|
||||
GstD3DSurfaceBufferPool *pool = GST_D3DSURFACE_BUFFER_POOL_CAST (bpool);
|
||||
GstD3DVideoSink *sink = pool->sink;
|
||||
GstD3DVideoSinkClass *klass = GST_D3DVIDEOSINK_GET_CLASS (sink);
|
||||
GstD3DSurfaceMemory *mem;
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
D3DFORMAT d3dformat;
|
||||
gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
|
||||
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
|
||||
D3DLOCKED_RECT lr;
|
||||
HRESULT hr;
|
||||
gsize size = 0;
|
||||
|
||||
*buffer = NULL;
|
||||
if (!pool->add_metavideo) {
|
||||
GST_DEBUG_OBJECT (pool, "No video meta allowed, fallback alloc");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
d3dformat =
|
||||
gst_video_format_to_d3d_format (GST_VIDEO_INFO_FORMAT (&pool->info));
|
||||
hr = IDirect3DDevice9_CreateOffscreenPlainSurface (klass->d3d.
|
||||
device.d3d_device, GST_VIDEO_INFO_WIDTH (&pool->info),
|
||||
GST_VIDEO_INFO_HEIGHT (&pool->info), d3dformat, D3DPOOL_DEFAULT, &surface,
|
||||
NULL);
|
||||
if (hr != D3D_OK) {
|
||||
GST_ERROR_OBJECT (sink, "Failed to create D3D surface");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
IDirect3DSurface9_LockRect (surface, &lr, NULL, D3DLOCK_READONLY);
|
||||
if (!lr.pBits) {
|
||||
GST_ERROR_OBJECT (sink, "Failed to lock D3D surface");
|
||||
IDirect3DSurface9_Release (surface);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
switch (GST_VIDEO_INFO_FORMAT (&pool->info)) {
|
||||
case GST_VIDEO_FORMAT_BGR:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
size = lr.Pitch * GST_VIDEO_INFO_HEIGHT (&pool->info) * 3;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_BGRx:
|
||||
case GST_VIDEO_FORMAT_RGBx:
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
case GST_VIDEO_FORMAT_RGBA:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
size = lr.Pitch * GST_VIDEO_INFO_HEIGHT (&pool->info) * 4;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_RGB16:
|
||||
case GST_VIDEO_FORMAT_RGB15:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
size = lr.Pitch * GST_VIDEO_INFO_HEIGHT (&pool->info) * 2;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_YUY2:
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
size = lr.Pitch * GST_VIDEO_INFO_HEIGHT (&pool->info) * 2;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_YV12:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
offset[2] =
|
||||
offset[0] + stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&pool->info, 0);
|
||||
stride[2] = lr.Pitch / 2;
|
||||
offset[1] =
|
||||
offset[2] + stride[2] * GST_VIDEO_INFO_COMP_HEIGHT (&pool->info, 2);
|
||||
stride[1] = lr.Pitch / 2;
|
||||
size =
|
||||
offset[1] + stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&pool->info, 1);
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
offset[0] = 0;
|
||||
stride[0] = lr.Pitch;
|
||||
offset[1] =
|
||||
offset[0] + stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&pool->info, 0);
|
||||
stride[1] = lr.Pitch;
|
||||
size =
|
||||
offset[1] + stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&pool->info, 1);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
IDirect3DSurface9_UnlockRect (surface);
|
||||
|
||||
*buffer = gst_buffer_new ();
|
||||
|
||||
gst_buffer_add_video_meta_full (*buffer, GST_VIDEO_FRAME_FLAG_NONE,
|
||||
GST_VIDEO_INFO_FORMAT (&pool->info), GST_VIDEO_INFO_WIDTH (&pool->info),
|
||||
GST_VIDEO_INFO_HEIGHT (&pool->info),
|
||||
GST_VIDEO_INFO_N_PLANES (&pool->info), offset, stride);
|
||||
|
||||
mem = g_slice_new0 (GstD3DSurfaceMemory);
|
||||
gst_memory_init (GST_MEMORY_CAST (mem), 0, pool->allocator, NULL, size, 0, 0,
|
||||
size);
|
||||
|
||||
mem->surface = surface;
|
||||
mem->sink = gst_object_ref (sink);
|
||||
mem->x = mem->y = 0;
|
||||
mem->width = GST_VIDEO_INFO_WIDTH (&pool->info);
|
||||
mem->height = GST_VIDEO_INFO_HEIGHT (&pool->info);
|
||||
g_mutex_init (&mem->lock);
|
||||
|
||||
gst_buffer_append_memory (*buffer, GST_MEMORY_CAST (mem));
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
fallback:
|
||||
{
|
||||
return
|
||||
GST_BUFFER_POOL_CLASS
|
||||
(gst_d3dsurface_buffer_pool_parent_class)->alloc_buffer (bpool, buffer,
|
||||
params);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3dsurface_buffer_pool_class_init (GstD3DSurfaceBufferPoolClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
|
||||
|
||||
gobject_class->finalize = gst_d3dsurface_buffer_pool_finalize;
|
||||
|
||||
gstbufferpool_class->get_options = gst_d3dsurface_buffer_pool_get_options;
|
||||
gstbufferpool_class->set_config = gst_d3dsurface_buffer_pool_set_config;
|
||||
gstbufferpool_class->alloc_buffer = gst_d3dsurface_buffer_pool_alloc;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3dsurface_buffer_pool_init (GstD3DSurfaceBufferPool * pool)
|
||||
{
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
d3d_supported_caps (GstD3DVideoSink * sink)
|
||||
{
|
||||
|
@ -759,6 +1145,14 @@ end:
|
|||
gboolean
|
||||
d3d_stop (GstD3DVideoSink * sink)
|
||||
{
|
||||
if (sink->pool)
|
||||
gst_buffer_pool_set_active (sink->pool, FALSE);
|
||||
if (sink->fallback_pool)
|
||||
gst_buffer_pool_set_active (sink->fallback_pool, FALSE);
|
||||
gst_object_replace ((GstObject **) & sink->pool, NULL);
|
||||
gst_object_replace ((GstObject **) & sink->fallback_pool, NULL);
|
||||
gst_buffer_replace (&sink->fallback_buffer, NULL);
|
||||
|
||||
/* Release D3D resources */
|
||||
d3d_set_window_handle (sink, 0, FALSE);
|
||||
return TRUE;
|
||||
|
@ -1031,51 +1425,43 @@ end:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
||||
GstBuffer * buffer)
|
||||
d3d_copy_buffer (GstD3DVideoSink * sink, GstBuffer * from, GstBuffer * to)
|
||||
{
|
||||
D3DLOCKED_RECT lr;
|
||||
guint8 *dest;
|
||||
int deststride;
|
||||
gboolean ret = FALSE;
|
||||
gint unhdl_line = 0;
|
||||
GstVideoFrame frame;
|
||||
GstVideoFrame from_frame, to_frame;
|
||||
|
||||
memset (&from_frame, 0, sizeof (from_frame));
|
||||
memset (&to_frame, 0, sizeof (to_frame));
|
||||
|
||||
LOCK_SINK (sink);
|
||||
|
||||
if (!sink->d3d.renderable || sink->d3d.device_lost)
|
||||
goto end;
|
||||
|
||||
if (!buffer
|
||||
|| !gst_video_frame_map (&frame, &sink->info, buffer, GST_MAP_READ)) {
|
||||
if (!gst_video_frame_map (&from_frame, &sink->info, from, GST_MAP_READ) ||
|
||||
!gst_video_frame_map (&to_frame, &sink->info, to, GST_MAP_WRITE)) {
|
||||
GST_ERROR_OBJECT (sink, "NULL GstBuffer");
|
||||
goto end;
|
||||
}
|
||||
|
||||
IDirect3DSurface9_LockRect (surface, &lr, NULL, 0);
|
||||
dest = (guint8 *) lr.pBits;
|
||||
|
||||
if (!dest) {
|
||||
GST_ERROR_OBJECT (sink, "No D3D surface dest buffer");
|
||||
goto unlock_surface;
|
||||
}
|
||||
|
||||
deststride = lr.Pitch;
|
||||
|
||||
switch (sink->format) {
|
||||
case GST_VIDEO_FORMAT_YUY2:
|
||||
case GST_VIDEO_FORMAT_UYVY:{
|
||||
const guint8 *src;
|
||||
gint srcstride;
|
||||
guint8 *dst;
|
||||
gint dststride, srcstride;
|
||||
gint i, h, w;
|
||||
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
w = GST_ROUND_UP_4 (GST_VIDEO_FRAME_WIDTH (&frame) * 2);
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&from_frame, 0);
|
||||
dst = GST_VIDEO_FRAME_PLANE_DATA (&to_frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&from_frame, 0);
|
||||
dststride = GST_VIDEO_FRAME_PLANE_STRIDE (&to_frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&from_frame);
|
||||
w = GST_ROUND_UP_4 (GST_VIDEO_FRAME_WIDTH (&from_frame) * 2);
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy (dest, src, w);
|
||||
dest += deststride;
|
||||
memcpy (dst, src, w);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
|
||||
|
@ -1084,36 +1470,21 @@ d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
|||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_YV12:{
|
||||
const guint8 *src;
|
||||
gint srcstride, deststride_;
|
||||
guint8 *dest_;
|
||||
gint i, j, h, h_, w_;
|
||||
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
guint8 *dst;
|
||||
gint srcstride, dststride;
|
||||
gint i, j, h_, w_;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
src = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
|
||||
srcstride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
|
||||
h_ = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
|
||||
w_ = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
deststride_ = deststride;
|
||||
dest_ = dest;
|
||||
break;
|
||||
case 2:
|
||||
deststride_ = deststride / 2;
|
||||
dest_ = dest + h * deststride;
|
||||
break;
|
||||
case 1:
|
||||
deststride_ = deststride / 2;
|
||||
dest_ = dest + h * deststride + h_ * deststride_;
|
||||
break;
|
||||
}
|
||||
src = GST_VIDEO_FRAME_COMP_DATA (&from_frame, i);
|
||||
dst = GST_VIDEO_FRAME_COMP_DATA (&to_frame, i);
|
||||
srcstride = GST_VIDEO_FRAME_COMP_STRIDE (&from_frame, i);
|
||||
dststride = GST_VIDEO_FRAME_COMP_STRIDE (&to_frame, i);
|
||||
h_ = GST_VIDEO_FRAME_COMP_HEIGHT (&from_frame, i);
|
||||
w_ = GST_VIDEO_FRAME_COMP_WIDTH (&from_frame, i);
|
||||
|
||||
for (j = 0; j < h_; j++) {
|
||||
memcpy (dest_, src, w_);
|
||||
dest_ += deststride_;
|
||||
memcpy (dst, src, w_);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
}
|
||||
|
@ -1122,30 +1493,21 @@ d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
|||
}
|
||||
case GST_VIDEO_FORMAT_NV12:{
|
||||
const guint8 *src;
|
||||
gint srcstride;
|
||||
guint8 *dest_;
|
||||
gint i, j, h, h_, w_;
|
||||
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
guint8 *dst;
|
||||
gint srcstride, dststride;
|
||||
gint i, j, h_, w_;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&frame, i);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, i);
|
||||
h_ = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
|
||||
w_ = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
dest_ = dest;
|
||||
break;
|
||||
case 1:
|
||||
dest_ = dest + h * deststride;
|
||||
break;
|
||||
}
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&from_frame, i);
|
||||
dst = GST_VIDEO_FRAME_PLANE_DATA (&to_frame, i);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&from_frame, i);
|
||||
dststride = GST_VIDEO_FRAME_PLANE_STRIDE (&to_frame, i);
|
||||
h_ = GST_VIDEO_FRAME_COMP_HEIGHT (&from_frame, i);
|
||||
w_ = GST_VIDEO_FRAME_COMP_WIDTH (&from_frame, i);
|
||||
|
||||
for (j = 0; j < h_; j++) {
|
||||
memcpy (dest_, src, w_ * 2);
|
||||
dest_ += deststride;
|
||||
memcpy (dst, src, w_ * 2);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
}
|
||||
|
@ -1157,17 +1519,20 @@ d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
|||
case GST_VIDEO_FORMAT_BGRx:
|
||||
case GST_VIDEO_FORMAT_RGBx:{
|
||||
const guint8 *src;
|
||||
gint srcstride;
|
||||
guint8 *dst;
|
||||
gint srcstride, dststride;
|
||||
gint i, h, w;
|
||||
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&frame) * 4;
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&from_frame, 0);
|
||||
dst = GST_VIDEO_FRAME_PLANE_DATA (&to_frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&from_frame, 0);
|
||||
dststride = GST_VIDEO_FRAME_PLANE_STRIDE (&to_frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&from_frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&from_frame) * 4;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy (dest, src, w);
|
||||
dest += deststride;
|
||||
memcpy (dst, src, w);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
|
||||
|
@ -1175,17 +1540,20 @@ d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
|||
}
|
||||
case GST_VIDEO_FORMAT_BGR:{
|
||||
const guint8 *src;
|
||||
gint srcstride;
|
||||
guint8 *dst;
|
||||
gint srcstride, dststride;
|
||||
gint i, h, w;
|
||||
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&frame) * 3;
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&from_frame, 0);
|
||||
dst = GST_VIDEO_FRAME_PLANE_DATA (&to_frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&from_frame, 0);
|
||||
dststride = GST_VIDEO_FRAME_PLANE_STRIDE (&to_frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&from_frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&from_frame) * 3;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy (dest, src, w);
|
||||
dest += deststride;
|
||||
memcpy (dst, src, w);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
|
||||
|
@ -1194,45 +1562,47 @@ d3d_copy_buffer_to_surface (GstD3DVideoSink * sink, LPDIRECT3DSURFACE9 surface,
|
|||
case GST_VIDEO_FORMAT_RGB16:
|
||||
case GST_VIDEO_FORMAT_RGB15:{
|
||||
const guint8 *src;
|
||||
gint srcstride;
|
||||
guint8 *dst;
|
||||
gint srcstride, dststride;
|
||||
gint i, h, w;
|
||||
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&frame) * 2;
|
||||
src = GST_VIDEO_FRAME_PLANE_DATA (&from_frame, 0);
|
||||
dst = GST_VIDEO_FRAME_PLANE_DATA (&to_frame, 0);
|
||||
srcstride = GST_VIDEO_FRAME_PLANE_STRIDE (&from_frame, 0);
|
||||
dststride = GST_VIDEO_FRAME_PLANE_STRIDE (&to_frame, 0);
|
||||
h = GST_VIDEO_FRAME_HEIGHT (&from_frame);
|
||||
w = GST_VIDEO_FRAME_WIDTH (&from_frame) * 2;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy (dest, src, w);
|
||||
dest += deststride;
|
||||
memcpy (dst, src, w);
|
||||
dst += dststride;
|
||||
src += srcstride;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unhdl_line = __LINE__;
|
||||
goto unhandled_format;
|
||||
}
|
||||
|
||||
goto done;
|
||||
ret = TRUE;
|
||||
|
||||
end:
|
||||
if (from_frame.buffer)
|
||||
gst_video_frame_unmap (&from_frame);
|
||||
if (to_frame.buffer)
|
||||
gst_video_frame_unmap (&to_frame);
|
||||
|
||||
UNLOCK_SINK (sink);
|
||||
return ret;
|
||||
|
||||
unhandled_format:
|
||||
GST_ERROR_OBJECT (sink,
|
||||
"Unhandled format [LN:%d] '%s' -> '%s' (should not get here)", unhdl_line,
|
||||
"Unhandled format '%s' -> '%s' (should not get here)",
|
||||
gst_video_format_to_string (sink->format),
|
||||
d3d_format_to_string (sink->d3d.format));
|
||||
goto unlock_surface;
|
||||
|
||||
done:
|
||||
ret = TRUE;
|
||||
unlock_surface:
|
||||
IDirect3DSurface9_UnlockRect (surface);
|
||||
gst_video_frame_unmap (&frame);
|
||||
|
||||
end:
|
||||
UNLOCK_SINK (sink);
|
||||
return ret;
|
||||
ret = FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1397,12 +1767,9 @@ GstFlowReturn
|
|||
d3d_render_buffer (GstD3DVideoSink * sink, GstBuffer * buf)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstMapInfo map;
|
||||
GstMemory *mem;
|
||||
LPDIRECT3DSURFACE9 surface = NULL;
|
||||
|
||||
g_return_val_if_fail (gst_buffer_map (buf, &map, GST_MAP_READ) != FALSE,
|
||||
GST_FLOW_ERROR);
|
||||
|
||||
LOCK_SINK (sink);
|
||||
|
||||
if (!sink->d3d.window_handle) {
|
||||
|
@ -1428,26 +1795,59 @@ d3d_render_buffer (GstD3DVideoSink * sink, GstBuffer * buf)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (!surface) {
|
||||
HRESULT hr;
|
||||
GstD3DVideoSinkClass *klass = GST_D3DVIDEOSINK_GET_CLASS (sink);
|
||||
if (gst_buffer_n_memory (buf) != 1 ||
|
||||
(mem = gst_buffer_peek_memory (buf, 0)) == 0 ||
|
||||
!gst_memory_is_type (mem, GST_D3D_SURFACE_MEMORY_NAME)) {
|
||||
GstBuffer *tmp;
|
||||
GstBufferPoolAcquireParams params = { 0, };
|
||||
|
||||
hr = IDirect3DDevice9_CreateOffscreenPlainSurface (klass->d3d.
|
||||
device.d3d_device, GST_VIDEO_SINK_WIDTH (sink),
|
||||
GST_VIDEO_SINK_HEIGHT (sink), sink->d3d.format, D3DPOOL_DEFAULT,
|
||||
&surface, NULL);
|
||||
if (hr != D3D_OK || surface == NULL) {
|
||||
GST_ERROR_OBJECT (sink, "Failed to create D3D surface");
|
||||
ret = GST_FLOW_ERROR;
|
||||
if (!sink->fallback_pool
|
||||
|| !gst_buffer_pool_set_active (sink->fallback_pool, TRUE)) {
|
||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||
goto end;
|
||||
}
|
||||
d3d_copy_buffer_to_surface (sink, surface, buf);
|
||||
if (sink->d3d.surface)
|
||||
IDirect3DSurface9_Release (sink->d3d.surface);
|
||||
IDirect3DSurface9_AddRef (surface);
|
||||
sink->d3d.surface = surface;
|
||||
|
||||
/* take a buffer from our pool, if there is no buffer in the pool something
|
||||
* is seriously wrong, waiting for the pool here might deadlock when we try
|
||||
* to go to PAUSED because we never flush the pool. */
|
||||
params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
|
||||
ret = gst_buffer_pool_acquire_buffer (sink->fallback_pool, &tmp, ¶ms);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto end;
|
||||
|
||||
if (sink->fallback_buffer) {
|
||||
gst_buffer_unref (sink->fallback_buffer);
|
||||
sink->fallback_buffer = NULL;
|
||||
}
|
||||
|
||||
mem = gst_buffer_peek_memory (tmp, 0);
|
||||
if (!mem || !gst_memory_is_type (mem, GST_D3D_SURFACE_MEMORY_NAME)) {
|
||||
ret = GST_FLOW_ERROR;
|
||||
gst_buffer_unref (tmp);
|
||||
goto end;
|
||||
}
|
||||
d3d_copy_buffer (sink, buf, tmp);
|
||||
buf = tmp;
|
||||
|
||||
surface = ((GstD3DSurfaceMemory *) mem)->surface;
|
||||
|
||||
/* Need to keep an additional ref until the next buffer
|
||||
* to make sure it isn't reused until then */
|
||||
sink->fallback_buffer = buf;
|
||||
} else {
|
||||
mem = gst_buffer_peek_memory (buf, 0);
|
||||
surface = ((GstD3DSurfaceMemory *) mem)->surface;
|
||||
|
||||
if (sink->fallback_buffer) {
|
||||
gst_buffer_unref (sink->fallback_buffer);
|
||||
sink->fallback_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sink->d3d.surface)
|
||||
IDirect3DSurface9_Release (sink->d3d.surface);
|
||||
IDirect3DSurface9_AddRef (surface);
|
||||
sink->d3d.surface = surface;
|
||||
|
||||
if (!d3d_present_swap_chain (sink)) {
|
||||
ret = GST_FLOW_ERROR;
|
||||
|
|
|
@ -92,7 +92,6 @@ typedef struct _GstD3DData {
|
|||
gboolean device_lost;
|
||||
} GstD3DData;
|
||||
|
||||
|
||||
gboolean d3d_class_init(GstD3DVideoSink * klass);
|
||||
void d3d_class_destroy(GstD3DVideoSink * klass);
|
||||
|
||||
|
@ -105,4 +104,33 @@ GstFlowReturn d3d_render_buffer(GstD3DVideoSink * sink, GstBuffer * buf);
|
|||
GstCaps * d3d_supported_caps(GstD3DVideoSink * sink);
|
||||
gboolean d3d_set_render_format(GstD3DVideoSink * sink);
|
||||
|
||||
#define GST_TYPE_D3DSURFACE_BUFFER_POOL (gst_d3dsurface_buffer_pool_get_type())
|
||||
#define GST_IS_D3DSURFACE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_D3DSURFACE_BUFFER_POOL))
|
||||
#define GST_D3DSURFACE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_D3DSURFACE_BUFFER_POOL, GstD3DSurfaceBufferPool))
|
||||
#define GST_D3DSURFACE_BUFFER_POOL_CAST(obj) ((GstD3DSurfaceBufferPool*)(obj))
|
||||
|
||||
typedef struct _GstD3DSurfaceBufferPool {
|
||||
GstVideoBufferPool parent;
|
||||
|
||||
GstD3DVideoSink *sink;
|
||||
GstVideoInfo info;
|
||||
gboolean add_metavideo;
|
||||
|
||||
GstAllocator *allocator;
|
||||
} GstD3DSurfaceBufferPool;
|
||||
|
||||
typedef struct _GstD3DSurfaceBufferPoolClass {
|
||||
GstVideoBufferPoolClass parent_class;
|
||||
} GstD3DSurfaceBufferPoolClass;
|
||||
|
||||
GType gst_d3dsurface_meta_api_get_type (void);
|
||||
#define GST_D3DSURFACE_META_API_TYPE (gst_d3dsurface_meta_api_get_type())
|
||||
const GstMetaInfo * gst_d3dsurface_meta_get_info (void);
|
||||
#define GST_D3DSURFACE_META_INFO (gst_d3dsurface_meta_get_info())
|
||||
|
||||
#define gst_buffer_get_d3dsurface_meta(b) ((GstD3DSurfaceMeta*)gst_buffer_get_meta((b),GST_D3DSURFACE_META_API_TYPE))
|
||||
|
||||
GType gst_d3dsurface_buffer_pool_get_type (void);
|
||||
GstBufferPool * gst_d3dsurface_buffer_pool_new (GstD3DVideoSink * sink);
|
||||
|
||||
#endif /* _D3DHELPERS_H_ */
|
||||
|
|
|
@ -185,6 +185,9 @@ gst_d3dvideosink_finalize (GObject * gobject)
|
|||
|
||||
GST_DEBUG_OBJECT (sink, " ");
|
||||
|
||||
gst_object_replace ((GstObject **) & sink->pool, NULL);
|
||||
gst_object_replace ((GstObject **) & sink->fallback_pool, NULL);
|
||||
|
||||
gst_caps_replace (&sink->supported_caps, NULL);
|
||||
|
||||
g_rec_mutex_clear (&sink->lock);
|
||||
|
@ -274,6 +277,9 @@ gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
gint display_par_n = 1, display_par_d = 1; /* display's PAR */
|
||||
guint num, den;
|
||||
gchar *tmp = NULL;
|
||||
GstBufferPool *newpool, *oldpool;
|
||||
GstBufferPool *newfbpool, *oldfbpool;
|
||||
GstStructure *config;
|
||||
|
||||
GST_DEBUG_OBJECT (bsink, " ");
|
||||
|
||||
|
@ -356,6 +362,40 @@ gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
/* Create a window (or start using an application-supplied one, then connect the graph */
|
||||
d3d_prepare_window (sink);
|
||||
|
||||
newpool = gst_d3dsurface_buffer_pool_new (sink);
|
||||
config = gst_buffer_pool_get_config (newpool);
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
|
||||
if (!gst_buffer_pool_set_config (newpool, config)) {
|
||||
gst_object_unref (newpool);
|
||||
GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
newfbpool = gst_d3dsurface_buffer_pool_new (sink);
|
||||
config = gst_buffer_pool_get_config (newfbpool);
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
|
||||
/* Fallback pool must use videometa */
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
if (!gst_buffer_pool_set_config (newfbpool, config)) {
|
||||
gst_object_unref (newfbpool);
|
||||
GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (sink);
|
||||
oldpool = sink->pool;
|
||||
sink->pool = newpool;
|
||||
oldfbpool = sink->fallback_pool;
|
||||
sink->fallback_pool = newfbpool;
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
|
||||
if (oldpool)
|
||||
gst_object_unref (oldpool);
|
||||
if (oldfbpool)
|
||||
gst_object_unref (oldfbpool);
|
||||
|
||||
return TRUE;
|
||||
/* ERRORS */
|
||||
incompatible_caps:
|
||||
|
@ -411,8 +451,73 @@ gst_d3dvideosink_stop (GstBaseSink * bsink)
|
|||
static gboolean
|
||||
gst_d3dvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||
{
|
||||
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
|
||||
GstBufferPool *pool;
|
||||
GstStructure *config;
|
||||
GstCaps *caps;
|
||||
guint size;
|
||||
gboolean need_pool;
|
||||
|
||||
gst_query_parse_allocation (query, &caps, &need_pool);
|
||||
if (!caps) {
|
||||
GST_DEBUG_OBJECT (sink, "no caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
|
||||
|
||||
GST_OBJECT_LOCK (sink);
|
||||
pool = sink->pool ? gst_object_ref (sink->pool) : NULL;
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
|
||||
if (pool) {
|
||||
GstCaps *pcaps;
|
||||
|
||||
/* we had a pool, check caps */
|
||||
GST_DEBUG_OBJECT (sink, "check existing pool caps");
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL);
|
||||
|
||||
if (!gst_caps_is_equal (caps, pcaps)) {
|
||||
GST_DEBUG_OBJECT (sink, "pool has different caps");
|
||||
/* different caps, we can't use this pool */
|
||||
gst_object_unref (pool);
|
||||
pool = NULL;
|
||||
}
|
||||
gst_structure_free (config);
|
||||
}
|
||||
|
||||
if (pool == NULL && need_pool) {
|
||||
GstVideoInfo info;
|
||||
|
||||
if (!gst_video_info_from_caps (&info, caps)) {
|
||||
GST_ERROR_OBJECT (sink, "allocation query has invalid caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "create new pool");
|
||||
pool = gst_d3dsurface_buffer_pool_new (sink);
|
||||
|
||||
/* the normal size of a frame */
|
||||
size = info.size;
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
|
||||
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||
gst_object_unref (pool);
|
||||
GST_ERROR_OBJECT (sink, "failed to set pool configuration");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (pool) {
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_query_add_allocation_pool (query, pool, size, 2, 0);
|
||||
gst_object_unref (pool);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ struct _GstD3DVideoSink
|
|||
GstVideoInfo info;
|
||||
gint width;
|
||||
gint height;
|
||||
GstBufferPool *pool;
|
||||
GstBufferPool *fallback_pool;
|
||||
GstBuffer *fallback_buffer;
|
||||
|
||||
GstVideoRectangle render_rect;
|
||||
|
||||
|
|
Loading…
Reference in a new issue