v4l2: add some more debug
[platform/upstream/gstreamer.git] / sys / v4l2 / v4l2src_calls.c
1 /* GStreamer
2  *
3  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4  *               2006 Edgard Lima <edgard.lima@indt.org.br>
5  *
6  * v4l2src.c - system calls
7  *
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.
12  *
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.
17  *
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.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <sys/mman.h>
34 #include <string.h>
35 #include <errno.h>
36 #include "v4l2src_calls.h"
37 #include <sys/time.h>
38 #include <unistd.h>
39 #ifdef __sun
40 /* Needed on older Solaris Nevada builds (72 at least) */
41 #include <stropts.h>
42 #include <sys/ioccom.h>
43 #endif
44
45 #include "gstv4l2tuner.h"
46 #include "gstv4l2bufferpool.h"
47
48 #include "gst/gst-i18n-plugin.h"
49
50 #define GST_CAT_DEFAULT v4l2src_debug
51 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
52
53
54 /******************************************************
55  * gst_v4l2src_grab_frame ():
56  *   grab a frame for capturing
57  * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
58  ******************************************************/
59 GstFlowReturn
60 gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
61 {
62 #define NUM_TRIALS 50
63   GstV4l2Object *v4l2object;
64   GstV4l2BufferPool *pool;
65   gint32 trials = NUM_TRIALS;
66   GstBuffer *pool_buffer;
67   gboolean need_copy;
68   gint ret;
69
70   v4l2object = v4l2src->v4l2object;
71   pool = v4l2object->pool;
72   if (!pool)
73     goto no_buffer_pool;
74
75   GST_DEBUG_OBJECT (v4l2src, "grab frame");
76
77   for (;;) {
78     if (v4l2object->can_poll_device) {
79       ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE);
80       if (G_UNLIKELY (ret < 0)) {
81         if (errno == EBUSY)
82           goto stopped;
83         if (errno == ENXIO) {
84           GST_DEBUG_OBJECT (v4l2src,
85               "v4l2 device doesn't support polling. Disabling");
86           v4l2object->can_poll_device = FALSE;
87         } else {
88           if (errno != EAGAIN && errno != EINTR)
89             goto select_error;
90         }
91       }
92     }
93
94     pool_buffer = gst_v4l2_buffer_pool_dqbuf (pool);
95     if (pool_buffer)
96       break;
97
98     GST_WARNING_OBJECT (v4l2src, "trials=%d", trials);
99
100     /* if the sync() got interrupted, we can retry */
101     switch (errno) {
102       case EINVAL:
103       case ENOMEM:
104         /* fatal */
105         return GST_FLOW_ERROR;
106
107       case EAGAIN:
108       case EIO:
109       case EINTR:
110       default:
111         /* try again, until too many trials */
112         break;
113     }
114
115     /* check nr. of attempts to capture */
116     if (--trials == -1) {
117       goto too_many_trials;
118     }
119   }
120
121   /* if we are handing out the last buffer in the pool, we need to make a
122    * copy and bring the buffer back in the pool. */
123   need_copy = v4l2src->always_copy
124       || !gst_v4l2_buffer_pool_available_buffers (pool);
125
126   if (G_UNLIKELY (need_copy)) {
127     if (!v4l2src->always_copy) {
128       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2src,
129           "running out of buffers, making a copy to reuse current one");
130     }
131     *buf = gst_buffer_copy (pool_buffer);
132     /* this will requeue */
133     gst_buffer_unref (pool_buffer);
134   } else {
135     *buf = pool_buffer;
136   }
137   /* we set the buffer metadata in gst_v4l2src_create() */
138
139   return GST_FLOW_OK;
140
141   /* ERRORS */
142 no_buffer_pool:
143   {
144     GST_DEBUG ("no buffer pool");
145     return GST_FLOW_WRONG_STATE;
146   }
147 select_error:
148   {
149     GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
150         ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
151     return GST_FLOW_ERROR;
152   }
153 stopped:
154   {
155     GST_DEBUG ("stop called");
156     return GST_FLOW_WRONG_STATE;
157   }
158 too_many_trials:
159   {
160     GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
161         (_("Failed trying to get video frames from device '%s'."),
162             v4l2object->videodev),
163         (_("Failed after %d tries. device %s. system error: %s"),
164             NUM_TRIALS, v4l2object->videodev, g_strerror (errno)));
165     return GST_FLOW_ERROR;
166   }
167 }