1/*
2Copyright (c) 2013, Broadcom Europe Ltd
3Copyright (c) 2013, James Hughes
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of the copyright holder nor the
14 names of its contributors may be used to endorse or promote products
15 derived from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
21DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <stdio.h>
30#include <memory.h>
31#include <ctype.h>
32
33#include "interface/vcos/vcos.h"
34
35#include "interface/vmcs_host/vc_vchi_gencmd.h"
36#include "interface/mmal/mmal.h"
37#include "interface/mmal/mmal_logging.h"
38#include "interface/mmal/util/mmal_util.h"
39#include "interface/mmal/util/mmal_util_params.h"
40#include "interface/mmal/util/mmal_default_components.h"
41#include "interface/mmal/util/mmal_connection.h"
42
43#include "RaspiCamControl.h"
44#include "RaspiCLI.h"
45#include "RaspiHelpers.h"
46
47/// Structure to cross reference exposure strings against the MMAL parameter equivalent
48static XREF_T exposure_map[] =
49{
50 {"off", MMAL_PARAM_EXPOSUREMODE_OFF},
51 {"auto", MMAL_PARAM_EXPOSUREMODE_AUTO},
52 {"night", MMAL_PARAM_EXPOSUREMODE_NIGHT},
53 {"nightpreview", MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW},
54 {"backlight", MMAL_PARAM_EXPOSUREMODE_BACKLIGHT},
55 {"spotlight", MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT},
56 {"sports", MMAL_PARAM_EXPOSUREMODE_SPORTS},
57 {"snow", MMAL_PARAM_EXPOSUREMODE_SNOW},
58 {"beach", MMAL_PARAM_EXPOSUREMODE_BEACH},
59 {"verylong", MMAL_PARAM_EXPOSUREMODE_VERYLONG},
60 {"fixedfps", MMAL_PARAM_EXPOSUREMODE_FIXEDFPS},
61 {"antishake", MMAL_PARAM_EXPOSUREMODE_ANTISHAKE},
62 {"fireworks", MMAL_PARAM_EXPOSUREMODE_FIREWORKS}
63};
64
65static const int exposure_map_size = sizeof(exposure_map) / sizeof(exposure_map[0]);
66
67/// Structure to cross reference flicker avoid strings against the MMAL parameter equivalent
68
69static XREF_T flicker_avoid_map[] =
70{
71 {"off", MMAL_PARAM_FLICKERAVOID_OFF},
72 {"auto", MMAL_PARAM_FLICKERAVOID_AUTO},
73 {"50hz", MMAL_PARAM_FLICKERAVOID_50HZ},
74 {"60hz", MMAL_PARAM_FLICKERAVOID_60HZ}
75};
76
77static const int flicker_avoid_map_size = sizeof(flicker_avoid_map) / sizeof(flicker_avoid_map[0]);
78
79/// Structure to cross reference awb strings against the MMAL parameter equivalent
80static XREF_T awb_map[] =
81{
82 {"off", MMAL_PARAM_AWBMODE_OFF},
83 {"auto", MMAL_PARAM_AWBMODE_AUTO},
84 {"sun", MMAL_PARAM_AWBMODE_SUNLIGHT},
85 {"cloud", MMAL_PARAM_AWBMODE_CLOUDY},
86 {"shade", MMAL_PARAM_AWBMODE_SHADE},
87 {"tungsten", MMAL_PARAM_AWBMODE_TUNGSTEN},
88 {"fluorescent", MMAL_PARAM_AWBMODE_FLUORESCENT},
89 {"incandescent", MMAL_PARAM_AWBMODE_INCANDESCENT},
90 {"flash", MMAL_PARAM_AWBMODE_FLASH},
91 {"horizon", MMAL_PARAM_AWBMODE_HORIZON},
92 {"greyworld", MMAL_PARAM_AWBMODE_GREYWORLD}
93};
94
95static const int awb_map_size = sizeof(awb_map) / sizeof(awb_map[0]);
96
97/// Structure to cross reference image effect against the MMAL parameter equivalent
98static XREF_T imagefx_map[] =
99{
100 {"none", MMAL_PARAM_IMAGEFX_NONE},
101 {"negative", MMAL_PARAM_IMAGEFX_NEGATIVE},
102 {"solarise", MMAL_PARAM_IMAGEFX_SOLARIZE},
103 {"sketch", MMAL_PARAM_IMAGEFX_SKETCH},
104 {"denoise", MMAL_PARAM_IMAGEFX_DENOISE},
105 {"emboss", MMAL_PARAM_IMAGEFX_EMBOSS},
106 {"oilpaint", MMAL_PARAM_IMAGEFX_OILPAINT},
107 {"hatch", MMAL_PARAM_IMAGEFX_HATCH},
108 {"gpen", MMAL_PARAM_IMAGEFX_GPEN},
109 {"pastel", MMAL_PARAM_IMAGEFX_PASTEL},
110 {"watercolour", MMAL_PARAM_IMAGEFX_WATERCOLOUR},
111 {"film", MMAL_PARAM_IMAGEFX_FILM},
112 {"blur", MMAL_PARAM_IMAGEFX_BLUR},
113 {"saturation", MMAL_PARAM_IMAGEFX_SATURATION},
114 {"colourswap", MMAL_PARAM_IMAGEFX_COLOURSWAP},
115 {"washedout", MMAL_PARAM_IMAGEFX_WASHEDOUT},
116 {"posterise", MMAL_PARAM_IMAGEFX_POSTERISE},
117 {"colourpoint", MMAL_PARAM_IMAGEFX_COLOURPOINT},
118 {"colourbalance", MMAL_PARAM_IMAGEFX_COLOURBALANCE},
119 {"cartoon", MMAL_PARAM_IMAGEFX_CARTOON}
120};
121
122static const int imagefx_map_size = sizeof(imagefx_map) / sizeof(imagefx_map[0]);
123
124static XREF_T metering_mode_map[] =
125{
126 {"average", MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE},
127 {"spot", MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT},
128 {"backlit", MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT},
129 {"matrix", MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX}
130};
131
132static const int metering_mode_map_size = sizeof(metering_mode_map)/sizeof(metering_mode_map[0]);
133
134static XREF_T drc_mode_map[] =
135{
136 {"off", MMAL_PARAMETER_DRC_STRENGTH_OFF},
137 {"low", MMAL_PARAMETER_DRC_STRENGTH_LOW},
138 {"med", MMAL_PARAMETER_DRC_STRENGTH_MEDIUM},
139 {"high", MMAL_PARAMETER_DRC_STRENGTH_HIGH}
140};
141
142static const int drc_mode_map_size = sizeof(drc_mode_map)/sizeof(drc_mode_map[0]);
143
144static XREF_T stereo_mode_map[] =
145{
146 {"off", MMAL_STEREOSCOPIC_MODE_NONE},
147 {"sbs", MMAL_STEREOSCOPIC_MODE_SIDE_BY_SIDE},
148 {"tb", MMAL_STEREOSCOPIC_MODE_TOP_BOTTOM},
149};
150
151static const int stereo_mode_map_size = sizeof(stereo_mode_map)/sizeof(stereo_mode_map[0]);
152
153enum
154{
155 CommandSharpness,
156 CommandContrast,
157 CommandBrightness,
158 CommandSaturation,
159 CommandISO,
160 CommandVideoStab,
161 CommandEVComp,
162 CommandExposure,
163 CommandAWB,
164 CommandImageFX,
165 CommandColourFX,
166 CommandMeterMode,
167 CommandRotation,
168 CommandHFlip,
169 CommandVFlip,
170 CommandROI,
171 CommandShutterSpeed,
172 CommandAwbGains,
173 CommandDRCLevel,
174 CommandStatsPass,
175 CommandAnnotate,
176 CommandStereoMode,
177 CommandStereoDecimate,
178 CommandStereoSwap,
179 CommandAnnotateExtras,
180 CommandFlicker,
181 CommandAnalogGain,
182 CommandDigitalGain,
183 CommandSettings
184};
185
186static COMMAND_LIST cmdline_commands[] =
187{
188 {CommandSharpness, "-sharpness", "sh", "Set image sharpness (-100 to 100)", 1},
189 {CommandContrast, "-contrast", "co", "Set image contrast (-100 to 100)", 1},
190 {CommandBrightness, "-brightness","br", "Set image brightness (0 to 100)", 1},
191 {CommandSaturation, "-saturation","sa", "Set image saturation (-100 to 100)", 1},
192 {CommandISO, "-ISO", "ISO","Set capture ISO", 1},
193 {CommandVideoStab, "-vstab", "vs", "Turn on video stabilisation", 0},
194 {CommandEVComp, "-ev", "ev", "Set EV compensation - steps of 1/6 stop", 1},
195 {CommandExposure, "-exposure", "ex", "Set exposure mode (see Notes)", 1},
196 {CommandFlicker, "-flicker", "fli","Set flicker avoid mode (see Notes)", 1},
197 {CommandAWB, "-awb", "awb","Set AWB mode (see Notes)", 1},
198 {CommandImageFX, "-imxfx", "ifx","Set image effect (see Notes)", 1},
199 {CommandColourFX, "-colfx", "cfx","Set colour effect (U:V)", 1},
200 {CommandMeterMode, "-metering", "mm", "Set metering mode (see Notes)", 1},
201 {CommandRotation, "-rotation", "rot","Set image rotation (0-359)", 1},
202 {CommandHFlip, "-hflip", "hf", "Set horizontal flip", 0},
203 {CommandVFlip, "-vflip", "vf", "Set vertical flip", 0},
204 {CommandROI, "-roi", "roi","Set region of interest (x,y,w,d as normalised coordinates [0.0-1.0])", 1},
205 {CommandShutterSpeed,"-shutter", "ss", "Set shutter speed in microseconds", 1},
206 {CommandAwbGains, "-awbgains", "awbg", "Set AWB gains - AWB mode must be off", 1},
207 {CommandDRCLevel, "-drc", "drc", "Set DRC Level (see Notes)", 1},
208 {CommandStatsPass, "-stats", "st", "Force recomputation of statistics on stills capture pass"},
209 {CommandAnnotate, "-annotate", "a", "Enable/Set annotate flags or text", 1},
210 {CommandStereoMode, "-stereo", "3d", "Select stereoscopic mode", 1},
211 {CommandStereoDecimate,"-decimate","dec", "Half width/height of stereo image"},
212 {CommandStereoSwap, "-3dswap", "3dswap", "Swap camera order for stereoscopic"},
213 {CommandAnnotateExtras,"-annotateex","ae", "Set extra annotation parameters (text size, text colour(hex YUV), bg colour(hex YUV), justify, x, y)", 2},
214 {CommandAnalogGain, "-analoggain", "ag", "Set the analog gain (floating point)", 1},
215 {CommandDigitalGain, "-digitalgain", "dg", "Set the digital gain (floating point)", 1},
216 {CommandSettings, "-settings", "set","Retrieve camera settings and write to stdout", 0},
217};
218
219static int cmdline_commands_size = sizeof(cmdline_commands) / sizeof(cmdline_commands[0]);
220
221
222#define parameter_reset -99999
223
224#define zoom_full_16P16 ((unsigned int)(65536 * 0.15))
225#define zoom_increment_16P16 (65536UL / 10)
226
227/**
228 * Update the passed in parameter according to the rest of the parameters
229 * passed in.
230 *
231 *
232 * @return 0 if reached end of cycle for this parameter, !0 otherwise
233 */
234static int update_cycle_parameter(int *option, int min, int max, int increment)
235{
236 vcos_assert(option);
237 if (!option)
238 return 0;
239
240 if (*option == parameter_reset)
241 *option = min - increment;
242
243 *option += increment;
244
245 if (*option > max)
246 {
247 *option = parameter_reset;
248 return 0;
249 }
250 else
251 return 1;
252}
253
254
255/**
256 * Test/Demo code to cycle through a bunch of camera settings
257 * This code is pretty hacky so please don't complain!!
258 * It only does stuff that should have a visual impact (hence demo!)
259 * This will override any user supplied parameters
260 *
261 * Each call of this function will move on to the next setting
262 *
263 * @param camera Pointer to the camera to change settings on.
264 * @return 0 if reached end of complete sequence, !0 otherwise
265 */
266
267int raspicamcontrol_cycle_test(MMAL_COMPONENT_T *camera)
268{
269 static int parameter = 0;
270 static int parameter_option = parameter_reset; // which value the parameter currently has
271
272 vcos_assert(camera);
273
274 // We are going to cycle through all the relevant entries in the parameter block
275 // and send options to the camera.
276 if (parameter == 0)
277 {
278 // sharpness
279 if (update_cycle_parameter(&parameter_option, -100, 100, 10))
280 raspicamcontrol_set_sharpness(camera, parameter_option);
281 else
282 {
283 raspicamcontrol_set_sharpness(camera, 0);
284 parameter++;
285 }
286 }
287 else if (parameter == 1)
288 {
289 // contrast
290 if (update_cycle_parameter(&parameter_option, -100, 100, 10))
291 raspicamcontrol_set_contrast(camera, parameter_option);
292 else
293 {
294 raspicamcontrol_set_contrast(camera, 0);
295 parameter++;
296 }
297 }
298 else if (parameter == 2)
299 {
300 // brightness
301 if (update_cycle_parameter(&parameter_option, 0, 100, 10))
302 raspicamcontrol_set_brightness(camera, parameter_option);
303 else
304 {
305 raspicamcontrol_set_brightness(camera, 50);
306 parameter++;
307 }
308 }
309 else if (parameter == 3)
310 {
311 // contrast
312 if (update_cycle_parameter(&parameter_option, -100, 100, 10))
313 raspicamcontrol_set_saturation(camera, parameter_option);
314 else
315 {
316 parameter++;
317 raspicamcontrol_set_saturation(camera, 0);
318 }
319 }
320 else if (parameter == 4)
321 {
322 // EV
323 if (update_cycle_parameter(&parameter_option, -10, 10, 4))
324 raspicamcontrol_set_exposure_compensation(camera, parameter_option);
325 else
326 {
327 raspicamcontrol_set_exposure_compensation(camera, 0);
328 parameter++;
329 }
330 }
331 else if (parameter == 5)
332 {
333 // MMAL_PARAM_EXPOSUREMODE_T
334 if (update_cycle_parameter(&parameter_option, 0, exposure_map_size, 1))
335 raspicamcontrol_set_exposure_mode(camera, exposure_map[parameter_option].mmal_mode);
336 else
337 {
338 raspicamcontrol_set_exposure_mode(camera, MMAL_PARAM_EXPOSUREMODE_AUTO);
339 parameter++;
340 }
341 }
342 else if (parameter == 6)
343 {
344 // MMAL_PARAM_AWB_T
345 if (update_cycle_parameter(&parameter_option, 0, awb_map_size, 1))
346 raspicamcontrol_set_awb_mode(camera, awb_map[parameter_option].mmal_mode);
347 else
348 {
349 raspicamcontrol_set_awb_mode(camera, MMAL_PARAM_AWBMODE_AUTO);
350 parameter++;
351 }
352 }
353 if (parameter == 7)
354 {
355 // MMAL_PARAM_IMAGEFX_T
356 if (update_cycle_parameter(&parameter_option, 0, imagefx_map_size, 1))
357 raspicamcontrol_set_imageFX(camera, imagefx_map[parameter_option].mmal_mode);
358 else
359 {
360 raspicamcontrol_set_imageFX(camera, MMAL_PARAM_IMAGEFX_NONE);
361 parameter++;
362 }
363 }
364 if (parameter == 8)
365 {
366 MMAL_PARAM_COLOURFX_T colfx = {0,0,0};
367 switch (parameter_option)
368 {
369 case parameter_reset :
370 parameter_option = 1;
371 colfx.u = 128;
372 colfx.v = 128;
373 break;
374 case 1 :
375 parameter_option = 2;
376 colfx.u = 100;
377 colfx.v = 200;
378 break;
379 case 2 :
380 parameter_option = parameter_reset;
381 colfx.enable = 0;
382 parameter++;
383 break;
384 }
385 raspicamcontrol_set_colourFX(camera, &colfx);
386 }
387
388 // Orientation
389 if (parameter == 9)
390 {
391 switch (parameter_option)
392 {
393 case parameter_reset:
394 raspicamcontrol_set_rotation(camera, 90);
395 parameter_option = 1;
396 break;
397
398 case 1 :
399 raspicamcontrol_set_rotation(camera, 180);
400 parameter_option = 2;
401 break;
402
403 case 2 :
404 raspicamcontrol_set_rotation(camera, 270);
405 parameter_option = 3;
406 break;
407
408 case 3 :
409 {
410 raspicamcontrol_set_rotation(camera, 0);
411 raspicamcontrol_set_flips(camera, 1,0);
412 parameter_option = 4;
413 break;
414 }
415 case 4 :
416 {
417 raspicamcontrol_set_flips(camera, 0,1);
418 parameter_option = 5;
419 break;
420 }
421 case 5 :
422 {
423 raspicamcontrol_set_flips(camera, 1, 1);
424 parameter_option = 6;
425 break;
426 }
427 case 6 :
428 {
429 raspicamcontrol_set_flips(camera, 0, 0);
430 parameter_option = parameter_reset;
431 parameter++;
432 break;
433 }
434 }
435 }
436
437 if (parameter == 10)
438 {
439 parameter = 1;
440 return 0;
441 }
442
443 return 1;
444}
445
446
447
448/**
449 * Convert string to the MMAL parameter for exposure mode
450 * @param str Incoming string to match
451 * @return MMAL parameter matching the string, or the AUTO option if no match found
452 */
453static MMAL_PARAM_EXPOSUREMODE_T exposure_mode_from_string(const char *str)
454{
455 int i = raspicli_map_xref(str, exposure_map, exposure_map_size);
456
457 if( i != -1)
458 return (MMAL_PARAM_EXPOSUREMODE_T)i;
459
460 vcos_log_error("Unknown exposure mode: %s", str);
461 return MMAL_PARAM_EXPOSUREMODE_AUTO;
462}
463
464/**
465 * Convert string to the MMAL parameter for flicker avoid mode
466 * @param str Incoming string to match
467 * @return MMAL parameter matching the string, or the AUTO option if no match found
468 */
469static MMAL_PARAM_FLICKERAVOID_T flicker_avoid_mode_from_string(const char *str)
470{
471 int i = raspicli_map_xref(str, flicker_avoid_map, flicker_avoid_map_size);
472
473 if( i != -1)
474 return (MMAL_PARAM_FLICKERAVOID_T)i;
475
476 vcos_log_error("Unknown flicker avoid mode: %s", str);
477 return MMAL_PARAM_FLICKERAVOID_OFF;
478}
479
480/**
481 * Convert string to the MMAL parameter for AWB mode
482 * @param str Incoming string to match
483 * @return MMAL parameter matching the string, or the AUTO option if no match found
484 */
485static MMAL_PARAM_AWBMODE_T awb_mode_from_string(const char *str)
486{
487 int i = raspicli_map_xref(str, awb_map, awb_map_size);
488
489 if( i != -1)
490 return (MMAL_PARAM_AWBMODE_T)i;
491
492 vcos_log_error("Unknown awb mode: %s", str);
493 return MMAL_PARAM_AWBMODE_AUTO;
494}
495
496/**
497 * Convert string to the MMAL parameter for image effects mode
498 * @param str Incoming string to match
499 * @return MMAL parameter matching the strong, or the AUTO option if no match found
500 */
501MMAL_PARAM_IMAGEFX_T imagefx_mode_from_string(const char *str)
502{
503 int i = raspicli_map_xref(str, imagefx_map, imagefx_map_size);
504
505 if( i != -1)
506 return (MMAL_PARAM_IMAGEFX_T)i;
507
508 vcos_log_error("Unknown image fx: %s", str);
509 return MMAL_PARAM_IMAGEFX_NONE;
510}
511
512/**
513 * Convert string to the MMAL parameter for exposure metering mode
514 * @param str Incoming string to match
515 * @return MMAL parameter matching the string, or the AUTO option if no match found
516 */
517static MMAL_PARAM_EXPOSUREMETERINGMODE_T metering_mode_from_string(const char *str)
518{
519 int i = raspicli_map_xref(str, metering_mode_map, metering_mode_map_size);
520
521 if( i != -1)
522 return (MMAL_PARAM_EXPOSUREMETERINGMODE_T)i;
523
524 vcos_log_error("Unknown metering mode: %s", str);
525 return MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
526}
527
528/**
529 * Convert string to the MMAL parameter for DRC level
530 * @param str Incoming string to match
531 * @return MMAL parameter matching the string, or the AUTO option if no match found
532 */
533static MMAL_PARAMETER_DRC_STRENGTH_T drc_mode_from_string(const char *str)
534{
535 int i = raspicli_map_xref(str, drc_mode_map, drc_mode_map_size);
536
537 if( i != -1)
538 return (MMAL_PARAMETER_DRC_STRENGTH_T)i;
539
540 vcos_log_error("Unknown DRC level: %s", str);
541 return MMAL_PARAMETER_DRC_STRENGTH_OFF;
542}
543
544/**
545 * Convert string to the MMAL parameter for exposure metering mode
546 * @param str Incoming string to match
547 * @return MMAL parameter matching the string, or the AUTO option if no match found
548 */
549static MMAL_STEREOSCOPIC_MODE_T stereo_mode_from_string(const char *str)
550{
551 int i = raspicli_map_xref(str, stereo_mode_map, stereo_mode_map_size);
552
553 if( i != -1)
554 return (MMAL_STEREOSCOPIC_MODE_T)i;
555
556 vcos_log_error("Unknown metering mode: %s", str);
557 return MMAL_STEREOSCOPIC_MODE_NONE;
558}
559
560/**
561 * Parse a possible command pair - command and parameter
562 * @param arg1 Command
563 * @param arg2 Parameter (could be NULL)
564 * @return How many parameters were used, 0,1,2
565 */
566int raspicamcontrol_parse_cmdline(RASPICAM_CAMERA_PARAMETERS *params, const char *arg1, const char *arg2)
567{
568 int command_id, used = 0, num_parameters;
569
570 if (!arg1)
571 return 0;
572
573 command_id = raspicli_get_command_id(cmdline_commands, cmdline_commands_size, arg1, &num_parameters);
574
575 // If invalid command, or we are missing a parameter, drop out
576 if (command_id==-1 || (command_id != -1 && num_parameters > 0 && arg2 == NULL))
577 return 0;
578
579 switch (command_id)
580 {
581 case CommandSharpness : // sharpness - needs single number parameter
582 sscanf(arg2, "%d", &params->sharpness);
583 used = 2;
584 break;
585
586 case CommandContrast : // contrast - needs single number parameter
587 sscanf(arg2, "%d", &params->contrast);
588 used = 2;
589 break;
590
591 case CommandBrightness : // brightness - needs single number parameter
592 sscanf(arg2, "%d", &params->brightness);
593 used = 2;
594 break;
595
596 case CommandSaturation : // saturation - needs single number parameter
597 sscanf(arg2, "%d", &params->saturation);
598 used = 2;
599 break;
600
601 case CommandISO : // ISO - needs single number parameter
602 sscanf(arg2, "%d", &params->ISO);
603 used = 2;
604 break;
605
606 case CommandVideoStab : // video stabilisation - if here, its on
607 params->videoStabilisation = 1;
608 used = 1;
609 break;
610
611 case CommandEVComp : // EV - needs single number parameter
612 sscanf(arg2, "%d", &params->exposureCompensation);
613 used = 2;
614 break;
615
616 case CommandExposure : // exposure mode - needs string
617 params->exposureMode = exposure_mode_from_string(arg2);
618 used = 2;
619 break;
620
621 case CommandFlicker : // flicker avoid mode - needs string
622 params->flickerAvoidMode = flicker_avoid_mode_from_string(arg2);
623 used = 2;
624 break;
625
626 case CommandAWB : // AWB mode - needs single number parameter
627 params->awbMode = awb_mode_from_string(arg2);
628 used = 2;
629 break;
630
631 case CommandImageFX : // Image FX - needs string
632 params->imageEffect = imagefx_mode_from_string(arg2);
633 used = 2;
634 break;
635
636 case CommandColourFX : // Colour FX - needs string "u:v"
637 sscanf(arg2, "%d:%d", &params->colourEffects.u, &params->colourEffects.v);
638 params->colourEffects.enable = 1;
639 used = 2;
640 break;
641
642 case CommandMeterMode:
643 params->exposureMeterMode = metering_mode_from_string(arg2);
644 used = 2;
645 break;
646
647 case CommandRotation : // Rotation - degree
648 sscanf(arg2, "%d", &params->rotation);
649 used = 2;
650 break;
651
652 case CommandHFlip :
653 params->hflip = 1;
654 used = 1;
655 break;
656
657 case CommandVFlip :
658 params->vflip = 1;
659 used = 1;
660 break;
661
662 case CommandROI :
663 {
664 double x,y,w,h;
665 int args;
666
667 args = sscanf(arg2, "%lf,%lf,%lf,%lf", &x,&y,&w,&h);
668
669 if (args != 4 || x > 1.0 || y > 1.0 || w > 1.0 || h > 1.0)
670 {
671 return 0;
672 }
673
674 // Make sure we stay within bounds
675 if (x + w > 1.0)
676 w = 1 - x;
677
678 if (y + h > 1.0)
679 h = 1 - y;
680
681 params->roi.x = x;
682 params->roi.y = y;
683 params->roi.w = w;
684 params->roi.h = h;
685
686 used = 2;
687 break;
688 }
689
690 case CommandShutterSpeed : // Shutter speed needs single number parameter
691 {
692 sscanf(arg2, "%d", &params->shutter_speed);
693 used = 2;
694 break;
695 }
696
697 case CommandAwbGains :
698 {
699 double r,b;
700 int args;
701
702 args = sscanf(arg2, "%lf,%lf", &r,&b);
703
704 if (args != 2 || r > 8.0 || b > 8.0)
705 {
706 return 0;
707 }
708
709 params->awb_gains_r = r;
710 params->awb_gains_b = b;
711
712 used = 2;
713 break;
714 }
715
716 case CommandDRCLevel:
717 {
718 params->drc_level = drc_mode_from_string(arg2);
719 used = 2;
720 break;
721 }
722
723 case CommandStatsPass:
724 {
725 params->stats_pass = MMAL_TRUE;
726 used = 1;
727 break;
728 }
729
730 case CommandAnnotate:
731 {
732 char dummy;
733 unsigned int bitmask;
734 // If parameter is a number, assume its a bitmask, otherwise a string
735 if (sscanf(arg2, "%u%c", &bitmask, &dummy) == 1)
736 {
737 params->enable_annotate |= bitmask;
738 }
739 else
740 {
741 params->enable_annotate |= ANNOTATE_USER_TEXT;
742 //copy string char by char and replace "\n" with newline character
743 unsigned char c;
744 char const *s = arg2;
745 char *t = &params->annotate_string[0];
746 int n=0;
747 while ((c = *s++) && n < MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3-1)
748 {
749 if (c == '\\' && *s)
750 {
751 switch (c = *s++)
752 {
753 case 'n':
754 c = '\n';
755 break;
756
757 default:
758 c = '\\';
759 s--;
760 break;
761 }
762 }
763 *(t++) = c;
764 n++;
765 }
766 *t='\0';
767
768 //params->annotate_string[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3-1] = '\0';
769 }
770 used=2;
771 break;
772 }
773
774 case CommandAnnotateExtras:
775 {
776 // 3 parameters - text size (6-80), text colour (Hex VVUUYY) and background colour (Hex VVUUYY)
777 sscanf(arg2, "%u,%X,%X,%u,%u,%u", &params->annotate_text_size,
778 &params->annotate_text_colour,
779 &params->annotate_bg_colour,
780 &params->annotate_justify,
781 &params->annotate_x,
782 &params->annotate_y
783 );
784 used=2;
785 break;
786 }
787
788 case CommandStereoMode:
789 {
790 params->stereo_mode.mode = stereo_mode_from_string(arg2);
791 used = 2;
792 break;
793 }
794
795 case CommandStereoDecimate:
796 {
797 params->stereo_mode.decimate = MMAL_TRUE;
798 used = 1;
799 break;
800 }
801
802 case CommandStereoSwap:
803 {
804 params->stereo_mode.swap_eyes = MMAL_TRUE;
805 used = 1;
806 break;
807 }
808
809 case CommandAnalogGain:
810 {
811 double gain;
812 int args;
813
814 args = sscanf(arg2, "%lf", &gain);
815
816 if (args != 1 || gain > 16.0)
817 {
818 return 0;
819 }
820
821 params->analog_gain = gain;
822
823 used = 2;
824 break;
825 }
826 case CommandDigitalGain:
827 {
828 double gain;
829 int args;
830
831 args = sscanf(arg2, "%lf", &gain);
832
833 if (args != 1 || gain > 64.0)
834 {
835 return 0;
836 }
837
838 params->digital_gain = gain;
839
840 used = 2;
841 break;
842 }
843
844 case CommandSettings:
845 {
846 params->settings = 1;
847 used = 1;
848 break;
849 }
850
851 }
852
853 return used;
854}
855
856/**
857 * Display help for command line options
858 */
859void raspicamcontrol_display_help()
860{
861 int i;
862
863 fprintf(stdout, "\nImage parameter commands\n\n");
864
865 raspicli_display_help(cmdline_commands, cmdline_commands_size);
866
867 fprintf(stdout, "\n\nNotes\n\nExposure mode options :\n%s", exposure_map[0].mode );
868
869 for (i=1; i<exposure_map_size; i++)
870 {
871 fprintf(stdout, ",%s", exposure_map[i].mode);
872 }
873
874 fprintf(stdout, "\n\nFlicker avoid mode options :\n%s", flicker_avoid_map[0].mode );
875
876 for (i=1; i<flicker_avoid_map_size; i++)
877 {
878 fprintf(stdout, ",%s", flicker_avoid_map[i].mode);
879 }
880
881 fprintf(stdout, "\n\nAWB mode options :\n%s", awb_map[0].mode );
882
883 for (i=1; i<awb_map_size; i++)
884 {
885 fprintf(stdout, ",%s", awb_map[i].mode);
886 }
887
888 fprintf(stdout, "\n\nImage Effect mode options :\n%s", imagefx_map[0].mode );
889
890 for (i=1; i<imagefx_map_size; i++)
891 {
892 fprintf(stdout, ",%s", imagefx_map[i].mode);
893 }
894
895 fprintf(stdout, "\n\nMetering Mode options :\n%s", metering_mode_map[0].mode );
896
897 for (i=1; i<metering_mode_map_size; i++)
898 {
899 fprintf(stdout, ",%s", metering_mode_map[i].mode);
900 }
901
902 fprintf(stdout, "\n\nDynamic Range Compression (DRC) options :\n%s", drc_mode_map[0].mode );
903
904 for (i=1; i<drc_mode_map_size; i++)
905 {
906 fprintf(stdout, ",%s", drc_mode_map[i].mode);
907 }
908
909 fprintf(stdout, "\n");
910}
911
912
913/**
914 * Dump contents of camera parameter structure to stderr for debugging/verbose logging
915 *
916 * @param params Const pointer to parameters structure to dump
917 */
918void raspicamcontrol_dump_parameters(const RASPICAM_CAMERA_PARAMETERS *params)
919{
920 const char *exp_mode = raspicli_unmap_xref(params->exposureMode, exposure_map, exposure_map_size);
921 const char *fl_mode = raspicli_unmap_xref(params->flickerAvoidMode, flicker_avoid_map, flicker_avoid_map_size);
922 const char *awb_mode = raspicli_unmap_xref(params->awbMode, awb_map, awb_map_size);
923 const char *image_effect = raspicli_unmap_xref(params->imageEffect, imagefx_map, imagefx_map_size);
924 const char *metering_mode = raspicli_unmap_xref(params->exposureMeterMode, metering_mode_map, metering_mode_map_size);
925
926 fprintf(stderr, "Sharpness %d, Contrast %d, Brightness %d\n", params->sharpness, params->contrast, params->brightness);
927 fprintf(stderr, "Saturation %d, ISO %d, Video Stabilisation %s, Exposure compensation %d\n", params->saturation, params->ISO, params->videoStabilisation ? "Yes": "No", params->exposureCompensation);
928 fprintf(stderr, "Exposure Mode '%s', AWB Mode '%s', Image Effect '%s'\n", exp_mode, awb_mode, image_effect);
929 fprintf(stderr, "Flicker Avoid Mode '%s'\n", fl_mode);
930 fprintf(stderr, "Metering Mode '%s', Colour Effect Enabled %s with U = %d, V = %d\n", metering_mode, params->colourEffects.enable ? "Yes":"No", params->colourEffects.u, params->colourEffects.v);
931 fprintf(stderr, "Rotation %d, hflip %s, vflip %s\n", params->rotation, params->hflip ? "Yes":"No",params->vflip ? "Yes":"No");
932 fprintf(stderr, "ROI x %lf, y %f, w %f h %f\n", params->roi.x, params->roi.y, params->roi.w, params->roi.h);
933}
934
935
936
937/**
938 * Give the supplied parameter block a set of default values
939 * @params Pointer to parameter block
940 */
941void raspicamcontrol_set_defaults(RASPICAM_CAMERA_PARAMETERS *params)
942{
943 vcos_assert(params);
944
945 params->sharpness = 0;
946 params->contrast = 0;
947 params->brightness = 50;
948 params->saturation = 0;
949 params->ISO = 0; // 0 = auto
950 params->videoStabilisation = 0;
951 params->exposureCompensation = 0;
952 params->exposureMode = MMAL_PARAM_EXPOSUREMODE_AUTO;
953 params->flickerAvoidMode = MMAL_PARAM_FLICKERAVOID_OFF;
954 params->exposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
955 params->awbMode = MMAL_PARAM_AWBMODE_AUTO;
956 params->imageEffect = MMAL_PARAM_IMAGEFX_NONE;
957 params->colourEffects.enable = 0;
958 params->colourEffects.u = 128;
959 params->colourEffects.v = 128;
960 params->rotation = 0;
961 params->hflip = params->vflip = 0;
962 params->roi.x = params->roi.y = 0.0;
963 params->roi.w = params->roi.h = 1.0;
964 params->shutter_speed = 0; // 0 = auto
965 params->awb_gains_r = 0; // Only have any function if AWB OFF is used.
966 params->awb_gains_b = 0;
967 params->drc_level = MMAL_PARAMETER_DRC_STRENGTH_OFF;
968 params->stats_pass = MMAL_FALSE;
969 params->enable_annotate = 0;
970 params->annotate_string[0] = '\0';
971 params->annotate_text_size = 0; //Use firmware default
972 params->annotate_text_colour = -1; //Use firmware default
973 params->annotate_bg_colour = -1; //Use firmware default
974 params->stereo_mode.mode = MMAL_STEREOSCOPIC_MODE_NONE;
975 params->stereo_mode.decimate = MMAL_FALSE;
976 params->stereo_mode.swap_eyes = MMAL_FALSE;
977}
978
979/**
980 * Get all the current camera parameters from specified camera component
981 * @param camera Pointer to camera component
982 * @param params Pointer to parameter block to accept settings
983 * @return 0 if successful, non-zero if unsuccessful
984 */
985int raspicamcontrol_get_all_parameters(MMAL_COMPONENT_T *camera, RASPICAM_CAMERA_PARAMETERS *params)
986{
987 vcos_assert(camera);
988 vcos_assert(params);
989
990 if (!camera || !params)
991 return 1;
992
993 /* TODO : Write these get functions
994 params->sharpness = raspicamcontrol_get_sharpness(camera);
995 params->contrast = raspicamcontrol_get_contrast(camera);
996 params->brightness = raspicamcontrol_get_brightness(camera);
997 params->saturation = raspicamcontrol_get_saturation(camera);
998 params->ISO = raspicamcontrol_get_ISO(camera);
999 params->videoStabilisation = raspicamcontrol_get_video_stabilisation(camera);
1000 params->exposureCompensation = raspicamcontrol_get_exposure_compensation(camera);
1001 params->exposureMode = raspicamcontrol_get_exposure_mode(camera);
1002 params->flickerAvoidMode = raspicamcontrol_get_flicker_avoid_mode(camera);
1003 params->awbMode = raspicamcontrol_get_awb_mode(camera);
1004 params->imageEffect = raspicamcontrol_get_image_effect(camera);
1005 params->colourEffects = raspicamcontrol_get_colour_effect(camera);
1006 params->thumbnailConfig = raspicamcontrol_get_thumbnail_config(camera);
1007 */
1008 return 0;
1009}
1010
1011/**
1012 * Set the specified camera to all the specified settings
1013 * @param camera Pointer to camera component
1014 * @param params Pointer to parameter block containing parameters
1015 * @return 0 if successful, none-zero if unsuccessful.
1016 */
1017int raspicamcontrol_set_all_parameters(MMAL_COMPONENT_T *camera, const RASPICAM_CAMERA_PARAMETERS *params)
1018{
1019 int result;
1020
1021 result = raspicamcontrol_set_saturation(camera, params->saturation);
1022 result += raspicamcontrol_set_sharpness(camera, params->sharpness);
1023 result += raspicamcontrol_set_contrast(camera, params->contrast);
1024 result += raspicamcontrol_set_brightness(camera, params->brightness);
1025 result += raspicamcontrol_set_ISO(camera, params->ISO);
1026 result += raspicamcontrol_set_video_stabilisation(camera, params->videoStabilisation);
1027 result += raspicamcontrol_set_exposure_compensation(camera, params->exposureCompensation);
1028 result += raspicamcontrol_set_exposure_mode(camera, params->exposureMode);
1029 result += raspicamcontrol_set_flicker_avoid_mode(camera, params->flickerAvoidMode);
1030 result += raspicamcontrol_set_metering_mode(camera, params->exposureMeterMode);
1031 result += raspicamcontrol_set_awb_mode(camera, params->awbMode);
1032 result += raspicamcontrol_set_awb_gains(camera, params->awb_gains_r, params->awb_gains_b);
1033 result += raspicamcontrol_set_imageFX(camera, params->imageEffect);
1034 result += raspicamcontrol_set_colourFX(camera, &params->colourEffects);
1035 //result += raspicamcontrol_set_thumbnail_parameters(camera, &params->thumbnailConfig); TODO Not working for some reason
1036 result += raspicamcontrol_set_rotation(camera, params->rotation);
1037 result += raspicamcontrol_set_flips(camera, params->hflip, params->vflip);
1038 result += raspicamcontrol_set_ROI(camera, params->roi);
1039 result += raspicamcontrol_set_shutter_speed(camera, params->shutter_speed);
1040 result += raspicamcontrol_set_DRC(camera, params->drc_level);
1041 result += raspicamcontrol_set_stats_pass(camera, params->stats_pass);
1042 result += raspicamcontrol_set_annotate(camera, params->enable_annotate, params->annotate_string,
1043 params->annotate_text_size,
1044 params->annotate_text_colour,
1045 params->annotate_bg_colour,
1046 params->annotate_justify,
1047 params->annotate_x,
1048 params->annotate_y);
1049 result += raspicamcontrol_set_gains(camera, params->analog_gain, params->digital_gain);
1050
1051 if (params->settings)
1052 {
1053 MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T change_event_request =
1054 {
1055 {MMAL_PARAMETER_CHANGE_EVENT_REQUEST, sizeof(MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T)},
1056 MMAL_PARAMETER_CAMERA_SETTINGS, 1
1057 };
1058
1059 MMAL_STATUS_T status = mmal_port_parameter_set(camera->control, &change_event_request.hdr);
1060 if ( status != MMAL_SUCCESS )
1061 {
1062 vcos_log_error("No camera settings events");
1063 }
1064
1065 result += status;
1066 }
1067
1068 return result;
1069}
1070
1071/**
1072 * Adjust the saturation level for images
1073 * @param camera Pointer to camera component
1074 * @param saturation Value to adjust, -100 to 100
1075 * @return 0 if successful, non-zero if any parameters out of range
1076 */
1077int raspicamcontrol_set_saturation(MMAL_COMPONENT_T *camera, int saturation)
1078{
1079 int ret = 0;
1080
1081 if (!camera)
1082 return 1;
1083
1084 if (saturation >= -100 && saturation <= 100)
1085 {
1086 MMAL_RATIONAL_T value = {saturation, 100};
1087 ret = mmal_status_to_int(mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SATURATION, value));
1088 }
1089 else
1090 {
1091 vcos_log_error("Invalid saturation value");
1092 ret = 1;
1093 }
1094
1095 return ret;
1096}
1097
1098/**
1099 * Set the sharpness of the image
1100 * @param camera Pointer to camera component
1101 * @param sharpness Sharpness adjustment -100 to 100
1102 */
1103int raspicamcontrol_set_sharpness(MMAL_COMPONENT_T *camera, int sharpness)
1104{
1105 int ret = 0;
1106
1107 if (!camera)
1108 return 1;
1109
1110 if (sharpness >= -100 && sharpness <= 100)
1111 {
1112 MMAL_RATIONAL_T value = {sharpness, 100};
1113 ret = mmal_status_to_int(mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SHARPNESS, value));
1114 }
1115 else
1116 {
1117 vcos_log_error("Invalid sharpness value");
1118 ret = 1;
1119 }
1120
1121 return ret;
1122}
1123
1124/**
1125 * Set the contrast adjustment for the image
1126 * @param camera Pointer to camera component
1127 * @param contrast Contrast adjustment -100 to 100
1128 * @return
1129 */
1130int raspicamcontrol_set_contrast(MMAL_COMPONENT_T *camera, int contrast)
1131{
1132 int ret = 0;
1133
1134 if (!camera)
1135 return 1;
1136
1137 if (contrast >= -100 && contrast <= 100)
1138 {
1139 MMAL_RATIONAL_T value = {contrast, 100};
1140 ret = mmal_status_to_int(mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_CONTRAST, value));
1141 }
1142 else
1143 {
1144 vcos_log_error("Invalid contrast value");
1145 ret = 1;
1146 }
1147
1148 return ret;
1149}
1150
1151/**
1152 * Adjust the brightness level for images
1153 * @param camera Pointer to camera component
1154 * @param brightness Value to adjust, 0 to 100
1155 * @return 0 if successful, non-zero if any parameters out of range
1156 */
1157int raspicamcontrol_set_brightness(MMAL_COMPONENT_T *camera, int brightness)
1158{
1159 int ret = 0;
1160
1161 if (!camera)
1162 return 1;
1163
1164 if (brightness >= 0 && brightness <= 100)
1165 {
1166 MMAL_RATIONAL_T value = {brightness, 100};
1167 ret = mmal_status_to_int(mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_BRIGHTNESS, value));
1168 }
1169 else
1170 {
1171 vcos_log_error("Invalid brightness value");
1172 ret = 1;
1173 }
1174
1175 return ret;
1176}
1177
1178/**
1179 * Adjust the ISO used for images
1180 * @param camera Pointer to camera component
1181 * @param ISO Value to set TODO :
1182 * @return 0 if successful, non-zero if any parameters out of range
1183 */
1184int raspicamcontrol_set_ISO(MMAL_COMPONENT_T *camera, int ISO)
1185{
1186 if (!camera)
1187 return 1;
1188
1189 return mmal_status_to_int(mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_ISO, ISO));
1190}
1191
1192/**
1193 * Adjust the metering mode for images
1194 * @param camera Pointer to camera component
1195 * @param saturation Value from following
1196 * - MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
1197 * - MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
1198 * - MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
1199 * - MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX
1200 * @return 0 if successful, non-zero if any parameters out of range
1201 */
1202int raspicamcontrol_set_metering_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_EXPOSUREMETERINGMODE_T m_mode )
1203{
1204 MMAL_PARAMETER_EXPOSUREMETERINGMODE_T meter_mode = {{MMAL_PARAMETER_EXP_METERING_MODE,sizeof(meter_mode)},
1205 m_mode
1206 };
1207 if (!camera)
1208 return 1;
1209
1210 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &meter_mode.hdr));
1211}
1212
1213
1214/**
1215 * Set the video stabilisation flag. Only used in video mode
1216 * @param camera Pointer to camera component
1217 * @param saturation Flag 0 off 1 on
1218 * @return 0 if successful, non-zero if any parameters out of range
1219 */
1220int raspicamcontrol_set_video_stabilisation(MMAL_COMPONENT_T *camera, int vstabilisation)
1221{
1222 if (!camera)
1223 return 1;
1224
1225 return mmal_status_to_int(mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_VIDEO_STABILISATION, vstabilisation));
1226}
1227
1228/**
1229 * Adjust the exposure compensation for images (EV)
1230 * @param camera Pointer to camera component
1231 * @param exp_comp Value to adjust, -10 to +10
1232 * @return 0 if successful, non-zero if any parameters out of range
1233 */
1234int raspicamcontrol_set_exposure_compensation(MMAL_COMPONENT_T *camera, int exp_comp)
1235{
1236 if (!camera)
1237 return 1;
1238
1239 return mmal_status_to_int(mmal_port_parameter_set_int32(camera->control, MMAL_PARAMETER_EXPOSURE_COMP, exp_comp));
1240}
1241
1242
1243/**
1244 * Set exposure mode for images
1245 * @param camera Pointer to camera component
1246 * @param mode Exposure mode to set from
1247 * - MMAL_PARAM_EXPOSUREMODE_OFF,
1248 * - MMAL_PARAM_EXPOSUREMODE_AUTO,
1249 * - MMAL_PARAM_EXPOSUREMODE_NIGHT,
1250 * - MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
1251 * - MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
1252 * - MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
1253 * - MMAL_PARAM_EXPOSUREMODE_SPORTS,
1254 * - MMAL_PARAM_EXPOSUREMODE_SNOW,
1255 * - MMAL_PARAM_EXPOSUREMODE_BEACH,
1256 * - MMAL_PARAM_EXPOSUREMODE_VERYLONG,
1257 * - MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
1258 * - MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
1259 * - MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
1260 *
1261 * @return 0 if successful, non-zero if any parameters out of range
1262 */
1263int raspicamcontrol_set_exposure_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_EXPOSUREMODE_T mode)
1264{
1265 MMAL_PARAMETER_EXPOSUREMODE_T exp_mode = {{MMAL_PARAMETER_EXPOSURE_MODE,sizeof(exp_mode)}, mode};
1266
1267 if (!camera)
1268 return 1;
1269
1270 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &exp_mode.hdr));
1271}
1272
1273
1274/**
1275 * Set flicker avoid mode for images
1276 * @param camera Pointer to camera component
1277 * @param mode Exposure mode to set from
1278 * - MMAL_PARAM_FLICKERAVOID_OFF,
1279 * - MMAL_PARAM_FLICKERAVOID_AUTO,
1280 * - MMAL_PARAM_FLICKERAVOID_50HZ,
1281 * - MMAL_PARAM_FLICKERAVOID_60HZ,
1282 *
1283 * @return 0 if successful, non-zero if any parameters out of range
1284 */
1285int raspicamcontrol_set_flicker_avoid_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_FLICKERAVOID_T mode)
1286{
1287 MMAL_PARAMETER_FLICKERAVOID_T fl_mode = {{MMAL_PARAMETER_FLICKER_AVOID,sizeof(fl_mode)}, mode};
1288
1289 if (!camera)
1290 return 1;
1291
1292 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &fl_mode.hdr));
1293}
1294
1295
1296/**
1297 * Set the aWB (auto white balance) mode for images
1298 * @param camera Pointer to camera component
1299 * @param awb_mode Value to set from
1300 * - MMAL_PARAM_AWBMODE_OFF,
1301 * - MMAL_PARAM_AWBMODE_AUTO,
1302 * - MMAL_PARAM_AWBMODE_SUNLIGHT,
1303 * - MMAL_PARAM_AWBMODE_CLOUDY,
1304 * - MMAL_PARAM_AWBMODE_SHADE,
1305 * - MMAL_PARAM_AWBMODE_TUNGSTEN,
1306 * - MMAL_PARAM_AWBMODE_FLUORESCENT,
1307 * - MMAL_PARAM_AWBMODE_INCANDESCENT,
1308 * - MMAL_PARAM_AWBMODE_FLASH,
1309 * - MMAL_PARAM_AWBMODE_HORIZON,
1310 * @return 0 if successful, non-zero if any parameters out of range
1311 */
1312int raspicamcontrol_set_awb_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_AWBMODE_T awb_mode)
1313{
1314 MMAL_PARAMETER_AWBMODE_T param = {{MMAL_PARAMETER_AWB_MODE,sizeof(param)}, awb_mode};
1315
1316 if (!camera)
1317 return 1;
1318
1319 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &param.hdr));
1320}
1321
1322int raspicamcontrol_set_awb_gains(MMAL_COMPONENT_T *camera, float r_gain, float b_gain)
1323{
1324 MMAL_PARAMETER_AWB_GAINS_T param = {{MMAL_PARAMETER_CUSTOM_AWB_GAINS,sizeof(param)}, {0,0}, {0,0}};
1325
1326 if (!camera)
1327 return 1;
1328
1329 if (!r_gain || !b_gain)
1330 return 0;
1331
1332 param.r_gain.num = (unsigned int)(r_gain * 65536);
1333 param.b_gain.num = (unsigned int)(b_gain * 65536);
1334 param.r_gain.den = param.b_gain.den = 65536;
1335 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &param.hdr));
1336}
1337
1338/**
1339 * Set the image effect for the images
1340 * @param camera Pointer to camera component
1341 * @param imageFX Value from
1342 * - MMAL_PARAM_IMAGEFX_NONE,
1343 * - MMAL_PARAM_IMAGEFX_NEGATIVE,
1344 * - MMAL_PARAM_IMAGEFX_SOLARIZE,
1345 * - MMAL_PARAM_IMAGEFX_POSTERIZE,
1346 * - MMAL_PARAM_IMAGEFX_WHITEBOARD,
1347 * - MMAL_PARAM_IMAGEFX_BLACKBOARD,
1348 * - MMAL_PARAM_IMAGEFX_SKETCH,
1349 * - MMAL_PARAM_IMAGEFX_DENOISE,
1350 * - MMAL_PARAM_IMAGEFX_EMBOSS,
1351 * - MMAL_PARAM_IMAGEFX_OILPAINT,
1352 * - MMAL_PARAM_IMAGEFX_HATCH,
1353 * - MMAL_PARAM_IMAGEFX_GPEN,
1354 * - MMAL_PARAM_IMAGEFX_PASTEL,
1355 * - MMAL_PARAM_IMAGEFX_WATERCOLOUR,
1356 * - MMAL_PARAM_IMAGEFX_FILM,
1357 * - MMAL_PARAM_IMAGEFX_BLUR,
1358 * - MMAL_PARAM_IMAGEFX_SATURATION,
1359 * - MMAL_PARAM_IMAGEFX_COLOURSWAP,
1360 * - MMAL_PARAM_IMAGEFX_WASHEDOUT,
1361 * - MMAL_PARAM_IMAGEFX_POSTERISE,
1362 * - MMAL_PARAM_IMAGEFX_COLOURPOINT,
1363 * - MMAL_PARAM_IMAGEFX_COLOURBALANCE,
1364 * - MMAL_PARAM_IMAGEFX_CARTOON,
1365 * @return 0 if successful, non-zero if any parameters out of range
1366 */
1367int raspicamcontrol_set_imageFX(MMAL_COMPONENT_T *camera, MMAL_PARAM_IMAGEFX_T imageFX)
1368{
1369 MMAL_PARAMETER_IMAGEFX_T imgFX = {{MMAL_PARAMETER_IMAGE_EFFECT,sizeof(imgFX)}, imageFX};
1370
1371 if (!camera)
1372 return 1;
1373
1374 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &imgFX.hdr));
1375}
1376
1377/* TODO :what to do with the image effects parameters?
1378 MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,sizeof(imfx_param)},
1379 imageFX, 0, {0}};
1380mmal_port_parameter_set(camera->control, &imfx_param.hdr);
1381 */
1382
1383/**
1384 * Set the colour effect for images (Set UV component)
1385 * @param camera Pointer to camera component
1386 * @param colourFX Contains enable state and U and V numbers to set (e.g. 128,128 = Black and white)
1387 * @return 0 if successful, non-zero if any parameters out of range
1388 */
1389int raspicamcontrol_set_colourFX(MMAL_COMPONENT_T *camera, const MMAL_PARAM_COLOURFX_T *colourFX)
1390{
1391 MMAL_PARAMETER_COLOURFX_T colfx = {{MMAL_PARAMETER_COLOUR_EFFECT,sizeof(colfx)}, 0, 0, 0};
1392
1393 if (!camera)
1394 return 1;
1395
1396 colfx.enable = colourFX->enable;
1397 colfx.u = colourFX->u;
1398 colfx.v = colourFX->v;
1399
1400 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &colfx.hdr));
1401
1402}
1403
1404
1405/**
1406 * Set the rotation of the image
1407 * @param camera Pointer to camera component
1408 * @param rotation Degree of rotation (any number, but will be converted to 0,90,180 or 270 only)
1409 * @return 0 if successful, non-zero if any parameters out of range
1410 */
1411int raspicamcontrol_set_rotation(MMAL_COMPONENT_T *camera, int rotation)
1412{
1413 int ret;
1414 int my_rotation = ((rotation % 360 ) / 90) * 90;
1415
1416 ret = mmal_port_parameter_set_int32(camera->output[0], MMAL_PARAMETER_ROTATION, my_rotation);
1417 mmal_port_parameter_set_int32(camera->output[1], MMAL_PARAMETER_ROTATION, my_rotation);
1418 mmal_port_parameter_set_int32(camera->output[2], MMAL_PARAMETER_ROTATION, my_rotation);
1419
1420 return mmal_status_to_int(ret);
1421}
1422
1423/**
1424 * Set the flips state of the image
1425 * @param camera Pointer to camera component
1426 * @param hflip If true, horizontally flip the image
1427 * @param vflip If true, vertically flip the image
1428 *
1429 * @return 0 if successful, non-zero if any parameters out of range
1430 */
1431int raspicamcontrol_set_flips(MMAL_COMPONENT_T *camera, int hflip, int vflip)
1432{
1433 MMAL_PARAMETER_MIRROR_T mirror = {{MMAL_PARAMETER_MIRROR, sizeof(MMAL_PARAMETER_MIRROR_T)}, MMAL_PARAM_MIRROR_NONE};
1434
1435 if (hflip && vflip)
1436 mirror.value = MMAL_PARAM_MIRROR_BOTH;
1437 else if (hflip)
1438 mirror.value = MMAL_PARAM_MIRROR_HORIZONTAL;
1439 else if (vflip)
1440 mirror.value = MMAL_PARAM_MIRROR_VERTICAL;
1441
1442 mmal_port_parameter_set(camera->output[0], &mirror.hdr);
1443 mmal_port_parameter_set(camera->output[1], &mirror.hdr);
1444 return mmal_status_to_int(mmal_port_parameter_set(camera->output[2], &mirror.hdr));
1445}
1446
1447/**
1448 * Set the ROI of the sensor to use for captures/preview
1449 * @param camera Pointer to camera component
1450 * @param rect Normalised coordinates of ROI rectangle
1451 *
1452 * @return 0 if successful, non-zero if any parameters out of range
1453 */
1454int raspicamcontrol_set_ROI(MMAL_COMPONENT_T *camera, PARAM_FLOAT_RECT_T rect)
1455{
1456 MMAL_PARAMETER_INPUT_CROP_T crop = {{MMAL_PARAMETER_INPUT_CROP, sizeof(MMAL_PARAMETER_INPUT_CROP_T)}};
1457
1458 crop.rect.x = (65536 * rect.x);
1459 crop.rect.y = (65536 * rect.y);
1460 crop.rect.width = (65536 * rect.w);
1461 crop.rect.height = (65536 * rect.h);
1462
1463 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &crop.hdr));
1464}
1465
1466/**
1467 * Zoom in and Zoom out by changing ROI
1468 * @param camera Pointer to camera component
1469 * @param zoom_command zoom command enum
1470 * @return 0 if successful, non-zero otherwise
1471 */
1472int raspicamcontrol_zoom_in_zoom_out(MMAL_COMPONENT_T *camera, ZOOM_COMMAND_T zoom_command, PARAM_FLOAT_RECT_T *roi)
1473{
1474 MMAL_PARAMETER_INPUT_CROP_T crop;
1475 crop.hdr.id = MMAL_PARAMETER_INPUT_CROP;
1476 crop.hdr.size = sizeof(crop);
1477
1478 if (mmal_port_parameter_get(camera->control, &crop.hdr) != MMAL_SUCCESS)
1479 {
1480 vcos_log_error("mmal_port_parameter_get(camera->control, &crop.hdr) failed, skip it");
1481 return 0;
1482 }
1483
1484 if (zoom_command == ZOOM_IN)
1485 {
1486 if (crop.rect.width <= (zoom_full_16P16 + zoom_increment_16P16))
1487 {
1488 crop.rect.width = zoom_full_16P16;
1489 crop.rect.height = zoom_full_16P16;
1490 }
1491 else
1492 {
1493 crop.rect.width -= zoom_increment_16P16;
1494 crop.rect.height -= zoom_increment_16P16;
1495 }
1496 }
1497 else if (zoom_command == ZOOM_OUT)
1498 {
1499 unsigned int increased_size = crop.rect.width + zoom_increment_16P16;
1500 if (increased_size < crop.rect.width) //overflow
1501 {
1502 crop.rect.width = 65536;
1503 crop.rect.height = 65536;
1504 }
1505 else
1506 {
1507 crop.rect.width = increased_size;
1508 crop.rect.height = increased_size;
1509 }
1510 }
1511
1512 if (zoom_command == ZOOM_RESET)
1513 {
1514 crop.rect.x = 0;
1515 crop.rect.y = 0;
1516 crop.rect.width = 65536;
1517 crop.rect.height = 65536;
1518 }
1519 else
1520 {
1521 unsigned int centered_top_coordinate = (65536 - crop.rect.width) / 2;
1522 crop.rect.x = centered_top_coordinate;
1523 crop.rect.y = centered_top_coordinate;
1524 }
1525
1526 int ret = mmal_status_to_int(mmal_port_parameter_set(camera->control, &crop.hdr));
1527
1528 if (ret == 0)
1529 {
1530 roi->x = roi->y = (double)crop.rect.x/65536;
1531 roi->w = roi->h = (double)crop.rect.width/65536;
1532 }
1533 else
1534 {
1535 vcos_log_error("Failed to set crop values, x/y: %u, w/h: %u", crop.rect.x, crop.rect.width);
1536 ret = 1;
1537 }
1538
1539 return ret;
1540}
1541
1542/**
1543 * Adjust the exposure time used for images
1544 * @param camera Pointer to camera component
1545 * @param shutter speed in microseconds
1546 * @return 0 if successful, non-zero if any parameters out of range
1547 */
1548int raspicamcontrol_set_shutter_speed(MMAL_COMPONENT_T *camera, int speed)
1549{
1550 if (!camera)
1551 return 1;
1552
1553 return mmal_status_to_int(mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_SHUTTER_SPEED, speed));
1554}
1555
1556/**
1557 * Adjust the Dynamic range compression level
1558 * @param camera Pointer to camera component
1559 * @param strength Strength of DRC to apply
1560 * MMAL_PARAMETER_DRC_STRENGTH_OFF
1561 * MMAL_PARAMETER_DRC_STRENGTH_LOW
1562 * MMAL_PARAMETER_DRC_STRENGTH_MEDIUM
1563 * MMAL_PARAMETER_DRC_STRENGTH_HIGH
1564 *
1565 * @return 0 if successful, non-zero if any parameters out of range
1566 */
1567int raspicamcontrol_set_DRC(MMAL_COMPONENT_T *camera, MMAL_PARAMETER_DRC_STRENGTH_T strength)
1568{
1569 MMAL_PARAMETER_DRC_T drc = {{MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, sizeof(MMAL_PARAMETER_DRC_T)}, strength};
1570
1571 if (!camera)
1572 return 1;
1573
1574 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &drc.hdr));
1575}
1576
1577int raspicamcontrol_set_stats_pass(MMAL_COMPONENT_T *camera, int stats_pass)
1578{
1579 if (!camera)
1580 return 1;
1581
1582 return mmal_status_to_int(mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_CAPTURE_STATS_PASS, stats_pass));
1583}
1584
1585
1586/**
1587 * Set the annotate data
1588 * @param camera Pointer to camera component
1589 * @param Bitmask of required annotation data. 0 for off.
1590 * @param If set, a pointer to text string to use instead of bitmask, max length 32 characters
1591 *
1592 * @return 0 if successful, non-zero if any parameters out of range
1593 */
1594int raspicamcontrol_set_annotate(MMAL_COMPONENT_T *camera, const int settings, const char *string,
1595 const int text_size, const int text_colour, const int bg_colour,
1596 const unsigned int justify, const unsigned int x, const unsigned int y)
1597{
1598 MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T annotate =
1599 {{MMAL_PARAMETER_ANNOTATE, sizeof(MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T)}};
1600
1601 if (settings)
1602 {
1603 time_t t = time(NULL);
1604 struct tm tm = *localtime(&t);
1605 char tmp[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V4];
1606 int process_datetime = 1;
1607
1608 annotate.enable = 1;
1609
1610 if (settings & (ANNOTATE_APP_TEXT | ANNOTATE_USER_TEXT))
1611 {
1612 if ((settings & (ANNOTATE_TIME_TEXT | ANNOTATE_DATE_TEXT)) && strchr(string,'%') != NULL)
1613 {
1614 //string contains strftime parameter?
1615 strftime(annotate.text, MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3, string, &tm );
1616 process_datetime = 0;
1617 }
1618 else
1619 {
1620 strncpy(annotate.text, string, MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3);
1621 }
1622 annotate.text[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3-1] = '\0';
1623 }
1624
1625 if (process_datetime && (settings & ANNOTATE_TIME_TEXT))
1626 {
1627 if(strlen(annotate.text))
1628 {
1629 strftime(tmp, 32, " %X", &tm );
1630 }
1631 else
1632 {
1633 strftime(tmp, 32, "%X", &tm );
1634 }
1635 strncat(annotate.text, tmp, MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3 - strlen(annotate.text) - 1);
1636 }
1637
1638 if (process_datetime && (settings & ANNOTATE_DATE_TEXT))
1639 {
1640 if(strlen(annotate.text))
1641 {
1642 strftime(tmp, 32, " %x", &tm );
1643 }
1644 else
1645 {
1646 strftime(tmp, 32, "%x", &tm );
1647 }
1648 strncat(annotate.text, tmp, MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3 - strlen(annotate.text) - 1);
1649 }
1650
1651 if (settings & ANNOTATE_SHUTTER_SETTINGS)
1652 annotate.show_shutter = MMAL_TRUE;
1653
1654 if (settings & ANNOTATE_GAIN_SETTINGS)
1655 annotate.show_analog_gain = MMAL_TRUE;
1656
1657 if (settings & ANNOTATE_LENS_SETTINGS)
1658 annotate.show_lens = MMAL_TRUE;
1659
1660 if (settings & ANNOTATE_CAF_SETTINGS)
1661 annotate.show_caf = MMAL_TRUE;
1662
1663 if (settings & ANNOTATE_MOTION_SETTINGS)
1664 annotate.show_motion = MMAL_TRUE;
1665
1666 if (settings & ANNOTATE_FRAME_NUMBER)
1667 annotate.show_frame_num = MMAL_TRUE;
1668
1669 if (settings & ANNOTATE_BLACK_BACKGROUND)
1670 annotate.enable_text_background = MMAL_TRUE;
1671
1672 annotate.text_size = text_size;
1673
1674 if (text_colour != -1)
1675 {
1676 annotate.custom_text_colour = MMAL_TRUE;
1677 annotate.custom_text_Y = text_colour&0xff;
1678 annotate.custom_text_U = (text_colour>>8)&0xff;
1679 annotate.custom_text_V = (text_colour>>16)&0xff;
1680 }
1681 else
1682 annotate.custom_text_colour = MMAL_FALSE;
1683
1684 if (bg_colour != -1)
1685 {
1686 annotate.custom_background_colour = MMAL_TRUE;
1687 annotate.custom_background_Y = bg_colour&0xff;
1688 annotate.custom_background_U = (bg_colour>>8)&0xff;
1689 annotate.custom_background_V = (bg_colour>>16)&0xff;
1690 }
1691 else
1692 annotate.custom_background_colour = MMAL_FALSE;
1693
1694 annotate.justify = justify;
1695 annotate.x_offset = x;
1696 annotate.y_offset = y;
1697 }
1698 else
1699 annotate.enable = 0;
1700
1701 return mmal_status_to_int(mmal_port_parameter_set(camera->control, &annotate.hdr));
1702}
1703
1704int raspicamcontrol_set_stereo_mode(MMAL_PORT_T *port, MMAL_PARAMETER_STEREOSCOPIC_MODE_T *stereo_mode)
1705{
1706 MMAL_PARAMETER_STEREOSCOPIC_MODE_T stereo = { {MMAL_PARAMETER_STEREOSCOPIC_MODE, sizeof(stereo)},
1707 MMAL_STEREOSCOPIC_MODE_NONE, MMAL_FALSE, MMAL_FALSE
1708 };
1709 if (stereo_mode->mode != MMAL_STEREOSCOPIC_MODE_NONE)
1710 {
1711 stereo.mode = stereo_mode->mode;
1712 stereo.decimate = stereo_mode->decimate;
1713 stereo.swap_eyes = stereo_mode->swap_eyes;
1714 }
1715 return mmal_status_to_int(mmal_port_parameter_set(port, &stereo.hdr));
1716}
1717
1718int raspicamcontrol_set_gains(MMAL_COMPONENT_T *camera, float analog, float digital)
1719{
1720 MMAL_RATIONAL_T rational = {0,65536};
1721 MMAL_STATUS_T status;
1722
1723 if (!camera)
1724 return 1;
1725
1726 rational.num = (unsigned int)(analog * 65536);
1727 status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_ANALOG_GAIN, rational);
1728 if (status != MMAL_SUCCESS)
1729 return mmal_status_to_int(status);
1730
1731 rational.num = (unsigned int)(digital * 65536);
1732 status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_DIGITAL_GAIN, rational);
1733 return mmal_status_to_int(status);
1734}
1735
1736/**
1737 * Asked GPU how much memory it has allocated
1738 *
1739 * @return amount of memory in MB
1740 */
1741static int raspicamcontrol_get_mem_gpu(void)
1742{
1743 char response[80] = "";
1744 int gpu_mem = 0;
1745 if (vc_gencmd(response, sizeof response, "get_mem gpu") == 0)
1746 vc_gencmd_number_property(response, "gpu", &gpu_mem);
1747 return gpu_mem;
1748}
1749
1750/**
1751 * Ask GPU about its camera abilities
1752 * @param supported None-zero if software supports the camera
1753 * @param detected None-zero if a camera has been detected
1754 */
1755static void raspicamcontrol_get_camera(int *supported, int *detected)
1756{
1757 char response[80] = "";
1758 if (vc_gencmd(response, sizeof response, "get_camera") == 0)
1759 {
1760 if (supported)
1761 vc_gencmd_number_property(response, "supported", supported);
1762 if (detected)
1763 vc_gencmd_number_property(response, "detected", detected);
1764 }
1765}
1766
1767/**
1768 * Check to see if camera is supported, and we have allocated enough memory
1769 * Ask GPU about its camera abilities
1770 * @param supported None-zero if software supports the camera
1771 * @param detected None-zero if a camera has been detected
1772 */
1773void raspicamcontrol_check_configuration(int min_gpu_mem)
1774{
1775 int gpu_mem = raspicamcontrol_get_mem_gpu();
1776 int supported = 0, detected = 0;
1777 raspicamcontrol_get_camera(&supported, &detected);
1778 if (!supported)
1779 vcos_log_error("Camera is not enabled in this build. Try running \"sudo raspi-config\" and ensure that \"camera\" has been enabled\n");
1780 else if (gpu_mem < min_gpu_mem)
1781 vcos_log_error("Only %dM of gpu_mem is configured. Try running \"sudo raspi-config\" and ensure that \"memory_split\" has a value of %d or greater\n", gpu_mem, min_gpu_mem);
1782 else if (!detected)
1783 vcos_log_error("Camera is not detected. Please check carefully the camera module is installed correctly\n");
1784 else
1785 vcos_log_error("Failed to run camera app. Please check for firmware updates\n");
1786}
1787
1788
1789/** Default camera callback function
1790 * Handles the --settings
1791 * @param port
1792 * @param Callback data
1793 */
1794void default_camera_control_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
1795{
1796 fprintf(stderr, "Camera control callback cmd=0x%08x", buffer->cmd);
1797
1798 if (buffer->cmd == MMAL_EVENT_PARAMETER_CHANGED)
1799 {
1800 MMAL_EVENT_PARAMETER_CHANGED_T *param = (MMAL_EVENT_PARAMETER_CHANGED_T *)buffer->data;
1801 switch (param->hdr.id)
1802 {
1803 case MMAL_PARAMETER_CAMERA_SETTINGS:
1804 {
1805 MMAL_PARAMETER_CAMERA_SETTINGS_T *settings = (MMAL_PARAMETER_CAMERA_SETTINGS_T*)param;
1806 vcos_log_error("Exposure now %u, analog gain %u/%u, digital gain %u/%u",
1807 settings->exposure,
1808 settings->analog_gain.num, settings->analog_gain.den,
1809 settings->digital_gain.num, settings->digital_gain.den);
1810 vcos_log_error("AWB R=%u/%u, B=%u/%u",
1811 settings->awb_red_gain.num, settings->awb_red_gain.den,
1812 settings->awb_blue_gain.num, settings->awb_blue_gain.den);
1813 }
1814 break;
1815 }
1816 }
1817 else if (buffer->cmd == MMAL_EVENT_ERROR)
1818 {
1819 vcos_log_error("No data received from sensor. Check all connections, including the Sunny one on the camera board");
1820 }
1821 else
1822 {
1823 vcos_log_error("Received unexpected camera control callback event, 0x%08x", buffer->cmd);
1824 }
1825
1826 mmal_buffer_header_release(buffer);
1827}
1828