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