1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-12-26 05:02:18 +00:00
freebsd-ports/multimedia/gstreamer-plugins/files/patch-sys_v4l_v4lsrc_calls.c
Joe Marcus Clarke 6f32add9a7 The FreeBSD GNOME team is proud to annunce the release of GNOME 2.22.0 for
FreeBSD.  The official GNOME 2.22 release notes can be found at
http://library.gnome.org/misc/release-notes/2.22/ .  On the FreeBSD front,
this release features an updated hal port with support for video4linux
devices, DRM (Direct Rendering), and better support of removable media.  Work
is also underway to tie webkit more closely into GNOME.  As part of the
GNOME 2.22 upgrade, GStreamer received a rather large upgrade as well.
Be sure to consult UPDATING on the proper steps to upgrade all of your
GNOME ports.

This release would not have been possible without the contributions and
testing efforts of the following people:

Pawel Worach
kan
edwin
Peter Ulrich Kruppa
J. W. Ballantine
Yasuda Keisuke
Andriy Gapon
2008-03-24 03:52:36 +00:00

262 lines
8.3 KiB
C

--- sys/v4l/v4lsrc_calls.c.orig 2008-03-03 17:29:52.000000000 -0500
+++ sys/v4l/v4lsrc_calls.c 2008-03-20 23:50:39.000000000 -0400
@@ -26,12 +26,14 @@
#include <stdlib.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
+#include <unistd.h>
#include "v4lsrc_calls.h"
#include <sys/time.h>
@@ -87,6 +89,51 @@
return FALSE;
}
+ if (GST_V4LELEMENT (v4lsrc)->use_read) {
+ struct video_picture vp;
+ struct video_window vw;
+
+
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGPICT, &vp) == -1) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
+ ("Error getting current picture info for frame (%d): %s", num, g_strerror (errno)));
+ return FALSE;
+ }
+
+ vp.palette = v4lsrc->mmap.format;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSPICT, &vp) == -1) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
+ ("Error setting picture info for frame (%d): %s", num, g_strerror (errno)));
+ return FALSE;
+ }
+
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGWIN, &vw) == -1) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
+ ("Error getting current window properties for frame (%d): %s", num, g_strerror (errno)));
+ return FALSE;
+ }
+
+ vw.width = v4lsrc->mmap.width;
+ vw.height = v4lsrc->mmap.height;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSWIN, &vw) == -1) {
+ vw.flags &= (0x3F00 - 1);
+ vw.flags |= 15 << 16;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSWIN, &vw) == -1) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
+ ("Error setting window properties for frame (%d): %s", num, g_strerror (errno)));
+ return FALSE;
+ }
+ }
+
+
+ if (read(GST_V4LELEMENT (v4lsrc)->video_fd, GST_V4LELEMENT (v4lsrc)->buffer + (1024 * 768 * 3 * num), v4lsrc->mmap.width * v4lsrc->mmap.height * 3/2) < 0) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
+ ("Error queueing a buffer (%d): %s", num, g_strerror (errno)));
+ return FALSE;
+ }
+ goto done;
+ }
+
/* instruct the driver to prepare capture using buffer frame num */
v4lsrc->mmap.frame = num;
if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd,
@@ -95,6 +142,7 @@
("Error queueing a buffer (%d): %s", num, g_strerror (errno)));
return FALSE;
}
+done:
v4lsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED;
v4lsrc->num_queued++;
@@ -117,6 +165,10 @@
return FALSE;
}
+ if (GST_V4LELEMENT (v4lsrc)->use_read) {
+ goto done;
+ }
+
while (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &num) < 0) {
/* if the sync() got interrupted, we can retry */
if (errno != EINTR) {
@@ -126,6 +178,7 @@
}
GST_DEBUG_OBJECT (v4lsrc, "Sync got interrupted");
}
+done:
GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d done", num);
v4lsrc->frame_queue_state[num] = QUEUE_STATE_SYNCED;
@@ -168,13 +221,28 @@
GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc));
+ GST_V4LELEMENT (v4lsrc)->use_read = FALSE;
+
/* request the mmap buffer info:
* total size of mmap buffer, number of frames, offsets of frames */
if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF,
&(v4lsrc->mbuf)) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
- ("Error getting buffer information: %s", g_strerror (errno)));
- return FALSE;
+ int i;
+
+ GST_V4LELEMENT (v4lsrc)->buffer = (guint8 *) g_malloc0 (sizeof (guint8) * 1024 * 768 * 3 * MIN_BUFFERS_QUEUED);
+ GST_V4LELEMENT (v4lsrc)->use_read = TRUE;
+
+ v4lsrc->frame_queue_state = (gint8 *) g_malloc (sizeof (gint8) * MIN_BUFFERS_QUEUED);
+
+ v4lsrc->mbuf.frames = MIN_BUFFERS_QUEUED;
+ for (i = 0; i < MIN_BUFFERS_QUEUED; i++) {
+ v4lsrc->mbuf.offsets[i] = (1024 * 768 * 3 * i);
+ }
+
+ /* lock for the frame_state */
+ v4lsrc->mutex_queue_state = g_mutex_new ();
+ v4lsrc->cond_queue_state = g_cond_new ();
+ goto done;
}
if (v4lsrc->mbuf.frames < MIN_BUFFERS_QUEUED) {
@@ -205,6 +273,7 @@
GST_V4LELEMENT (v4lsrc)->buffer = NULL;
return FALSE;
}
+done:
return TRUE;
}
@@ -413,10 +482,14 @@
v4lsrc->frame_queue_state = NULL;
/* unmap the buffer */
- if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, CLOSE, (NULL),
- ("error munmap'ing capture buffer: %s", g_strerror (errno)));
- return FALSE;
+ if (GST_V4LELEMENT (v4lsrc)->use_read) {
+ g_free (GST_V4LELEMENT (v4lsrc)->buffer);
+ } else {
+ if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, CLOSE, (NULL),
+ ("error munmap'ing capture buffer: %s", g_strerror (errno)));
+ return FALSE;
+ }
}
GST_V4LELEMENT (v4lsrc)->buffer = NULL;
@@ -446,6 +519,7 @@
/* so, we need a buffer and some more stuff */
int frame = 0;
guint8 *buffer;
+ gboolean use_read = FALSE;
struct video_mbuf vmbuf;
struct video_mmap vmmap;
@@ -456,24 +530,72 @@
/* let's start by requesting a buffer and mmap()'ing it */
if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF, &vmbuf) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
- ("Error getting buffer information: %s", g_strerror (errno)));
- return FALSE;
- }
- /* Map the buffers */
- buffer = mmap (NULL, vmbuf.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
- if (buffer == MAP_FAILED) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
- ("Error mapping our try-out buffer: %s", g_strerror (errno)));
- return FALSE;
- }
+ buffer = (gint8 *) g_malloc0 (sizeof (gint8) * 1024 * 768 * 3);
+ use_read = TRUE;
+ } else {
+ /* Map the buffers */
+ buffer = mmap (0, vmbuf.size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
+ if (buffer == MAP_FAILED) {
+ GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
+ ("Error mapping our try-out buffer: %s", g_strerror (errno)));
+ return FALSE;
+ }
+ }
/* now that we have a buffer, let's try out our format */
vmmap.width = width;
vmmap.height = height;
vmmap.format = palette;
vmmap.frame = frame;
+ if (use_read) {
+ struct video_picture vp;
+ struct video_window vw;
+
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGWIN, &vw) == -1) {
+ GST_ERROR_OBJECT (v4lsrc,
+ "Error getting current window properties: %s", g_strerror (errno));
+ g_free (buffer);
+ return FALSE;
+ }
+
+ vw.width = width;
+ vw.height = height;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSWIN, &vw) == -1) {
+ vw.flags &= (0x3F00 - 1);
+ vw.flags |= 15 << 16;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSWIN, &vw) == -1) {
+ GST_ERROR_OBJECT (v4lsrc,
+ "Error setting window properties: %s", g_strerror (errno));
+ g_free (buffer);
+ return FALSE;
+ }
+ }
+
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGPICT, &vp) == -1) {
+ GST_ERROR_OBJECT (v4lsrc,
+ "Error getting current picture info: %s", g_strerror (errno));
+ g_free (buffer);
+ return FALSE;
+ }
+
+ vp.palette = palette;
+ if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSPICT, &vp) == -1) {
+ GST_ERROR_OBJECT (v4lsrc,
+ "Error setting picture info: %s", g_strerror (errno));
+ g_free (buffer);
+ return FALSE;
+ }
+
+
+ if (read (GST_V4LELEMENT (v4lsrc)->video_fd, buffer, width * height * 3/2) < 0) {
+ GST_ERROR_OBJECT (v4lsrc,
+ "Error reading into our try-out buffer: %s", g_strerror (errno));
+ g_free (buffer);
+ return FALSE;
+ }
+ goto done;
+ }
if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0) {
if (errno != EINVAL) /* our format failed! */
GST_ERROR_OBJECT (v4lsrc,
@@ -488,7 +610,11 @@
return FALSE;
}
- munmap (buffer, vmbuf.size);
+done:
+ if (use_read)
+ g_free (buffer);
+ else
+ munmap (buffer, vmbuf.size);
/* if we got here, it worked! woohoo, the format is supported! */
return TRUE;