1 /* GStreamer android.hardware.Camera Source
3 * Copyright (C) 2012, Cisco Systems, Inc.
4 * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * SECTION:element-ahcsrc
26 * ahcsrc can be used to capture video from android devices. It uses the
27 * android.hardware.Camera Java API to capture from the system's cameras.
29 * In order for the plugin to get registered, it must be able to find its
30 * Java callbacks class. That class is embedded as a jar file inside the source
31 * element (if properly compiled) and will be written to a temporary directory
32 * so it can be loaded into the virtual machine.
33 * In order for it to work, an environment variable must be set to a writable
35 * The source will look for the environment variable “TMP� which must contain
36 * the absolute path to a writable directory.
37 * It can be retrieved using the following Java code :
39 * context.getCacheDir().getAbsolutePath();
41 * Where the @context variable is an object of type android.content.Context
42 * (including its subclasses android.app.Activity or android.app.Application).
43 * Another optional environment variable can be set for pointing to the
44 * optimized dex classes directory. If the environment variable “DEX� is
45 * available, it will be used, otherwise, the directory in the “TMP� environment
46 * variable will be used for the optimized dex directory.
47 * The system dex directory can be obtained using the following Java code :
49 * context.getDir("dex", 0).getAbsolutePath();
52 * > Those environment variable must be set before gst_init is called from
55 * > If the "TMP" environment variable is not available or the directory is not
56 * > writable or any other issue happens while trying to load the embedded jar
57 * > file, then the source will fallback on trying to load the class directly
58 * > from the running application.
59 * > The file com/gstreamer/GstAhcCallback.java in the source's directory can be
60 * > copied into the Android application so it can be loaded at runtime
61 * > as a fallback mechanism.
69 #include <gst/video/video.h>
70 #define GST_USE_UNSTABLE_API
71 #include <gst/interfaces/photography.h>
73 #include "gstjniutils.h"
75 #include "gstahcsrc.h"
78 static void gst_ahc_src_set_property (GObject * object, guint prop_id,
79 const GValue * value, GParamSpec * pspec);
80 static void gst_ahc_src_get_property (GObject * object, guint prop_id,
81 GValue * value, GParamSpec * pspec);
82 static void gst_ahc_src_finalize (GObject * object);
85 static GstStateChangeReturn gst_ahc_src_change_state (GstElement * element,
86 GstStateChange transition);
89 static GstCaps *gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter);
90 static gboolean gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps);
91 static GstCaps *gst_ahc_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
92 static gboolean gst_ahc_src_start (GstBaseSrc * bsrc);
93 static gboolean gst_ahc_src_stop (GstBaseSrc * bsrc);
94 static gboolean gst_ahc_src_unlock (GstBaseSrc * bsrc);
95 static gboolean gst_ahc_src_unlock_stop (GstBaseSrc * bsrc);
96 static GstFlowReturn gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer);
97 static gboolean gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query);
100 static void gst_ahc_src_photography_init (gpointer g_iface,
101 gpointer iface_data);
102 static gboolean gst_ahc_src_get_ev_compensation (GstPhotography * photo,
104 static gboolean _white_balance_to_enum (const gchar * white_balance,
105 GstPhotographyWhiteBalanceMode * mode);
106 static gboolean gst_ahc_src_get_white_balance_mode (GstPhotography * photo,
107 GstPhotographyWhiteBalanceMode * wb_mode);
108 static gboolean _color_effects_to_enum (const gchar * color_effect,
109 GstPhotographyColorToneMode * mode);
110 static gboolean gst_ahc_src_get_colour_tone_mode (GstPhotography * photo,
111 GstPhotographyColorToneMode * tone_mode);
112 static gboolean _scene_modes_to_enum (const gchar * scene,
113 GstPhotographySceneMode * mode);
114 static gboolean gst_ahc_src_get_scene_mode (GstPhotography * photo,
115 GstPhotographySceneMode * scene_mode);
116 static gboolean _flash_modes_to_enum (const gchar * flash,
117 GstPhotographyFlashMode * mode);
118 static gboolean gst_ahc_src_get_flash_mode (GstPhotography * photo,
119 GstPhotographyFlashMode * flash_mode);
120 static gboolean gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom);
121 static gboolean _antibanding_to_enum (const gchar * antibanding,
122 GstPhotographyFlickerReductionMode * mode);
123 static gboolean gst_ahc_src_get_flicker_mode (GstPhotography * photo,
124 GstPhotographyFlickerReductionMode * flicker_mode);
125 static gboolean _focus_modes_to_enum (const gchar * focus,
126 GstPhotographyFocusMode * mode);
127 static gboolean gst_ahc_src_get_focus_mode (GstPhotography * photo,
128 GstPhotographyFocusMode * focus_mode);
130 static gboolean gst_ahc_src_set_ev_compensation (GstPhotography * photo,
132 static gboolean gst_ahc_src_set_white_balance_mode (GstPhotography * photo,
133 GstPhotographyWhiteBalanceMode wb_mode);
134 static gboolean gst_ahc_src_set_colour_tone_mode (GstPhotography * photo,
135 GstPhotographyColorToneMode tone_mode);
136 static gboolean gst_ahc_src_set_scene_mode (GstPhotography * photo,
137 GstPhotographySceneMode scene_mode);
138 static gboolean gst_ahc_src_set_flash_mode (GstPhotography * photo,
139 GstPhotographyFlashMode flash_mode);
140 static gboolean gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom);
141 static gboolean gst_ahc_src_set_flicker_mode (GstPhotography * photo,
142 GstPhotographyFlickerReductionMode flicker_mode);
143 static gboolean gst_ahc_src_set_focus_mode (GstPhotography * photo,
144 GstPhotographyFocusMode focus_mode);
146 static GstPhotographyCaps gst_ahc_src_get_capabilities (GstPhotography * photo);
147 static void gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on);
150 static void gst_ahc_src_close (GstAHCSrc * self);
151 static void gst_ahc_src_on_preview_frame (jbyteArray data, gpointer user_data);
152 static void gst_ahc_src_on_error (gint error, gpointer user_data);
153 static void gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data);
155 #define NUM_CALLBACK_BUFFERS 5
157 #define GST_AHC_SRC_CAPS_STR \
158 GST_VIDEO_CAPS_MAKE_WITH_FEATURES("ANY", " { YV12, YUY2, NV21, NV16, RGB16 }")
160 static GstStaticPadTemplate gst_ahc_src_pad_template =
161 GST_STATIC_PAD_TEMPLATE ("src",
164 GST_STATIC_CAPS (GST_AHC_SRC_CAPS_STR));
166 GST_DEBUG_CATEGORY_STATIC (gst_ahc_src_debug);
167 #define GST_CAT_DEFAULT gst_ahc_src_debug
169 #define parent_class gst_ahc_src_parent_class
177 PROP_DEVICE_ORIENTATION,
179 PROP_HORIZONTAL_VIEW_ANGLE,
180 PROP_VERTICAL_VIEW_ANGLE,
181 PROP_VIDEO_STABILIZATION,
186 PROP_NOISE_REDUCTION,
192 PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
193 PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
199 PROP_MIN_EXPOSURE_TIME,
200 PROP_MAX_EXPOSURE_TIME,
203 PROP_COLOR_TEMPERATURE,
208 static GParamSpec *properties[PROP_LAST];
210 #define DEFAULT_DEVICE "0"
212 G_DEFINE_TYPE_WITH_CODE (GstAHCSrc, gst_ahc_src, GST_TYPE_PUSH_SRC,
213 G_IMPLEMENT_INTERFACE (GST_TYPE_PHOTOGRAPHY, gst_ahc_src_photography_init));
215 #define CAMERA_FACING_BACK 0
216 #define CAMERA_FACING_FRONT 1
219 gst_ahc_src_facing_get_type (void)
221 static GType type = 0;
222 static const GEnumValue types[] = {
223 {CAMERA_FACING_BACK, "Back", "back"},
224 {CAMERA_FACING_FRONT, "Front", "front"},
229 type = g_enum_register_static ("GstAHCSrcFacing", types);
234 #define GST_AHC_SRC_FACING_TYPE (gst_ahc_src_facing_get_type())
237 gst_ahc_src_photography_init (gpointer g_iface, gpointer iface_data)
239 GstPhotographyInterface *iface = g_iface;
241 iface->get_ev_compensation = gst_ahc_src_get_ev_compensation;
242 iface->get_white_balance_mode = gst_ahc_src_get_white_balance_mode;
243 iface->get_color_tone_mode = gst_ahc_src_get_colour_tone_mode;
244 iface->get_scene_mode = gst_ahc_src_get_scene_mode;
245 iface->get_flash_mode = gst_ahc_src_get_flash_mode;
246 iface->get_zoom = gst_ahc_src_get_zoom;
247 iface->get_flicker_mode = gst_ahc_src_get_flicker_mode;
248 iface->get_focus_mode = gst_ahc_src_get_focus_mode;
250 iface->set_ev_compensation = gst_ahc_src_set_ev_compensation;
251 iface->set_white_balance_mode = gst_ahc_src_set_white_balance_mode;
252 iface->set_color_tone_mode = gst_ahc_src_set_colour_tone_mode;
253 iface->set_scene_mode = gst_ahc_src_set_scene_mode;
254 iface->set_flash_mode = gst_ahc_src_set_flash_mode;
255 iface->set_zoom = gst_ahc_src_set_zoom;
256 iface->set_flicker_mode = gst_ahc_src_set_flicker_mode;
257 iface->set_focus_mode = gst_ahc_src_set_focus_mode;
259 iface->get_capabilities = gst_ahc_src_get_capabilities;
260 iface->set_autofocus = gst_ahc_src_set_autofocus;
264 gst_ahc_src_class_init (GstAHCSrcClass * klass)
266 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
267 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
268 GstPushSrcClass *gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
269 GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
271 gobject_class->set_property = gst_ahc_src_set_property;
272 gobject_class->get_property = gst_ahc_src_get_property;
273 gobject_class->finalize = gst_ahc_src_finalize;
275 element_class->change_state = gst_ahc_src_change_state;
277 gstbasesrc_class->get_caps = gst_ahc_src_getcaps;
278 gstbasesrc_class->set_caps = gst_ahc_src_setcaps;
279 gstbasesrc_class->fixate = gst_ahc_src_fixate;
280 gstbasesrc_class->start = gst_ahc_src_start;
281 gstbasesrc_class->stop = gst_ahc_src_stop;
282 gstbasesrc_class->unlock = gst_ahc_src_unlock;
283 gstbasesrc_class->unlock_stop = gst_ahc_src_unlock_stop;
284 gstbasesrc_class->query = gst_ahc_src_query;
286 gstpushsrc_class->create = gst_ahc_src_create;
288 gst_element_class_add_static_pad_template (element_class,
289 &gst_ahc_src_pad_template);
294 * The Device ID of the camera to capture from
296 properties[PROP_DEVICE] = g_param_spec_string ("device",
297 "Device", "Device ID", DEFAULT_DEVICE,
298 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
299 g_object_class_install_property (gobject_class, PROP_DEVICE,
300 properties[PROP_DEVICE]);
303 * GstAHCSrc:device-name:
305 * A user-friendly name for the camera device
307 properties[PROP_DEVICE_NAME] = g_param_spec_string ("device-name",
308 "Device name", "Device name", NULL,
309 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
310 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
311 properties[PROP_DEVICE_NAME]);
314 * GstAHCSrc:device-orientation:
316 * The orientation of the currently set camera @device.
317 * The value is the angle that the camera image needs to be rotated clockwise
318 * so it shows correctly on the display in its natural orientation.
319 * It should be 0, 90, 180, or 270.
321 properties[PROP_DEVICE_ORIENTATION] = g_param_spec_int ("device-orientation",
322 "Device orientation", "The orientation of the camera image",
323 0, 360, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
324 g_object_class_install_property (gobject_class, PROP_DEVICE_ORIENTATION,
325 properties[PROP_DEVICE_ORIENTATION]);
328 * GstAHCSrc:device-facing:
330 * The direction that the currently select camera @device faces.
332 * A value of 0 means the camera is facing the opposite direction as the
333 * screen while a value of 1 means the camera is facing the same direction
336 properties[PROP_DEVICE_FACING] = g_param_spec_enum ("device-facing",
337 "Device facing", "The direction that the camera faces",
338 GST_AHC_SRC_FACING_TYPE, CAMERA_FACING_BACK,
339 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
340 g_object_class_install_property (gobject_class, PROP_DEVICE_FACING,
341 properties[PROP_DEVICE_FACING]);
344 * GstAHCSrc:focal-length:
346 * Gets the focal length (in millimeter) of the camera.
348 properties[PROP_FOCAL_LENGTH] = g_param_spec_float ("focal-length",
349 "Focal length", "Gets the focal length (in millimeter) of the camera",
350 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
351 g_object_class_install_property (gobject_class, PROP_FOCAL_LENGTH,
352 properties[PROP_FOCAL_LENGTH]);
355 * GstAHCSrc:horizontal-view-angle:
357 * Gets the horizontal angle of view in degrees.
359 properties[PROP_HORIZONTAL_VIEW_ANGLE] =
360 g_param_spec_float ("horizontal-view-angle", "Horizontal view angle",
361 "Gets the horizontal angle of view in degrees",
362 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
363 g_object_class_install_property (gobject_class, PROP_HORIZONTAL_VIEW_ANGLE,
364 properties[PROP_HORIZONTAL_VIEW_ANGLE]);
367 * GstAHCSrc:vertical-view-angle:
369 * Gets the vertical angle of view in degrees.
371 properties[PROP_VERTICAL_VIEW_ANGLE] =
372 g_param_spec_float ("vertical-view-angle", "Vertical view angle",
373 "Gets the vertical angle of view in degrees",
374 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
375 g_object_class_install_property (gobject_class, PROP_VERTICAL_VIEW_ANGLE,
376 properties[PROP_VERTICAL_VIEW_ANGLE]);
379 * GstAHCSrc:video-stabilization:
381 * Video stabilization reduces the shaking due to the motion of the camera.
383 properties[PROP_VIDEO_STABILIZATION] =
384 g_param_spec_boolean ("video-stabilization", "Video stabilization",
385 "Video stabilization reduces the shaking due to the motion of the camera",
386 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
387 g_object_class_install_property (gobject_class, PROP_VIDEO_STABILIZATION,
388 properties[PROP_VIDEO_STABILIZATION]);
391 * GstAHCSrc:smooth-zoom:
393 * If enabled, then smooth zooming will be used when the @zoom property is
394 * changed. In that case, the @zoom property can be queried to know the
395 * current zoom level while the smooth zoom is in progress.
397 properties[PROP_SMOOTH_ZOOM] = g_param_spec_boolean ("smooth-zoom",
398 "Smooth Zoom", "Use smooth zoom when available",
399 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
400 g_object_class_install_property (gobject_class, PROP_SMOOTH_ZOOM,
401 properties[PROP_SMOOTH_ZOOM]);
403 /* Override GstPhotography properties */
404 g_object_class_override_property (gobject_class, PROP_WB_MODE,
405 GST_PHOTOGRAPHY_PROP_WB_MODE);
406 properties[PROP_WB_MODE] = g_object_class_find_property (gobject_class,
407 GST_PHOTOGRAPHY_PROP_WB_MODE);
409 g_object_class_override_property (gobject_class, PROP_COLOUR_TONE,
410 GST_PHOTOGRAPHY_PROP_COLOR_TONE);
411 properties[PROP_COLOUR_TONE] = g_object_class_find_property (gobject_class,
412 GST_PHOTOGRAPHY_PROP_COLOR_TONE);
414 g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
415 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
416 properties[PROP_SCENE_MODE] = g_object_class_find_property (gobject_class,
417 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
419 g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
420 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
421 properties[PROP_FLASH_MODE] = g_object_class_find_property (gobject_class,
422 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
424 g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
425 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
426 properties[PROP_NOISE_REDUCTION] =
427 g_object_class_find_property (gobject_class,
428 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
430 g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
431 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
432 properties[PROP_CAPABILITIES] = g_object_class_find_property (gobject_class,
433 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
435 g_object_class_override_property (gobject_class, PROP_EV_COMP,
436 GST_PHOTOGRAPHY_PROP_EV_COMP);
437 properties[PROP_EV_COMP] = g_object_class_find_property (gobject_class,
438 GST_PHOTOGRAPHY_PROP_EV_COMP);
440 g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
441 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
442 properties[PROP_ISO_SPEED] = g_object_class_find_property (gobject_class,
443 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
445 g_object_class_override_property (gobject_class, PROP_APERTURE,
446 GST_PHOTOGRAPHY_PROP_APERTURE);
447 properties[PROP_APERTURE] = g_object_class_find_property (gobject_class,
448 GST_PHOTOGRAPHY_PROP_APERTURE);
451 g_object_class_override_property (gobject_class, PROP_EXPOSURE_MODE,
452 GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE);
453 properties[PROP_EXPOSURE] = g_object_class_find_property (gobject_class,
454 GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE);
457 g_object_class_override_property (gobject_class,
458 PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
459 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
460 properties[PROP_IMAGE_CAPTURE_SUPPORTED_CAPS] =
461 g_object_class_find_property (gobject_class,
462 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
464 g_object_class_override_property (gobject_class,
465 PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
466 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
467 properties[PROP_IMAGE_PREVIEW_SUPPORTED_CAPS] =
468 g_object_class_find_property (gobject_class,
469 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
471 g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
472 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
473 properties[PROP_FLICKER_MODE] = g_object_class_find_property (gobject_class,
474 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
476 g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
477 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
478 properties[PROP_FOCUS_MODE] = g_object_class_find_property (gobject_class,
479 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
481 g_object_class_override_property (gobject_class, PROP_ZOOM,
482 GST_PHOTOGRAPHY_PROP_ZOOM);
483 properties[PROP_ZOOM] = g_object_class_find_property (gobject_class,
484 GST_PHOTOGRAPHY_PROP_ZOOM);
486 g_object_class_override_property (gobject_class, PROP_WHITE_POINT,
487 GST_PHOTOGRAPHY_PROP_WHITE_POINT);
488 properties[PROP_WHITE_POINT] = g_object_class_find_property (gobject_class,
489 GST_PHOTOGRAPHY_PROP_WHITE_POINT);
491 g_object_class_override_property (gobject_class, PROP_MIN_EXPOSURE_TIME,
492 GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME);
493 properties[PROP_MIN_EXPOSURE_TIME] =
494 g_object_class_find_property (gobject_class,
495 GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME);
497 g_object_class_override_property (gobject_class, PROP_MAX_EXPOSURE_TIME,
498 GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME);
499 properties[PROP_MAX_EXPOSURE_TIME] =
500 g_object_class_find_property (gobject_class,
501 GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME);
503 g_object_class_override_property (gobject_class, PROP_LENS_FOCUS,
504 GST_PHOTOGRAPHY_PROP_LENS_FOCUS);
505 properties[PROP_LENS_FOCUS] = g_object_class_find_property (gobject_class,
506 GST_PHOTOGRAPHY_PROP_LENS_FOCUS);
508 g_object_class_override_property (gobject_class, PROP_EXPOSURE_TIME,
509 GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME);
510 properties[PROP_EXPOSURE_TIME] = g_object_class_find_property (gobject_class,
511 GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME);
513 g_object_class_override_property (gobject_class, PROP_COLOR_TEMPERATURE,
514 GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE);
515 properties[PROP_COLOR_TEMPERATURE] =
516 g_object_class_find_property (gobject_class,
517 GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE);
519 g_object_class_override_property (gobject_class, PROP_ANALOG_GAIN,
520 GST_PHOTOGRAPHY_PROP_ANALOG_GAIN);
521 properties[PROP_ANALOG_GAIN] = g_object_class_find_property (gobject_class,
522 GST_PHOTOGRAPHY_PROP_ANALOG_GAIN);
524 gst_element_class_set_static_metadata (element_class,
525 "Android Camera Source",
526 "Source/Video/Hardware",
527 "Reads frames from android.hardware.Camera class into buffers",
528 "Youness Alaoui <youness.alaoui@collabora.co.uk>");
530 GST_DEBUG_CATEGORY_INIT (gst_ahc_src_debug, "ahcsrc", 0,
531 "android.hardware.Camera source element");
535 _data_queue_check_full (GstDataQueue * queue, guint visible,
536 guint bytes, guint64 time, gpointer checkdata)
542 gst_ahc_src_init (GstAHCSrc * self)
544 gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
545 gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
546 gst_base_src_set_do_timestamp (GST_BASE_SRC (self), FALSE);
549 self->texture = NULL;
551 self->queue = gst_data_queue_new (_data_queue_check_full, NULL, NULL, NULL);
553 self->previous_ts = GST_CLOCK_TIME_NONE;
555 g_mutex_init (&self->mutex);
559 gst_ahc_src_finalize (GObject * object)
561 GstAHCSrc *self = GST_AHC_SRC (object);
563 g_clear_object (&self->queue);
564 g_mutex_clear (&self->mutex);
566 G_OBJECT_CLASS (parent_class)->finalize (object);
570 gst_ahc_src_set_property (GObject * object, guint prop_id,
571 const GValue * value, GParamSpec * pspec)
573 GstAHCSrc *self = GST_AHC_SRC (object);
575 GST_DEBUG_OBJECT (self, "set props %d", prop_id);
579 const gchar *dev = g_value_get_string (value);
580 gchar *endptr = NULL;
583 device = g_ascii_strtoll (dev, &endptr, 10);
584 if (endptr != dev && endptr[0] == 0 && device < G_MAXINT)
585 self->device = (gint) device;
588 case PROP_VIDEO_STABILIZATION:
590 GstAHCParameters *params;
592 params = gst_ah_camera_get_parameters (self->camera);
594 gst_ahc_parameters_set_video_stabilization (params,
595 g_value_get_boolean (value));
596 gst_ah_camera_set_parameters (self->camera, params);
597 gst_ahc_parameters_free (params);
601 case PROP_SMOOTH_ZOOM:
602 self->smooth_zoom = g_value_get_boolean (value);
605 GstPhotographyWhiteBalanceMode wb = g_value_get_enum (value);
607 gst_ahc_src_set_white_balance_mode (GST_PHOTOGRAPHY (self), wb);
610 case PROP_COLOUR_TONE:{
611 GstPhotographyColorToneMode tone = g_value_get_enum (value);
613 gst_ahc_src_set_colour_tone_mode (GST_PHOTOGRAPHY (self), tone);
616 case PROP_SCENE_MODE:{
617 GstPhotographySceneMode scene = g_value_get_enum (value);
619 gst_ahc_src_set_scene_mode (GST_PHOTOGRAPHY (self), scene);
622 case PROP_FLASH_MODE:{
623 GstPhotographyFlashMode flash = g_value_get_enum (value);
625 gst_ahc_src_set_flash_mode (GST_PHOTOGRAPHY (self), flash);
629 gfloat ev = g_value_get_float (value);
631 gst_ahc_src_set_ev_compensation (GST_PHOTOGRAPHY (self), ev);
634 case PROP_FLICKER_MODE:{
635 GstPhotographyFlickerReductionMode flicker = g_value_get_enum (value);
637 gst_ahc_src_set_flicker_mode (GST_PHOTOGRAPHY (self), flicker);
640 case PROP_FOCUS_MODE:{
641 GstPhotographyFocusMode focus = g_value_get_enum (value);
643 gst_ahc_src_set_focus_mode (GST_PHOTOGRAPHY (self), focus);
647 gfloat zoom = g_value_get_float (value);
649 gst_ahc_src_set_zoom (GST_PHOTOGRAPHY (self), zoom);
652 case PROP_NOISE_REDUCTION:
655 case PROP_EXPOSURE_MODE:
656 case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:
657 case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS:
658 case PROP_WHITE_POINT:
659 case PROP_MIN_EXPOSURE_TIME:
660 case PROP_MAX_EXPOSURE_TIME:
661 case PROP_LENS_FOCUS:
662 case PROP_EXPOSURE_TIME:
663 case PROP_COLOR_TEMPERATURE:
664 case PROP_ANALOG_GAIN:
667 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
673 gst_ahc_src_get_property (GObject * object, guint prop_id,
674 GValue * value, GParamSpec * pspec)
676 GstAHCSrc *self = GST_AHC_SRC (object);
681 gchar *dev = g_strdup_printf ("%d", self->device);
683 g_value_take_string (value, dev);
686 case PROP_DEVICE_NAME:{
687 GstAHCCameraInfo info;
690 if (gst_ah_camera_get_camera_info (self->device, &info))
691 dev = g_strdup_printf ("#%d %s", self->device,
692 info.facing == CameraInfo_CAMERA_FACING_BACK ? "Back" : "Front");
694 dev = g_strdup_printf ("#%d", self->device);
696 g_value_take_string (value, dev);
699 case PROP_DEVICE_FACING:{
700 GstAHCCameraInfo info;
702 if (gst_ah_camera_get_camera_info (self->device, &info))
703 g_value_set_enum (value, info.facing == CameraInfo_CAMERA_FACING_BACK ?
704 CAMERA_FACING_BACK : CAMERA_FACING_FRONT);
706 g_value_set_enum (value, CAMERA_FACING_BACK);
709 case PROP_DEVICE_ORIENTATION:{
710 GstAHCCameraInfo info;
712 if (gst_ah_camera_get_camera_info (self->device, &info))
713 g_value_set_int (value, info.orientation);
715 g_value_set_int (value, 0);
718 case PROP_FOCAL_LENGTH:
720 GstAHCParameters *params;
722 params = gst_ah_camera_get_parameters (self->camera);
724 g_value_set_float (value,
725 gst_ahc_parameters_get_focal_length (params));
726 gst_ahc_parameters_free (params);
730 case PROP_HORIZONTAL_VIEW_ANGLE:
732 GstAHCParameters *params;
734 params = gst_ah_camera_get_parameters (self->camera);
736 g_value_set_float (value,
737 gst_ahc_parameters_get_horizontal_view_angle (params));
738 gst_ahc_parameters_free (params);
742 case PROP_VERTICAL_VIEW_ANGLE:
744 GstAHCParameters *params;
746 params = gst_ah_camera_get_parameters (self->camera);
748 g_value_set_float (value,
749 gst_ahc_parameters_get_vertical_view_angle (params));
750 gst_ahc_parameters_free (params);
754 case PROP_VIDEO_STABILIZATION:
756 GstAHCParameters *params;
758 params = gst_ah_camera_get_parameters (self->camera);
760 g_value_set_boolean (value,
761 gst_ahc_parameters_get_video_stabilization (params));
762 gst_ahc_parameters_free (params);
766 case PROP_SMOOTH_ZOOM:
767 g_value_set_boolean (value, self->smooth_zoom);
770 GstPhotographyWhiteBalanceMode wb;
772 if (gst_ahc_src_get_white_balance_mode (GST_PHOTOGRAPHY (self), &wb))
773 g_value_set_enum (value, wb);
776 case PROP_COLOUR_TONE:{
777 GstPhotographyColorToneMode tone;
779 if (gst_ahc_src_get_colour_tone_mode (GST_PHOTOGRAPHY (self), &tone))
780 g_value_set_enum (value, tone);
783 case PROP_SCENE_MODE:{
784 GstPhotographySceneMode scene;
786 if (gst_ahc_src_get_scene_mode (GST_PHOTOGRAPHY (self), &scene))
787 g_value_set_enum (value, scene);
790 case PROP_FLASH_MODE:{
791 GstPhotographyFlashMode flash;
793 if (gst_ahc_src_get_flash_mode (GST_PHOTOGRAPHY (self), &flash))
794 g_value_set_enum (value, flash);
797 case PROP_CAPABILITIES:{
798 GstPhotographyCaps caps;
800 caps = gst_ahc_src_get_capabilities (GST_PHOTOGRAPHY (self));
801 g_value_set_ulong (value, caps);
807 if (gst_ahc_src_get_ev_compensation (GST_PHOTOGRAPHY (self), &ev))
808 g_value_set_float (value, ev);
811 case PROP_FLICKER_MODE:{
812 GstPhotographyFlickerReductionMode flicker;
814 if (gst_ahc_src_get_flicker_mode (GST_PHOTOGRAPHY (self), &flicker))
815 g_value_set_enum (value, flicker);
818 case PROP_FOCUS_MODE:{
819 GstPhotographyFocusMode focus;
821 if (gst_ahc_src_get_focus_mode (GST_PHOTOGRAPHY (self), &focus))
822 g_value_set_enum (value, focus);
828 if (gst_ahc_src_get_zoom (GST_PHOTOGRAPHY (self), &zoom))
829 g_value_set_float (value, zoom);
832 case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:
833 case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS:
834 case PROP_NOISE_REDUCTION:
837 case PROP_EXPOSURE_MODE:
838 case PROP_WHITE_POINT:
839 case PROP_MIN_EXPOSURE_TIME:
840 case PROP_MAX_EXPOSURE_TIME:
841 case PROP_LENS_FOCUS:
842 case PROP_EXPOSURE_TIME:
843 case PROP_COLOR_TEMPERATURE:
844 case PROP_ANALOG_GAIN:
847 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
853 _antibanding_to_enum (const gchar * antibanding,
854 GstPhotographyFlickerReductionMode * mode)
856 if (antibanding == Parameters_ANTIBANDING_AUTO)
857 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO;
858 else if (antibanding == Parameters_ANTIBANDING_50HZ)
859 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ;
860 else if (antibanding == Parameters_ANTIBANDING_60HZ)
861 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ;
862 else if (antibanding == Parameters_ANTIBANDING_OFF)
863 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF;
871 _white_balance_to_enum (const gchar * white_balance,
872 GstPhotographyWhiteBalanceMode * mode)
874 if (white_balance == Parameters_WHITE_BALANCE_AUTO)
875 *mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
876 else if (white_balance == Parameters_WHITE_BALANCE_INCANDESCENT)
877 *mode = GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN;
878 else if (white_balance == Parameters_WHITE_BALANCE_FLUORESCENT)
879 *mode = GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT;
880 else if (white_balance == Parameters_WHITE_BALANCE_WARM_FLUORESCENT)
881 *mode = GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT;
882 else if (white_balance == Parameters_WHITE_BALANCE_DAYLIGHT)
883 *mode = GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT;
884 else if (white_balance == Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT)
885 *mode = GST_PHOTOGRAPHY_WB_MODE_CLOUDY;
886 else if (white_balance == Parameters_WHITE_BALANCE_TWILIGHT)
887 *mode = GST_PHOTOGRAPHY_WB_MODE_SUNSET;
888 else if (white_balance == Parameters_WHITE_BALANCE_SHADE)
889 *mode = GST_PHOTOGRAPHY_WB_MODE_SHADE;
897 _color_effects_to_enum (const gchar * color_effect,
898 GstPhotographyColorToneMode * mode)
900 if (color_effect == Parameters_EFFECT_NONE)
901 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
902 else if (color_effect == Parameters_EFFECT_MONO)
903 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE;
904 else if (color_effect == Parameters_EFFECT_NEGATIVE)
905 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE;
906 else if (color_effect == Parameters_EFFECT_SOLARIZE)
907 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE;
908 else if (color_effect == Parameters_EFFECT_SEPIA)
909 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA;
910 else if (color_effect == Parameters_EFFECT_POSTERIZE)
911 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE;
912 else if (color_effect == Parameters_EFFECT_WHITEBOARD)
913 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD;
914 else if (color_effect == Parameters_EFFECT_BLACKBOARD)
915 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD;
916 else if (color_effect == Parameters_EFFECT_AQUA)
917 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA;
925 _scene_modes_to_enum (const gchar * scene, GstPhotographySceneMode * mode)
927 if (scene == Parameters_SCENE_MODE_AUTO)
928 *mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
929 else if (scene == Parameters_SCENE_MODE_ACTION)
930 *mode = GST_PHOTOGRAPHY_SCENE_MODE_ACTION;
931 else if (scene == Parameters_SCENE_MODE_PORTRAIT)
932 *mode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT;
933 else if (scene == Parameters_SCENE_MODE_LANDSCAPE)
934 *mode = GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE;
935 else if (scene == Parameters_SCENE_MODE_NIGHT)
936 *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT;
937 else if (scene == Parameters_SCENE_MODE_NIGHT_PORTRAIT)
938 *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT;
939 else if (scene == Parameters_SCENE_MODE_THEATRE)
940 *mode = GST_PHOTOGRAPHY_SCENE_MODE_THEATRE;
941 else if (scene == Parameters_SCENE_MODE_BEACH)
942 *mode = GST_PHOTOGRAPHY_SCENE_MODE_BEACH;
943 else if (scene == Parameters_SCENE_MODE_SNOW)
944 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SNOW;
945 else if (scene == Parameters_SCENE_MODE_SUNSET)
946 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SUNSET;
947 else if (scene == Parameters_SCENE_MODE_STEADYPHOTO)
948 *mode = GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO;
949 else if (scene == Parameters_SCENE_MODE_FIREWORKS)
950 *mode = GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS;
951 else if (scene == Parameters_SCENE_MODE_SPORTS)
952 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT;
953 else if (scene == Parameters_SCENE_MODE_PARTY)
954 *mode = GST_PHOTOGRAPHY_SCENE_MODE_PARTY;
955 else if (scene == Parameters_SCENE_MODE_CANDLELIGHT)
956 *mode = GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT;
957 else if (scene == Parameters_SCENE_MODE_BARCODE)
958 *mode = GST_PHOTOGRAPHY_SCENE_MODE_BARCODE;
966 _flash_modes_to_enum (const gchar * flash, GstPhotographyFlashMode * mode)
968 if (flash == Parameters_FLASH_MODE_OFF)
969 *mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
970 else if (flash == Parameters_FLASH_MODE_AUTO)
971 *mode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
972 else if (flash == Parameters_FLASH_MODE_ON)
973 *mode = GST_PHOTOGRAPHY_FLASH_MODE_ON;
974 else if (flash == Parameters_FLASH_MODE_RED_EYE)
975 *mode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE;
976 else if (flash == Parameters_FLASH_MODE_TORCH)
977 *mode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN;
985 _focus_modes_to_enum (const gchar * focus, GstPhotographyFocusMode * mode)
987 if (focus == Parameters_FOCUS_MODE_AUTO)
988 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
989 else if (focus == Parameters_FOCUS_MODE_INFINITY)
990 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY;
991 else if (focus == Parameters_FOCUS_MODE_MACRO)
992 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_MACRO;
993 else if (focus == Parameters_FOCUS_MODE_FIXED)
994 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL;
995 else if (focus == Parameters_FOCUS_MODE_EDOF)
996 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED;
997 else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_VIDEO)
998 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED;
999 else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_PICTURE)
1000 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL;
1008 gst_ahc_src_get_ev_compensation (GstPhotography * photo, gfloat * ev_comp)
1010 GstAHCSrc *self = GST_AHC_SRC (photo);
1011 gboolean ret = FALSE;
1014 GstAHCParameters *params;
1016 params = gst_ah_camera_get_parameters (self->camera);
1021 ev = gst_ahc_parameters_get_exposure_compensation (params);
1022 min = gst_ahc_parameters_get_min_exposure_compensation (params);
1023 max = gst_ahc_parameters_get_max_exposure_compensation (params);
1024 step = gst_ahc_parameters_get_exposure_compensation_step (params);
1026 if (step != 0.0 && min != max && min <= ev && ev <= max) {
1028 *ev_comp = ev * step;
1031 gst_ahc_parameters_free (params);
1039 gst_ahc_src_get_white_balance_mode (GstPhotography * photo,
1040 GstPhotographyWhiteBalanceMode * wb_mode)
1042 GstAHCSrc *self = GST_AHC_SRC (photo);
1043 gboolean ret = FALSE;
1046 GstAHCParameters *params;
1048 params = gst_ah_camera_get_parameters (self->camera);
1050 const gchar *wb = gst_ahc_parameters_get_white_balance (params);
1051 GstPhotographyWhiteBalanceMode mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
1053 if (_white_balance_to_enum (wb, &mode)) {
1060 gst_ahc_parameters_free (params);
1068 gst_ahc_src_get_colour_tone_mode (GstPhotography * photo,
1069 GstPhotographyColorToneMode * tone_mode)
1071 GstAHCSrc *self = GST_AHC_SRC (photo);
1072 gboolean ret = FALSE;
1075 GstAHCParameters *params;
1077 params = gst_ah_camera_get_parameters (self->camera);
1079 const gchar *effect = gst_ahc_parameters_get_color_effect (params);
1080 GstPhotographyColorToneMode mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
1082 if (_color_effects_to_enum (effect, &mode)) {
1089 gst_ahc_parameters_free (params);
1097 gst_ahc_src_get_scene_mode (GstPhotography * photo,
1098 GstPhotographySceneMode * scene_mode)
1100 GstAHCSrc *self = GST_AHC_SRC (photo);
1101 gboolean ret = FALSE;
1103 if (scene_mode && self->camera) {
1104 GstAHCParameters *params;
1106 params = gst_ah_camera_get_parameters (self->camera);
1108 const gchar *scene = gst_ahc_parameters_get_scene_mode (params);
1109 GstPhotographySceneMode mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
1111 if (_scene_modes_to_enum (scene, &mode)) {
1118 gst_ahc_parameters_free (params);
1126 gst_ahc_src_get_flash_mode (GstPhotography * photo,
1127 GstPhotographyFlashMode * flash_mode)
1129 GstAHCSrc *self = GST_AHC_SRC (photo);
1130 gboolean ret = FALSE;
1133 GstAHCParameters *params;
1135 params = gst_ah_camera_get_parameters (self->camera);
1137 const gchar *flash = gst_ahc_parameters_get_flash_mode (params);
1138 GstPhotographyFlashMode mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
1140 if (_flash_modes_to_enum (flash, &mode)) {
1147 gst_ahc_parameters_free (params);
1155 gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom)
1157 GstAHCSrc *self = GST_AHC_SRC (photo);
1158 gboolean ret = FALSE;
1161 GstAHCParameters *params;
1163 params = gst_ah_camera_get_parameters (self->camera);
1165 GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params);
1166 gint zoom_idx = gst_ahc_parameters_get_zoom (params);
1167 gint max_zoom = gst_ahc_parameters_get_max_zoom (params);
1169 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1) &&
1170 zoom_idx >= 0 && zoom_idx < max_zoom) {
1173 zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, zoom_idx));
1175 *zoom = (gfloat) zoom_value / 100.0;
1180 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1181 gst_ahc_parameters_free (params);
1189 gst_ahc_src_get_flicker_mode (GstPhotography * photo,
1190 GstPhotographyFlickerReductionMode * flicker_mode)
1192 GstAHCSrc *self = GST_AHC_SRC (photo);
1193 gboolean ret = FALSE;
1196 GstAHCParameters *params;
1198 params = gst_ah_camera_get_parameters (self->camera);
1200 const gchar *antibanding = gst_ahc_parameters_get_antibanding (params);
1201 GstPhotographyFlickerReductionMode mode =
1202 GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO;
1204 if (_antibanding_to_enum (antibanding, &mode)) {
1208 *flicker_mode = mode;
1211 gst_ahc_parameters_free (params);
1219 gst_ahc_src_get_focus_mode (GstPhotography * photo,
1220 GstPhotographyFocusMode * focus_mode)
1222 GstAHCSrc *self = GST_AHC_SRC (photo);
1223 gboolean ret = FALSE;
1226 GstAHCParameters *params;
1228 params = gst_ah_camera_get_parameters (self->camera);
1230 const gchar *focus = gst_ahc_parameters_get_focus_mode (params);
1231 GstPhotographyFocusMode mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
1233 if (_focus_modes_to_enum (focus, &mode)) {
1240 gst_ahc_parameters_free (params);
1249 gst_ahc_src_set_ev_compensation (GstPhotography * photo, gfloat ev_comp)
1251 GstAHCSrc *self = GST_AHC_SRC (photo);
1252 gboolean ret = FALSE;
1255 GstAHCParameters *params;
1257 params = gst_ah_camera_get_parameters (self->camera);
1262 ev = gst_ahc_parameters_get_exposure_compensation (params);
1263 min = gst_ahc_parameters_get_min_exposure_compensation (params);
1264 max = gst_ahc_parameters_get_max_exposure_compensation (params);
1265 step = gst_ahc_parameters_get_exposure_compensation_step (params);
1266 if (step != 0.0 && min != max &&
1267 (min * step) <= ev_comp && ev_comp <= (max * step)) {
1268 ev = ev_comp / step;
1269 if ((ev * step) == ev_comp) {
1270 gst_ahc_parameters_set_exposure_compensation (params, ev);
1271 ret = gst_ah_camera_set_parameters (self->camera, params);
1275 gst_ahc_parameters_free (params);
1282 gst_ahc_src_set_white_balance_mode (GstPhotography * photo,
1283 GstPhotographyWhiteBalanceMode wb_mode)
1285 GstAHCSrc *self = GST_AHC_SRC (photo);
1286 gboolean ret = FALSE;
1289 GstAHCParameters *params;
1291 params = gst_ah_camera_get_parameters (self->camera);
1293 const gchar *white_balance = NULL;
1296 case GST_PHOTOGRAPHY_WB_MODE_AUTO:
1297 white_balance = Parameters_WHITE_BALANCE_AUTO;
1299 case GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT:
1300 white_balance = Parameters_WHITE_BALANCE_DAYLIGHT;
1302 case GST_PHOTOGRAPHY_WB_MODE_CLOUDY:
1303 white_balance = Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT;
1305 case GST_PHOTOGRAPHY_WB_MODE_SUNSET:
1306 white_balance = Parameters_WHITE_BALANCE_TWILIGHT;
1308 case GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN:
1309 white_balance = Parameters_WHITE_BALANCE_INCANDESCENT;
1311 case GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT:
1312 white_balance = Parameters_WHITE_BALANCE_FLUORESCENT;
1314 case GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT:
1315 white_balance = Parameters_WHITE_BALANCE_WARM_FLUORESCENT;
1317 case GST_PHOTOGRAPHY_WB_MODE_SHADE:
1318 white_balance = Parameters_WHITE_BALANCE_SHADE;
1321 white_balance = NULL;
1325 if (white_balance) {
1326 gst_ahc_parameters_set_white_balance (params, white_balance);
1327 ret = gst_ah_camera_set_parameters (self->camera, params);
1329 gst_ahc_parameters_free (params);
1337 gst_ahc_src_set_colour_tone_mode (GstPhotography * photo,
1338 GstPhotographyColorToneMode tone_mode)
1340 GstAHCSrc *self = GST_AHC_SRC (photo);
1341 gboolean ret = FALSE;
1344 GstAHCParameters *params;
1346 params = gst_ah_camera_get_parameters (self->camera);
1348 const gchar *color_effect = NULL;
1350 switch (tone_mode) {
1351 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL:
1352 color_effect = Parameters_EFFECT_NONE;
1354 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA:
1355 color_effect = Parameters_EFFECT_SEPIA;
1357 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE:
1358 color_effect = Parameters_EFFECT_NEGATIVE;
1360 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE:
1361 color_effect = Parameters_EFFECT_MONO;
1363 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE:
1364 color_effect = Parameters_EFFECT_SOLARIZE;
1366 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE:
1367 color_effect = Parameters_EFFECT_POSTERIZE;
1369 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD:
1370 color_effect = Parameters_EFFECT_WHITEBOARD;
1372 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD:
1373 color_effect = Parameters_EFFECT_BLACKBOARD;
1375 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA:
1376 color_effect = Parameters_EFFECT_AQUA;
1378 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NATURAL:
1379 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_VIVID:
1380 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_COLORSWAP:
1381 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_OUT_OF_FOCUS:
1382 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKY_BLUE:
1383 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRASS_GREEN:
1384 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKIN_WHITEN:
1386 color_effect = NULL;
1391 gst_ahc_parameters_set_color_effect (params, color_effect);
1392 ret = gst_ah_camera_set_parameters (self->camera, params);
1394 gst_ahc_parameters_free (params);
1402 gst_ahc_src_set_scene_mode (GstPhotography * photo,
1403 GstPhotographySceneMode scene_mode)
1405 GstAHCSrc *self = GST_AHC_SRC (photo);
1406 gboolean ret = FALSE;
1409 GstAHCParameters *params;
1411 params = gst_ah_camera_get_parameters (self->camera);
1413 const gchar *scene = NULL;
1415 switch (scene_mode) {
1416 case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT:
1417 scene = Parameters_SCENE_MODE_PORTRAIT;
1419 case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE:
1420 scene = Parameters_SCENE_MODE_LANDSCAPE;
1422 case GST_PHOTOGRAPHY_SCENE_MODE_SPORT:
1423 scene = Parameters_SCENE_MODE_SPORTS;
1425 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT:
1426 scene = Parameters_SCENE_MODE_NIGHT;
1428 case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
1429 scene = Parameters_SCENE_MODE_AUTO;
1431 case GST_PHOTOGRAPHY_SCENE_MODE_ACTION:
1432 scene = Parameters_SCENE_MODE_ACTION;
1434 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT:
1435 scene = Parameters_SCENE_MODE_NIGHT_PORTRAIT;
1437 case GST_PHOTOGRAPHY_SCENE_MODE_THEATRE:
1438 scene = Parameters_SCENE_MODE_THEATRE;
1440 case GST_PHOTOGRAPHY_SCENE_MODE_BEACH:
1441 scene = Parameters_SCENE_MODE_BEACH;
1443 case GST_PHOTOGRAPHY_SCENE_MODE_SNOW:
1444 scene = Parameters_SCENE_MODE_SNOW;
1446 case GST_PHOTOGRAPHY_SCENE_MODE_SUNSET:
1447 scene = Parameters_SCENE_MODE_SUNSET;
1449 case GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO:
1450 scene = Parameters_SCENE_MODE_STEADYPHOTO;
1452 case GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS:
1453 scene = Parameters_SCENE_MODE_FIREWORKS;
1455 case GST_PHOTOGRAPHY_SCENE_MODE_PARTY:
1456 scene = Parameters_SCENE_MODE_PARTY;
1458 case GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT:
1459 scene = Parameters_SCENE_MODE_CANDLELIGHT;
1461 case GST_PHOTOGRAPHY_SCENE_MODE_BARCODE:
1462 scene = Parameters_SCENE_MODE_BARCODE;
1464 case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL:
1465 case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP:
1472 gst_ahc_parameters_set_scene_mode (params, scene);
1473 ret = gst_ah_camera_set_parameters (self->camera, params);
1475 gst_ahc_parameters_free (params);
1483 gst_ahc_src_set_flash_mode (GstPhotography * photo,
1484 GstPhotographyFlashMode flash_mode)
1486 GstAHCSrc *self = GST_AHC_SRC (photo);
1487 gboolean ret = FALSE;
1490 GstAHCParameters *params;
1492 params = gst_ah_camera_get_parameters (self->camera);
1494 const gchar *flash = NULL;
1496 switch (flash_mode) {
1497 case GST_PHOTOGRAPHY_FLASH_MODE_AUTO:
1498 flash = Parameters_FLASH_MODE_AUTO;
1500 case GST_PHOTOGRAPHY_FLASH_MODE_OFF:
1501 flash = Parameters_FLASH_MODE_OFF;
1503 case GST_PHOTOGRAPHY_FLASH_MODE_ON:
1504 flash = Parameters_FLASH_MODE_ON;
1506 case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN:
1507 flash = Parameters_FLASH_MODE_TORCH;
1509 case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE:
1510 flash = Parameters_FLASH_MODE_RED_EYE;
1518 gst_ahc_parameters_set_flash_mode (params, flash);
1519 ret = gst_ah_camera_set_parameters (self->camera, params);
1521 gst_ahc_parameters_free (params);
1529 gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom)
1531 GstAHCSrc *self = GST_AHC_SRC (photo);
1532 gboolean ret = FALSE;
1535 GstAHCParameters *params;
1537 params = gst_ah_camera_get_parameters (self->camera);
1539 GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params);
1540 gint max_zoom = gst_ahc_parameters_get_max_zoom (params);
1543 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1)) {
1545 gint value = zoom * 100;
1547 for (i = 0; i < max_zoom + 1; i++) {
1548 gint zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, i));
1550 if (value == zoom_value)
1555 if (zoom_idx != -1) {
1556 if (self->smooth_zoom &&
1557 gst_ahc_parameters_is_smooth_zoom_supported (params)) {
1558 // First, we need to cancel any previous smooth zoom operation
1559 gst_ah_camera_stop_smooth_zoom (self->camera);
1560 ret = gst_ah_camera_start_smooth_zoom (self->camera, zoom_idx);
1562 gst_ahc_parameters_set_zoom (params, zoom_idx);
1563 ret = gst_ah_camera_set_parameters (self->camera, params);
1567 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1568 gst_ahc_parameters_free (params);
1576 gst_ahc_src_set_flicker_mode (GstPhotography * photo,
1577 GstPhotographyFlickerReductionMode flicker_mode)
1579 GstAHCSrc *self = GST_AHC_SRC (photo);
1580 gboolean ret = FALSE;
1583 GstAHCParameters *params;
1585 params = gst_ah_camera_get_parameters (self->camera);
1587 const gchar *antibanding = NULL;
1589 switch (flicker_mode) {
1590 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF:
1591 antibanding = Parameters_ANTIBANDING_OFF;
1593 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ:
1594 antibanding = Parameters_ANTIBANDING_50HZ;
1596 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ:
1597 antibanding = Parameters_ANTIBANDING_60HZ;
1599 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO:
1600 antibanding = Parameters_ANTIBANDING_AUTO;
1608 gst_ahc_parameters_set_antibanding (params, antibanding);
1609 ret = gst_ah_camera_set_parameters (self->camera, params);
1611 gst_ahc_parameters_free (params);
1619 gst_ahc_src_set_focus_mode (GstPhotography * photo,
1620 GstPhotographyFocusMode focus_mode)
1622 GstAHCSrc *self = GST_AHC_SRC (photo);
1623 gboolean ret = FALSE;
1626 GstAHCParameters *params;
1628 params = gst_ah_camera_get_parameters (self->camera);
1630 const gchar *focus = NULL;
1632 switch (focus_mode) {
1633 case GST_PHOTOGRAPHY_FOCUS_MODE_AUTO:
1634 focus = Parameters_FOCUS_MODE_AUTO;
1636 case GST_PHOTOGRAPHY_FOCUS_MODE_MACRO:
1637 focus = Parameters_FOCUS_MODE_MACRO;
1639 case GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY:
1640 focus = Parameters_FOCUS_MODE_INFINITY;
1642 case GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL:
1643 focus = Parameters_FOCUS_MODE_FIXED;
1645 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL:
1646 focus = Parameters_FOCUS_MODE_CONTINUOUS_PICTURE;
1648 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED:
1649 focus = Parameters_FOCUS_MODE_CONTINUOUS_VIDEO;
1651 case GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED:
1652 focus = Parameters_FOCUS_MODE_EDOF;
1654 case GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT:
1661 gst_ahc_parameters_set_focus_mode (params, focus);
1662 ret = gst_ah_camera_set_parameters (self->camera, params);
1664 gst_ahc_parameters_free (params);
1671 static GstPhotographyCaps
1672 gst_ahc_src_get_capabilities (GstPhotography * photo)
1674 GstAHCSrc *self = GST_AHC_SRC (photo);
1676 GstPhotographyCaps caps = GST_PHOTOGRAPHY_CAPS_EV_COMP |
1677 GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
1678 GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
1679 GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_ZOOM;
1682 GstAHCParameters *params;
1684 params = gst_ah_camera_get_parameters (self->camera);
1685 if (!gst_ahc_parameters_is_zoom_supported (params))
1686 caps &= ~GST_PHOTOGRAPHY_CAPS_ZOOM;
1688 gst_ahc_parameters_free (params);
1695 gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data)
1697 GstAHCSrc *self = GST_AHC_SRC (user_data);
1699 GST_WARNING_OBJECT (self, "Auto focus completed : %d", success);
1700 gst_element_post_message (GST_ELEMENT (self),
1701 gst_message_new_custom (GST_MESSAGE_ELEMENT, GST_OBJECT (self),
1702 gst_structure_new_empty (GST_PHOTOGRAPHY_AUTOFOCUS_DONE)));
1706 gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on)
1708 GstAHCSrc *self = GST_AHC_SRC (photo);
1712 gst_ah_camera_auto_focus (self->camera, gst_ahc_src_on_auto_focus, self);
1714 gst_ah_camera_cancel_auto_focus (self->camera);
1720 _compare_formats (int f1, int f2)
1724 /* YV12 has priority */
1725 if (f1 == ImageFormat_YV12)
1727 if (f2 == ImageFormat_YV12)
1730 if (f1 == ImageFormat_NV21)
1732 if (f2 == ImageFormat_NV21)
1734 /* Then we don't care */
1739 _compare_sizes (GstAHCSize * s1, GstAHCSize * s2)
1741 return ((s2->width * s2->height) - (s1->width * s1->height));
1746 _compare_ranges (int *r1, int *r2)
1749 /* Smallest range */
1750 return (r1[1] - r1[0]) - (r2[1] - r2[0]);
1753 return r2[1] - r1[1];
1757 gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter)
1759 GstAHCSrc *self = GST_AHC_SRC (src);
1762 GstCaps *ret = gst_caps_new_empty ();
1763 GstAHCParameters *params;
1765 params = gst_ah_camera_get_parameters (self->camera);
1767 GList *formats, *sizes, *ranges;
1769 int previous_format = ImageFormat_UNKNOWN;
1771 formats = gst_ahc_parameters_get_supported_preview_formats (params);
1772 formats = g_list_sort (formats, (GCompareFunc) _compare_formats);
1773 sizes = gst_ahc_parameters_get_supported_preview_sizes (params);
1774 sizes = g_list_sort (sizes, (GCompareFunc) _compare_sizes);
1775 ranges = gst_ahc_parameters_get_supported_preview_fps_range (params);
1776 ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges);
1777 GST_DEBUG_OBJECT (self, "Supported preview formats:");
1779 for (i = formats; i; i = i->next) {
1780 int f = GPOINTER_TO_INT (i->data);
1781 gchar *format_string = NULL;
1782 GstStructure *format = NULL;
1784 /* Ignore duplicates */
1785 if (f == previous_format)
1788 /* Can't use switch/case because the values are not constants */
1789 if (f == ImageFormat_NV16) {
1790 GST_DEBUG_OBJECT (self, " NV16 (%d)", f);
1791 format_string = g_strdup ("NV16");
1792 } else if (f == ImageFormat_NV21) {
1793 GST_DEBUG_OBJECT (self, " NV21 (%d)", f);
1794 format_string = g_strdup ("NV21");
1795 } else if (f == ImageFormat_RGB_565) {
1796 GstVideoFormat vformat;
1797 vformat = gst_video_format_from_masks (16, 16, G_LITTLE_ENDIAN,
1798 0xf800, 0x07e0, 0x001f, 0x0);
1799 GST_DEBUG_OBJECT (self, " RGB565 (%d)", f);
1800 format_string = g_strdup (gst_video_format_to_string (vformat));
1801 } else if (f == ImageFormat_YUY2) {
1802 GST_DEBUG_OBJECT (self, " YUY2 (%d)", f);
1803 format_string = g_strdup ("YUY2");
1804 } else if (f == ImageFormat_YV12) {
1805 GST_DEBUG_OBJECT (self, " YV12 (%d)", f);
1806 format_string = g_strdup ("YV12");
1808 previous_format = f;
1810 if (format_string) {
1811 format = gst_structure_new ("video/x-raw",
1812 "format", G_TYPE_STRING, format_string, NULL);
1813 g_free (format_string);
1817 for (j = sizes; j; j = j->next) {
1818 GstAHCSize *s = j->data;
1821 size = gst_structure_copy (format);
1822 gst_structure_set (size, "width", G_TYPE_INT, s->width,
1823 "height", G_TYPE_INT, s->height,
1824 "interlaced", G_TYPE_BOOLEAN, FALSE,
1825 "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
1827 for (k = ranges; k; k = k->next) {
1828 int *range = k->data;
1831 s = gst_structure_copy (size);
1832 if (range[0] == range[1]) {
1833 gst_structure_set (s, "framerate", GST_TYPE_FRACTION,
1834 range[0], 1000, NULL);
1836 gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE,
1837 range[0], 1000, range[1], 1000, NULL);
1839 gst_caps_append_structure (ret, s);
1841 gst_structure_free (size);
1843 gst_structure_free (format);
1846 GST_DEBUG_OBJECT (self, "Supported preview sizes:");
1847 for (i = sizes; i; i = i->next) {
1848 GstAHCSize *s = i->data;
1850 GST_DEBUG_OBJECT (self, " %dx%d", s->width, s->height);
1852 GST_DEBUG_OBJECT (self, "Supported preview fps range:");
1853 for (i = ranges; i; i = i->next) {
1854 int *range = i->data;
1856 GST_DEBUG_OBJECT (self, " [%d, %d]", range[0], range[1]);
1859 gst_ahc_parameters_supported_preview_formats_free (formats);
1860 gst_ahc_parameters_supported_preview_sizes_free (sizes);
1861 gst_ahc_parameters_supported_preview_fps_range_free (ranges);
1862 gst_ahc_parameters_free (params);
1872 gst_ahc_src_fixate (GstBaseSrc * src, GstCaps * caps)
1874 GstAHCSrc *self = GST_AHC_SRC (src);
1875 GstStructure *s = gst_caps_get_structure (caps, 0);
1877 GST_DEBUG_OBJECT (self, "Fixating : %" GST_PTR_FORMAT, caps);
1879 caps = gst_caps_make_writable (caps);
1881 /* Width/height will be fixed already here, format will
1882 * be left for fixation by the default handler.
1883 * We only have to fixate framerate here, to the
1884 * highest possible framerate.
1886 gst_structure_fixate_field_nearest_fraction (s, "framerate", G_MAXINT, 1);
1888 caps = GST_BASE_SRC_CLASS (parent_class)->fixate (src, caps);
1894 gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps)
1896 GstAHCSrc *self = GST_AHC_SRC (src);
1897 gboolean ret = FALSE;
1898 GstAHCParameters *params = NULL;
1900 if (!self->camera) {
1901 GST_WARNING_OBJECT (self, "setcaps called without a camera available");
1905 params = gst_ah_camera_get_parameters (self->camera);
1908 const gchar *format_str = NULL;
1909 GstVideoFormat format;
1911 gint width, height, fps_n, fps_d, buffer_size;
1913 gint range_size = G_MAXINT;
1915 s = gst_caps_get_structure (caps, 0);
1917 format_str = gst_structure_get_string (s, "format");
1918 format = gst_video_format_from_string (format_str);
1920 gst_structure_get_int (s, "width", &width);
1921 gst_structure_get_int (s, "height", &height);
1922 gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d);
1924 fps_n *= 1000 / fps_d;
1926 /* Select the best range that contains our framerate.
1927 * We *must* set a range of those returned by the camera
1928 * according to the API docs and can't use a subset of any
1930 * We chose the smallest range that contains the target
1933 self->fps_max = self->fps_min = 0;
1934 ranges = gst_ahc_parameters_get_supported_preview_fps_range (params);
1935 ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges);
1936 for (l = ranges; l; l = l->next) {
1937 int *range = l->data;
1939 if (fps_n >= range[0] && fps_n <= range[1] &&
1940 range_size > (range[1] - range[0])) {
1941 self->fps_min = range[0];
1942 self->fps_max = range[1];
1943 range_size = range[1] - range[0];
1946 gst_ahc_parameters_supported_preview_fps_range_free (ranges);
1947 if (self->fps_max == 0 || self->fps_min == 0) {
1948 GST_ERROR_OBJECT (self, "Couldn't find an applicable FPS range");
1953 case GST_VIDEO_FORMAT_YV12:
1954 fmt = ImageFormat_YV12;
1956 case GST_VIDEO_FORMAT_NV21:
1957 fmt = ImageFormat_NV21;
1959 case GST_VIDEO_FORMAT_YUY2:
1960 fmt = ImageFormat_YUY2;
1962 case GST_VIDEO_FORMAT_RGB16:
1963 fmt = ImageFormat_RGB_565;
1965 /* GST_VIDEO_FORMAT_NV16 doesn't exist */
1966 //case GST_VIDEO_FORMAT_NV16:
1967 //fmt = ImageFormat_NV16;
1970 fmt = ImageFormat_UNKNOWN;
1974 if (fmt == ImageFormat_UNKNOWN) {
1975 GST_WARNING_OBJECT (self, "unsupported video format (%s)", format_str);
1979 gst_ahc_parameters_set_preview_size (params, width, height);
1980 gst_ahc_parameters_set_preview_format (params, fmt);
1981 gst_ahc_parameters_set_preview_fps_range (params, self->fps_min,
1984 GST_DEBUG_OBJECT (self, "Setting camera parameters : %d %dx%d @ [%f, %f]",
1985 fmt, width, height, self->fps_min / 1000.0, self->fps_max / 1000.0);
1987 if (!gst_ah_camera_set_parameters (self->camera, params)) {
1988 GST_WARNING_OBJECT (self, "Unable to set video parameters");
1992 self->width = width;
1993 self->height = height;
1995 buffer_size = width * height *
1996 ((double) gst_ag_imageformat_get_bits_per_pixel (fmt) / 8);
1998 if (buffer_size > self->buffer_size) {
1999 JNIEnv *env = gst_amc_jni_get_env ();
2002 for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) {
2003 jbyteArray array = (*env)->NewByteArray (env, buffer_size);
2006 gst_ah_camera_add_callback_buffer (self->camera, array);
2007 (*env)->DeleteLocalRef (env, array);
2011 self->buffer_size = buffer_size;
2013 GST_DEBUG_OBJECT (self, "setting buffer w:%d h:%d buffer_size: %d",
2014 self->width, self->height, self->buffer_size);
2021 gst_ahc_parameters_free (params);
2023 if (ret && self->start) {
2024 GST_DEBUG_OBJECT (self, "Starting preview");
2025 ret = gst_ah_camera_start_preview (self->camera);
2027 /* Need to reset callbacks after every startPreview */
2028 gst_ah_camera_set_preview_callback_with_buffer (self->camera,
2029 gst_ahc_src_on_preview_frame, self);
2030 gst_ah_camera_set_error_callback (self->camera, gst_ahc_src_on_error,
2032 self->start = FALSE;
2046 gst_ahc_src_buffer_free_func (gpointer priv)
2048 FreeFuncBuffer *data = (FreeFuncBuffer *) priv;
2049 GstAHCSrc *self = data->self;
2050 JNIEnv *env = gst_amc_jni_get_env ();
2052 g_mutex_lock (&self->mutex);
2054 GST_DEBUG_OBJECT (self, "release %p->%p", data, data->array);
2056 (*env)->ReleaseByteArrayElements (env, data->array, data->data, JNI_ABORT);
2058 gst_ah_camera_add_callback_buffer (self->camera, data->array);
2060 (*env)->DeleteGlobalRef (env, data->array);
2062 g_slice_free (FreeFuncBuffer, data);
2064 g_mutex_unlock (&self->mutex);
2065 gst_object_unref (self);
2069 _data_queue_item_free (GstDataQueueItem * item)
2071 GST_DEBUG ("release %p", item->object);
2073 gst_buffer_unref (GST_BUFFER (item->object));
2074 g_slice_free (GstDataQueueItem, item);
2078 gst_ahc_src_on_preview_frame (jbyteArray array, gpointer user_data)
2080 GstAHCSrc *self = GST_AHC_SRC (user_data);
2081 JNIEnv *env = gst_amc_jni_get_env ();
2083 GstDataQueueItem *item = NULL;
2084 FreeFuncBuffer *malloc_data = NULL;
2085 GstClockTime timestamp = GST_CLOCK_TIME_NONE;
2086 GstClockTime duration = 0;
2088 gboolean queued = FALSE;
2090 g_mutex_lock (&self->mutex);
2092 if (array == NULL) {
2093 GST_DEBUG_OBJECT (self, "Size of array in queue is too small, dropping it");
2097 if ((clock = GST_ELEMENT_CLOCK (self))) {
2098 GstClockTime base_time = GST_ELEMENT_CAST (self)->base_time;
2099 GstClockTime current_ts;
2101 gst_object_ref (clock);
2102 current_ts = gst_clock_get_time (clock) - base_time;
2103 gst_object_unref (clock);
2104 if (GST_CLOCK_TIME_IS_VALID (self->previous_ts)) {
2105 timestamp = self->previous_ts;
2106 duration = current_ts - self->previous_ts;
2107 self->previous_ts = current_ts;
2109 /* Drop the first buffer */
2110 self->previous_ts = current_ts;
2111 gst_ah_camera_add_callback_buffer (self->camera, array);
2112 GST_DEBUG_OBJECT (self, "dropping the first buffer");
2116 GST_DEBUG_OBJECT (self, "element clock hasn't created yet.");
2117 gst_ah_camera_add_callback_buffer (self->camera, array);
2121 GST_DEBUG_OBJECT (self, "Received data buffer %p", array);
2123 malloc_data = g_slice_new (FreeFuncBuffer);
2124 malloc_data->self = gst_object_ref (self);
2125 malloc_data->array = (*env)->NewGlobalRef (env, array);
2126 malloc_data->data = (*env)->GetByteArrayElements (env, array, NULL);
2129 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, malloc_data->data,
2130 self->buffer_size, 0, self->buffer_size, malloc_data,
2131 gst_ahc_src_buffer_free_func);
2132 GST_BUFFER_DURATION (buffer) = duration;
2133 GST_BUFFER_PTS (buffer) = timestamp;
2135 GST_DEBUG_OBJECT (self, "creating wrapped buffer (size: %d)",
2138 item = g_slice_new (GstDataQueueItem);
2139 item->object = GST_MINI_OBJECT (buffer);
2140 item->size = gst_buffer_get_size (buffer);
2141 item->duration = GST_BUFFER_DURATION (buffer);
2142 item->visible = TRUE;
2143 item->destroy = (GDestroyNotify) _data_queue_item_free;
2145 GST_DEBUG_OBJECT (self, "wrapping jni array %p->%p %p->%p", item,
2146 item->object, malloc_data, malloc_data->array);
2148 queued = gst_data_queue_push (self->queue, item);
2151 g_mutex_unlock (&self->mutex);
2153 if (item && !queued) {
2154 GST_INFO_OBJECT (self, "could not add buffer to queue");
2155 /* Can't add buffer to queue. Must be flushing. */
2156 _data_queue_item_free (item);
2161 gst_ahc_src_on_error (gint error, gpointer user_data)
2163 GstAHCSrc *self = GST_AHC_SRC (user_data);
2165 GST_WARNING_OBJECT (self, "Received error code : %d", error);
2169 gst_ahc_src_open (GstAHCSrc * self)
2173 GST_DEBUG_OBJECT (self, "Opening camera");
2175 self->camera = gst_ah_camera_open (self->device);
2178 GST_DEBUG_OBJECT (self, "Opened camera");
2180 self->texture = gst_amc_surface_texture_jni_new (&err);
2181 if (self->texture == NULL) {
2182 GST_ERROR_OBJECT (self,
2183 "Failed to create surface texture object: %s", err->message);
2184 g_clear_error (&err);
2185 goto failed_surfacetexutre;
2187 gst_ah_camera_set_preview_texture (self->camera, self->texture);
2188 self->buffer_size = 0;
2190 gint num_cams = gst_ah_camera_get_number_of_cameras ();
2191 if (num_cams > 0 && self->device < num_cams) {
2192 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2193 ("Unable to open device '%d'.", self->device), (NULL));
2194 } else if (num_cams > 0) {
2195 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2196 ("Device '%d' does not exist.", self->device), (NULL));
2198 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2199 ("There are no cameras available on this device."), (NULL));
2203 return (self->camera != NULL);
2205 failed_surfacetexutre:
2206 gst_ah_camera_release (self->camera);
2207 gst_ah_camera_free (self->camera);
2208 self->camera = NULL;
2214 gst_ahc_src_close (GstAHCSrc * self)
2219 gst_ah_camera_set_error_callback (self->camera, NULL, NULL);
2220 gst_ah_camera_set_preview_callback_with_buffer (self->camera, NULL, NULL);
2221 gst_ah_camera_release (self->camera);
2222 gst_ah_camera_free (self->camera);
2224 self->camera = NULL;
2227 && !gst_amc_surface_texture_release ((GstAmcSurfaceTexture *)
2228 self->texture, &err)) {
2229 GST_ERROR_OBJECT (self, "Failed to release surface texture object: %s",
2231 g_clear_error (&err);
2234 g_clear_object (&self->texture);
2237 static GstStateChangeReturn
2238 gst_ahc_src_change_state (GstElement * element, GstStateChange transition)
2240 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2241 GstAHCSrc *self = GST_AHC_SRC (element);
2243 switch (transition) {
2244 case GST_STATE_CHANGE_NULL_TO_READY:
2245 if (!gst_ahc_src_open (self))
2246 return GST_STATE_CHANGE_FAILURE;
2252 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2254 switch (transition) {
2255 case GST_STATE_CHANGE_READY_TO_NULL:
2256 gst_ahc_src_close (self);
2266 gst_ahc_src_start (GstBaseSrc * bsrc)
2268 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2270 GST_DEBUG_OBJECT (self, "Starting preview");
2272 self->previous_ts = GST_CLOCK_TIME_NONE;
2273 self->fps_min = self->fps_max = self->width = self->height = 0;
2274 self->format = ImageFormat_UNKNOWN;
2284 gst_ahc_src_stop (GstBaseSrc * bsrc)
2286 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2288 GST_DEBUG_OBJECT (self, "Stopping preview");
2290 gst_data_queue_flush (self->queue);
2291 self->start = FALSE;
2292 gst_ah_camera_set_error_callback (self->camera, NULL, NULL);
2293 return gst_ah_camera_stop_preview (self->camera);
2299 gst_ahc_src_unlock (GstBaseSrc * bsrc)
2301 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2303 GST_DEBUG_OBJECT (self, "Unlocking create");
2304 gst_data_queue_set_flushing (self->queue, TRUE);
2310 gst_ahc_src_unlock_stop (GstBaseSrc * bsrc)
2312 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2314 GST_DEBUG_OBJECT (self, "Stopping unlock");
2315 gst_data_queue_set_flushing (self->queue, FALSE);
2320 static GstFlowReturn
2321 gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer)
2323 GstAHCSrc *self = GST_AHC_SRC (src);
2324 GstDataQueueItem *item;
2326 if (!gst_data_queue_pop (self->queue, &item)) {
2327 GST_INFO_OBJECT (self, "empty queue");
2328 return GST_FLOW_FLUSHING;
2331 GST_DEBUG_OBJECT (self, "creating buffer %p->%p", item, item->object);
2333 *buffer = GST_BUFFER (item->object);
2334 g_slice_free (GstDataQueueItem, item);
2340 gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query)
2342 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2344 switch (GST_QUERY_TYPE (query)) {
2345 case GST_QUERY_LATENCY:{
2348 /* Cannot query latency before setcaps() */
2349 if (self->fps_min == 0)
2352 /* Allow of 1 frame latency base on the longer frame duration */
2353 gst_query_parse_latency (query, NULL, &min, NULL);
2354 min = gst_util_uint64_scale (GST_SECOND, 1000, self->fps_min);
2355 GST_DEBUG_OBJECT (self,
2356 "Reporting latency min: %" GST_TIME_FORMAT, GST_TIME_ARGS (min));
2357 gst_query_set_latency (query, TRUE, min, min);
2363 return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
2367 g_assert_not_reached ();