1 /* GStreamer android.hardware.Camera Source
2 *
3 * Copyright (C) 2012, Cisco Systems, Inc.
4 * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>
5 *
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.
10 *
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.
15 *
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.
20 */
21
22 /**
23 * SECTION:element-ahcsrc
24 * @title: ahcsrc
25 *
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.
28 *
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
34 * directory.
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 retreived using the following Java code :
38 * |[
39 * context.getCacheDir().getAbsolutePath();
40 * ]|
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 :
48 * |[
49 * context.getDir("dex", 0).getAbsolutePath();
50 * ]|
51 *
52 * > Those environment variable must be set before gst_init is called from
53 * > the native code.
54 *
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.
62 *
63 */
64
65 #ifdef HAVE_CONFIG_H
66 # include "config.h"
67 #endif
68
69 #include <gst/video/video.h>
70 #include <gst/interfaces/photography.h>
71
72 #include "gstjniutils.h"
73
74 #include "gstahcsrc.h"
75
76 /* GObject */
77 static void gst_ahc_src_set_property (GObject * object, guint prop_id,
78 const GValue * value, GParamSpec * pspec);
79 static void gst_ahc_src_get_property (GObject * object, guint prop_id,
80 GValue * value, GParamSpec * pspec);
81 static void gst_ahc_src_finalize (GObject * object);
82
83 /* GstElement */
84 static GstStateChangeReturn gst_ahc_src_change_state (GstElement * element,
85 GstStateChange transition);
86
87 /* GstBaseSrc */
88 static GstCaps *gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter);
89 static gboolean gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps);
90 static GstCaps *gst_ahc_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
91 static gboolean gst_ahc_src_start (GstBaseSrc * bsrc);
92 static gboolean gst_ahc_src_stop (GstBaseSrc * bsrc);
93 static gboolean gst_ahc_src_unlock (GstBaseSrc * bsrc);
94 static gboolean gst_ahc_src_unlock_stop (GstBaseSrc * bsrc);
95 static GstFlowReturn gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer);
96 static gboolean gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query);
97
98 /* GstPhotography */
99 static void gst_ahc_src_photography_init (gpointer g_iface,
100 gpointer iface_data);
101 static gboolean gst_ahc_src_get_ev_compensation (GstPhotography * photo,
102 gfloat * ev_comp);
103 static gboolean _white_balance_to_enum (const gchar * white_balance,
104 GstPhotographyWhiteBalanceMode * mode);
105 static gboolean gst_ahc_src_get_white_balance_mode (GstPhotography * photo,
106 GstPhotographyWhiteBalanceMode * wb_mode);
107 static gboolean _color_effects_to_enum (const gchar * color_effect,
108 GstPhotographyColorToneMode * mode);
109 static gboolean gst_ahc_src_get_colour_tone_mode (GstPhotography * photo,
110 GstPhotographyColorToneMode * tone_mode);
111 static gboolean _scene_modes_to_enum (const gchar * scene,
112 GstPhotographySceneMode * mode);
113 static gboolean gst_ahc_src_get_scene_mode (GstPhotography * photo,
114 GstPhotographySceneMode * scene_mode);
115 static gboolean _flash_modes_to_enum (const gchar * flash,
116 GstPhotographyFlashMode * mode);
117 static gboolean gst_ahc_src_get_flash_mode (GstPhotography * photo,
118 GstPhotographyFlashMode * flash_mode);
119 static gboolean gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom);
120 static gboolean _antibanding_to_enum (const gchar * antibanding,
121 GstPhotographyFlickerReductionMode * mode);
122 static gboolean gst_ahc_src_get_flicker_mode (GstPhotography * photo,
123 GstPhotographyFlickerReductionMode * flicker_mode);
124 static gboolean _focus_modes_to_enum (const gchar * focus,
125 GstPhotographyFocusMode * mode);
126 static gboolean gst_ahc_src_get_focus_mode (GstPhotography * photo,
127 GstPhotographyFocusMode * focus_mode);
128
129 static gboolean gst_ahc_src_set_ev_compensation (GstPhotography * photo,
130 gfloat ev_comp);
131 static gboolean gst_ahc_src_set_white_balance_mode (GstPhotography * photo,
132 GstPhotographyWhiteBalanceMode wb_mode);
133 static gboolean gst_ahc_src_set_colour_tone_mode (GstPhotography * photo,
134 GstPhotographyColorToneMode tone_mode);
135 static gboolean gst_ahc_src_set_scene_mode (GstPhotography * photo,
136 GstPhotographySceneMode scene_mode);
137 static gboolean gst_ahc_src_set_flash_mode (GstPhotography * photo,
138 GstPhotographyFlashMode flash_mode);
139 static gboolean gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom);
140 static gboolean gst_ahc_src_set_flicker_mode (GstPhotography * photo,
141 GstPhotographyFlickerReductionMode flicker_mode);
142 static gboolean gst_ahc_src_set_focus_mode (GstPhotography * photo,
143 GstPhotographyFocusMode focus_mode);
144
145 static GstPhotographyCaps gst_ahc_src_get_capabilities (GstPhotography * photo);
146 static void gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on);
147
148 /* GstAHCSrc */
149 static void gst_ahc_src_close (GstAHCSrc * self);
150 static void gst_ahc_src_on_preview_frame (jbyteArray data, gpointer user_data);
151 static void gst_ahc_src_on_error (gint error, gpointer user_data);
152 static void gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data);
153
154 #define NUM_CALLBACK_BUFFERS 5
155
156 #define GST_AHC_SRC_CAPS_STR \
157 GST_VIDEO_CAPS_MAKE_WITH_FEATURES("ANY", " { YV12, YUY2, NV21, NV16, RGB16 }")
158
159 static GstStaticPadTemplate gst_ahc_src_pad_template =
160 GST_STATIC_PAD_TEMPLATE ("src",
161 GST_PAD_SRC,
162 GST_PAD_ALWAYS,
163 GST_STATIC_CAPS (GST_AHC_SRC_CAPS_STR));
164
165 GST_DEBUG_CATEGORY_STATIC (gst_ahc_src_debug);
166 #define GST_CAT_DEFAULT gst_ahc_src_debug
167
168 #define parent_class gst_ahc_src_parent_class
169
170 enum
171 {
172 PROP_0,
173 PROP_DEVICE,
174 PROP_DEVICE_NAME,
175 PROP_DEVICE_FACING,
176 PROP_DEVICE_ORIENTATION,
177 PROP_FOCAL_LENGTH,
178 PROP_HORIZONTAL_VIEW_ANGLE,
179 PROP_VERTICAL_VIEW_ANGLE,
180 PROP_VIDEO_STABILIZATION,
181 PROP_WB_MODE,
182 PROP_COLOUR_TONE,
183 PROP_SCENE_MODE,
184 PROP_FLASH_MODE,
185 PROP_NOISE_REDUCTION,
186 PROP_CAPABILITIES,
187 PROP_EV_COMP,
188 PROP_ISO_SPEED,
189 PROP_APERTURE,
190 PROP_EXPOSURE_MODE,
191 PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
192 PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
193 PROP_FLICKER_MODE,
194 PROP_FOCUS_MODE,
195 PROP_ZOOM,
196 PROP_SMOOTH_ZOOM,
197 PROP_WHITE_POINT,
198 PROP_MIN_EXPOSURE_TIME,
199 PROP_MAX_EXPOSURE_TIME,
200 PROP_LENS_FOCUS,
201 PROP_EXPOSURE_TIME,
202 PROP_COLOR_TEMPERATURE,
203 PROP_ANALOG_GAIN,
204 PROP_LAST
205 };
206
207 static GParamSpec *properties[PROP_LAST];
208
209 #define DEFAULT_DEVICE "0"
210
211 G_DEFINE_TYPE_WITH_CODE (GstAHCSrc, gst_ahc_src, GST_TYPE_PUSH_SRC,
212 G_IMPLEMENT_INTERFACE (GST_TYPE_PHOTOGRAPHY, gst_ahc_src_photography_init));
213
214 #define CAMERA_FACING_BACK 0
215 #define CAMERA_FACING_FRONT 1
216
217 static GType
gst_ahc_src_facing_get_type(void)218 gst_ahc_src_facing_get_type (void)
219 {
220 static GType type = 0;
221 static const GEnumValue types[] = {
222 {CAMERA_FACING_BACK, "Back", "back"},
223 {CAMERA_FACING_FRONT, "Front", "front"},
224 {0, NULL, NULL}
225 };
226
227 if (!type) {
228 type = g_enum_register_static ("GstAHCSrcFacing", types);
229 }
230 return type;
231 }
232
233 #define GST_AHC_SRC_FACING_TYPE (gst_ahc_src_facing_get_type())
234
235 static void
gst_ahc_src_photography_init(gpointer g_iface,gpointer iface_data)236 gst_ahc_src_photography_init (gpointer g_iface, gpointer iface_data)
237 {
238 GstPhotographyInterface *iface = g_iface;
239
240 iface->get_ev_compensation = gst_ahc_src_get_ev_compensation;
241 iface->get_white_balance_mode = gst_ahc_src_get_white_balance_mode;
242 iface->get_color_tone_mode = gst_ahc_src_get_colour_tone_mode;
243 iface->get_scene_mode = gst_ahc_src_get_scene_mode;
244 iface->get_flash_mode = gst_ahc_src_get_flash_mode;
245 iface->get_zoom = gst_ahc_src_get_zoom;
246 iface->get_flicker_mode = gst_ahc_src_get_flicker_mode;
247 iface->get_focus_mode = gst_ahc_src_get_focus_mode;
248
249 iface->set_ev_compensation = gst_ahc_src_set_ev_compensation;
250 iface->set_white_balance_mode = gst_ahc_src_set_white_balance_mode;
251 iface->set_color_tone_mode = gst_ahc_src_set_colour_tone_mode;
252 iface->set_scene_mode = gst_ahc_src_set_scene_mode;
253 iface->set_flash_mode = gst_ahc_src_set_flash_mode;
254 iface->set_zoom = gst_ahc_src_set_zoom;
255 iface->set_flicker_mode = gst_ahc_src_set_flicker_mode;
256 iface->set_focus_mode = gst_ahc_src_set_focus_mode;
257
258 iface->get_capabilities = gst_ahc_src_get_capabilities;
259 iface->set_autofocus = gst_ahc_src_set_autofocus;
260 }
261
262 static void
gst_ahc_src_class_init(GstAHCSrcClass * klass)263 gst_ahc_src_class_init (GstAHCSrcClass * klass)
264 {
265 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
266 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
267 GstPushSrcClass *gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
268 GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
269
270 gobject_class->set_property = gst_ahc_src_set_property;
271 gobject_class->get_property = gst_ahc_src_get_property;
272 gobject_class->finalize = gst_ahc_src_finalize;
273
274 element_class->change_state = gst_ahc_src_change_state;
275
276 gstbasesrc_class->get_caps = gst_ahc_src_getcaps;
277 gstbasesrc_class->set_caps = gst_ahc_src_setcaps;
278 gstbasesrc_class->fixate = gst_ahc_src_fixate;
279 gstbasesrc_class->start = gst_ahc_src_start;
280 gstbasesrc_class->stop = gst_ahc_src_stop;
281 gstbasesrc_class->unlock = gst_ahc_src_unlock;
282 gstbasesrc_class->unlock_stop = gst_ahc_src_unlock_stop;
283 gstbasesrc_class->query = gst_ahc_src_query;
284
285 gstpushsrc_class->create = gst_ahc_src_create;
286
287 gst_element_class_add_static_pad_template (element_class,
288 &gst_ahc_src_pad_template);
289
290 /**
291 * GstAHCSrc:device:
292 *
293 * The Device ID of the camera to capture from
294 */
295 properties[PROP_DEVICE] = g_param_spec_string ("device",
296 "Device", "Device ID", DEFAULT_DEVICE,
297 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
298 g_object_class_install_property (gobject_class, PROP_DEVICE,
299 properties[PROP_DEVICE]);
300
301 /**
302 * GstAHCSrc:device-name:
303 *
304 * A user-friendly name for the camera device
305 */
306 properties[PROP_DEVICE_NAME] = g_param_spec_string ("device-name",
307 "Device name", "Device name", NULL,
308 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
309 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
310 properties[PROP_DEVICE_NAME]);
311
312 /**
313 * GstAHCSrc:device-orientation:
314 *
315 * The orientation of the currently set camera @device.
316 * The value is the angle that the camera image needs to be rotated clockwise
317 * so it shows correctly on the display in its natural orientation.
318 * It should be 0, 90, 180, or 270.
319 */
320 properties[PROP_DEVICE_ORIENTATION] = g_param_spec_int ("device-orientation",
321 "Device orientation", "The orientation of the camera image",
322 0, 360, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
323 g_object_class_install_property (gobject_class, PROP_DEVICE_ORIENTATION,
324 properties[PROP_DEVICE_ORIENTATION]);
325
326 /**
327 * GstAHCSrc:device-facing:
328 *
329 * The direction that the currently select camera @device faces.
330 *
331 * A value of 0 means the camera is facing the opposite direction as the
332 * screen while a value of 1 means the camera is facing the same direction
333 * as the screen.
334 */
335 properties[PROP_DEVICE_FACING] = g_param_spec_enum ("device-facing",
336 "Device facing", "The direction that the camera faces",
337 GST_AHC_SRC_FACING_TYPE, CAMERA_FACING_BACK,
338 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
339 g_object_class_install_property (gobject_class, PROP_DEVICE_FACING,
340 properties[PROP_DEVICE_FACING]);
341
342 /**
343 * GstAHCSrc:focal-length:
344 *
345 * Gets the focal length (in millimeter) of the camera.
346 */
347 properties[PROP_FOCAL_LENGTH] = g_param_spec_float ("focal-length",
348 "Focal length", "Gets the focal length (in millimeter) of the camera",
349 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
350 g_object_class_install_property (gobject_class, PROP_FOCAL_LENGTH,
351 properties[PROP_FOCAL_LENGTH]);
352
353 /**
354 * GstAHCSrc:horizontal-view-angle:
355 *
356 * Gets the horizontal angle of view in degrees.
357 */
358 properties[PROP_HORIZONTAL_VIEW_ANGLE] =
359 g_param_spec_float ("horizontal-view-angle", "Horizontal view angle",
360 "Gets the horizontal angle of view in degrees",
361 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
362 g_object_class_install_property (gobject_class, PROP_HORIZONTAL_VIEW_ANGLE,
363 properties[PROP_HORIZONTAL_VIEW_ANGLE]);
364
365 /**
366 * GstAHCSrc:vertical-view-angle:
367 *
368 * Gets the vertical angle of view in degrees.
369 */
370 properties[PROP_VERTICAL_VIEW_ANGLE] =
371 g_param_spec_float ("vertical-view-angle", "Vertical view angle",
372 "Gets the vertical angle of view in degrees",
373 -G_MAXFLOAT, G_MAXFLOAT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
374 g_object_class_install_property (gobject_class, PROP_VERTICAL_VIEW_ANGLE,
375 properties[PROP_VERTICAL_VIEW_ANGLE]);
376
377 /**
378 * GstAHCSrc:video-stabilization:
379 *
380 * Video stabilization reduces the shaking due to the motion of the camera.
381 */
382 properties[PROP_VIDEO_STABILIZATION] =
383 g_param_spec_boolean ("video-stabilization", "Video stabilization",
384 "Video stabilization reduces the shaking due to the motion of the camera",
385 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
386 g_object_class_install_property (gobject_class, PROP_VIDEO_STABILIZATION,
387 properties[PROP_VIDEO_STABILIZATION]);
388
389 /**
390 * GstAHCSrc:smooth-zoom:
391 *
392 * If enabled, then smooth zooming will be used when the @zoom property is
393 * changed. In that case, the @zoom property can be queried to know the
394 * current zoom level while the smooth zoom is in progress.
395 */
396 properties[PROP_SMOOTH_ZOOM] = g_param_spec_boolean ("smooth-zoom",
397 "Smooth Zoom", "Use smooth zoom when available",
398 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
399 g_object_class_install_property (gobject_class, PROP_SMOOTH_ZOOM,
400 properties[PROP_SMOOTH_ZOOM]);
401
402 /* Override GstPhotography properties */
403 g_object_class_override_property (gobject_class, PROP_WB_MODE,
404 GST_PHOTOGRAPHY_PROP_WB_MODE);
405 properties[PROP_WB_MODE] = g_object_class_find_property (gobject_class,
406 GST_PHOTOGRAPHY_PROP_WB_MODE);
407
408 g_object_class_override_property (gobject_class, PROP_COLOUR_TONE,
409 GST_PHOTOGRAPHY_PROP_COLOR_TONE);
410 properties[PROP_COLOUR_TONE] = g_object_class_find_property (gobject_class,
411 GST_PHOTOGRAPHY_PROP_COLOR_TONE);
412
413 g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
414 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
415 properties[PROP_SCENE_MODE] = g_object_class_find_property (gobject_class,
416 GST_PHOTOGRAPHY_PROP_SCENE_MODE);
417
418 g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
419 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
420 properties[PROP_FLASH_MODE] = g_object_class_find_property (gobject_class,
421 GST_PHOTOGRAPHY_PROP_FLASH_MODE);
422
423 g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
424 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
425 properties[PROP_NOISE_REDUCTION] =
426 g_object_class_find_property (gobject_class,
427 GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
428
429 g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
430 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
431 properties[PROP_CAPABILITIES] = g_object_class_find_property (gobject_class,
432 GST_PHOTOGRAPHY_PROP_CAPABILITIES);
433
434 g_object_class_override_property (gobject_class, PROP_EV_COMP,
435 GST_PHOTOGRAPHY_PROP_EV_COMP);
436 properties[PROP_EV_COMP] = g_object_class_find_property (gobject_class,
437 GST_PHOTOGRAPHY_PROP_EV_COMP);
438
439 g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
440 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
441 properties[PROP_ISO_SPEED] = g_object_class_find_property (gobject_class,
442 GST_PHOTOGRAPHY_PROP_ISO_SPEED);
443
444 g_object_class_override_property (gobject_class, PROP_APERTURE,
445 GST_PHOTOGRAPHY_PROP_APERTURE);
446 properties[PROP_APERTURE] = g_object_class_find_property (gobject_class,
447 GST_PHOTOGRAPHY_PROP_APERTURE);
448
449 #if 0
450 g_object_class_override_property (gobject_class, PROP_EXPOSURE_MODE,
451 GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE);
452 properties[PROP_EXPOSURE] = g_object_class_find_property (gobject_class,
453 GST_PHOTOGRAPHY_PROP_EXPOSURE_MODE);
454 #endif
455
456 g_object_class_override_property (gobject_class,
457 PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
458 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
459 properties[PROP_IMAGE_CAPTURE_SUPPORTED_CAPS] =
460 g_object_class_find_property (gobject_class,
461 GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
462
463 g_object_class_override_property (gobject_class,
464 PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
465 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
466 properties[PROP_IMAGE_PREVIEW_SUPPORTED_CAPS] =
467 g_object_class_find_property (gobject_class,
468 GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
469
470 g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
471 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
472 properties[PROP_FLICKER_MODE] = g_object_class_find_property (gobject_class,
473 GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
474
475 g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
476 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
477 properties[PROP_FOCUS_MODE] = g_object_class_find_property (gobject_class,
478 GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
479
480 g_object_class_override_property (gobject_class, PROP_ZOOM,
481 GST_PHOTOGRAPHY_PROP_ZOOM);
482 properties[PROP_ZOOM] = g_object_class_find_property (gobject_class,
483 GST_PHOTOGRAPHY_PROP_ZOOM);
484
485 g_object_class_override_property (gobject_class, PROP_WHITE_POINT,
486 GST_PHOTOGRAPHY_PROP_WHITE_POINT);
487 properties[PROP_WHITE_POINT] = g_object_class_find_property (gobject_class,
488 GST_PHOTOGRAPHY_PROP_WHITE_POINT);
489
490 g_object_class_override_property (gobject_class, PROP_MIN_EXPOSURE_TIME,
491 GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME);
492 properties[PROP_MIN_EXPOSURE_TIME] =
493 g_object_class_find_property (gobject_class,
494 GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME);
495
496 g_object_class_override_property (gobject_class, PROP_MAX_EXPOSURE_TIME,
497 GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME);
498 properties[PROP_MAX_EXPOSURE_TIME] =
499 g_object_class_find_property (gobject_class,
500 GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME);
501
502 g_object_class_override_property (gobject_class, PROP_LENS_FOCUS,
503 GST_PHOTOGRAPHY_PROP_LENS_FOCUS);
504 properties[PROP_LENS_FOCUS] = g_object_class_find_property (gobject_class,
505 GST_PHOTOGRAPHY_PROP_LENS_FOCUS);
506
507 g_object_class_override_property (gobject_class, PROP_EXPOSURE_TIME,
508 GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME);
509 properties[PROP_EXPOSURE_TIME] = g_object_class_find_property (gobject_class,
510 GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME);
511
512 g_object_class_override_property (gobject_class, PROP_COLOR_TEMPERATURE,
513 GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE);
514 properties[PROP_COLOR_TEMPERATURE] =
515 g_object_class_find_property (gobject_class,
516 GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE);
517
518 g_object_class_override_property (gobject_class, PROP_ANALOG_GAIN,
519 GST_PHOTOGRAPHY_PROP_ANALOG_GAIN);
520 properties[PROP_ANALOG_GAIN] = g_object_class_find_property (gobject_class,
521 GST_PHOTOGRAPHY_PROP_ANALOG_GAIN);
522
523 gst_element_class_set_static_metadata (element_class,
524 "Android Camera Source",
525 "Source/Video/Hardware",
526 "Reads frames from android.hardware.Camera class into buffers",
527 "Youness Alaoui <youness.alaoui@collabora.co.uk>");
528
529 GST_DEBUG_CATEGORY_INIT (gst_ahc_src_debug, "ahcsrc", 0,
530 "android.hardware.Camera source element");
531 }
532
533 static gboolean
_data_queue_check_full(GstDataQueue * queue,guint visible,guint bytes,guint64 time,gpointer checkdata)534 _data_queue_check_full (GstDataQueue * queue, guint visible,
535 guint bytes, guint64 time, gpointer checkdata)
536 {
537 return FALSE;
538 }
539
540 static void
gst_ahc_src_init(GstAHCSrc * self)541 gst_ahc_src_init (GstAHCSrc * self)
542 {
543 gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
544 gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
545 gst_base_src_set_do_timestamp (GST_BASE_SRC (self), FALSE);
546
547 self->camera = NULL;
548 self->texture = NULL;
549 self->data = NULL;
550 self->queue = gst_data_queue_new (_data_queue_check_full, NULL, NULL, NULL);
551 self->start = FALSE;
552 self->previous_ts = GST_CLOCK_TIME_NONE;
553
554 g_mutex_init (&self->mutex);
555 }
556
557 static void
gst_ahc_src_finalize(GObject * object)558 gst_ahc_src_finalize (GObject * object)
559 {
560 GstAHCSrc *self = GST_AHC_SRC (object);
561
562 g_clear_object (&self->queue);
563 g_mutex_clear (&self->mutex);
564
565 G_OBJECT_CLASS (parent_class)->finalize (object);
566 }
567
568 static void
gst_ahc_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)569 gst_ahc_src_set_property (GObject * object, guint prop_id,
570 const GValue * value, GParamSpec * pspec)
571 {
572 GstAHCSrc *self = GST_AHC_SRC (object);
573
574 GST_DEBUG_OBJECT (self, "set props %d", prop_id);
575
576 switch (prop_id) {
577 case PROP_DEVICE:{
578 const gchar *dev = g_value_get_string (value);
579 gchar *endptr = NULL;
580 guint64 device;
581
582 device = g_ascii_strtoll (dev, &endptr, 10);
583 if (endptr != dev && endptr[0] == 0 && device < G_MAXINT)
584 self->device = (gint) device;
585 }
586 break;
587 case PROP_VIDEO_STABILIZATION:
588 if (self->camera) {
589 GstAHCParameters *params;
590
591 params = gst_ah_camera_get_parameters (self->camera);
592 if (params) {
593 gst_ahc_parameters_set_video_stabilization (params,
594 g_value_get_boolean (value));
595 gst_ah_camera_set_parameters (self->camera, params);
596 gst_ahc_parameters_free (params);
597 }
598 }
599 break;
600 case PROP_SMOOTH_ZOOM:
601 self->smooth_zoom = g_value_get_boolean (value);
602 break;
603 case PROP_WB_MODE:{
604 GstPhotographyWhiteBalanceMode wb = g_value_get_enum (value);
605
606 gst_ahc_src_set_white_balance_mode (GST_PHOTOGRAPHY (self), wb);
607 }
608 break;
609 case PROP_COLOUR_TONE:{
610 GstPhotographyColorToneMode tone = g_value_get_enum (value);
611
612 gst_ahc_src_set_colour_tone_mode (GST_PHOTOGRAPHY (self), tone);
613 }
614 break;
615 case PROP_SCENE_MODE:{
616 GstPhotographySceneMode scene = g_value_get_enum (value);
617
618 gst_ahc_src_set_scene_mode (GST_PHOTOGRAPHY (self), scene);
619 }
620 break;
621 case PROP_FLASH_MODE:{
622 GstPhotographyFlashMode flash = g_value_get_enum (value);
623
624 gst_ahc_src_set_flash_mode (GST_PHOTOGRAPHY (self), flash);
625 }
626 break;
627 case PROP_EV_COMP:{
628 gfloat ev = g_value_get_float (value);
629
630 gst_ahc_src_set_ev_compensation (GST_PHOTOGRAPHY (self), ev);
631 }
632 break;
633 case PROP_FLICKER_MODE:{
634 GstPhotographyFlickerReductionMode flicker = g_value_get_enum (value);
635
636 gst_ahc_src_set_flicker_mode (GST_PHOTOGRAPHY (self), flicker);
637 }
638 break;
639 case PROP_FOCUS_MODE:{
640 GstPhotographyFocusMode focus = g_value_get_enum (value);
641
642 gst_ahc_src_set_focus_mode (GST_PHOTOGRAPHY (self), focus);
643 }
644 break;
645 case PROP_ZOOM:{
646 gfloat zoom = g_value_get_float (value);
647
648 gst_ahc_src_set_zoom (GST_PHOTOGRAPHY (self), zoom);
649 }
650 break;
651 case PROP_NOISE_REDUCTION:
652 case PROP_ISO_SPEED:
653 case PROP_APERTURE:
654 case PROP_EXPOSURE_MODE:
655 case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:
656 case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS:
657 case PROP_WHITE_POINT:
658 case PROP_MIN_EXPOSURE_TIME:
659 case PROP_MAX_EXPOSURE_TIME:
660 case PROP_LENS_FOCUS:
661 case PROP_EXPOSURE_TIME:
662 case PROP_COLOR_TEMPERATURE:
663 case PROP_ANALOG_GAIN:
664 break;
665 default:
666 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
667 break;
668 }
669 }
670
671 static void
gst_ahc_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)672 gst_ahc_src_get_property (GObject * object, guint prop_id,
673 GValue * value, GParamSpec * pspec)
674 {
675 GstAHCSrc *self = GST_AHC_SRC (object);
676 (void) self;
677
678 switch (prop_id) {
679 case PROP_DEVICE:{
680 gchar *dev = g_strdup_printf ("%d", self->device);
681
682 g_value_take_string (value, dev);
683 }
684 break;
685 case PROP_DEVICE_NAME:{
686 GstAHCCameraInfo info;
687 gchar *dev;
688
689 if (gst_ah_camera_get_camera_info (self->device, &info))
690 dev = g_strdup_printf ("#%d %s", self->device,
691 info.facing == CameraInfo_CAMERA_FACING_BACK ? "Back" : "Front");
692 else
693 dev = g_strdup_printf ("#%d", self->device);
694
695 g_value_take_string (value, dev);
696 }
697 break;
698 case PROP_DEVICE_FACING:{
699 GstAHCCameraInfo info;
700
701 if (gst_ah_camera_get_camera_info (self->device, &info))
702 g_value_set_enum (value, info.facing == CameraInfo_CAMERA_FACING_BACK ?
703 CAMERA_FACING_BACK : CAMERA_FACING_FRONT);
704 else
705 g_value_set_enum (value, CAMERA_FACING_BACK);
706 }
707 break;
708 case PROP_DEVICE_ORIENTATION:{
709 GstAHCCameraInfo info;
710
711 if (gst_ah_camera_get_camera_info (self->device, &info))
712 g_value_set_int (value, info.orientation);
713 else
714 g_value_set_int (value, 0);
715 }
716 break;
717 case PROP_FOCAL_LENGTH:
718 if (self->camera) {
719 GstAHCParameters *params;
720
721 params = gst_ah_camera_get_parameters (self->camera);
722 if (params) {
723 g_value_set_float (value,
724 gst_ahc_parameters_get_focal_length (params));
725 gst_ahc_parameters_free (params);
726 }
727 }
728 break;
729 case PROP_HORIZONTAL_VIEW_ANGLE:
730 if (self->camera) {
731 GstAHCParameters *params;
732
733 params = gst_ah_camera_get_parameters (self->camera);
734 if (params) {
735 g_value_set_float (value,
736 gst_ahc_parameters_get_horizontal_view_angle (params));
737 gst_ahc_parameters_free (params);
738 }
739 }
740 break;
741 case PROP_VERTICAL_VIEW_ANGLE:
742 if (self->camera) {
743 GstAHCParameters *params;
744
745 params = gst_ah_camera_get_parameters (self->camera);
746 if (params) {
747 g_value_set_float (value,
748 gst_ahc_parameters_get_vertical_view_angle (params));
749 gst_ahc_parameters_free (params);
750 }
751 }
752 break;
753 case PROP_VIDEO_STABILIZATION:
754 if (self->camera) {
755 GstAHCParameters *params;
756
757 params = gst_ah_camera_get_parameters (self->camera);
758 if (params) {
759 g_value_set_boolean (value,
760 gst_ahc_parameters_get_video_stabilization (params));
761 gst_ahc_parameters_free (params);
762 }
763 }
764 break;
765 case PROP_SMOOTH_ZOOM:
766 g_value_set_boolean (value, self->smooth_zoom);
767 break;
768 case PROP_WB_MODE:{
769 GstPhotographyWhiteBalanceMode wb;
770
771 if (gst_ahc_src_get_white_balance_mode (GST_PHOTOGRAPHY (self), &wb))
772 g_value_set_enum (value, wb);
773 }
774 break;
775 case PROP_COLOUR_TONE:{
776 GstPhotographyColorToneMode tone;
777
778 if (gst_ahc_src_get_colour_tone_mode (GST_PHOTOGRAPHY (self), &tone))
779 g_value_set_enum (value, tone);
780 }
781 break;
782 case PROP_SCENE_MODE:{
783 GstPhotographySceneMode scene;
784
785 if (gst_ahc_src_get_scene_mode (GST_PHOTOGRAPHY (self), &scene))
786 g_value_set_enum (value, scene);
787 }
788 break;
789 case PROP_FLASH_MODE:{
790 GstPhotographyFlashMode flash;
791
792 if (gst_ahc_src_get_flash_mode (GST_PHOTOGRAPHY (self), &flash))
793 g_value_set_enum (value, flash);
794 }
795 break;
796 case PROP_CAPABILITIES:{
797 GstPhotographyCaps caps;
798
799 caps = gst_ahc_src_get_capabilities (GST_PHOTOGRAPHY (self));
800 g_value_set_ulong (value, caps);
801 }
802 break;
803 case PROP_EV_COMP:{
804 gfloat ev;
805
806 if (gst_ahc_src_get_ev_compensation (GST_PHOTOGRAPHY (self), &ev))
807 g_value_set_float (value, ev);
808 }
809 break;
810 case PROP_FLICKER_MODE:{
811 GstPhotographyFlickerReductionMode flicker;
812
813 if (gst_ahc_src_get_flicker_mode (GST_PHOTOGRAPHY (self), &flicker))
814 g_value_set_enum (value, flicker);
815 }
816 break;
817 case PROP_FOCUS_MODE:{
818 GstPhotographyFocusMode focus;
819
820 if (gst_ahc_src_get_focus_mode (GST_PHOTOGRAPHY (self), &focus))
821 g_value_set_enum (value, focus);
822 }
823 break;
824 case PROP_ZOOM:{
825 gfloat zoom;
826
827 if (gst_ahc_src_get_zoom (GST_PHOTOGRAPHY (self), &zoom))
828 g_value_set_float (value, zoom);
829 }
830 break;
831 case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:
832 case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS:
833 case PROP_NOISE_REDUCTION:
834 case PROP_ISO_SPEED:
835 case PROP_APERTURE:
836 case PROP_EXPOSURE_MODE:
837 case PROP_WHITE_POINT:
838 case PROP_MIN_EXPOSURE_TIME:
839 case PROP_MAX_EXPOSURE_TIME:
840 case PROP_LENS_FOCUS:
841 case PROP_EXPOSURE_TIME:
842 case PROP_COLOR_TEMPERATURE:
843 case PROP_ANALOG_GAIN:
844 break;
845 default:
846 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
847 break;
848 }
849 }
850
851 static gboolean
_antibanding_to_enum(const gchar * antibanding,GstPhotographyFlickerReductionMode * mode)852 _antibanding_to_enum (const gchar * antibanding,
853 GstPhotographyFlickerReductionMode * mode)
854 {
855 if (antibanding == Parameters_ANTIBANDING_AUTO)
856 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO;
857 else if (antibanding == Parameters_ANTIBANDING_50HZ)
858 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ;
859 else if (antibanding == Parameters_ANTIBANDING_60HZ)
860 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ;
861 else if (antibanding == Parameters_ANTIBANDING_OFF)
862 *mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF;
863 else
864 return FALSE;
865
866 return TRUE;
867 }
868
869 static gboolean
_white_balance_to_enum(const gchar * white_balance,GstPhotographyWhiteBalanceMode * mode)870 _white_balance_to_enum (const gchar * white_balance,
871 GstPhotographyWhiteBalanceMode * mode)
872 {
873 if (white_balance == Parameters_WHITE_BALANCE_AUTO)
874 *mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
875 else if (white_balance == Parameters_WHITE_BALANCE_INCANDESCENT)
876 *mode = GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN;
877 else if (white_balance == Parameters_WHITE_BALANCE_FLUORESCENT)
878 *mode = GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT;
879 else if (white_balance == Parameters_WHITE_BALANCE_WARM_FLUORESCENT)
880 *mode = GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT;
881 else if (white_balance == Parameters_WHITE_BALANCE_DAYLIGHT)
882 *mode = GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT;
883 else if (white_balance == Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT)
884 *mode = GST_PHOTOGRAPHY_WB_MODE_CLOUDY;
885 else if (white_balance == Parameters_WHITE_BALANCE_TWILIGHT)
886 *mode = GST_PHOTOGRAPHY_WB_MODE_SUNSET;
887 else if (white_balance == Parameters_WHITE_BALANCE_SHADE)
888 *mode = GST_PHOTOGRAPHY_WB_MODE_SHADE;
889 else
890 return FALSE;
891
892 return TRUE;
893 }
894
895 static gboolean
_color_effects_to_enum(const gchar * color_effect,GstPhotographyColorToneMode * mode)896 _color_effects_to_enum (const gchar * color_effect,
897 GstPhotographyColorToneMode * mode)
898 {
899 if (color_effect == Parameters_EFFECT_NONE)
900 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
901 else if (color_effect == Parameters_EFFECT_MONO)
902 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE;
903 else if (color_effect == Parameters_EFFECT_NEGATIVE)
904 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE;
905 else if (color_effect == Parameters_EFFECT_SOLARIZE)
906 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE;
907 else if (color_effect == Parameters_EFFECT_SEPIA)
908 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA;
909 else if (color_effect == Parameters_EFFECT_POSTERIZE)
910 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE;
911 else if (color_effect == Parameters_EFFECT_WHITEBOARD)
912 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD;
913 else if (color_effect == Parameters_EFFECT_BLACKBOARD)
914 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD;
915 else if (color_effect == Parameters_EFFECT_AQUA)
916 *mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA;
917 else
918 return FALSE;
919
920 return TRUE;
921 }
922
923 static gboolean
_scene_modes_to_enum(const gchar * scene,GstPhotographySceneMode * mode)924 _scene_modes_to_enum (const gchar * scene, GstPhotographySceneMode * mode)
925 {
926 if (scene == Parameters_SCENE_MODE_AUTO)
927 *mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
928 else if (scene == Parameters_SCENE_MODE_ACTION)
929 *mode = GST_PHOTOGRAPHY_SCENE_MODE_ACTION;
930 else if (scene == Parameters_SCENE_MODE_PORTRAIT)
931 *mode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT;
932 else if (scene == Parameters_SCENE_MODE_LANDSCAPE)
933 *mode = GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE;
934 else if (scene == Parameters_SCENE_MODE_NIGHT)
935 *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT;
936 else if (scene == Parameters_SCENE_MODE_NIGHT_PORTRAIT)
937 *mode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT;
938 else if (scene == Parameters_SCENE_MODE_THEATRE)
939 *mode = GST_PHOTOGRAPHY_SCENE_MODE_THEATRE;
940 else if (scene == Parameters_SCENE_MODE_BEACH)
941 *mode = GST_PHOTOGRAPHY_SCENE_MODE_BEACH;
942 else if (scene == Parameters_SCENE_MODE_SNOW)
943 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SNOW;
944 else if (scene == Parameters_SCENE_MODE_SUNSET)
945 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SUNSET;
946 else if (scene == Parameters_SCENE_MODE_STEADYPHOTO)
947 *mode = GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO;
948 else if (scene == Parameters_SCENE_MODE_FIREWORKS)
949 *mode = GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS;
950 else if (scene == Parameters_SCENE_MODE_SPORTS)
951 *mode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT;
952 else if (scene == Parameters_SCENE_MODE_PARTY)
953 *mode = GST_PHOTOGRAPHY_SCENE_MODE_PARTY;
954 else if (scene == Parameters_SCENE_MODE_CANDLELIGHT)
955 *mode = GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT;
956 else if (scene == Parameters_SCENE_MODE_BARCODE)
957 *mode = GST_PHOTOGRAPHY_SCENE_MODE_BARCODE;
958 else
959 return FALSE;
960
961 return TRUE;
962 }
963
964 static gboolean
_flash_modes_to_enum(const gchar * flash,GstPhotographyFlashMode * mode)965 _flash_modes_to_enum (const gchar * flash, GstPhotographyFlashMode * mode)
966 {
967 if (flash == Parameters_FLASH_MODE_OFF)
968 *mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
969 else if (flash == Parameters_FLASH_MODE_AUTO)
970 *mode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
971 else if (flash == Parameters_FLASH_MODE_ON)
972 *mode = GST_PHOTOGRAPHY_FLASH_MODE_ON;
973 else if (flash == Parameters_FLASH_MODE_RED_EYE)
974 *mode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE;
975 else if (flash == Parameters_FLASH_MODE_TORCH)
976 *mode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN;
977 else
978 return FALSE;
979
980 return TRUE;
981 }
982
983 static gboolean
_focus_modes_to_enum(const gchar * focus,GstPhotographyFocusMode * mode)984 _focus_modes_to_enum (const gchar * focus, GstPhotographyFocusMode * mode)
985 {
986 if (focus == Parameters_FOCUS_MODE_AUTO)
987 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
988 else if (focus == Parameters_FOCUS_MODE_INFINITY)
989 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY;
990 else if (focus == Parameters_FOCUS_MODE_MACRO)
991 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_MACRO;
992 else if (focus == Parameters_FOCUS_MODE_FIXED)
993 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL;
994 else if (focus == Parameters_FOCUS_MODE_EDOF)
995 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED;
996 else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_VIDEO)
997 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED;
998 else if (focus == Parameters_FOCUS_MODE_CONTINUOUS_PICTURE)
999 *mode = GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL;
1000 else
1001 return FALSE;
1002
1003 return TRUE;
1004 }
1005
1006 static gboolean
gst_ahc_src_get_ev_compensation(GstPhotography * photo,gfloat * ev_comp)1007 gst_ahc_src_get_ev_compensation (GstPhotography * photo, gfloat * ev_comp)
1008 {
1009 GstAHCSrc *self = GST_AHC_SRC (photo);
1010 gboolean ret = FALSE;
1011
1012 if (self->camera) {
1013 GstAHCParameters *params;
1014
1015 params = gst_ah_camera_get_parameters (self->camera);
1016 if (params) {
1017 gint ev, min, max;
1018 gfloat step;
1019
1020 ev = gst_ahc_parameters_get_exposure_compensation (params);
1021 min = gst_ahc_parameters_get_min_exposure_compensation (params);
1022 max = gst_ahc_parameters_get_max_exposure_compensation (params);
1023 step = gst_ahc_parameters_get_exposure_compensation_step (params);
1024
1025 if (step != 0.0 && min != max && min <= ev && ev <= max) {
1026 if (ev_comp)
1027 *ev_comp = ev * step;
1028 ret = TRUE;
1029 }
1030 gst_ahc_parameters_free (params);
1031 }
1032 }
1033
1034 return ret;
1035 }
1036
1037 static gboolean
gst_ahc_src_get_white_balance_mode(GstPhotography * photo,GstPhotographyWhiteBalanceMode * wb_mode)1038 gst_ahc_src_get_white_balance_mode (GstPhotography * photo,
1039 GstPhotographyWhiteBalanceMode * wb_mode)
1040 {
1041 GstAHCSrc *self = GST_AHC_SRC (photo);
1042 gboolean ret = FALSE;
1043
1044 if (self->camera) {
1045 GstAHCParameters *params;
1046
1047 params = gst_ah_camera_get_parameters (self->camera);
1048 if (params) {
1049 const gchar *wb = gst_ahc_parameters_get_white_balance (params);
1050 GstPhotographyWhiteBalanceMode mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
1051
1052 if (_white_balance_to_enum (wb, &mode)) {
1053 ret = TRUE;
1054
1055 if (wb_mode)
1056 *wb_mode = mode;
1057 }
1058
1059 gst_ahc_parameters_free (params);
1060 }
1061 }
1062
1063 return ret;
1064 }
1065
1066 static gboolean
gst_ahc_src_get_colour_tone_mode(GstPhotography * photo,GstPhotographyColorToneMode * tone_mode)1067 gst_ahc_src_get_colour_tone_mode (GstPhotography * photo,
1068 GstPhotographyColorToneMode * tone_mode)
1069 {
1070 GstAHCSrc *self = GST_AHC_SRC (photo);
1071 gboolean ret = FALSE;
1072
1073 if (self->camera) {
1074 GstAHCParameters *params;
1075
1076 params = gst_ah_camera_get_parameters (self->camera);
1077 if (params) {
1078 const gchar *effect = gst_ahc_parameters_get_color_effect (params);
1079 GstPhotographyColorToneMode mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
1080
1081 if (_color_effects_to_enum (effect, &mode)) {
1082 ret = TRUE;
1083
1084 if (tone_mode)
1085 *tone_mode = mode;
1086 }
1087
1088 gst_ahc_parameters_free (params);
1089 }
1090 }
1091
1092 return ret;
1093 }
1094
1095 static gboolean
gst_ahc_src_get_scene_mode(GstPhotography * photo,GstPhotographySceneMode * scene_mode)1096 gst_ahc_src_get_scene_mode (GstPhotography * photo,
1097 GstPhotographySceneMode * scene_mode)
1098 {
1099 GstAHCSrc *self = GST_AHC_SRC (photo);
1100 gboolean ret = FALSE;
1101
1102 if (scene_mode && self->camera) {
1103 GstAHCParameters *params;
1104
1105 params = gst_ah_camera_get_parameters (self->camera);
1106 if (params) {
1107 const gchar *scene = gst_ahc_parameters_get_scene_mode (params);
1108 GstPhotographySceneMode mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
1109
1110 if (_scene_modes_to_enum (scene, &mode)) {
1111 ret = TRUE;
1112
1113 if (scene_mode)
1114 *scene_mode = mode;
1115 }
1116
1117 gst_ahc_parameters_free (params);
1118 }
1119 }
1120
1121 return ret;
1122 }
1123
1124 static gboolean
gst_ahc_src_get_flash_mode(GstPhotography * photo,GstPhotographyFlashMode * flash_mode)1125 gst_ahc_src_get_flash_mode (GstPhotography * photo,
1126 GstPhotographyFlashMode * flash_mode)
1127 {
1128 GstAHCSrc *self = GST_AHC_SRC (photo);
1129 gboolean ret = FALSE;
1130
1131 if (self->camera) {
1132 GstAHCParameters *params;
1133
1134 params = gst_ah_camera_get_parameters (self->camera);
1135 if (params) {
1136 const gchar *flash = gst_ahc_parameters_get_flash_mode (params);
1137 GstPhotographyFlashMode mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
1138
1139 if (_flash_modes_to_enum (flash, &mode)) {
1140 ret = TRUE;
1141
1142 if (flash_mode)
1143 *flash_mode = mode;
1144 }
1145
1146 gst_ahc_parameters_free (params);
1147 }
1148 }
1149
1150 return ret;
1151 }
1152
1153 static gboolean
gst_ahc_src_get_zoom(GstPhotography * photo,gfloat * zoom)1154 gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom)
1155 {
1156 GstAHCSrc *self = GST_AHC_SRC (photo);
1157 gboolean ret = FALSE;
1158
1159 if (self->camera) {
1160 GstAHCParameters *params;
1161
1162 params = gst_ah_camera_get_parameters (self->camera);
1163 if (params) {
1164 GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params);
1165 gint zoom_idx = gst_ahc_parameters_get_zoom (params);
1166 gint max_zoom = gst_ahc_parameters_get_max_zoom (params);
1167
1168 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1) &&
1169 zoom_idx >= 0 && zoom_idx < max_zoom) {
1170 gint zoom_value;
1171
1172 zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, zoom_idx));
1173 if (zoom)
1174 *zoom = (gfloat) zoom_value / 100.0;
1175
1176 ret = TRUE;
1177 }
1178
1179 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1180 gst_ahc_parameters_free (params);
1181 }
1182 }
1183
1184 return ret;
1185 }
1186
1187 static gboolean
gst_ahc_src_get_flicker_mode(GstPhotography * photo,GstPhotographyFlickerReductionMode * flicker_mode)1188 gst_ahc_src_get_flicker_mode (GstPhotography * photo,
1189 GstPhotographyFlickerReductionMode * flicker_mode)
1190 {
1191 GstAHCSrc *self = GST_AHC_SRC (photo);
1192 gboolean ret = FALSE;
1193
1194 if (self->camera) {
1195 GstAHCParameters *params;
1196
1197 params = gst_ah_camera_get_parameters (self->camera);
1198 if (params) {
1199 const gchar *antibanding = gst_ahc_parameters_get_antibanding (params);
1200 GstPhotographyFlickerReductionMode mode =
1201 GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO;
1202
1203 if (_antibanding_to_enum (antibanding, &mode)) {
1204 ret = TRUE;
1205
1206 if (flicker_mode)
1207 *flicker_mode = mode;
1208 }
1209
1210 gst_ahc_parameters_free (params);
1211 }
1212 }
1213
1214 return ret;
1215 }
1216
1217 static gboolean
gst_ahc_src_get_focus_mode(GstPhotography * photo,GstPhotographyFocusMode * focus_mode)1218 gst_ahc_src_get_focus_mode (GstPhotography * photo,
1219 GstPhotographyFocusMode * focus_mode)
1220 {
1221 GstAHCSrc *self = GST_AHC_SRC (photo);
1222 gboolean ret = FALSE;
1223
1224 if (self->camera) {
1225 GstAHCParameters *params;
1226
1227 params = gst_ah_camera_get_parameters (self->camera);
1228 if (params) {
1229 const gchar *focus = gst_ahc_parameters_get_focus_mode (params);
1230 GstPhotographyFocusMode mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
1231
1232 if (_focus_modes_to_enum (focus, &mode)) {
1233 ret = TRUE;
1234
1235 if (focus_mode)
1236 *focus_mode = mode;
1237 }
1238
1239 gst_ahc_parameters_free (params);
1240 }
1241 }
1242
1243 return ret;
1244 }
1245
1246
1247 static gboolean
gst_ahc_src_set_ev_compensation(GstPhotography * photo,gfloat ev_comp)1248 gst_ahc_src_set_ev_compensation (GstPhotography * photo, gfloat ev_comp)
1249 {
1250 GstAHCSrc *self = GST_AHC_SRC (photo);
1251 gboolean ret = FALSE;
1252
1253 if (self->camera) {
1254 GstAHCParameters *params;
1255
1256 params = gst_ah_camera_get_parameters (self->camera);
1257 if (params) {
1258 gint ev, min, max;
1259 gfloat step;
1260
1261 ev = gst_ahc_parameters_get_exposure_compensation (params);
1262 min = gst_ahc_parameters_get_min_exposure_compensation (params);
1263 max = gst_ahc_parameters_get_max_exposure_compensation (params);
1264 step = gst_ahc_parameters_get_exposure_compensation_step (params);
1265 if (step != 0.0 && min != max &&
1266 (min * step) <= ev_comp && ev_comp <= (max * step)) {
1267 ev = ev_comp / step;
1268 if ((ev * step) == ev_comp) {
1269 gst_ahc_parameters_set_exposure_compensation (params, ev);
1270 ret = gst_ah_camera_set_parameters (self->camera, params);
1271 }
1272 }
1273 }
1274 gst_ahc_parameters_free (params);
1275 }
1276
1277 return ret;
1278 }
1279
1280 static gboolean
gst_ahc_src_set_white_balance_mode(GstPhotography * photo,GstPhotographyWhiteBalanceMode wb_mode)1281 gst_ahc_src_set_white_balance_mode (GstPhotography * photo,
1282 GstPhotographyWhiteBalanceMode wb_mode)
1283 {
1284 GstAHCSrc *self = GST_AHC_SRC (photo);
1285 gboolean ret = FALSE;
1286
1287 if (self->camera) {
1288 GstAHCParameters *params;
1289
1290 params = gst_ah_camera_get_parameters (self->camera);
1291 if (params) {
1292 const gchar *white_balance = NULL;
1293
1294 switch (wb_mode) {
1295 case GST_PHOTOGRAPHY_WB_MODE_AUTO:
1296 white_balance = Parameters_WHITE_BALANCE_AUTO;
1297 break;
1298 case GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT:
1299 white_balance = Parameters_WHITE_BALANCE_DAYLIGHT;
1300 break;
1301 case GST_PHOTOGRAPHY_WB_MODE_CLOUDY:
1302 white_balance = Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT;
1303 break;
1304 case GST_PHOTOGRAPHY_WB_MODE_SUNSET:
1305 white_balance = Parameters_WHITE_BALANCE_TWILIGHT;
1306 break;
1307 case GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN:
1308 white_balance = Parameters_WHITE_BALANCE_INCANDESCENT;
1309 break;
1310 case GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT:
1311 white_balance = Parameters_WHITE_BALANCE_FLUORESCENT;
1312 break;
1313 case GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT:
1314 white_balance = Parameters_WHITE_BALANCE_WARM_FLUORESCENT;
1315 break;
1316 case GST_PHOTOGRAPHY_WB_MODE_SHADE:
1317 white_balance = Parameters_WHITE_BALANCE_SHADE;
1318 break;
1319 default:
1320 white_balance = NULL;
1321 break;
1322 }
1323
1324 if (white_balance) {
1325 gst_ahc_parameters_set_white_balance (params, white_balance);
1326 ret = gst_ah_camera_set_parameters (self->camera, params);
1327 }
1328 gst_ahc_parameters_free (params);
1329 }
1330 }
1331
1332 return ret;
1333 }
1334
1335 static gboolean
gst_ahc_src_set_colour_tone_mode(GstPhotography * photo,GstPhotographyColorToneMode tone_mode)1336 gst_ahc_src_set_colour_tone_mode (GstPhotography * photo,
1337 GstPhotographyColorToneMode tone_mode)
1338 {
1339 GstAHCSrc *self = GST_AHC_SRC (photo);
1340 gboolean ret = FALSE;
1341
1342 if (self->camera) {
1343 GstAHCParameters *params;
1344
1345 params = gst_ah_camera_get_parameters (self->camera);
1346 if (params) {
1347 const gchar *color_effect = NULL;
1348
1349 switch (tone_mode) {
1350 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL:
1351 color_effect = Parameters_EFFECT_NONE;
1352 break;
1353 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA:
1354 color_effect = Parameters_EFFECT_SEPIA;
1355 break;
1356 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE:
1357 color_effect = Parameters_EFFECT_NEGATIVE;
1358 break;
1359 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE:
1360 color_effect = Parameters_EFFECT_MONO;
1361 break;
1362 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE:
1363 color_effect = Parameters_EFFECT_SOLARIZE;
1364 break;
1365 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE:
1366 color_effect = Parameters_EFFECT_POSTERIZE;
1367 break;
1368 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD:
1369 color_effect = Parameters_EFFECT_WHITEBOARD;
1370 break;
1371 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD:
1372 color_effect = Parameters_EFFECT_BLACKBOARD;
1373 break;
1374 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA:
1375 color_effect = Parameters_EFFECT_AQUA;
1376 break;
1377 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NATURAL:
1378 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_VIVID:
1379 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_COLORSWAP:
1380 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_OUT_OF_FOCUS:
1381 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKY_BLUE:
1382 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRASS_GREEN:
1383 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKIN_WHITEN:
1384 default:
1385 color_effect = NULL;
1386 break;
1387 }
1388
1389 if (color_effect) {
1390 gst_ahc_parameters_set_color_effect (params, color_effect);
1391 ret = gst_ah_camera_set_parameters (self->camera, params);
1392 }
1393 gst_ahc_parameters_free (params);
1394 }
1395 }
1396
1397 return ret;
1398 }
1399
1400 static gboolean
gst_ahc_src_set_scene_mode(GstPhotography * photo,GstPhotographySceneMode scene_mode)1401 gst_ahc_src_set_scene_mode (GstPhotography * photo,
1402 GstPhotographySceneMode scene_mode)
1403 {
1404 GstAHCSrc *self = GST_AHC_SRC (photo);
1405 gboolean ret = FALSE;
1406
1407 if (self->camera) {
1408 GstAHCParameters *params;
1409
1410 params = gst_ah_camera_get_parameters (self->camera);
1411 if (params) {
1412 const gchar *scene = NULL;
1413
1414 switch (scene_mode) {
1415 case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT:
1416 scene = Parameters_SCENE_MODE_PORTRAIT;
1417 break;
1418 case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE:
1419 scene = Parameters_SCENE_MODE_LANDSCAPE;
1420 break;
1421 case GST_PHOTOGRAPHY_SCENE_MODE_SPORT:
1422 scene = Parameters_SCENE_MODE_SPORTS;
1423 break;
1424 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT:
1425 scene = Parameters_SCENE_MODE_NIGHT;
1426 break;
1427 case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
1428 scene = Parameters_SCENE_MODE_AUTO;
1429 break;
1430 case GST_PHOTOGRAPHY_SCENE_MODE_ACTION:
1431 scene = Parameters_SCENE_MODE_ACTION;
1432 break;
1433 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT:
1434 scene = Parameters_SCENE_MODE_NIGHT_PORTRAIT;
1435 break;
1436 case GST_PHOTOGRAPHY_SCENE_MODE_THEATRE:
1437 scene = Parameters_SCENE_MODE_THEATRE;
1438 break;
1439 case GST_PHOTOGRAPHY_SCENE_MODE_BEACH:
1440 scene = Parameters_SCENE_MODE_BEACH;
1441 break;
1442 case GST_PHOTOGRAPHY_SCENE_MODE_SNOW:
1443 scene = Parameters_SCENE_MODE_SNOW;
1444 break;
1445 case GST_PHOTOGRAPHY_SCENE_MODE_SUNSET:
1446 scene = Parameters_SCENE_MODE_SUNSET;
1447 break;
1448 case GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO:
1449 scene = Parameters_SCENE_MODE_STEADYPHOTO;
1450 break;
1451 case GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS:
1452 scene = Parameters_SCENE_MODE_FIREWORKS;
1453 break;
1454 case GST_PHOTOGRAPHY_SCENE_MODE_PARTY:
1455 scene = Parameters_SCENE_MODE_PARTY;
1456 break;
1457 case GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT:
1458 scene = Parameters_SCENE_MODE_CANDLELIGHT;
1459 break;
1460 case GST_PHOTOGRAPHY_SCENE_MODE_BARCODE:
1461 scene = Parameters_SCENE_MODE_BARCODE;
1462 break;
1463 case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL:
1464 case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP:
1465 default:
1466 scene = NULL;
1467 break;
1468 }
1469
1470 if (scene) {
1471 gst_ahc_parameters_set_scene_mode (params, scene);
1472 ret = gst_ah_camera_set_parameters (self->camera, params);
1473 }
1474 gst_ahc_parameters_free (params);
1475 }
1476 }
1477
1478 return ret;
1479 }
1480
1481 static gboolean
gst_ahc_src_set_flash_mode(GstPhotography * photo,GstPhotographyFlashMode flash_mode)1482 gst_ahc_src_set_flash_mode (GstPhotography * photo,
1483 GstPhotographyFlashMode flash_mode)
1484 {
1485 GstAHCSrc *self = GST_AHC_SRC (photo);
1486 gboolean ret = FALSE;
1487
1488 if (self->camera) {
1489 GstAHCParameters *params;
1490
1491 params = gst_ah_camera_get_parameters (self->camera);
1492 if (params) {
1493 const gchar *flash = NULL;
1494
1495 switch (flash_mode) {
1496 case GST_PHOTOGRAPHY_FLASH_MODE_AUTO:
1497 flash = Parameters_FLASH_MODE_AUTO;
1498 break;
1499 case GST_PHOTOGRAPHY_FLASH_MODE_OFF:
1500 flash = Parameters_FLASH_MODE_OFF;
1501 break;
1502 case GST_PHOTOGRAPHY_FLASH_MODE_ON:
1503 flash = Parameters_FLASH_MODE_ON;
1504 break;
1505 case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN:
1506 flash = Parameters_FLASH_MODE_TORCH;
1507 break;
1508 case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE:
1509 flash = Parameters_FLASH_MODE_RED_EYE;
1510 break;
1511 default:
1512 flash = NULL;
1513 break;
1514 }
1515
1516 if (flash) {
1517 gst_ahc_parameters_set_flash_mode (params, flash);
1518 ret = gst_ah_camera_set_parameters (self->camera, params);
1519 }
1520 gst_ahc_parameters_free (params);
1521 }
1522 }
1523
1524 return ret;
1525 }
1526
1527 static gboolean
gst_ahc_src_set_zoom(GstPhotography * photo,gfloat zoom)1528 gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom)
1529 {
1530 GstAHCSrc *self = GST_AHC_SRC (photo);
1531 gboolean ret = FALSE;
1532
1533 if (self->camera) {
1534 GstAHCParameters *params;
1535
1536 params = gst_ah_camera_get_parameters (self->camera);
1537 if (params) {
1538 GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params);
1539 gint max_zoom = gst_ahc_parameters_get_max_zoom (params);
1540 gint zoom_idx = -1;
1541
1542 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1)) {
1543 gint i;
1544 gint value = zoom * 100;
1545
1546 for (i = 0; i < max_zoom + 1; i++) {
1547 gint zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, i));
1548
1549 if (value == zoom_value)
1550 zoom_idx = i;
1551 }
1552 }
1553
1554 if (zoom_idx != -1) {
1555 if (self->smooth_zoom &&
1556 gst_ahc_parameters_is_smooth_zoom_supported (params)) {
1557 // First, we need to cancel any previous smooth zoom operation
1558 gst_ah_camera_stop_smooth_zoom (self->camera);
1559 ret = gst_ah_camera_start_smooth_zoom (self->camera, zoom_idx);
1560 } else {
1561 gst_ahc_parameters_set_zoom (params, zoom_idx);
1562 ret = gst_ah_camera_set_parameters (self->camera, params);
1563 }
1564 }
1565
1566 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1567 gst_ahc_parameters_free (params);
1568 }
1569 }
1570
1571 return ret;
1572 }
1573
1574 static gboolean
gst_ahc_src_set_flicker_mode(GstPhotography * photo,GstPhotographyFlickerReductionMode flicker_mode)1575 gst_ahc_src_set_flicker_mode (GstPhotography * photo,
1576 GstPhotographyFlickerReductionMode flicker_mode)
1577 {
1578 GstAHCSrc *self = GST_AHC_SRC (photo);
1579 gboolean ret = FALSE;
1580
1581 if (self->camera) {
1582 GstAHCParameters *params;
1583
1584 params = gst_ah_camera_get_parameters (self->camera);
1585 if (params) {
1586 const gchar *antibanding = NULL;
1587
1588 switch (flicker_mode) {
1589 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF:
1590 antibanding = Parameters_ANTIBANDING_OFF;
1591 break;
1592 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ:
1593 antibanding = Parameters_ANTIBANDING_50HZ;
1594 break;
1595 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ:
1596 antibanding = Parameters_ANTIBANDING_60HZ;
1597 break;
1598 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO:
1599 antibanding = Parameters_ANTIBANDING_AUTO;
1600 break;
1601 default:
1602 antibanding = NULL;
1603 break;
1604 }
1605
1606 if (antibanding) {
1607 gst_ahc_parameters_set_antibanding (params, antibanding);
1608 ret = gst_ah_camera_set_parameters (self->camera, params);
1609 }
1610 gst_ahc_parameters_free (params);
1611 }
1612 }
1613
1614 return ret;
1615 }
1616
1617 static gboolean
gst_ahc_src_set_focus_mode(GstPhotography * photo,GstPhotographyFocusMode focus_mode)1618 gst_ahc_src_set_focus_mode (GstPhotography * photo,
1619 GstPhotographyFocusMode focus_mode)
1620 {
1621 GstAHCSrc *self = GST_AHC_SRC (photo);
1622 gboolean ret = FALSE;
1623
1624 if (self->camera) {
1625 GstAHCParameters *params;
1626
1627 params = gst_ah_camera_get_parameters (self->camera);
1628 if (params) {
1629 const gchar *focus = NULL;
1630
1631 switch (focus_mode) {
1632 case GST_PHOTOGRAPHY_FOCUS_MODE_AUTO:
1633 focus = Parameters_FOCUS_MODE_AUTO;
1634 break;
1635 case GST_PHOTOGRAPHY_FOCUS_MODE_MACRO:
1636 focus = Parameters_FOCUS_MODE_MACRO;
1637 break;
1638 case GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY:
1639 focus = Parameters_FOCUS_MODE_INFINITY;
1640 break;
1641 case GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL:
1642 focus = Parameters_FOCUS_MODE_FIXED;
1643 break;
1644 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL:
1645 focus = Parameters_FOCUS_MODE_CONTINUOUS_PICTURE;
1646 break;
1647 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED:
1648 focus = Parameters_FOCUS_MODE_CONTINUOUS_VIDEO;
1649 break;
1650 case GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED:
1651 focus = Parameters_FOCUS_MODE_EDOF;
1652 break;
1653 case GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT:
1654 default:
1655 focus = NULL;
1656 break;
1657 }
1658
1659 if (focus) {
1660 gst_ahc_parameters_set_focus_mode (params, focus);
1661 ret = gst_ah_camera_set_parameters (self->camera, params);
1662 }
1663 gst_ahc_parameters_free (params);
1664 }
1665 }
1666
1667 return ret;
1668 }
1669
1670 static GstPhotographyCaps
gst_ahc_src_get_capabilities(GstPhotography * photo)1671 gst_ahc_src_get_capabilities (GstPhotography * photo)
1672 {
1673 GstAHCSrc *self = GST_AHC_SRC (photo);
1674
1675 GstPhotographyCaps caps = GST_PHOTOGRAPHY_CAPS_EV_COMP |
1676 GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
1677 GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
1678 GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_ZOOM;
1679
1680 if (self->camera) {
1681 GstAHCParameters *params;
1682
1683 params = gst_ah_camera_get_parameters (self->camera);
1684 if (!gst_ahc_parameters_is_zoom_supported (params))
1685 caps &= ~GST_PHOTOGRAPHY_CAPS_ZOOM;
1686
1687 gst_ahc_parameters_free (params);
1688 }
1689
1690 return caps;
1691 }
1692
1693 static void
gst_ahc_src_on_auto_focus(gboolean success,gpointer user_data)1694 gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data)
1695 {
1696 GstAHCSrc *self = GST_AHC_SRC (user_data);
1697
1698 GST_WARNING_OBJECT (self, "Auto focus completed : %d", success);
1699 gst_element_post_message (GST_ELEMENT (self),
1700 gst_message_new_custom (GST_MESSAGE_ELEMENT, GST_OBJECT (self),
1701 gst_structure_new_empty (GST_PHOTOGRAPHY_AUTOFOCUS_DONE)));
1702 }
1703
1704 static void
gst_ahc_src_set_autofocus(GstPhotography * photo,gboolean on)1705 gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on)
1706 {
1707 GstAHCSrc *self = GST_AHC_SRC (photo);
1708
1709 if (self->camera) {
1710 if (on)
1711 gst_ah_camera_auto_focus (self->camera, gst_ahc_src_on_auto_focus, self);
1712 else
1713 gst_ah_camera_cancel_auto_focus (self->camera);
1714 }
1715
1716 }
1717
1718 static gint
_compare_formats(int f1,int f2)1719 _compare_formats (int f1, int f2)
1720 {
1721 if (f1 == f2)
1722 return 0;
1723 /* YV12 has priority */
1724 if (f1 == ImageFormat_YV12)
1725 return -1;
1726 if (f2 == ImageFormat_YV12)
1727 return 1;
1728 /* Then NV21 */
1729 if (f1 == ImageFormat_NV21)
1730 return -1;
1731 if (f2 == ImageFormat_NV21)
1732 return 1;
1733 /* Then we don't care */
1734 return f2 - f1;
1735 }
1736
1737 static gint
_compare_sizes(GstAHCSize * s1,GstAHCSize * s2)1738 _compare_sizes (GstAHCSize * s1, GstAHCSize * s2)
1739 {
1740 return ((s2->width * s2->height) - (s1->width * s1->height));
1741 }
1742
1743
1744 static gint
_compare_ranges(int * r1,int * r2)1745 _compare_ranges (int *r1, int *r2)
1746 {
1747 if (r1[1] == r2[1])
1748 /* Smallest range */
1749 return (r1[1] - r1[0]) - (r2[1] - r2[0]);
1750 else
1751 /* Highest fps */
1752 return r2[1] - r1[1];
1753 }
1754
1755 static GstCaps *
gst_ahc_src_getcaps(GstBaseSrc * src,GstCaps * filter)1756 gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter)
1757 {
1758 GstAHCSrc *self = GST_AHC_SRC (src);
1759
1760 if (self->camera) {
1761 GstCaps *ret = gst_caps_new_empty ();
1762 GstAHCParameters *params;
1763
1764 params = gst_ah_camera_get_parameters (self->camera);
1765 if (params) {
1766 GList *formats, *sizes, *ranges;
1767 GList *i, *j, *k;
1768 int previous_format = ImageFormat_UNKNOWN;
1769
1770 formats = gst_ahc_parameters_get_supported_preview_formats (params);
1771 formats = g_list_sort (formats, (GCompareFunc) _compare_formats);
1772 sizes = gst_ahc_parameters_get_supported_preview_sizes (params);
1773 sizes = g_list_sort (sizes, (GCompareFunc) _compare_sizes);
1774 ranges = gst_ahc_parameters_get_supported_preview_fps_range (params);
1775 ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges);
1776 GST_DEBUG_OBJECT (self, "Supported preview formats:");
1777
1778 for (i = formats; i; i = i->next) {
1779 int f = GPOINTER_TO_INT (i->data);
1780 gchar *format_string = NULL;
1781 GstStructure *format = NULL;
1782
1783 /* Ignore duplicates */
1784 if (f == previous_format)
1785 continue;
1786
1787 /* Can't use switch/case because the values are not constants */
1788 if (f == ImageFormat_NV16) {
1789 GST_DEBUG_OBJECT (self, " NV16 (%d)", f);
1790 format_string = g_strdup ("NV16");
1791 } else if (f == ImageFormat_NV21) {
1792 GST_DEBUG_OBJECT (self, " NV21 (%d)", f);
1793 format_string = g_strdup ("NV21");
1794 } else if (f == ImageFormat_RGB_565) {
1795 GstVideoFormat vformat;
1796 vformat = gst_video_format_from_masks (16, 16, G_LITTLE_ENDIAN,
1797 0xf800, 0x07e0, 0x001f, 0x0);
1798 GST_DEBUG_OBJECT (self, " RGB565 (%d)", f);
1799 format_string = g_strdup (gst_video_format_to_string (vformat));
1800 } else if (f == ImageFormat_YUY2) {
1801 GST_DEBUG_OBJECT (self, " YUY2 (%d)", f);
1802 format_string = g_strdup ("YUY2");
1803 } else if (f == ImageFormat_YV12) {
1804 GST_DEBUG_OBJECT (self, " YV12 (%d)", f);
1805 format_string = g_strdup ("YV12");
1806 }
1807 previous_format = f;
1808
1809 if (format_string) {
1810 format = gst_structure_new ("video/x-raw",
1811 "format", G_TYPE_STRING, format_string, NULL);
1812 g_free (format_string);
1813 }
1814
1815 if (format) {
1816 for (j = sizes; j; j = j->next) {
1817 GstAHCSize *s = j->data;
1818 GstStructure *size;
1819
1820 size = gst_structure_copy (format);
1821 gst_structure_set (size, "width", G_TYPE_INT, s->width,
1822 "height", G_TYPE_INT, s->height,
1823 "interlaced", G_TYPE_BOOLEAN, FALSE,
1824 "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
1825
1826 for (k = ranges; k; k = k->next) {
1827 int *range = k->data;
1828 GstStructure *s;
1829
1830 s = gst_structure_copy (size);
1831 if (range[0] == range[1]) {
1832 gst_structure_set (s, "framerate", GST_TYPE_FRACTION,
1833 range[0], 1000, NULL);
1834 } else {
1835 gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE,
1836 range[0], 1000, range[1], 1000, NULL);
1837 }
1838 gst_caps_append_structure (ret, s);
1839 }
1840 gst_structure_free (size);
1841 }
1842 gst_structure_free (format);
1843 }
1844 }
1845 GST_DEBUG_OBJECT (self, "Supported preview sizes:");
1846 for (i = sizes; i; i = i->next) {
1847 GstAHCSize *s = i->data;
1848
1849 GST_DEBUG_OBJECT (self, " %dx%d", s->width, s->height);
1850 }
1851 GST_DEBUG_OBJECT (self, "Supported preview fps range:");
1852 for (i = ranges; i; i = i->next) {
1853 int *range = i->data;
1854
1855 GST_DEBUG_OBJECT (self, " [%d, %d]", range[0], range[1]);
1856 }
1857
1858 gst_ahc_parameters_supported_preview_formats_free (formats);
1859 gst_ahc_parameters_supported_preview_sizes_free (sizes);
1860 gst_ahc_parameters_supported_preview_fps_range_free (ranges);
1861 gst_ahc_parameters_free (params);
1862 }
1863
1864 return ret;
1865 } else {
1866 return NULL;
1867 }
1868 }
1869
1870 static GstCaps *
gst_ahc_src_fixate(GstBaseSrc * src,GstCaps * caps)1871 gst_ahc_src_fixate (GstBaseSrc * src, GstCaps * caps)
1872 {
1873 GstAHCSrc *self = GST_AHC_SRC (src);
1874 GstStructure *s = gst_caps_get_structure (caps, 0);
1875
1876 GST_DEBUG_OBJECT (self, "Fixating : %" GST_PTR_FORMAT, caps);
1877
1878 caps = gst_caps_make_writable (caps);
1879
1880 /* Width/height will be fixed already here, format will
1881 * be left for fixation by the default handler.
1882 * We only have to fixate framerate here, to the
1883 * highest possible framerate.
1884 */
1885 gst_structure_fixate_field_nearest_fraction (s, "framerate", G_MAXINT, 1);
1886
1887 caps = GST_BASE_SRC_CLASS (parent_class)->fixate (src, caps);
1888
1889 return caps;
1890 }
1891
1892 static gboolean
gst_ahc_src_setcaps(GstBaseSrc * src,GstCaps * caps)1893 gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps)
1894 {
1895 GstAHCSrc *self = GST_AHC_SRC (src);
1896 gboolean ret = FALSE;
1897 GstAHCParameters *params = NULL;
1898
1899 if (!self->camera) {
1900 GST_WARNING_OBJECT (self, "setcaps called without a camera available");
1901 goto end;
1902 }
1903
1904 params = gst_ah_camera_get_parameters (self->camera);
1905 if (params) {
1906 GstStructure *s;
1907 const gchar *format_str = NULL;
1908 GstVideoFormat format;
1909 gint fmt;
1910 gint width, height, fps_n, fps_d, buffer_size;
1911 GList *ranges, *l;
1912 gint range_size = G_MAXINT;
1913
1914 s = gst_caps_get_structure (caps, 0);
1915
1916 format_str = gst_structure_get_string (s, "format");
1917 format = gst_video_format_from_string (format_str);
1918
1919 gst_structure_get_int (s, "width", &width);
1920 gst_structure_get_int (s, "height", &height);
1921 gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d);
1922
1923 fps_n *= 1000 / fps_d;
1924
1925 /* Select the best range that contains our framerate.
1926 * We *must* set a range of those returned by the camera
1927 * according to the API docs and can't use a subset of any
1928 * of those ranges.
1929 * We chose the smallest range that contains the target
1930 * framerate.
1931 */
1932 self->fps_max = self->fps_min = 0;
1933 ranges = gst_ahc_parameters_get_supported_preview_fps_range (params);
1934 ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges);
1935 for (l = ranges; l; l = l->next) {
1936 int *range = l->data;
1937
1938 if (fps_n >= range[0] && fps_n <= range[1] &&
1939 range_size > (range[1] - range[0])) {
1940 self->fps_min = range[0];
1941 self->fps_max = range[1];
1942 range_size = range[1] - range[0];
1943 }
1944 }
1945 gst_ahc_parameters_supported_preview_fps_range_free (ranges);
1946 if (self->fps_max == 0 || self->fps_min == 0) {
1947 GST_ERROR_OBJECT (self, "Couldn't find an applicable FPS range");
1948 goto end;
1949 }
1950
1951 switch (format) {
1952 case GST_VIDEO_FORMAT_YV12:
1953 fmt = ImageFormat_YV12;
1954 break;
1955 case GST_VIDEO_FORMAT_NV21:
1956 fmt = ImageFormat_NV21;
1957 break;
1958 case GST_VIDEO_FORMAT_YUY2:
1959 fmt = ImageFormat_YUY2;
1960 break;
1961 case GST_VIDEO_FORMAT_RGB16:
1962 fmt = ImageFormat_RGB_565;
1963 break;
1964 /* GST_VIDEO_FORMAT_NV16 doesn't exist */
1965 //case GST_VIDEO_FORMAT_NV16:
1966 //fmt = ImageFormat_NV16;
1967 //break;
1968 default:
1969 fmt = ImageFormat_UNKNOWN;
1970 break;
1971 }
1972
1973 if (fmt == ImageFormat_UNKNOWN) {
1974 GST_WARNING_OBJECT (self, "unsupported video format (%s)", format_str);
1975 goto end;
1976 }
1977
1978 gst_ahc_parameters_set_preview_size (params, width, height);
1979 gst_ahc_parameters_set_preview_format (params, fmt);
1980 gst_ahc_parameters_set_preview_fps_range (params, self->fps_min,
1981 self->fps_max);
1982
1983 GST_DEBUG_OBJECT (self, "Setting camera parameters : %d %dx%d @ [%f, %f]",
1984 fmt, width, height, self->fps_min / 1000.0, self->fps_max / 1000.0);
1985
1986 if (!gst_ah_camera_set_parameters (self->camera, params)) {
1987 GST_WARNING_OBJECT (self, "Unable to set video parameters");
1988 goto end;
1989 }
1990
1991 self->width = width;
1992 self->height = height;
1993 self->format = fmt;
1994 buffer_size = width * height *
1995 ((double) gst_ag_imageformat_get_bits_per_pixel (fmt) / 8);
1996
1997 if (buffer_size > self->buffer_size) {
1998 JNIEnv *env = gst_amc_jni_get_env ();
1999 gint i;
2000
2001 for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) {
2002 jbyteArray array = (*env)->NewByteArray (env, buffer_size);
2003
2004 if (array) {
2005 gst_ah_camera_add_callback_buffer (self->camera, array);
2006 (*env)->DeleteLocalRef (env, array);
2007 }
2008 }
2009 }
2010 self->buffer_size = buffer_size;
2011
2012 GST_DEBUG_OBJECT (self, "setting buffer w:%d h:%d buffer_size: %d",
2013 self->width, self->height, self->buffer_size);
2014
2015 ret = TRUE;
2016 }
2017
2018 end:
2019 if (params)
2020 gst_ahc_parameters_free (params);
2021
2022 if (ret && self->start) {
2023 GST_DEBUG_OBJECT (self, "Starting preview");
2024 ret = gst_ah_camera_start_preview (self->camera);
2025 if (ret) {
2026 /* Need to reset callbacks after every startPreview */
2027 gst_ah_camera_set_preview_callback_with_buffer (self->camera,
2028 gst_ahc_src_on_preview_frame, self);
2029 gst_ah_camera_set_error_callback (self->camera, gst_ahc_src_on_error,
2030 self);
2031 self->start = FALSE;
2032 }
2033 }
2034 return ret;
2035 }
2036
2037 typedef struct
2038 {
2039 GstAHCSrc *self;
2040 jbyteArray array;
2041 jbyte *data;
2042 } FreeFuncBuffer;
2043
2044 static void
gst_ahc_src_buffer_free_func(gpointer priv)2045 gst_ahc_src_buffer_free_func (gpointer priv)
2046 {
2047 FreeFuncBuffer *data = (FreeFuncBuffer *) priv;
2048 GstAHCSrc *self = data->self;
2049 JNIEnv *env = gst_amc_jni_get_env ();
2050
2051 g_mutex_lock (&self->mutex);
2052
2053 GST_DEBUG_OBJECT (self, "release %p->%p", data, data->array);
2054
2055 (*env)->ReleaseByteArrayElements (env, data->array, data->data, JNI_ABORT);
2056 if (self->camera)
2057 gst_ah_camera_add_callback_buffer (self->camera, data->array);
2058
2059 (*env)->DeleteGlobalRef (env, data->array);
2060
2061 g_slice_free (FreeFuncBuffer, data);
2062
2063 g_mutex_unlock (&self->mutex);
2064 gst_object_unref (self);
2065 }
2066
2067 static void
_data_queue_item_free(GstDataQueueItem * item)2068 _data_queue_item_free (GstDataQueueItem * item)
2069 {
2070 GST_DEBUG ("release %p", item->object);
2071
2072 gst_buffer_unref (GST_BUFFER (item->object));
2073 g_slice_free (GstDataQueueItem, item);
2074 }
2075
2076 static void
gst_ahc_src_on_preview_frame(jbyteArray array,gpointer user_data)2077 gst_ahc_src_on_preview_frame (jbyteArray array, gpointer user_data)
2078 {
2079 GstAHCSrc *self = GST_AHC_SRC (user_data);
2080 JNIEnv *env = gst_amc_jni_get_env ();
2081 GstBuffer *buffer;
2082 GstDataQueueItem *item = NULL;
2083 FreeFuncBuffer *malloc_data = NULL;
2084 GstClockTime timestamp = GST_CLOCK_TIME_NONE;
2085 GstClockTime duration = 0;
2086 GstClock *clock;
2087 gboolean queued = FALSE;
2088
2089 g_mutex_lock (&self->mutex);
2090
2091 if (array == NULL) {
2092 GST_DEBUG_OBJECT (self, "Size of array in queue is too small, dropping it");
2093 goto done;
2094 }
2095
2096 if ((clock = GST_ELEMENT_CLOCK (self))) {
2097 GstClockTime base_time = GST_ELEMENT_CAST (self)->base_time;
2098 GstClockTime current_ts;
2099
2100 gst_object_ref (clock);
2101 current_ts = gst_clock_get_time (clock) - base_time;
2102 gst_object_unref (clock);
2103 if (GST_CLOCK_TIME_IS_VALID (self->previous_ts)) {
2104 timestamp = self->previous_ts;
2105 duration = current_ts - self->previous_ts;
2106 self->previous_ts = current_ts;
2107 } else {
2108 /* Drop the first buffer */
2109 self->previous_ts = current_ts;
2110 gst_ah_camera_add_callback_buffer (self->camera, array);
2111 GST_DEBUG_OBJECT (self, "dropping the first buffer");
2112 goto done;
2113 }
2114 } else {
2115 GST_DEBUG_OBJECT (self, "element clock hasn't created yet.");
2116 gst_ah_camera_add_callback_buffer (self->camera, array);
2117 goto done;
2118 }
2119
2120 GST_DEBUG_OBJECT (self, "Received data buffer %p", array);
2121
2122 malloc_data = g_slice_new (FreeFuncBuffer);
2123 malloc_data->self = gst_object_ref (self);
2124 malloc_data->array = (*env)->NewGlobalRef (env, array);
2125 malloc_data->data = (*env)->GetByteArrayElements (env, array, NULL);
2126
2127 buffer =
2128 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, malloc_data->data,
2129 self->buffer_size, 0, self->buffer_size, malloc_data,
2130 gst_ahc_src_buffer_free_func);
2131 GST_BUFFER_DURATION (buffer) = duration;
2132 GST_BUFFER_PTS (buffer) = timestamp;
2133
2134 GST_DEBUG_OBJECT (self, "creating wrapped buffer (size: %d)",
2135 self->buffer_size);
2136
2137 item = g_slice_new (GstDataQueueItem);
2138 item->object = GST_MINI_OBJECT (buffer);
2139 item->size = gst_buffer_get_size (buffer);
2140 item->duration = GST_BUFFER_DURATION (buffer);
2141 item->visible = TRUE;
2142 item->destroy = (GDestroyNotify) _data_queue_item_free;
2143
2144 GST_DEBUG_OBJECT (self, "wrapping jni array %p->%p %p->%p", item,
2145 item->object, malloc_data, malloc_data->array);
2146
2147 queued = gst_data_queue_push (self->queue, item);
2148
2149 done:
2150 g_mutex_unlock (&self->mutex);
2151
2152 if (item && !queued) {
2153 GST_INFO_OBJECT (self, "could not add buffer to queue");
2154 /* Can't add buffer to queue. Must be flushing. */
2155 _data_queue_item_free (item);
2156 }
2157 }
2158
2159 static void
gst_ahc_src_on_error(gint error,gpointer user_data)2160 gst_ahc_src_on_error (gint error, gpointer user_data)
2161 {
2162 GstAHCSrc *self = GST_AHC_SRC (user_data);
2163
2164 GST_WARNING_OBJECT (self, "Received error code : %d", error);
2165 }
2166
2167 static gboolean
gst_ahc_src_open(GstAHCSrc * self)2168 gst_ahc_src_open (GstAHCSrc * self)
2169 {
2170 GError *err = NULL;
2171
2172 GST_DEBUG_OBJECT (self, "Opening camera");
2173
2174 self->camera = gst_ah_camera_open (self->device);
2175
2176 if (self->camera) {
2177 GST_DEBUG_OBJECT (self, "Opened camera");
2178
2179 self->texture = gst_amc_surface_texture_new (&err);
2180 if (self->texture == NULL) {
2181 GST_ERROR_OBJECT (self,
2182 "Failed to create surface texture object: %s", err->message);
2183 g_clear_error (&err);
2184 goto failed_surfacetexutre;
2185 }
2186 gst_ah_camera_set_preview_texture (self->camera, self->texture);
2187 self->buffer_size = 0;
2188 } else {
2189 gint num_cams = gst_ah_camera_get_number_of_cameras ();
2190 if (num_cams > 0 && self->device < num_cams) {
2191 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2192 ("Unable to open device '%d'.", self->device), (NULL));
2193 } else if (num_cams > 0) {
2194 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2195 ("Device '%d' does not exist.", self->device), (NULL));
2196 } else {
2197 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2198 ("There are no cameras available on this device."), (NULL));
2199 }
2200 }
2201
2202 return (self->camera != NULL);
2203
2204 failed_surfacetexutre:
2205 gst_ah_camera_release (self->camera);
2206 gst_ah_camera_free (self->camera);
2207 self->camera = NULL;
2208
2209 return FALSE;
2210 }
2211
2212 static void
gst_ahc_src_close(GstAHCSrc * self)2213 gst_ahc_src_close (GstAHCSrc * self)
2214 {
2215 GError *err = NULL;
2216
2217 if (self->camera) {
2218 gst_ah_camera_set_error_callback (self->camera, NULL, NULL);
2219 gst_ah_camera_set_preview_callback_with_buffer (self->camera, NULL, NULL);
2220 gst_ah_camera_release (self->camera);
2221 gst_ah_camera_free (self->camera);
2222 }
2223 self->camera = NULL;
2224
2225 if (self->texture && !gst_amc_surface_texture_release (self->texture, &err)) {
2226 GST_ERROR_OBJECT (self,
2227 "Failed to release surface texture object: %s", err->message);
2228 g_clear_error (&err);
2229 }
2230
2231 g_clear_object (&self->texture);
2232 }
2233
2234 static GstStateChangeReturn
gst_ahc_src_change_state(GstElement * element,GstStateChange transition)2235 gst_ahc_src_change_state (GstElement * element, GstStateChange transition)
2236 {
2237 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2238 GstAHCSrc *self = GST_AHC_SRC (element);
2239
2240 switch (transition) {
2241 case GST_STATE_CHANGE_NULL_TO_READY:
2242 if (!gst_ahc_src_open (self))
2243 return GST_STATE_CHANGE_FAILURE;
2244 break;
2245 default:
2246 break;
2247 }
2248
2249 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2250
2251 switch (transition) {
2252 case GST_STATE_CHANGE_READY_TO_NULL:
2253 gst_ahc_src_close (self);
2254 break;
2255 default:
2256 break;
2257 }
2258
2259 return ret;
2260 }
2261
2262 static gboolean
gst_ahc_src_start(GstBaseSrc * bsrc)2263 gst_ahc_src_start (GstBaseSrc * bsrc)
2264 {
2265 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2266
2267 GST_DEBUG_OBJECT (self, "Starting preview");
2268 if (self->camera) {
2269 self->previous_ts = GST_CLOCK_TIME_NONE;
2270 self->fps_min = self->fps_max = self->width = self->height = 0;
2271 self->format = ImageFormat_UNKNOWN;
2272 self->start = TRUE;
2273
2274 return TRUE;
2275 } else {
2276 return FALSE;
2277 }
2278 }
2279
2280 static gboolean
gst_ahc_src_stop(GstBaseSrc * bsrc)2281 gst_ahc_src_stop (GstBaseSrc * bsrc)
2282 {
2283 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2284
2285 GST_DEBUG_OBJECT (self, "Stopping preview");
2286 if (self->camera) {
2287 gst_data_queue_flush (self->queue);
2288 self->start = FALSE;
2289 gst_ah_camera_set_error_callback (self->camera, NULL, NULL);
2290 return gst_ah_camera_stop_preview (self->camera);
2291 }
2292 return TRUE;
2293 }
2294
2295 static gboolean
gst_ahc_src_unlock(GstBaseSrc * bsrc)2296 gst_ahc_src_unlock (GstBaseSrc * bsrc)
2297 {
2298 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2299
2300 GST_DEBUG_OBJECT (self, "Unlocking create");
2301 gst_data_queue_set_flushing (self->queue, TRUE);
2302
2303 return TRUE;
2304 }
2305
2306 static gboolean
gst_ahc_src_unlock_stop(GstBaseSrc * bsrc)2307 gst_ahc_src_unlock_stop (GstBaseSrc * bsrc)
2308 {
2309 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2310
2311 GST_DEBUG_OBJECT (self, "Stopping unlock");
2312 gst_data_queue_set_flushing (self->queue, FALSE);
2313
2314 return TRUE;
2315 }
2316
2317 static GstFlowReturn
gst_ahc_src_create(GstPushSrc * src,GstBuffer ** buffer)2318 gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer)
2319 {
2320 GstAHCSrc *self = GST_AHC_SRC (src);
2321 GstDataQueueItem *item;
2322
2323 if (!gst_data_queue_pop (self->queue, &item)) {
2324 GST_INFO_OBJECT (self, "empty queue");
2325 return GST_FLOW_FLUSHING;
2326 }
2327
2328 GST_DEBUG_OBJECT (self, "creating buffer %p->%p", item, item->object);
2329
2330 *buffer = GST_BUFFER (item->object);
2331 g_slice_free (GstDataQueueItem, item);
2332
2333 return GST_FLOW_OK;
2334 }
2335
2336 static gboolean
gst_ahc_src_query(GstBaseSrc * bsrc,GstQuery * query)2337 gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query)
2338 {
2339 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2340
2341 switch (GST_QUERY_TYPE (query)) {
2342 case GST_QUERY_LATENCY:{
2343 GstClockTime min;
2344
2345 /* Cannot query latency before setcaps() */
2346 if (self->fps_min == 0)
2347 return FALSE;
2348
2349 /* Allow of 1 frame latency base on the longer frame duration */
2350 gst_query_parse_latency (query, NULL, &min, NULL);
2351 min = gst_util_uint64_scale (GST_SECOND, 1000, self->fps_min);
2352 GST_DEBUG_OBJECT (self,
2353 "Reporting latency min: %" GST_TIME_FORMAT, GST_TIME_ARGS (min));
2354 gst_query_set_latency (query, TRUE, min, min);
2355
2356 return TRUE;
2357 break;
2358 }
2359 default:
2360 return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
2361 break;
2362 }
2363
2364 g_assert_not_reached ();
2365 }
2366