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 retrieved 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 #define GST_USE_UNSTABLE_API
71 #include <gst/interfaces/photography.h>
72
73 #include "gstjniutils.h"
74
75 #include "gstahcsrc.h"
76
77 /* GObject */
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);
83
84 /* GstElement */
85 static GstStateChangeReturn gst_ahc_src_change_state (GstElement * element,
86 GstStateChange transition);
87
88 /* GstBaseSrc */
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);
98
99 /* GstPhotography */
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,
103 gfloat * ev_comp);
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);
129
130 static gboolean gst_ahc_src_set_ev_compensation (GstPhotography * photo,
131 gfloat ev_comp);
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);
145
146 static GstPhotographyCaps gst_ahc_src_get_capabilities (GstPhotography * photo);
147 static void gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on);
148
149 /* GstAHCSrc */
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);
154
155 #define NUM_CALLBACK_BUFFERS 5
156
157 #define GST_AHC_SRC_CAPS_STR \
158 GST_VIDEO_CAPS_MAKE_WITH_FEATURES("ANY", " { YV12, YUY2, NV21, NV16, RGB16 }")
159
160 static GstStaticPadTemplate gst_ahc_src_pad_template =
161 GST_STATIC_PAD_TEMPLATE ("src",
162 GST_PAD_SRC,
163 GST_PAD_ALWAYS,
164 GST_STATIC_CAPS (GST_AHC_SRC_CAPS_STR));
165
166 GST_DEBUG_CATEGORY_STATIC (gst_ahc_src_debug);
167 #define GST_CAT_DEFAULT gst_ahc_src_debug
168
169 #define parent_class gst_ahc_src_parent_class
170
171 enum
172 {
173 PROP_0,
174 PROP_DEVICE,
175 PROP_DEVICE_NAME,
176 PROP_DEVICE_FACING,
177 PROP_DEVICE_ORIENTATION,
178 PROP_FOCAL_LENGTH,
179 PROP_HORIZONTAL_VIEW_ANGLE,
180 PROP_VERTICAL_VIEW_ANGLE,
181 PROP_VIDEO_STABILIZATION,
182 PROP_WB_MODE,
183 PROP_COLOUR_TONE,
184 PROP_SCENE_MODE,
185 PROP_FLASH_MODE,
186 PROP_NOISE_REDUCTION,
187 PROP_CAPABILITIES,
188 PROP_EV_COMP,
189 PROP_ISO_SPEED,
190 PROP_APERTURE,
191 PROP_EXPOSURE_MODE,
192 PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
193 PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
194 PROP_FLICKER_MODE,
195 PROP_FOCUS_MODE,
196 PROP_ZOOM,
197 PROP_SMOOTH_ZOOM,
198 PROP_WHITE_POINT,
199 PROP_MIN_EXPOSURE_TIME,
200 PROP_MAX_EXPOSURE_TIME,
201 PROP_LENS_FOCUS,
202 PROP_EXPOSURE_TIME,
203 PROP_COLOR_TEMPERATURE,
204 PROP_ANALOG_GAIN,
205 PROP_LAST
206 };
207
208 static GParamSpec *properties[PROP_LAST];
209
210 #define DEFAULT_DEVICE "0"
211
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));
214
215 #define CAMERA_FACING_BACK 0
216 #define CAMERA_FACING_FRONT 1
217
218 static GType
gst_ahc_src_facing_get_type(void)219 gst_ahc_src_facing_get_type (void)
220 {
221 static GType type = 0;
222 static const GEnumValue types[] = {
223 {CAMERA_FACING_BACK, "Back", "back"},
224 {CAMERA_FACING_FRONT, "Front", "front"},
225 {0, NULL, NULL}
226 };
227
228 if (!type) {
229 type = g_enum_register_static ("GstAHCSrcFacing", types);
230 }
231 return type;
232 }
233
234 #define GST_AHC_SRC_FACING_TYPE (gst_ahc_src_facing_get_type())
235
236 static void
gst_ahc_src_photography_init(gpointer g_iface,gpointer iface_data)237 gst_ahc_src_photography_init (gpointer g_iface, gpointer iface_data)
238 {
239 GstPhotographyInterface *iface = g_iface;
240
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;
249
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;
258
259 iface->get_capabilities = gst_ahc_src_get_capabilities;
260 iface->set_autofocus = gst_ahc_src_set_autofocus;
261 }
262
263 static void
gst_ahc_src_class_init(GstAHCSrcClass * klass)264 gst_ahc_src_class_init (GstAHCSrcClass * klass)
265 {
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);
270
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;
274
275 element_class->change_state = gst_ahc_src_change_state;
276
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;
285
286 gstpushsrc_class->create = gst_ahc_src_create;
287
288 gst_element_class_add_static_pad_template (element_class,
289 &gst_ahc_src_pad_template);
290
291 /**
292 * GstAHCSrc:device:
293 *
294 * The Device ID of the camera to capture from
295 */
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]);
301
302 /**
303 * GstAHCSrc:device-name:
304 *
305 * A user-friendly name for the camera device
306 */
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]);
312
313 /**
314 * GstAHCSrc:device-orientation:
315 *
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.
320 */
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]);
326
327 /**
328 * GstAHCSrc:device-facing:
329 *
330 * The direction that the currently select camera @device faces.
331 *
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
334 * as the screen.
335 */
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]);
342
343 /**
344 * GstAHCSrc:focal-length:
345 *
346 * Gets the focal length (in millimeter) of the camera.
347 */
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]);
353
354 /**
355 * GstAHCSrc:horizontal-view-angle:
356 *
357 * Gets the horizontal angle of view in degrees.
358 */
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]);
365
366 /**
367 * GstAHCSrc:vertical-view-angle:
368 *
369 * Gets the vertical angle of view in degrees.
370 */
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]);
377
378 /**
379 * GstAHCSrc:video-stabilization:
380 *
381 * Video stabilization reduces the shaking due to the motion of the camera.
382 */
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]);
389
390 /**
391 * GstAHCSrc:smooth-zoom:
392 *
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.
396 */
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]);
402
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);
408
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);
413
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);
418
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);
423
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);
429
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);
434
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);
439
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);
444
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);
449
450 #if 0
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);
455 #endif
456
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);
463
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);
470
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);
475
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);
480
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);
485
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);
490
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);
496
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);
502
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);
507
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);
512
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);
518
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);
523
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>");
529
530 GST_DEBUG_CATEGORY_INIT (gst_ahc_src_debug, "ahcsrc", 0,
531 "android.hardware.Camera source element");
532 }
533
534 static gboolean
_data_queue_check_full(GstDataQueue * queue,guint visible,guint bytes,guint64 time,gpointer checkdata)535 _data_queue_check_full (GstDataQueue * queue, guint visible,
536 guint bytes, guint64 time, gpointer checkdata)
537 {
538 return FALSE;
539 }
540
541 static void
gst_ahc_src_init(GstAHCSrc * self)542 gst_ahc_src_init (GstAHCSrc * self)
543 {
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);
547
548 self->camera = NULL;
549 self->texture = NULL;
550 self->data = NULL;
551 self->queue = gst_data_queue_new (_data_queue_check_full, NULL, NULL, NULL);
552 self->start = FALSE;
553 self->previous_ts = GST_CLOCK_TIME_NONE;
554
555 g_mutex_init (&self->mutex);
556 }
557
558 static void
gst_ahc_src_finalize(GObject * object)559 gst_ahc_src_finalize (GObject * object)
560 {
561 GstAHCSrc *self = GST_AHC_SRC (object);
562
563 g_clear_object (&self->queue);
564 g_mutex_clear (&self->mutex);
565
566 G_OBJECT_CLASS (parent_class)->finalize (object);
567 }
568
569 static void
gst_ahc_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)570 gst_ahc_src_set_property (GObject * object, guint prop_id,
571 const GValue * value, GParamSpec * pspec)
572 {
573 GstAHCSrc *self = GST_AHC_SRC (object);
574
575 GST_DEBUG_OBJECT (self, "set props %d", prop_id);
576
577 switch (prop_id) {
578 case PROP_DEVICE:{
579 const gchar *dev = g_value_get_string (value);
580 gchar *endptr = NULL;
581 guint64 device;
582
583 device = g_ascii_strtoll (dev, &endptr, 10);
584 if (endptr != dev && endptr[0] == 0 && device < G_MAXINT)
585 self->device = (gint) device;
586 }
587 break;
588 case PROP_VIDEO_STABILIZATION:
589 if (self->camera) {
590 GstAHCParameters *params;
591
592 params = gst_ah_camera_get_parameters (self->camera);
593 if (params) {
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);
598 }
599 }
600 break;
601 case PROP_SMOOTH_ZOOM:
602 self->smooth_zoom = g_value_get_boolean (value);
603 break;
604 case PROP_WB_MODE:{
605 GstPhotographyWhiteBalanceMode wb = g_value_get_enum (value);
606
607 gst_ahc_src_set_white_balance_mode (GST_PHOTOGRAPHY (self), wb);
608 }
609 break;
610 case PROP_COLOUR_TONE:{
611 GstPhotographyColorToneMode tone = g_value_get_enum (value);
612
613 gst_ahc_src_set_colour_tone_mode (GST_PHOTOGRAPHY (self), tone);
614 }
615 break;
616 case PROP_SCENE_MODE:{
617 GstPhotographySceneMode scene = g_value_get_enum (value);
618
619 gst_ahc_src_set_scene_mode (GST_PHOTOGRAPHY (self), scene);
620 }
621 break;
622 case PROP_FLASH_MODE:{
623 GstPhotographyFlashMode flash = g_value_get_enum (value);
624
625 gst_ahc_src_set_flash_mode (GST_PHOTOGRAPHY (self), flash);
626 }
627 break;
628 case PROP_EV_COMP:{
629 gfloat ev = g_value_get_float (value);
630
631 gst_ahc_src_set_ev_compensation (GST_PHOTOGRAPHY (self), ev);
632 }
633 break;
634 case PROP_FLICKER_MODE:{
635 GstPhotographyFlickerReductionMode flicker = g_value_get_enum (value);
636
637 gst_ahc_src_set_flicker_mode (GST_PHOTOGRAPHY (self), flicker);
638 }
639 break;
640 case PROP_FOCUS_MODE:{
641 GstPhotographyFocusMode focus = g_value_get_enum (value);
642
643 gst_ahc_src_set_focus_mode (GST_PHOTOGRAPHY (self), focus);
644 }
645 break;
646 case PROP_ZOOM:{
647 gfloat zoom = g_value_get_float (value);
648
649 gst_ahc_src_set_zoom (GST_PHOTOGRAPHY (self), zoom);
650 }
651 break;
652 case PROP_NOISE_REDUCTION:
653 case PROP_ISO_SPEED:
654 case PROP_APERTURE:
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:
665 break;
666 default:
667 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
668 break;
669 }
670 }
671
672 static void
gst_ahc_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)673 gst_ahc_src_get_property (GObject * object, guint prop_id,
674 GValue * value, GParamSpec * pspec)
675 {
676 GstAHCSrc *self = GST_AHC_SRC (object);
677 (void) self;
678
679 switch (prop_id) {
680 case PROP_DEVICE:{
681 gchar *dev = g_strdup_printf ("%d", self->device);
682
683 g_value_take_string (value, dev);
684 }
685 break;
686 case PROP_DEVICE_NAME:{
687 GstAHCCameraInfo info;
688 gchar *dev;
689
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");
693 else
694 dev = g_strdup_printf ("#%d", self->device);
695
696 g_value_take_string (value, dev);
697 }
698 break;
699 case PROP_DEVICE_FACING:{
700 GstAHCCameraInfo info;
701
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);
705 else
706 g_value_set_enum (value, CAMERA_FACING_BACK);
707 }
708 break;
709 case PROP_DEVICE_ORIENTATION:{
710 GstAHCCameraInfo info;
711
712 if (gst_ah_camera_get_camera_info (self->device, &info))
713 g_value_set_int (value, info.orientation);
714 else
715 g_value_set_int (value, 0);
716 }
717 break;
718 case PROP_FOCAL_LENGTH:
719 if (self->camera) {
720 GstAHCParameters *params;
721
722 params = gst_ah_camera_get_parameters (self->camera);
723 if (params) {
724 g_value_set_float (value,
725 gst_ahc_parameters_get_focal_length (params));
726 gst_ahc_parameters_free (params);
727 }
728 }
729 break;
730 case PROP_HORIZONTAL_VIEW_ANGLE:
731 if (self->camera) {
732 GstAHCParameters *params;
733
734 params = gst_ah_camera_get_parameters (self->camera);
735 if (params) {
736 g_value_set_float (value,
737 gst_ahc_parameters_get_horizontal_view_angle (params));
738 gst_ahc_parameters_free (params);
739 }
740 }
741 break;
742 case PROP_VERTICAL_VIEW_ANGLE:
743 if (self->camera) {
744 GstAHCParameters *params;
745
746 params = gst_ah_camera_get_parameters (self->camera);
747 if (params) {
748 g_value_set_float (value,
749 gst_ahc_parameters_get_vertical_view_angle (params));
750 gst_ahc_parameters_free (params);
751 }
752 }
753 break;
754 case PROP_VIDEO_STABILIZATION:
755 if (self->camera) {
756 GstAHCParameters *params;
757
758 params = gst_ah_camera_get_parameters (self->camera);
759 if (params) {
760 g_value_set_boolean (value,
761 gst_ahc_parameters_get_video_stabilization (params));
762 gst_ahc_parameters_free (params);
763 }
764 }
765 break;
766 case PROP_SMOOTH_ZOOM:
767 g_value_set_boolean (value, self->smooth_zoom);
768 break;
769 case PROP_WB_MODE:{
770 GstPhotographyWhiteBalanceMode wb;
771
772 if (gst_ahc_src_get_white_balance_mode (GST_PHOTOGRAPHY (self), &wb))
773 g_value_set_enum (value, wb);
774 }
775 break;
776 case PROP_COLOUR_TONE:{
777 GstPhotographyColorToneMode tone;
778
779 if (gst_ahc_src_get_colour_tone_mode (GST_PHOTOGRAPHY (self), &tone))
780 g_value_set_enum (value, tone);
781 }
782 break;
783 case PROP_SCENE_MODE:{
784 GstPhotographySceneMode scene;
785
786 if (gst_ahc_src_get_scene_mode (GST_PHOTOGRAPHY (self), &scene))
787 g_value_set_enum (value, scene);
788 }
789 break;
790 case PROP_FLASH_MODE:{
791 GstPhotographyFlashMode flash;
792
793 if (gst_ahc_src_get_flash_mode (GST_PHOTOGRAPHY (self), &flash))
794 g_value_set_enum (value, flash);
795 }
796 break;
797 case PROP_CAPABILITIES:{
798 GstPhotographyCaps caps;
799
800 caps = gst_ahc_src_get_capabilities (GST_PHOTOGRAPHY (self));
801 g_value_set_ulong (value, caps);
802 }
803 break;
804 case PROP_EV_COMP:{
805 gfloat ev;
806
807 if (gst_ahc_src_get_ev_compensation (GST_PHOTOGRAPHY (self), &ev))
808 g_value_set_float (value, ev);
809 }
810 break;
811 case PROP_FLICKER_MODE:{
812 GstPhotographyFlickerReductionMode flicker;
813
814 if (gst_ahc_src_get_flicker_mode (GST_PHOTOGRAPHY (self), &flicker))
815 g_value_set_enum (value, flicker);
816 }
817 break;
818 case PROP_FOCUS_MODE:{
819 GstPhotographyFocusMode focus;
820
821 if (gst_ahc_src_get_focus_mode (GST_PHOTOGRAPHY (self), &focus))
822 g_value_set_enum (value, focus);
823 }
824 break;
825 case PROP_ZOOM:{
826 gfloat zoom;
827
828 if (gst_ahc_src_get_zoom (GST_PHOTOGRAPHY (self), &zoom))
829 g_value_set_float (value, zoom);
830 }
831 break;
832 case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:
833 case PROP_IMAGE_PREVIEW_SUPPORTED_CAPS:
834 case PROP_NOISE_REDUCTION:
835 case PROP_ISO_SPEED:
836 case PROP_APERTURE:
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:
845 break;
846 default:
847 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
848 break;
849 }
850 }
851
852 static gboolean
_antibanding_to_enum(const gchar * antibanding,GstPhotographyFlickerReductionMode * mode)853 _antibanding_to_enum (const gchar * antibanding,
854 GstPhotographyFlickerReductionMode * mode)
855 {
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;
864 else
865 return FALSE;
866
867 return TRUE;
868 }
869
870 static gboolean
_white_balance_to_enum(const gchar * white_balance,GstPhotographyWhiteBalanceMode * mode)871 _white_balance_to_enum (const gchar * white_balance,
872 GstPhotographyWhiteBalanceMode * mode)
873 {
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;
890 else
891 return FALSE;
892
893 return TRUE;
894 }
895
896 static gboolean
_color_effects_to_enum(const gchar * color_effect,GstPhotographyColorToneMode * mode)897 _color_effects_to_enum (const gchar * color_effect,
898 GstPhotographyColorToneMode * mode)
899 {
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;
918 else
919 return FALSE;
920
921 return TRUE;
922 }
923
924 static gboolean
_scene_modes_to_enum(const gchar * scene,GstPhotographySceneMode * mode)925 _scene_modes_to_enum (const gchar * scene, GstPhotographySceneMode * mode)
926 {
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;
959 else
960 return FALSE;
961
962 return TRUE;
963 }
964
965 static gboolean
_flash_modes_to_enum(const gchar * flash,GstPhotographyFlashMode * mode)966 _flash_modes_to_enum (const gchar * flash, GstPhotographyFlashMode * mode)
967 {
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;
978 else
979 return FALSE;
980
981 return TRUE;
982 }
983
984 static gboolean
_focus_modes_to_enum(const gchar * focus,GstPhotographyFocusMode * mode)985 _focus_modes_to_enum (const gchar * focus, GstPhotographyFocusMode * mode)
986 {
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;
1001 else
1002 return FALSE;
1003
1004 return TRUE;
1005 }
1006
1007 static gboolean
gst_ahc_src_get_ev_compensation(GstPhotography * photo,gfloat * ev_comp)1008 gst_ahc_src_get_ev_compensation (GstPhotography * photo, gfloat * ev_comp)
1009 {
1010 GstAHCSrc *self = GST_AHC_SRC (photo);
1011 gboolean ret = FALSE;
1012
1013 if (self->camera) {
1014 GstAHCParameters *params;
1015
1016 params = gst_ah_camera_get_parameters (self->camera);
1017 if (params) {
1018 gint ev, min, max;
1019 gfloat step;
1020
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);
1025
1026 if (step != 0.0 && min != max && min <= ev && ev <= max) {
1027 if (ev_comp)
1028 *ev_comp = ev * step;
1029 ret = TRUE;
1030 }
1031 gst_ahc_parameters_free (params);
1032 }
1033 }
1034
1035 return ret;
1036 }
1037
1038 static gboolean
gst_ahc_src_get_white_balance_mode(GstPhotography * photo,GstPhotographyWhiteBalanceMode * wb_mode)1039 gst_ahc_src_get_white_balance_mode (GstPhotography * photo,
1040 GstPhotographyWhiteBalanceMode * wb_mode)
1041 {
1042 GstAHCSrc *self = GST_AHC_SRC (photo);
1043 gboolean ret = FALSE;
1044
1045 if (self->camera) {
1046 GstAHCParameters *params;
1047
1048 params = gst_ah_camera_get_parameters (self->camera);
1049 if (params) {
1050 const gchar *wb = gst_ahc_parameters_get_white_balance (params);
1051 GstPhotographyWhiteBalanceMode mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
1052
1053 if (_white_balance_to_enum (wb, &mode)) {
1054 ret = TRUE;
1055
1056 if (wb_mode)
1057 *wb_mode = mode;
1058 }
1059
1060 gst_ahc_parameters_free (params);
1061 }
1062 }
1063
1064 return ret;
1065 }
1066
1067 static gboolean
gst_ahc_src_get_colour_tone_mode(GstPhotography * photo,GstPhotographyColorToneMode * tone_mode)1068 gst_ahc_src_get_colour_tone_mode (GstPhotography * photo,
1069 GstPhotographyColorToneMode * tone_mode)
1070 {
1071 GstAHCSrc *self = GST_AHC_SRC (photo);
1072 gboolean ret = FALSE;
1073
1074 if (self->camera) {
1075 GstAHCParameters *params;
1076
1077 params = gst_ah_camera_get_parameters (self->camera);
1078 if (params) {
1079 const gchar *effect = gst_ahc_parameters_get_color_effect (params);
1080 GstPhotographyColorToneMode mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
1081
1082 if (_color_effects_to_enum (effect, &mode)) {
1083 ret = TRUE;
1084
1085 if (tone_mode)
1086 *tone_mode = mode;
1087 }
1088
1089 gst_ahc_parameters_free (params);
1090 }
1091 }
1092
1093 return ret;
1094 }
1095
1096 static gboolean
gst_ahc_src_get_scene_mode(GstPhotography * photo,GstPhotographySceneMode * scene_mode)1097 gst_ahc_src_get_scene_mode (GstPhotography * photo,
1098 GstPhotographySceneMode * scene_mode)
1099 {
1100 GstAHCSrc *self = GST_AHC_SRC (photo);
1101 gboolean ret = FALSE;
1102
1103 if (scene_mode && self->camera) {
1104 GstAHCParameters *params;
1105
1106 params = gst_ah_camera_get_parameters (self->camera);
1107 if (params) {
1108 const gchar *scene = gst_ahc_parameters_get_scene_mode (params);
1109 GstPhotographySceneMode mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
1110
1111 if (_scene_modes_to_enum (scene, &mode)) {
1112 ret = TRUE;
1113
1114 if (scene_mode)
1115 *scene_mode = mode;
1116 }
1117
1118 gst_ahc_parameters_free (params);
1119 }
1120 }
1121
1122 return ret;
1123 }
1124
1125 static gboolean
gst_ahc_src_get_flash_mode(GstPhotography * photo,GstPhotographyFlashMode * flash_mode)1126 gst_ahc_src_get_flash_mode (GstPhotography * photo,
1127 GstPhotographyFlashMode * flash_mode)
1128 {
1129 GstAHCSrc *self = GST_AHC_SRC (photo);
1130 gboolean ret = FALSE;
1131
1132 if (self->camera) {
1133 GstAHCParameters *params;
1134
1135 params = gst_ah_camera_get_parameters (self->camera);
1136 if (params) {
1137 const gchar *flash = gst_ahc_parameters_get_flash_mode (params);
1138 GstPhotographyFlashMode mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
1139
1140 if (_flash_modes_to_enum (flash, &mode)) {
1141 ret = TRUE;
1142
1143 if (flash_mode)
1144 *flash_mode = mode;
1145 }
1146
1147 gst_ahc_parameters_free (params);
1148 }
1149 }
1150
1151 return ret;
1152 }
1153
1154 static gboolean
gst_ahc_src_get_zoom(GstPhotography * photo,gfloat * zoom)1155 gst_ahc_src_get_zoom (GstPhotography * photo, gfloat * zoom)
1156 {
1157 GstAHCSrc *self = GST_AHC_SRC (photo);
1158 gboolean ret = FALSE;
1159
1160 if (self->camera) {
1161 GstAHCParameters *params;
1162
1163 params = gst_ah_camera_get_parameters (self->camera);
1164 if (params) {
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);
1168
1169 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1) &&
1170 zoom_idx >= 0 && zoom_idx < max_zoom) {
1171 gint zoom_value;
1172
1173 zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, zoom_idx));
1174 if (zoom)
1175 *zoom = (gfloat) zoom_value / 100.0;
1176
1177 ret = TRUE;
1178 }
1179
1180 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1181 gst_ahc_parameters_free (params);
1182 }
1183 }
1184
1185 return ret;
1186 }
1187
1188 static gboolean
gst_ahc_src_get_flicker_mode(GstPhotography * photo,GstPhotographyFlickerReductionMode * flicker_mode)1189 gst_ahc_src_get_flicker_mode (GstPhotography * photo,
1190 GstPhotographyFlickerReductionMode * flicker_mode)
1191 {
1192 GstAHCSrc *self = GST_AHC_SRC (photo);
1193 gboolean ret = FALSE;
1194
1195 if (self->camera) {
1196 GstAHCParameters *params;
1197
1198 params = gst_ah_camera_get_parameters (self->camera);
1199 if (params) {
1200 const gchar *antibanding = gst_ahc_parameters_get_antibanding (params);
1201 GstPhotographyFlickerReductionMode mode =
1202 GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO;
1203
1204 if (_antibanding_to_enum (antibanding, &mode)) {
1205 ret = TRUE;
1206
1207 if (flicker_mode)
1208 *flicker_mode = mode;
1209 }
1210
1211 gst_ahc_parameters_free (params);
1212 }
1213 }
1214
1215 return ret;
1216 }
1217
1218 static gboolean
gst_ahc_src_get_focus_mode(GstPhotography * photo,GstPhotographyFocusMode * focus_mode)1219 gst_ahc_src_get_focus_mode (GstPhotography * photo,
1220 GstPhotographyFocusMode * focus_mode)
1221 {
1222 GstAHCSrc *self = GST_AHC_SRC (photo);
1223 gboolean ret = FALSE;
1224
1225 if (self->camera) {
1226 GstAHCParameters *params;
1227
1228 params = gst_ah_camera_get_parameters (self->camera);
1229 if (params) {
1230 const gchar *focus = gst_ahc_parameters_get_focus_mode (params);
1231 GstPhotographyFocusMode mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
1232
1233 if (_focus_modes_to_enum (focus, &mode)) {
1234 ret = TRUE;
1235
1236 if (focus_mode)
1237 *focus_mode = mode;
1238 }
1239
1240 gst_ahc_parameters_free (params);
1241 }
1242 }
1243
1244 return ret;
1245 }
1246
1247
1248 static gboolean
gst_ahc_src_set_ev_compensation(GstPhotography * photo,gfloat ev_comp)1249 gst_ahc_src_set_ev_compensation (GstPhotography * photo, gfloat ev_comp)
1250 {
1251 GstAHCSrc *self = GST_AHC_SRC (photo);
1252 gboolean ret = FALSE;
1253
1254 if (self->camera) {
1255 GstAHCParameters *params;
1256
1257 params = gst_ah_camera_get_parameters (self->camera);
1258 if (params) {
1259 gint ev, min, max;
1260 gfloat step;
1261
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);
1272 }
1273 }
1274 }
1275 gst_ahc_parameters_free (params);
1276 }
1277
1278 return ret;
1279 }
1280
1281 static gboolean
gst_ahc_src_set_white_balance_mode(GstPhotography * photo,GstPhotographyWhiteBalanceMode wb_mode)1282 gst_ahc_src_set_white_balance_mode (GstPhotography * photo,
1283 GstPhotographyWhiteBalanceMode wb_mode)
1284 {
1285 GstAHCSrc *self = GST_AHC_SRC (photo);
1286 gboolean ret = FALSE;
1287
1288 if (self->camera) {
1289 GstAHCParameters *params;
1290
1291 params = gst_ah_camera_get_parameters (self->camera);
1292 if (params) {
1293 const gchar *white_balance = NULL;
1294
1295 switch (wb_mode) {
1296 case GST_PHOTOGRAPHY_WB_MODE_AUTO:
1297 white_balance = Parameters_WHITE_BALANCE_AUTO;
1298 break;
1299 case GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT:
1300 white_balance = Parameters_WHITE_BALANCE_DAYLIGHT;
1301 break;
1302 case GST_PHOTOGRAPHY_WB_MODE_CLOUDY:
1303 white_balance = Parameters_WHITE_BALANCE_CLOUDY_DAYLIGHT;
1304 break;
1305 case GST_PHOTOGRAPHY_WB_MODE_SUNSET:
1306 white_balance = Parameters_WHITE_BALANCE_TWILIGHT;
1307 break;
1308 case GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN:
1309 white_balance = Parameters_WHITE_BALANCE_INCANDESCENT;
1310 break;
1311 case GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT:
1312 white_balance = Parameters_WHITE_BALANCE_FLUORESCENT;
1313 break;
1314 case GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT:
1315 white_balance = Parameters_WHITE_BALANCE_WARM_FLUORESCENT;
1316 break;
1317 case GST_PHOTOGRAPHY_WB_MODE_SHADE:
1318 white_balance = Parameters_WHITE_BALANCE_SHADE;
1319 break;
1320 default:
1321 white_balance = NULL;
1322 break;
1323 }
1324
1325 if (white_balance) {
1326 gst_ahc_parameters_set_white_balance (params, white_balance);
1327 ret = gst_ah_camera_set_parameters (self->camera, params);
1328 }
1329 gst_ahc_parameters_free (params);
1330 }
1331 }
1332
1333 return ret;
1334 }
1335
1336 static gboolean
gst_ahc_src_set_colour_tone_mode(GstPhotography * photo,GstPhotographyColorToneMode tone_mode)1337 gst_ahc_src_set_colour_tone_mode (GstPhotography * photo,
1338 GstPhotographyColorToneMode tone_mode)
1339 {
1340 GstAHCSrc *self = GST_AHC_SRC (photo);
1341 gboolean ret = FALSE;
1342
1343 if (self->camera) {
1344 GstAHCParameters *params;
1345
1346 params = gst_ah_camera_get_parameters (self->camera);
1347 if (params) {
1348 const gchar *color_effect = NULL;
1349
1350 switch (tone_mode) {
1351 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL:
1352 color_effect = Parameters_EFFECT_NONE;
1353 break;
1354 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA:
1355 color_effect = Parameters_EFFECT_SEPIA;
1356 break;
1357 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE:
1358 color_effect = Parameters_EFFECT_NEGATIVE;
1359 break;
1360 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE:
1361 color_effect = Parameters_EFFECT_MONO;
1362 break;
1363 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE:
1364 color_effect = Parameters_EFFECT_SOLARIZE;
1365 break;
1366 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE:
1367 color_effect = Parameters_EFFECT_POSTERIZE;
1368 break;
1369 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD:
1370 color_effect = Parameters_EFFECT_WHITEBOARD;
1371 break;
1372 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD:
1373 color_effect = Parameters_EFFECT_BLACKBOARD;
1374 break;
1375 case GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA:
1376 color_effect = Parameters_EFFECT_AQUA;
1377 break;
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:
1385 default:
1386 color_effect = NULL;
1387 break;
1388 }
1389
1390 if (color_effect) {
1391 gst_ahc_parameters_set_color_effect (params, color_effect);
1392 ret = gst_ah_camera_set_parameters (self->camera, params);
1393 }
1394 gst_ahc_parameters_free (params);
1395 }
1396 }
1397
1398 return ret;
1399 }
1400
1401 static gboolean
gst_ahc_src_set_scene_mode(GstPhotography * photo,GstPhotographySceneMode scene_mode)1402 gst_ahc_src_set_scene_mode (GstPhotography * photo,
1403 GstPhotographySceneMode scene_mode)
1404 {
1405 GstAHCSrc *self = GST_AHC_SRC (photo);
1406 gboolean ret = FALSE;
1407
1408 if (self->camera) {
1409 GstAHCParameters *params;
1410
1411 params = gst_ah_camera_get_parameters (self->camera);
1412 if (params) {
1413 const gchar *scene = NULL;
1414
1415 switch (scene_mode) {
1416 case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT:
1417 scene = Parameters_SCENE_MODE_PORTRAIT;
1418 break;
1419 case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE:
1420 scene = Parameters_SCENE_MODE_LANDSCAPE;
1421 break;
1422 case GST_PHOTOGRAPHY_SCENE_MODE_SPORT:
1423 scene = Parameters_SCENE_MODE_SPORTS;
1424 break;
1425 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT:
1426 scene = Parameters_SCENE_MODE_NIGHT;
1427 break;
1428 case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
1429 scene = Parameters_SCENE_MODE_AUTO;
1430 break;
1431 case GST_PHOTOGRAPHY_SCENE_MODE_ACTION:
1432 scene = Parameters_SCENE_MODE_ACTION;
1433 break;
1434 case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT:
1435 scene = Parameters_SCENE_MODE_NIGHT_PORTRAIT;
1436 break;
1437 case GST_PHOTOGRAPHY_SCENE_MODE_THEATRE:
1438 scene = Parameters_SCENE_MODE_THEATRE;
1439 break;
1440 case GST_PHOTOGRAPHY_SCENE_MODE_BEACH:
1441 scene = Parameters_SCENE_MODE_BEACH;
1442 break;
1443 case GST_PHOTOGRAPHY_SCENE_MODE_SNOW:
1444 scene = Parameters_SCENE_MODE_SNOW;
1445 break;
1446 case GST_PHOTOGRAPHY_SCENE_MODE_SUNSET:
1447 scene = Parameters_SCENE_MODE_SUNSET;
1448 break;
1449 case GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO:
1450 scene = Parameters_SCENE_MODE_STEADYPHOTO;
1451 break;
1452 case GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS:
1453 scene = Parameters_SCENE_MODE_FIREWORKS;
1454 break;
1455 case GST_PHOTOGRAPHY_SCENE_MODE_PARTY:
1456 scene = Parameters_SCENE_MODE_PARTY;
1457 break;
1458 case GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT:
1459 scene = Parameters_SCENE_MODE_CANDLELIGHT;
1460 break;
1461 case GST_PHOTOGRAPHY_SCENE_MODE_BARCODE:
1462 scene = Parameters_SCENE_MODE_BARCODE;
1463 break;
1464 case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL:
1465 case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP:
1466 default:
1467 scene = NULL;
1468 break;
1469 }
1470
1471 if (scene) {
1472 gst_ahc_parameters_set_scene_mode (params, scene);
1473 ret = gst_ah_camera_set_parameters (self->camera, params);
1474 }
1475 gst_ahc_parameters_free (params);
1476 }
1477 }
1478
1479 return ret;
1480 }
1481
1482 static gboolean
gst_ahc_src_set_flash_mode(GstPhotography * photo,GstPhotographyFlashMode flash_mode)1483 gst_ahc_src_set_flash_mode (GstPhotography * photo,
1484 GstPhotographyFlashMode flash_mode)
1485 {
1486 GstAHCSrc *self = GST_AHC_SRC (photo);
1487 gboolean ret = FALSE;
1488
1489 if (self->camera) {
1490 GstAHCParameters *params;
1491
1492 params = gst_ah_camera_get_parameters (self->camera);
1493 if (params) {
1494 const gchar *flash = NULL;
1495
1496 switch (flash_mode) {
1497 case GST_PHOTOGRAPHY_FLASH_MODE_AUTO:
1498 flash = Parameters_FLASH_MODE_AUTO;
1499 break;
1500 case GST_PHOTOGRAPHY_FLASH_MODE_OFF:
1501 flash = Parameters_FLASH_MODE_OFF;
1502 break;
1503 case GST_PHOTOGRAPHY_FLASH_MODE_ON:
1504 flash = Parameters_FLASH_MODE_ON;
1505 break;
1506 case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN:
1507 flash = Parameters_FLASH_MODE_TORCH;
1508 break;
1509 case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE:
1510 flash = Parameters_FLASH_MODE_RED_EYE;
1511 break;
1512 default:
1513 flash = NULL;
1514 break;
1515 }
1516
1517 if (flash) {
1518 gst_ahc_parameters_set_flash_mode (params, flash);
1519 ret = gst_ah_camera_set_parameters (self->camera, params);
1520 }
1521 gst_ahc_parameters_free (params);
1522 }
1523 }
1524
1525 return ret;
1526 }
1527
1528 static gboolean
gst_ahc_src_set_zoom(GstPhotography * photo,gfloat zoom)1529 gst_ahc_src_set_zoom (GstPhotography * photo, gfloat zoom)
1530 {
1531 GstAHCSrc *self = GST_AHC_SRC (photo);
1532 gboolean ret = FALSE;
1533
1534 if (self->camera) {
1535 GstAHCParameters *params;
1536
1537 params = gst_ah_camera_get_parameters (self->camera);
1538 if (params) {
1539 GList *zoom_ratios = gst_ahc_parameters_get_zoom_ratios (params);
1540 gint max_zoom = gst_ahc_parameters_get_max_zoom (params);
1541 gint zoom_idx = -1;
1542
1543 if (zoom_ratios && g_list_length (zoom_ratios) == (max_zoom + 1)) {
1544 gint i;
1545 gint value = zoom * 100;
1546
1547 for (i = 0; i < max_zoom + 1; i++) {
1548 gint zoom_value = GPOINTER_TO_INT (g_list_nth_data (zoom_ratios, i));
1549
1550 if (value == zoom_value)
1551 zoom_idx = i;
1552 }
1553 }
1554
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);
1561 } else {
1562 gst_ahc_parameters_set_zoom (params, zoom_idx);
1563 ret = gst_ah_camera_set_parameters (self->camera, params);
1564 }
1565 }
1566
1567 gst_ahc_parameters_zoom_ratios_free (zoom_ratios);
1568 gst_ahc_parameters_free (params);
1569 }
1570 }
1571
1572 return ret;
1573 }
1574
1575 static gboolean
gst_ahc_src_set_flicker_mode(GstPhotography * photo,GstPhotographyFlickerReductionMode flicker_mode)1576 gst_ahc_src_set_flicker_mode (GstPhotography * photo,
1577 GstPhotographyFlickerReductionMode flicker_mode)
1578 {
1579 GstAHCSrc *self = GST_AHC_SRC (photo);
1580 gboolean ret = FALSE;
1581
1582 if (self->camera) {
1583 GstAHCParameters *params;
1584
1585 params = gst_ah_camera_get_parameters (self->camera);
1586 if (params) {
1587 const gchar *antibanding = NULL;
1588
1589 switch (flicker_mode) {
1590 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF:
1591 antibanding = Parameters_ANTIBANDING_OFF;
1592 break;
1593 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ:
1594 antibanding = Parameters_ANTIBANDING_50HZ;
1595 break;
1596 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ:
1597 antibanding = Parameters_ANTIBANDING_60HZ;
1598 break;
1599 case GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO:
1600 antibanding = Parameters_ANTIBANDING_AUTO;
1601 break;
1602 default:
1603 antibanding = NULL;
1604 break;
1605 }
1606
1607 if (antibanding) {
1608 gst_ahc_parameters_set_antibanding (params, antibanding);
1609 ret = gst_ah_camera_set_parameters (self->camera, params);
1610 }
1611 gst_ahc_parameters_free (params);
1612 }
1613 }
1614
1615 return ret;
1616 }
1617
1618 static gboolean
gst_ahc_src_set_focus_mode(GstPhotography * photo,GstPhotographyFocusMode focus_mode)1619 gst_ahc_src_set_focus_mode (GstPhotography * photo,
1620 GstPhotographyFocusMode focus_mode)
1621 {
1622 GstAHCSrc *self = GST_AHC_SRC (photo);
1623 gboolean ret = FALSE;
1624
1625 if (self->camera) {
1626 GstAHCParameters *params;
1627
1628 params = gst_ah_camera_get_parameters (self->camera);
1629 if (params) {
1630 const gchar *focus = NULL;
1631
1632 switch (focus_mode) {
1633 case GST_PHOTOGRAPHY_FOCUS_MODE_AUTO:
1634 focus = Parameters_FOCUS_MODE_AUTO;
1635 break;
1636 case GST_PHOTOGRAPHY_FOCUS_MODE_MACRO:
1637 focus = Parameters_FOCUS_MODE_MACRO;
1638 break;
1639 case GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY:
1640 focus = Parameters_FOCUS_MODE_INFINITY;
1641 break;
1642 case GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL:
1643 focus = Parameters_FOCUS_MODE_FIXED;
1644 break;
1645 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL:
1646 focus = Parameters_FOCUS_MODE_CONTINUOUS_PICTURE;
1647 break;
1648 case GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED:
1649 focus = Parameters_FOCUS_MODE_CONTINUOUS_VIDEO;
1650 break;
1651 case GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED:
1652 focus = Parameters_FOCUS_MODE_EDOF;
1653 break;
1654 case GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT:
1655 default:
1656 focus = NULL;
1657 break;
1658 }
1659
1660 if (focus) {
1661 gst_ahc_parameters_set_focus_mode (params, focus);
1662 ret = gst_ah_camera_set_parameters (self->camera, params);
1663 }
1664 gst_ahc_parameters_free (params);
1665 }
1666 }
1667
1668 return ret;
1669 }
1670
1671 static GstPhotographyCaps
gst_ahc_src_get_capabilities(GstPhotography * photo)1672 gst_ahc_src_get_capabilities (GstPhotography * photo)
1673 {
1674 GstAHCSrc *self = GST_AHC_SRC (photo);
1675
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;
1680
1681 if (self->camera) {
1682 GstAHCParameters *params;
1683
1684 params = gst_ah_camera_get_parameters (self->camera);
1685 if (!gst_ahc_parameters_is_zoom_supported (params))
1686 caps &= ~GST_PHOTOGRAPHY_CAPS_ZOOM;
1687
1688 gst_ahc_parameters_free (params);
1689 }
1690
1691 return caps;
1692 }
1693
1694 static void
gst_ahc_src_on_auto_focus(gboolean success,gpointer user_data)1695 gst_ahc_src_on_auto_focus (gboolean success, gpointer user_data)
1696 {
1697 GstAHCSrc *self = GST_AHC_SRC (user_data);
1698
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)));
1703 }
1704
1705 static void
gst_ahc_src_set_autofocus(GstPhotography * photo,gboolean on)1706 gst_ahc_src_set_autofocus (GstPhotography * photo, gboolean on)
1707 {
1708 GstAHCSrc *self = GST_AHC_SRC (photo);
1709
1710 if (self->camera) {
1711 if (on)
1712 gst_ah_camera_auto_focus (self->camera, gst_ahc_src_on_auto_focus, self);
1713 else
1714 gst_ah_camera_cancel_auto_focus (self->camera);
1715 }
1716
1717 }
1718
1719 static gint
_compare_formats(int f1,int f2)1720 _compare_formats (int f1, int f2)
1721 {
1722 if (f1 == f2)
1723 return 0;
1724 /* YV12 has priority */
1725 if (f1 == ImageFormat_YV12)
1726 return -1;
1727 if (f2 == ImageFormat_YV12)
1728 return 1;
1729 /* Then NV21 */
1730 if (f1 == ImageFormat_NV21)
1731 return -1;
1732 if (f2 == ImageFormat_NV21)
1733 return 1;
1734 /* Then we don't care */
1735 return f2 - f1;
1736 }
1737
1738 static gint
_compare_sizes(GstAHCSize * s1,GstAHCSize * s2)1739 _compare_sizes (GstAHCSize * s1, GstAHCSize * s2)
1740 {
1741 return ((s2->width * s2->height) - (s1->width * s1->height));
1742 }
1743
1744
1745 static gint
_compare_ranges(int * r1,int * r2)1746 _compare_ranges (int *r1, int *r2)
1747 {
1748 if (r1[1] == r2[1])
1749 /* Smallest range */
1750 return (r1[1] - r1[0]) - (r2[1] - r2[0]);
1751 else
1752 /* Highest fps */
1753 return r2[1] - r1[1];
1754 }
1755
1756 static GstCaps *
gst_ahc_src_getcaps(GstBaseSrc * src,GstCaps * filter)1757 gst_ahc_src_getcaps (GstBaseSrc * src, GstCaps * filter)
1758 {
1759 GstAHCSrc *self = GST_AHC_SRC (src);
1760
1761 if (self->camera) {
1762 GstCaps *ret = gst_caps_new_empty ();
1763 GstAHCParameters *params;
1764
1765 params = gst_ah_camera_get_parameters (self->camera);
1766 if (params) {
1767 GList *formats, *sizes, *ranges;
1768 GList *i, *j, *k;
1769 int previous_format = ImageFormat_UNKNOWN;
1770
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:");
1778
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;
1783
1784 /* Ignore duplicates */
1785 if (f == previous_format)
1786 continue;
1787
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");
1807 }
1808 previous_format = f;
1809
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);
1814 }
1815
1816 if (format) {
1817 for (j = sizes; j; j = j->next) {
1818 GstAHCSize *s = j->data;
1819 GstStructure *size;
1820
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);
1826
1827 for (k = ranges; k; k = k->next) {
1828 int *range = k->data;
1829 GstStructure *s;
1830
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);
1835 } else {
1836 gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE,
1837 range[0], 1000, range[1], 1000, NULL);
1838 }
1839 gst_caps_append_structure (ret, s);
1840 }
1841 gst_structure_free (size);
1842 }
1843 gst_structure_free (format);
1844 }
1845 }
1846 GST_DEBUG_OBJECT (self, "Supported preview sizes:");
1847 for (i = sizes; i; i = i->next) {
1848 GstAHCSize *s = i->data;
1849
1850 GST_DEBUG_OBJECT (self, " %dx%d", s->width, s->height);
1851 }
1852 GST_DEBUG_OBJECT (self, "Supported preview fps range:");
1853 for (i = ranges; i; i = i->next) {
1854 int *range = i->data;
1855
1856 GST_DEBUG_OBJECT (self, " [%d, %d]", range[0], range[1]);
1857 }
1858
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);
1863 }
1864
1865 return ret;
1866 } else {
1867 return NULL;
1868 }
1869 }
1870
1871 static GstCaps *
gst_ahc_src_fixate(GstBaseSrc * src,GstCaps * caps)1872 gst_ahc_src_fixate (GstBaseSrc * src, GstCaps * caps)
1873 {
1874 GstAHCSrc *self = GST_AHC_SRC (src);
1875 GstStructure *s = gst_caps_get_structure (caps, 0);
1876
1877 GST_DEBUG_OBJECT (self, "Fixating : %" GST_PTR_FORMAT, caps);
1878
1879 caps = gst_caps_make_writable (caps);
1880
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.
1885 */
1886 gst_structure_fixate_field_nearest_fraction (s, "framerate", G_MAXINT, 1);
1887
1888 caps = GST_BASE_SRC_CLASS (parent_class)->fixate (src, caps);
1889
1890 return caps;
1891 }
1892
1893 static gboolean
gst_ahc_src_setcaps(GstBaseSrc * src,GstCaps * caps)1894 gst_ahc_src_setcaps (GstBaseSrc * src, GstCaps * caps)
1895 {
1896 GstAHCSrc *self = GST_AHC_SRC (src);
1897 gboolean ret = FALSE;
1898 GstAHCParameters *params = NULL;
1899
1900 if (!self->camera) {
1901 GST_WARNING_OBJECT (self, "setcaps called without a camera available");
1902 goto end;
1903 }
1904
1905 params = gst_ah_camera_get_parameters (self->camera);
1906 if (params) {
1907 GstStructure *s;
1908 const gchar *format_str = NULL;
1909 GstVideoFormat format;
1910 gint fmt;
1911 gint width, height, fps_n, fps_d, buffer_size;
1912 GList *ranges, *l;
1913 gint range_size = G_MAXINT;
1914
1915 s = gst_caps_get_structure (caps, 0);
1916
1917 format_str = gst_structure_get_string (s, "format");
1918 format = gst_video_format_from_string (format_str);
1919
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);
1923
1924 fps_n *= 1000 / fps_d;
1925
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
1929 * of those ranges.
1930 * We chose the smallest range that contains the target
1931 * framerate.
1932 */
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;
1938
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];
1944 }
1945 }
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");
1949 goto end;
1950 }
1951
1952 switch (format) {
1953 case GST_VIDEO_FORMAT_YV12:
1954 fmt = ImageFormat_YV12;
1955 break;
1956 case GST_VIDEO_FORMAT_NV21:
1957 fmt = ImageFormat_NV21;
1958 break;
1959 case GST_VIDEO_FORMAT_YUY2:
1960 fmt = ImageFormat_YUY2;
1961 break;
1962 case GST_VIDEO_FORMAT_RGB16:
1963 fmt = ImageFormat_RGB_565;
1964 break;
1965 /* GST_VIDEO_FORMAT_NV16 doesn't exist */
1966 //case GST_VIDEO_FORMAT_NV16:
1967 //fmt = ImageFormat_NV16;
1968 //break;
1969 default:
1970 fmt = ImageFormat_UNKNOWN;
1971 break;
1972 }
1973
1974 if (fmt == ImageFormat_UNKNOWN) {
1975 GST_WARNING_OBJECT (self, "unsupported video format (%s)", format_str);
1976 goto end;
1977 }
1978
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,
1982 self->fps_max);
1983
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);
1986
1987 if (!gst_ah_camera_set_parameters (self->camera, params)) {
1988 GST_WARNING_OBJECT (self, "Unable to set video parameters");
1989 goto end;
1990 }
1991
1992 self->width = width;
1993 self->height = height;
1994 self->format = fmt;
1995 buffer_size = width * height *
1996 ((double) gst_ag_imageformat_get_bits_per_pixel (fmt) / 8);
1997
1998 if (buffer_size > self->buffer_size) {
1999 JNIEnv *env = gst_amc_jni_get_env ();
2000 gint i;
2001
2002 for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) {
2003 jbyteArray array = (*env)->NewByteArray (env, buffer_size);
2004
2005 if (array) {
2006 gst_ah_camera_add_callback_buffer (self->camera, array);
2007 (*env)->DeleteLocalRef (env, array);
2008 }
2009 }
2010 }
2011 self->buffer_size = buffer_size;
2012
2013 GST_DEBUG_OBJECT (self, "setting buffer w:%d h:%d buffer_size: %d",
2014 self->width, self->height, self->buffer_size);
2015
2016 ret = TRUE;
2017 }
2018
2019 end:
2020 if (params)
2021 gst_ahc_parameters_free (params);
2022
2023 if (ret && self->start) {
2024 GST_DEBUG_OBJECT (self, "Starting preview");
2025 ret = gst_ah_camera_start_preview (self->camera);
2026 if (ret) {
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,
2031 self);
2032 self->start = FALSE;
2033 }
2034 }
2035 return ret;
2036 }
2037
2038 typedef struct
2039 {
2040 GstAHCSrc *self;
2041 jbyteArray array;
2042 jbyte *data;
2043 } FreeFuncBuffer;
2044
2045 static void
gst_ahc_src_buffer_free_func(gpointer priv)2046 gst_ahc_src_buffer_free_func (gpointer priv)
2047 {
2048 FreeFuncBuffer *data = (FreeFuncBuffer *) priv;
2049 GstAHCSrc *self = data->self;
2050 JNIEnv *env = gst_amc_jni_get_env ();
2051
2052 g_mutex_lock (&self->mutex);
2053
2054 GST_DEBUG_OBJECT (self, "release %p->%p", data, data->array);
2055
2056 (*env)->ReleaseByteArrayElements (env, data->array, data->data, JNI_ABORT);
2057 if (self->camera)
2058 gst_ah_camera_add_callback_buffer (self->camera, data->array);
2059
2060 (*env)->DeleteGlobalRef (env, data->array);
2061
2062 g_slice_free (FreeFuncBuffer, data);
2063
2064 g_mutex_unlock (&self->mutex);
2065 gst_object_unref (self);
2066 }
2067
2068 static void
_data_queue_item_free(GstDataQueueItem * item)2069 _data_queue_item_free (GstDataQueueItem * item)
2070 {
2071 GST_DEBUG ("release %p", item->object);
2072
2073 gst_buffer_unref (GST_BUFFER (item->object));
2074 g_slice_free (GstDataQueueItem, item);
2075 }
2076
2077 static void
gst_ahc_src_on_preview_frame(jbyteArray array,gpointer user_data)2078 gst_ahc_src_on_preview_frame (jbyteArray array, gpointer user_data)
2079 {
2080 GstAHCSrc *self = GST_AHC_SRC (user_data);
2081 JNIEnv *env = gst_amc_jni_get_env ();
2082 GstBuffer *buffer;
2083 GstDataQueueItem *item = NULL;
2084 FreeFuncBuffer *malloc_data = NULL;
2085 GstClockTime timestamp = GST_CLOCK_TIME_NONE;
2086 GstClockTime duration = 0;
2087 GstClock *clock;
2088 gboolean queued = FALSE;
2089
2090 g_mutex_lock (&self->mutex);
2091
2092 if (array == NULL) {
2093 GST_DEBUG_OBJECT (self, "Size of array in queue is too small, dropping it");
2094 goto done;
2095 }
2096
2097 if ((clock = GST_ELEMENT_CLOCK (self))) {
2098 GstClockTime base_time = GST_ELEMENT_CAST (self)->base_time;
2099 GstClockTime current_ts;
2100
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;
2108 } else {
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");
2113 goto done;
2114 }
2115 } else {
2116 GST_DEBUG_OBJECT (self, "element clock hasn't created yet.");
2117 gst_ah_camera_add_callback_buffer (self->camera, array);
2118 goto done;
2119 }
2120
2121 GST_DEBUG_OBJECT (self, "Received data buffer %p", array);
2122
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);
2127
2128 buffer =
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;
2134
2135 GST_DEBUG_OBJECT (self, "creating wrapped buffer (size: %d)",
2136 self->buffer_size);
2137
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;
2144
2145 GST_DEBUG_OBJECT (self, "wrapping jni array %p->%p %p->%p", item,
2146 item->object, malloc_data, malloc_data->array);
2147
2148 queued = gst_data_queue_push (self->queue, item);
2149
2150 done:
2151 g_mutex_unlock (&self->mutex);
2152
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);
2157 }
2158 }
2159
2160 static void
gst_ahc_src_on_error(gint error,gpointer user_data)2161 gst_ahc_src_on_error (gint error, gpointer user_data)
2162 {
2163 GstAHCSrc *self = GST_AHC_SRC (user_data);
2164
2165 GST_WARNING_OBJECT (self, "Received error code : %d", error);
2166 }
2167
2168 static gboolean
gst_ahc_src_open(GstAHCSrc * self)2169 gst_ahc_src_open (GstAHCSrc * self)
2170 {
2171 GError *err = NULL;
2172
2173 GST_DEBUG_OBJECT (self, "Opening camera");
2174
2175 self->camera = gst_ah_camera_open (self->device);
2176
2177 if (self->camera) {
2178 GST_DEBUG_OBJECT (self, "Opened camera");
2179
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;
2186 }
2187 gst_ah_camera_set_preview_texture (self->camera, self->texture);
2188 self->buffer_size = 0;
2189 } else {
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));
2197 } else {
2198 GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
2199 ("There are no cameras available on this device."), (NULL));
2200 }
2201 }
2202
2203 return (self->camera != NULL);
2204
2205 failed_surfacetexutre:
2206 gst_ah_camera_release (self->camera);
2207 gst_ah_camera_free (self->camera);
2208 self->camera = NULL;
2209
2210 return FALSE;
2211 }
2212
2213 static void
gst_ahc_src_close(GstAHCSrc * self)2214 gst_ahc_src_close (GstAHCSrc * self)
2215 {
2216 GError *err = NULL;
2217
2218 if (self->camera) {
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);
2223 }
2224 self->camera = NULL;
2225
2226 if (self->texture
2227 && !gst_amc_surface_texture_release ((GstAmcSurfaceTexture *)
2228 self->texture, &err)) {
2229 GST_ERROR_OBJECT (self, "Failed to release surface texture object: %s",
2230 err->message);
2231 g_clear_error (&err);
2232 }
2233
2234 g_clear_object (&self->texture);
2235 }
2236
2237 static GstStateChangeReturn
gst_ahc_src_change_state(GstElement * element,GstStateChange transition)2238 gst_ahc_src_change_state (GstElement * element, GstStateChange transition)
2239 {
2240 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2241 GstAHCSrc *self = GST_AHC_SRC (element);
2242
2243 switch (transition) {
2244 case GST_STATE_CHANGE_NULL_TO_READY:
2245 if (!gst_ahc_src_open (self))
2246 return GST_STATE_CHANGE_FAILURE;
2247 break;
2248 default:
2249 break;
2250 }
2251
2252 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2253
2254 switch (transition) {
2255 case GST_STATE_CHANGE_READY_TO_NULL:
2256 gst_ahc_src_close (self);
2257 break;
2258 default:
2259 break;
2260 }
2261
2262 return ret;
2263 }
2264
2265 static gboolean
gst_ahc_src_start(GstBaseSrc * bsrc)2266 gst_ahc_src_start (GstBaseSrc * bsrc)
2267 {
2268 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2269
2270 GST_DEBUG_OBJECT (self, "Starting preview");
2271 if (self->camera) {
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;
2275 self->start = TRUE;
2276
2277 return TRUE;
2278 } else {
2279 return FALSE;
2280 }
2281 }
2282
2283 static gboolean
gst_ahc_src_stop(GstBaseSrc * bsrc)2284 gst_ahc_src_stop (GstBaseSrc * bsrc)
2285 {
2286 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2287
2288 GST_DEBUG_OBJECT (self, "Stopping preview");
2289 if (self->camera) {
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);
2294 }
2295 return TRUE;
2296 }
2297
2298 static gboolean
gst_ahc_src_unlock(GstBaseSrc * bsrc)2299 gst_ahc_src_unlock (GstBaseSrc * bsrc)
2300 {
2301 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2302
2303 GST_DEBUG_OBJECT (self, "Unlocking create");
2304 gst_data_queue_set_flushing (self->queue, TRUE);
2305
2306 return TRUE;
2307 }
2308
2309 static gboolean
gst_ahc_src_unlock_stop(GstBaseSrc * bsrc)2310 gst_ahc_src_unlock_stop (GstBaseSrc * bsrc)
2311 {
2312 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2313
2314 GST_DEBUG_OBJECT (self, "Stopping unlock");
2315 gst_data_queue_set_flushing (self->queue, FALSE);
2316
2317 return TRUE;
2318 }
2319
2320 static GstFlowReturn
gst_ahc_src_create(GstPushSrc * src,GstBuffer ** buffer)2321 gst_ahc_src_create (GstPushSrc * src, GstBuffer ** buffer)
2322 {
2323 GstAHCSrc *self = GST_AHC_SRC (src);
2324 GstDataQueueItem *item;
2325
2326 if (!gst_data_queue_pop (self->queue, &item)) {
2327 GST_INFO_OBJECT (self, "empty queue");
2328 return GST_FLOW_FLUSHING;
2329 }
2330
2331 GST_DEBUG_OBJECT (self, "creating buffer %p->%p", item, item->object);
2332
2333 *buffer = GST_BUFFER (item->object);
2334 g_slice_free (GstDataQueueItem, item);
2335
2336 return GST_FLOW_OK;
2337 }
2338
2339 static gboolean
gst_ahc_src_query(GstBaseSrc * bsrc,GstQuery * query)2340 gst_ahc_src_query (GstBaseSrc * bsrc, GstQuery * query)
2341 {
2342 GstAHCSrc *self = GST_AHC_SRC (bsrc);
2343
2344 switch (GST_QUERY_TYPE (query)) {
2345 case GST_QUERY_LATENCY:{
2346 GstClockTime min;
2347
2348 /* Cannot query latency before setcaps() */
2349 if (self->fps_min == 0)
2350 return FALSE;
2351
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);
2358
2359 return TRUE;
2360 break;
2361 }
2362 default:
2363 return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
2364 break;
2365 }
2366
2367 g_assert_not_reached ();
2368 }
2369