PHP in Elphel cameras

From ElphelWiki
Revision as of 16:03, 11 January 2008 by Andrey.filippov (talk | contribs) (elphel_autoexposure_set)
Jump to: navigation, search

Why PHP?

One of the main objectives of Elphel products is to make them developer-friendly. Just opening of the camera internals (including source code, FPGA code, hardware schematics) is not enough without providing means to modify the cameras easily, and here PHP comes to the rescue. It is powerful and efficient and is well known by many developers including those who may have problems to modify FPGA code or kernel drivers. It is much easier to try your custom applications written in PHP - just transfer the files to the camera (i.e. with ftp) and open them in the web browser.

PHP supports custom extensions written in C and we'll work (and I hope not just we at Elphel) to provide more custom function to combine flexibility and ease of use of the PHP with efficiency of native compiled code.

PHP in Elphel cameras (models 353/363)

Current version of PHP in Elphel cameras is 5.2.1, we will try to keep it (almost) current. As of now ( Elphel software version 7.1.6) there are two copies of PHP in the camera - one is working through Boa web server (traditional for Axis ETRAX based products) in CGI mode (port 80) and the other one in Fast CGI mode through Lighttpd on port 81. Fast CGI mode does not restart applications (like traditional CGI does) for each HTTP request but rather keeps them alive to serve multiple requests. In the case of large application like PHP itself it makes a big performance difference and allows usage of the PHP scripts in the camera without the penalty of slow responses - something really undesirable for AJAX applications.


How to use PHP in the camera

