mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
X11: port imagesinks to new miniobjects
Remove the subbuffer from X11 sinks and use the private pointer to store a single buffer metadata with the extra info.
This commit is contained in:
parent
03c710d6cd
commit
e78903e662
4 changed files with 360 additions and 433 deletions
|
@ -130,7 +130,7 @@ MotifWmHints, MwmHints;
|
|||
|
||||
static void gst_ximagesink_reset (GstXImageSink * ximagesink);
|
||||
static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||
GstXImageBuffer * ximage);
|
||||
GstBuffer * ximage);
|
||||
static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink);
|
||||
static void gst_ximagesink_expose (GstXOverlay * overlay);
|
||||
|
||||
|
@ -165,36 +165,24 @@ static GstVideoSinkClass *parent_class = NULL;
|
|||
/* ============================================================= */
|
||||
|
||||
/* ximage buffers */
|
||||
#define GET_XDATA(buf) ((GstXImageData *) (GST_BUFFER_CAST(buf)->owner_priv))
|
||||
|
||||
static GstBufferClass *ximage_buffer_parent_class = NULL;
|
||||
|
||||
#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type())
|
||||
|
||||
#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER))
|
||||
#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer))
|
||||
#define GST_XIMAGE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass))
|
||||
|
||||
/* So some words about GstMiniObject, this is pretty messy...
|
||||
GstMiniObject does not use the standard finalizing of GObjects, you are
|
||||
supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref
|
||||
which will handle its own refcount system and call gst_mini_object_free.
|
||||
gst_mini_object_free will call the class finalize method which is not the
|
||||
one from GObject, after calling this finalize method it will free the object
|
||||
instance for you if the refcount is still 0 so you should not chain up */
|
||||
static void
|
||||
gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
|
||||
gst_ximage_buffer_dispose (GstBuffer * ximage)
|
||||
{
|
||||
GstXImageData *data = NULL;
|
||||
GstXImageSink *ximagesink = NULL;
|
||||
gboolean recycled = FALSE;
|
||||
gboolean running;
|
||||
|
||||
g_return_if_fail (ximage != NULL);
|
||||
data = GET_XDATA (ximage);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
ximagesink = ximage->ximagesink;
|
||||
if (G_UNLIKELY (ximagesink == NULL)) {
|
||||
GST_WARNING_OBJECT (ximagesink, "no sink found");
|
||||
goto beach;
|
||||
}
|
||||
ximagesink = data->ximagesink;
|
||||
if (G_UNLIKELY (ximagesink == NULL))
|
||||
goto no_sink;
|
||||
|
||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||
|
||||
GST_OBJECT_LOCK (ximagesink);
|
||||
running = ximagesink->running;
|
||||
|
@ -205,84 +193,44 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
|
|||
GST_DEBUG_OBJECT (ximagesink,
|
||||
"destroy image %p because the sink is shutting down", ximage);
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||
} else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
|
||||
(ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
|
||||
} else if ((data->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
|
||||
(data->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
|
||||
/* If our geometry changed we can't reuse that image. */
|
||||
GST_DEBUG_OBJECT (ximagesink,
|
||||
"destroy image %p as its size changed %dx%d vs current %dx%d",
|
||||
ximage, ximage->width, ximage->height,
|
||||
ximage, data->width, data->height,
|
||||
GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||
} else {
|
||||
/* In that case we can reuse the image and add it to our image pool. */
|
||||
GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
|
||||
/* need to increment the refcount again to recycle */
|
||||
gst_buffer_ref (GST_BUFFER_CAST (ximage));
|
||||
gst_buffer_ref (ximage);
|
||||
g_mutex_lock (ximagesink->pool_lock);
|
||||
ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
|
||||
g_mutex_unlock (ximagesink->pool_lock);
|
||||
recycled = TRUE;
|
||||
}
|
||||
|
||||
if (!recycled)
|
||||
GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->finalize
|
||||
(GST_MINI_OBJECT (ximage));
|
||||
|
||||
beach:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximage_buffer_free (GstXImageBuffer * ximage)
|
||||
{
|
||||
/* make sure it is not recycled */
|
||||
ximage->width = -1;
|
||||
ximage->height = -1;
|
||||
gst_buffer_unref (GST_BUFFER_CAST (ximage));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
|
||||
{
|
||||
#ifdef HAVE_XSHM
|
||||
ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
|
||||
ximage_buffer->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
|
||||
{
|
||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
||||
|
||||
ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
|
||||
|
||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
||||
gst_ximage_buffer_finalize;
|
||||
}
|
||||
|
||||
static GType
|
||||
gst_ximage_buffer_get_type (void)
|
||||
{
|
||||
static GType _gst_ximage_buffer_type;
|
||||
|
||||
if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) {
|
||||
static const GTypeInfo ximage_buffer_info = {
|
||||
sizeof (GstBufferClass),
|
||||
NULL,
|
||||
NULL,
|
||||
gst_ximage_buffer_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstXImageBuffer),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_ximage_buffer_init,
|
||||
NULL
|
||||
};
|
||||
_gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
||||
"GstXImageBuffer", &ximage_buffer_info, 0);
|
||||
no_sink:
|
||||
{
|
||||
GST_WARNING ("no sink found");
|
||||
return;
|
||||
}
|
||||
return _gst_ximage_buffer_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximage_buffer_free (GstBuffer * ximage)
|
||||
{
|
||||
GstXImageData *data = GET_XDATA (ximage);
|
||||
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
/* make sure it is not recycled */
|
||||
data->width = -1;
|
||||
data->height = -1;
|
||||
gst_buffer_unref (ximage);
|
||||
}
|
||||
|
||||
/* X11 stuff */
|
||||
|
@ -398,27 +346,37 @@ beach:
|
|||
#endif /* HAVE_XSHM */
|
||||
|
||||
/* This function handles GstXImageBuffer creation depending on XShm availability */
|
||||
static GstXImageBuffer *
|
||||
static GstBuffer *
|
||||
gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||
{
|
||||
GstXImageBuffer *ximage = NULL;
|
||||
GstBuffer *buffer = NULL;
|
||||
GstXImageData *data = NULL;
|
||||
GstStructure *structure = NULL;
|
||||
gboolean succeeded = FALSE;
|
||||
int (*handler) (Display *, XErrorEvent *);
|
||||
|
||||
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
|
||||
|
||||
ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER);
|
||||
data = g_slice_new0 (GstXImageData);
|
||||
#ifdef HAVE_XSHM
|
||||
data->SHMInfo.shmaddr = ((void *) -1);
|
||||
data->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
|
||||
buffer = gst_buffer_new ();
|
||||
GST_MINI_OBJECT_CAST (buffer)->dispose =
|
||||
(GstMiniObjectDisposeFunction) gst_ximage_buffer_dispose;
|
||||
buffer->owner_priv = data;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &ximage->width) ||
|
||||
!gst_structure_get_int (structure, "height", &ximage->height)) {
|
||||
if (!gst_structure_get_int (structure, "width", &data->width) ||
|
||||
!gst_structure_get_int (structure, "height", &data->height)) {
|
||||
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage,
|
||||
ximage->width, ximage->height);
|
||||
GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", data,
|
||||
data->width, data->height);
|
||||
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
|
||||
|
@ -428,11 +386,11 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
|||
|
||||
#ifdef HAVE_XSHM
|
||||
if (ximagesink->xcontext->use_xshm) {
|
||||
ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
|
||||
data->ximage = XShmCreateImage (ximagesink->xcontext->disp,
|
||||
ximagesink->xcontext->visual,
|
||||
ximagesink->xcontext->depth,
|
||||
ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
|
||||
if (!ximage->ximage || error_caught) {
|
||||
ZPixmap, NULL, &data->SHMInfo, data->width, data->height);
|
||||
if (!data->ximage || error_caught) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
/* Reset error handler */
|
||||
error_caught = FALSE;
|
||||
|
@ -440,53 +398,52 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
|||
/* Push an error */
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximage->width, ximage->height),
|
||||
data->width, data->height),
|
||||
("could not XShmCreateImage a %dx%d image",
|
||||
ximage->width, ximage->height));
|
||||
data->width, data->height));
|
||||
goto beach;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
GST_LOG_OBJECT (ximagesink,
|
||||
"XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
|
||||
ximage->size, ximage->width, ximage->ximage->bytes_per_line);
|
||||
data->size, data->width, data->ximage->bytes_per_line);
|
||||
|
||||
ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
|
||||
IPC_CREAT | 0777);
|
||||
if (ximage->SHMInfo.shmid == -1) {
|
||||
data->SHMInfo.shmid = shmget (IPC_PRIVATE, data->size, IPC_CREAT | 0777);
|
||||
if (data->SHMInfo.shmid == -1) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximage->width, ximage->height),
|
||||
data->width, data->height),
|
||||
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
||||
ximage->size));
|
||||
data->size));
|
||||
goto beach;
|
||||
}
|
||||
|
||||
ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0);
|
||||
if (ximage->SHMInfo.shmaddr == ((void *) -1)) {
|
||||
data->SHMInfo.shmaddr = shmat (data->SHMInfo.shmid, NULL, 0);
|
||||
if (data->SHMInfo.shmaddr == ((void *) -1)) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximage->width, ximage->height),
|
||||
data->width, data->height),
|
||||
("Failed to shmat: %s", g_strerror (errno)));
|
||||
/* Clean up the shared memory segment */
|
||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
goto beach;
|
||||
}
|
||||
|
||||
ximage->ximage->data = ximage->SHMInfo.shmaddr;
|
||||
ximage->SHMInfo.readOnly = FALSE;
|
||||
data->ximage->data = data->SHMInfo.shmaddr;
|
||||
data->SHMInfo.readOnly = FALSE;
|
||||
|
||||
if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) {
|
||||
if (XShmAttach (ximagesink->xcontext->disp, &data->SHMInfo) == 0) {
|
||||
/* Clean up shm seg */
|
||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximage->width, ximage->height), ("Failed to XShmAttach"));
|
||||
data->width, data->height), ("Failed to XShmAttach"));
|
||||
goto beach;
|
||||
}
|
||||
|
||||
|
@ -495,19 +452,19 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
|||
/* Now that everyone has attached, we can delete the shared memory segment.
|
||||
* This way, it will be deleted as soon as we detach later, and not
|
||||
* leaked if we crash. */
|
||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
guint allocsize;
|
||||
|
||||
ximage->ximage = XCreateImage (ximagesink->xcontext->disp,
|
||||
data->ximage = XCreateImage (ximagesink->xcontext->disp,
|
||||
ximagesink->xcontext->visual,
|
||||
ximagesink->xcontext->depth,
|
||||
ZPixmap, 0, NULL,
|
||||
ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
|
||||
if (!ximage->ximage || error_caught) {
|
||||
data->width, data->height, ximagesink->xcontext->bpp, 0);
|
||||
if (!data->ximage || error_caught) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
/* Reset error handler */
|
||||
error_caught = FALSE;
|
||||
|
@ -515,33 +472,31 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
|||
/* Push an error */
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximage->width, ximage->height),
|
||||
("could not XCreateImage a %dx%d image",
|
||||
ximage->width, ximage->height));
|
||||
data->width, data->height),
|
||||
("could not XCreateImage a %dx%d image", data->width, data->height));
|
||||
goto beach;
|
||||
}
|
||||
|
||||
/* upstream will assume that rowstrides are multiples of 4, but this
|
||||
* doesn't always seem to be the case with XCreateImage() */
|
||||
if ((ximage->ximage->bytes_per_line % 4) != 0) {
|
||||
if ((data->ximage->bytes_per_line % 4) != 0) {
|
||||
GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
|
||||
"usually assumed");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* alloc a bit more for unexpected strides to avoid crashes upstream.
|
||||
* FIXME: if we get an unrounded stride, the image will be displayed
|
||||
* distorted, since all upstream elements assume a rounded stride */
|
||||
allocsize =
|
||||
GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) *
|
||||
ximage->ximage->height;
|
||||
ximage->ximage->data = g_malloc (allocsize);
|
||||
GST_ROUND_UP_4 (data->ximage->bytes_per_line) * data->ximage->height;
|
||||
data->ximage->data = g_malloc (allocsize);
|
||||
GST_LOG_OBJECT (ximagesink,
|
||||
"non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
|
||||
"stride %d", ximage->size, allocsize, ximage->width,
|
||||
ximage->ximage->bytes_per_line);
|
||||
"stride %d", data->size, allocsize, data->width,
|
||||
data->ximage->bytes_per_line);
|
||||
|
||||
XSync (ximagesink->xcontext->disp, FALSE);
|
||||
}
|
||||
|
@ -552,30 +507,35 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
|||
|
||||
succeeded = TRUE;
|
||||
|
||||
GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
|
||||
GST_BUFFER_SIZE (ximage) = ximage->size;
|
||||
|
||||
/* Keep a ref to our sink */
|
||||
ximage->ximagesink = gst_object_ref (ximagesink);
|
||||
data->ximagesink = gst_object_ref (ximagesink);
|
||||
|
||||
GST_BUFFER_DATA (buffer) = (guchar *) data->ximage->data;
|
||||
GST_BUFFER_SIZE (buffer) = data->size;
|
||||
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
|
||||
beach:
|
||||
if (!succeeded) {
|
||||
gst_ximage_buffer_free (ximage);
|
||||
ximage = NULL;
|
||||
gst_ximage_buffer_free (buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
return ximage;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* This function destroys a GstXImageBuffer handling XShm availability */
|
||||
/* This function destroys a GstBuffer with GstXImageData handling XShm availability */
|
||||
static void
|
||||
gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||
GstXImageBuffer * ximage)
|
||||
gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink, GstBuffer * ximage)
|
||||
{
|
||||
GstXImageData *data;
|
||||
|
||||
g_return_if_fail (ximage != NULL);
|
||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||
|
||||
data = GET_XDATA (ximage);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
/* Hold the object lock to ensure the XContext doesn't disappear */
|
||||
GST_OBJECT_LOCK (ximagesink);
|
||||
|
||||
|
@ -588,8 +548,8 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
|||
if (!ximagesink->xcontext) {
|
||||
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
|
||||
#ifdef HAVE_XSHM
|
||||
if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (ximage->SHMInfo.shmaddr);
|
||||
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (data->SHMInfo.shmaddr);
|
||||
}
|
||||
#endif
|
||||
goto beach;
|
||||
|
@ -599,19 +559,19 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
|||
|
||||
#ifdef HAVE_XSHM
|
||||
if (ximagesink->xcontext->use_xshm) {
|
||||
if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
|
||||
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
XShmDetach (ximagesink->xcontext->disp, &data->SHMInfo);
|
||||
XSync (ximagesink->xcontext->disp, 0);
|
||||
shmdt (ximage->SHMInfo.shmaddr);
|
||||
shmdt (data->SHMInfo.shmaddr);
|
||||
}
|
||||
if (ximage->ximage)
|
||||
XDestroyImage (ximage->ximage);
|
||||
if (data->ximage)
|
||||
XDestroyImage (data->ximage);
|
||||
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
if (ximage->ximage) {
|
||||
XDestroyImage (ximage->ximage);
|
||||
if (data->ximage) {
|
||||
XDestroyImage (data->ximage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,11 +582,13 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
|||
beach:
|
||||
GST_OBJECT_UNLOCK (ximagesink);
|
||||
|
||||
if (ximage->ximagesink) {
|
||||
if (data->ximagesink) {
|
||||
/* Release the ref to our sink */
|
||||
ximage->ximagesink = NULL;
|
||||
data->ximagesink = NULL;
|
||||
gst_object_unref (ximagesink);
|
||||
}
|
||||
g_slice_free (GstXImageData, data);
|
||||
ximage->owner_priv = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -669,8 +631,9 @@ gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
|
|||
|
||||
/* This function puts a GstXImageBuffer on a GstXImageSink's window */
|
||||
static gboolean
|
||||
gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||
gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
|
||||
{
|
||||
GstXImageData *data;
|
||||
GstVideoRectangle src, dst, result;
|
||||
gboolean draw_border = FALSE;
|
||||
|
||||
|
@ -698,8 +661,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
|
||||
}
|
||||
GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
|
||||
ximagesink->cur_image =
|
||||
GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage)));
|
||||
ximagesink->cur_image = gst_buffer_ref (ximage);
|
||||
}
|
||||
|
||||
/* Expose sends a NULL image, we take the latest frame */
|
||||
|
@ -713,8 +675,9 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
}
|
||||
}
|
||||
|
||||
src.w = ximage->width;
|
||||
src.h = ximage->height;
|
||||
data = GET_XDATA (ximage);
|
||||
src.w = data->width;
|
||||
src.h = data->height;
|
||||
dst.w = ximagesink->xwindow->width;
|
||||
dst.h = ximagesink->xwindow->height;
|
||||
|
||||
|
@ -734,7 +697,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
||||
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
||||
XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
||||
ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
|
||||
ximagesink->xwindow->gc, data->ximage, 0, 0, result.x, result.y,
|
||||
result.w, result.h, FALSE);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
|
@ -744,7 +707,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
||||
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
||||
XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
||||
ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
|
||||
ximagesink->xwindow->gc, data->ximage, 0, 0, result.x, result.y,
|
||||
result.w, result.h);
|
||||
}
|
||||
|
||||
|
@ -853,7 +816,7 @@ gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
|
|||
|
||||
xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
|
||||
ximagesink->xcontext->root,
|
||||
0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black);
|
||||
0, 0, width, height, 0, 0, ximagesink->xcontext->black);
|
||||
|
||||
/* We have to do that to prevent X from redrawing the background on
|
||||
ConfigureNotify. This takes away flickering of video when resizing. */
|
||||
|
@ -1413,11 +1376,10 @@ gst_ximagesink_xcontext_clear (GstXImageSink * ximagesink)
|
|||
static void
|
||||
gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
|
||||
{
|
||||
|
||||
g_mutex_lock (ximagesink->pool_lock);
|
||||
|
||||
while (ximagesink->buffer_pool) {
|
||||
GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
|
||||
GstBuffer *ximage = ximagesink->buffer_pool->data;
|
||||
|
||||
ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
|
||||
ximagesink->buffer_pool);
|
||||
|
@ -1541,13 +1503,16 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
/* If our ximage has changed we destroy it, next chain iteration will create
|
||||
a new one */
|
||||
if ((ximagesink->ximage) &&
|
||||
((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) ||
|
||||
(GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) {
|
||||
GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
|
||||
ximagesink->ximage);
|
||||
gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
|
||||
ximagesink->ximage = NULL;
|
||||
if ((ximagesink->ximage)) {
|
||||
GstXImageData *data = GET_XDATA (ximagesink->ximage);
|
||||
|
||||
if (((GST_VIDEO_SINK_WIDTH (ximagesink) != data->width) ||
|
||||
(GST_VIDEO_SINK_HEIGHT (ximagesink) != data->height))) {
|
||||
GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
|
||||
ximagesink->ximage);
|
||||
gst_buffer_unref (ximagesink->ximage);
|
||||
ximagesink->ximage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -1668,13 +1633,16 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
if (!ximagesink->xcontext)
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
#if 0
|
||||
/* If this buffer has been allocated using our buffer management we simply
|
||||
put the ximage which is in the PRIVATE pointer */
|
||||
if (GST_IS_XIMAGE_BUFFER (buf)) {
|
||||
GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
|
||||
if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
|
||||
goto no_window;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Else we have to copy the data into our private image, */
|
||||
/* if we have one... */
|
||||
GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
|
||||
|
@ -1686,10 +1654,11 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
/* The create method should have posted an informative error */
|
||||
goto no_ximage;
|
||||
|
||||
if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) {
|
||||
if (GST_BUFFER_SIZE (ximagesink->ximage) < GST_BUFFER_SIZE (buf)) {
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
ximagesink->ximage->width, ximagesink->ximage->height),
|
||||
GET_XDATA (ximagesink->ximage)->width,
|
||||
GET_XDATA (ximagesink->ximage)->height),
|
||||
("XServer allocated buffer size did not match input buffer"));
|
||||
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
|
||||
|
@ -1698,7 +1667,7 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
}
|
||||
}
|
||||
memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
|
||||
MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
|
||||
MIN (GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (ximagesink->ximage)));
|
||||
if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
|
||||
goto no_window;
|
||||
}
|
||||
|
@ -1752,7 +1721,7 @@ gst_ximagesink_event (GstBaseSink * sink, GstEvent * event)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Buffer management
|
||||
*
|
||||
* The buffer_alloc function must either return a buffer with given size and
|
||||
|
@ -1938,6 +1907,7 @@ alloc:
|
|||
beach:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interfaces stuff */
|
||||
|
||||
|
@ -2436,8 +2406,10 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
|
|||
|
||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
|
||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
|
||||
#if 0
|
||||
gstbasesink_class->buffer_alloc =
|
||||
GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
|
||||
#endif
|
||||
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
|
||||
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_ximagesink_event);
|
||||
|
||||
|
@ -2490,11 +2462,6 @@ gst_ximagesink_get_type (void)
|
|||
&navigation_info);
|
||||
g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
|
||||
&overlay_info);
|
||||
|
||||
/* register type and create class in a more safe place instead of at
|
||||
* runtime since the type registration and class creation is not
|
||||
* threadsafe. */
|
||||
g_type_class_ref (gst_ximage_buffer_get_type ());
|
||||
}
|
||||
|
||||
return ximagesink_type;
|
||||
|
|
|
@ -52,8 +52,7 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstXContext GstXContext;
|
||||
typedef struct _GstXWindow GstXWindow;
|
||||
|
||||
typedef struct _GstXImageBuffer GstXImageBuffer;
|
||||
typedef struct _GstXImageBufferClass GstXImageBufferClass;
|
||||
typedef struct _GstXImageData GstXImageData;
|
||||
|
||||
typedef struct _GstXImageSink GstXImageSink;
|
||||
typedef struct _GstXImageSinkClass GstXImageSinkClass;
|
||||
|
@ -129,20 +128,19 @@ struct _GstXWindow
|
|||
GC gc;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* GstXImageBuffer:
|
||||
* GstXImageData:
|
||||
* @ximagesink: a reference to our #GstXImageSink
|
||||
* @ximage: the XImage of this buffer
|
||||
* @width: the width in pixels of XImage @ximage
|
||||
* @height: the height in pixels of XImage @ximage
|
||||
* @size: the size in bytes of XImage @ximage
|
||||
*
|
||||
* Subclass of #GstBuffer containing additional information about an XImage.
|
||||
* Structure with additional information about an XImage.
|
||||
*/
|
||||
struct _GstXImageBuffer
|
||||
struct _GstXImageData
|
||||
{
|
||||
GstBuffer buffer;
|
||||
|
||||
/* Reference to the ximagesink we belong to */
|
||||
GstXImageSink *ximagesink;
|
||||
|
||||
|
@ -194,8 +192,8 @@ struct _GstXImageSink
|
|||
|
||||
GstXContext *xcontext;
|
||||
GstXWindow *xwindow;
|
||||
GstXImageBuffer *ximage;
|
||||
GstXImageBuffer *cur_image;
|
||||
GstBuffer *ximage;
|
||||
GstBuffer *cur_image;
|
||||
|
||||
GThread *event_thread;
|
||||
gboolean running;
|
||||
|
|
|
@ -143,10 +143,8 @@ MotifWmHints, MwmHints;
|
|||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||
|
||||
static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
|
||||
|
||||
static GstBufferClass *xvimage_buffer_parent_class = NULL;
|
||||
static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
|
||||
|
||||
static void gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
|
||||
GstBuffer * xvimage);
|
||||
static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
|
||||
xvimagesink);
|
||||
static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
|
||||
|
@ -200,99 +198,19 @@ static GstVideoSinkClass *parent_class = NULL;
|
|||
/* ============================================================= */
|
||||
|
||||
/* xvimage buffers */
|
||||
|
||||
#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type())
|
||||
|
||||
#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER))
|
||||
#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer))
|
||||
#define GST_XVIMAGE_BUFFER_CAST(obj) ((GstXvImageBuffer *)(obj))
|
||||
|
||||
/* This function destroys a GstXvImage handling XShm availability */
|
||||
static void
|
||||
gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
|
||||
{
|
||||
GstXvImageSink *xvimagesink;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
|
||||
|
||||
xvimagesink = xvimage->xvimagesink;
|
||||
if (G_UNLIKELY (xvimagesink == NULL))
|
||||
goto no_sink;
|
||||
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
|
||||
GST_OBJECT_LOCK (xvimagesink);
|
||||
|
||||
/* If the destroyed image is the current one we destroy our reference too */
|
||||
if (xvimagesink->cur_image == xvimage)
|
||||
xvimagesink->cur_image = NULL;
|
||||
|
||||
/* 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 (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (xvimage->SHMInfo.shmaddr);
|
||||
}
|
||||
#endif
|
||||
goto beach;
|
||||
}
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
|
||||
xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
|
||||
XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo);
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
shmdt (xvimage->SHMInfo.shmaddr);
|
||||
}
|
||||
if (xvimage->xvimage)
|
||||
XFree (xvimage->xvimage);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
if (xvimage->xvimage) {
|
||||
if (xvimage->xvimage->data) {
|
||||
g_free (xvimage->xvimage->data);
|
||||
}
|
||||
XFree (xvimage->xvimage);
|
||||
}
|
||||
}
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
beach:
|
||||
GST_OBJECT_UNLOCK (xvimagesink);
|
||||
xvimage->xvimagesink = NULL;
|
||||
gst_object_unref (xvimagesink);
|
||||
|
||||
GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->finalize (GST_MINI_OBJECT
|
||||
(xvimage));
|
||||
|
||||
return;
|
||||
|
||||
no_sink:
|
||||
{
|
||||
GST_WARNING ("no sink found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#define GET_XVDATA(buf) ((GstXvImageData *) (GST_BUFFER_CAST(buf)->owner_priv))
|
||||
|
||||
static void
|
||||
gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
|
||||
gst_xvimage_buffer_dispose (GstBuffer * xvimage)
|
||||
{
|
||||
GstXvImageData *data = NULL;
|
||||
GstXvImageSink *xvimagesink;
|
||||
gboolean running;
|
||||
|
||||
xvimagesink = xvimage->xvimagesink;
|
||||
data = GET_XVDATA (xvimage);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
xvimagesink = data->xvimagesink;
|
||||
if (G_UNLIKELY (xvimagesink == NULL))
|
||||
goto no_sink;
|
||||
|
||||
|
@ -302,22 +220,22 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
|
|||
running = xvimagesink->running;
|
||||
GST_OBJECT_UNLOCK (xvimagesink);
|
||||
|
||||
/* If our geometry changed we can't reuse that image. */
|
||||
if (running == FALSE) {
|
||||
GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
|
||||
gst_xvimage_buffer_destroy (xvimage);
|
||||
} else if ((xvimage->width != xvimagesink->video_width) ||
|
||||
(xvimage->height != xvimagesink->video_height)) {
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||
} else if ((data->width != xvimagesink->video_width) ||
|
||||
(data->height != xvimagesink->video_height)) {
|
||||
/* If our geometry changed we can't reuse that image. */
|
||||
GST_LOG_OBJECT (xvimage,
|
||||
"destroy image as its size changed %dx%d vs current %dx%d",
|
||||
xvimage->width, xvimage->height,
|
||||
data->width, data->height,
|
||||
xvimagesink->video_width, xvimagesink->video_height);
|
||||
gst_xvimage_buffer_destroy (xvimage);
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||
} else {
|
||||
/* In that case we can reuse the image and add it to our image pool. */
|
||||
GST_LOG_OBJECT (xvimage, "recycling image in pool");
|
||||
/* need to increment the refcount again to recycle */
|
||||
gst_buffer_ref (GST_BUFFER_CAST (xvimage));
|
||||
gst_buffer_ref (xvimage);
|
||||
g_mutex_lock (xvimagesink->pool_lock);
|
||||
xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
|
||||
xvimage);
|
||||
|
@ -333,56 +251,16 @@ no_sink:
|
|||
}
|
||||
|
||||
static void
|
||||
gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
|
||||
gst_xvimage_buffer_free (GstBuffer * xvimage)
|
||||
{
|
||||
GstXvImageData *data = GET_XVDATA (xvimage);
|
||||
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
/* make sure it is not recycled */
|
||||
xvimage->width = -1;
|
||||
xvimage->height = -1;
|
||||
gst_buffer_unref (GST_BUFFER (xvimage));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
|
||||
{
|
||||
#ifdef HAVE_XSHM
|
||||
xvimage->SHMInfo.shmaddr = ((void *) -1);
|
||||
xvimage->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
|
||||
{
|
||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
||||
|
||||
xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
|
||||
|
||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
||||
gst_xvimage_buffer_finalize;
|
||||
}
|
||||
|
||||
static GType
|
||||
gst_xvimage_buffer_get_type (void)
|
||||
{
|
||||
static GType _gst_xvimage_buffer_type;
|
||||
|
||||
if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) {
|
||||
static const GTypeInfo xvimage_buffer_info = {
|
||||
sizeof (GstBufferClass),
|
||||
NULL,
|
||||
NULL,
|
||||
gst_xvimage_buffer_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstXvImageBuffer),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_xvimage_buffer_init,
|
||||
NULL
|
||||
};
|
||||
_gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
||||
"GstXvImageBuffer", &xvimage_buffer_info, 0);
|
||||
}
|
||||
return _gst_xvimage_buffer_type;
|
||||
data->width = -1;
|
||||
data->height = -1;
|
||||
gst_buffer_unref (xvimage);
|
||||
}
|
||||
|
||||
/* X11 stuff */
|
||||
|
@ -505,10 +383,11 @@ beach:
|
|||
#endif /* HAVE_XSHM */
|
||||
|
||||
/* This function handles GstXvImage creation depending on XShm availability */
|
||||
static GstXvImageBuffer *
|
||||
static GstBuffer *
|
||||
gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||
{
|
||||
GstXvImageBuffer *xvimage = NULL;
|
||||
GstBuffer *buffer = NULL;
|
||||
GstXvImageData *data = NULL;
|
||||
GstStructure *structure = NULL;
|
||||
gboolean succeeded = FALSE;
|
||||
int (*handler) (Display *, XErrorEvent *);
|
||||
|
@ -518,29 +397,37 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
if (caps == NULL)
|
||||
return NULL;
|
||||
|
||||
xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
|
||||
GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer");
|
||||
data = g_slice_new0 (GstXvImageData);
|
||||
#ifdef HAVE_XSHM
|
||||
data->SHMInfo.shmaddr = ((void *) -1);
|
||||
data->SHMInfo.shmid = -1;
|
||||
#endif
|
||||
|
||||
buffer = gst_buffer_new ();
|
||||
GST_DEBUG_OBJECT (xvimagesink, "Creating new XvImageBuffer");
|
||||
GST_MINI_OBJECT_CAST (buffer)->dispose =
|
||||
(GstMiniObjectDisposeFunction) gst_xvimage_buffer_dispose;
|
||||
buffer->owner_priv = data;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
|
||||
!gst_structure_get_int (structure, "height", &xvimage->height)) {
|
||||
if (!gst_structure_get_int (structure, "width", &data->width) ||
|
||||
!gst_structure_get_int (structure, "height", &data->height)) {
|
||||
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
|
||||
xvimage->height);
|
||||
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", data->width, data->height);
|
||||
|
||||
xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
||||
if (xvimage->im_format == -1) {
|
||||
data->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
||||
if (data->im_format == -1) {
|
||||
GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height), ("Invalid input caps"));
|
||||
data->width, data->height), ("Invalid input caps"));
|
||||
goto beach_unlocked;
|
||||
}
|
||||
xvimage->xvimagesink = gst_object_ref (xvimagesink);
|
||||
data->xvimagesink = gst_object_ref (xvimagesink);
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
||||
|
@ -552,11 +439,10 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
if (xvimagesink->xcontext->use_xshm) {
|
||||
int expected_size;
|
||||
|
||||
xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
|
||||
data->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xcontext->xv_port_id,
|
||||
xvimage->im_format, NULL,
|
||||
xvimage->width, xvimage->height, &xvimage->SHMInfo);
|
||||
if (!xvimage->xvimage || error_caught) {
|
||||
data->im_format, NULL, data->width, data->height, &data->SHMInfo);
|
||||
if (!data->xvimage || error_caught) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
/* Reset error handler */
|
||||
error_caught = FALSE;
|
||||
|
@ -564,20 +450,20 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
/* Push an error */
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height),
|
||||
data->width, data->height),
|
||||
("could not XvShmCreateImage a %dx%d image",
|
||||
xvimage->width, xvimage->height));
|
||||
data->width, data->height));
|
||||
goto beach_unlocked;
|
||||
}
|
||||
|
||||
/* we have to use the returned data_size for our shm size */
|
||||
xvimage->size = xvimage->xvimage->data_size;
|
||||
data->size = data->xvimage->data_size;
|
||||
GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
|
||||
xvimage->size);
|
||||
data->size);
|
||||
|
||||
/* calculate the expected size. This is only for sanity checking the
|
||||
* number we get from X. */
|
||||
switch (xvimage->im_format) {
|
||||
switch (data->im_format) {
|
||||
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
||||
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
|
||||
{
|
||||
|
@ -586,17 +472,17 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
guint plane;
|
||||
|
||||
offsets[0] = 0;
|
||||
pitches[0] = GST_ROUND_UP_4 (xvimage->width);
|
||||
offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (xvimage->height);
|
||||
pitches[1] = GST_ROUND_UP_8 (xvimage->width) / 2;
|
||||
pitches[0] = GST_ROUND_UP_4 (data->width);
|
||||
offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (data->height);
|
||||
pitches[1] = GST_ROUND_UP_8 (data->width) / 2;
|
||||
offsets[2] =
|
||||
offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2;
|
||||
offsets[1] + pitches[1] * GST_ROUND_UP_2 (data->height) / 2;
|
||||
pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
|
||||
|
||||
expected_size =
|
||||
offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2;
|
||||
offsets[2] + pitches[2] * GST_ROUND_UP_2 (data->height) / 2;
|
||||
|
||||
for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
|
||||
for (plane = 0; plane < data->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]);
|
||||
|
@ -605,64 +491,63 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
}
|
||||
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
|
||||
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||
expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
|
||||
expected_size = data->height * GST_ROUND_UP_4 (data->width * 2);
|
||||
break;
|
||||
default:
|
||||
expected_size = 0;
|
||||
break;
|
||||
}
|
||||
if (expected_size != 0 && xvimage->size != expected_size) {
|
||||
if (expected_size != 0 && data->size != expected_size) {
|
||||
GST_WARNING_OBJECT (xvimagesink,
|
||||
"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
|
||||
xvimage->size, expected_size);
|
||||
data->size, expected_size);
|
||||
}
|
||||
|
||||
/* Be verbose about our XvImage stride */
|
||||
{
|
||||
guint plane;
|
||||
|
||||
for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
|
||||
for (plane = 0; plane < data->xvimage->num_planes; plane++) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
|
||||
"offset of %d", plane, xvimage->xvimage->pitches[plane],
|
||||
xvimage->xvimage->offsets[plane]);
|
||||
"offset of %d", plane, data->xvimage->pitches[plane],
|
||||
data->xvimage->offsets[plane]);
|
||||
}
|
||||
}
|
||||
|
||||
xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
|
||||
IPC_CREAT | 0777);
|
||||
if (xvimage->SHMInfo.shmid == -1) {
|
||||
data->SHMInfo.shmid = shmget (IPC_PRIVATE, data->size, IPC_CREAT | 0777);
|
||||
if (data->SHMInfo.shmid == -1) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height),
|
||||
data->width, data->height),
|
||||
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
||||
xvimage->size));
|
||||
data->size));
|
||||
goto beach_unlocked;
|
||||
}
|
||||
|
||||
xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
|
||||
if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
|
||||
data->SHMInfo.shmaddr = shmat (data->SHMInfo.shmid, NULL, 0);
|
||||
if (data->SHMInfo.shmaddr == ((void *) -1)) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height),
|
||||
data->width, data->height),
|
||||
("Failed to shmat: %s", g_strerror (errno)));
|
||||
/* Clean up the shared memory segment */
|
||||
shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
goto beach_unlocked;
|
||||
}
|
||||
|
||||
xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
|
||||
xvimage->SHMInfo.readOnly = FALSE;
|
||||
data->xvimage->data = data->SHMInfo.shmaddr;
|
||||
data->SHMInfo.readOnly = FALSE;
|
||||
|
||||
if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
|
||||
if (XShmAttach (xvimagesink->xcontext->disp, &data->SHMInfo) == 0) {
|
||||
/* Clean up the shared memory segment */
|
||||
shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height), ("Failed to XShmAttach"));
|
||||
data->width, data->height), ("Failed to XShmAttach"));
|
||||
goto beach_unlocked;
|
||||
}
|
||||
|
||||
|
@ -671,17 +556,17 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
/* 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 (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
|
||||
xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
|
||||
data->SHMInfo.shmid, data->SHMInfo.shmseg);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
|
||||
data->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xcontext->xv_port_id,
|
||||
xvimage->im_format, NULL, xvimage->width, xvimage->height);
|
||||
if (!xvimage->xvimage || error_caught) {
|
||||
data->im_format, NULL, data->width, data->height);
|
||||
if (!data->xvimage || error_caught) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
/* Reset error handler */
|
||||
error_caught = FALSE;
|
||||
|
@ -689,15 +574,14 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
/* Push an error */
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create outputimage buffer of %dx%d pixels",
|
||||
xvimage->width, xvimage->height),
|
||||
("could not XvCreateImage a %dx%d image",
|
||||
xvimage->width, xvimage->height));
|
||||
data->width, data->height),
|
||||
("could not XvCreateImage a %dx%d image", data->width, data->height));
|
||||
goto beach_unlocked;
|
||||
}
|
||||
|
||||
/* we have to use the returned data_size for our image size */
|
||||
xvimage->size = xvimage->xvimage->data_size;
|
||||
xvimage->xvimage->data = g_malloc (xvimage->size);
|
||||
data->size = data->xvimage->data_size;
|
||||
data->xvimage->data = g_malloc (data->size);
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
}
|
||||
|
@ -708,18 +592,93 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
|||
|
||||
succeeded = TRUE;
|
||||
|
||||
GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
|
||||
GST_BUFFER_SIZE (xvimage) = xvimage->size;
|
||||
GST_BUFFER_DATA (buffer) = (guchar *) data->xvimage->data;
|
||||
GST_BUFFER_SIZE (buffer) = data->size;
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
beach_unlocked:
|
||||
if (!succeeded) {
|
||||
gst_xvimage_buffer_free (xvimage);
|
||||
xvimage = NULL;
|
||||
gst_xvimage_buffer_free (buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
return xvimage;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* This function destroys a GstXvImage handling XShm availability */
|
||||
static void
|
||||
gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
|
||||
GstBuffer * xvimage)
|
||||
{
|
||||
GstXvImageData *data = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
|
||||
|
||||
g_return_if_fail (xvimage != NULL);
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
|
||||
data = GET_XVDATA (xvimage);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
GST_OBJECT_LOCK (xvimagesink);
|
||||
|
||||
/* If the destroyed image is the current one we destroy our reference too */
|
||||
if (xvimagesink->cur_image == xvimage)
|
||||
xvimagesink->cur_image = NULL;
|
||||
|
||||
/* 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 (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
shmdt (data->SHMInfo.shmaddr);
|
||||
}
|
||||
#endif
|
||||
goto beach;
|
||||
}
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
|
||||
data->SHMInfo.shmid, data->SHMInfo.shmseg);
|
||||
XShmDetach (xvimagesink->xcontext->disp, &data->SHMInfo);
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
shmdt (data->SHMInfo.shmaddr);
|
||||
}
|
||||
if (data->xvimage)
|
||||
XFree (data->xvimage);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
if (data->xvimage) {
|
||||
if (data->xvimage->data) {
|
||||
g_free (data->xvimage->data);
|
||||
}
|
||||
XFree (data->xvimage);
|
||||
}
|
||||
}
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
beach:
|
||||
GST_OBJECT_UNLOCK (xvimagesink);
|
||||
|
||||
data->xvimagesink = NULL;
|
||||
gst_object_unref (xvimagesink);
|
||||
|
||||
g_slice_free (GstXvImageData, data);
|
||||
xvimage->owner_priv = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are called with the x_lock taken */
|
||||
|
@ -769,9 +728,9 @@ gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
|
|||
/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
|
||||
* if no window was available */
|
||||
static gboolean
|
||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||
GstXvImageBuffer * xvimage)
|
||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
||||
{
|
||||
GstXvImageData *data;
|
||||
GstVideoRectangle result;
|
||||
gboolean draw_border = FALSE;
|
||||
|
||||
|
@ -794,11 +753,10 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
if (xvimage && xvimagesink->cur_image != xvimage) {
|
||||
if (xvimagesink->cur_image) {
|
||||
GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
|
||||
gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
|
||||
gst_buffer_unref (xvimagesink->cur_image);
|
||||
}
|
||||
GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
|
||||
xvimagesink->cur_image =
|
||||
GST_XVIMAGE_BUFFER_CAST (gst_buffer_ref (GST_BUFFER_CAST (xvimage)));
|
||||
xvimagesink->cur_image = gst_buffer_ref (xvimage);
|
||||
}
|
||||
|
||||
/* Expose sends a NULL image, we take the latest frame */
|
||||
|
@ -837,19 +795,21 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
xvimagesink->redraw_border = FALSE;
|
||||
}
|
||||
|
||||
data = GET_XVDATA (xvimage);
|
||||
|
||||
/* We scale to the window's geometry */
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
GST_LOG_OBJECT (xvimagesink,
|
||||
"XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
|
||||
GST_PTR_FORMAT,
|
||||
xvimage->width, xvimage->height,
|
||||
data->width, data->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, xvimage->xvimage,
|
||||
xvimagesink->xwindow->gc, data->xvimage,
|
||||
xvimagesink->disp_x, xvimagesink->disp_y,
|
||||
xvimagesink->disp_width, xvimagesink->disp_height,
|
||||
result.x, result.y, result.w, result.h, FALSE);
|
||||
|
@ -859,7 +819,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
XvPutImage (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xcontext->xv_port_id,
|
||||
xvimagesink->xwindow->win,
|
||||
xvimagesink->xwindow->gc, xvimage->xvimage,
|
||||
xvimagesink->xwindow->gc, data->xvimage,
|
||||
xvimagesink->disp_x, xvimagesink->disp_y,
|
||||
xvimagesink->disp_width, xvimagesink->disp_height,
|
||||
result.x, result.y, result.w, result.h);
|
||||
|
@ -1734,6 +1694,7 @@ gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
|
|||
ratio = 4.0 * 576 / (3.0 * 720);
|
||||
}
|
||||
GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
|
||||
|
||||
/* now find the one from par[][2] with the lowest delta to the real one */
|
||||
delta = DELTA (0);
|
||||
index = 0;
|
||||
|
@ -2013,7 +1974,7 @@ gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
|
|||
g_mutex_lock (xvimagesink->pool_lock);
|
||||
|
||||
while (xvimagesink->image_pool) {
|
||||
GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
|
||||
GstBuffer *xvimage = xvimagesink->image_pool->data;
|
||||
|
||||
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
|
||||
xvimagesink->image_pool);
|
||||
|
@ -2212,17 +2173,18 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
/* We renew our xvimage only if size or format changed;
|
||||
* the xvimage is the same size as the video pixel size */
|
||||
if ((xvimagesink->xvimage) &&
|
||||
((im_format != xvimagesink->xvimage->im_format) ||
|
||||
(video_width != xvimagesink->xvimage->width) ||
|
||||
(video_height != xvimagesink->xvimage->height))) {
|
||||
GST_DEBUG_OBJECT (xvimagesink,
|
||||
"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
|
||||
GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
|
||||
GST_FOURCC_ARGS (im_format));
|
||||
GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
|
||||
gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
|
||||
xvimagesink->xvimage = NULL;
|
||||
if ((xvimagesink->xvimage)) {
|
||||
GstXvImageData *data = GET_XVDATA (xvimagesink->xvimage);
|
||||
|
||||
if (((im_format != data->im_format) ||
|
||||
(video_width != data->width) || (video_height != data->height))) {
|
||||
GST_DEBUG_OBJECT (xvimagesink,
|
||||
"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
|
||||
GST_FOURCC_ARGS (data->im_format), GST_FOURCC_ARGS (im_format));
|
||||
GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
|
||||
gst_buffer_unref (xvimagesink->xvimage);
|
||||
xvimagesink->xvimage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
@ -2362,6 +2324,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
|
||||
xvimagesink = GST_XVIMAGESINK (vsink);
|
||||
|
||||
#if 0
|
||||
/* If this buffer has been allocated using our buffer management we simply
|
||||
put the ximage which is in the PRIVATE pointer */
|
||||
if (GST_IS_XVIMAGE_BUFFER (buf)) {
|
||||
|
@ -2369,7 +2332,9 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
if (!gst_xvimagesink_xvimage_put (xvimagesink,
|
||||
GST_XVIMAGE_BUFFER_CAST (buf)))
|
||||
goto no_window;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink,
|
||||
"slow copy into bufferpool buffer %p", buf);
|
||||
/* Else we have to copy the data into our private image, */
|
||||
|
@ -2384,21 +2349,22 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
|||
/* The create method should have posted an informative error */
|
||||
goto no_image;
|
||||
|
||||
if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
|
||||
if (GST_BUFFER_SIZE (xvimagesink->xvimage) < GST_BUFFER_SIZE (buf)) {
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||
("Failed to create output image buffer of %dx%d pixels",
|
||||
xvimagesink->xvimage->width, xvimagesink->xvimage->height),
|
||||
GET_XVDATA (xvimagesink->xvimage)->width,
|
||||
GET_XVDATA (xvimagesink->xvimage)->height),
|
||||
("XServer allocated buffer size did not match input buffer"));
|
||||
|
||||
gst_xvimage_buffer_destroy (xvimagesink->xvimage);
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
|
||||
xvimagesink->xvimage = NULL;
|
||||
goto no_image;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (xvimagesink->xvimage->xvimage->data,
|
||||
memcpy (GST_BUFFER_DATA (xvimagesink->xvimage),
|
||||
GST_BUFFER_DATA (buf),
|
||||
MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
|
||||
MIN (GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (xvimagesink->xvimage)));
|
||||
|
||||
if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
|
||||
goto no_window;
|
||||
|
@ -2452,6 +2418,7 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Buffer management */
|
||||
|
||||
static GstCaps *
|
||||
|
@ -2508,7 +2475,7 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
|
|||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstXvImageSink *xvimagesink;
|
||||
GstXvImageBuffer *xvimage = NULL;
|
||||
GstXvImageData *xvimage = NULL;
|
||||
GstCaps *intersection = NULL;
|
||||
GstStructure *structure = NULL;
|
||||
gint width, height, image_format;
|
||||
|
@ -2709,6 +2676,7 @@ invalid_caps:
|
|||
goto beach;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interfaces stuff */
|
||||
|
||||
|
@ -3674,8 +3642,10 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
|
|||
|
||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
|
||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
|
||||
#if 0
|
||||
gstbasesink_class->buffer_alloc =
|
||||
GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
|
||||
#endif
|
||||
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
|
||||
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event);
|
||||
|
||||
|
@ -3749,12 +3719,6 @@ gst_xvimagesink_get_type (void)
|
|||
&colorbalance_info);
|
||||
g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
|
||||
&propertyprobe_info);
|
||||
|
||||
|
||||
/* register type and create class in a more safe place instead of at
|
||||
* runtime since the type registration and class creation is not
|
||||
* threadsafe. */
|
||||
g_type_class_ref (gst_xvimage_buffer_get_type ());
|
||||
}
|
||||
|
||||
return xvimagesink_type;
|
||||
|
|
|
@ -58,8 +58,7 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstXContext GstXContext;
|
||||
typedef struct _GstXWindow GstXWindow;
|
||||
typedef struct _GstXvImageFormat GstXvImageFormat;
|
||||
typedef struct _GstXvImageBuffer GstXvImageBuffer;
|
||||
typedef struct _GstXvImageBufferClass GstXvImageBufferClass;
|
||||
typedef struct _GstXvImageData GstXvImageData;
|
||||
|
||||
typedef struct _GstXvImageSink GstXvImageSink;
|
||||
typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
|
||||
|
@ -163,7 +162,7 @@ struct _GstXvImageFormat {
|
|||
};
|
||||
|
||||
/**
|
||||
* GstXImageBuffer:
|
||||
* GstXImageData:
|
||||
* @xvimagesink: a reference to our #GstXvImageSink
|
||||
* @xvimage: the XvImage of this buffer
|
||||
* @width: the width in pixels of XvImage @xvimage
|
||||
|
@ -171,11 +170,9 @@ struct _GstXvImageFormat {
|
|||
* @im_format: the image format of XvImage @xvimage
|
||||
* @size: the size in bytes of XvImage @xvimage
|
||||
*
|
||||
* Subclass of #GstBuffer containing additional information about an XvImage.
|
||||
* Structure with additional information about an XvImage.
|
||||
*/
|
||||
struct _GstXvImageBuffer {
|
||||
GstBuffer buffer;
|
||||
|
||||
struct _GstXvImageData {
|
||||
/* Reference to the xvimagesink we belong to */
|
||||
GstXvImageSink *xvimagesink;
|
||||
|
||||
|
@ -234,12 +231,13 @@ struct _GstXvImageSink {
|
|||
|
||||
GstXContext *xcontext;
|
||||
GstXWindow *xwindow;
|
||||
GstXvImageBuffer *xvimage;
|
||||
GstXvImageBuffer *cur_image;
|
||||
GstBuffer *xvimage;
|
||||
GstBuffer *cur_image;
|
||||
|
||||
GThread *event_thread;
|
||||
gboolean running;
|
||||
|
||||
/* Framerate numerator and denominator */
|
||||
gint fps_n;
|
||||
gint fps_d;
|
||||
|
||||
|
|
Loading…
Reference in a new issue