- NC393 development progress and the future plans
- Reaching 220 MB/s sustained write speed with SATA-2 controller
- A web interface for a simpler and more flexible Linux kernel dynamic debug controlling
- I will not have to learn SystemVerilog
- Tutorial 02: Eclipse-based FPGA development environment for Elphel cameras
This program allows recording of the video/images acquired by Elphel 353/363 series cameras to the storage media. It is developed to use such media as hard disk drives, compact flash cards or USB storage devices (with reduced data rate as ETRAX FS processor currently supports only USB 1.1, not the fast USB 2). But it might work over the NFS and be useful even for the basic model 353 cameras that do not have any additional storage devices attached.
camogm is designed to run in the background and accept commands through a named pipe. It writes JPEG-encoded frames from the camera circbuf-circular video buffer in any of the 3 formats:
- ogm - MJPEG video in Xiph Ogg container
- jpeg - series of the individual JPEG files (1 file per frame)
- mov - MJPEG video in Apple QuickTime(R) container
As of today the last one (mov) is probably the fastest one in the camera as it uses the minimum of computational resources. Ogg is optimized for streaming and requires additional memory copying and checksum calculation for all of the recorded data, individual JPEG files grow large directories that can use system resources, while recording mov format simply merges FPGA-encoded frames (with JPEG and optional Exif headers added by the software) and the file header (with frame index) is calculated only once per file.
This program makes use of the circbuf that can hold several seconds of even high resolution/high frame rate video, so switching from file to file and/or waiting for the search operations on the HDD will not cause the frame loss - that can be verified if the Exif headers are enabled - regardless of the format selected each frame will have the exact timestamp (with 1 microsecond resolution).
Eventually camogm will be started (and restarted if needed) automatically at boot time, now it is started manually with the command
Where <named_pipe_name> is the filename that will be used to pass commands to the camogm. A good choice is "/var/state/camogm_cmd" and it is used in a camogmstate.php - a demo PHP script that can read the current status of the camogm recorder. Running camogm without any parameters or with "--help" will just output the short version of this page. So this is the example of the command that starts camogm as a background process from the shell prompt (i.e. telnet or Phpshell):
camogm /var/state/camogm_cmd &
Sending Commands to camogm
When the camogm is running you may verify that with the command:
ps | grep "camogm"
It is waiting for the commands to be sent to the pipe (/var/state/camogm_cmd above) as text strings. Commands are separated with the new lines ("\n") and/or semicolons (";"), command names are separated from the optional parameters by spaces " " and/or equal signs "=". The following is an example of such command sent from the shell prompt using command "echo" and output redirection ">" to th camogm command pipe
echo "status; exif 1; format=jpeg;status=/var/tmp/camogm.status" > /var/state/camogm_cmd
That command will:
- print current status information sending it to the standard output (may not be visible if the program was not started from the same session),
- set exif mode ON (each frame will have the full Exif header including a precise time stamp),
- set output format to a series of individual JPEG files, and then
- send status information to a file /var/tmp/camogm.status in the camera file system.
The camogmstate.php script shows how to use a named pipe for the status information so the caller will wait until camogm returns that status info (the "echo" command by itself will not wait for the status, there can (and will) be a delay between finishing of echo (or equivalent) and the appearance of the status info in the output file. With the current state of the software that status info may never come if the camera frame capture process is stopped while camogm was recording video as it checks for the new commands once per frame if it is in the "running" state (in "stopped" state in checks for the incoming commands twice a second)
No parameters - just start recording video/images. At least two frames in the buffer are needed to start recording (they will not be lost) - the time stamp difference is used to calculate the frame rate. In the case there are not enough frames in the buffer (i.e. video acquisition is not started) the state of the camogm (reported by status and xstatus) will be "starting" before it will become "running". The video will be recorded to the same file (may be a directory for .jpeg format) until explicitly stopped, or until the specified file size/duration/number of frames is exceeded or some critical parameters (like frame dimensions) are changed. In those cases (not explicitly stopped) camogm will restart recording into a new file (filenames are composed from the specified prefix and the timestamp) so that no frames will be lost (if it is not overwhelmed by the incoming frame rate) and the first frame of a new file segment will be the next one acquired after the last one in the previous file.
Just stop the recording. If the video acquisition is on and camogm is started again before the circbuf is overrun, there will be no gaps in the recording. But if the pause will be too long some frames will be lost and there will be a gap between the next file and the previous one.
Terminate camogm program (it will execute implied "stop" command first to finish recording if any).
Specify the maximal duration of each individual file segment. The new file will be started if this time limit will be exceeded. The default duration is 60 seconds, current value is reported by status/xstatus commands.
Specify the maximal size of each individual file segment in bytes. The new file will be started if this limit will be exceeded. The limit is 2.147.483.647 bytes (~2 GB), current value is reported by status/xstatus commands.
Specify the maximal number of frames of each individual file segment. The new file will be started if this limit is exceeded. The default value is 16384.
frames_per_chunk=<number_of_frames_per_chunk> (default 10)
Sets the number of chunk entries in the *.mov header (10 means there's 1 chunk entry with an absolute offset in the header for each 10 frames).
start_after_timestamp=SS.UU # double (0123456789.012345)
Delays recording start until a specific time-stamp has been reached. This command alone does not start a recording you need to run the "start" command as well after setting start_after_timestamp.
prefix value is used by the camogm to generate file names/paths to store video content. Full paths will be generated from the specified prefix, timestamps of the first frame in the segment and appropriate extension (".ogm",".jpeg" or ".mov"). The prefix consists of directory path (everything before the last slash "/") and the file name prefix (what remains after the last "/"). In the case of video formats (".ogm",".mov") the directory prefix should point to an existent directory on the mounted writeable media - camogm will not try to create missing directories and will just fail to start recording. In the case of individual JPEG files camogm will try to create the last level in directory structure if it does not exist and place all the frame files there.
Controls generation and output of Exif headers for each JPEG-encoded frame. These headers slightly (for the large frames) increase the file sizes and add a little of computation to the CPU, but they are very useful for later processing as they provide precise timing information that does not depend on particular file format and timing calculations that involve frame rate and frame numbers.
turns it off, while
turns it on. Current default value is off, but that may change in the future so it is better to specify the desired value.
Currently only works for "mov" format (will add to "ogm" later). Values >1.0 make the video play back slower than recorded ('slow motion'), the values less than 1.0 make the playback faster (time lapse video).
Skip specified number of frames after each frame stored (default 0 - no skip)
Alternative way to reduce frame rate of the recorded images - specify required image period (integer value, in seconds). All intermediate images will be skipped, only first after each multiple of the specified interval will be stored. That means, that the time interval between subsequent images maybe slightly different, but the rounding error will not accumulate during long recordings.
timelapse and frameskip are mutually exclusive (they even use the same variable with positive values for frame skip (in frames) and negative - timelapse (in seconds).
- ogm - record video as Ogg Media Stream
- jpeg - record video as a series of JPEG files
- mov - record video as Apple Quicktime (R) files
Mostly a debug feature. Force camogm to start next file from the two most recent images in the circbuf, discarding all the older ones. It is the same action camogm does when the buffer is overrun and frames are lost.
The first command form (with to file specified) turns the debug output off, the second - directs it somewhere. camogm recognizes several special names like "stdout" and "stderr", it also treats file name "none", "null" and "/dev/null" as empty and turns the debug feature off.
Allows to specify debug verbosity level, the higher the level the more information is output (it may slow down camogm and cause it to drop frames even if it could handle it with no/low debug output).
As a debug feature camogm can set the camera global circbuf read pointer to the current value of camogm's read pointer. In that case it is possible to watch the camogm progress by other programs, such as imgsrv
This command provides the current camogm state information and sends it to standard output (maybe invisible if camogm was started from different shell session or by other means) or to the specified output file in plain text format. The same information is available in XML format - see xstatus command below. The following is a commented sample output generated by the status command:
state running // may be stopped, running and starting. Usually the last // one can be only visible if there are no images coming to the buffer. file /tmp/z/qvid1195433980_662716.mov // full path toi the current file being recorded frame 293 // current frame number (starts from 0) file duration 14.616060 sec // current duration of the video in this file segment file length 13167561 B // current video file size frame period 50055 (0xc387) // frame period in microseconds (this one is approximately 1/20 sec) frames to skip 100 (left 37) // number of frames to skip after the frame is acquired. Shown only if frame skip mode is enabled. timelapse period 10 sec (remaining 10 sec) // frame period for time lapse mode (time till next frame will be stored). Shown only if time lapse mode enabled width 1024 (0x400) // frame width in pixels height 768 (0x300) // frame height in pixels // - blank line output format mov // output file format - one of "ogm", "jpeg" and "mov" using exif yes // frames are generated with Exif headers that include time stamps path prefix: /tmp/z/qvid // file prefix as specified in prefix command max file duration: 60 sec // maximal file duration as specified in duration command max file length: 100000000 B // maximal file length as specified in length command max frames 16384 // maximal number of frames as specified in ... none yet, uses default timescale 1.000000 // time scale as specified in timescale command frames per chunk 10 // "frames per chunk" used in "mov" format // - blank line buffer overruns 0 // number of buffer overruns while recording since last status/xstatus // (these commands zero the buffer overruns counter). If no overruns // are reported, no frames are lost, including between file segments. buffer minimal 19748288 // Minimal level of the buffer memory since last status/xstatus command. buffer free 19748192 // Current amount of free memory in the video buffer (actual value might // be one frame less as the FPGA write pointer is reported only after // the whole frame is stored buffer used 43680 // Amount of memory currently used in the video buffer. circbuf_rp 10933536 (0xa6d520) // Current location of the read pointer in the video buffer // - blank line debug output to stderr // where the debug messages are sent to (as specified in debug command) debug level 1 // Debug verbosity level, the higher - the more "noisier". Set in // debuglev command. use global pointer no // see save_gp command.
"-1" values that status/xstatus commands may return for some parameters mean "undefined", they are calculated only during video recording.
Same information as described for status command above, but presented in XML format more suitable to be processed by other software while status is easier to read by humans. See camogmstate.php PHP script that returns this XML data to the HTTP GET requests.
<?xml version="1.0"?> <camogm_state> <state>"running"</state> <file_name>"/tmp/z/qvid1195440137_027276.mov"</file_name> <frame_number>281</frame_number> <file_duration>14.015400</file_duration> <file_length>12731197</file_length> <frame_period>50055</frame_period> <frames_skip>0</frames_skip> <seconds_skip>10</seconds_skip> <frames_skip_left>0</frames_skip_left> <seconds_skip_left>7</seconds_skip_left> <frame_width>1024</frame_width> <frame_height>768</frame_height> <format>"mov"</format> <exif>"yes"</exif> <prefix>"/tmp/z/qvid"</prefix> <max_duration>60</max_duration> <max_length>100000000</max_length> <max_frames>16384</max_frames> <timescale>1.000000</timescale> <frames_per_chunk>10</frames_per_chunk> <buffer_overruns>0</buffer_overruns> <buffer_minimal>19747712</buffer_minimal> <buffer_free>19747808</buffer_free> <buffer_used>44064</buffer_used> <circbuf_rp>16275392</circbuf_rp> <debug_output>"stderr"</debug_output> <debug_level>1</debug_level> <use_global_rp>"no"</use_global_rp> </camogm_state>
This program does not control the process of acquisition of the video/images to the camera internal buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected format and stores the result files.
Geo Tagging Specific Commands
kml=1 # turn on geotagging
kml=0 # turn off geotagging
Enable / Disable KML output (geotagging).
Set the amount of seconds between KML entries. (default: 2)
kml_hhf=45 # set horizontal half FOV to 45° so the full horizontal FOV is 90°
Set horizontal half FOV in degrees. (default: 20.0)
kml_vhf=30 # set half vertical FOV to 30° so the full vertical FOV is 60°
Set vertical half FOV in degrees. (default: 15.0)
???Set "near" distance to PhotoOverlay in metres (Don't use "0") (default: 40)???
Set altitude/height mode.
- gps - absolute GPS altitude
- ground - relative to ground (default)
Set height offset (added to GPS altitude) in metres. (default: 10)
This is modified version of camogm to support audio recording (from the firmware 188.8.131.52 or later). It support recording of audio 16bit mono/stereo, from 11025 to 44100 Hz to QuickTime(MOV) and OGG(OGM) file formats. Source of the audio is the sound card (can be connected to camera over USB), and file storage can be USB-flash, HDD (connected to camera directly) or NFS-mounted disk. Preferred method is HDD drive, connected to camera directly, because NFS-mounted disk have a non-uniform system load what can cause broken files.
The recorded movie have the same duration of the video and sound, but when play it's depend on how player work with file - for example, QuickTime player play movie like the sound is shorter than video, MPlayer will repeat the last sound piece at the end of movie etc. - so it's better to merge movie from the chunks to single movie.
P.S. First check the sound hardware: set volume to maximum by command
amixer set PCM 100
and try to play test sound file:
- if you can't hear any sound, probably you have an old USB card on the camera - this new 10349 RevC will work correctly with sound card.
command to enable or disable audio recording. When audio support is disabled, camogm work in the same way as original camogm. By default audio is disabled.
command to set audio format - frame rate and number of channels. Frame rate can be from 11025 to 44100 Hz; number of channels - 1 for mono sound, or 2 - for stereo. By default 44100/2
This option is to force writing to storage after each recorded frame. Using a filesystem the OS will write data to buffer before writing to a real device. This is not a problem with a HDD or other storage media mounted directly on the camera, but with NFS mounted folder this causes trouble as the NFS driver will fill up the buffer and only send data over the network once the buffer is full - this causes a short hang on the camera and frames might be lost. (default: disabled)
Graphical User Interface for camogm.
Please see Camogmgui
Elphel393 series cameras
The functionality of camogm has been updated in Elphel393 series of cameras. The new version of the program can write data to a raw disk (disk without file system) and send the data over web sockets. The new version of camogm should be started with two command line arguments:
camogm -n <named_pipe_name> -p <port_number>
Where <named_pipe_name> is the file name that will be used to pass commands to camogm and <port_number> is a port number used for web interface. The existing command set has been extended with several new commands addressing new functions.
Enable sensor port <port_number>. All sensor ports are enabled by default.
Disable sensor port <port_number>. camogm does not read data from disabled ports.
commands to set or reset path to raw device buffer. Setting path to raw device buffer along with jpeg format set switches camogm to raw device buffer operation. All subsequent writes and reads will be performed to or from raw disk. camogm saves write pointer while the program is running and sequential starts and stops will not lead to data overwrite. camogm will reject the 'start' command if the path to raw device buffer is set and current image format is not jpeg. You should either reset the path with 'rawdev_path' command without parameters or set format to jpeg with 'format=jpeg' to continue operation. Note, that camogm does not check the disk in any way and if the path is mistakenly set to a device with file system, the file system and the data on it will be destroyed.
camogm can process commands sent over a web socket. A command can be sent as HTTP GET request or as a simple string prefixed with 'cmd/', e.g.:
camogm can process the following commands:
Find a file with a time stamp which is within one minute time frame from the time stamp given. If such a file was found, camogm saves the position of the file and 'next_file' command can be used to advance to the next file on disk. If file was not found, camogm silently resets connection without any data sent.
Get next file from disk. This command should only be used after 'find_file' command successfully finished and returned a file. If file pointer was not set or file was not found, camogm silently resets connection without any data sent.
Read disk dump and send it over socket. The dump is split into several pieces and camogm returns the number of files to be sent in response to the command:
Number of files: <number>
The socket is closed right after this string is sent. camogm opens a socket for each file to be send, waits for connection, sends a file and closes connection after a file was sent.
Read raw device buffer and create disk index directory. This directory contains the offsets of all files found on disk and can be used to retrieve files from disk. This command is a prerequisite for get_index, read_file and read_all_files commands. Note that reading disks of several dozens or hundreds of Gib in size can take much time.
Get disk index directory. Each record in the directory corresponds to a single file and has the following format:
<unix_time> here is time in Unix format, it represents the number of seconds elapsed since 1970-01-01 00:00:00 +0000 (UTC).
Read a file from raw disk buffer and send it over socket. The disk index directory should be built prior this command. If a file was not found in disk index directory (for example, because of a mistake in the command string), camogm silently resets connection without any data sent.
Retrieve all files from disk. Disk index directory should be built before this command can be executed. When this command is received, camogm sends back the number of files in the disk index directory:
Number of files: <number>
The socket is closed right after this string is sent. camogm opens a socket for each file to be send, waits for connection, sends a file and closes connection after a file is sent.