mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
miniobject: port to 0.11
Use buffer private data instead of subclassing.
This commit is contained in:
parent
8131d1157f
commit
d90a388289
7 changed files with 178 additions and 246 deletions
|
@ -52,23 +52,24 @@
|
||||||
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
||||||
#define GST_CAT_DEFAULT v4l2_debug
|
#define GST_CAT_DEFAULT v4l2_debug
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GstV4l2Buffer:
|
* GstV4l2Buffer:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static GstBufferClass *v4l2buffer_parent_class = NULL;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
|
gst_v4l2_buffer_dispose (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
GstV4l2Data *data;
|
||||||
GstV4l2BufferPool *pool;
|
GstV4l2BufferPool *pool;
|
||||||
gboolean resuscitated = FALSE;
|
gboolean resuscitated = FALSE;
|
||||||
gint index;
|
gint index;
|
||||||
|
|
||||||
pool = buffer->pool;
|
data = GST_V4L2_GET_DATA (buffer);
|
||||||
|
g_assert (data != NULL);
|
||||||
|
|
||||||
index = buffer->vbuffer.index;
|
pool = data->pool;
|
||||||
|
|
||||||
|
index = data->vbuffer.index;
|
||||||
|
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, "finalizing buffer %p %d", buffer, index);
|
GST_LOG_OBJECT (pool->v4l2elem, "finalizing buffer %p %d", buffer, index);
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
|
||||||
if (resuscitated) {
|
if (resuscitated) {
|
||||||
/* FIXME: check that the caps didn't change */
|
/* FIXME: check that the caps didn't change */
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
|
GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
|
||||||
gst_buffer_ref (GST_BUFFER (buffer));
|
gst_buffer_ref (buffer);
|
||||||
GST_BUFFER_SIZE (buffer) = 0;
|
GST_BUFFER_SIZE (buffer) = 0;
|
||||||
pool->buffers[index] = buffer;
|
pool->buffers[index] = buffer;
|
||||||
}
|
}
|
||||||
|
@ -105,96 +106,65 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
|
||||||
if (!resuscitated) {
|
if (!resuscitated) {
|
||||||
GST_LOG_OBJECT (pool->v4l2elem,
|
GST_LOG_OBJECT (pool->v4l2elem,
|
||||||
"buffer %p (data %p, len %u) not recovered, unmapping",
|
"buffer %p (data %p, len %u) not recovered, unmapping",
|
||||||
buffer, GST_BUFFER_DATA (buffer), buffer->vbuffer.length);
|
buffer, GST_BUFFER_DATA (buffer), data->vbuffer.length);
|
||||||
gst_mini_object_unref (GST_MINI_OBJECT (pool));
|
v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), data->vbuffer.length);
|
||||||
v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), buffer->vbuffer.length);
|
|
||||||
|
|
||||||
GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
|
g_object_unref (pool);
|
||||||
(buffer));
|
g_slice_free (GstV4l2Data, data);
|
||||||
|
buffer->owner_priv = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstBuffer *
|
||||||
gst_v4l2_buffer_class_init (gpointer g_class, gpointer class_data)
|
|
||||||
{
|
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
||||||
|
|
||||||
v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
|
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
|
||||||
gst_v4l2_buffer_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
|
||||||
gst_v4l2_buffer_get_type (void)
|
|
||||||
{
|
|
||||||
static GType _gst_v4l2_buffer_type;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_v4l2_buffer_type == 0)) {
|
|
||||||
static const GTypeInfo v4l2_buffer_info = {
|
|
||||||
sizeof (GstBufferClass),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
gst_v4l2_buffer_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstV4l2Buffer),
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
_gst_v4l2_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
||||||
"GstV4l2Buffer", &v4l2_buffer_info, 0);
|
|
||||||
}
|
|
||||||
return _gst_v4l2_buffer_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstV4l2Buffer *
|
|
||||||
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
|
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstV4l2Buffer *ret;
|
GstV4l2Data *data;
|
||||||
guint8 *data;
|
GstBuffer *ret;
|
||||||
|
guint8 *mem;
|
||||||
|
|
||||||
ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER);
|
ret = gst_buffer_new ();
|
||||||
|
data = g_slice_new (GstV4l2Data);
|
||||||
|
ret->owner_priv = data;
|
||||||
|
GST_MINI_OBJECT_CAST (ret)->dispose =
|
||||||
|
(GstMiniObjectDisposeFunction) gst_v4l2_buffer_dispose;
|
||||||
|
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index,
|
GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index,
|
||||||
ret, pool);
|
ret, pool);
|
||||||
|
|
||||||
ret->pool =
|
data->pool = (GstV4l2BufferPool *) g_object_ref (pool);
|
||||||
(GstV4l2BufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool));
|
|
||||||
|
|
||||||
ret->vbuffer.index = index;
|
data->vbuffer.index = index;
|
||||||
ret->vbuffer.type = pool->type;
|
data->vbuffer.type = pool->type;
|
||||||
ret->vbuffer.memory = V4L2_MEMORY_MMAP;
|
data->vbuffer.memory = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0)
|
if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &data->vbuffer) < 0)
|
||||||
goto querybuf_failed;
|
goto querybuf_failed;
|
||||||
|
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " index: %u", ret->vbuffer.index);
|
GST_LOG_OBJECT (pool->v4l2elem, " index: %u", data->vbuffer.index);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " type: %d", ret->vbuffer.type);
|
GST_LOG_OBJECT (pool->v4l2elem, " type: %d", data->vbuffer.type);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " bytesused: %u", ret->vbuffer.bytesused);
|
GST_LOG_OBJECT (pool->v4l2elem, " bytesused: %u", data->vbuffer.bytesused);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " flags: %08x", ret->vbuffer.flags);
|
GST_LOG_OBJECT (pool->v4l2elem, " flags: %08x", data->vbuffer.flags);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " field: %d", ret->vbuffer.field);
|
GST_LOG_OBJECT (pool->v4l2elem, " field: %d", data->vbuffer.field);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " memory: %d", ret->vbuffer.memory);
|
GST_LOG_OBJECT (pool->v4l2elem, " memory: %d", data->vbuffer.memory);
|
||||||
if (ret->vbuffer.memory == V4L2_MEMORY_MMAP)
|
if (data->vbuffer.memory == V4L2_MEMORY_MMAP)
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " MMAP offset: %u",
|
GST_LOG_OBJECT (pool->v4l2elem, " MMAP offset: %u",
|
||||||
ret->vbuffer.m.offset);
|
data->vbuffer.m.offset);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " length: %u", ret->vbuffer.length);
|
GST_LOG_OBJECT (pool->v4l2elem, " length: %u", data->vbuffer.length);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " input: %u", ret->vbuffer.input);
|
GST_LOG_OBJECT (pool->v4l2elem, " input: %u", data->vbuffer.input);
|
||||||
|
|
||||||
data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length,
|
mem = (guint8 *) v4l2_mmap (0, data->vbuffer.length,
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
|
PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
|
||||||
ret->vbuffer.m.offset);
|
data->vbuffer.m.offset);
|
||||||
|
|
||||||
if (data == MAP_FAILED)
|
if (mem == MAP_FAILED)
|
||||||
goto mmap_failed;
|
goto mmap_failed;
|
||||||
|
|
||||||
GST_BUFFER_DATA (ret) = data;
|
GST_BUFFER_DATA (ret) = mem;
|
||||||
GST_BUFFER_SIZE (ret) = ret->vbuffer.length;
|
GST_BUFFER_SIZE (ret) = data->vbuffer.length;
|
||||||
|
|
||||||
GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
|
GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
|
||||||
|
|
||||||
gst_buffer_set_caps (GST_BUFFER (ret), caps);
|
gst_buffer_set_caps (ret, caps);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -204,7 +174,7 @@ querybuf_failed:
|
||||||
gint errnosave = errno;
|
gint errnosave = errno;
|
||||||
|
|
||||||
GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
|
GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
|
||||||
gst_buffer_unref (GST_BUFFER (ret));
|
gst_buffer_unref (ret);
|
||||||
errno = errnosave;
|
errno = errnosave;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +183,7 @@ mmap_failed:
|
||||||
gint errnosave = errno;
|
gint errnosave = errno;
|
||||||
|
|
||||||
GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
|
GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
|
||||||
gst_buffer_unref (GST_BUFFER (ret));
|
gst_buffer_unref (ret);
|
||||||
errno = errnosave;
|
errno = errnosave;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -224,11 +194,13 @@ mmap_failed:
|
||||||
* GstV4l2BufferPool:
|
* GstV4l2BufferPool:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static GstMiniObjectClass *buffer_pool_parent_class = NULL;
|
static GObjectClass *buffer_pool_parent_class = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_buffer_pool_finalize (GstV4l2BufferPool * pool)
|
gst_v4l2_buffer_pool_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
|
||||||
|
|
||||||
g_mutex_free (pool->lock);
|
g_mutex_free (pool->lock);
|
||||||
pool->lock = NULL;
|
pool->lock = NULL;
|
||||||
|
|
||||||
|
@ -243,8 +215,7 @@ gst_v4l2_buffer_pool_finalize (GstV4l2BufferPool * pool)
|
||||||
pool->buffers = NULL;
|
pool->buffers = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
|
buffer_pool_parent_class->finalize (object);
|
||||||
(pool));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -258,12 +229,11 @@ gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool, gpointer g_class)
|
||||||
static void
|
static void
|
||||||
gst_v4l2_buffer_pool_class_init (gpointer g_class, gpointer class_data)
|
gst_v4l2_buffer_pool_class_init (gpointer g_class, gpointer class_data)
|
||||||
{
|
{
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
GObjectClass *object_class = G_OBJECT_CLASS (g_class);
|
||||||
|
|
||||||
buffer_pool_parent_class = g_type_class_peek_parent (g_class);
|
buffer_pool_parent_class = g_type_class_peek_parent (g_class);
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
object_class->finalize = gst_v4l2_buffer_pool_finalize;
|
||||||
gst_v4l2_buffer_pool_finalize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
|
@ -273,7 +243,7 @@ gst_v4l2_buffer_pool_get_type (void)
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_v4l2_buffer_pool_type == 0)) {
|
if (G_UNLIKELY (_gst_v4l2_buffer_pool_type == 0)) {
|
||||||
static const GTypeInfo v4l2_buffer_pool_info = {
|
static const GTypeInfo v4l2_buffer_pool_info = {
|
||||||
sizeof (GstMiniObjectClass),
|
sizeof (GObjectClass),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
gst_v4l2_buffer_pool_class_init,
|
gst_v4l2_buffer_pool_class_init,
|
||||||
|
@ -284,7 +254,7 @@ gst_v4l2_buffer_pool_get_type (void)
|
||||||
(GInstanceInitFunc) gst_v4l2_buffer_pool_init,
|
(GInstanceInitFunc) gst_v4l2_buffer_pool_init,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
_gst_v4l2_buffer_pool_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
|
_gst_v4l2_buffer_pool_type = g_type_register_static (G_TYPE_OBJECT,
|
||||||
"GstV4l2BufferPool", &v4l2_buffer_pool_info, 0);
|
"GstV4l2BufferPool", &v4l2_buffer_pool_info, 0);
|
||||||
}
|
}
|
||||||
return _gst_v4l2_buffer_pool_type;
|
return _gst_v4l2_buffer_pool_type;
|
||||||
|
@ -335,7 +305,7 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
|
||||||
gint n;
|
gint n;
|
||||||
struct v4l2_requestbuffers breq;
|
struct v4l2_requestbuffers breq;
|
||||||
|
|
||||||
pool = (GstV4l2BufferPool *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER_POOL);
|
pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
|
||||||
|
|
||||||
pool->video_fd = v4l2_dup (fd);
|
pool->video_fd = v4l2_dup (fd);
|
||||||
if (pool->video_fd < 0)
|
if (pool->video_fd < 0)
|
||||||
|
@ -370,7 +340,7 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
|
||||||
pool->requeuebuf = requeuebuf;
|
pool->requeuebuf = requeuebuf;
|
||||||
pool->type = type;
|
pool->type = type;
|
||||||
pool->buffer_count = num_buffers;
|
pool->buffer_count = num_buffers;
|
||||||
pool->buffers = g_new0 (GstV4l2Buffer *, num_buffers);
|
pool->buffers = g_new0 (GstBuffer *, num_buffers);
|
||||||
pool->avail_buffers = g_async_queue_new ();
|
pool->avail_buffers = g_async_queue_new ();
|
||||||
|
|
||||||
/* now, map the buffers: */
|
/* now, map the buffers: */
|
||||||
|
@ -389,7 +359,7 @@ dup_failed:
|
||||||
{
|
{
|
||||||
gint errnosave = errno;
|
gint errnosave = errno;
|
||||||
|
|
||||||
gst_mini_object_unref (GST_MINI_OBJECT (pool));
|
g_object_unref (pool);
|
||||||
|
|
||||||
errno = errnosave;
|
errno = errnosave;
|
||||||
|
|
||||||
|
@ -461,7 +431,7 @@ gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool)
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_mini_object_unref (GST_MINI_OBJECT (pool));
|
g_object_unref (pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -472,10 +442,10 @@ gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool)
|
||||||
*
|
*
|
||||||
* Get an available buffer in the pool
|
* Get an available buffer in the pool
|
||||||
*/
|
*/
|
||||||
GstV4l2Buffer *
|
GstBuffer *
|
||||||
gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
|
gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
|
||||||
{
|
{
|
||||||
GstV4l2Buffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
buf = g_async_queue_pop (pool->avail_buffers);
|
buf = g_async_queue_pop (pool->avail_buffers);
|
||||||
|
@ -485,7 +455,7 @@ gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
||||||
GST_BUFFER_SIZE (buf) = buf->vbuffer.length;
|
GST_BUFFER_SIZE (buf) = GST_V4L2_GET_DATA (buf)->vbuffer.length;
|
||||||
GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
|
GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
|
||||||
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
||||||
}
|
}
|
||||||
|
@ -506,11 +476,14 @@ gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
|
||||||
* Returns: %TRUE for success
|
* Returns: %TRUE for success
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstV4l2Buffer * buf)
|
gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, "enqueue pool buffer %d", buf->vbuffer.index);
|
GstV4l2Data *data = GST_V4L2_GET_DATA (buf);
|
||||||
|
|
||||||
if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &buf->vbuffer) < 0)
|
GST_LOG_OBJECT (pool->v4l2elem, "enqueue pool buffer %d",
|
||||||
|
data->vbuffer.index);
|
||||||
|
|
||||||
|
if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &data->vbuffer) < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
pool->num_live_buffers--;
|
pool->num_live_buffers--;
|
||||||
|
@ -530,18 +503,17 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstV4l2Buffer * buf)
|
||||||
*
|
*
|
||||||
* Returns: a buffer
|
* Returns: a buffer
|
||||||
*/
|
*/
|
||||||
GstV4l2Buffer *
|
GstBuffer *
|
||||||
gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
|
gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
|
||||||
{
|
{
|
||||||
GstV4l2Object *v4l2object = get_v4l2_object (pool->v4l2elem);
|
GstV4l2Object *v4l2object = get_v4l2_object (pool->v4l2elem);
|
||||||
GstV4l2Buffer *pool_buffer;
|
GstBuffer *pool_buffer;
|
||||||
struct v4l2_buffer buffer;
|
struct v4l2_buffer buffer;
|
||||||
|
|
||||||
memset (&buffer, 0x00, sizeof (buffer));
|
memset (&buffer, 0x00, sizeof (buffer));
|
||||||
buffer.type = pool->type;
|
buffer.type = pool->type;
|
||||||
buffer.memory = V4L2_MEMORY_MMAP;
|
buffer.memory = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
|
|
||||||
if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) {
|
if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) {
|
||||||
|
|
||||||
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
||||||
|
|
|
@ -46,12 +46,12 @@ GType gst_v4l2_buffer_pool_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
|
typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
|
||||||
typedef struct _GstV4l2Buffer GstV4l2Buffer;
|
typedef struct _GstV4l2Data GstV4l2Data;
|
||||||
|
|
||||||
|
|
||||||
struct _GstV4l2BufferPool
|
struct _GstV4l2BufferPool
|
||||||
{
|
{
|
||||||
GstMiniObject parent;
|
GObject parent;
|
||||||
|
|
||||||
GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */
|
GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */
|
||||||
gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */
|
gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */
|
||||||
|
@ -63,12 +63,12 @@ struct _GstV4l2BufferPool
|
||||||
GAsyncQueue* avail_buffers;/* pool of available buffers, not with the driver and which aren't held outside the bufferpool */
|
GAsyncQueue* avail_buffers;/* pool of available buffers, not with the driver and which aren't held outside the bufferpool */
|
||||||
gint video_fd; /* a dup(2) of the v4l2object's video_fd */
|
gint video_fd; /* a dup(2) of the v4l2object's video_fd */
|
||||||
guint buffer_count;
|
guint buffer_count;
|
||||||
GstV4l2Buffer **buffers;
|
GstBuffer **buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2Buffer {
|
#define GST_V4L2_GET_DATA(buf) ((GstV4l2Data *) (GST_BUFFER_CAST (buf)->owner_priv))
|
||||||
GstBuffer buffer;
|
|
||||||
|
|
||||||
|
struct _GstV4l2Data {
|
||||||
struct v4l2_buffer vbuffer;
|
struct v4l2_buffer vbuffer;
|
||||||
|
|
||||||
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
|
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
|
||||||
|
@ -82,9 +82,9 @@ void gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool);
|
||||||
GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type);
|
GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type);
|
||||||
|
|
||||||
|
|
||||||
GstV4l2Buffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking);
|
GstBuffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking);
|
||||||
gboolean gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool *pool, GstV4l2Buffer *buf);
|
gboolean gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool *pool, GstBuffer *buf);
|
||||||
GstV4l2Buffer *gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool *pool);
|
GstBuffer *gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool *pool);
|
||||||
|
|
||||||
gint gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool *pool);
|
gint gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool *pool);
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ static gboolean
|
||||||
gst_v4l2src_buffer_pool_activate (GstV4l2BufferPool * pool,
|
gst_v4l2src_buffer_pool_activate (GstV4l2BufferPool * pool,
|
||||||
GstV4l2Src * v4l2src)
|
GstV4l2Src * v4l2src)
|
||||||
{
|
{
|
||||||
GstV4l2Buffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
while ((buf = gst_v4l2_buffer_pool_get (pool, FALSE)) != NULL)
|
while ((buf = gst_v4l2_buffer_pool_get (pool, FALSE)) != NULL)
|
||||||
if (!gst_v4l2_buffer_pool_qbuf (pool, buf))
|
if (!gst_v4l2_buffer_pool_qbuf (pool, buf))
|
||||||
|
@ -81,7 +81,8 @@ queue_failed:
|
||||||
(_("Could not enqueue buffers in device '%s'."),
|
(_("Could not enqueue buffers in device '%s'."),
|
||||||
v4l2src->v4l2object->videodev),
|
v4l2src->v4l2object->videodev),
|
||||||
("enqueing buffer %d/%d failed: %s",
|
("enqueing buffer %d/%d failed: %s",
|
||||||
buf->vbuffer.index, v4l2src->num_buffers, g_strerror (errno)));
|
GST_V4L2_GET_DATA (buf)->vbuffer.index, v4l2src->num_buffers,
|
||||||
|
g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,24 +80,24 @@ static void gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc);
|
||||||
|
|
||||||
/* Called when a buffer is returned from the pipeline */
|
/* Called when a buffer is returned from the pipeline */
|
||||||
static void
|
static void
|
||||||
gst_ximage_src_return_buf (GstXImageSrc * ximagesrc,
|
gst_ximage_src_return_buf (GstXImageSrc * ximagesrc, GstBuffer * ximage)
|
||||||
GstXImageSrcBuffer * ximage)
|
|
||||||
{
|
{
|
||||||
|
GstXImageData *data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
|
|
||||||
/* If our geometry changed we can't reuse that image. */
|
/* If our geometry changed we can't reuse that image. */
|
||||||
if ((ximage->width != ximagesrc->width) ||
|
if ((data->width != ximagesrc->width) || (data->height != ximagesrc->height)) {
|
||||||
(ximage->height != ximagesrc->height)) {
|
|
||||||
GST_DEBUG_OBJECT (ximagesrc,
|
GST_DEBUG_OBJECT (ximagesrc,
|
||||||
"destroy image %p as its size changed %dx%d vs current %dx%d",
|
"destroy image %p as its size changed %dx%d vs current %dx%d",
|
||||||
ximage, ximage->width, ximage->height,
|
ximage, data->width, data->height, ximagesrc->width, ximagesrc->height);
|
||||||
ximagesrc->width, ximagesrc->height);
|
|
||||||
g_mutex_lock (ximagesrc->x_lock);
|
g_mutex_lock (ximagesrc->x_lock);
|
||||||
gst_ximageutil_ximage_destroy (ximagesrc->xcontext, ximage);
|
gst_ximageutil_ximage_destroy (ximagesrc->xcontext, ximage);
|
||||||
|
g_slice_free (GstXImageData, data);
|
||||||
g_mutex_unlock (ximagesrc->x_lock);
|
g_mutex_unlock (ximagesrc->x_lock);
|
||||||
} else {
|
} else {
|
||||||
/* In that case we can reuse the image and add it to our image pool. */
|
/* In that case we can reuse the image and add it to our image pool. */
|
||||||
GST_LOG_OBJECT (ximagesrc, "recycling image %p in pool", ximage);
|
GST_LOG_OBJECT (ximagesrc, "recycling image %p in pool", ximage);
|
||||||
/* need to increment the refcount again to recycle */
|
/* need to increment the refcount again to recycle */
|
||||||
gst_buffer_ref (GST_BUFFER (ximage));
|
gst_buffer_ref (ximage);
|
||||||
g_mutex_lock (ximagesrc->pool_lock);
|
g_mutex_lock (ximagesrc->pool_lock);
|
||||||
ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage);
|
ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage);
|
||||||
g_mutex_unlock (ximagesrc->pool_lock);
|
g_mutex_unlock (ximagesrc->pool_lock);
|
||||||
|
@ -358,17 +358,20 @@ composite_pixel (GstXContext * xcontext, guchar * dest, guchar * src)
|
||||||
|
|
||||||
/* Retrieve an XImageSrcBuffer, preferably from our
|
/* Retrieve an XImageSrcBuffer, preferably from our
|
||||||
* pool of existing images and populate it from the window */
|
* pool of existing images and populate it from the window */
|
||||||
static GstXImageSrcBuffer *
|
static GstBuffer *
|
||||||
gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
{
|
{
|
||||||
GstXImageSrcBuffer *ximage = NULL;
|
GstBuffer *ximage = NULL;
|
||||||
|
GstXImageData *data;
|
||||||
|
|
||||||
g_mutex_lock (ximagesrc->pool_lock);
|
g_mutex_lock (ximagesrc->pool_lock);
|
||||||
while (ximagesrc->buffer_pool != NULL) {
|
while (ximagesrc->buffer_pool != NULL) {
|
||||||
ximage = ximagesrc->buffer_pool->data;
|
ximage = ximagesrc->buffer_pool->data;
|
||||||
|
|
||||||
if ((ximage->width != ximagesrc->width) ||
|
data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
(ximage->height != ximagesrc->height)) {
|
|
||||||
|
if ((data->width != ximagesrc->width) ||
|
||||||
|
(data->height != ximagesrc->height)) {
|
||||||
gst_ximage_buffer_free (ximage);
|
gst_ximage_buffer_free (ximage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,13 +416,16 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
gst_value_get_fraction_numerator (xcontext->par),
|
gst_value_get_fraction_numerator (xcontext->par),
|
||||||
gst_value_get_fraction_denominator (xcontext->par), NULL);
|
gst_value_get_fraction_denominator (xcontext->par), NULL);
|
||||||
|
|
||||||
gst_buffer_set_caps (GST_BUFFER (ximage), caps);
|
gst_buffer_set_caps (ximage, caps);
|
||||||
g_mutex_unlock (ximagesrc->x_lock);
|
g_mutex_unlock (ximagesrc->x_lock);
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_XIMAGE_SRC (ximagesrc), NULL);
|
g_return_val_if_fail (GST_IS_XIMAGE_SRC (ximagesrc), NULL);
|
||||||
|
|
||||||
|
data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
|
|
||||||
#ifdef HAVE_XDAMAGE
|
#ifdef HAVE_XDAMAGE
|
||||||
if (ximagesrc->have_xdamage && ximagesrc->use_damage &&
|
if (ximagesrc->have_xdamage && ximagesrc->use_damage &&
|
||||||
ximagesrc->last_ximage != NULL) {
|
ximagesrc->last_ximage != NULL) {
|
||||||
|
@ -492,7 +498,7 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
startx, starty, width, height);
|
startx, starty, width, height);
|
||||||
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
startx, starty, width, height, AllPlanes, ZPixmap,
|
startx, starty, width, height, AllPlanes, ZPixmap,
|
||||||
ximage->ximage, startx - ximagesrc->startx,
|
data->ximage, startx - ximagesrc->startx,
|
||||||
starty - ximagesrc->starty);
|
starty - ximagesrc->starty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -504,7 +510,7 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
rects[i].x, rects[i].y,
|
rects[i].x, rects[i].y,
|
||||||
rects[i].width, rects[i].height,
|
rects[i].width, rects[i].height,
|
||||||
AllPlanes, ZPixmap, ximage->ximage, rects[i].x, rects[i].y);
|
AllPlanes, ZPixmap, data->ximage, rects[i].x, rects[i].y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (rects);
|
free (rects);
|
||||||
|
@ -566,14 +572,14 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
|
GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
|
||||||
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
startx, starty, iwidth, iheight, AllPlanes, ZPixmap,
|
startx, starty, iwidth, iheight, AllPlanes, ZPixmap,
|
||||||
ximage->ximage, startx - ximagesrc->startx,
|
data->ximage, startx - ximagesrc->startx,
|
||||||
starty - ximagesrc->starty);
|
starty - ximagesrc->starty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
|
GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
|
||||||
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
x, y, width, height, AllPlanes, ZPixmap, ximage->ximage, x, y);
|
x, y, width, height, AllPlanes, ZPixmap, data->ximage, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -586,7 +592,7 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
if (ximagesrc->xcontext->use_xshm) {
|
if (ximagesrc->xcontext->use_xshm) {
|
||||||
GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XShm");
|
GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XShm");
|
||||||
XShmGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XShmGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
ximage->ximage, ximagesrc->startx, ximagesrc->starty, AllPlanes);
|
data->ximage, ximagesrc->startx, ximagesrc->starty, AllPlanes);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
|
@ -595,9 +601,9 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
if (ximagesrc->remote) {
|
if (ximagesrc->remote) {
|
||||||
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
|
ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
|
||||||
ximagesrc->height, AllPlanes, ZPixmap, ximage->ximage, 0, 0);
|
ximagesrc->height, AllPlanes, ZPixmap, data->ximage, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
ximage->ximage =
|
data->ximage =
|
||||||
XGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
XGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
|
||||||
ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
|
ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
|
||||||
ximagesrc->height, AllPlanes, ZPixmap);
|
ximagesrc->height, AllPlanes, ZPixmap);
|
||||||
|
@ -677,7 +683,7 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
|
||||||
(guint8 *) & (ximagesrc->cursor_image->pixels[((j -
|
(guint8 *) & (ximagesrc->cursor_image->pixels[((j -
|
||||||
cy) * ximagesrc->cursor_image->width + (i - cx))]);
|
cy) * ximagesrc->cursor_image->width + (i - cx))]);
|
||||||
dest =
|
dest =
|
||||||
(guint8 *) & (ximage->ximage->data[((j -
|
(guint8 *) & (data->ximage->data[((j -
|
||||||
ximagesrc->starty) * ximagesrc->width + (i -
|
ximagesrc->starty) * ximagesrc->width + (i -
|
||||||
ximagesrc->startx)) * (ximagesrc->xcontext->bpp /
|
ximagesrc->startx)) * (ximagesrc->xcontext->bpp /
|
||||||
8)]);
|
8)]);
|
||||||
|
@ -708,7 +714,7 @@ static GstFlowReturn
|
||||||
gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
|
gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
|
||||||
{
|
{
|
||||||
GstXImageSrc *s = GST_XIMAGE_SRC (bs);
|
GstXImageSrc *s = GST_XIMAGE_SRC (bs);
|
||||||
GstXImageSrcBuffer *image;
|
GstBuffer *image;
|
||||||
GstClockTime base_time;
|
GstClockTime base_time;
|
||||||
GstClockTime next_capture_ts;
|
GstClockTime next_capture_ts;
|
||||||
GstClockTime dur;
|
GstClockTime dur;
|
||||||
|
@ -889,7 +895,7 @@ gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc)
|
||||||
{
|
{
|
||||||
g_mutex_lock (ximagesrc->pool_lock);
|
g_mutex_lock (ximagesrc->pool_lock);
|
||||||
while (ximagesrc->buffer_pool != NULL) {
|
while (ximagesrc->buffer_pool != NULL) {
|
||||||
GstXImageSrcBuffer *ximage = ximagesrc->buffer_pool->data;
|
GstBuffer *ximage = ximagesrc->buffer_pool->data;
|
||||||
|
|
||||||
gst_ximage_buffer_free (ximage);
|
gst_ximage_buffer_free (ximage);
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ struct _GstXImageSrc
|
||||||
int damage_event_base;
|
int damage_event_base;
|
||||||
XserverRegion damage_region;
|
XserverRegion damage_region;
|
||||||
GC damage_copy_gc;
|
GC damage_copy_gc;
|
||||||
GstXImageSrcBuffer *last_ximage;
|
GstBuffer *last_ximage;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -296,154 +296,112 @@ ximageutil_calculate_pixel_aspect_ratio (GstXContext * xcontext)
|
||||||
gst_value_get_fraction_denominator (xcontext->par));
|
gst_value_get_fraction_denominator (xcontext->par));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstBufferClass *ximagesrc_buffer_parent_class = NULL;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_ximagesrc_buffer_finalize (GstXImageSrcBuffer * ximage)
|
gst_ximagesrc_buffer_dispose (GstBuffer * ximage)
|
||||||
{
|
{
|
||||||
GstElement *parent;
|
GstElement *parent;
|
||||||
|
GstXImageData *data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
|
|
||||||
g_return_if_fail (ximage != NULL);
|
g_return_if_fail (ximage != NULL);
|
||||||
|
|
||||||
parent = ximage->parent;
|
parent = data->parent;
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
g_warning ("XImageSrcBuffer->ximagesrc == NULL");
|
g_warning ("XImageSrcBuffer->ximagesrc == NULL");
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ximage->return_func)
|
if (data->return_func)
|
||||||
ximage->return_func (parent, ximage);
|
data->return_func (parent, ximage);
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
|
|
||||||
GST_MINI_OBJECT_CLASS (ximagesrc_buffer_parent_class)->finalize
|
|
||||||
(GST_MINI_OBJECT (ximage));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_ximage_buffer_free (GstXImageSrcBuffer * ximage)
|
gst_ximage_buffer_free (GstBuffer * ximage)
|
||||||
{
|
{
|
||||||
|
GstXImageData *data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
/* make sure it is not recycled */
|
/* make sure it is not recycled */
|
||||||
ximage->width = -1;
|
data->width = -1;
|
||||||
ximage->height = -1;
|
data->height = -1;
|
||||||
gst_buffer_unref (GST_BUFFER (ximage));
|
gst_buffer_unref (ximage);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ximagesrc_buffer_init (GstXImageSrcBuffer * ximage_buffer, gpointer g_class)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XSHM
|
|
||||||
ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
|
|
||||||
ximage_buffer->SHMInfo.shmid = -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ximagesrc_buffer_class_init (gpointer g_class, gpointer class_data)
|
|
||||||
{
|
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
||||||
|
|
||||||
ximagesrc_buffer_parent_class = g_type_class_peek_parent (g_class);
|
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
|
||||||
gst_ximagesrc_buffer_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
|
||||||
gst_ximagesrc_buffer_get_type (void)
|
|
||||||
{
|
|
||||||
static GType _gst_ximagesrc_buffer_type;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_ximagesrc_buffer_type == 0)) {
|
|
||||||
static const GTypeInfo ximagesrc_buffer_info = {
|
|
||||||
sizeof (GstBufferClass),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
gst_ximagesrc_buffer_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstXImageSrcBuffer),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_ximagesrc_buffer_init,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
_gst_ximagesrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
||||||
"GstXImageSrcBuffer", &ximagesrc_buffer_info, 0);
|
|
||||||
}
|
|
||||||
return _gst_ximagesrc_buffer_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function handles GstXImageSrcBuffer creation depending on XShm availability */
|
/* This function handles GstXImageSrcBuffer creation depending on XShm availability */
|
||||||
GstXImageSrcBuffer *
|
GstBuffer *
|
||||||
gst_ximageutil_ximage_new (GstXContext * xcontext,
|
gst_ximageutil_ximage_new (GstXContext * xcontext,
|
||||||
GstElement * parent, int width, int height, BufferReturnFunc return_func)
|
GstElement * parent, int width, int height, BufferReturnFunc return_func)
|
||||||
{
|
{
|
||||||
GstXImageSrcBuffer *ximage = NULL;
|
GstBuffer *ximage = NULL;
|
||||||
|
GstXImageData *data;
|
||||||
gboolean succeeded = FALSE;
|
gboolean succeeded = FALSE;
|
||||||
|
|
||||||
ximage =
|
ximage = gst_buffer_new ();
|
||||||
(GstXImageSrcBuffer *) gst_mini_object_new (GST_TYPE_XIMAGESRC_BUFFER);
|
data = g_slice_new (GstXImageData);
|
||||||
|
ximage->owner_priv = data;
|
||||||
|
GST_MINI_OBJECT_CAST (ximage)->dispose =
|
||||||
|
(GstMiniObjectDisposeFunction) gst_ximagesrc_buffer_dispose;
|
||||||
|
|
||||||
ximage->width = width;
|
data->width = width;
|
||||||
ximage->height = height;
|
data->height = height;
|
||||||
|
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
|
data->SHMInfo.shmaddr = ((void *) -1);
|
||||||
|
data->SHMInfo.shmid = -1;
|
||||||
|
|
||||||
if (xcontext->use_xshm) {
|
if (xcontext->use_xshm) {
|
||||||
ximage->ximage = XShmCreateImage (xcontext->disp,
|
data->ximage = XShmCreateImage (xcontext->disp,
|
||||||
xcontext->visual, xcontext->depth,
|
xcontext->visual, xcontext->depth,
|
||||||
ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
|
ZPixmap, NULL, &data->SHMInfo, data->width, data->height);
|
||||||
if (!ximage->ximage) {
|
if (!data->ximage) {
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to use the returned bytes_per_line for our shm size */
|
/* we have to use the returned bytes_per_line for our shm size */
|
||||||
ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
|
data->size = data->ximage->bytes_per_line * data->ximage->height;
|
||||||
ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
|
data->SHMInfo.shmid = shmget (IPC_PRIVATE, data->size, IPC_CREAT | 0777);
|
||||||
IPC_CREAT | 0777);
|
if (data->SHMInfo.shmid == -1)
|
||||||
if (ximage->SHMInfo.shmid == -1)
|
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, 0, 0);
|
data->SHMInfo.shmaddr = shmat (data->SHMInfo.shmid, 0, 0);
|
||||||
if (ximage->SHMInfo.shmaddr == ((void *) -1))
|
if (data->SHMInfo.shmaddr == ((void *) -1))
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
/* Delete the SHM segment. It will actually go away automatically
|
/* Delete the SHM segment. It will actually go away automatically
|
||||||
* when we detach now */
|
* when we detach now */
|
||||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, 0);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, 0);
|
||||||
|
|
||||||
ximage->ximage->data = ximage->SHMInfo.shmaddr;
|
data->ximage->data = data->SHMInfo.shmaddr;
|
||||||
ximage->SHMInfo.readOnly = FALSE;
|
data->SHMInfo.readOnly = FALSE;
|
||||||
|
|
||||||
if (XShmAttach (xcontext->disp, &ximage->SHMInfo) == 0)
|
if (XShmAttach (xcontext->disp, &data->SHMInfo) == 0)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
XSync (xcontext->disp, FALSE);
|
XSync (xcontext->disp, FALSE);
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
{
|
{
|
||||||
ximage->ximage = XCreateImage (xcontext->disp,
|
data->ximage = XCreateImage (xcontext->disp,
|
||||||
xcontext->visual,
|
xcontext->visual,
|
||||||
xcontext->depth,
|
xcontext->depth,
|
||||||
ZPixmap, 0, NULL, ximage->width, ximage->height, xcontext->bpp, 0);
|
ZPixmap, 0, NULL, data->width, data->height, xcontext->bpp, 0);
|
||||||
if (!ximage->ximage)
|
if (!data->ximage)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
/* we have to use the returned bytes_per_line for our image size */
|
/* we have to use the returned bytes_per_line for our image size */
|
||||||
ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
|
data->size = data->ximage->bytes_per_line * data->ximage->height;
|
||||||
ximage->ximage->data = g_malloc (ximage->size);
|
data->ximage->data = g_malloc (data->size);
|
||||||
|
|
||||||
XSync (xcontext->disp, FALSE);
|
XSync (xcontext->disp, FALSE);
|
||||||
}
|
}
|
||||||
succeeded = TRUE;
|
succeeded = TRUE;
|
||||||
|
|
||||||
GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
|
GST_BUFFER_DATA (ximage) = (guchar *) data->ximage->data;
|
||||||
GST_BUFFER_SIZE (ximage) = ximage->size;
|
GST_BUFFER_SIZE (ximage) = data->size;
|
||||||
|
|
||||||
/* Keep a ref to our src */
|
/* Keep a ref to our src */
|
||||||
ximage->parent = gst_object_ref (parent);
|
data->parent = gst_object_ref (parent);
|
||||||
ximage->return_func = return_func;
|
data->return_func = return_func;
|
||||||
beach:
|
beach:
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
gst_ximage_buffer_free (ximage);
|
gst_ximage_buffer_free (ximage);
|
||||||
|
@ -455,9 +413,12 @@ beach:
|
||||||
|
|
||||||
/* This function destroys a GstXImageBuffer handling XShm availability */
|
/* This function destroys a GstXImageBuffer handling XShm availability */
|
||||||
void
|
void
|
||||||
gst_ximageutil_ximage_destroy (GstXContext * xcontext,
|
gst_ximageutil_ximage_destroy (GstXContext * xcontext, GstBuffer * ximage)
|
||||||
GstXImageSrcBuffer * ximage)
|
|
||||||
{
|
{
|
||||||
|
GstXImageData *data;
|
||||||
|
|
||||||
|
data = GST_XIMAGE_GET_DATA (ximage);
|
||||||
|
|
||||||
/* We might have some buffers destroyed after changing state to NULL */
|
/* We might have some buffers destroyed after changing state to NULL */
|
||||||
if (!xcontext)
|
if (!xcontext)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
@ -466,28 +427,28 @@ gst_ximageutil_ximage_destroy (GstXContext * xcontext,
|
||||||
|
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
if (xcontext->use_xshm) {
|
if (xcontext->use_xshm) {
|
||||||
if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
|
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||||
XShmDetach (xcontext->disp, &ximage->SHMInfo);
|
XShmDetach (xcontext->disp, &data->SHMInfo);
|
||||||
XSync (xcontext->disp, 0);
|
XSync (xcontext->disp, 0);
|
||||||
shmdt (ximage->SHMInfo.shmaddr);
|
shmdt (data->SHMInfo.shmaddr);
|
||||||
}
|
}
|
||||||
if (ximage->ximage)
|
if (data->ximage)
|
||||||
XDestroyImage (ximage->ximage);
|
XDestroyImage (data->ximage);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
{
|
{
|
||||||
if (ximage->ximage) {
|
if (data->ximage) {
|
||||||
XDestroyImage (ximage->ximage);
|
XDestroyImage (data->ximage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XSync (xcontext->disp, FALSE);
|
XSync (xcontext->disp, FALSE);
|
||||||
beach:
|
beach:
|
||||||
if (ximage->parent) {
|
if (data->parent) {
|
||||||
/* Release the ref to our parent */
|
/* Release the ref to our parent */
|
||||||
gst_object_unref (ximage->parent);
|
gst_object_unref (data->parent);
|
||||||
ximage->parent = NULL;
|
data->parent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -43,7 +43,7 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstXContext GstXContext;
|
typedef struct _GstXContext GstXContext;
|
||||||
typedef struct _GstXWindow GstXWindow;
|
typedef struct _GstXWindow GstXWindow;
|
||||||
typedef struct _GstXImage GstXImage;
|
typedef struct _GstXImage GstXImage;
|
||||||
typedef struct _GstXImageSrcBuffer GstXImageSrcBuffer;
|
typedef struct _GstXImageData GstXImageData;
|
||||||
|
|
||||||
/* Global X Context stuff */
|
/* Global X Context stuff */
|
||||||
/**
|
/**
|
||||||
|
@ -130,21 +130,20 @@ void ximageutil_calculate_pixel_aspect_ratio (GstXContext * xcontext);
|
||||||
/* custom ximagesrc buffer, copied from ximagesink */
|
/* custom ximagesrc buffer, copied from ximagesink */
|
||||||
|
|
||||||
/* BufferReturnFunc is called when a buffer is finalised */
|
/* BufferReturnFunc is called when a buffer is finalised */
|
||||||
typedef void (*BufferReturnFunc) (GstElement *parent, GstXImageSrcBuffer *buf);
|
typedef void (*BufferReturnFunc) (GstElement *parent, GstBuffer *buf);
|
||||||
|
|
||||||
|
#define GST_XIMAGE_GET_DATA(buf) ((GstXImageData *) (GST_BUFFER_CAST(buf)->owner_priv))
|
||||||
/**
|
/**
|
||||||
* GstXImageSrcBuffer:
|
* GstXImageData:
|
||||||
* @parent: a reference to the element we belong to
|
* @parent: a reference to the element we belong to
|
||||||
* @ximage: the XImage of this buffer
|
* @ximage: the XImage of this buffer
|
||||||
* @width: the width in pixels of XImage @ximage
|
* @width: the width in pixels of XImage @ximage
|
||||||
* @height: the height in pixels of XImage @ximage
|
* @height: the height in pixels of XImage @ximage
|
||||||
* @size: the size in bytes of XImage @ximage
|
* @size: the size in bytes of XImage @ximage
|
||||||
*
|
*
|
||||||
* Subclass of #GstBuffer containing additional information about an XImage.
|
* Extra data attached to buffers containing additional information about an XImage.
|
||||||
*/
|
*/
|
||||||
struct _GstXImageSrcBuffer {
|
struct _GstXImageData {
|
||||||
GstBuffer buffer;
|
|
||||||
|
|
||||||
/* Reference to the ximagesrc we belong to */
|
/* Reference to the ximagesrc we belong to */
|
||||||
GstElement *parent;
|
GstElement *parent;
|
||||||
|
|
||||||
|
@ -156,26 +155,19 @@ struct _GstXImageSrcBuffer {
|
||||||
|
|
||||||
gint width, height;
|
gint width, height;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
BufferReturnFunc return_func;
|
BufferReturnFunc return_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GstXImageSrcBuffer *gst_ximageutil_ximage_new (GstXContext *xcontext,
|
GstBuffer *gst_ximageutil_ximage_new (GstXContext *xcontext,
|
||||||
GstElement *parent, int width, int height, BufferReturnFunc return_func);
|
GstElement *parent, int width, int height, BufferReturnFunc return_func);
|
||||||
|
|
||||||
void gst_ximageutil_ximage_destroy (GstXContext *xcontext,
|
void gst_ximageutil_ximage_destroy (GstXContext *xcontext,
|
||||||
GstXImageSrcBuffer * ximage);
|
GstBuffer * ximage);
|
||||||
|
|
||||||
/* Call to manually release a buffer */
|
/* Call to manually release a buffer */
|
||||||
void gst_ximage_buffer_free (GstXImageSrcBuffer *ximage);
|
void gst_ximage_buffer_free (GstBuffer *ximage);
|
||||||
|
|
||||||
#define GST_TYPE_XIMAGESRC_BUFFER (gst_ximagesrc_buffer_get_type())
|
|
||||||
#define GST_IS_XIMAGESRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGESRC_BUFFER))
|
|
||||||
#define GST_IS_XIMAGESRC_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_XIMAGESRC_BUFFER))
|
|
||||||
#define GST_XIMAGESRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBuffer))
|
|
||||||
#define GST_XIMAGESRC_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBufferClass))
|
|
||||||
#define GST_XIMAGESRC_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBufferClass))
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue