mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
xvimagesink: Implement XvImage memory as a GstMemory, not as a GstMeta
This commit is contained in:
parent
354d7ba302
commit
45ac6dea64
3 changed files with 239 additions and 175 deletions
|
@ -49,39 +49,6 @@ struct _GstXvImageBufferPoolPrivate
|
|||
gboolean need_alignment;
|
||||
};
|
||||
|
||||
static void gst_xvimage_meta_free (GstXvImageMeta * meta, GstBuffer * buffer);
|
||||
|
||||
/* xvimage metadata */
|
||||
GType
|
||||
gst_xvimage_meta_api_get_type (void)
|
||||
{
|
||||
static volatile GType type;
|
||||
static const gchar *tags[] =
|
||||
{ "memory", "size", "colorspace", "orientation", NULL };
|
||||
|
||||
if (g_once_init_enter (&type)) {
|
||||
GType _type = gst_meta_api_type_register ("GstXvImageMetaAPI", tags);
|
||||
g_once_init_leave (&type, _type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const GstMetaInfo *
|
||||
gst_xvimage_meta_get_info (void)
|
||||
{
|
||||
static const GstMetaInfo *xvimage_meta_info = NULL;
|
||||
|
||||
if (g_once_init_enter (&xvimage_meta_info)) {
|
||||
const GstMetaInfo *meta =
|
||||
gst_meta_register (GST_XVIMAGE_META_API_TYPE, "GstXvImageMeta",
|
||||
sizeof (GstXvImageMeta), (GstMetaInitFunction) NULL,
|
||||
(GstMetaFreeFunction) gst_xvimage_meta_free,
|
||||
(GstMetaTransformFunction) NULL);
|
||||
g_once_init_leave (&xvimage_meta_info, meta);
|
||||
}
|
||||
return xvimage_meta_info;
|
||||
}
|
||||
|
||||
/* X11 stuff */
|
||||
static gboolean error_caught = FALSE;
|
||||
|
||||
|
@ -96,16 +63,174 @@ gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static GstXvImageMeta *
|
||||
gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
||||
static GstMemory *
|
||||
gst_xvimage_memory_alloc (GstAllocator * allocator, gsize size,
|
||||
GstAllocationParams * params)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimage_memory_free (GstAllocator * allocator, GstMemory * gmem)
|
||||
{
|
||||
GstXvImageMemory *mem = (GstXvImageMemory *) gmem;
|
||||
GstXvImageSink *xvimagesink;
|
||||
|
||||
if (gmem->parent)
|
||||
goto sub_mem;
|
||||
|
||||
xvimagesink = mem->sink;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "free memory %p", mem);
|
||||
|
||||
/* Hold the object lock to ensure the XContext doesn't disappear */
|
||||
GST_OBJECT_LOCK (xvimagesink);
|
||||
/* We might have some buffers destroyed after changing state to NULL */
|
||||
if (xvimagesink->xcontext == NULL) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
|
||||
#ifdef HAVE_XSHM
|
||||
/* Need to free the shared memory segment even if the x context
|
||||
* was already cleaned up */
|
||||
if (mem->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (mem->SHMInfo.shmaddr);
|
||||
}
|
||||
#endif
|
||||
if (mem->xvimage)
|
||||
XFree (mem->xvimage);
|
||||
goto beach;
|
||||
}
|
||||
|
||||
g_mutex_lock (&xvimagesink->x_lock);
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
if (mem->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
|
||||
mem->SHMInfo.shmid, mem->SHMInfo.shmseg);
|
||||
XShmDetach (xvimagesink->xcontext->disp, &mem->SHMInfo);
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
shmdt (mem->SHMInfo.shmaddr);
|
||||
mem->SHMInfo.shmaddr = (void *) -1;
|
||||
}
|
||||
if (mem->xvimage)
|
||||
XFree (mem->xvimage);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
if (mem->xvimage) {
|
||||
g_free (mem->xvimage->data);
|
||||
XFree (mem->xvimage);
|
||||
}
|
||||
}
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
g_mutex_unlock (&xvimagesink->x_lock);
|
||||
|
||||
beach:
|
||||
GST_OBJECT_UNLOCK (xvimagesink);
|
||||
|
||||
gst_object_unref (mem->sink);
|
||||
|
||||
sub_mem:
|
||||
g_slice_free (GstXvImageMemory, mem);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
xvimage_memory_map (GstXvImageMemory * mem, gsize maxsize, GstMapFlags flags)
|
||||
{
|
||||
return mem->xvimage->data + mem->parent.offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xvimage_memory_unmap (GstXvImageMemory * mem)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstXvImageMemory *
|
||||
xvimage_memory_share (GstXvImageMemory * mem, gssize offset, gsize size)
|
||||
{
|
||||
GstXvImageMemory *sub;
|
||||
GstMemory *parent;
|
||||
|
||||
/* We can only share the complete memory */
|
||||
if (offset != 0)
|
||||
return NULL;
|
||||
if (size != -1 && size != mem->size)
|
||||
return NULL;
|
||||
|
||||
/* find the real parent */
|
||||
if ((parent = mem->parent.parent) == NULL)
|
||||
parent = (GstMemory *) mem;
|
||||
|
||||
if (size == -1)
|
||||
size = mem->parent.size - offset;
|
||||
|
||||
/* the shared memory is always readonly */
|
||||
sub = g_slice_new (GstXvImageMemory);
|
||||
|
||||
gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) |
|
||||
GST_MINI_OBJECT_FLAG_LOCK_READONLY, g_object_ref (mem->parent.allocator),
|
||||
&mem->parent, mem->parent.maxsize, mem->parent.align,
|
||||
mem->parent.offset + offset, size);
|
||||
sub->sink = mem->sink;
|
||||
sub->xvimage = mem->xvimage;
|
||||
sub->SHMInfo = mem->SHMInfo;
|
||||
sub->x = mem->x;
|
||||
sub->y = mem->y;
|
||||
sub->width = mem->width;
|
||||
sub->height = mem->height;
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
typedef GstAllocator GstXvImageMemoryAllocator;
|
||||
typedef GstAllocatorClass GstXvImageMemoryAllocatorClass;
|
||||
|
||||
GType xvimage_memory_allocator_get_type (void);
|
||||
G_DEFINE_TYPE (GstXvImageMemoryAllocator, xvimage_memory_allocator,
|
||||
GST_TYPE_ALLOCATOR);
|
||||
|
||||
#define GST_XVIMAGE_ALLOCATOR_NAME "xvimage"
|
||||
#define GST_TYPE_XVIMAGE_MEMORY_ALLOCATOR (xvimage_memory_allocator_get_type())
|
||||
#define GST_IS_XVIMAGE_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_MEMORY_ALLOCATOR))
|
||||
|
||||
static void
|
||||
xvimage_memory_allocator_class_init (GstXvImageMemoryAllocatorClass * klass)
|
||||
{
|
||||
GstAllocatorClass *allocator_class;
|
||||
|
||||
allocator_class = (GstAllocatorClass *) klass;
|
||||
|
||||
allocator_class->alloc = gst_xvimage_memory_alloc;
|
||||
allocator_class->free = gst_xvimage_memory_free;
|
||||
}
|
||||
|
||||
static void
|
||||
xvimage_memory_allocator_init (GstXvImageMemoryAllocator * allocator)
|
||||
{
|
||||
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
|
||||
|
||||
alloc->mem_type = GST_XVIMAGE_ALLOCATOR_NAME;
|
||||
alloc->mem_map = (GstMemoryMapFunction) xvimage_memory_map;
|
||||
alloc->mem_unmap = (GstMemoryUnmapFunction) xvimage_memory_unmap;
|
||||
alloc->mem_share = (GstMemoryShareFunction) xvimage_memory_share;
|
||||
/* fallback copy and is_span */
|
||||
|
||||
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
xvimage_memory_alloc (GstXvImageBufferPool * xvpool)
|
||||
{
|
||||
GstXvImageSink *xvimagesink;
|
||||
int (*handler) (Display *, XErrorEvent *);
|
||||
gboolean success = FALSE;
|
||||
GstXContext *xcontext;
|
||||
GstXvImageMeta *meta;
|
||||
gint width, height, im_format, align = 15, offset;
|
||||
GstXvImageBufferPoolPrivate *priv;
|
||||
GstXvImageMemory *mem;
|
||||
|
||||
priv = xvpool->priv;
|
||||
xvimagesink = xvpool->sink;
|
||||
|
@ -115,21 +240,20 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
height = priv->padded_height;
|
||||
im_format = priv->im_format;
|
||||
|
||||
meta =
|
||||
(GstXvImageMeta *) gst_buffer_add_meta (buffer, GST_XVIMAGE_META_INFO,
|
||||
NULL);
|
||||
#ifdef HAVE_XSHM
|
||||
meta->SHMInfo.shmaddr = ((void *) -1);
|
||||
meta->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
meta->x = priv->align.padding_left;
|
||||
meta->y = priv->align.padding_top;
|
||||
meta->width = priv->info.width;
|
||||
meta->height = priv->info.height;
|
||||
meta->sink = gst_object_ref (xvimagesink);
|
||||
meta->im_format = im_format;
|
||||
mem = g_slice_new (GstXvImageMemory);
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "creating image %p (%dx%d)", buffer,
|
||||
#ifdef HAVE_XSHM
|
||||
mem->SHMInfo.shmaddr = ((void *) -1);
|
||||
mem->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
mem->x = priv->align.padding_left;
|
||||
mem->y = priv->align.padding_top;
|
||||
mem->width = priv->info.width;
|
||||
mem->height = priv->info.height;
|
||||
mem->sink = gst_object_ref (xvimagesink);
|
||||
mem->im_format = im_format;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "creating image %p (%dx%d)", mem,
|
||||
width, height);
|
||||
|
||||
g_mutex_lock (&xvimagesink->x_lock);
|
||||
|
@ -142,9 +266,9 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
if (xcontext->use_xshm) {
|
||||
int expected_size;
|
||||
|
||||
meta->xvimage = XvShmCreateImage (xcontext->disp,
|
||||
xcontext->xv_port_id, im_format, NULL, width, height, &meta->SHMInfo);
|
||||
if (!meta->xvimage || error_caught) {
|
||||
mem->xvimage = XvShmCreateImage (xcontext->disp,
|
||||
xcontext->xv_port_id, im_format, NULL, width, height, &mem->SHMInfo);
|
||||
if (!mem->xvimage || error_caught) {
|
||||
g_mutex_unlock (&xvimagesink->x_lock);
|
||||
|
||||
/* Reset error flag */
|
||||
|
@ -165,9 +289,9 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
}
|
||||
|
||||
/* we have to use the returned data_size for our shm size */
|
||||
meta->size = meta->xvimage->data_size;
|
||||
mem->size = mem->xvimage->data_size;
|
||||
GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
|
||||
meta->size);
|
||||
mem->size);
|
||||
|
||||
/* calculate the expected size. This is only for sanity checking the
|
||||
* number we get from X. */
|
||||
|
@ -188,7 +312,7 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
|
||||
expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (height) / 2;
|
||||
|
||||
for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
|
||||
for (plane = 0; plane < mem->xvimage->num_planes; plane++) {
|
||||
GST_DEBUG_OBJECT (xvimagesink,
|
||||
"Plane %u has a expected pitch of %d bytes, " "offset of %d",
|
||||
plane, pitches[plane], offsets[plane]);
|
||||
|
@ -203,39 +327,39 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
expected_size = 0;
|
||||
break;
|
||||
}
|
||||
if (expected_size != 0 && meta->size != expected_size) {
|
||||
if (expected_size != 0 && mem->size != expected_size) {
|
||||
GST_WARNING_OBJECT (xvimagesink,
|
||||
"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
|
||||
meta->size, expected_size);
|
||||
mem->size, expected_size);
|
||||
}
|
||||
|
||||
/* Be verbose about our XvImage stride */
|
||||
{
|
||||
guint plane;
|
||||
|
||||
for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
|
||||
for (plane = 0; plane < mem->xvimage->num_planes; plane++) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
|
||||
"offset of %d", plane, meta->xvimage->pitches[plane],
|
||||
meta->xvimage->offsets[plane]);
|
||||
"offset of %d", plane, mem->xvimage->pitches[plane],
|
||||
mem->xvimage->offsets[plane]);
|
||||
}
|
||||
}
|
||||
|
||||
/* get shared memory */
|
||||
meta->SHMInfo.shmid =
|
||||
shmget (IPC_PRIVATE, meta->size + align, IPC_CREAT | 0777);
|
||||
if (meta->SHMInfo.shmid == -1)
|
||||
mem->SHMInfo.shmid =
|
||||
shmget (IPC_PRIVATE, mem->size + align, IPC_CREAT | 0777);
|
||||
if (mem->SHMInfo.shmid == -1)
|
||||
goto shmget_failed;
|
||||
|
||||
/* attach */
|
||||
meta->SHMInfo.shmaddr = shmat (meta->SHMInfo.shmid, NULL, 0);
|
||||
if (meta->SHMInfo.shmaddr == ((void *) -1))
|
||||
mem->SHMInfo.shmaddr = shmat (mem->SHMInfo.shmid, NULL, 0);
|
||||
if (mem->SHMInfo.shmaddr == ((void *) -1))
|
||||
goto shmat_failed;
|
||||
|
||||
/* now we can set up the image data */
|
||||
meta->xvimage->data = meta->SHMInfo.shmaddr;
|
||||
meta->SHMInfo.readOnly = FALSE;
|
||||
mem->xvimage->data = mem->SHMInfo.shmaddr;
|
||||
mem->SHMInfo.readOnly = FALSE;
|
||||
|
||||
if (XShmAttach (xcontext->disp, &meta->SHMInfo) == 0)
|
||||
if (XShmAttach (xcontext->disp, &mem->SHMInfo) == 0)
|
||||
goto xattach_failed;
|
||||
|
||||
XSync (xcontext->disp, FALSE);
|
||||
|
@ -243,49 +367,50 @@ gst_buffer_add_xvimage_meta (GstBuffer * buffer, GstXvImageBufferPool * xvpool)
|
|||
/* Delete the shared memory segment as soon as we everyone is attached.
|
||||
* This way, it will be deleted as soon as we detach later, and not
|
||||
* leaked if we crash. */
|
||||
shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (mem->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
|
||||
meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
|
||||
mem->SHMInfo.shmid, mem->SHMInfo.shmseg);
|
||||
} else
|
||||
no_xshm:
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
meta->xvimage = XvCreateImage (xcontext->disp,
|
||||
mem->xvimage = XvCreateImage (xcontext->disp,
|
||||
xcontext->xv_port_id, im_format, NULL, width, height);
|
||||
if (!meta->xvimage || error_caught)
|
||||
if (!mem->xvimage || error_caught)
|
||||
goto create_failed;
|
||||
|
||||
/* we have to use the returned data_size for our image size */
|
||||
meta->size = meta->xvimage->data_size;
|
||||
meta->xvimage->data = g_malloc (meta->size + align);
|
||||
mem->size = mem->xvimage->data_size;
|
||||
mem->xvimage->data = g_malloc (mem->size + align);
|
||||
|
||||
XSync (xcontext->disp, FALSE);
|
||||
}
|
||||
|
||||
if ((offset = ((guintptr) meta->xvimage->data & align)))
|
||||
if ((offset = ((guintptr) mem->xvimage->data & align)))
|
||||
offset = (align + 1) - offset;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "memory %p, align %d, offset %d",
|
||||
meta->xvimage->data, align, offset);
|
||||
mem->xvimage->data, align, offset);
|
||||
|
||||
/* Reset error handler */
|
||||
error_caught = FALSE;
|
||||
XSetErrorHandler (handler);
|
||||
|
||||
gst_buffer_append_memory (buffer,
|
||||
gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, meta->xvimage->data,
|
||||
meta->size + align, offset, meta->size, NULL, NULL));
|
||||
gst_memory_init (GST_MEMORY_CAST (mem), 0, g_object_ref (xvpool->allocator),
|
||||
NULL, mem->size + align, align, offset, mem->size);
|
||||
|
||||
g_mutex_unlock (&xvimagesink->x_lock);
|
||||
|
||||
success = TRUE;
|
||||
|
||||
beach:
|
||||
if (!success)
|
||||
meta = NULL;
|
||||
if (!success) {
|
||||
g_slice_free (GstXvImageMemory, mem);
|
||||
mem = NULL;
|
||||
}
|
||||
|
||||
return meta;
|
||||
return GST_MEMORY_CAST (mem);
|
||||
|
||||
/* ERRORS */
|
||||
create_failed:
|
||||
|
@ -309,7 +434,7 @@ shmget_failed:
|
|||
("Failed to create output image buffer of %dx%d pixels",
|
||||
width, height),
|
||||
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
||||
meta->size));
|
||||
mem->size));
|
||||
goto beach;
|
||||
}
|
||||
shmat_failed:
|
||||
|
@ -319,13 +444,13 @@ shmat_failed:
|
|||
("Failed to create output image buffer of %dx%d pixels",
|
||||
width, height), ("Failed to shmat: %s", g_strerror (errno)));
|
||||
/* Clean up the shared memory segment */
|
||||
shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (mem->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
goto beach;
|
||||
}
|
||||
xattach_failed:
|
||||
{
|
||||
/* Clean up the shared memory segment */
|
||||
shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (mem->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
g_mutex_unlock (&xvimagesink->x_lock);
|
||||
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
|
@ -336,65 +461,6 @@ xattach_failed:
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimage_meta_free (GstXvImageMeta * meta, GstBuffer * buffer)
|
||||
{
|
||||
GstXvImageSink *xvimagesink;
|
||||
|
||||
xvimagesink = meta->sink;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "free meta on buffer %p", buffer);
|
||||
|
||||
/* Hold the object lock to ensure the XContext doesn't disappear */
|
||||
GST_OBJECT_LOCK (xvimagesink);
|
||||
/* We might have some buffers destroyed after changing state to NULL */
|
||||
if (xvimagesink->xcontext == NULL) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
|
||||
#ifdef HAVE_XSHM
|
||||
/* Need to free the shared memory segment even if the x context
|
||||
* was already cleaned up */
|
||||
if (meta->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (meta->SHMInfo.shmaddr);
|
||||
}
|
||||
#endif
|
||||
if (meta->xvimage)
|
||||
XFree (meta->xvimage);
|
||||
goto beach;
|
||||
}
|
||||
|
||||
g_mutex_lock (&xvimagesink->x_lock);
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
if (meta->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
|
||||
meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
|
||||
XShmDetach (xvimagesink->xcontext->disp, &meta->SHMInfo);
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
shmdt (meta->SHMInfo.shmaddr);
|
||||
meta->SHMInfo.shmaddr = (void *) -1;
|
||||
}
|
||||
if (meta->xvimage)
|
||||
XFree (meta->xvimage);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
if (meta->xvimage) {
|
||||
g_free (meta->xvimage->data);
|
||||
XFree (meta->xvimage);
|
||||
}
|
||||
}
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
g_mutex_unlock (&xvimagesink->x_lock);
|
||||
|
||||
beach:
|
||||
GST_OBJECT_UNLOCK (xvimagesink);
|
||||
|
||||
gst_object_unref (meta->sink);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
/* This function checks that it is actually really possible to create an image
|
||||
using XShm */
|
||||
|
@ -625,16 +691,17 @@ xvimage_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
|
|||
GstXvImageBufferPoolPrivate *priv = xvpool->priv;
|
||||
GstVideoInfo *info;
|
||||
GstBuffer *xvimage;
|
||||
GstXvImageMeta *meta;
|
||||
GstMemory *mem;
|
||||
|
||||
info = &priv->info;
|
||||
|
||||
xvimage = gst_buffer_new ();
|
||||
meta = gst_buffer_add_xvimage_meta (xvimage, xvpool);
|
||||
if (meta == NULL) {
|
||||
mem = xvimage_memory_alloc (xvpool);
|
||||
if (mem == NULL) {
|
||||
gst_buffer_unref (xvimage);
|
||||
goto no_buffer;
|
||||
}
|
||||
gst_buffer_append_memory (xvimage, mem);
|
||||
|
||||
if (priv->add_metavideo) {
|
||||
GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
|
||||
|
@ -665,6 +732,7 @@ gst_xvimage_buffer_pool_new (GstXvImageSink * xvimagesink)
|
|||
|
||||
pool = g_object_new (GST_TYPE_XVIMAGE_BUFFER_POOL, NULL);
|
||||
pool->sink = gst_object_ref (xvimagesink);
|
||||
pool->allocator = g_object_new (GST_TYPE_XVIMAGE_MEMORY_ALLOCATOR, NULL);
|
||||
|
||||
GST_LOG_OBJECT (pool, "new XvImage buffer pool %p", pool);
|
||||
|
||||
|
@ -703,6 +771,7 @@ gst_xvimage_buffer_pool_finalize (GObject * object)
|
|||
if (priv->caps)
|
||||
gst_caps_unref (priv->caps);
|
||||
gst_object_unref (pool->sink);
|
||||
g_object_unref (pool->allocator);
|
||||
|
||||
G_OBJECT_CLASS (gst_xvimage_buffer_pool_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstXvImageMeta GstXvImageMeta;
|
||||
typedef struct _GstXvImageMemory GstXvImageMemory;
|
||||
|
||||
typedef struct _GstXvImageBufferPool GstXvImageBufferPool;
|
||||
typedef struct _GstXvImageBufferPoolClass GstXvImageBufferPoolClass;
|
||||
|
@ -47,15 +47,8 @@ typedef struct _GstXvImageBufferPoolPrivate GstXvImageBufferPoolPrivate;
|
|||
|
||||
#include "xvimagesink.h"
|
||||
|
||||
GType gst_xvimage_meta_api_get_type (void);
|
||||
#define GST_XVIMAGE_META_API_TYPE (gst_xvimage_meta_api_get_type())
|
||||
const GstMetaInfo * gst_xvimage_meta_get_info (void);
|
||||
#define GST_XVIMAGE_META_INFO (gst_xvimage_meta_get_info())
|
||||
|
||||
#define gst_buffer_get_xvimage_meta(b) ((GstXvImageMeta*)gst_buffer_get_meta((b),GST_XVIMAGE_META_API_TYPE))
|
||||
|
||||
/**
|
||||
* GstXvImageMeta:
|
||||
* GstXvImageMemory:
|
||||
* @sink: a reference to the our #GstXvImageSink
|
||||
* @xvimage: the XvImage of this buffer
|
||||
* @width: the width in pixels of XvImage @xvimage
|
||||
|
@ -63,11 +56,11 @@ const GstMetaInfo * gst_xvimage_meta_get_info (void);
|
|||
* @im_format: the format of XvImage @xvimage
|
||||
* @size: the size in bytes of XvImage @xvimage
|
||||
*
|
||||
* Subclass of #GstMeta containing additional information about an XvImage.
|
||||
* Subclass of #GstMemory containing additional information about an XvImage.
|
||||
*/
|
||||
struct _GstXvImageMeta
|
||||
struct _GstXvImageMemory
|
||||
{
|
||||
GstMeta meta;
|
||||
GstMemory parent;
|
||||
|
||||
/* Reference to the xvimagesink we belong to */
|
||||
GstXvImageSink *sink;
|
||||
|
@ -95,6 +88,7 @@ struct _GstXvImageBufferPool
|
|||
GstBufferPool bufferpool;
|
||||
|
||||
GstXvImageSink *sink;
|
||||
GstAllocator *allocator;
|
||||
|
||||
GstXvImageBufferPoolPrivate *priv;
|
||||
};
|
||||
|
|
|
@ -267,7 +267,7 @@ gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
|
|||
static gboolean
|
||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
||||
{
|
||||
GstXvImageMeta *meta;
|
||||
GstXvImageMemory *mem;
|
||||
GstVideoCropMeta *crop;
|
||||
GstVideoRectangle result;
|
||||
gboolean draw_border = FALSE;
|
||||
|
@ -309,22 +309,22 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
|||
}
|
||||
}
|
||||
|
||||
meta = gst_buffer_get_xvimage_meta (xvimage);
|
||||
mem = (GstXvImageMemory *) gst_buffer_peek_memory (xvimage, 0);
|
||||
|
||||
crop = gst_buffer_get_video_crop_meta (xvimage);
|
||||
|
||||
if (crop) {
|
||||
src.x = crop->x + meta->x;
|
||||
src.y = crop->y + meta->y;
|
||||
src.x = crop->x + mem->x;
|
||||
src.y = crop->y + mem->y;
|
||||
src.w = crop->width;
|
||||
src.h = crop->height;
|
||||
GST_LOG_OBJECT (xvimagesink,
|
||||
"crop %dx%d-%dx%d", crop->x, crop->y, crop->width, crop->height);
|
||||
} else {
|
||||
src.x = meta->x;
|
||||
src.y = meta->y;
|
||||
src.w = meta->width;
|
||||
src.h = meta->height;
|
||||
src.x = mem->x;
|
||||
src.y = mem->y;
|
||||
src.w = mem->width;
|
||||
src.h = mem->height;
|
||||
}
|
||||
|
||||
if (xvimagesink->keep_aspect) {
|
||||
|
@ -356,13 +356,13 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
|||
if (xvimagesink->xcontext->use_xshm) {
|
||||
GST_LOG_OBJECT (xvimagesink,
|
||||
"XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
|
||||
GST_PTR_FORMAT, meta->width, meta->height,
|
||||
GST_PTR_FORMAT, mem->width, mem->height,
|
||||
xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
|
||||
|
||||
XvShmPutImage (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xcontext->xv_port_id,
|
||||
xvimagesink->xwindow->win,
|
||||
xvimagesink->xwindow->gc, meta->xvimage,
|
||||
xvimagesink->xwindow->gc, mem->xvimage,
|
||||
src.x, src.y, src.w, src.h,
|
||||
result.x, result.y, result.w, result.h, FALSE);
|
||||
} else
|
||||
|
@ -371,7 +371,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
|||
XvPutImage (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xcontext->xv_port_id,
|
||||
xvimagesink->xwindow->win,
|
||||
xvimagesink->xwindow->gc, meta->xvimage,
|
||||
xvimagesink->xwindow->gc, mem->xvimage,
|
||||
src.x, src.y, src.w, src.h, result.x, result.y, result.w, result.h);
|
||||
}
|
||||
|
||||
|
@ -1810,14 +1810,15 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
{
|
||||
GstFlowReturn res;
|
||||
GstXvImageSink *xvimagesink;
|
||||
GstXvImageMeta *meta;
|
||||
GstBuffer *to_put;
|
||||
GstXvImageMemory *mem;
|
||||
|
||||
xvimagesink = GST_XVIMAGESINK (vsink);
|
||||
|
||||
meta = gst_buffer_get_xvimage_meta (buf);
|
||||
|
||||
if (meta && meta->sink == xvimagesink) {
|
||||
if (gst_buffer_n_memory (buf) == 1
|
||||
&& (mem = (GstXvImageMemory *) gst_buffer_peek_memory (buf, 0))
|
||||
&& g_strcmp0 (mem->parent.allocator->mem_type, "xvimage") == 0
|
||||
&& mem->sink == xvimagesink) {
|
||||
/* If this buffer has been allocated using our buffer management we simply
|
||||
put the ximage which is in the PRIVATE pointer */
|
||||
GST_LOG_OBJECT (xvimagesink, "buffer %p from our pool, writing directly",
|
||||
|
|
Loading…
Reference in a new issue