3 * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
6 * v4l2src.c - system calls
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
29 #include <sys/types.h>
32 #include <sys/ioctl.h>
36 #include "v4l2src_calls.h"
40 /* Needed on older Solaris Nevada builds (72 at least) */
42 #include <sys/ioccom.h>
45 #include "gstv4l2tuner.h"
46 #include "gstv4l2bufferpool.h"
48 #include "gst/gst-i18n-plugin.h"
50 #define GST_CAT_DEFAULT v4l2src_debug
51 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
54 #define GST_V4L2_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
55 #define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
57 /* On some systems MAP_FAILED seems to be missing */
59 #define MAP_FAILED ((caddr_t) -1)
66 gst_v4l2src_buffer_pool_activate (GstV4l2BufferPool * pool,
71 while ((buf = gst_v4l2_buffer_pool_get (pool, FALSE)) != NULL)
72 if (!gst_v4l2_buffer_pool_qbuf (pool, buf))
80 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
81 (_("Could not enqueue buffers in device '%s'."),
82 v4l2src->v4l2object->videodev),
83 ("enqueing buffer %d/%d failed: %s",
84 buf->vbuffer.index, v4l2src->num_buffers, g_strerror (errno)));
89 /******************************************************
90 * gst_v4l2src_grab_frame ():
91 * grab a frame for capturing
92 * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
93 ******************************************************/
95 gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
98 GstV4l2Object *v4l2object;
99 GstV4l2BufferPool *pool;
100 gint32 trials = NUM_TRIALS;
101 GstBuffer *pool_buffer;
105 v4l2object = v4l2src->v4l2object;
106 pool = v4l2src->pool;
110 GST_DEBUG_OBJECT (v4l2src, "grab frame");
113 if (v4l2object->can_poll_device) {
114 ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE);
115 if (G_UNLIKELY (ret < 0)) {
118 if (errno == ENXIO) {
119 GST_DEBUG_OBJECT (v4l2src,
120 "v4l2 device doesn't support polling. Disabling");
121 v4l2object->can_poll_device = FALSE;
123 if (errno != EAGAIN && errno != EINTR)
129 pool_buffer = GST_BUFFER (gst_v4l2_buffer_pool_dqbuf (pool));
133 GST_WARNING_OBJECT (pool->v4l2elem, "trials=%d", trials);
135 /* if the sync() got interrupted, we can retry */
140 return GST_FLOW_ERROR;
146 /* try again, until too many trials */
150 /* check nr. of attempts to capture */
151 if (--trials == -1) {
152 goto too_many_trials;
156 /* if we are handing out the last buffer in the pool, we need to make a
157 * copy and bring the buffer back in the pool. */
158 need_copy = v4l2src->always_copy
159 || !gst_v4l2_buffer_pool_available_buffers (pool);
161 if (G_UNLIKELY (need_copy)) {
162 if (!v4l2src->always_copy) {
163 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2src,
164 "running out of buffers, making a copy to reuse current one");
166 *buf = gst_buffer_copy (pool_buffer);
167 GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
168 /* this will requeue */
169 gst_buffer_unref (pool_buffer);
173 /* we set the buffer metadata in gst_v4l2src_create() */
180 GST_DEBUG ("no buffer pool");
181 return GST_FLOW_WRONG_STATE;
185 GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, READ, (NULL),
186 ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
187 return GST_FLOW_ERROR;
191 GST_DEBUG ("stop called");
192 return GST_FLOW_WRONG_STATE;
196 GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
197 (_("Failed trying to get video frames from device '%s'."),
198 v4l2object->videodev),
199 (_("Failed after %d tries. device %s. system error: %s"),
200 NUM_TRIALS, v4l2object->videodev, g_strerror (errno)));
201 return GST_FLOW_ERROR;
205 /******************************************************
206 * gst_v4l2src_set_capture():
207 * set capture parameters
208 * return value: TRUE on success, FALSE on error
209 ******************************************************/
211 gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
212 guint32 width, guint32 height, gboolean interlaced,
213 guint fps_n, guint fps_d)
215 gint fd = v4l2src->v4l2object->video_fd;
216 struct v4l2_streamparm stream;
218 if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
221 if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width,
222 height, interlaced)) {
223 /* error already reported */
227 /* Is there a reason we require the caller to always specify a framerate? */
228 GST_DEBUG_OBJECT (v4l2src, "Desired framerate: %u/%u", fps_n, fps_d);
230 memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
231 stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
232 if (v4l2_ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
233 GST_ELEMENT_WARNING (v4l2src, RESOURCE, SETTINGS,
234 (_("Could not get parameters on device '%s'"),
235 v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
239 /* We used to skip frame rate setup if the camera was already setup
240 with the requested frame rate. This breaks some cameras though,
241 causing them to not output data (several models of Thinkpad cameras
242 have this problem at least).
245 /* We want to change the frame rate, so check whether we can. Some cheap USB
246 * cameras don't have the capability */
247 if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
248 GST_DEBUG_OBJECT (v4l2src, "Not setting framerate (not supported)");
252 GST_LOG_OBJECT (v4l2src, "Setting framerate to %u/%u", fps_n, fps_d);
254 /* Note: V4L2 wants the frame interval, we have the frame rate */
255 stream.parm.capture.timeperframe.numerator = fps_d;
256 stream.parm.capture.timeperframe.denominator = fps_n;
258 /* some cheap USB cam's won't accept any change */
259 if (v4l2_ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
260 GST_ELEMENT_WARNING (v4l2src, RESOURCE, SETTINGS,
261 (_("Video input device did not accept new frame rate setting.")),
266 v4l2src->fps_n = fps_n;
267 v4l2src->fps_d = fps_d;
269 /* if we have a framerate pre-calculate duration */
270 if (fps_n > 0 && fps_d > 0) {
271 v4l2src->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
273 v4l2src->duration = GST_CLOCK_TIME_NONE;
276 GST_INFO_OBJECT (v4l2src,
277 "Set framerate to %u/%u and duration to %" GST_TIME_FORMAT, fps_n, fps_d,
278 GST_TIME_ARGS (v4l2src->duration));
284 /******************************************************
285 * gst_v4l2src_capture_init():
286 * initialize the capture system
287 * return value: TRUE on success, FALSE on error
288 ******************************************************/
290 gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps * caps)
292 GST_DEBUG_OBJECT (v4l2src, "initializing the capture system");
294 GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
295 GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
297 if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
299 /* Map the buffers */
300 GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
302 if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2src),
303 v4l2src->v4l2object->video_fd,
304 v4l2src->num_buffers, caps, TRUE, V4L2_BUF_TYPE_VIDEO_CAPTURE)))
305 goto buffer_pool_new_failed;
307 GST_INFO_OBJECT (v4l2src, "capturing buffers via mmap()");
308 v4l2src->use_mmap = TRUE;
310 if (v4l2src->num_buffers != v4l2src->pool->buffer_count) {
311 v4l2src->num_buffers = v4l2src->pool->buffer_count;
312 g_object_notify (G_OBJECT (v4l2src), "queue-size");
315 } else if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
316 GST_INFO_OBJECT (v4l2src, "capturing buffers via read()");
317 v4l2src->use_mmap = FALSE;
318 v4l2src->pool = NULL;
320 goto no_supported_capture_method;
323 GST_V4L2_SET_ACTIVE (v4l2src->v4l2object);
328 buffer_pool_new_failed:
330 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
331 (_("Could not map buffers from device '%s'"),
332 v4l2src->v4l2object->videodev),
333 ("Failed to create buffer pool: %s", g_strerror (errno)));
336 no_supported_capture_method:
338 GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
339 (_("The driver of device '%s' does not support any known capture "
340 "method."), v4l2src->v4l2object->videodev), (NULL));
346 /******************************************************
347 * gst_v4l2src_capture_start():
348 * start streaming capture
349 * return value: TRUE on success, FALSE on error
350 ******************************************************/
352 gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
354 GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
355 //GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
356 GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
358 v4l2src->quit = FALSE;
360 if (v4l2src->use_mmap) {
361 if (!gst_v4l2src_buffer_pool_activate (v4l2src->pool, v4l2src)) {
365 if (!gst_v4l2_object_start_streaming (v4l2src->v4l2object)) {
370 v4l2src->is_capturing = TRUE;
375 /******************************************************
376 * gst_v4l2src_capture_stop():
377 * stop streaming capture
378 * return value: TRUE on success, FALSE on error
379 ******************************************************/
381 gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
383 GST_DEBUG_OBJECT (v4l2src, "stopping capturing");
385 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
388 if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
392 if (v4l2src->use_mmap) {
393 /* we actually need to sync on all queued buffers but not
394 * on the non-queued ones */
395 if (!gst_v4l2_object_stop_streaming (v4l2src->v4l2object)) {
402 /* make an optional pending wait stop */
403 v4l2src->quit = TRUE;
404 v4l2src->is_capturing = FALSE;
409 /******************************************************
410 * gst_v4l2src_capture_deinit():
411 * deinitialize the capture system
412 * return value: TRUE on success, FALSE on error
413 ******************************************************/
415 gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
417 GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
419 if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
422 if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
427 gst_v4l2_buffer_pool_destroy (v4l2src->pool);
428 v4l2src->pool = NULL;
431 GST_V4L2_SET_INACTIVE (v4l2src->v4l2object);