change NULL to (NULL) for GST_ELEMENT_ERROR
[platform/upstream/gst-plugins-base.git] / sys / v4l / v4lmjpegsrc_calls.c
1 /* G-Streamer hardware MJPEG video source plugin
2  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <string.h>
30 #include <errno.h>
31 #include "v4lmjpegsrc_calls.h"
32
33 /* On some systems MAP_FAILED seems to be missing */
34 #ifndef MAP_FAILED
35 #define MAP_FAILED ( (caddr_t) -1 )
36 #endif
37
38 #define MIN_BUFFERS_QUEUED 2
39
40 #define DEBUG(format, args...) \
41         GST_DEBUG_OBJECT (\
42                 GST_ELEMENT(v4lmjpegsrc), \
43                 "V4LMJPEGSRC: " format, ##args)
44
45 enum {
46   QUEUE_STATE_ERROR = -1,
47   QUEUE_STATE_READY_FOR_QUEUE,
48   QUEUE_STATE_QUEUED,
49   QUEUE_STATE_SYNCED,
50 };
51
52 /******************************************************
53  * gst_v4lmjpegsrc_queue_frame():
54  *   queue a frame for capturing
55  * return value: TRUE on success, FALSE on error
56  ******************************************************/
57
58 static gboolean
59 gst_v4lmjpegsrc_queue_frame (GstV4lMjpegSrc *v4lmjpegsrc,
60                              gint           num)
61 {
62   DEBUG("queueing frame %d", num);
63
64   if (v4lmjpegsrc->frame_queue_state[num] != QUEUE_STATE_READY_FOR_QUEUE) {
65     return FALSE;
66   }
67
68   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)
69   {
70     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, (NULL),
71       ("Error queueing a buffer (%d): %s",
72       num, g_strerror(errno)));
73     return FALSE;
74   }
75
76   v4lmjpegsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED;
77   v4lmjpegsrc->num_queued++;
78
79   return TRUE;
80 }
81
82
83 /******************************************************
84  * gst_v4lmjpegsrc_sync_next_frame():
85  *   sync on the next frame for capturing
86  * return value: TRUE on success, FALSE on error
87  ******************************************************/
88
89 static gboolean
90 gst_v4lmjpegsrc_sync_next_frame (GstV4lMjpegSrc *v4lmjpegsrc,
91                                  gint           *num)
92 {
93   DEBUG("syncing on next frame");
94
95   if (v4lmjpegsrc->num_queued <= 0) {
96     return FALSE;
97   }
98
99   while (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd,
100                MJPIOC_SYNC, &(v4lmjpegsrc->bsync)) < 0) {
101     if (errno != EINTR) {
102       GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SYNC, NULL, GST_ERROR_SYSTEM);
103       return FALSE;
104     }
105     DEBUG("Sync got interrupted");
106   }
107
108   *num = v4lmjpegsrc->bsync.frame;
109
110   v4lmjpegsrc->frame_queue_state[*num] = QUEUE_STATE_SYNCED;
111   v4lmjpegsrc->num_queued--;
112
113   return TRUE;
114 }
115
116
117 /******************************************************
118  * gst_v4lmjpegsrc_set_buffer():
119  *   set buffer parameters (size/count)
120  * return value: TRUE on success, FALSE on error
121  ******************************************************/
122
123 gboolean
124 gst_v4lmjpegsrc_set_buffer (GstV4lMjpegSrc *v4lmjpegsrc,
125                             gint           numbufs,
126                             gint           bufsize)
127 {
128   DEBUG("setting buffer info to numbufs = %d, bufsize = %d KB",
129     numbufs, bufsize);
130   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
131   GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
132
133   v4lmjpegsrc->breq.size = bufsize * 1024;
134   v4lmjpegsrc->breq.count = numbufs;
135
136   return TRUE;
137 }
138
139
140 /******************************************************
141  * gst_v4lmjpegsrc_set_capture():
142  *   set capture parameters (simple)
143  * return value: TRUE on success, FALSE on error
144  ******************************************************/
145
146 gboolean
147 gst_v4lmjpegsrc_set_capture (GstV4lMjpegSrc *v4lmjpegsrc,
148                              gint           decimation,
149                              gint           quality)
150 {
151   int norm, input, mw;
152   struct mjpeg_params bparm;
153
154   DEBUG("setting decimation = %d, quality = %d",
155     decimation, quality);
156   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
157   GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
158
159   gst_v4l_get_chan_norm(GST_V4LELEMENT(v4lmjpegsrc), &input, &norm);
160
161   /* Query params for capture */
162   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
163   {
164     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, NULL, GST_ERROR_SYSTEM);
165     return FALSE;
166   }
167
168   bparm.decimation = decimation;
169   bparm.quality = quality;
170   bparm.norm = norm;
171   bparm.input = input;
172   bparm.APP_len = 0; /* no JPEG markers - TODO: this is definately not right for decimation==1 */
173
174   mw = GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxwidth;
175   if (mw != 768 && mw != 640)
176   {
177     if (decimation == 1)
178       mw = 720;
179     else
180       mw = 704;
181   }
182   v4lmjpegsrc->end_width = mw / decimation;
183   v4lmjpegsrc->end_height = (norm==VIDEO_MODE_NTSC?480:576) / decimation;
184
185   /* TODO: interlacing */
186
187   /* Set params for capture */
188   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)
189   {
190     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, NULL, GST_ERROR_SYSTEM);
191     return FALSE;
192   }
193
194   return TRUE;
195 }
196
197
198 /******************************************************
199  * gst_v4lmjpegsrc_set_capture_m():
200  *   set capture parameters (advanced)
201  * return value: TRUE on success, FALSE on error
202  ******************************************************/
203
204 gboolean gst_v4lmjpegsrc_set_capture_m (GstV4lMjpegSrc *v4lmjpegsrc,
205                                         gint           x_offset,
206                                         gint           y_offset,
207                                         gint           width,
208                                         gint           height,
209                                         gint           h_decimation,
210                                         gint           v_decimation,
211                                         gint           quality)
212 {
213   gint norm, input;
214   gint maxwidth;
215   struct mjpeg_params bparm;
216
217   DEBUG("setting x_offset = %d, y_offset = %d, "
218     "width = %d, height = %d, h_decimation = %d, v_decimation = %d, quality = %d\n",
219     x_offset, y_offset, width, height, h_decimation, v_decimation, quality);
220   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
221   GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
222
223   gst_v4l_get_chan_norm(GST_V4LELEMENT(v4lmjpegsrc), &input, &norm);
224
225   if (GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxwidth != 768 &&
226     GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxwidth != 640)
227     maxwidth = 720;
228   else
229     maxwidth = GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxwidth;
230
231   /* Query params for capture */
232   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd, MJPIOC_G_PARAMS, &bparm) < 0)
233   {
234     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, NULL, GST_ERROR_SYSTEM);
235     return FALSE;
236   }
237
238   bparm.decimation = 0;
239   bparm.quality = quality;
240   bparm.norm = norm;
241   bparm.input = input;
242   bparm.APP_len = 0; /* no JPEG markers - TODO: this is definately
243                       * not right for decimation==1 */
244
245   if (width <= 0)
246   {
247     if (x_offset < 0) x_offset = 0;
248     width = (maxwidth==720&&h_decimation!=1)?704:maxwidth - 2*x_offset;
249   }
250   else
251   {
252     if (x_offset < 0)
253       x_offset = (maxwidth - width)/2;
254   }
255
256   if (height <= 0)
257   {
258     if (y_offset < 0) y_offset = 0;
259     height = (norm==VIDEO_MODE_NTSC)?480:576 - 2*y_offset;
260   }
261   else
262   {
263     if (y_offset < 0)
264       y_offset = ((norm==VIDEO_MODE_NTSC)?480:576 - height)/2;
265   }
266
267   if (width + x_offset > maxwidth)
268   {
269     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, NULL,
270       ("Image width+offset (%d) bigger than maximum (%d)",
271       width + x_offset, maxwidth));
272     return FALSE;
273   }
274   if ((width%(bparm.HorDcm*16))!=0) 
275   {
276     GST_ELEMENT_ERROR (v4lmjpegsrc, STREAM, FORMAT, NULL,
277       ("Image width (%d) not multiple of %d (required for JPEG)",
278       width, bparm.HorDcm*16));
279     return FALSE;
280   }
281   if (height + y_offset > (norm==VIDEO_MODE_NTSC ? 480 : 576)) 
282   {
283     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, NULL,
284       ("Image height+offset (%d) bigger than maximum (%d)",
285       height + y_offset, (norm==VIDEO_MODE_NTSC ? 480 : 576)));
286     return FALSE;
287   }
288   /* RJ: Image height must only be a multiple of 8, but geom_height
289    * is double the field height
290    */
291   if ((height%(bparm.VerDcm*16))!=0) 
292   {
293     GST_ELEMENT_ERROR (v4lmjpegsrc, STREAM, FORMAT, NULL,
294       ("Image height (%d) not multiple of %d (required for JPEG)",
295       height, bparm.VerDcm*16));
296     return FALSE;
297   }
298
299   bparm.img_x = x_offset;
300   bparm.img_width = width;
301   bparm.img_y = y_offset;
302   bparm.img_height = height;
303   bparm.HorDcm = h_decimation;
304   bparm.VerDcm = (v_decimation==4) ? 2 : 1;
305   bparm.TmpDcm = (v_decimation==1) ? 1 : 2;
306   bparm.field_per_buff = (v_decimation==1) ? 2 : 1;
307
308   v4lmjpegsrc->end_width = width / h_decimation;
309   v4lmjpegsrc->end_width = height / v_decimation;
310
311   /* TODO: interlacing */
312
313   /* Set params for capture */
314   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd, MJPIOC_S_PARAMS, &bparm) < 0)
315   {
316     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, NULL, GST_ERROR_SYSTEM);
317     return FALSE;
318   }
319
320   return TRUE;
321 }
322
323
324 /******************************************************
325  * gst_v4lmjpegsrc_capture_init():
326  *   initialize the capture system
327  * return value: TRUE on success, FALSE on error
328  ******************************************************/
329
330 gboolean
331 gst_v4lmjpegsrc_capture_init (GstV4lMjpegSrc *v4lmjpegsrc)
332 {
333   DEBUG("initting capture subsystem");
334   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
335   GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
336
337   /* Request buffers */
338   if (ioctl(GST_V4LELEMENT(v4lmjpegsrc)->video_fd,
339             MJPIOC_REQBUFS, &(v4lmjpegsrc->breq)) < 0)
340   {
341     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, NULL, GST_ERROR_SYSTEM);
342     return FALSE;
343   }
344
345   if (v4lmjpegsrc->breq.count < MIN_BUFFERS_QUEUED)
346   {
347     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, NULL,
348       ("Too little buffers. We got %ld, we want at least %d",
349       v4lmjpegsrc->breq.count, MIN_BUFFERS_QUEUED));
350     return FALSE;
351   }
352
353   gst_info("Got %ld buffers of size %ld KB\n",
354     v4lmjpegsrc->breq.count, v4lmjpegsrc->breq.size/1024);
355
356   /* keep track of queued buffers */
357   v4lmjpegsrc->frame_queue_state = (gint8 *)
358     g_malloc(sizeof(gint8) * v4lmjpegsrc->breq.count);
359
360   /* track how often to use each frame */
361   v4lmjpegsrc->use_num_times = (gint *)
362     g_malloc(sizeof(gint) * v4lmjpegsrc->breq.count);
363
364   /* lock for the frame_state */
365   v4lmjpegsrc->mutex_queue_state = g_mutex_new();
366   v4lmjpegsrc->cond_queue_state = g_cond_new();
367
368   /* Map the buffers */
369   GST_V4LELEMENT(v4lmjpegsrc)->buffer = mmap(0,
370     v4lmjpegsrc->breq.count * v4lmjpegsrc->breq.size, 
371     PROT_READ|PROT_WRITE, MAP_SHARED, GST_V4LELEMENT(v4lmjpegsrc)->video_fd, 0);
372   if (GST_V4LELEMENT(v4lmjpegsrc)->buffer == MAP_FAILED)
373   {
374     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, NULL,
375       ("Error mapping video buffers: %s", g_strerror (errno)));
376     GST_V4LELEMENT(v4lmjpegsrc)->buffer = NULL;
377     return FALSE;
378   }
379
380   return TRUE;
381 }
382
383
384 /******************************************************
385  * gst_v4lmjpegsrc_capture_start():
386  *   start streaming capture
387  * return value: TRUE on success, FALSE on error
388  ******************************************************/
389
390 gboolean
391 gst_v4lmjpegsrc_capture_start (GstV4lMjpegSrc *v4lmjpegsrc)
392 {
393   int n;
394
395   DEBUG("starting capture");
396   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
397   GST_V4L_CHECK_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
398
399   g_mutex_lock(v4lmjpegsrc->mutex_queue_state);
400
401   v4lmjpegsrc->quit = FALSE;
402   v4lmjpegsrc->num_queued = 0;
403   v4lmjpegsrc->queue_frame = 0;
404
405   /* set all buffers ready to queue , this starts streaming capture */
406   for (n=0;n<v4lmjpegsrc->breq.count;n++) {
407     v4lmjpegsrc->frame_queue_state[n] = QUEUE_STATE_READY_FOR_QUEUE;
408     if (!gst_v4lmjpegsrc_queue_frame(v4lmjpegsrc, n)) {
409       g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
410       gst_v4lmjpegsrc_capture_stop(v4lmjpegsrc);
411       return FALSE;
412     }
413   }
414
415   g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
416
417   return TRUE;
418 }
419
420
421 /******************************************************
422  * gst_v4lmjpegsrc_grab_frame():
423  *   grab one frame during streaming capture
424  * return value: TRUE on success, FALSE on error
425  ******************************************************/
426
427 gboolean
428 gst_v4lmjpegsrc_grab_frame (GstV4lMjpegSrc *v4lmjpegsrc,
429                             gint           *num,
430                             gint           *size)
431 {
432   DEBUG("grabbing frame");
433   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
434   GST_V4L_CHECK_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
435
436   g_mutex_lock(v4lmjpegsrc->mutex_queue_state);
437
438   /* do we have enough frames? */
439   while (v4lmjpegsrc->num_queued < MIN_BUFFERS_QUEUED ||
440          v4lmjpegsrc->frame_queue_state[v4lmjpegsrc->queue_frame] ==
441            QUEUE_STATE_READY_FOR_QUEUE) {
442     while (v4lmjpegsrc->frame_queue_state[v4lmjpegsrc->queue_frame] !=
443              QUEUE_STATE_READY_FOR_QUEUE &&
444            !v4lmjpegsrc->quit) {
445       GST_DEBUG (
446                 "Waiting for frames to become available (%d < %d)",
447                 v4lmjpegsrc->num_queued, MIN_BUFFERS_QUEUED);
448       g_cond_wait(v4lmjpegsrc->cond_queue_state,
449                   v4lmjpegsrc->mutex_queue_state);
450     }
451     if (v4lmjpegsrc->quit) {
452       g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
453       return TRUE; /* it won't get through anyway */
454     }
455     if (!gst_v4lmjpegsrc_queue_frame(v4lmjpegsrc, v4lmjpegsrc->queue_frame)) {
456       g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
457       return FALSE;
458     }
459     v4lmjpegsrc->queue_frame = (v4lmjpegsrc->queue_frame + 1) % v4lmjpegsrc->breq.count;
460   }
461
462   /* syncing on the buffer grabs it */
463   if (!gst_v4lmjpegsrc_sync_next_frame(v4lmjpegsrc, num)) {
464     return FALSE;
465   }
466
467   *size = v4lmjpegsrc->bsync.length;
468
469   g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
470
471   return TRUE;
472 }
473
474
475 /******************************************************
476  * gst_v4lmjpegsrc_get_buffer():
477  *   get the memory address of a single buffer
478  * return value: TRUE on success, FALSE on error
479  ******************************************************/
480
481 guint8 *
482 gst_v4lmjpegsrc_get_buffer (GstV4lMjpegSrc *v4lmjpegsrc,
483                             gint           num)
484 {
485   /*DEBUG("gst_v4lmjpegsrc_get_buffer(), num = %d", num);*/
486
487   if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc)) ||
488       !GST_V4L_IS_OPEN(GST_V4LELEMENT(v4lmjpegsrc)))
489     return NULL;
490
491   if (num < 0 || num >= v4lmjpegsrc->breq.count)
492     return NULL;
493
494   return GST_V4LELEMENT(v4lmjpegsrc)->buffer+(v4lmjpegsrc->breq.size*num);
495 }
496
497
498 /******************************************************
499  * gst_v4lmjpegsrc_requeue_frame():
500  *   requeue a frame for capturing
501  * return value: TRUE on success, FALSE on error
502  ******************************************************/
503
504 gboolean
505 gst_v4lmjpegsrc_requeue_frame (GstV4lMjpegSrc *v4lmjpegsrc,
506                                gint           num)
507 {
508   DEBUG("requeueing frame %d", num);
509   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
510   GST_V4L_CHECK_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
511
512   /* mark frame as 'ready to requeue' */
513   g_mutex_lock(v4lmjpegsrc->mutex_queue_state);
514
515   if (v4lmjpegsrc->frame_queue_state[num] != QUEUE_STATE_SYNCED) {
516     GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, NULL,
517                       ("Invalid state %d (expected %d), can't requeue",
518                       v4lmjpegsrc->frame_queue_state[num],
519                       QUEUE_STATE_SYNCED));
520     return FALSE;
521   }
522
523   v4lmjpegsrc->frame_queue_state[num] = QUEUE_STATE_READY_FOR_QUEUE;
524
525   /* let an optional wait know */
526   g_cond_broadcast(v4lmjpegsrc->cond_queue_state);
527
528   g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
529
530   return TRUE;
531 }
532
533
534 /******************************************************
535  * gst_v4lmjpegsrc_capture_stop():
536  *   stop streaming capture
537  * return value: TRUE on success, FALSE on error
538  ******************************************************/
539
540 gboolean
541 gst_v4lmjpegsrc_capture_stop (GstV4lMjpegSrc *v4lmjpegsrc)
542 {
543   int n;
544
545   DEBUG("stopping capture");
546   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
547   GST_V4L_CHECK_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
548
549   g_mutex_lock(v4lmjpegsrc->mutex_queue_state);
550
551   /* make an optional pending wait stop */
552   v4lmjpegsrc->quit = TRUE;
553   g_cond_broadcast(v4lmjpegsrc->cond_queue_state);
554                                                                                 
555   /* sync on remaining frames */
556   while (v4lmjpegsrc->num_queued > 0) {
557     gst_v4lmjpegsrc_sync_next_frame(v4lmjpegsrc, &n);
558   }
559
560   g_mutex_unlock(v4lmjpegsrc->mutex_queue_state);
561
562   return TRUE;
563 }
564
565
566 /******************************************************
567  * gst_v4lmjpegsrc_capture_deinit():
568  *   deinitialize the capture system
569  * return value: TRUE on success, FALSE on error
570  ******************************************************/
571
572 gboolean
573 gst_v4lmjpegsrc_capture_deinit (GstV4lMjpegSrc *v4lmjpegsrc)
574 {
575   DEBUG("quitting capture subsystem");
576   GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lmjpegsrc));
577   GST_V4L_CHECK_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc));
578
579   /* unmap the buffer */
580   munmap(GST_V4LELEMENT(v4lmjpegsrc)->buffer, v4lmjpegsrc->breq.size * v4lmjpegsrc->breq.count);
581   GST_V4LELEMENT(v4lmjpegsrc)->buffer = NULL;
582
583   /* free buffer tracker */
584   g_mutex_free(v4lmjpegsrc->mutex_queue_state);
585   g_cond_free(v4lmjpegsrc->cond_queue_state);
586   g_free(v4lmjpegsrc->frame_queue_state);
587   g_free(v4lmjpegsrc->use_num_times);
588
589   return TRUE;
590 }