"Fossies" - the Fresh Open Source Software Archive

Member "motion-Release-4.3.0/src/raspicam/RaspiCamControl.c" (14 Jan 2020, 61313 Bytes) of package /linux/misc/motion-Release-4.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "RaspiCamControl.c" see the Fossies "Dox" file reference documentation.

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