3 * Copyright (C) 2013-2015 Jan Schmidt <jan@centricular.com>
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
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.
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.
45 * SECTION:element-rpicamsrc
47 * @short_description: Raspberry Pi Camera Source
49 * Source element for capturing video from the Raspberry Pi camera module.
51 * This element works the same way that the `raspivid` command-line utility
52 * does and has a similar feature set.
54 * The element can output video in form of raw video frames or encoded as
55 * (M)JPEG or H.264 video. You can use the element properties to fine-tune
56 * the capture, image processing and encoding parameters.
58 * ## Example pipelines
60 * gst-launch-1.0 -v rpicamsrc preview=true ! fakesink
62 * should show a preview window on the screen.
65 * gst-launch-1.0 -e rpicamsrc bitrate=1000000 ! h264parse ! matroskamux ! filesink location=test.mkv
67 * should produce a file called test.mkv containing an H.264 video stream. We
68 * pass -e to gst-launch-1.0 so that the pipeline is finalised properly when
69 * interrupted with Control-C. This makes sure the Matroska file headers are
70 * updated when streaming ends.
73 * gst-launch-1.0 -e rpicamsrc bitrate=5000000 num-buffers=500 keyframe-interval=30 ! h264parse ! splitmuxsink location=video%02d.mov max-size-time=10000000000 max-size-bytes=1000000
75 * Records a video stream captured from the Raspberry Pi camera module and
76 * muxes it into ISO mp4 files, splitting as needed to limit size/duration to
77 * 10 seconds and 1MB maximum size.
79 * gst-launch-1.0 -e rpicamsrc ! image/jpeg,framerate=1/1 ! multifilesink location=image-%05d.jpg
81 * Captures a stream of JPEG images from the Raspberry Pi camera module at
82 * a rate of 1 frame per second and writes each frame into a new file in the
83 * current directory, starting with image-00000.jpg, then image-00001.jpg etc.
91 #include <gst/video/video.h>
93 #include "gstrpicamsrc.h"
94 #include "gstrpicam_types.h"
95 #include "gstrpicam-enum-types.h"
96 #include "gstrpicamsrcdeviceprovider.h"
97 #include "RaspiCapture.h"
100 #include "interface/vcos/vcos.h"
102 #include "interface/mmal/mmal.h"
103 #include "interface/mmal/mmal_logging.h"
104 #include "interface/mmal/mmal_buffer.h"
105 #include "interface/mmal/util/mmal_util.h"
106 #include "interface/mmal/util/mmal_util_params.h"
107 #include "interface/mmal/util/mmal_default_components.h"
108 #include "interface/mmal/util/mmal_connection.h"
110 GST_DEBUG_CATEGORY (gst_rpi_cam_src_debug);
112 /* comment out to use JPEG codec instead of MJPEG */
113 // #define USE_JPEG_CODEC
115 /* Filter signals and args */
127 PROP_KEYFRAME_INTERVAL,
129 PROP_PREVIEW_ENCODED,
130 PROP_PREVIEW_OPACITY,
141 PROP_VIDEO_STABILISATION,
142 PROP_EXPOSURE_COMPENSATION,
144 PROP_EXPOSURE_METERING_MODE,
149 PROP_IMAGE_EFFECT_PARAMS,
158 PROP_QUANTISATION_PARAMETER,
163 PROP_ANNOTATION_MODE,
164 PROP_ANNOTATION_TEXT,
165 PROP_ANNOTATION_TEXT_SIZE,
166 PROP_ANNOTATION_TEXT_COLOUR,
167 PROP_ANNOTATION_TEXT_BG_COLOUR,
168 PROP_INTRA_REFRESH_TYPE,
169 PROP_VIDEO_DIRECTION,
174 #define CAMERA_DEFAULT 0
176 #define BITRATE_DEFAULT 17000000 /* 17Mbit/s default for 1080p */
177 #define BITRATE_HIGHEST 25000000
179 #define QUANTISATION_DEFAULT 0
181 #define SHARPNESS_DEFAULT 0
182 #define CONTRAST_DEFAULT 0
183 #define BRIGHTNESS_DEFAULT 50
184 #define SATURATION_DEFAULT 0
185 #define ISO_DEFAULT 0
186 #define VIDEO_STABILISATION_DEFAULT FALSE
187 #define EXPOSURE_COMPENSATION_DEFAULT 0
188 #define KEYFRAME_INTERVAL_DEFAULT -1
190 #define EXPOSURE_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_MODE_AUTO
191 #define EXPOSURE_METERING_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_AVERAGE
193 #define DEFAULT_JPEG_QUALITY 50
196 params->exposureMode = MMAL_PARAM_EXPOSUREMODE_AUTO;
197 params->exposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
198 params->awbMode = MMAL_PARAM_AWBMODE_AUTO;
199 params->imageEffect = MMAL_PARAM_IMAGEFX_NONE;
200 params->colourEffects.enable = 0;
201 params->colourEffects.u = 128;
202 params->colourEffects.v = 128;
203 params->rotation = 0;
204 params->hflip = params->vflip = 0;
205 params->roi.x = params->roi.y = 0.0;
206 params->roi.w = params->roi.h = 1.0;
211 "width = " GST_VIDEO_SIZE_RANGE "," \
212 "height = " GST_VIDEO_SIZE_RANGE "," \
213 "framerate = " GST_VIDEO_FPS_RANGE
216 "width = " GST_VIDEO_SIZE_RANGE ", " \
217 "height = " GST_VIDEO_SIZE_RANGE ", " \
218 "framerate = " GST_VIDEO_FPS_RANGE ", " \
219 "stream-format = (string) byte-stream, " \
220 "alignment = (string) nal, " \
221 "profile = (string) { constrained-baseline, baseline, main, high }"
223 GST_VIDEO_CAPS_MAKE ("{ I420, RGB, BGR, RGBA }") /* FIXME: Map more raw formats */
225 static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
228 GST_STATIC_CAPS (H264_CAPS "; " JPEG_CAPS "; " RAW_CAPS)
232 static void gst_rpi_cam_src_finalize (GObject * object);
234 static void gst_rpi_cam_src_colorbalance_init (GstColorBalanceInterface *
236 static void gst_rpi_cam_src_orientation_init (GstVideoOrientationInterface *
238 static void gst_rpi_cam_src_direction_init (GstVideoDirectionInterface * iface);
240 static void gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
241 const GValue * value, GParamSpec * pspec);
242 static void gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
243 GValue * value, GParamSpec * pspec);
244 static gboolean gst_rpi_cam_src_start (GstBaseSrc * parent);
245 static gboolean gst_rpi_cam_src_stop (GstBaseSrc * parent);
246 static gboolean gst_rpi_cam_src_decide_allocation (GstBaseSrc * src,
248 static GstFlowReturn gst_rpi_cam_src_create (GstPushSrc * parent,
250 static GstCaps *gst_rpi_cam_src_get_caps (GstBaseSrc * src, GstCaps * filter);
251 static gboolean gst_rpi_cam_src_set_caps (GstBaseSrc * src, GstCaps * caps);
252 static GstCaps *gst_rpi_cam_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
253 static gboolean gst_rpi_cam_src_event (GstBaseSrc * src, GstEvent * event);
254 static gboolean gst_rpi_cam_src_send_event (GstElement * element,
257 #define gst_rpi_cam_src_parent_class parent_class
258 G_DEFINE_TYPE_WITH_CODE (GstRpiCamSrc, gst_rpi_cam_src,
260 G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
261 gst_rpi_cam_src_colorbalance_init);
262 G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_DIRECTION,
263 gst_rpi_cam_src_direction_init);
264 G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION,
265 gst_rpi_cam_src_orientation_init));
267 #define C_ENUM(v) ((gint) v)
269 #define GST_RPI_CAM_SRC_TYPE_SENSOR_MODE gst_rpi_cam_src_sensor_mode_get_type()
270 static GType gst_rpi_cam_src_sensor_mode_get_type (void);
273 gst_rpi_cam_src_sensor_mode_get_type (void)
275 static const GEnumValue values[] = {
276 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_AUTOMATIC), "Automatic", "automatic"},
277 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_1920x1080), "1920x1080 16:9 1-30fps",
279 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_2592x1944_FAST),
280 "2592x1944 4:3 1-15fps / 3240x2464 15fps w/ v.2 board",
282 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_2592x1944_SLOW),
283 "2592x1944 4:3 0.1666-1fps / 3240x2464 15fps w/ v.2 board",
285 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_1296x972), "1296x972 4:3 1-42fps",
287 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_1296x730), "1296x730 16:9 1-49fps",
289 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_640x480_SLOW),
290 "640x480 4:3 42.1-60fps", "640x480-slow"},
291 {C_ENUM (GST_RPI_CAM_SRC_SENSOR_MODE_640x480_FAST),
292 "640x480 4:3 60.1-90fps", "640x480-fast"},
295 static volatile GType id = 0;
296 if (g_once_init_enter ((gsize *) & id)) {
298 _id = g_enum_register_static ("GstRpiCamSrcSensorMode", values);
299 g_once_init_leave ((gsize *) & id, _id);
307 gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass)
309 GObjectClass *gobject_class;
310 GstElementClass *gstelement_class;
311 GstBaseSrcClass *basesrc_class;
312 GstPushSrcClass *pushsrc_class;
313 gobject_class = (GObjectClass *) klass;
314 gstelement_class = (GstElementClass *) klass;
315 basesrc_class = (GstBaseSrcClass *) klass;
316 pushsrc_class = (GstPushSrcClass *) klass;
318 gobject_class->finalize = gst_rpi_cam_src_finalize;
319 gobject_class->set_property = gst_rpi_cam_src_set_property;
320 gobject_class->get_property = gst_rpi_cam_src_get_property;
321 g_object_class_install_property (gobject_class, PROP_CAMERA_NUMBER,
322 g_param_spec_int ("camera-number", "Camera Number",
323 "Which camera to use on a multi-camera system - 0 or 1", 0,
324 1, CAMERA_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
325 g_object_class_install_property (gobject_class, PROP_BITRATE,
326 g_param_spec_int ("bitrate", "Bitrate",
327 "Bitrate for encoding. 0 for VBR using quantisation-parameter", 0,
328 BITRATE_HIGHEST, BITRATE_DEFAULT,
329 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
330 #ifdef USE_JPEG_CODEC
331 g_object_class_install_property (gobject_class, PROP_JPEG_QUALITY,
332 g_param_spec_int ("jpeg-quality", "JPEG Quality",
333 "Quality setting for JPEG encode", 1, 100, DEFAULT_JPEG_QUALITY,
334 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 g_object_class_install_property (gobject_class, PROP_KEYFRAME_INTERVAL,
337 g_param_spec_int ("keyframe-interval", "Keyframe Interface",
338 "Interval (in frames) between I frames. -1 = automatic, 0 = single-keyframe",
339 -1, G_MAXINT, KEYFRAME_INTERVAL_DEFAULT,
340 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
341 g_object_class_install_property (gobject_class, PROP_PREVIEW,
342 g_param_spec_boolean ("preview", "Preview Window",
343 "Display preview window overlay", TRUE,
344 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
345 g_object_class_install_property (gobject_class, PROP_FULLSCREEN,
346 g_param_spec_boolean ("fullscreen", "Fullscreen Preview",
347 "Display preview window full screen", TRUE,
348 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
349 g_object_class_install_property (gobject_class, PROP_PREVIEW_ENCODED,
350 g_param_spec_boolean ("preview-encoded", "Preview Encoded",
351 "Display encoder output in the preview", TRUE,
352 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
353 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_OPACITY,
354 g_param_spec_int ("preview-opacity", "Preview Opacity",
355 "Opacity to use for the preview window", 0, 255, 255,
356 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
357 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_X,
358 g_param_spec_int ("preview-x", "Preview window X position",
359 "Start X coordinate of the preview window (in pixels)", 0, 2048, 0,
360 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_Y,
362 g_param_spec_int ("preview-y", "Preview window Y position",
363 "Start Y coordinate of the preview window (in pixels)", 0, 2048, 0,
364 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
365 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_W,
366 g_param_spec_int ("preview-w", "Preview window width",
367 "Width of the preview window (in pixels)", 0, 2048, 1024,
368 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
369 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PREVIEW_H,
370 g_param_spec_int ("preview-h", "Preview window height",
371 "Height of the preview window (in pixels)", 0, 2048, 768,
372 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
373 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHARPNESS,
374 g_param_spec_int ("sharpness", "Sharpness", "Image capture sharpness",
375 -100, 100, SHARPNESS_DEFAULT,
376 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
377 g_object_class_install_property (gobject_class, PROP_CONTRAST,
378 g_param_spec_int ("contrast", "Contrast", "Image capture contrast", -100,
379 100, CONTRAST_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
380 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
381 g_param_spec_int ("brightness", "Brightness", "Image capture brightness",
382 0, 100, BRIGHTNESS_DEFAULT,
383 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
384 g_object_class_install_property (gobject_class, PROP_SATURATION,
385 g_param_spec_int ("saturation", "Saturation", "Image capture saturation",
386 -100, 100, SATURATION_DEFAULT,
387 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
388 g_object_class_install_property (gobject_class, PROP_ISO,
389 g_param_spec_int ("iso", "ISO", "ISO value to use (0 = Auto)", 0, 3200, 0,
390 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
391 g_object_class_install_property (gobject_class, PROP_VIDEO_STABILISATION,
392 g_param_spec_boolean ("video-stabilisation", "Video Stabilisation",
393 "Enable or disable video stabilisation", FALSE,
394 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
395 g_object_class_install_property (gobject_class, PROP_EXPOSURE_COMPENSATION,
396 g_param_spec_int ("exposure-compensation", "EV compensation",
397 "Exposure Value compensation", -10, 10, 0,
398 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
399 g_object_class_install_property (gobject_class, PROP_EXPOSURE_MODE,
400 g_param_spec_enum ("exposure-mode", "Exposure Mode",
401 "Camera exposure mode to use",
402 GST_RPI_CAM_SRC_TYPE_EXPOSURE_MODE, EXPOSURE_MODE_DEFAULT,
403 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
404 g_object_class_install_property (gobject_class, PROP_EXPOSURE_METERING_MODE,
405 g_param_spec_enum ("metering-mode", "Exposure Metering Mode",
406 "Camera exposure metering mode to use",
407 GST_RPI_CAM_SRC_TYPE_EXPOSURE_METERING_MODE,
408 EXPOSURE_METERING_MODE_DEFAULT,
409 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
410 g_object_class_install_property (gobject_class, PROP_DRC,
411 g_param_spec_enum ("drc", "DRC level", "Dynamic Range Control level",
412 GST_RPI_CAM_SRC_TYPE_DRC_LEVEL, GST_RPI_CAM_SRC_DRC_LEVEL_OFF,
413 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
414 g_object_class_install_property (gobject_class, PROP_AWB_MODE,
415 g_param_spec_enum ("awb-mode", "Automatic White Balance Mode",
416 "White Balance mode", GST_RPI_CAM_SRC_TYPE_AWB_MODE,
417 GST_RPI_CAM_SRC_AWB_MODE_AUTO,
418 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
419 g_object_class_install_property (gobject_class, PROP_AWB_GAIN_RED,
420 g_param_spec_float ("awb-gain-red", "AWB Red Gain",
421 "Manual AWB Gain for red channel when awb-mode=off", 0, 8.0, 0,
422 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
423 g_object_class_install_property (gobject_class, PROP_AWB_GAIN_BLUE,
424 g_param_spec_float ("awb-gain-blue", "AWB Blue Gain",
425 "Manual AWB Gain for blue channel when awb-mode=off", 0, 8.0, 0,
426 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
427 g_object_class_install_property (gobject_class, PROP_IMAGE_EFFECT,
428 g_param_spec_enum ("image-effect", "Image effect",
429 "Visual FX to apply to the image",
430 GST_RPI_CAM_SRC_TYPE_IMAGE_EFFECT,
431 GST_RPI_CAM_SRC_IMAGEFX_NONE,
432 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
434 PROP_IMAGE_EFFECT_PARAMS, PROP_COLOUR_EFFECTS,
436 g_object_class_install_property (gobject_class, PROP_ROTATION,
437 g_param_spec_int ("rotation", "Rotation",
438 "Rotate captured image (0, 90, 180, 270 degrees)", 0, 270, 0,
439 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
440 g_object_class_install_property (gobject_class, PROP_HFLIP,
441 g_param_spec_boolean ("hflip", "Horizontal Flip",
442 "Flip capture horizontally", FALSE,
443 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
444 g_object_class_install_property (gobject_class, PROP_VFLIP,
445 g_param_spec_boolean ("vflip", "Vertical Flip",
446 "Flip capture vertically", FALSE,
447 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
448 g_object_class_install_property (gobject_class, PROP_ROI_X,
449 g_param_spec_float ("roi-x", "ROI X",
450 "Normalised region-of-interest X coord", 0, 1.0, 0,
451 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
452 g_object_class_install_property (gobject_class, PROP_ROI_Y,
453 g_param_spec_float ("roi-y", "ROI Y",
454 "Normalised region-of-interest Y coord", 0, 1.0, 0,
455 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
456 g_object_class_install_property (gobject_class, PROP_ROI_W,
457 g_param_spec_float ("roi-w", "ROI W",
458 "Normalised region-of-interest W coord", 0, 1.0, 1.0,
459 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
460 g_object_class_install_property (gobject_class, PROP_ROI_H,
461 g_param_spec_float ("roi-h", "ROI H",
462 "Normalised region-of-interest H coord", 0, 1.0, 1.0,
463 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
464 g_object_class_install_property (gobject_class,
465 PROP_QUANTISATION_PARAMETER,
466 g_param_spec_int ("quantisation-parameter",
467 "Quantisation Parameter",
468 "Set a Quantisation Parameter approx 10-40 with bitrate=0 for VBR encoding. 0 = off",
469 0, G_MAXINT, QUANTISATION_DEFAULT,
470 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
471 g_object_class_install_property (gobject_class, PROP_INLINE_HEADERS,
472 g_param_spec_boolean ("inline-headers", "Inline Headers",
473 "Set to TRUE to insert SPS/PPS before each IDR packet", FALSE,
474 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
475 g_object_class_install_property (gobject_class, PROP_SHUTTER_SPEED,
476 g_param_spec_int ("shutter-speed", "Shutter Speed",
477 "Set a fixed shutter speed, in microseconds. (0 = Auto)", 0,
478 6000000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
479 g_object_class_install_property (gobject_class, PROP_SENSOR_MODE,
480 g_param_spec_enum ("sensor-mode", "Camera Sensor Mode",
481 "Manually set the camera sensor mode",
482 gst_rpi_cam_src_sensor_mode_get_type (),
483 GST_RPI_CAM_SRC_SENSOR_MODE_AUTOMATIC,
484 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
485 g_object_class_install_property (gobject_class, PROP_ANNOTATION_MODE,
486 g_param_spec_flags ("annotation-mode", "Annotation Mode",
487 "Flags to control annotation of the output video",
488 GST_RPI_CAM_SRC_TYPE_ANNOTATION_MODE, 0,
489 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
490 g_object_class_install_property (gobject_class, PROP_ANNOTATION_TEXT,
491 g_param_spec_string ("annotation-text", "Annotation Text",
492 "Text string to annotate onto video when annotation-mode flags include 'custom-text'",
493 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
494 g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH_TYPE,
495 g_param_spec_enum ("intra-refresh-type", "Intra Refresh Type",
496 "Type of Intra Refresh to use, -1 to disable intra refresh",
497 GST_RPI_CAM_SRC_TYPE_INTRA_REFRESH_TYPE,
498 GST_RPI_CAM_SRC_INTRA_REFRESH_TYPE_NONE,
499 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
500 g_object_class_install_property (gobject_class, PROP_ANNOTATION_TEXT_SIZE,
501 g_param_spec_int ("annotation-text-size", "Annotation text size",
502 "Set the size of annotation text (in pixels) (0 = Auto)", 0,
503 G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
504 g_object_class_install_property (gobject_class, PROP_ANNOTATION_TEXT_COLOUR,
505 g_param_spec_int ("annotation-text-colour",
506 "Annotation text colour (VUY)",
507 "Set the annotation text colour, as the integer corresponding to a VUY value eg 0x8080FF = 8421631, -1 for default",
508 -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
509 g_object_class_install_property (gobject_class,
510 PROP_ANNOTATION_TEXT_BG_COLOUR,
511 g_param_spec_int ("annotation-text-bg-colour",
512 "Annotation text background colour (VUY)",
513 "Set the annotation text background colour, as the integer corresponding to a VUY value eg 0x8080FF = 8421631, -1 for default",
514 -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
515 g_object_class_override_property (gobject_class, PROP_VIDEO_DIRECTION,
517 g_object_class_install_property (gobject_class, PROP_USE_STC,
518 g_param_spec_boolean ("use-stc", "Use System Time Clock",
519 "Use the camera STC for timestamping buffers", TRUE,
520 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
522 gst_element_class_set_static_metadata (gstelement_class,
523 "Raspberry Pi Camera Source", "Source/Video",
524 "Raspberry Pi camera module source", "Jan Schmidt <jan@centricular.com>");
525 gst_element_class_add_pad_template (gstelement_class,
526 gst_static_pad_template_get (&video_src_template));
527 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_start);
528 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_stop);
529 basesrc_class->decide_allocation =
530 GST_DEBUG_FUNCPTR (gst_rpi_cam_src_decide_allocation);
531 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_get_caps);
532 basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_set_caps);
533 basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_fixate);
534 basesrc_class->event = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_event);
535 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_send_event);
536 pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rpi_cam_src_create);
537 raspicapture_init ();
539 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_SENSOR_MODE, 0);
540 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_EXPOSURE_MODE, 0);
541 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_EXPOSURE_METERING_MODE, 0);
542 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_AWB_MODE, 0);
543 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_IMAGE_EFFECT, 0);
544 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_FLICKER_AVOIDANCE, 0);
545 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_DRC_LEVEL, 0);
546 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_ANNOTATION_MODE, 0);
547 gst_type_mark_as_plugin_api (GST_RPI_CAM_SRC_TYPE_INTRA_REFRESH_TYPE, 0);
551 gst_rpi_cam_src_init (GstRpiCamSrc * src)
553 GstColorBalanceChannel *channel;
555 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
556 gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
557 raspicapture_default_config (&src->capture_config);
558 src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT;
559 src->capture_config.verbose = 1;
560 src->capture_config.useSTC = TRUE;
562 g_mutex_init (&src->config_lock);
564 /* basesrc will generate timestamps if use-stc = false */
565 gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
567 /* Generate the channels list */
568 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
569 channel->label = g_strdup ("CONTRAST");
570 channel->min_value = -100;
571 channel->max_value = 100;
572 src->channels = g_list_append (src->channels, channel);
574 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
575 channel->label = g_strdup ("BRIGHTNESS");
576 channel->min_value = 0;
577 channel->max_value = 100;
578 src->channels = g_list_append (src->channels, channel);
580 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
581 channel->label = g_strdup ("SATURATION");
582 channel->min_value = -100;
583 channel->max_value = 100;
584 src->channels = g_list_append (src->channels, channel);
588 gst_rpi_cam_src_finalize (GObject * object)
590 GstRpiCamSrc *src = GST_RPICAMSRC (object);
591 GList *channels = NULL;
592 g_mutex_clear (&src->config_lock);
594 channels = src->channels;
596 GstColorBalanceChannel *channel = channels->data;
598 g_object_unref (channel);
599 channels->data = NULL;
600 channels = g_list_next (channels);
604 g_list_free (src->channels);
606 G_OBJECT_CLASS (gst_rpi_cam_src_parent_class)->finalize (object);
610 gst_rpi_cam_src_colorbalance_list_channels (GstColorBalance * balance)
612 GstRpiCamSrc *src = GST_RPICAMSRC (balance);
614 g_return_val_if_fail (src != NULL, NULL);
615 g_return_val_if_fail (GST_IS_RPICAMSRC (src), NULL);
617 return src->channels;
621 gst_rpi_cam_src_colorbalance_set_value (GstColorBalance * balance,
622 GstColorBalanceChannel * channel, gint value)
624 GstRpiCamSrc *src = GST_RPICAMSRC (balance);
625 gboolean changed = FALSE;
627 g_return_if_fail (src != NULL);
628 g_return_if_fail (GST_IS_RPICAMSRC (src));
629 g_return_if_fail (channel->label != NULL);
631 g_mutex_lock (&src->config_lock);
632 if (!g_ascii_strcasecmp (channel->label, "SATURATION")) {
633 changed = value != src->capture_config.camera_parameters.saturation;
634 src->capture_config.camera_parameters.saturation = value;
635 } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) {
636 changed = value != src->capture_config.camera_parameters.brightness;
637 src->capture_config.camera_parameters.brightness = value;
638 } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) {
639 changed = value != src->capture_config.camera_parameters.contrast;
640 src->capture_config.camera_parameters.contrast = value;
644 src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
646 g_mutex_unlock (&src->config_lock);
649 gst_color_balance_value_changed (balance, channel,
650 gst_color_balance_get_value (balance, channel));
655 gst_rpi_cam_src_colorbalance_get_value (GstColorBalance * balance,
656 GstColorBalanceChannel * channel)
658 GstRpiCamSrc *src = GST_RPICAMSRC (balance);
661 g_return_val_if_fail (src != NULL, 0);
662 g_return_val_if_fail (GST_IS_RPICAMSRC (src), 0);
663 g_return_val_if_fail (channel->label != NULL, 0);
665 g_mutex_lock (&src->config_lock);
667 if (!g_ascii_strcasecmp (channel->label, "SATURATION")) {
668 value = src->capture_config.camera_parameters.saturation;
669 } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) {
670 value = src->capture_config.camera_parameters.brightness;
671 } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) {
672 value = src->capture_config.camera_parameters.contrast;
675 g_mutex_unlock (&src->config_lock);
680 static GstColorBalanceType
681 gst_rpi_cam_src_colorbalance_get_balance_type (GstColorBalance * balance)
683 return GST_COLOR_BALANCE_HARDWARE;
687 gst_rpi_cam_src_reset_custom_orientation (GstRpiCamSrc * src)
689 src->orientation = GST_VIDEO_ORIENTATION_CUSTOM;
693 gst_rpi_cam_src_set_orientation (GstRpiCamSrc * src,
694 GstVideoOrientationMethod orientation)
696 switch (orientation) {
697 case GST_VIDEO_ORIENTATION_IDENTITY:
698 src->capture_config.camera_parameters.rotation = 0;
699 src->capture_config.camera_parameters.hflip = FALSE;
700 src->capture_config.camera_parameters.vflip = FALSE;
701 GST_DEBUG_OBJECT (src, "set orientation identity");
703 case GST_VIDEO_ORIENTATION_90R:
704 src->capture_config.camera_parameters.rotation = 90;
705 src->capture_config.camera_parameters.hflip = FALSE;
706 src->capture_config.camera_parameters.vflip = FALSE;
707 GST_DEBUG_OBJECT (src, "set orientation 90R");
709 case GST_VIDEO_ORIENTATION_180:
710 src->capture_config.camera_parameters.rotation = 180;
711 src->capture_config.camera_parameters.hflip = FALSE;
712 src->capture_config.camera_parameters.vflip = FALSE;
713 GST_DEBUG_OBJECT (src, "set orientation 180");
715 case GST_VIDEO_ORIENTATION_90L:
716 src->capture_config.camera_parameters.rotation = 270;
717 src->capture_config.camera_parameters.hflip = FALSE;
718 src->capture_config.camera_parameters.vflip = FALSE;
719 GST_DEBUG_OBJECT (src, "set orientation 90L");
721 case GST_VIDEO_ORIENTATION_HORIZ:
722 src->capture_config.camera_parameters.rotation = 0;
723 src->capture_config.camera_parameters.hflip = TRUE;
724 src->capture_config.camera_parameters.vflip = FALSE;
725 GST_DEBUG_OBJECT (src, "set orientation hflip");
727 case GST_VIDEO_ORIENTATION_VERT:
728 src->capture_config.camera_parameters.rotation = 0;
729 src->capture_config.camera_parameters.hflip = FALSE;
730 src->capture_config.camera_parameters.vflip = TRUE;
731 GST_DEBUG_OBJECT (src, "set orientation vflip");
733 case GST_VIDEO_ORIENTATION_UL_LR:
734 src->capture_config.camera_parameters.rotation = 90;
735 src->capture_config.camera_parameters.hflip = FALSE;
736 src->capture_config.camera_parameters.vflip = TRUE;
737 GST_DEBUG_OBJECT (src, "set orientation trans");
739 case GST_VIDEO_ORIENTATION_UR_LL:
740 src->capture_config.camera_parameters.rotation = 270;
741 src->capture_config.camera_parameters.hflip = FALSE;
742 src->capture_config.camera_parameters.vflip = TRUE;
743 GST_DEBUG_OBJECT (src, "set orientation trans");
745 case GST_VIDEO_ORIENTATION_CUSTOM:
748 GST_WARNING_OBJECT (src, "unsupported orientation %d", orientation);
752 orientation >= GST_VIDEO_ORIENTATION_IDENTITY &&
753 orientation <= GST_VIDEO_ORIENTATION_CUSTOM ?
754 orientation : GST_VIDEO_ORIENTATION_CUSTOM;
755 src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
759 gst_rpi_cam_src_direction_init (GstVideoDirectionInterface * iface)
761 /* We implement the video-direction property */
765 gst_rpi_cam_src_colorbalance_init (GstColorBalanceInterface * iface)
767 iface->list_channels = gst_rpi_cam_src_colorbalance_list_channels;
768 iface->set_value = gst_rpi_cam_src_colorbalance_set_value;
769 iface->get_value = gst_rpi_cam_src_colorbalance_get_value;
770 iface->get_balance_type = gst_rpi_cam_src_colorbalance_get_balance_type;
774 gst_rpi_cam_src_orientation_get_hflip (GstVideoOrientation * orientation,
777 GstRpiCamSrc *src = GST_RPICAMSRC (orientation);
779 g_return_val_if_fail (src != NULL, FALSE);
780 g_return_val_if_fail (GST_IS_RPICAMSRC (src), FALSE);
782 g_mutex_lock (&src->config_lock);
783 *flip = src->capture_config.camera_parameters.hflip;
784 g_mutex_unlock (&src->config_lock);
790 gst_rpi_cam_src_orientation_get_vflip (GstVideoOrientation * orientation,
793 GstRpiCamSrc *src = GST_RPICAMSRC (orientation);
795 g_return_val_if_fail (src != NULL, FALSE);
796 g_return_val_if_fail (GST_IS_RPICAMSRC (src), FALSE);
798 g_mutex_lock (&src->config_lock);
799 *flip = src->capture_config.camera_parameters.vflip;
800 g_mutex_unlock (&src->config_lock);
806 gst_rpi_cam_src_orientation_set_hflip (GstVideoOrientation * orientation,
809 GstRpiCamSrc *src = GST_RPICAMSRC (orientation);
811 g_return_val_if_fail (src != NULL, FALSE);
812 g_return_val_if_fail (GST_IS_RPICAMSRC (src), FALSE);
814 g_mutex_lock (&src->config_lock);
815 gst_rpi_cam_src_reset_custom_orientation (src);
816 src->capture_config.camera_parameters.hflip = flip;
817 src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
818 g_mutex_unlock (&src->config_lock);
824 gst_rpi_cam_src_orientation_set_vflip (GstVideoOrientation * orientation,
827 GstRpiCamSrc *src = GST_RPICAMSRC (orientation);
829 g_return_val_if_fail (src != NULL, FALSE);
830 g_return_val_if_fail (GST_IS_RPICAMSRC (src), FALSE);
832 g_mutex_lock (&src->config_lock);
833 gst_rpi_cam_src_reset_custom_orientation (src);
834 src->capture_config.camera_parameters.vflip = flip;
835 src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
836 g_mutex_unlock (&src->config_lock);
842 gst_rpi_cam_src_orientation_init (GstVideoOrientationInterface * iface)
844 iface->get_hflip = gst_rpi_cam_src_orientation_get_hflip;
845 iface->set_hflip = gst_rpi_cam_src_orientation_set_hflip;
846 iface->get_vflip = gst_rpi_cam_src_orientation_get_vflip;
847 iface->set_vflip = gst_rpi_cam_src_orientation_set_vflip;
849 /* TODO: hcenter / vcenter support */
853 gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
854 const GValue * value, GParamSpec * pspec)
856 GstRpiCamSrc *src = GST_RPICAMSRC (object);
858 g_mutex_lock (&src->config_lock);
861 case PROP_CAMERA_NUMBER:
862 src->capture_config.cameraNum = g_value_get_int (value);
865 src->capture_config.bitrate = g_value_get_int (value);
866 src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
868 case PROP_JPEG_QUALITY:
869 src->capture_config.jpegQuality = g_value_get_int (value);
870 src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
872 case PROP_KEYFRAME_INTERVAL:
873 src->capture_config.intraperiod = g_value_get_int (value);
874 src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
877 src->capture_config.preview_parameters.wantPreview =
878 g_value_get_boolean (value);
879 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
881 case PROP_PREVIEW_ENCODED:
882 src->capture_config.immutableInput = g_value_get_boolean (value);
883 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
885 case PROP_FULLSCREEN:
886 src->capture_config.preview_parameters.wantFullScreenPreview =
887 g_value_get_boolean (value);
888 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
890 case PROP_PREVIEW_OPACITY:
891 src->capture_config.preview_parameters.opacity = g_value_get_int (value);
892 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
895 src->capture_config.preview_parameters.previewWindow.x =
896 g_value_get_int (value);
897 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
900 src->capture_config.preview_parameters.previewWindow.y =
901 g_value_get_int (value);
902 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
905 src->capture_config.preview_parameters.previewWindow.width =
906 g_value_get_int (value);
907 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
910 src->capture_config.preview_parameters.previewWindow.height =
911 g_value_get_int (value);
912 src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
915 src->capture_config.camera_parameters.sharpness = g_value_get_int (value);
916 src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
919 src->capture_config.camera_parameters.contrast = g_value_get_int (value);
920 src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
922 case PROP_BRIGHTNESS:
923 src->capture_config.camera_parameters.brightness =
924 g_value_get_int (value);
925 src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
927 case PROP_SATURATION:
928 src->capture_config.camera_parameters.saturation =
929 g_value_get_int (value);
930 src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
933 src->capture_config.camera_parameters.ISO = g_value_get_int (value);
934 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
936 case PROP_VIDEO_STABILISATION:
937 src->capture_config.camera_parameters.videoStabilisation =
938 g_value_get_boolean (value);
939 src->capture_config.change_flags |= PROP_CHANGE_VIDEO_STABILISATION;
941 case PROP_EXPOSURE_COMPENSATION:
942 src->capture_config.camera_parameters.exposureCompensation =
943 g_value_get_int (value);
944 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
946 case PROP_EXPOSURE_MODE:
947 src->capture_config.camera_parameters.exposureMode =
948 g_value_get_enum (value);
949 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
951 case PROP_EXPOSURE_METERING_MODE:
952 src->capture_config.camera_parameters.exposureMeterMode =
953 g_value_get_enum (value);
954 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
957 gst_rpi_cam_src_reset_custom_orientation (src);
958 src->capture_config.camera_parameters.rotation = g_value_get_int (value);
961 src->capture_config.camera_parameters.awbMode = g_value_get_enum (value);
962 src->capture_config.change_flags |= PROP_CHANGE_AWB;
964 case PROP_AWB_GAIN_RED:
965 src->capture_config.camera_parameters.awb_gains_r =
966 g_value_get_float (value);
967 src->capture_config.change_flags |= PROP_CHANGE_AWB;
969 case PROP_AWB_GAIN_BLUE:
970 src->capture_config.camera_parameters.awb_gains_b =
971 g_value_get_float (value);
972 src->capture_config.change_flags |= PROP_CHANGE_AWB;
974 case PROP_IMAGE_EFFECT:
975 src->capture_config.camera_parameters.imageEffect =
976 g_value_get_enum (value);
977 src->capture_config.change_flags |= PROP_CHANGE_IMAGE_COLOUR_EFFECT;
980 gst_rpi_cam_src_reset_custom_orientation (src);
981 src->capture_config.camera_parameters.hflip = g_value_get_boolean (value);
982 src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
985 gst_rpi_cam_src_reset_custom_orientation (src);
986 src->capture_config.camera_parameters.vflip = g_value_get_boolean (value);
987 src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
990 src->capture_config.camera_parameters.roi.x = g_value_get_float (value);
991 src->capture_config.change_flags |= PROP_CHANGE_ROI;
994 src->capture_config.camera_parameters.roi.y = g_value_get_float (value);
995 src->capture_config.change_flags |= PROP_CHANGE_ROI;
998 src->capture_config.camera_parameters.roi.w = g_value_get_float (value);
999 src->capture_config.change_flags |= PROP_CHANGE_ROI;
1002 src->capture_config.camera_parameters.roi.h = g_value_get_float (value);
1003 src->capture_config.change_flags |= PROP_CHANGE_ROI;
1005 case PROP_QUANTISATION_PARAMETER:
1006 src->capture_config.quantisationParameter = g_value_get_int (value);
1007 src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
1009 case PROP_INLINE_HEADERS:
1010 src->capture_config.bInlineHeaders = g_value_get_boolean (value);
1012 case PROP_SHUTTER_SPEED:
1013 src->capture_config.camera_parameters.shutter_speed =
1014 g_value_get_int (value);
1015 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
1018 src->capture_config.camera_parameters.drc_level =
1019 g_value_get_enum (value);
1020 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
1022 case PROP_SENSOR_MODE:
1023 src->capture_config.sensor_mode = g_value_get_enum (value);
1024 src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
1026 case PROP_ANNOTATION_MODE:
1027 src->capture_config.camera_parameters.enable_annotate =
1028 g_value_get_flags (value);
1029 src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
1031 case PROP_ANNOTATION_TEXT:
1032 strncpy (src->capture_config.camera_parameters.annotate_string,
1033 g_value_get_string (value), MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V2);
1034 src->capture_config.
1035 camera_parameters.annotate_string[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V2
1037 src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
1039 case PROP_ANNOTATION_TEXT_SIZE:
1040 src->capture_config.camera_parameters.annotate_text_size =
1041 g_value_get_int (value);
1042 src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
1044 case PROP_ANNOTATION_TEXT_COLOUR:
1045 src->capture_config.camera_parameters.annotate_text_colour =
1046 g_value_get_int (value);
1047 src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
1049 case PROP_ANNOTATION_TEXT_BG_COLOUR:
1050 src->capture_config.camera_parameters.annotate_bg_colour =
1051 g_value_get_int (value);
1052 src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
1054 case PROP_INTRA_REFRESH_TYPE:
1055 src->capture_config.intra_refresh_type = g_value_get_enum (value);
1056 src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
1058 case PROP_VIDEO_DIRECTION:
1059 gst_rpi_cam_src_set_orientation (src, g_value_get_enum (value));
1062 src->capture_config.useSTC = g_value_get_boolean (value);
1065 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1069 g_mutex_unlock (&src->config_lock);
1073 gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
1074 GValue * value, GParamSpec * pspec)
1076 GstRpiCamSrc *src = GST_RPICAMSRC (object);
1078 g_mutex_lock (&src->config_lock);
1080 case PROP_CAMERA_NUMBER:
1081 g_value_set_int (value, src->capture_config.cameraNum);
1084 g_value_set_int (value, src->capture_config.bitrate);
1086 case PROP_JPEG_QUALITY:
1087 g_value_set_int (value, src->capture_config.jpegQuality);
1089 case PROP_KEYFRAME_INTERVAL:
1090 g_value_set_int (value, src->capture_config.intraperiod);
1093 g_value_set_boolean (value,
1094 src->capture_config.preview_parameters.wantPreview);
1096 case PROP_PREVIEW_ENCODED:
1097 g_value_set_boolean (value, src->capture_config.immutableInput);
1099 case PROP_FULLSCREEN:
1100 g_value_set_boolean (value,
1101 src->capture_config.preview_parameters.wantFullScreenPreview);
1103 case PROP_PREVIEW_OPACITY:
1104 g_value_set_int (value, src->capture_config.preview_parameters.opacity);
1106 case PROP_PREVIEW_X:
1107 g_value_set_int (value,
1108 src->capture_config.preview_parameters.previewWindow.x);
1110 case PROP_PREVIEW_Y:
1111 g_value_set_int (value,
1112 src->capture_config.preview_parameters.previewWindow.y);
1114 case PROP_PREVIEW_W:
1115 g_value_set_int (value,
1116 src->capture_config.preview_parameters.previewWindow.width);
1118 case PROP_PREVIEW_H:
1119 g_value_set_int (value,
1120 src->capture_config.preview_parameters.previewWindow.height);
1122 case PROP_SHARPNESS:
1123 g_value_set_int (value, src->capture_config.camera_parameters.sharpness);
1126 g_value_set_int (value, src->capture_config.camera_parameters.contrast);
1128 case PROP_BRIGHTNESS:
1129 g_value_set_int (value, src->capture_config.camera_parameters.brightness);
1131 case PROP_SATURATION:
1132 g_value_set_int (value, src->capture_config.camera_parameters.saturation);
1135 g_value_set_int (value, src->capture_config.camera_parameters.ISO);
1137 case PROP_VIDEO_STABILISATION:
1138 g_value_set_boolean (value,
1139 src->capture_config.camera_parameters.videoStabilisation != 0);
1141 case PROP_EXPOSURE_COMPENSATION:
1142 g_value_set_int (value,
1143 src->capture_config.camera_parameters.exposureCompensation);
1145 case PROP_EXPOSURE_MODE:
1146 g_value_set_enum (value,
1147 src->capture_config.camera_parameters.exposureMode);
1149 case PROP_EXPOSURE_METERING_MODE:
1150 g_value_set_enum (value,
1151 src->capture_config.camera_parameters.exposureMeterMode);
1154 g_value_set_int (value, src->capture_config.camera_parameters.rotation);
1157 g_value_set_enum (value, src->capture_config.camera_parameters.awbMode);
1159 case PROP_AWB_GAIN_RED:
1160 g_value_set_float (value,
1161 src->capture_config.camera_parameters.awb_gains_r);
1163 case PROP_AWB_GAIN_BLUE:
1164 g_value_set_float (value,
1165 src->capture_config.camera_parameters.awb_gains_b);
1167 case PROP_IMAGE_EFFECT:
1168 g_value_set_enum (value,
1169 src->capture_config.camera_parameters.imageEffect);
1172 g_value_set_boolean (value,
1173 src->capture_config.camera_parameters.hflip != 0);
1176 g_value_set_boolean (value,
1177 src->capture_config.camera_parameters.vflip != 0);
1180 g_value_set_float (value, src->capture_config.camera_parameters.roi.x);
1183 g_value_set_float (value, src->capture_config.camera_parameters.roi.y);
1186 g_value_set_float (value, src->capture_config.camera_parameters.roi.w);
1189 g_value_set_float (value, src->capture_config.camera_parameters.roi.h);
1191 case PROP_QUANTISATION_PARAMETER:
1192 g_value_set_int (value, src->capture_config.quantisationParameter);
1194 case PROP_INLINE_HEADERS:
1195 g_value_set_boolean (value, src->capture_config.bInlineHeaders);
1197 case PROP_SHUTTER_SPEED:
1198 g_value_set_int (value,
1199 src->capture_config.camera_parameters.shutter_speed);
1202 g_value_set_enum (value, src->capture_config.camera_parameters.drc_level);
1204 case PROP_SENSOR_MODE:
1205 g_value_set_enum (value, src->capture_config.sensor_mode);
1207 case PROP_ANNOTATION_MODE:
1208 g_value_set_flags (value,
1209 src->capture_config.camera_parameters.enable_annotate);
1211 case PROP_ANNOTATION_TEXT:
1212 g_value_set_string (value,
1213 src->capture_config.camera_parameters.annotate_string);
1215 case PROP_ANNOTATION_TEXT_SIZE:
1216 g_value_set_int (value,
1217 src->capture_config.camera_parameters.annotate_text_size);
1219 case PROP_ANNOTATION_TEXT_COLOUR:
1220 g_value_set_int (value,
1221 src->capture_config.camera_parameters.annotate_text_colour);
1223 case PROP_ANNOTATION_TEXT_BG_COLOUR:
1224 g_value_set_int (value,
1225 src->capture_config.camera_parameters.annotate_bg_colour);
1227 case PROP_INTRA_REFRESH_TYPE:
1228 g_value_set_enum (value, src->capture_config.intra_refresh_type);
1230 case PROP_VIDEO_DIRECTION:
1231 g_value_set_enum (value, src->orientation);
1234 g_value_set_boolean (value, src->capture_config.useSTC);
1237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1240 g_mutex_unlock (&src->config_lock);
1244 gst_rpi_cam_src_start (GstBaseSrc * parent)
1246 GstRpiCamSrc *src = GST_RPICAMSRC (parent);
1247 GST_LOG_OBJECT (src, "In src_start()");
1248 /* Ensure basesrc timestamping is off is use-stc is on */
1249 if (src->capture_config.useSTC)
1250 gst_base_src_set_do_timestamp (GST_BASE_SRC (src), FALSE);
1251 g_mutex_lock (&src->config_lock);
1252 src->capture_state = raspi_capture_setup (&src->capture_config);
1253 /* Clear all capture flags */
1254 src->capture_config.change_flags = 0;
1255 g_mutex_unlock (&src->config_lock);
1256 if (src->capture_state == NULL)
1262 gst_rpi_cam_src_stop (GstBaseSrc * parent)
1264 GstRpiCamSrc *src = GST_RPICAMSRC (parent);
1266 raspi_capture_stop (src->capture_state);
1267 raspi_capture_free (src->capture_state);
1268 src->capture_state = NULL;
1269 src->started = FALSE;
1274 gst_rpi_cam_src_send_event (GstElement * parent, GstEvent * event)
1276 GstRpiCamSrc *src = GST_RPICAMSRC (parent);
1278 switch (GST_EVENT_TYPE (event)) {
1279 case GST_EVENT_CUSTOM_DOWNSTREAM:
1280 case GST_EVENT_CUSTOM_UPSTREAM:
1281 if (gst_video_event_is_force_key_unit (event)) {
1283 ret = raspi_capture_request_i_frame (src->capture_state);
1287 gst_event_unref (event);
1289 ret = GST_ELEMENT_CLASS (parent_class)->send_event (parent, event);
1293 ret = GST_ELEMENT_CLASS (parent_class)->send_event (parent, event);
1300 gst_rpi_cam_src_event (GstBaseSrc * parent, GstEvent * event)
1302 GstRpiCamSrc *src = GST_RPICAMSRC (parent);
1304 switch (GST_EVENT_TYPE (event)) {
1305 case GST_EVENT_CUSTOM_DOWNSTREAM:
1306 case GST_EVENT_CUSTOM_UPSTREAM:
1307 if (gst_video_event_is_force_key_unit (event)) {
1309 ret = raspi_capture_request_i_frame (src->capture_state);
1314 ret = GST_BASE_SRC_CLASS (parent_class)->event (parent, event);
1318 ret = GST_BASE_SRC_CLASS (parent_class)->event (parent, event);
1325 gst_rpi_cam_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
1327 GstRpiCamSrc *src = GST_RPICAMSRC (bsrc);
1331 caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
1332 if (src->capture_state == NULL)
1334 /* FIXME: Retrieve limiting parameters from the camera module, max width/height fps-range */
1335 caps = gst_caps_make_writable (caps);
1336 for (i = 0; i < gst_caps_get_size (caps); i++) {
1337 GstStructure *s = gst_caps_get_structure (caps, i);
1338 if (gst_structure_has_name (s, "video/x-h264")) {
1339 gst_caps_set_simple (caps, "width", GST_TYPE_INT_RANGE, 1, 1920, "height",
1340 GST_TYPE_INT_RANGE, 1, 1080, "framerate", GST_TYPE_FRACTION_RANGE, 0,
1341 1, RPICAMSRC_MAX_FPS, 1, NULL);
1343 gst_caps_set_simple (caps, "width", GST_TYPE_INT_RANGE, 1, 3240, "height",
1344 GST_TYPE_INT_RANGE, 1, 2464, "framerate", GST_TYPE_FRACTION_RANGE, 0,
1345 1, RPICAMSRC_MAX_FPS, 1, NULL);
1349 GST_DEBUG_OBJECT (src, "get_caps returning %" GST_PTR_FORMAT, caps);
1354 gst_rpi_cam_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
1356 GstRpiCamSrc *src = GST_RPICAMSRC (bsrc);
1358 GstStructure *structure;
1359 const gchar *profile_str = NULL;
1361 GST_DEBUG_OBJECT (src, "In set_caps %" GST_PTR_FORMAT, caps);
1362 if (!gst_video_info_from_caps (&info, caps))
1365 structure = gst_caps_get_structure (caps, 0);
1366 if (gst_structure_has_name (structure, "video/x-h264")) {
1367 src->capture_config.encoding = MMAL_ENCODING_H264;
1368 profile_str = gst_structure_get_string (structure, "profile");
1370 if (g_str_equal (profile_str, "baseline"))
1371 src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
1372 else if (g_str_equal (profile_str, "constrained-baseline"))
1373 src->capture_config.profile =
1374 MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
1375 else if (g_str_equal (profile_str, "main"))
1376 src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
1377 else if (g_str_equal (profile_str, "high"))
1378 src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
1380 g_warning ("Unknown profile string in rpicamsrc caps: %s", profile_str);
1382 } else if (gst_structure_has_name (structure, "image/jpeg")) {
1383 #ifdef USE_JPEG_CODEC
1384 src->capture_config.encoding = MMAL_ENCODING_JPEG;
1386 src->capture_config.encoding = MMAL_ENCODING_MJPEG;
1390 switch (GST_VIDEO_INFO_FORMAT (&info)) {
1391 case GST_VIDEO_FORMAT_I420:
1392 src->capture_config.encoding = MMAL_ENCODING_I420;
1394 case GST_VIDEO_FORMAT_RGB:
1395 src->capture_config.encoding = MMAL_ENCODING_RGB24;
1397 case GST_VIDEO_FORMAT_BGR:
1398 src->capture_config.encoding = MMAL_ENCODING_BGR24;
1400 case GST_VIDEO_FORMAT_RGBA:
1401 src->capture_config.encoding = MMAL_ENCODING_RGBA;
1408 src->capture_config.width = info.width;
1409 src->capture_config.height = info.height;
1410 src->capture_config.fps_n = info.fps_n;
1411 src->capture_config.fps_d = info.fps_d;
1413 if (info.fps_n != 0 && info.fps_d != 0)
1414 src->duration = gst_util_uint64_scale_int (GST_SECOND, info.fps_d,
1417 src->duration = GST_CLOCK_TIME_NONE;
1423 gst_rpi_cam_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
1425 GST_LOG_OBJECT (bsrc, "In decide_allocation");
1426 return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
1430 gst_rpi_cam_src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
1432 GstStructure *structure;
1434 GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
1435 caps = gst_caps_make_writable (caps);
1436 for (i = 0; i < gst_caps_get_size (caps); ++i) {
1437 structure = gst_caps_get_structure (caps, i);
1438 /* Fixate to 1920x1080 resolution if possible */
1439 gst_structure_fixate_field_nearest_int (structure, "width", 1920);
1440 gst_structure_fixate_field_nearest_int (structure, "height", 1080);
1441 gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
1442 gst_structure_fixate_field (structure, "format");
1445 GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
1446 caps = GST_BASE_SRC_CLASS (parent_class)->fixate (basesrc, caps);
1450 static GstFlowReturn
1451 gst_rpi_cam_src_create (GstPushSrc * parent, GstBuffer ** buf)
1453 GstRpiCamSrc *src = GST_RPICAMSRC (parent);
1455 GstClock *clock = NULL;
1456 GstClockTime base_time;
1458 if (!src->started) {
1459 g_mutex_lock (&src->config_lock);
1460 raspi_capture_update_config (src->capture_state, &src->capture_config,
1462 src->capture_config.change_flags = 0;
1463 g_mutex_unlock (&src->config_lock);
1465 if (!raspi_capture_start (src->capture_state))
1466 return GST_FLOW_ERROR;
1467 src->started = TRUE;
1470 GST_OBJECT_LOCK (src);
1471 if ((clock = GST_ELEMENT_CLOCK (src)) != NULL)
1472 gst_object_ref (clock);
1473 base_time = GST_ELEMENT_CAST (src)->base_time;
1474 GST_OBJECT_UNLOCK (src);
1476 g_mutex_lock (&src->config_lock);
1477 if (src->capture_config.change_flags) {
1478 raspi_capture_update_config (src->capture_state, &src->capture_config,
1480 src->capture_config.change_flags = 0;
1482 g_mutex_unlock (&src->config_lock);
1487 GstBuffer *cbuf = NULL;
1489 /* FIXME: Use custom allocator */
1491 raspi_capture_fill_buffer (src->capture_state, &cbuf, clock, base_time);
1494 GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT,
1495 gst_buffer_get_size (cbuf));
1498 /* Only set the duration when we have a PTS update from the rpi encoder.
1499 * not every buffer is a frame */
1500 if (GST_BUFFER_PTS_IS_VALID (cbuf))
1501 GST_BUFFER_DURATION (cbuf) = src->duration;
1505 *buf = gst_buffer_append (*buf, cbuf);
1509 } while (ret == GST_FLOW_KEEP_ACCUMULATING);
1511 if (ret == GST_FLOW_ERROR_TIMEOUT) {
1512 GST_ELEMENT_ERROR (src, STREAM, FAILED,
1513 ("Camera capture timed out."),
1514 ("Waiting for a buffer from the camera took too long."));
1515 ret = GST_FLOW_ERROR;
1518 if (ret != GST_FLOW_OK)
1519 gst_clear_buffer (buf);
1522 gst_object_unref (clock);
1532 plugin_init (GstPlugin * plugin)
1536 GST_DEBUG_CATEGORY_INIT (gst_rpi_cam_src_debug, "rpicamsrc",
1537 0, "rpicamsrc debug");
1539 ret = gst_element_register (plugin, "rpicamsrc", GST_RANK_NONE,
1540 GST_TYPE_RPICAMSRC);
1542 ret &= gst_device_provider_register (plugin, "rpicamsrcdeviceprovider",
1543 GST_RANK_PRIMARY, GST_TYPE_RPICAMSRC_DEVICE_PROVIDER);
1548 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1551 "Raspberry Pi Camera Source",
1552 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)