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