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