Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / sys / v4l / gstv4ljpegsrc.c
1 /* GStreamer
2  *
3  * gstv4ljpegsrc.c: V4L source element for JPEG cameras
4  *
5  * Copyright (C) 2004-2005 Jan Schmidt <thaytan@mad.scientist.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  e Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <sys/time.h>
29 #include "gstv4ljpegsrc.h"
30 #include "v4lsrc_calls.h"
31
32 GST_DEBUG_CATEGORY_STATIC (v4ljpegsrc_debug);
33 #define GST_CAT_DEFAULT v4ljpegsrc_debug
34
35 /* init functions */
36 static void gst_v4ljpegsrc_base_init (gpointer g_class);
37 static void gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass);
38 static void gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc);
39
40 /* buffer functions */
41 static GstPadLinkReturn gst_v4ljpegsrc_src_link (GstPad * pad,
42     const GstCaps * caps);
43 static GstCaps *gst_v4ljpegsrc_getcaps (GstPad * pad);
44 static GstData *gst_v4ljpegsrc_get (GstPad * pad);
45
46 static GstElementClass *parent_class = NULL;
47
48 GType
49 gst_v4ljpegsrc_get_type (void)
50 {
51   static GType v4ljpegsrc_type = 0;
52
53   if (!v4ljpegsrc_type) {
54     static const GTypeInfo v4ljpegsrc_info = {
55       sizeof (GstV4lJpegSrcClass),
56       gst_v4ljpegsrc_base_init,
57       NULL,
58       (GClassInitFunc) gst_v4ljpegsrc_class_init,
59       NULL,
60       NULL,
61       sizeof (GstV4lJpegSrc),
62       0,
63       (GInstanceInitFunc) gst_v4ljpegsrc_init,
64       NULL
65     };
66
67     v4ljpegsrc_type =
68         g_type_register_static (GST_TYPE_V4LSRC, "GstV4lJpegSrc",
69         &v4ljpegsrc_info, 0);
70     GST_DEBUG_CATEGORY_INIT (v4ljpegsrc_debug, "v4ljpegsrc", 0,
71         "V4L JPEG source element");
72   }
73   return v4ljpegsrc_type;
74 }
75
76 static void
77 gst_v4ljpegsrc_base_init (gpointer g_class)
78 {
79   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
80
81   gst_element_class_set_details_simple (gstelement_class,
82       "Video (video4linux/raw) Jpeg Source", "Source/Video",
83       "Reads jpeg frames from a video4linux (eg ov519) device",
84       "Jan Schmidt <thaytan@mad.scientist.com>");
85 }
86
87 static void
88 gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass)
89 {
90   parent_class = g_type_class_peek_parent (klass);
91 }
92
93 static void
94 gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc)
95 {
96   GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc);
97   GstPad *pad = v4lsrc->srcpad;
98
99   /*
100    * Stash away and then replace the getcaps and get functions on the src pad
101    */
102   v4ljpegsrc->getfn = GST_RPAD_GETFUNC (pad);
103   v4ljpegsrc->getcapsfn = GST_RPAD_GETCAPSFUNC (pad);
104
105   gst_pad_set_get_function (v4lsrc->srcpad, gst_v4ljpegsrc_get);
106   gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4ljpegsrc_getcaps);
107   gst_pad_set_link_function (v4lsrc->srcpad, gst_v4ljpegsrc_src_link);
108 }
109
110 static GstPadLinkReturn
111 gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
112 {
113   GstV4lJpegSrc *v4ljpegsrc;
114   GstV4lSrc *v4lsrc;
115   gint w, h, palette = -1;
116   const GValue *fps;
117   GstStructure *structure;
118   gboolean was_capturing;
119   struct video_window *vwin;
120
121   v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
122   v4lsrc = GST_V4LSRC (v4ljpegsrc);
123   vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
124   was_capturing = v4lsrc->is_capturing;
125
126   /* in case the buffers are active (which means that we already
127    * did capsnego before and didn't clean up), clean up anyways */
128   if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
129     if (was_capturing) {
130       if (!gst_v4lsrc_capture_stop (v4lsrc))
131         return GST_PAD_LINK_REFUSED;
132     }
133     if (!gst_v4lsrc_capture_deinit (v4lsrc))
134       return GST_PAD_LINK_REFUSED;
135   } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
136     return GST_PAD_LINK_DELAYED;
137   }
138
139   structure = gst_caps_get_structure (vscapslist, 0);
140
141   gst_structure_get_int (structure, "width", &w);
142   gst_structure_get_int (structure, "height", &h);
143   fps = gst_structure_get_value (structure, "framerate");
144
145   GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %d/%d fps", w, h,
146       gst_value_get_fraction_numerator (fps),
147       gst_value_get_fraction_denominator (fps));
148
149   /* set framerate if it's not already correct */
150   if (fps != gst_v4lsrc_get_fps (v4lsrc)) {
151     int fps_index = fps / 15.0 * 16;
152
153     GST_DEBUG_OBJECT (v4ljpegsrc, "Trying to set fps index %d", fps_index);
154     /* set bits 16 to 21 to 0 */
155     vwin->flags &= (0x3F00 - 1);
156     /* set bits 16 to 21 to the index */
157     vwin->flags |= fps_index << 16;
158     if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
159       return GST_PAD_LINK_DELAYED;
160     }
161   }
162
163   /*
164    * Try to set the camera to capture RGB24 
165    */
166   palette = VIDEO_PALETTE_RGB24;
167   v4lsrc->buffer_size = w * h * 3;
168
169   GST_DEBUG_OBJECT (v4ljpegsrc, "trying to set_capture %dx%d, palette %d",
170       w, h, palette);
171   /* this only fills in v4lsrc->mmap values */
172   if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
173     GST_WARNING_OBJECT (v4ljpegsrc, "could not set_capture %dx%d, palette %d",
174         w, h, palette);
175     return GST_PAD_LINK_REFUSED;
176   }
177
178   /* first try the negotiated settings using try_capture */
179   if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
180     GST_DEBUG_OBJECT (v4ljpegsrc, "failed trying palette %d for %dx%d", palette,
181         w, h);
182     return GST_PAD_LINK_REFUSED;
183   }
184
185   if (!gst_v4lsrc_capture_init (v4lsrc))
186     return GST_PAD_LINK_REFUSED;
187
188   if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) {
189     if (!gst_v4lsrc_capture_start (v4lsrc))
190       return GST_PAD_LINK_REFUSED;
191   }
192
193   return GST_PAD_LINK_OK;
194 }
195
196 static GstCaps *
197 gst_v4ljpegsrc_getcaps (GstPad * pad)
198 {
199   GstCaps *list;
200   GstV4lJpegSrc *v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
201   GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc);
202   struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
203   gfloat fps = 0.0;
204
205   if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
206     return gst_caps_new_any ();
207   }
208   if (!v4lsrc->autoprobe) {
209     /* FIXME: query current caps and return those, with _any appended */
210     return gst_caps_new_any ();
211   }
212
213   list = gst_caps_new_simple ("image/jpeg", NULL);
214   GST_DEBUG_OBJECT (v4ljpegsrc,
215       "Device reports w: %d-%d, h: %d-%d, fps: %f",
216       vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps);
217
218   if (vcap->minwidth < vcap->maxwidth) {
219     gst_caps_set_simple (list, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
220         vcap->maxwidth, NULL);
221   } else {
222     gst_caps_set_simple (list, "width", G_TYPE_INT, vcap->minwidth, NULL);
223   }
224   if (vcap->minheight < vcap->maxheight) {
225     gst_caps_set_simple (list, "height", GST_TYPE_INT_RANGE, vcap->minheight,
226         vcap->maxheight, NULL);
227   } else {
228     gst_caps_set_simple (list, "height", G_TYPE_INT, vcap->minheight, NULL);
229   }
230
231   if (v4lsrc->fps_list) {
232     GstStructure *structure = gst_caps_get_structure (list, 0);
233
234     gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
235   }
236   GST_DEBUG_OBJECT (v4ljpegsrc, "caps: %" GST_PTR_FORMAT, list);
237
238   return list;
239 }
240
241 static GstData *
242 gst_v4ljpegsrc_get (GstPad * pad)
243 {
244   GstV4lJpegSrc *v4ljpegsrc;
245   GstV4lSrc *v4lsrc;
246   GstData *data;
247   GstBuffer *buf;
248   GstBuffer *outbuf;
249   int jpeg_size;
250
251   g_return_val_if_fail (pad != NULL, NULL);
252   v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad));
253   v4lsrc = GST_V4LSRC (v4ljpegsrc);
254
255   /* Fetch from the v4lsrc class get fn.  */
256   data = v4ljpegsrc->getfn (pad);
257
258   /* If not a buffer, return it unchanged */
259   if (!data || (!GST_IS_BUFFER (data)))
260     return data;
261
262   buf = GST_BUFFER (data);
263
264   /* Confirm that the buffer contains jpeg data */
265
266   /* 
267    * Create a new subbuffer from the jpeg data 
268    * The first 2 bytes in the buffer are the size of the jpeg data
269    */
270   if (GST_BUFFER_SIZE (buf) > 2) {
271     jpeg_size = (int) (GST_READ_UINT16_LE (GST_BUFFER_DATA (buf))) * 8;
272   } else
273     jpeg_size = 0;
274
275   /* Check that the size is sensible */
276   if ((jpeg_size <= 0) || (jpeg_size > GST_BUFFER_SIZE (buf) - 2)) {
277     GST_ELEMENT_ERROR (v4ljpegsrc, STREAM, FORMAT, (NULL),
278         ("Invalid non-jpeg frame from camera"));
279     return NULL;
280   }
281
282   GST_DEBUG_OBJECT (v4ljpegsrc, "Creating JPEG subbuffer of size %d",
283       jpeg_size);
284   outbuf = gst_buffer_create_sub (buf, 2, jpeg_size);
285
286   /* Copy timestamps onto the subbuffer */
287   gst_buffer_stamp (outbuf, buf);
288
289   /* Release the main buffer */
290   gst_buffer_unref (buf);
291
292   return GST_DATA (outbuf);
293 }