c8a42d612b4d43b118235a8959853311a4494b20
[platform/upstream/gstreamer.git] / sys / rpicamsrc / gstrpicamsrc.c
1 /*
2  * GStreamer
3  * Copyright (C) 2013 Jan Schmidt <jan@centricular.com>
4  * 
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Alternatively, the contents of this file may be used under the
24  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
25  * which case the following provisions apply instead of the ones
26  * mentioned above:
27  *
28  * This library is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU Library General Public
30  * License as published by the Free Software Foundation; either
31  * version 2 of the License, or (at your option) any later version.
32  *
33  * This library is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36  * Library General Public License for more details.
37  *
38  * You should have received a copy of the GNU Library General Public
39  * License along with this library; if not, write to the
40  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
41  * Boston, MA 02111-1307, USA.
42  */
43
44 /**
45  * SECTION:element-rpicamsrc
46  *
47  * Source element for capturing from the Raspberry Pi camera module
48  *
49  * <refsect2>
50  * <title>Example launch line</title>
51  * |[
52  * gst-launch -v -m rpicamsrc ! fakesink
53  * ]|
54  * </refsect2>
55  */
56
57 #ifdef HAVE_CONFIG_H
58 #  include <config.h>
59 #endif
60
61 #include <gst/gst.h>
62 #include <gst/video/video.h>
63
64 #include "gstrpicamsrc.h"
65 #include "gstrpicam_types.h"
66 #include "gstrpicam-enum-types.h"
67 #include "RaspiCapture.h"
68
69 #include "bcm_host.h"
70 #include "interface/vcos/vcos.h"
71
72 #include "interface/mmal/mmal.h"
73 #include "interface/mmal/mmal_logging.h"
74 #include "interface/mmal/mmal_buffer.h"
75 #include "interface/mmal/util/mmal_util.h"
76 #include "interface/mmal/util/mmal_util_params.h"
77 #include "interface/mmal/util/mmal_default_components.h"
78 #include "interface/mmal/util/mmal_connection.h"
79
80 GST_DEBUG_CATEGORY_STATIC (gst_rpi_cam_src_debug);
81 #define GST_CAT_DEFAULT gst_rpi_cam_src_debug
82
83 /* Filter signals and args */
84 enum
85 {
86   /* FILL ME */
87   LAST_SIGNAL
88 };
89
90 enum
91 {
92   PROP_0,
93   PROP_BITRATE,
94   PROP_PREVIEW,
95   PROP_PREVIEW_ENCODED,
96   PROP_PREVIEW_OPACITY,
97   PROP_FULLSCREEN,
98   PROP_SHARPNESS,
99   PROP_CONTRAST,
100   PROP_BRIGHTNESS,
101   PROP_SATURATION,
102   PROP_ISO,
103   PROP_VIDEO_STABILISATION,
104   PROP_EXPOSURE_COMPENSATION,
105   PROP_EXPOSURE_MODE,
106   PROP_EXPOSURE_METERING_MODE,
107   PROP_AWB_MODE,
108   PROP_IMAGE_EFFECT,
109   PROP_IMAGE_EFFECT_PARAMS,
110   PROP_COLOUR_EFFECTS,
111   PROP_ROTATION,
112   PROP_HFLIP,
113   PROP_VFLIP,
114   PROP_ROI_X,
115   PROP_ROI_Y,
116   PROP_ROI_W,
117   PROP_ROI_H,
118 };
119
120 #define BITRATE_DEFAULT 17000000        /* 17Mbit/s default for 1080p */
121 #define BITRATE_HIGHEST 25000000
122
123 #define SHARPNESS_DEFAULT 0
124 #define CONTRAST_DEFAULT 0
125 #define BRIGHTNESS_DEFAULT 50
126 #define SATURATION_DEFAULT 0
127 #define ISO_DEFAULT 0
128 #define VIDEO_STABILISATION_DEFAULT FALSE
129 #define EXPOSURE_COMPENSATION_DEFAULT 0
130
131 #define EXPOSURE_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_MODE_AUTO
132 #define EXPOSURE_METERING_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_AVERAGE
133
134 /*
135    params->exposureMode = MMAL_PARAM_EXPOSUREMODE_AUTO;
136    params->exposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
137    params->awbMode = MMAL_PARAM_AWBMODE_AUTO;
138    params->imageEffect = MMAL_PARAM_IMAGEFX_NONE;
139    params->colourEffects.enable = 0;
140    params->colourEffects.u = 128;
141    params->colourEffects.v = 128;
142    params->rotation = 0;
143    params->hflip = params->vflip = 0;
144    params->roi.x = params->roi.y = 0.0;
145    params->roi.w = params->roi.h = 1.0;
146 */
147
148 #define RAW_AND_JPEG_CAPS \
149   GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \
150   "image/jpeg,"                                   \
151   "width = " GST_VIDEO_SIZE_RANGE ","             \
152   "height = " GST_VIDEO_SIZE_RANGE ","            \
153   "framerate = " GST_VIDEO_FPS_RANGE
154 #define H264_CAPS                               \
155   "video/x-h264, "                              \
156   "width = " GST_VIDEO_SIZE_RANGE ", "          \
157   "height = " GST_VIDEO_SIZE_RANGE ", "         \
158   "framerate = " GST_VIDEO_FPS_RANGE ", "       \
159   "stream-format = (string) { byte-stream }, "  \
160   "alignment = (string) { au }, "               \
161   "profile = (string) { baseline, main, high }"
162
163 static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
164     GST_PAD_SRC,
165     GST_PAD_ALWAYS,
166     GST_STATIC_CAPS ( /*RAW_AND_JPEG_CAPS "; " */ H264_CAPS)
167     );
168
169 #define gst_rpi_cam_src_parent_class parent_class
170 G_DEFINE_TYPE (GstRpiCamSrc, gst_rpi_cam_src, GST_TYPE_PUSH_SRC);
171
172 static void gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
173     const GValue * value, GParamSpec * pspec);
174 static void gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
175     GValue * value, GParamSpec * pspec);
176 static gboolean gst_rpi_cam_src_start (GstBaseSrc * parent);
177 static gboolean gst_rpi_cam_src_stop (GstBaseSrc * parent);
178 static gboolean gst_rpi_cam_src_decide_allocation (GstBaseSrc * src,
179     GstQuery * query);
180 static GstFlowReturn gst_rpi_cam_src_create (GstPushSrc * parent,
181     GstBuffer ** buf);
182 static GstCaps *gst_rpi_cam_src_get_caps (GstBaseSrc * src, GstCaps * filter);
183 static gboolean gst_rpi_cam_src_set_caps (GstBaseSrc * src, GstCaps * caps);
184 static GstCaps *gst_rpi_cam_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
185
186 static void
187 gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass)
188 {
189   GObjectClass *gobject_class;
190   GstElementClass *gstelement_class;
191   GstBaseSrcClass *basesrc_class;
192   GstPushSrcClass *pushsrc_class;
193
194   gobject_class = (GObjectClass *) klass;
195   gstelement_class = (GstElementClass *) klass;
196   basesrc_class = (GstBaseSrcClass *) klass;
197   pushsrc_class = (GstPushSrcClass *) klass;
198
199   gobject_class->set_property = gst_rpi_cam_src_set_property;
200   gobject_class->get_property = gst_rpi_cam_src_get_property;
201
202   g_object_class_install_property (gobject_class, PROP_BITRATE,
203       g_param_spec_int ("bitrate", "Bitrate", "Bitrate for encoding",
204           1, BITRATE_HIGHEST, BITRATE_DEFAULT,
205           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206   g_object_class_install_property (gobject_class, PROP_PREVIEW,
207       g_param_spec_boolean ("preview",
208           "Preview Window", "Display preview window overlay",
209           TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
210   g_object_class_install_property (gobject_class, PROP_FULLSCREEN,
211       g_param_spec_boolean ("fullscreen",
212           "Fullscreen Preview", "Display preview window full screen",
213           TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
214   g_object_class_install_property (gobject_class, PROP_PREVIEW_ENCODED,
215       g_param_spec_boolean ("preview-encoded",
216           "Preview Encoded", "Display encoder output in the preview",
217           TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_OPACITY,
219       g_param_spec_int ("preview-opacity", "Preview Opacity",
220           "Opacity to use for the preview window", 0, 255, 255,
221           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
222   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHARPNESS,
223       g_param_spec_int ("sharpness", "Sharpness", "Image capture sharpness",
224           -100, 100, SHARPNESS_DEFAULT,
225           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
226   g_object_class_install_property (gobject_class, PROP_CONTRAST,
227       g_param_spec_int ("contrast", "Contrast", "Image capture contrast", -100,
228           100, CONTRAST_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
229   g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
230       g_param_spec_int ("brightness", "Brightness", "Image capture brightness",
231           0, 100, BRIGHTNESS_DEFAULT,
232           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233   g_object_class_install_property (gobject_class, PROP_SATURATION,
234       g_param_spec_int ("saturation", "Saturation", "Image capture saturation",
235           -100, 100, SATURATION_DEFAULT,
236           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
237   g_object_class_install_property (gobject_class, PROP_ISO,
238       g_param_spec_int ("iso", "ISO", "ISO value to use (0 = Auto)", 0, 3200, 0,
239           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
240   g_object_class_install_property (gobject_class, PROP_VIDEO_STABILISATION,
241       g_param_spec_boolean ("video-stabilisation", "Video Stabilisation",
242           "Enable or disable video stabilisation", FALSE,
243           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
244   g_object_class_install_property (gobject_class, PROP_EXPOSURE_COMPENSATION,
245       g_param_spec_int ("exposure-compensation", "EV compensation",
246           "Exposure Value compensation", -10, 10, 0,
247           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
248   g_object_class_install_property (gobject_class, PROP_EXPOSURE_MODE,
249       g_param_spec_enum ("exposure-mode", "Exposure Mode",
250           "Camera exposure mode to use",
251           GST_RPI_CAM_TYPE_RPI_CAM_SRC_EXPOSURE_MODE, EXPOSURE_MODE_DEFAULT,
252           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
253   g_object_class_install_property (gobject_class, PROP_EXPOSURE_METERING_MODE,
254       g_param_spec_enum ("metering-mode", "Exposure Metering Mode",
255           "Camera exposure metering mode to use",
256           GST_RPI_CAM_TYPE_RPI_CAM_SRC_EXPOSURE_METERING_MODE,
257           EXPOSURE_METERING_MODE_DEFAULT,
258           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
259   g_object_class_install_property (gobject_class, PROP_AWB_MODE,
260       g_param_spec_enum ("awb-mode", "Automatic White Balance Mode",
261           "White Balance mode", GST_RPI_CAM_TYPE_RPI_CAM_SRC_AWB_MODE,
262           GST_RPI_CAM_SRC_AWB_MODE_AUTO,
263           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
264   g_object_class_install_property (gobject_class, PROP_IMAGE_EFFECT,
265       g_param_spec_enum ("image-effect", "Image effect",
266           "Visual FX to apply to the image",
267           GST_RPI_CAM_TYPE_RPI_CAM_SRC_IMAGE_EFFECT,
268           GST_RPI_CAM_SRC_IMAGEFX_NONE,
269           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
270 #if 0
271   PROP_IMAGE_EFFECT_PARAMS, PROP_COLOUR_EFFECTS,
272 #endif
273       g_object_class_install_property (gobject_class, PROP_ROTATION,
274       g_param_spec_int ("rotation", "Rotation",
275           "Rotate captured image (0, 90, 180, 270 degrees)", 0, 270, 0,
276           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
277   g_object_class_install_property (gobject_class, PROP_HFLIP,
278       g_param_spec_boolean ("hflip", "Horizontal Flip",
279           "Flip capture horizontally", FALSE,
280           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
281   g_object_class_install_property (gobject_class, PROP_VFLIP,
282       g_param_spec_boolean ("vflip", "Vertical Flip", "Flip capture vertically",
283           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
284   g_object_class_install_property (gobject_class, PROP_ROI_X,
285       g_param_spec_float ("roi-x", "ROI X",
286           "Normalised region-of-interest X coord", 0, 1.0, 0,
287           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
288   g_object_class_install_property (gobject_class, PROP_ROI_Y,
289       g_param_spec_float ("roi-y", "ROI Y",
290           "Normalised region-of-interest Y coord", 0, 1.0, 0,
291           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
292   g_object_class_install_property (gobject_class, PROP_ROI_W,
293       g_param_spec_float ("roi-w", "ROI W",
294           "Normalised region-of-interest W coord", 0, 1.0, 1.0,
295           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
296   g_object_class_install_property (gobject_class, PROP_ROI_H,
297       g_param_spec_float ("roi-h", "ROI H",
298           "Normalised region-of-interest H coord", 0, 1.0, 1.0,
299           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
300
301   gst_element_class_set_static_metadata (gstelement_class,
302       "Raspberry Pi Camera Source",
303       "Source/Video",
304       "Raspberry Pi camera module source", "Jan Schmidt <jan@centricular.com>");
305
306   gst_element_class_add_pad_template (gstelement_class,
307       gst_static_pad_template_get (&video_src_template));
308
309   basesrc_class->start = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_start);
310   basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_stop);
311   basesrc_class->decide_allocation =
312       GST_DEBUG_FUNCPTR (gst_rpi_cam_src_decide_allocation);
313   basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_get_caps);
314   basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_set_caps);
315   basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_fixate);
316   pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_create);
317
318   raspicapture_init ();
319 }
320
321 static void
322 gst_rpi_cam_src_init (GstRpiCamSrc * src)
323 {
324   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
325   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
326   raspicapture_default_config (&src->capture_config);
327
328   src->capture_config.verbose = 1;
329   /* do-timestamping by default for now. FIXME: Implement proper timestamping */
330   gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
331 }
332
333 static void
334 gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
335     const GValue * value, GParamSpec * pspec)
336 {
337   GstRpiCamSrc *src = GST_RPICAMSRC (object);
338
339   switch (prop_id) {
340     case PROP_BITRATE:
341       src->capture_config.bitrate = g_value_get_int (value);
342       break;
343     case PROP_PREVIEW:
344       src->capture_config.preview_parameters.wantPreview =
345           g_value_get_boolean (value);
346       break;
347     case PROP_PREVIEW_ENCODED:
348       src->capture_config.immutableInput = g_value_get_boolean (value);
349       break;
350     case PROP_FULLSCREEN:
351       src->capture_config.preview_parameters.wantFullScreenPreview =
352           g_value_get_boolean (value);
353       break;
354     case PROP_PREVIEW_OPACITY:
355       src->capture_config.preview_parameters.opacity = g_value_get_int (value);
356       break;
357     case PROP_SHARPNESS:
358       src->capture_config.camera_parameters.sharpness = g_value_get_int (value);
359       break;
360     case PROP_CONTRAST:
361       src->capture_config.camera_parameters.contrast = g_value_get_int (value);
362       break;
363     case PROP_BRIGHTNESS:
364       src->capture_config.camera_parameters.brightness =
365           g_value_get_int (value);
366       break;
367     case PROP_SATURATION:
368       src->capture_config.camera_parameters.saturation =
369           g_value_get_int (value);
370       break;
371     case PROP_ISO:
372       src->capture_config.camera_parameters.ISO = g_value_get_int (value);
373       break;
374     case PROP_VIDEO_STABILISATION:
375       src->capture_config.camera_parameters.videoStabilisation =
376           g_value_get_boolean (value);
377       break;
378     case PROP_EXPOSURE_COMPENSATION:
379       src->capture_config.camera_parameters.exposureCompensation =
380           g_value_get_int (value);
381       break;
382     case PROP_EXPOSURE_MODE:
383       src->capture_config.camera_parameters.exposureMode =
384           g_value_get_enum (value);
385       break;
386     case PROP_EXPOSURE_METERING_MODE:
387       src->capture_config.camera_parameters.exposureMeterMode =
388           g_value_get_enum (value);
389       break;
390     case PROP_ROTATION:
391       src->capture_config.camera_parameters.rotation = g_value_get_int (value);
392       break;
393     case PROP_AWB_MODE:
394       src->capture_config.camera_parameters.awbMode = g_value_get_enum (value);
395       break;
396     case PROP_IMAGE_EFFECT:
397       src->capture_config.camera_parameters.imageEffect = g_value_get_enum (value);
398       break;
399     case PROP_HFLIP:
400       src->capture_config.camera_parameters.hflip = g_value_get_boolean (value);
401       break;
402     case PROP_VFLIP:
403       src->capture_config.camera_parameters.vflip = g_value_get_boolean (value);
404       break;
405     case PROP_ROI_X:
406       src->capture_config.camera_parameters.roi.x = g_value_get_float (value);
407       break;
408     case PROP_ROI_Y:
409       src->capture_config.camera_parameters.roi.y = g_value_get_float (value);
410       break;
411     case PROP_ROI_W:
412       src->capture_config.camera_parameters.roi.w = g_value_get_float (value);
413       break;
414     case PROP_ROI_H:
415       src->capture_config.camera_parameters.roi.h = g_value_get_float (value);
416       break;
417     default:
418       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
419       break;
420   }
421 }
422
423 static void
424 gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
425     GValue * value, GParamSpec * pspec)
426 {
427   GstRpiCamSrc *src = GST_RPICAMSRC (object);
428
429   switch (prop_id) {
430     case PROP_BITRATE:
431       g_value_set_int (value, src->capture_config.bitrate);
432       break;
433     case PROP_PREVIEW:
434       g_value_set_boolean (value,
435           src->capture_config.preview_parameters.wantPreview);
436       break;
437     case PROP_PREVIEW_ENCODED:
438       g_value_set_boolean (value, src->capture_config.immutableInput);
439       break;
440     case PROP_FULLSCREEN:
441       g_value_set_boolean (value,
442           src->capture_config.preview_parameters.wantFullScreenPreview);
443       break;
444     case PROP_PREVIEW_OPACITY:
445       g_value_set_int (value, src->capture_config.preview_parameters.opacity);
446       break;
447     case PROP_SHARPNESS:
448       g_value_set_int (value, src->capture_config.camera_parameters.sharpness);
449       break;
450     case PROP_CONTRAST:
451       g_value_set_int (value, src->capture_config.camera_parameters.contrast);
452       break;
453     case PROP_BRIGHTNESS:
454       g_value_set_int (value, src->capture_config.camera_parameters.brightness);
455       break;
456     case PROP_SATURATION:
457       g_value_set_int (value, src->capture_config.camera_parameters.saturation);
458       break;
459     case PROP_ISO:
460       g_value_set_int (value, src->capture_config.camera_parameters.ISO);
461       break;
462     case PROP_VIDEO_STABILISATION:
463       g_value_set_boolean (value,
464           ! !(src->capture_config.camera_parameters.videoStabilisation));
465       break;
466     case PROP_EXPOSURE_COMPENSATION:
467       g_value_set_int (value,
468           src->capture_config.camera_parameters.exposureCompensation);
469       break;
470     case PROP_EXPOSURE_MODE:
471       g_value_set_enum (value,
472           src->capture_config.camera_parameters.exposureMode);
473       break;
474     case PROP_EXPOSURE_METERING_MODE:
475       g_value_set_enum (value,
476           src->capture_config.camera_parameters.exposureMeterMode);
477       break;
478     case PROP_ROTATION:
479       g_value_set_int (value, src->capture_config.camera_parameters.rotation);
480       break;
481     case PROP_AWB_MODE:
482       g_value_set_enum (value, src->capture_config.camera_parameters.awbMode);
483       break;
484     case PROP_IMAGE_EFFECT:
485       g_value_set_enum (value, src->capture_config.camera_parameters.imageEffect);
486       break;
487     case PROP_HFLIP:
488       g_value_set_boolean (value,
489           ! !(src->capture_config.camera_parameters.hflip));
490       break;
491     case PROP_VFLIP:
492       g_value_set_boolean (value,
493           ! !(src->capture_config.camera_parameters.vflip));
494       break;
495     case PROP_ROI_X:
496       g_value_set_float (value, src->capture_config.camera_parameters.roi.x);
497       break;
498     case PROP_ROI_Y:
499       g_value_set_float (value, src->capture_config.camera_parameters.roi.y);
500       break;
501     case PROP_ROI_W:
502       g_value_set_float (value, src->capture_config.camera_parameters.roi.w);
503       break;
504     case PROP_ROI_H:
505       g_value_set_float (value, src->capture_config.camera_parameters.roi.h);
506       break;
507     default:
508       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
509       break;
510   }
511 }
512
513 static gboolean
514 gst_rpi_cam_src_start (GstBaseSrc * parent)
515 {
516   GstRpiCamSrc *src = GST_RPICAMSRC (parent);
517   g_print ("In src_start()\n");
518   src->capture_state = raspi_capture_setup (&src->capture_config);
519   if (src->capture_state == NULL)
520     return FALSE;
521
522   return TRUE;
523 }
524
525 static gboolean
526 gst_rpi_cam_src_stop (GstBaseSrc * parent)
527 {
528   GstRpiCamSrc *src = GST_RPICAMSRC (parent);
529   if (src->started)
530     raspi_capture_stop (src->capture_state);
531   raspi_capture_free (src->capture_state);
532   src->capture_state = NULL;
533   return TRUE;
534 }
535
536 static GstCaps *
537 gst_rpi_cam_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
538 {
539   GstRpiCamSrc *src = GST_RPICAMSRC (bsrc);
540   GstCaps *caps;
541
542   caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
543   if (src->capture_state == NULL)
544     goto done;
545
546   /* FIXME: Retrieve limiting parameters from the camera module, max width/height fps-range */
547   caps = gst_caps_make_writable (caps);
548   gst_caps_set_simple (caps,
549       "width", GST_TYPE_INT_RANGE, 1, 1920,
550       "height", GST_TYPE_INT_RANGE, 1, 1080,
551       "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 60, 1, NULL);
552
553 done:
554   GST_DEBUG_OBJECT (src, "get_caps returning %" GST_PTR_FORMAT, caps);
555   return caps;
556 }
557
558 static gboolean
559 gst_rpi_cam_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
560 {
561   GstRpiCamSrc *src = GST_RPICAMSRC (bsrc);
562   GstVideoInfo info;
563
564   GST_DEBUG_OBJECT (src, "In set_caps %" GST_PTR_FORMAT, caps);
565   if (!gst_video_info_from_caps (&info, caps))
566     return FALSE;
567
568   src->capture_config.width = info.width;
569   src->capture_config.height = info.height;
570   src->capture_config.fps_n = info.fps_n;
571   src->capture_config.fps_d = info.fps_d;
572
573   return TRUE;
574 }
575
576 static gboolean
577 gst_rpi_cam_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
578 {
579   g_print ("In decide_allocation\n");
580   return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
581 }
582
583 static GstCaps *
584 gst_rpi_cam_src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
585 {
586   GstStructure *structure;
587   gint i;
588
589   GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
590
591   caps = gst_caps_make_writable (caps);
592
593   for (i = 0; i < gst_caps_get_size (caps); ++i) {
594     structure = gst_caps_get_structure (caps, i);
595
596     /* Fixate to 1920x1080 resolution if possible */
597     gst_structure_fixate_field_nearest_int (structure, "width", 1920);
598     gst_structure_fixate_field_nearest_int (structure, "height", 1080);
599     gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
600     gst_structure_fixate_field (structure, "format");
601   }
602
603   GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
604
605   caps = GST_BASE_SRC_CLASS (parent_class)->fixate (basesrc, caps);
606
607   return caps;
608 }
609
610 static GstFlowReturn
611 gst_rpi_cam_src_create (GstPushSrc * parent, GstBuffer ** buf)
612 {
613   GstRpiCamSrc *src = GST_RPICAMSRC (parent);
614   GstFlowReturn ret;
615
616   if (!src->started) {
617     if (!raspi_capture_start (src->capture_state))
618       return GST_FLOW_ERROR;
619     src->started = TRUE;
620   }
621
622   /* FIXME: Use custom allocator */
623   ret = raspi_capture_fill_buffer (src->capture_state, buf);
624   if (*buf)
625     GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT "\n",
626         gst_buffer_get_size (*buf));
627
628   return ret;
629 }
630
631 static gboolean
632 plugin_init (GstPlugin * rpicamsrc)
633 {
634   GST_DEBUG_CATEGORY_INIT (gst_rpi_cam_src_debug, "rpicamsrc",
635       0, "rpicamsrc debug");
636
637   return gst_element_register (rpicamsrc, "rpicamsrc", GST_RANK_NONE,
638       GST_TYPE_RPICAMSRC);
639 }
640
641 #ifndef PACKAGE
642 #define PACKAGE "gstrpicamsrc"
643 #endif
644
645 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
646     GST_VERSION_MINOR,
647     rpicamsrc,
648     "Raspberry Pi Camera Source",
649     plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")