It is very simple. It is the same as to try your HTML/JavaScript pages. You just need to ftp you script to one of the two locations (or their subdirectories) in the camera. Examples below assume you have the default camera IP=192.168.0.9:

  • /var/html (visible as http://192.168.0.9:81/var/ in the web browser) - recommended for experiments, if something goes wrong you can just power-cycle the camera and all your changes will be gone
  • /usr/html' (visible as http://192.168.0.9:81/ in the web browser) - permanent (until next full firmware upgrade ) storage in the camera flash memory. This second location is more dangerous as you can change the installed files and rebooting will not restore the default behaviour. Flash memory has limited number of write cycles and can develop additional bad blocks during usage, so this location is recommended for "final" files, already tested in /var/html.

You may also edit small text files with web-based editor. It does not allow to open non-existent file, but has an option to "Save As" - http://192.168.0.9:81/admin-bin/editcgi.cgi So you can try opening http://192.168.0.09:81/admin-bin/editcgi.cgi?file=/usr/html/phpinfo.php and then (modify and) save it to /var/html/test.php . When done - just open the following URL and watch the results of the script processing by in-camera PHP:

http://192.168.0.9:81/var/test.php  - run
http://192.168.0.9:81/admin-bin/editcgi.cgi?file=/var/html/test.php - edit

It is also possible to execute PHP scripts without the browser - camera startup scripts already use it for various initialization of the hardware. You can (silently) execute the same program in telnet session:

php /var/html/test.php >/dev/null

Elphel PHP extension in the camera

Since Elphel software version 7.1.6 there is a custom extension module for PHP installed in the camera, you may also create your own extension as described below. The existent extension exports several functions and defines constants.

Constants, defined in elphel PHP extension

see: Elphel_PHP_constants

elphel extension functions

Note: Currently arguments (and array values) are supposed to be numbers, not strings - you may want to use $value+0 (instead of just $value) if $value may be a string (i.e. passed from _GET[])--Andrey.filippov 19:55, 14 December 2007 (CST)


elphel_get_P_value

long elphel_get_P_value (long $address)

This function returns value of one of internal camera parameters, as defined in c313a.h and documented in Elphel_PHP_constants. It is strongly recommended to use symbolic names as the numeric values may change in the future (as they already did multiple times). The values are maintained by the camera driver(s), usually they are updated when the driver programs the acquisition process.

Example:

echo elphel_get_P_value(ELPHEL_FP100S)/100; // will return current camera sensor frame rate in (frames per second);



elphel_set_P_value

void elphel_set_P_value (long $address, long $data) Set camera parameters to be used when the camera will be "programmed" (see below). Example:

elphel_set_P_value(ELPHEL_QUALITY,100); // set JPEG compression quality to 100% - virtually lossless

The elphel_get_P_value and elphel_set_P_value deal with different variables. Those that are read are validated to match the allowed values and may differ from those written (and they are only updated when sensor/compressor are programmed). You may read the parameters values that were written to the camera by adding ELPHEL_NUMBER to the parameter address, i.e

echo elphel_get_P_value(ELPHEL_QUALITY+ELPHEL_NUMBER); // will output the compression quality as written



elphel_get_P_arr

array elphel_get_P_arr (array $template) Read multiple camera parameters as an associative array, according to $template. $template should have elements with the key names matching the camera parameters names, same as defined Elphel_PHP_constants, but without "ELPHEL_" prefix (all the elements with the other keys will be ignored). elphel_get_P_arr returns array, where element keys are the same as in $template (after removing of any unknown ones), and values are long values read from the camera.

Example:

$arr=array("foo"=>"", "WOI_LEFT" => "",  "WOI_TOP" => "", "1", 3, "WOI_WIDTH" => 0, "WOI_HEIGHT" => 0);
print_r ($arr);

will return (5MPix sensor, full window):

Array
(
   [WOI_LEFT] => 0
   [WOI_TOP] => 0
   [WOI_WIDTH] => 2592
   [WOI_HEIGHT] => 1936
)



elphel_set_P_arr

long elphel_set_P_arr (array $input)

Write multiple camera parameters, provided as an associative array, where keys are parameter names same as defined Elphel_PHP_constants, but without "ELPHEL_" prefix. Values should be numeric and integer, all other types are ignored.

Return value - number of successfully processed elements.

Example:

echo elphel_set_P_arr(array("WOI_LEFT" => 896,  "WOI_TOP" => 672, "WOI_WIDTH" => 800, "WOI_HEIGHT" => 600));

Will print 4 and set 800x600 window in the center of the 5Mpix sensor.



elphel_get_state

long elphel_get_state (void) There are multiple states defined in the camera, some are obsolete, the following are most common (no symbolic constants in PHP yet)

  • 0 - "reset" (i.e. no images yet acquired after power up)
  • 7 - "stopped" - sensor is constantly acquiring images (used for autoexposure), but compressor is stopped and no frames get to the circbuf
  • 8 - "running" - compressor is acquiring images to circbuf
  • 9 - "stopping" - compressor is compressing the last frame (transition from "running" to "stopped"
  • 10 - "single_buffer" - compressor is acquiring full circbuf (plus one frame as it will notice the buffer is full after overrunning the original starting point) and then will stop



elphel_reset_sensor

void elphel_reset_sensor (void)

Reset the sensor settings, stop compressor (if it was running) and force sensor re-initialization.

Example:

elphel_reset_sensor();



elphel_program_sensor

void elphel_program_sensor (long $nonstop)

Applies written earlier (see elphel_set_P_value, elphel_set_P_arr, elphel_white_balance) parameters to the cameras sensor and FPGA compressor. $nonstop determines if the acquisition should be restarted ($nonstop==0) ot updated without stopping ($nonstop==1).

Example:

elphel_program_sensor(0);



elphel_compressor_run

void elphel_compressor_run (void)

Turn the FPGA compressor on. Sensor should be already programmed ([[PHP_in_Elphel_cameras#|elphel_get_state] should return 7 (or higher) if tested prior to issuing elphel_compressor_run() command.

Example:

elphel_compressor_run();



elphel_compressor_stop

void elphel_compressor_stop (void)

Stop camera compressor (will stop transferring more frames to the circular buffer. This command does not to be synchronized - compressor will finish current frame before stopping.

Example:

elphel_compressor_stop();



elphel_compressor_frame

void elphel_compressor_frame (void)

Acquire one frame to the buffer (will apply written JPEG quality). Sensor should be already programmed - elphel_get_state should return 7 (or higher) if tested prior to issuing elphel_compressor_frame() command.

Example:

elphel_compressor_frame();



elphel_set_fpga_time

double elphel_set_fpga_time (double seconds)

Set FPGA internal timer that is used for time-stamping images and video frames. Internal counter has a 32-bit seconds counter and 12 bit microsecond one, so you may specify epoch - seconds since 01/01/1970.

Returns time set as a double - it should match the input parameter after rounding to microseconds (resolution of the FPGA timer).

Example:

elphel_set_fpga_time(0x47565ad3);

elphel_get_fpga_time

double elphel_get_fpga_time (void)

Copies current value of the FPGA timer registers to the global array (maybe read with several functions described above) and returns the the time as a double value, combining second as microseconds. The readout process guaranties that seconds and microseconds are sample simultaneously.

Example:

echo elphel_get_fpga_time();



elphel_white_balance

int elphel_white_balance ([double thrsh [, double minfrac [, double rscale [, double bscale]]]])

This function is designed to perform white balancing of the camera images. It relies on histogram calculation, "gamma" tables (curves) (both implemented in the FPGA) and the auto-exposure software in the camera (not yet included in this PHP extension, it is currently controlled through the separate CGI program). White balance uses the same window as auto-exposure, only data inside the specified rectangular window is processed.


The goal of this function is to make the brightest areas in the image white (equal values of red, green and blue), it assumes that auto-exposure algorithm (operating after each frame acquired) already adjusted the brightness of the images so it uses all the 8-bit range and some pixel values are close to the maximal 255.


The balancing is achieved by modification of the lookup tables ("gamma" tables, "curves") that map 12-bit (in 5MPix sensor, may be 10 or 14 bits with other devices) pixel data to the 8-bit pixel values used by the image/video compressor, the same values can be manually entered with elphel_get_P_value, elphel_get_P_arr functions applied to RSCALE and BSCALE parameters. The balancing is sensor-independent and it does not change sensor analog gains (where available), but if the required correction is significant, it is recommended to adjust those gains also, leaving only fine adjustment to the white balance algorithm - that will increase the dynamic range of the images.


All function parameters are optional, but you can not skip the first one(s) if you would like to specify the next one(s), in that case default values should be explicitly entered.


First parameter thrsh defines how bright should be pixels to be counted as white. Default value of 0.98 corresponds to 250 counts on 255 scale.


Second parameter minfrac (default 0.01) tells how many pixels (at least) should be counted, as a fraction of the total number of the pixels in the specified window. If there are too few pixels with the brightness above the thrsh, the thrsh will be lowered, to let more pixels to be counted.


Next two parameters - rscale and bscale (both with default values of 1.0) can be used to apply manual bias to the automatically calculated values of red and blue scales (relative.to green)


When this function is executed successfully it returns 0 (negative numbers indicate failure) in adjusts parameters (similar to manual elphel_get_P_value, elphel_get_P_arr), but that will propagate to the FPGA only after elphel_program_sensor is executed. If you do not need to change any other parameters, you may use elphel_program_sensor(1) - in this case the image/video acquisition process will not be interrupted, frame timing will be preserved.


As this function uses the histograms calculated from the previously acquired images, you actually need to acquire some. It is recommended you wait till the auto-exposure will adjust the brightness before executing elphel_white_balance. It also is not needed to run it as frequently as auto-exposure (for each frame), usually it is enough to call it only when the lighting conditions are changed.


Examples:

if (elphel_white_balance()>=0) elphel_program_sensor(1);

or

elphel_white_balance(0.98,0.01,1.0,1.2); // set bluish tint

whitebalance.php is an example script that uses this function. It is installed in the camera and can be called as (provided camera has the default IP of 192.168.0.9):

http://192.168.0.9/whitebalance.php

or

http://192.168.0.9/whitebalance.php?thrsh=0.98&minfrac=0.01&rscale=1.0&bscale=1.0

elphel_autoexposure_set

void elphel_autoexposure_set (void)

This function controls auto-exposure in the camera. It is a quick modification that preserves the existent functionality (including interface) and just adds control from the PHP. This function itself does not take any parameters, it also does not return any data, It applies parameters that have to be already written by either of elphel_set_P_value, elphel_set_P_arr, the current state of the auto-exposure algorithm can be read back using elphel_get_P_value, elphel_get_P_arr functions

Creating custom PHP extensions for Elphel cameras

... You may also want to try your scripts from the command line - in that case the stdout will be visible and you and PHP+your module will be able to complain about Segmentation faults (when invoked from the browser it you will get Error 500 at best if that happens). And you'll have to manually restart web server + PHP after module changes (remember - Fast CGI does not kill PHP after end of HTTP request?)