-#ifdef GST_EXT_XV_ENHANCEMENT
-/* This function handles GstXvImage creation depending on XShm availability */
-static GstXvImageBuffer *
-gst_xvimagesink_xvimage_new_for_last_image (GstXvImageSink * xvimagesink, gint im_format)
-{
- GstXvImageBuffer *xvimage = NULL;
- GstStructure *structure = NULL;
- gboolean succeeded = FALSE;
- int (*handler) (Display *, XErrorEvent *);
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
- GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer for last image");
-
- xvimage->width = xvimagesink->xvimage->width;
- xvimage->height = xvimagesink->xvimage->height;
-
- GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
- xvimage->height);
-
- xvimage->im_format = im_format;
- if (xvimage->im_format == -1) {
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height), ("Invalid input caps"));
- goto beach_unlocked;
- }
- xvimage->xvimagesink = gst_object_ref (xvimagesink);
-
- g_mutex_lock (xvimagesink->x_lock);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- int expected_size;
-
- xvimage->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) {
- g_mutex_unlock (xvimagesink->x_lock);
-
- /* Reset error flag */
- error_caught = FALSE;
-
- /* Push a warning */
- GST_ELEMENT_WARNING (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height),
- ("could not XvShmCreateImage a %dx%d image",
- xvimage->width, xvimage->height));
-
- /* must not change "use_xshm",
- because it causes memory curruption when buffer created by XvShmCreateImage is destroyed */
- goto beach_unlocked;
- }
-
- /* we have to use the returned data_size for our shm size */
- xvimage->size = xvimage->xvimage->data_size;
- GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
- xvimage->size);
-
- /* calculate the expected size. This is only for sanity checking the
- * number we get from X. */
- switch (xvimage->im_format) {
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
- {
- gint pitches[3];
- gint offsets[3];
- 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;
- offsets[2] =
- offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2;
- pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
-
- expected_size =
- offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2;
-
- for (plane = 0; plane < xvimage->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]);
- }
- break;
- }
- case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
- 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);
- break;
- default:
- expected_size = 0;
- break;
- }
- if (expected_size != 0 && xvimage->size != expected_size) {
- GST_WARNING_OBJECT (xvimagesink,
- "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
- xvimage->size, expected_size);
- }
-
- /* Be verbose about our XvImage stride */
- {
- guint plane;
-
- for (plane = 0; plane < xvimage->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]);
- }
- }
-
- xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
- IPC_CREAT | 0777);
- if (xvimage->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),
- ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
- xvimage->size));
- GST_ERROR_OBJECT(xvimagesink, "Failed to shmget: %s", g_strerror (errno));
- goto beach_unlocked;
- }
-
- xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
- if (xvimage->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),
- ("Failed to shmat: %s", g_strerror (errno)));
- /* Clean up the shared memory segment */
- shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
- goto beach_unlocked;
- }
-
- xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
- xvimage->SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
- /* Clean up the shared memory segment */
- shmctl (xvimage->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"));
- goto beach_unlocked;
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- /* 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);
-
- GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
- xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
- } else
-#endif /* HAVE_XSHM */
- {
- xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- xvimage->im_format, NULL, xvimagesink->aligned_width, xvimagesink->aligned_height);
- if (!xvimage->xvimage || error_caught) {
- g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* 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));
- 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);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
- }
-
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- succeeded = TRUE;
-
- GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
- GST_BUFFER_SIZE (xvimage) = xvimage->size;
-
- g_mutex_unlock (xvimagesink->x_lock);
-
-beach_unlocked:
- if (!succeeded) {
- gst_xvimage_buffer_free (xvimage);
- xvimage = NULL;
- }
-
- return xvimage;
-}
-
-static gboolean
-gst_xvimagesink_xvimage_handle_last_buffer (GstXvImageSink * xvimagesink, gint im_format)
-{
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
-
- xvimagesink->last_image = gst_xvimagesink_xvimage_new_for_last_image (xvimagesink, im_format);
- if (!xvimagesink->last_image) {
- /* The create method should have posted an informative error */
- GST_WARNING_OBJECT (xvimagesink, "could not create last image");
- return FALSE;
- }
-
- GST_INFO_OBJECT(xvimagesink, "last_image(%p)->xvimage->data:0x%x, last_image->size:%d",
- xvimagesink->last_image, xvimagesink->last_image->xvimage->data, xvimagesink->last_image->size);
-
- switch (im_format) {
- case GST_MAKE_FOURCC('N', 'V', '1', '2'):
- {
- int i = 0;
- gint y_size = 0;
- char *y_data = xvimagesink->last_image->xvimage->data;
- y_size = xvimagesink->last_image->width * xvimagesink->last_image->height;
- if (xvimagesink->last_image_vaddr[0]) {
- for(i = 0; i < xvimagesink->last_image->height; i++) {
- memcpy (y_data + i*xvimagesink->last_image->width, xvimagesink->last_image_vaddr[0] + i*xvimagesink->aligned_width, xvimagesink->last_image->width);
- }
- }
- if (xvimagesink->last_image_vaddr[1]) {
- for(i = 0; i < xvimagesink->last_image->height/2; i++) {
- memcpy (y_data + y_size + i*xvimagesink->last_image->width, xvimagesink->last_image_vaddr[1] + i*xvimagesink->aligned_width, xvimagesink->last_image->width);
- }
- }
- GST_LOG_OBJECT(xvimagesink, "last image was copied in NV12 format (w:%d, h:%d, y_size:%d", xvimagesink->last_image->width, xvimagesink->last_image->height, y_size);
- break;
- }
- default:
- GST_ERROR_OBJECT(xvimagesink, "Not support format for last image");
- gst_xvimage_buffer_destroy (xvimagesink->last_image);
- xvimagesink->last_image = NULL;
- GST_WARNING_OBJECT (xvimagesink, "could not create last image");
- return FALSE;
- }
-
- return TRUE;
-}
-#endif
-