rpicamsrc: fix indentation
[platform/upstream/gstreamer.git] / sys / rpicamsrc / RaspiCamControl.c
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
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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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", &params->sharpness);
460       used = 2;
461       break;
462
463    case CommandContrast : // contrast - needs single number parameter
464       sscanf(arg2, "%d", &params->contrast);
465       used = 2;
466       break;
467
468    case CommandBrightness : // brightness - needs single number parameter
469       sscanf(arg2, "%d", &params->brightness);
470       used = 2;
471       break;
472
473    case CommandSaturation : // saturation - needs single number parameter
474       sscanf(arg2, "%d", &params->saturation);
475       used = 2;
476       break;
477
478    case CommandISO : // ISO - needs single number parameter
479       sscanf(arg2, "%d", &params->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", &params->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", &params->colourEffects.u, &params->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", &params->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", &params->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", &params->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 = &params->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", &params->annotate_text_size,
648                                &params->annotate_text_colour,
649                                &params->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  */
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  */
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  */
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  */
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  */
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, &params->colourEffects);
883    //result += raspicamcontrol_set_thumbnail_parameters(camera, &params->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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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, &param.hdr));
1124 }
1125
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, &param.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  */
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  */
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  */
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  */
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  */
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  */
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  */
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
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  */
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
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  */
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  */
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  */
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* */