From 9709f438c44973a188cd9fd9bc1eaed5d57447d7 Mon Sep 17 00:00:00 2001 From: AngelCarpintero Date: Thu, 17 Jul 2008 09:55:50 +0000 Subject: [PATCH] Apply code standard --- CODE_STANDARD | 35 + conf.c | 3441 ++++++++++++++++++++++++----------------------- conf.h | 220 +-- mmx.h | 358 ++--- netcam_jpeg.c | 679 +++++----- netcam_wget.h | 36 +- track.c | 1253 ++++++++--------- track.h | 68 +- video_freebsd.c | 1668 +++++++++++------------ video_freebsd.h | 120 +- webcam.c | 638 ++++----- webcam.h | 22 +- 12 files changed, 4315 insertions(+), 4223 deletions(-) diff --git a/CODE_STANDARD b/CODE_STANDARD index 91046691..dd1be5a4 100644 --- a/CODE_STANDARD +++ b/CODE_STANDARD @@ -118,6 +118,7 @@ if ((picture=fopen(cnt->conf.mask_file, "r"))) { BAD EXAMPLE (even though Kenneth loves this one personally) + if ((picture=fopen(cnt->conf.mask_file, "r"))) { cnt->imgs.mask=get_pgm(cnt, picture, cnt->imgs.width, cnt->imgs.height); @@ -129,6 +130,40 @@ else printf("Hello world\n"); } + + +GOOD EXAMPLE + +switch (expr) { +case ABC: +case DEF: + statement; + break; +case UVW: + statement; + break; +default: + /* default case */ + statement; +} + +BAD EXAMPLE + +switch (expr) { + case ABC: + case DEF: + statement; + break; + case UVW: + statement; + break; + default: + /* default case */ + statement; +} + + + -------------------- RULE 6 Whitespace. diff --git a/conf.c b/conf.c index ff0c7272..1e7d0a8f 100644 --- a/conf.c +++ b/conf.c @@ -35,118 +35,118 @@ #ifndef HAVE_GET_CURRENT_DIR_NAME char *get_current_dir_name(void) { - char *buf = malloc(MAXPATHLEN); - getwd(buf); - return buf; + char *buf = malloc(MAXPATHLEN); + getwd(buf); + return buf; } #endif -#define stripnewline(x) {if ((x)[strlen(x)-1]=='\n') (x)[strlen(x) - 1] = 0; } +#define stripnewline(x) {if ((x)[strlen(x)-1]=='\n') (x)[strlen(x) - 1] = 0;} struct config conf_template = { - width: DEF_WIDTH, - height: DEF_HEIGHT, - quality: DEF_QUALITY, - rotate_deg: 0, - max_changes: DEF_CHANGES, - threshold_tune: 0, - output_normal: "on", - motion_img: 0, - output_all: 0, - gap: DEF_GAP, - maxmpegtime: DEF_MAXMPEGTIME, - snapshot_interval: 0, - locate: "off", - input: IN_DEFAULT, - norm: 0, - frame_limit: DEF_MAXFRAMERATE, - quiet: 1, - ppm: 0, - noise: DEF_NOISELEVEL, - noise_tune: 1, - minimum_frame_time: 0, - lightswitch: 0, - autobright: 0, - brightness: 0, - contrast: 0, - saturation: 0, - hue: 0, - roundrobin_frames: 1, - roundrobin_skip: 1, - pre_capture: 0, - post_capture: 0, - switchfilter: 0, - ffmpeg_cap_new: 0, - ffmpeg_cap_motion: 0, - ffmpeg_bps: DEF_FFMPEG_BPS, - ffmpeg_vbr: DEF_FFMPEG_VBR, - ffmpeg_video_codec: DEF_FFMPEG_CODEC, - webcam_port: 0, - webcam_quality: 50, - webcam_motion: 0, - webcam_maxrate: 1, - webcam_localhost: 1, - webcam_limit: 0, - control_port: 0, - control_localhost: 1, - control_html_output: 1, - control_authentication:NULL, - frequency: 0, - tuner_number: 0, - timelapse: 0, - timelapse_mode: DEF_TIMELAPSE_MODE, + width: DEF_WIDTH, + height: DEF_HEIGHT, + quality: DEF_QUALITY, + rotate_deg: 0, + max_changes: DEF_CHANGES, + threshold_tune: 0, + output_normal: "on", + motion_img: 0, + output_all: 0, + gap: DEF_GAP, + maxmpegtime: DEF_MAXMPEGTIME, + snapshot_interval: 0, + locate: "off", + input: IN_DEFAULT, + norm: 0, + frame_limit: DEF_MAXFRAMERATE, + quiet: 1, + ppm: 0, + noise: DEF_NOISELEVEL, + noise_tune: 1, + minimum_frame_time: 0, + lightswitch: 0, + autobright: 0, + brightness: 0, + contrast: 0, + saturation: 0, + hue: 0, + roundrobin_frames: 1, + roundrobin_skip: 1, + pre_capture: 0, + post_capture: 0, + switchfilter: 0, + ffmpeg_cap_new: 0, + ffmpeg_cap_motion: 0, + ffmpeg_bps: DEF_FFMPEG_BPS, + ffmpeg_vbr: DEF_FFMPEG_VBR, + ffmpeg_video_codec: DEF_FFMPEG_CODEC, + webcam_port: 0, + webcam_quality: 50, + webcam_motion: 0, + webcam_maxrate: 1, + webcam_localhost: 1, + webcam_limit: 0, + control_port: 0, + control_localhost: 1, + control_html_output: 1, + control_authentication:NULL, + frequency: 0, + tuner_number: 0, + timelapse: 0, + timelapse_mode: DEF_TIMELAPSE_MODE, #if (defined(BSD)) - tuner_device: NULL, + tuner_device: NULL, #endif - video_device: VIDEO_DEVICE, - v4l2_palette: 8, - vidpipe: NULL, - filepath: NULL, - jpegpath: DEF_JPEGPATH, - mpegpath: DEF_MPEGPATH, - snappath: DEF_SNAPPATH, - timepath: DEF_TIMEPATH, - on_event_start: NULL, - on_event_end: NULL, - mask_file: NULL, - smart_mask_speed: 0, - sql_log_image: 1, - sql_log_snapshot: 1, - sql_log_mpeg: 0, - sql_log_timelapse: 0, - sql_query: DEF_SQL_QUERY, - mysql_db: NULL, - mysql_host: "localhost", - mysql_user: NULL, - mysql_password: NULL, - on_picture_save: NULL, - on_motion_detected: NULL, - on_area_detected: NULL, - on_movie_start: NULL, - on_movie_end: NULL, - on_camera_lost: NULL, - motionvidpipe: NULL, - netcam_url: NULL, - netcam_userpass: NULL, - netcam_http: "1.0", /* Choices: 1.0, 1.1, or keep_alive */ - netcam_proxy: NULL, - netcam_broken: 0, - pgsql_db: NULL, - pgsql_host: "localhost", - pgsql_user: NULL, - pgsql_password: NULL, - pgsql_port: 5432, - text_changes: 0, - text_left: NULL, - text_right: DEF_TIMESTAMP, - text_event: DEF_EVENTSTAMP, - text_double: 0, - despeckle: NULL, - area_detect: NULL, - minimum_motion_frames: 1, - pid_file: NULL, + video_device: VIDEO_DEVICE, + v4l2_palette: 8, + vidpipe: NULL, + filepath: NULL, + jpegpath: DEF_JPEGPATH, + mpegpath: DEF_MPEGPATH, + snappath: DEF_SNAPPATH, + timepath: DEF_TIMEPATH, + on_event_start: NULL, + on_event_end: NULL, + mask_file: NULL, + smart_mask_speed: 0, + sql_log_image: 1, + sql_log_snapshot: 1, + sql_log_mpeg: 0, + sql_log_timelapse: 0, + sql_query: DEF_SQL_QUERY, + mysql_db: NULL, + mysql_host: "localhost", + mysql_user: NULL, + mysql_password: NULL, + on_picture_save: NULL, + on_motion_detected: NULL, + on_area_detected: NULL, + on_movie_start: NULL, + on_movie_end: NULL, + on_camera_lost: NULL, + motionvidpipe: NULL, + netcam_url: NULL, + netcam_userpass: NULL, + netcam_http: "1.0", /* Choices: 1.0, 1.1, or keep_alive */ + netcam_proxy: NULL, + netcam_broken: 0, + pgsql_db: NULL, + pgsql_host: "localhost", + pgsql_user: NULL, + pgsql_password: NULL, + pgsql_port: 5432, + text_changes: 0, + text_left: NULL, + text_right: DEF_TIMESTAMP, + text_event: DEF_EVENTSTAMP, + text_double: 0, + despeckle: NULL, + area_detect: NULL, + minimum_motion_frames: 1, + pid_file: NULL, }; @@ -166,1193 +166,1193 @@ static void usage(void); /* Pointer magic to determine relative addresses of variables to a struct context pointer */ -#define CNT_OFFSET(varname) ( (int)&((struct context *)NULL)->varname ) -#define CONF_OFFSET(varname) ( (int)&((struct context *)NULL)->conf.varname ) -#define TRACK_OFFSET(varname) ( (int)&((struct context *)NULL)->track.varname ) +#define CNT_OFFSET(varname) ((int)&((struct context *)NULL)->varname) +#define CONF_OFFSET(varname) ((int)&((struct context *)NULL)->conf.varname) +#define TRACK_OFFSET(varname) ((int)&((struct context *)NULL)->track.varname) config_param config_params[] = { - { - "daemon", - "############################################################\n" - "# Daemon\n" - "############################################################\n\n" - "# Start in daemon (background) mode and release terminal (default: off)", - 1, - CNT_OFFSET(daemon), - copy_bool, - print_bool - }, - { - "process_id_file", - "#File to store the process ID, also called pid file. (default: not defined)", - 1, - CONF_OFFSET(pid_file), - copy_string, - print_string - }, - { - "setup_mode", - "############################################################\n" - "# Basic Setup Mode\n" - "############################################################\n\n" - "# Start in Setup-Mode, daemon disabled. (default: off)", - 0, - CONF_OFFSET(setup_mode), - copy_bool, - print_bool - }, - { - "videodevice", - "\n###########################################################\n" - "# Capture device options\n" - "############################################################\n\n" - "# Videodevice to be used for capturing (default /dev/video0)\n" - "# for FreeBSD default is /dev/bktr0", - 0, - CONF_OFFSET(video_device), - copy_string, - print_string - }, - { - "v4l2_palette", - "# v4l2_palette allow to choose preferable palette to be use by motion\n" - "# to capture from those supported by your videodevice. ( default: 8)\n" - "# i.ex if your videodevice supports V4L2_PIX_FMT_SBGGR8 and\n" - "# V4L2_PIX_FMT_MJPEG by default motion will use V4L2_PIX_FMT_MJPEG so\n" - "# set v4l2_palette 1 to force motion use V4L2_PIX_FMT_SBGGR8 instead.\n" - "#\n" - "# Values :\n" - "#\n" - "# V4L2_PIX_FMT_SN9C10X : 0 'S910'\n" - "# V4L2_PIX_FMT_SBGGR8 : 1 'BA81'\n" - "# V4L2_PIX_FMT_MJPEG : 2 'MJPEG'\n" - "# V4L2_PIX_FMT_JPEG : 3 'JPEG'\n" - "# V4L2_PIX_FMT_RGB24 : 4 'RGB3'\n" - "# V4L2_PIX_FMT_UYVY : 5 'UYVY'\n" - "# V4L2_PIX_FMT_YUYV : 6 'YUYV'\n" - "# V4L2_PIX_FMT_YUV422P : 7 '422P'\n" - "# V4L2_PIX_FMT_YUV420 : 8 'YU12'", - 0, - CONF_OFFSET(v4l2_palette), - copy_short, - print_short - }, + { + "daemon", + "############################################################\n" + "# Daemon\n" + "############################################################\n\n" + "# Start in daemon (background) mode and release terminal (default: off)", + 1, + CNT_OFFSET(daemon), + copy_bool, + print_bool + }, + { + "process_id_file", + "#File to store the process ID, also called pid file. (default: not defined)", + 1, + CONF_OFFSET(pid_file), + copy_string, + print_string + }, + { + "setup_mode", + "############################################################\n" + "# Basic Setup Mode\n" + "############################################################\n\n" + "# Start in Setup-Mode, daemon disabled. (default: off)", + 0, + CONF_OFFSET(setup_mode), + copy_bool, + print_bool + }, + { + "videodevice", + "\n###########################################################\n" + "# Capture device options\n" + "############################################################\n\n" + "# Videodevice to be used for capturing (default /dev/video0)\n" + "# for FreeBSD default is /dev/bktr0", + 0, + CONF_OFFSET(video_device), + copy_string, + print_string + }, + { + "v4l2_palette", + "# v4l2_palette allow to choose preferable palette to be use by motion\n" + "# to capture from those supported by your videodevice. ( default: 8)\n" + "# i.ex if your videodevice supports V4L2_PIX_FMT_SBGGR8 and\n" + "# V4L2_PIX_FMT_MJPEG by default motion will use V4L2_PIX_FMT_MJPEG so\n" + "# set v4l2_palette 1 to force motion use V4L2_PIX_FMT_SBGGR8 instead.\n" + "#\n" + "# Values :\n" + "#\n" + "# V4L2_PIX_FMT_SN9C10X : 0 'S910'\n" + "# V4L2_PIX_FMT_SBGGR8 : 1 'BA81'\n" + "# V4L2_PIX_FMT_MJPEG : 2 'MJPEG'\n" + "# V4L2_PIX_FMT_JPEG : 3 'JPEG'\n" + "# V4L2_PIX_FMT_RGB24 : 4 'RGB3'\n" + "# V4L2_PIX_FMT_UYVY : 5 'UYVY'\n" + "# V4L2_PIX_FMT_YUYV : 6 'YUYV'\n" + "# V4L2_PIX_FMT_YUV422P : 7 '422P'\n" + "# V4L2_PIX_FMT_YUV420 : 8 'YU12'", + 0, + CONF_OFFSET(v4l2_palette), + copy_short, + print_short + }, #if (defined(BSD)) - { - "tunerdevice", - "# Tuner device to be used for capturing using tuner as source (default /dev/tuner0)\n" - "# This is ONLY used for FreeBSD. Leave it commented out for Linux", - 0, - CONF_OFFSET(tuner_device), - copy_string, - print_string - }, + { + "tunerdevice", + "# Tuner device to be used for capturing using tuner as source (default /dev/tuner0)\n" + "# This is ONLY used for FreeBSD. Leave it commented out for Linux", + 0, + CONF_OFFSET(tuner_device), + copy_string, + print_string + }, #endif - { - "input", - "# The video input to be used (default: 8)\n" - "# Should normally be set to 0 or 1 for video/TV cards, and 8 for USB cameras", - 0, - CONF_OFFSET(input), - copy_int, - print_int - }, - { - "norm", - "# The video norm to use (only for video capture and TV tuner cards)\n" - "# Values: 0 (PAL), 1 (NTSC), 2 (SECAM), 3 (PAL NC no colour). Default: 0 (PAL)", - 0, - CONF_OFFSET(norm), - copy_int, - print_int - }, - { - "frequency", - "# The frequency to set the tuner to (kHz) (only for TV tuner cards) (default: 0)", - 0, - CONF_OFFSET(frequency), - copy_int, - print_int - }, - { - "rotate", - "# Rotate image this number of degrees. The rotation affects all saved images as\n" - "# well as mpeg movies. Valid values: 0 (default = no rotation), 90, 180 and 270.", - 0, - CONF_OFFSET(rotate_deg), - copy_int, - print_int - }, - { - "width", - "# Image width (pixels). Valid range: Camera dependent, default: 352", - 0, - CONF_OFFSET(width), - copy_int, - print_int - }, - { - "height", - "# Image height (pixels). Valid range: Camera dependent, default: 288", - 0, - CONF_OFFSET(height), - copy_int, - print_int - }, - { - "framerate", - "# Maximum number of frames to be captured per second.\n" - "# Valid range: 2-100. Default: 100 (almost no limit).", - 0, - CONF_OFFSET(frame_limit), - copy_int, - print_int - }, - { - "minimum_frame_time", - "# Minimum time in seconds between capturing picture frames from the camera.\n" - "# Default: 0 = disabled - the capture rate is given by the camera framerate.\n" - "# This option is used when you want to capture images at a rate lower than 2 per second.", - 0, - CONF_OFFSET(minimum_frame_time), - copy_int, - print_int - }, - { - "netcam_url", - "# URL to use if you are using a network camera, size will be autodetected (incl http:// ftp:// or file:///)\n" - "# Must be a URL that returns single jpeg pictures or a raw mjpeg stream. Default: Not defined", - 0, - CONF_OFFSET(netcam_url), - copy_string, - print_string - }, - { - "netcam_userpass", - "# Username and password for network camera (only if required). Default: not defined\n" - "# Syntax is user:password", - 0, - CONF_OFFSET(netcam_userpass), - copy_string, - print_string - }, - { - "netcam_http", - "# The setting for keep-alive of network socket, should improve performance on compatible net cameras.\n" - "# 1.0 : the historical implementation using HTTP/1.0, closing the socket after each http request.\n" - "# keep_alive : Use HTTP/1.0 requests with keep alive header to reuse the same connection.\n" - "# 1.1 : Use HTTP/1.1 requests that support keep alive as default.\n" - "# Default: 1.0", - 0, - CONF_OFFSET(netcam_http), - copy_string, - print_string - }, - { - "netcam_proxy", - "# URL to use for a netcam proxy server, if required, e.g. \"http://myproxy\".\n" - "# If a port number other than 80 is needed, use \"http://myproxy:1234\".\n" - "# Default: not defined", - 0, - CONF_OFFSET(netcam_proxy), - copy_string, - print_string - }, - { - "netcam_broken", - "# Set less strict jpeg checks for network cameras with a poor/buggy firmware.\n" - "# Default: off", - 0, - CONF_OFFSET(netcam_broken), - copy_bool, - print_bool - }, - { - "auto_brightness", - "# Let motion regulate the brightness of a video device (default: off).\n" - "# The auto_brightness feature uses the brightness option as its target value.\n" - "# If brightness is zero auto_brightness will adjust to average brightness value 128.\n" - "# Only recommended for cameras without auto brightness", - 0, - CONF_OFFSET(autobright), - copy_bool, - print_bool - }, - { - "brightness", - "# Set the initial brightness of a video device.\n" - "# If auto_brightness is enabled, this value defines the average brightness level\n" - "# which Motion will try and adjust to.\n" - "# Valid range 0-255, default 0 = disabled", - 0, - CONF_OFFSET(brightness), - copy_int, - print_int - }, - { - "contrast", - "# Set the contrast of a video device.\n" - "# Valid range 0-255, default 0 = disabled", - 0, - CONF_OFFSET(contrast), - copy_int, - print_int - }, - { - "saturation", - "# Set the saturation of a video device.\n" - "# Valid range 0-255, default 0 = disabled", - 0, - CONF_OFFSET(saturation), - copy_int, - print_int - }, - { - "hue", - "# Set the hue of a video device (NTSC feature).\n" - "# Valid range 0-255, default 0 = disabled", - 0, - CONF_OFFSET(hue), - copy_int, - print_int - }, - { - "roundrobin_frames", - "\n############################################################\n" - "# Round Robin (multiple inputs on same video device name)\n" - "############################################################\n\n" - "# Number of frames to capture in each roundrobin step (default: 1)", - 0, - CONF_OFFSET(roundrobin_frames), - copy_int, - print_int - }, - { - "roundrobin_skip", - "# Number of frames to skip before each roundrobin step (default: 1)", - 0, - CONF_OFFSET(roundrobin_skip), - copy_int, - print_int - }, - { - "switchfilter", - "# Try to filter out noise generated by roundrobin (default: off)", - 0, - CONF_OFFSET(switchfilter), - copy_bool, - print_bool - }, - { - "threshold", - "\n############################################################\n" - "# Motion Detection Settings:\n" - "############################################################\n\n" - "# Threshold for number of changed pixels in an image that\n" - "# triggers motion detection (default: 1500)", - 0, - CONF_OFFSET(max_changes), - copy_int, - print_int - }, - { - "threshold_tune", - "# Automatically tune the threshold down if possible (default: off)", - 0, - CONF_OFFSET(threshold_tune), - copy_bool, - print_bool - }, - { - "noise_level", - "# Noise threshold for the motion detection (default: 32)", - 0, - CONF_OFFSET(noise), - copy_int, - print_int - }, - { - "noise_tune", - "# Automatically tune the noise threshold (default: on)", - 0, - CONF_OFFSET(noise_tune), - copy_bool, - print_bool - }, - { - "despeckle", - "# Despeckle motion image using (e)rode or (d)ilate or (l)abel (Default: not defined)\n" - "# Recommended value is EedDl. Any combination (and number of) of E, e, d, and D is valid.\n" - "# (l)abeling must only be used once and the 'l' must be the last letter.\n" - "# Comment out to disable", - 0, - CONF_OFFSET(despeckle), - copy_string, - print_string - }, - { - "area_detect", - "# Detect motion in predefined areas (1 - 9). Areas are numbered like that: 1 2 3\n" - "# A script (on_area_detected) is started immediately when motion is 4 5 6\n" - "# detected in one of the given areas, but only once during an event. 7 8 9\n" - "# One or more areas can be specified with this option. (Default: not defined)", - 0, - CONF_OFFSET(area_detect), - copy_string, - print_string - }, - { - "mask_file", - "# PGM file to use as a sensitivity mask.\n" - "# Full path name to. (Default: not defined)", - 0, - CONF_OFFSET(mask_file), - copy_string, - print_string - }, - { - "smart_mask_speed", - "# Dynamically create a mask file during operation (default: 0)\n" - "# Adjust speed of mask changes from 0 (off) to 10 (fast)", - 0, - CONF_OFFSET(smart_mask_speed), - copy_int, - print_int - }, - { - "lightswitch", - "# Ignore sudden massive light intensity changes given as a percentage of the picture\n" - "# area that changed intensity. Valid range: 0 - 100 , default: 0 = disabled", - 0, - CONF_OFFSET(lightswitch), - copy_int, - print_int - }, - { - "minimum_motion_frames", - "# Picture frames must contain motion at least the specified number of frames\n" - "# in a row before they are detected as true motion. At the default of 1, all\n" - "# motion is detected. Valid range: 1 to thousands, recommended 1-5", - 0, - CONF_OFFSET(minimum_motion_frames), - copy_int, - print_int - }, - { - "pre_capture", - "# Specifies the number of pre-captured (buffered) pictures from before motion\n" - "# was detected that will be output at motion detection.\n" - "# Recommended range: 0 to 5 (default: 0)\n" - "# Do not use large values! Large values will cause Motion to skip video frames and\n" - "# cause unsmooth mpegs. To smooth mpegs use larger values of post_capture instead.", - 0, - CONF_OFFSET(pre_capture), - copy_int, - print_int - }, - { - "post_capture", - "# Number of frames to capture after motion is no longer detected (default: 0)", - 0, - CONF_OFFSET(post_capture), - copy_int, - print_int - }, - { - "gap", - "# Gap is the seconds of no motion detection that triggers the end of an event\n" - "# An event is defined as a series of motion images taken within a short timeframe.\n" - "# Recommended value is 60 seconds (Default). The value 0 is allowed and disables\n" - "# events causing all Motion to be written to one single mpeg file and no pre_capture.", - 0, - CONF_OFFSET(gap), - copy_int, - print_int - }, - { - "max_mpeg_time", - "# Maximum length in seconds of an mpeg movie\n" - "# When value is exceeded a new mpeg file is created. (Default: 0 = infinite)", - 0, - CONF_OFFSET(maxmpegtime), - copy_int, - print_int - }, - { - "output_all", - "# Always save images even if there was no motion (default: off)", - 0, - CONF_OFFSET(output_all), - copy_bool, - print_bool - }, - { - "output_normal", - "\n############################################################\n" - "# Image File Output\n" - "############################################################\n\n" - "# Output 'normal' pictures when motion is detected (default: on)\n" - "# Valid values: on, off, first, best, center\n" - "# When set to 'first', only the first picture of an event is saved.\n" - "# Picture with most motion of an event is saved when set to 'best'.\n" - "# Picture with motion nearest center of picture is saved when set to 'center'.\n" - "# Can be used as preview shot for the corresponding movie.", - 0, - CONF_OFFSET(output_normal), - copy_string, - print_string - }, - { - "output_motion", - "# Output pictures with only the pixels moving object (ghost images) (default: off)", - 0, - CONF_OFFSET(motion_img), - copy_bool, - print_bool - }, - { - "quality", - "# The quality (in percent) to be used by the jpeg compression (default: 75)", - 0, - CONF_OFFSET(quality), - copy_int, - print_int - }, - { - "ppm", - "# Output ppm images instead of jpeg (default: off)", - 0, - CONF_OFFSET(ppm), - copy_bool, - print_bool - }, + { + "input", + "# The video input to be used (default: 8)\n" + "# Should normally be set to 0 or 1 for video/TV cards, and 8 for USB cameras", + 0, + CONF_OFFSET(input), + copy_int, + print_int + }, + { + "norm", + "# The video norm to use (only for video capture and TV tuner cards)\n" + "# Values: 0 (PAL), 1 (NTSC), 2 (SECAM), 3 (PAL NC no colour). Default: 0 (PAL)", + 0, + CONF_OFFSET(norm), + copy_int, + print_int + }, + { + "frequency", + "# The frequency to set the tuner to (kHz) (only for TV tuner cards) (default: 0)", + 0, + CONF_OFFSET(frequency), + copy_int, + print_int + }, + { + "rotate", + "# Rotate image this number of degrees. The rotation affects all saved images as\n" + "# well as mpeg movies. Valid values: 0 (default = no rotation), 90, 180 and 270.", + 0, + CONF_OFFSET(rotate_deg), + copy_int, + print_int + }, + { + "width", + "# Image width (pixels). Valid range: Camera dependent, default: 352", + 0, + CONF_OFFSET(width), + copy_int, + print_int + }, + { + "height", + "# Image height (pixels). Valid range: Camera dependent, default: 288", + 0, + CONF_OFFSET(height), + copy_int, + print_int + }, + { + "framerate", + "# Maximum number of frames to be captured per second.\n" + "# Valid range: 2-100. Default: 100 (almost no limit).", + 0, + CONF_OFFSET(frame_limit), + copy_int, + print_int + }, + { + "minimum_frame_time", + "# Minimum time in seconds between capturing picture frames from the camera.\n" + "# Default: 0 = disabled - the capture rate is given by the camera framerate.\n" + "# This option is used when you want to capture images at a rate lower than 2 per second.", + 0, + CONF_OFFSET(minimum_frame_time), + copy_int, + print_int + }, + { + "netcam_url", + "# URL to use if you are using a network camera, size will be autodetected (incl http:// ftp:// or file:///)\n" + "# Must be a URL that returns single jpeg pictures or a raw mjpeg stream. Default: Not defined", + 0, + CONF_OFFSET(netcam_url), + copy_string, + print_string + }, + { + "netcam_userpass", + "# Username and password for network camera (only if required). Default: not defined\n" + "# Syntax is user:password", + 0, + CONF_OFFSET(netcam_userpass), + copy_string, + print_string + }, + { + "netcam_http", + "# The setting for keep-alive of network socket, should improve performance on compatible net cameras.\n" + "# 1.0 : the historical implementation using HTTP/1.0, closing the socket after each http request.\n" + "# keep_alive : Use HTTP/1.0 requests with keep alive header to reuse the same connection.\n" + "# 1.1 : Use HTTP/1.1 requests that support keep alive as default.\n" + "# Default: 1.0", + 0, + CONF_OFFSET(netcam_http), + copy_string, + print_string + }, + { + "netcam_proxy", + "# URL to use for a netcam proxy server, if required, e.g. \"http://myproxy\".\n" + "# If a port number other than 80 is needed, use \"http://myproxy:1234\".\n" + "# Default: not defined", + 0, + CONF_OFFSET(netcam_proxy), + copy_string, + print_string + }, + { + "netcam_broken", + "# Set less strict jpeg checks for network cameras with a poor/buggy firmware.\n" + "# Default: off", + 0, + CONF_OFFSET(netcam_broken), + copy_bool, + print_bool + }, + { + "auto_brightness", + "# Let motion regulate the brightness of a video device (default: off).\n" + "# The auto_brightness feature uses the brightness option as its target value.\n" + "# If brightness is zero auto_brightness will adjust to average brightness value 128.\n" + "# Only recommended for cameras without auto brightness", + 0, + CONF_OFFSET(autobright), + copy_bool, + print_bool + }, + { + "brightness", + "# Set the initial brightness of a video device.\n" + "# If auto_brightness is enabled, this value defines the average brightness level\n" + "# which Motion will try and adjust to.\n" + "# Valid range 0-255, default 0 = disabled", + 0, + CONF_OFFSET(brightness), + copy_int, + print_int + }, + { + "contrast", + "# Set the contrast of a video device.\n" + "# Valid range 0-255, default 0 = disabled", + 0, + CONF_OFFSET(contrast), + copy_int, + print_int + }, + { + "saturation", + "# Set the saturation of a video device.\n" + "# Valid range 0-255, default 0 = disabled", + 0, + CONF_OFFSET(saturation), + copy_int, + print_int + }, + { + "hue", + "# Set the hue of a video device (NTSC feature).\n" + "# Valid range 0-255, default 0 = disabled", + 0, + CONF_OFFSET(hue), + copy_int, + print_int + }, + { + "roundrobin_frames", + "\n############################################################\n" + "# Round Robin (multiple inputs on same video device name)\n" + "############################################################\n\n" + "# Number of frames to capture in each roundrobin step (default: 1)", + 0, + CONF_OFFSET(roundrobin_frames), + copy_int, + print_int + }, + { + "roundrobin_skip", + "# Number of frames to skip before each roundrobin step (default: 1)", + 0, + CONF_OFFSET(roundrobin_skip), + copy_int, + print_int + }, + { + "switchfilter", + "# Try to filter out noise generated by roundrobin (default: off)", + 0, + CONF_OFFSET(switchfilter), + copy_bool, + print_bool + }, + { + "threshold", + "\n############################################################\n" + "# Motion Detection Settings:\n" + "############################################################\n\n" + "# Threshold for number of changed pixels in an image that\n" + "# triggers motion detection (default: 1500)", + 0, + CONF_OFFSET(max_changes), + copy_int, + print_int + }, + { + "threshold_tune", + "# Automatically tune the threshold down if possible (default: off)", + 0, + CONF_OFFSET(threshold_tune), + copy_bool, + print_bool + }, + { + "noise_level", + "# Noise threshold for the motion detection (default: 32)", + 0, + CONF_OFFSET(noise), + copy_int, + print_int + }, + { + "noise_tune", + "# Automatically tune the noise threshold (default: on)", + 0, + CONF_OFFSET(noise_tune), + copy_bool, + print_bool + }, + { + "despeckle", + "# Despeckle motion image using (e)rode or (d)ilate or (l)abel (Default: not defined)\n" + "# Recommended value is EedDl. Any combination (and number of) of E, e, d, and D is valid.\n" + "# (l)abeling must only be used once and the 'l' must be the last letter.\n" + "# Comment out to disable", + 0, + CONF_OFFSET(despeckle), + copy_string, + print_string + }, + { + "area_detect", + "# Detect motion in predefined areas (1 - 9). Areas are numbered like that: 1 2 3\n" + "# A script (on_area_detected) is started immediately when motion is 4 5 6\n" + "# detected in one of the given areas, but only once during an event. 7 8 9\n" + "# One or more areas can be specified with this option. (Default: not defined)", + 0, + CONF_OFFSET(area_detect), + copy_string, + print_string + }, + { + "mask_file", + "# PGM file to use as a sensitivity mask.\n" + "# Full path name to. (Default: not defined)", + 0, + CONF_OFFSET(mask_file), + copy_string, + print_string + }, + { + "smart_mask_speed", + "# Dynamically create a mask file during operation (default: 0)\n" + "# Adjust speed of mask changes from 0 (off) to 10 (fast)", + 0, + CONF_OFFSET(smart_mask_speed), + copy_int, + print_int + }, + { + "lightswitch", + "# Ignore sudden massive light intensity changes given as a percentage of the picture\n" + "# area that changed intensity. Valid range: 0 - 100 , default: 0 = disabled", + 0, + CONF_OFFSET(lightswitch), + copy_int, + print_int + }, + { + "minimum_motion_frames", + "# Picture frames must contain motion at least the specified number of frames\n" + "# in a row before they are detected as true motion. At the default of 1, all\n" + "# motion is detected. Valid range: 1 to thousands, recommended 1-5", + 0, + CONF_OFFSET(minimum_motion_frames), + copy_int, + print_int + }, + { + "pre_capture", + "# Specifies the number of pre-captured (buffered) pictures from before motion\n" + "# was detected that will be output at motion detection.\n" + "# Recommended range: 0 to 5 (default: 0)\n" + "# Do not use large values! Large values will cause Motion to skip video frames and\n" + "# cause unsmooth mpegs. To smooth mpegs use larger values of post_capture instead.", + 0, + CONF_OFFSET(pre_capture), + copy_int, + print_int + }, + { + "post_capture", + "# Number of frames to capture after motion is no longer detected (default: 0)", + 0, + CONF_OFFSET(post_capture), + copy_int, + print_int + }, + { + "gap", + "# Gap is the seconds of no motion detection that triggers the end of an event\n" + "# An event is defined as a series of motion images taken within a short timeframe.\n" + "# Recommended value is 60 seconds (Default). The value 0 is allowed and disables\n" + "# events causing all Motion to be written to one single mpeg file and no pre_capture.", + 0, + CONF_OFFSET(gap), + copy_int, + print_int + }, + { + "max_mpeg_time", + "# Maximum length in seconds of an mpeg movie\n" + "# When value is exceeded a new mpeg file is created. (Default: 0 = infinite)", + 0, + CONF_OFFSET(maxmpegtime), + copy_int, + print_int + }, + { + "output_all", + "# Always save images even if there was no motion (default: off)", + 0, + CONF_OFFSET(output_all), + copy_bool, + print_bool + }, + { + "output_normal", + "\n############################################################\n" + "# Image File Output\n" + "############################################################\n\n" + "# Output 'normal' pictures when motion is detected (default: on)\n" + "# Valid values: on, off, first, best, center\n" + "# When set to 'first', only the first picture of an event is saved.\n" + "# Picture with most motion of an event is saved when set to 'best'.\n" + "# Picture with motion nearest center of picture is saved when set to 'center'.\n" + "# Can be used as preview shot for the corresponding movie.", + 0, + CONF_OFFSET(output_normal), + copy_string, + print_string + }, + { + "output_motion", + "# Output pictures with only the pixels moving object (ghost images) (default: off)", + 0, + CONF_OFFSET(motion_img), + copy_bool, + print_bool + }, + { + "quality", + "# The quality (in percent) to be used by the jpeg compression (default: 75)", + 0, + CONF_OFFSET(quality), + copy_int, + print_int + }, + { + "ppm", + "# Output ppm images instead of jpeg (default: off)", + 0, + CONF_OFFSET(ppm), + copy_bool, + print_bool + }, #ifdef HAVE_FFMPEG - { - "ffmpeg_cap_new", - "\n############################################################\n" - "# FFMPEG related options\n" - "# Film (mpeg) file output, and deinterlacing of the video input\n" - "# The options movie_filename and timelapse_filename are also used\n" - "# by the ffmpeg feature\n" - "############################################################\n\n" - "# Use ffmpeg to encode mpeg movies in realtime (default: off)", - 0, - CONF_OFFSET(ffmpeg_cap_new), - copy_bool, - print_bool - }, - { - "ffmpeg_cap_motion", - "# Use ffmpeg to make movies with only the pixels moving\n" - "# object (ghost images) (default: off)", - 0, - CONF_OFFSET(ffmpeg_cap_motion), - copy_bool, - print_bool - }, - { - "ffmpeg_timelapse", - "# Use ffmpeg to encode a timelapse movie\n" - "# Default value 0 = off - else save frame every Nth second", - 0, - CONF_OFFSET(timelapse), - copy_int, - print_int - }, - { - "ffmpeg_timelapse_mode", - "# The file rollover mode of the timelapse video\n" - "# Valid values: hourly, daily (default), weekly-sunday, weekly-monday, monthly, manual", - 0, - CONF_OFFSET(timelapse_mode), - copy_string, - print_string - }, - { - "ffmpeg_bps", - "# Bitrate to be used by the ffmpeg encoder (default: 400000)\n" - "# This option is ignored if ffmpeg_variable_bitrate is not 0 (disabled)", - 0, - CONF_OFFSET(ffmpeg_bps), - copy_int, - print_int - }, - { - "ffmpeg_variable_bitrate", - "# Enables and defines variable bitrate for the ffmpeg encoder.\n" - "# ffmpeg_bps is ignored if variable bitrate is enabled.\n" - "# Valid values: 0 (default) = fixed bitrate defined by ffmpeg_bps,\n" - "# or the range 2 - 31 where 2 means best quality and 31 is worst.", - 0, - CONF_OFFSET(ffmpeg_vbr), - copy_int, - print_int - }, - { - "ffmpeg_video_codec", - "# Codec to used by ffmpeg for the video compression.\n" - "# Timelapse mpegs are always made in mpeg1 format independent from this option.\n" - "# Supported formats are: mpeg1 (ffmpeg-0.4.8 only), mpeg4 (default), and msmpeg4.\n" - "# mpeg1 - gives you files with extension .mpg\n" - "# mpeg4 or msmpeg4 - gives you files with extension .avi\n" - "# msmpeg4 is recommended for use with Windows Media Player because\n" - "# it requires no installation of codec on the Windows client.\n" - "# swf - gives you a flash film with extension .swf\n" - "# flv - gives you a flash video with extension .flv\n" - "# ffv1 - FF video codec 1 for Lossless Encoding ( experimental )\n" - "# mov - QuickTime ( testing )", - 0, - CONF_OFFSET(ffmpeg_video_codec), - copy_string, - print_string - }, - { - "ffmpeg_deinterlace", - "# Use ffmpeg to deinterlace video. Necessary if you use an analog camera\n" - "# and see horizontal combing on moving objects in video or pictures.\n" - "# (default: off)", - 0, - CONF_OFFSET(ffmpeg_deinterlace), - copy_bool, - print_bool - }, + { + "ffmpeg_cap_new", + "\n############################################################\n" + "# FFMPEG related options\n" + "# Film (mpeg) file output, and deinterlacing of the video input\n" + "# The options movie_filename and timelapse_filename are also used\n" + "# by the ffmpeg feature\n" + "############################################################\n\n" + "# Use ffmpeg to encode mpeg movies in realtime (default: off)", + 0, + CONF_OFFSET(ffmpeg_cap_new), + copy_bool, + print_bool + }, + { + "ffmpeg_cap_motion", + "# Use ffmpeg to make movies with only the pixels moving\n" + "# object (ghost images) (default: off)", + 0, + CONF_OFFSET(ffmpeg_cap_motion), + copy_bool, + print_bool + }, + { + "ffmpeg_timelapse", + "# Use ffmpeg to encode a timelapse movie\n" + "# Default value 0 = off - else save frame every Nth second", + 0, + CONF_OFFSET(timelapse), + copy_int, + print_int + }, + { + "ffmpeg_timelapse_mode", + "# The file rollover mode of the timelapse video\n" + "# Valid values: hourly, daily (default), weekly-sunday, weekly-monday, monthly, manual", + 0, + CONF_OFFSET(timelapse_mode), + copy_string, + print_string + }, + { + "ffmpeg_bps", + "# Bitrate to be used by the ffmpeg encoder (default: 400000)\n" + "# This option is ignored if ffmpeg_variable_bitrate is not 0 (disabled)", + 0, + CONF_OFFSET(ffmpeg_bps), + copy_int, + print_int + }, + { + "ffmpeg_variable_bitrate", + "# Enables and defines variable bitrate for the ffmpeg encoder.\n" + "# ffmpeg_bps is ignored if variable bitrate is enabled.\n" + "# Valid values: 0 (default) = fixed bitrate defined by ffmpeg_bps,\n" + "# or the range 2 - 31 where 2 means best quality and 31 is worst.", + 0, + CONF_OFFSET(ffmpeg_vbr), + copy_int, + print_int + }, + { + "ffmpeg_video_codec", + "# Codec to used by ffmpeg for the video compression.\n" + "# Timelapse mpegs are always made in mpeg1 format independent from this option.\n" + "# Supported formats are: mpeg1 (ffmpeg-0.4.8 only), mpeg4 (default), and msmpeg4.\n" + "# mpeg1 - gives you files with extension .mpg\n" + "# mpeg4 or msmpeg4 - gives you files with extension .avi\n" + "# msmpeg4 is recommended for use with Windows Media Player because\n" + "# it requires no installation of codec on the Windows client.\n" + "# swf - gives you a flash film with extension .swf\n" + "# flv - gives you a flash video with extension .flv\n" + "# ffv1 - FF video codec 1 for Lossless Encoding ( experimental )\n" + "# mov - QuickTime ( testing )", + 0, + CONF_OFFSET(ffmpeg_video_codec), + copy_string, + print_string + }, + { + "ffmpeg_deinterlace", + "# Use ffmpeg to deinterlace video. Necessary if you use an analog camera\n" + "# and see horizontal combing on moving objects in video or pictures.\n" + "# (default: off)", + 0, + CONF_OFFSET(ffmpeg_deinterlace), + copy_bool, + print_bool + }, #endif /* HAVE_FFMPEG */ - { - "snapshot_interval", - "\n############################################################\n" - "# Snapshots (Traditional Periodic Webcam File Output)\n" - "############################################################\n\n" - "# Make automated snapshot every N seconds (default: 0 = disabled)", - 0, - CONF_OFFSET(snapshot_interval), - copy_int, - print_int - }, - { - "locate", - "\n############################################################\n" - "# Text Display\n" - "# %Y = year, %m = month, %d = date,\n" - "# %H = hour, %M = minute, %S = second, %T = HH:MM:SS,\n" - "# %v = event, %q = frame number, %t = thread (camera) number,\n" - "# %D = changed pixels, %N = noise level, \\n = new line,\n" - "# %i and %J = width and height of motion area,\n" - "# %K and %L = X and Y coordinates of motion center\n" - "# %C = value defined by text_event - do not use with text_event!\n" - "# You can put quotation marks around the text to allow\n" - "# leading spaces\n" - "############################################################\n\n" - "# Locate and draw a box around the moving object.\n" - "# Valid values: on, off and preview (default: off)\n" - "# Set to 'preview' will only draw a box in preview_shot pictures.", - 0, - CONF_OFFSET(locate), - copy_string, - print_string - }, - { - "text_right", - "# Draws the timestamp using same options as C function strftime(3)\n" - "# Default: %Y-%m-%d\\n%T = date in ISO format and time in 24 hour clock\n" - "# Text is placed in lower right corner", - 0, - CONF_OFFSET(text_right), - copy_string, - print_string - }, - { - "text_left", - "# Draw a user defined text on the images using same options as C function strftime(3)\n" - "# Default: Not defined = no text\n" - "# Text is placed in lower left corner", - 0, - CONF_OFFSET(text_left), - copy_string, - print_string - }, - { - "text_changes", - "# Draw the number of changed pixed on the images (default: off)\n" - "# Will normally be set to off except when you setup and adjust the motion settings\n" - "# Text is placed in upper right corner", - 0, - CONF_OFFSET(text_changes), - copy_bool, - print_bool - }, - { - "text_event", - "# This option defines the value of the special event conversion specifier %C\n" - "# You can use any conversion specifier in this option except %C. Date and time\n" - "# values are from the timestamp of the first image in the current event.\n" - "# Default: %Y%m%d%H%M%S\n" - "# The idea is that %C can be used filenames and text_left/right for creating\n" - "# a unique identifier for each event.", - 0, - CONF_OFFSET(text_event), - copy_string, - print_string - }, - { - "text_double", - "# Draw characters at twice normal size on images. (default: off)", - 0, - CONF_OFFSET(text_double), - copy_bool, - print_bool - }, - { - "target_dir", - "\n############################################################\n" - "# Target Directories and filenames For Images And Films\n" - "# For the options snapshot_, jpeg_, mpeg_ and timelapse_filename\n" - "# you can use conversion specifiers\n" - "# %Y = year, %m = month, %d = date,\n" - "# %H = hour, %M = minute, %S = second,\n" - "# %v = event, %q = frame number, %t = thread (camera) number,\n" - "# %D = changed pixels, %N = noise level,\n" - "# %i and %J = width and height of motion area,\n" - "# %K and %L = X and Y coordinates of motion center\n" - "# %C = value defined by text_event\n" - "# Quotation marks round string are allowed.\n" - "############################################################\n\n" - "# Target base directory for pictures and films\n" - "# Recommended to use absolute path. (Default: current working directory)", - 0, - CONF_OFFSET(filepath), - copy_string, - print_string - }, - { - "snapshot_filename", - "# File path for snapshots (jpeg or ppm) relative to target_dir\n" - "# Default: "DEF_SNAPPATH"\n" - "# Default value is equivalent to legacy oldlayout option\n" - "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-snapshot\n" - "# File extension .jpg or .ppm is automatically added so do not include this.\n" - "# Note: A symbolic link called lastsnap.jpg created in the target_dir will always\n" - "# point to the latest snapshot, unless snapshot_filename is exactly 'lastsnap'", - 0, - CONF_OFFSET(snappath), - copy_string, - print_string - }, - { - "jpeg_filename", - "# File path for motion triggered images (jpeg or ppm) relative to target_dir\n" - "# Default: "DEF_JPEGPATH"\n" - "# Default value is equivalent to legacy oldlayout option\n" - "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q\n" - "# File extension .jpg or .ppm is automatically added so do not include this\n" - "# Set to 'preview' together with best-preview feature enables special naming\n" - "# convention for preview shots. See motion guide for details", - 0, - CONF_OFFSET(jpegpath), - copy_string, - print_string - }, + { + "snapshot_interval", + "\n############################################################\n" + "# Snapshots (Traditional Periodic Webcam File Output)\n" + "############################################################\n\n" + "# Make automated snapshot every N seconds (default: 0 = disabled)", + 0, + CONF_OFFSET(snapshot_interval), + copy_int, + print_int + }, + { + "locate", + "\n############################################################\n" + "# Text Display\n" + "# %Y = year, %m = month, %d = date,\n" + "# %H = hour, %M = minute, %S = second, %T = HH:MM:SS,\n" + "# %v = event, %q = frame number, %t = thread (camera) number,\n" + "# %D = changed pixels, %N = noise level, \\n = new line,\n" + "# %i and %J = width and height of motion area,\n" + "# %K and %L = X and Y coordinates of motion center\n" + "# %C = value defined by text_event - do not use with text_event!\n" + "# You can put quotation marks around the text to allow\n" + "# leading spaces\n" + "############################################################\n\n" + "# Locate and draw a box around the moving object.\n" + "# Valid values: on, off and preview (default: off)\n" + "# Set to 'preview' will only draw a box in preview_shot pictures.", + 0, + CONF_OFFSET(locate), + copy_string, + print_string + }, + { + "text_right", + "# Draws the timestamp using same options as C function strftime(3)\n" + "# Default: %Y-%m-%d\\n%T = date in ISO format and time in 24 hour clock\n" + "# Text is placed in lower right corner", + 0, + CONF_OFFSET(text_right), + copy_string, + print_string + }, + { + "text_left", + "# Draw a user defined text on the images using same options as C function strftime(3)\n" + "# Default: Not defined = no text\n" + "# Text is placed in lower left corner", + 0, + CONF_OFFSET(text_left), + copy_string, + print_string + }, + { + "text_changes", + "# Draw the number of changed pixed on the images (default: off)\n" + "# Will normally be set to off except when you setup and adjust the motion settings\n" + "# Text is placed in upper right corner", + 0, + CONF_OFFSET(text_changes), + copy_bool, + print_bool + }, + { + "text_event", + "# This option defines the value of the special event conversion specifier %C\n" + "# You can use any conversion specifier in this option except %C. Date and time\n" + "# values are from the timestamp of the first image in the current event.\n" + "# Default: %Y%m%d%H%M%S\n" + "# The idea is that %C can be used filenames and text_left/right for creating\n" + "# a unique identifier for each event.", + 0, + CONF_OFFSET(text_event), + copy_string, + print_string + }, + { + "text_double", + "# Draw characters at twice normal size on images. (default: off)", + 0, + CONF_OFFSET(text_double), + copy_bool, + print_bool + }, + { + "target_dir", + "\n############################################################\n" + "# Target Directories and filenames For Images And Films\n" + "# For the options snapshot_, jpeg_, mpeg_ and timelapse_filename\n" + "# you can use conversion specifiers\n" + "# %Y = year, %m = month, %d = date,\n" + "# %H = hour, %M = minute, %S = second,\n" + "# %v = event, %q = frame number, %t = thread (camera) number,\n" + "# %D = changed pixels, %N = noise level,\n" + "# %i and %J = width and height of motion area,\n" + "# %K and %L = X and Y coordinates of motion center\n" + "# %C = value defined by text_event\n" + "# Quotation marks round string are allowed.\n" + "############################################################\n\n" + "# Target base directory for pictures and films\n" + "# Recommended to use absolute path. (Default: current working directory)", + 0, + CONF_OFFSET(filepath), + copy_string, + print_string + }, + { + "snapshot_filename", + "# File path for snapshots (jpeg or ppm) relative to target_dir\n" + "# Default: "DEF_SNAPPATH"\n" + "# Default value is equivalent to legacy oldlayout option\n" + "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-snapshot\n" + "# File extension .jpg or .ppm is automatically added so do not include this.\n" + "# Note: A symbolic link called lastsnap.jpg created in the target_dir will always\n" + "# point to the latest snapshot, unless snapshot_filename is exactly 'lastsnap'", + 0, + CONF_OFFSET(snappath), + copy_string, + print_string + }, + { + "jpeg_filename", + "# File path for motion triggered images (jpeg or ppm) relative to target_dir\n" + "# Default: "DEF_JPEGPATH"\n" + "# Default value is equivalent to legacy oldlayout option\n" + "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q\n" + "# File extension .jpg or .ppm is automatically added so do not include this\n" + "# Set to 'preview' together with best-preview feature enables special naming\n" + "# convention for preview shots. See motion guide for details", + 0, + CONF_OFFSET(jpegpath), + copy_string, + print_string + }, #ifdef HAVE_FFMPEG - { - "movie_filename", - "# File path for motion triggered ffmpeg films (mpeg) relative to target_dir\n" - "# Default: "DEF_MPEGPATH"\n" - "# Default value is equivalent to legacy oldlayout option\n" - "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H%M%S\n" - "# File extension .mpg or .avi is automatically added so do not include this\n" - "# This option was previously called ffmpeg_filename", - 0, - CONF_OFFSET(mpegpath), - copy_string, - print_string - }, - { - "timelapse_filename", - "# File path for timelapse mpegs relative to target_dir\n" - "# Default: "DEF_TIMEPATH"\n" - "# Default value is near equivalent to legacy oldlayout option\n" - "# For Motion 3.0 compatible mode choose: %Y/%m/%d-timelapse\n" - "# File extension .mpg is automatically added so do not include this", - 0, - CONF_OFFSET(timepath), - copy_string, - print_string - }, + { + "movie_filename", + "# File path for motion triggered ffmpeg films (mpeg) relative to target_dir\n" + "# Default: "DEF_MPEGPATH"\n" + "# Default value is equivalent to legacy oldlayout option\n" + "# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H%M%S\n" + "# File extension .mpg or .avi is automatically added so do not include this\n" + "# This option was previously called ffmpeg_filename", + 0, + CONF_OFFSET(mpegpath), + copy_string, + print_string + }, + { + "timelapse_filename", + "# File path for timelapse mpegs relative to target_dir\n" + "# Default: "DEF_TIMEPATH"\n" + "# Default value is near equivalent to legacy oldlayout option\n" + "# For Motion 3.0 compatible mode choose: %Y/%m/%d-timelapse\n" + "# File extension .mpg is automatically added so do not include this", + 0, + CONF_OFFSET(timepath), + copy_string, + print_string + }, #endif /* HAVE_FFMPEG */ - { - "webcam_port", - "\n############################################################\n" - "# Live Webcam Server\n" - "############################################################\n\n" - "# The mini-http server listens to this port for requests (default: 0 = disabled)", - 0, - CONF_OFFSET(webcam_port), - copy_int, - print_int - }, - { - "webcam_quality", - "# Quality of the jpeg images produced (default: 50)", - 0, - CONF_OFFSET(webcam_quality), - copy_int, - print_int - }, - { - "webcam_motion", - "# Output frames at 1 fps when no motion is detected and increase to the\n" - "# rate given by webcam_maxrate when motion is detected (default: off)", - 0, - CONF_OFFSET(webcam_motion), - copy_bool, - print_bool - }, - { - "webcam_maxrate", - "# Maximum framerate for webcam streams (default: 1)", - 0, - CONF_OFFSET(webcam_maxrate), - copy_int, - print_int - }, - { - "webcam_localhost", - "# Restrict webcam connections to localhost only (default: on)", - 0, - CONF_OFFSET(webcam_localhost), - copy_bool, - print_bool - }, - { - "webcam_limit", - "# Limits the number of images per connection (default: 0 = unlimited)\n" - "# Number can be defined by multiplying actual webcam rate by desired number of seconds\n" - "# Actual webcam rate is the smallest of the numbers framerate and webcam_maxrate", - 0, - CONF_OFFSET(webcam_limit), - copy_int, - print_int - }, - { - "control_port", - "\n############################################################\n" - "# HTTP Based Control\n" - "############################################################\n\n" - "# TCP/IP port for the http server to listen on (default: 0 = disabled)", - 1, - CONF_OFFSET(control_port), - copy_int, - print_int - }, - { - "control_localhost", - "# Restrict control connections to localhost only (default: on)", - 1, - CONF_OFFSET(control_localhost), - copy_bool, - print_bool - }, - { - "control_html_output", - "# Output for http server, select off to choose raw text plain (default: on)", - 1, - CONF_OFFSET(control_html_output), - copy_bool, - print_bool - }, - { - "control_authentication", - "# Authentication for the http based control. Syntax username:password\n" - "# Default: not defined (Disabled)", - 1, - CONF_OFFSET(control_authentication), - copy_string, - print_string - }, - { - "track_type", - "\n############################################################\n" - "# Tracking (Pan/Tilt)\n" - "############################################################\n\n" - "# Type of tracker (0=none (default), 1=stepper, 2=iomojo, 3=pwc, 4=generic, 5=uvcvideo)\n" - "# The generic type enables the definition of motion center and motion size to\n" - "# be used with the conversion specifiers for options like on_motion_detected", - 0, - TRACK_OFFSET(type), - copy_short, - print_short - }, - { - "track_auto", - "# Enable auto tracking (default: off)", - 0, - TRACK_OFFSET(active), - copy_bool, - print_bool - }, - { - "track_port", - "# Serial port of motor (default: none)", - 0, - TRACK_OFFSET(port), - copy_string, - print_string - }, - { - "track_motorx", - "# Motor number for x-axis (default: 0)", - 0, - TRACK_OFFSET(motorx), - copy_short, - print_short - }, - { - "track_motory", - "# Motor number for y-axis (default: 0)", - 0, - TRACK_OFFSET(motory), - copy_short, - print_short - }, - { - "track_maxx", - "# Maximum value on x-axis (default: 0)", - 0, - TRACK_OFFSET(maxx), - copy_short, - print_short - }, - { - "track_maxy", - "# Maximum value on y-axis (default: 0)", - 0, - TRACK_OFFSET(maxy), - copy_short, - print_short - }, - { - "track_iomojo_id", - "# ID of an iomojo camera if used (default: 0)", - 0, - TRACK_OFFSET(iomojo_id), - copy_short, - print_short - }, - { - "track_step_angle_x", - "# Angle in degrees the camera moves per step on the X-axis\n" - "# with auto-track (default: 10)\n" - "# Currently only used with pwc type cameras", - 0, - TRACK_OFFSET(step_angle_x), - copy_short, - print_short - }, - { - "track_step_angle_y", - "# Angle in degrees the camera moves per step on the Y-axis\n" - "# with auto-track (default: 10)\n" - "# Currently only used with pwc type cameras", - 0, - TRACK_OFFSET(step_angle_y), - copy_short, - print_short - }, - { - "track_move_wait", - "# Delay to wait for after tracking movement as number\n" - "# of picture frames (default: 10)", - 0, - TRACK_OFFSET(move_wait), - copy_short, - print_short - }, - { - "track_speed", - "# Speed to set the motor to (stepper motor option) (default: 255)", - 0, - TRACK_OFFSET(speed), - copy_short, - print_short - }, - { - "track_stepsize", - "# Number of steps to make (stepper motor option) (default: 40)", - 0, - TRACK_OFFSET(stepsize), - copy_short, - print_short - }, - { - "quiet", - "\n############################################################\n" - "# External Commands, Warnings and Logging:\n" - "# You can use conversion specifiers for the on_xxxx commands\n" - "# %Y = year, %m = month, %d = date,\n" - "# %H = hour, %M = minute, %S = second,\n" - "# %v = event, %q = frame number, %t = thread (camera) number,\n" - "# %D = changed pixels, %N = noise level,\n" - "# %i and %J = width and height of motion area,\n" - "# %K and %L = X and Y coordinates of motion center\n" - "# %C = value defined by text_event\n" - "# %f = filename with full path\n" - "# %n = number indicating filetype\n" - "# Both %f and %n are only defined for on_picture_save,\n" - "# on_movie_start and on_movie_end\n" - "# Quotation marks round string are allowed.\n" - "############################################################\n\n" - "# Do not sound beeps when detecting motion (default: on)\n" - "# Note: Motion never beeps when running in daemon mode.", - 0, - CONF_OFFSET(quiet), - copy_bool, - print_bool - }, - { - "on_event_start", - "# Command to be executed when an event starts. (default: none)\n" - "# An event starts at first motion detected after a period of no motion defined by gap ", - 0, - CONF_OFFSET(on_event_start), - copy_string, - print_string - }, - { - "on_event_end", - "# Command to be executed when an event ends after a period of no motion\n" - "# (default: none). The period of no motion is defined by option gap.", - 0, - CONF_OFFSET(on_event_end), - copy_string, - print_string - }, - { - "on_picture_save", - "# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)\n" - "# To give the filename as an argument to a command append it with %f", - 0, - CONF_OFFSET(on_picture_save), - copy_string, - print_string - }, - { - "on_motion_detected", - "# Command to be executed when a motion frame is detected (default: none)", - 0, - CONF_OFFSET(on_motion_detected), - copy_string, - print_string - }, - { - "on_area_detected", - "# Command to be executed when motion in a predefined area is detected\n" - "# Check option 'area_detect'. (default: none)", - 0, - CONF_OFFSET(on_area_detected), - copy_string, - print_string - }, + { + "webcam_port", + "\n############################################################\n" + "# Live Webcam Server\n" + "############################################################\n\n" + "# The mini-http server listens to this port for requests (default: 0 = disabled)", + 0, + CONF_OFFSET(webcam_port), + copy_int, + print_int + }, + { + "webcam_quality", + "# Quality of the jpeg images produced (default: 50)", + 0, + CONF_OFFSET(webcam_quality), + copy_int, + print_int + }, + { + "webcam_motion", + "# Output frames at 1 fps when no motion is detected and increase to the\n" + "# rate given by webcam_maxrate when motion is detected (default: off)", + 0, + CONF_OFFSET(webcam_motion), + copy_bool, + print_bool + }, + { + "webcam_maxrate", + "# Maximum framerate for webcam streams (default: 1)", + 0, + CONF_OFFSET(webcam_maxrate), + copy_int, + print_int + }, + { + "webcam_localhost", + "# Restrict webcam connections to localhost only (default: on)", + 0, + CONF_OFFSET(webcam_localhost), + copy_bool, + print_bool + }, + { + "webcam_limit", + "# Limits the number of images per connection (default: 0 = unlimited)\n" + "# Number can be defined by multiplying actual webcam rate by desired number of seconds\n" + "# Actual webcam rate is the smallest of the numbers framerate and webcam_maxrate", + 0, + CONF_OFFSET(webcam_limit), + copy_int, + print_int + }, + { + "control_port", + "\n############################################################\n" + "# HTTP Based Control\n" + "############################################################\n\n" + "# TCP/IP port for the http server to listen on (default: 0 = disabled)", + 1, + CONF_OFFSET(control_port), + copy_int, + print_int + }, + { + "control_localhost", + "# Restrict control connections to localhost only (default: on)", + 1, + CONF_OFFSET(control_localhost), + copy_bool, + print_bool + }, + { + "control_html_output", + "# Output for http server, select off to choose raw text plain (default: on)", + 1, + CONF_OFFSET(control_html_output), + copy_bool, + print_bool + }, + { + "control_authentication", + "# Authentication for the http based control. Syntax username:password\n" + "# Default: not defined (Disabled)", + 1, + CONF_OFFSET(control_authentication), + copy_string, + print_string + }, + { + "track_type", + "\n############################################################\n" + "# Tracking (Pan/Tilt)\n" + "############################################################\n\n" + "# Type of tracker (0=none (default), 1=stepper, 2=iomojo, 3=pwc, 4=generic, 5=uvcvideo)\n" + "# The generic type enables the definition of motion center and motion size to\n" + "# be used with the conversion specifiers for options like on_motion_detected", + 0, + TRACK_OFFSET(type), + copy_short, + print_short + }, + { + "track_auto", + "# Enable auto tracking (default: off)", + 0, + TRACK_OFFSET(active), + copy_bool, + print_bool + }, + { + "track_port", + "# Serial port of motor (default: none)", + 0, + TRACK_OFFSET(port), + copy_string, + print_string + }, + { + "track_motorx", + "# Motor number for x-axis (default: 0)", + 0, + TRACK_OFFSET(motorx), + copy_short, + print_short + }, + { + "track_motory", + "# Motor number for y-axis (default: 0)", + 0, + TRACK_OFFSET(motory), + copy_short, + print_short + }, + { + "track_maxx", + "# Maximum value on x-axis (default: 0)", + 0, + TRACK_OFFSET(maxx), + copy_short, + print_short + }, + { + "track_maxy", + "# Maximum value on y-axis (default: 0)", + 0, + TRACK_OFFSET(maxy), + copy_short, + print_short + }, + { + "track_iomojo_id", + "# ID of an iomojo camera if used (default: 0)", + 0, + TRACK_OFFSET(iomojo_id), + copy_short, + print_short + }, + { + "track_step_angle_x", + "# Angle in degrees the camera moves per step on the X-axis\n" + "# with auto-track (default: 10)\n" + "# Currently only used with pwc type cameras", + 0, + TRACK_OFFSET(step_angle_x), + copy_short, + print_short + }, + { + "track_step_angle_y", + "# Angle in degrees the camera moves per step on the Y-axis\n" + "# with auto-track (default: 10)\n" + "# Currently only used with pwc type cameras", + 0, + TRACK_OFFSET(step_angle_y), + copy_short, + print_short + }, + { + "track_move_wait", + "# Delay to wait for after tracking movement as number\n" + "# of picture frames (default: 10)", + 0, + TRACK_OFFSET(move_wait), + copy_short, + print_short + }, + { + "track_speed", + "# Speed to set the motor to (stepper motor option) (default: 255)", + 0, + TRACK_OFFSET(speed), + copy_short, + print_short + }, + { + "track_stepsize", + "# Number of steps to make (stepper motor option) (default: 40)", + 0, + TRACK_OFFSET(stepsize), + copy_short, + print_short + }, + { + "quiet", + "\n############################################################\n" + "# External Commands, Warnings and Logging:\n" + "# You can use conversion specifiers for the on_xxxx commands\n" + "# %Y = year, %m = month, %d = date,\n" + "# %H = hour, %M = minute, %S = second,\n" + "# %v = event, %q = frame number, %t = thread (camera) number,\n" + "# %D = changed pixels, %N = noise level,\n" + "# %i and %J = width and height of motion area,\n" + "# %K and %L = X and Y coordinates of motion center\n" + "# %C = value defined by text_event\n" + "# %f = filename with full path\n" + "# %n = number indicating filetype\n" + "# Both %f and %n are only defined for on_picture_save,\n" + "# on_movie_start and on_movie_end\n" + "# Quotation marks round string are allowed.\n" + "############################################################\n\n" + "# Do not sound beeps when detecting motion (default: on)\n" + "# Note: Motion never beeps when running in daemon mode.", + 0, + CONF_OFFSET(quiet), + copy_bool, + print_bool + }, + { + "on_event_start", + "# Command to be executed when an event starts. (default: none)\n" + "# An event starts at first motion detected after a period of no motion defined by gap ", + 0, + CONF_OFFSET(on_event_start), + copy_string, + print_string + }, + { + "on_event_end", + "# Command to be executed when an event ends after a period of no motion\n" + "# (default: none). The period of no motion is defined by option gap.", + 0, + CONF_OFFSET(on_event_end), + copy_string, + print_string + }, + { + "on_picture_save", + "# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)\n" + "# To give the filename as an argument to a command append it with %f", + 0, + CONF_OFFSET(on_picture_save), + copy_string, + print_string + }, + { + "on_motion_detected", + "# Command to be executed when a motion frame is detected (default: none)", + 0, + CONF_OFFSET(on_motion_detected), + copy_string, + print_string + }, + { + "on_area_detected", + "# Command to be executed when motion in a predefined area is detected\n" + "# Check option 'area_detect'. (default: none)", + 0, + CONF_OFFSET(on_area_detected), + copy_string, + print_string + }, #ifdef HAVE_FFMPEG - { - "on_movie_start", - "# Command to be executed when a movie file (.mpg|.avi) is created. (default: none)\n" - "# To give the filename as an argument to a command append it with %f", - 0, - CONF_OFFSET(on_movie_start), - copy_string, - print_string - }, - { - "on_movie_end", - "# Command to be executed when a movie file (.mpg|.avi) is closed. (default: none)\n" - "# To give the filename as an argument to a command append it with %f", - 0, - CONF_OFFSET(on_movie_end), - copy_string, - print_string - }, + { + "on_movie_start", + "# Command to be executed when a movie file (.mpg|.avi) is created. (default: none)\n" + "# To give the filename as an argument to a command append it with %f", + 0, + CONF_OFFSET(on_movie_start), + copy_string, + print_string + }, + { + "on_movie_end", + "# Command to be executed when a movie file (.mpg|.avi) is closed. (default: none)\n" + "# To give the filename as an argument to a command append it with %f", + 0, + CONF_OFFSET(on_movie_end), + copy_string, + print_string + }, #endif /* HAVE_FFMPEG */ - { - "on_camera_lost", - "# Command to be executed when a camera can't be opened or if it is lost\n" - "# NOTE: There is situations when motion don't detect a lost camera!\n" - "# It depends on the driver, some drivers dosn't detect a lost camera at all\n" - "# Some hangs the motion thread. Some even hangs the PC! (default: none)\n", - 0, - CONF_OFFSET(on_camera_lost), - copy_string, - print_string - }, + { + "on_camera_lost", + "# Command to be executed when a camera can't be opened or if it is lost\n" + "# NOTE: There is situations when motion don't detect a lost camera!\n" + "# It depends on the driver, some drivers dosn't detect a lost camera at all\n" + "# Some hangs the motion thread. Some even hangs the PC! (default: none)\n", + 0, + CONF_OFFSET(on_camera_lost), + copy_string, + print_string + }, #if defined(HAVE_MYSQL) || defined(HAVE_PGSQL) - { - "sql_log_image", - "\n############################################################\n" - "# Common Options For MySQL and PostgreSQL database features.\n" - "# Options require the MySQL/PostgreSQL options to be active also.\n" - "############################################################\n\n" - "# Log to the database when creating motion triggered image file (default: on)", - 0, - CONF_OFFSET(sql_log_image), - copy_bool, - print_bool - }, - { - "sql_log_snapshot", - "# Log to the database when creating a snapshot image file (default: on)", - 0, - CONF_OFFSET(sql_log_snapshot), - copy_bool, - print_bool - }, - { - "sql_log_mpeg", - "# Log to the database when creating motion triggered mpeg file (default: off)", - 0, - CONF_OFFSET(sql_log_mpeg), - copy_bool, - print_bool - }, - { - "sql_log_timelapse", - "# Log to the database when creating timelapse mpeg file (default: off)", - 0, - CONF_OFFSET(sql_log_timelapse), - copy_bool, - print_bool - }, - { - "sql_query", - "# SQL query string that is sent to the database\n" - "# Use same conversion specifiers has for text features\n" - "# Additional special conversion specifiers are\n" - "# %n = the number representing the file_type\n" - "# %f = filename with full path\n" - "# Default value:\n" - "# insert into security(camera, filename, frame, file_type, time_stamp, text_event) values('%t', '%f', '%q', '%n', '%Y-%m-%d %T', '%C')", - 0, - CONF_OFFSET(sql_query), - copy_string, - print_string - }, + { + "sql_log_image", + "\n############################################################\n" + "# Common Options For MySQL and PostgreSQL database features.\n" + "# Options require the MySQL/PostgreSQL options to be active also.\n" + "############################################################\n\n" + "# Log to the database when creating motion triggered image file (default: on)", + 0, + CONF_OFFSET(sql_log_image), + copy_bool, + print_bool + }, + { + "sql_log_snapshot", + "# Log to the database when creating a snapshot image file (default: on)", + 0, + CONF_OFFSET(sql_log_snapshot), + copy_bool, + print_bool + }, + { + "sql_log_mpeg", + "# Log to the database when creating motion triggered mpeg file (default: off)", + 0, + CONF_OFFSET(sql_log_mpeg), + copy_bool, + print_bool + }, + { + "sql_log_timelapse", + "# Log to the database when creating timelapse mpeg file (default: off)", + 0, + CONF_OFFSET(sql_log_timelapse), + copy_bool, + print_bool + }, + { + "sql_query", + "# SQL query string that is sent to the database\n" + "# Use same conversion specifiers has for text features\n" + "# Additional special conversion specifiers are\n" + "# %n = the number representing the file_type\n" + "# %f = filename with full path\n" + "# Default value:\n" + "# insert into security(camera, filename, frame, file_type, time_stamp, text_event) values('%t', '%f', '%q', '%n', '%Y-%m-%d %T', '%C')", + 0, + CONF_OFFSET(sql_query), + copy_string, + print_string + }, #endif /* defined(HAVE_MYSQL) || defined(HAVE_PGSQL) */ #ifdef HAVE_MYSQL - { - "mysql_db", - "\n############################################################\n" - "# Database Options For MySQL\n" - "############################################################\n\n" - "# Mysql database to log to (default: not defined)", - 0, - CONF_OFFSET(mysql_db), - copy_string, - print_string - }, - { - "mysql_host", - "# The host on which the database is located (default: not defined)", - 0, - CONF_OFFSET(mysql_host), - copy_string, - print_string - }, - { - "mysql_user", - "# User account name for MySQL database (default: not defined)", - 0, - CONF_OFFSET(mysql_user), - copy_string, - print_string - }, - { - "mysql_password", - "# User password for MySQL database (default: not defined)", - 0, - CONF_OFFSET(mysql_password), - copy_string, - print_string - }, + { + "mysql_db", + "\n############################################################\n" + "# Database Options For MySQL\n" + "############################################################\n\n" + "# Mysql database to log to (default: not defined)", + 0, + CONF_OFFSET(mysql_db), + copy_string, + print_string + }, + { + "mysql_host", + "# The host on which the database is located (default: not defined)", + 0, + CONF_OFFSET(mysql_host), + copy_string, + print_string + }, + { + "mysql_user", + "# User account name for MySQL database (default: not defined)", + 0, + CONF_OFFSET(mysql_user), + copy_string, + print_string + }, + { + "mysql_password", + "# User password for MySQL database (default: not defined)", + 0, + CONF_OFFSET(mysql_password), + copy_string, + print_string + }, #endif /* HAVE_MYSQL */ #ifdef HAVE_PGSQL - { - "pgsql_db", - "\n############################################################\n" - "# Database Options For PostgreSQL\n" - "############################################################\n\n" - "# PostgreSQL database to log to (default: not defined)", - 0, - CONF_OFFSET(pgsql_db), - copy_string, - print_string - }, - { - "pgsql_host", - "# The host on which the database is located (default: not defined)", - 0, - CONF_OFFSET(pgsql_host), - copy_string, - print_string - }, - { - "pgsql_user", - "# User account name for PostgreSQL database (default: not defined)", - 0, - CONF_OFFSET(pgsql_user), - copy_string, - print_string - }, - { - "pgsql_password", - "# User password for PostgreSQL database (default: not defined)", - 0, - CONF_OFFSET(pgsql_password), - copy_string, - print_string - }, - { - "pgsql_port", - "# Port on which the PostgreSQL database is located (default: 5432)", - 0, - CONF_OFFSET(pgsql_port), - copy_int, - print_int - }, + { + "pgsql_db", + "\n############################################################\n" + "# Database Options For PostgreSQL\n" + "############################################################\n\n" + "# PostgreSQL database to log to (default: not defined)", + 0, + CONF_OFFSET(pgsql_db), + copy_string, + print_string + }, + { + "pgsql_host", + "# The host on which the database is located (default: not defined)", + 0, + CONF_OFFSET(pgsql_host), + copy_string, + print_string + }, + { + "pgsql_user", + "# User account name for PostgreSQL database (default: not defined)", + 0, + CONF_OFFSET(pgsql_user), + copy_string, + print_string + }, + { + "pgsql_password", + "# User password for PostgreSQL database (default: not defined)", + 0, + CONF_OFFSET(pgsql_password), + copy_string, + print_string + }, + { + "pgsql_port", + "# Port on which the PostgreSQL database is located (default: 5432)", + 0, + CONF_OFFSET(pgsql_port), + copy_int, + print_int + }, #endif /* HAVE_PGSQL */ - { - "video_pipe", - "\n############################################################\n" - "# Video Loopback Device (vloopback project)\n" - "############################################################\n\n" - "# Output images to a video4linux loopback device\n" - "# The value '-' means next available (default: not defined)", - 0, - CONF_OFFSET(vidpipe), - copy_string, - print_string - }, - { - "motion_video_pipe", - "# Output motion images to a video4linux loopback device\n" - "# The value '-' means next available (default: not defined)", - 0, - CONF_OFFSET(motionvidpipe), - copy_string, - print_string - }, - { - "thread", - "\n##############################################################\n" - "# Thread config files - One for each camera.\n" - "# Except if only one camera - You only need this config file.\n" - "# If you have more than one camera you MUST define one thread\n" - "# config file for each camera in addition to this config file.\n" - "##############################################################\n", - 1, - 0, - config_thread, - print_thread - }, + { + "video_pipe", + "\n############################################################\n" + "# Video Loopback Device (vloopback project)\n" + "############################################################\n\n" + "# Output images to a video4linux loopback device\n" + "# The value '-' means next available (default: not defined)", + 0, + CONF_OFFSET(vidpipe), + copy_string, + print_string + }, + { + "motion_video_pipe", + "# Output motion images to a video4linux loopback device\n" + "# The value '-' means next available (default: not defined)", + 0, + CONF_OFFSET(motionvidpipe), + copy_string, + print_string + }, + { + "thread", + "\n##############################################################\n" + "# Thread config files - One for each camera.\n" + "# Except if only one camera - You only need this config file.\n" + "# If you have more than one camera you MUST define one thread\n" + "# config file for each camera in addition to this config file.\n" + "##############################################################\n", + 1, + 0, + config_thread, + print_thread + }, { NULL, NULL, 0, 0, NULL, NULL } }; @@ -1361,38 +1361,40 @@ config_param config_params[] = { */ static void conf_cmdline (struct context *cnt, short int thread) { - struct config *conf=&cnt->conf; - int c; + struct config *conf = &cnt->conf; + int c; - /* For the string options, we free() if necessary and malloc() - * if necessary. This is accomplished by calling mystrcpy(); - * see this function for more information. - */ - while ((c=getopt(conf->argc, conf->argv, "c:d:hns?p:"))!=EOF) - switch (c) { - case 'c': - if (thread==-1) strcpy(cnt->conf_filename, optarg); - break; - case 'n': - cnt->daemon=0; - break; - case 's': - conf->setup_mode=1; - break; - case 'd': - /* no validation - just take what user gives */ - debug_level = (unsigned short int)atoi(optarg); - break; - case 'p': - if (thread==-1) strcpy(cnt->pid_file, optarg); - break; - case 'h': - case '?': - default: - usage(); - exit(1); - } - optind=1; + /* For the string options, we free() if necessary and malloc() + * if necessary. This is accomplished by calling mystrcpy(); + * see this function for more information. + */ + while ((c = getopt(conf->argc, conf->argv, "c:d:hns?p:")) != EOF) + switch (c) { + case 'c': + if (thread == -1) + strcpy(cnt->conf_filename, optarg); + break; + case 'n': + cnt->daemon = 0; + break; + case 's': + conf->setup_mode = 1; + break; + case 'd': + /* no validation - just take what user gives */ + debug_level = (unsigned short int)atoi(optarg); + break; + case 'p': + if (thread == -1) + strcpy(cnt->pid_file, optarg); + break; + case 'h': + case '?': + default: + usage(); + exit(1); + } + optind = 1; } @@ -1404,45 +1406,45 @@ static void conf_cmdline (struct context *cnt, short int thread) */ struct context **conf_cmdparse(struct context **cnt, const char *cmd, const char *arg1) { - unsigned short int i = 0; + unsigned short int i = 0; - if(!cmd) - return cnt; + if (!cmd) + return cnt; - /* We search through config_params until we find a param_name that matches - * our option given by cmd (or reach the end = NULL) - */ - while( config_params[i].param_name != NULL ) { - if(!strncasecmp(cmd, config_params[i].param_name , 255 + 50)) { // Why +50? - - /* if config_param is string we don't want to check arg1 */ - if (strcmp(config_type(&config_params[i]),"string")) { - if(config_params[i].conf_value && !arg1) - return cnt; - } - - /* We call the function given by the pointer config_params[i].copy - * If the option is a bool, copy_bool is called. - * If the option is an int, copy_int is called. - * If the option is a short, copy_short is called. - * If the option is a string, copy_string is called. - * If the option is a thread, config_thread is called. - * The arguments to the function are: - * cnt - a pointer to the context structure - * arg1 - a pointer to the new option value (represented as string) - * config_params[i].conf_value - an integer value which is a pointer - * to the context structure member relative to the pointer cnt. - */ - cnt=config_params[i].copy( cnt, arg1, config_params[i].conf_value ); - return cnt; - } - i++; - } + /* We search through config_params until we find a param_name that matches + * our option given by cmd (or reach the end = NULL) + */ + while (config_params[i].param_name != NULL) { + if (!strncasecmp(cmd, config_params[i].param_name , 255 + 50)) { // Why +50? + + /* if config_param is string we don't want to check arg1 */ + if (strcmp(config_type(&config_params[i]),"string")) { + if (config_params[i].conf_value && !arg1) + return cnt; + } + + /* We call the function given by the pointer config_params[i].copy + * If the option is a bool, copy_bool is called. + * If the option is an int, copy_int is called. + * If the option is a short, copy_short is called. + * If the option is a string, copy_string is called. + * If the option is a thread, config_thread is called. + * The arguments to the function are: + * cnt - a pointer to the context structure + * arg1 - a pointer to the new option value (represented as string) + * config_params[i].conf_value - an integer value which is a pointer + * to the context structure member relative to the pointer cnt. + */ + cnt = config_params[i].copy(cnt, arg1, config_params[i].conf_value); + return cnt; + } + i++; + } - /* We reached the end of config_params without finding a matching option */ - motion_log(LOG_ERR, 0, "Unknown config option \"%s\"",cmd); + /* We reached the end of config_params without finding a matching option */ + motion_log(LOG_ERR, 0, "Unknown config option \"%s\"", cmd); - return cnt; + return cnt; } /* conf_process walks through an already open config file line by line @@ -1457,66 +1459,66 @@ struct context **conf_cmdparse(struct context **cnt, const char *cmd, const char */ static struct context **conf_process(struct context **cnt, FILE *fp) { - /* process each line from the config file */ - - char line[PATH_MAX], *cmd = NULL, *arg1 = NULL; - char *beg = NULL, *end = NULL; + /* process each line from the config file */ + + char line[PATH_MAX], *cmd = NULL, *arg1 = NULL; + char *beg = NULL, *end = NULL; - while (fgets(line, PATH_MAX-1, fp)) { - if(!(line[0]=='#' || line[0]==';' || strlen(line)< 2)) {/* skipcomment */ - - arg1 = NULL; + while (fgets(line, PATH_MAX-1, fp)) { + if (!(line[0] == '#' || line[0] == ';' || strlen(line) < 2)) {/* skipcomment */ + + arg1 = NULL; - /* trim white space and any CR or LF at the end of the line */ - end = line + strlen(line) - 1; /* Point to the last non-null character in the string */ - while (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r') { - end--; - } - *(end+1) = '\0'; - - /* If line is only whitespace we continue to the next line */ - if (strlen(line) == 0) - continue; + /* trim white space and any CR or LF at the end of the line */ + end = line + strlen(line) - 1; /* Point to the last non-null character in the string */ + while (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r') { + end--; + } + *(end+1) = '\0'; + + /* If line is only whitespace we continue to the next line */ + if (strlen(line) == 0) + continue; - /* trim leading whitespace from the line and find command */ - beg = line; - while (*beg == ' ' || *beg == '\t') { - beg++; - } + /* trim leading whitespace from the line and find command */ + beg = line; + while (*beg == ' ' || *beg == '\t') { + beg++; + } - cmd = beg; /* command starts here */ + cmd = beg; /* command starts here */ - while (*beg != ' ' && *beg != '\t' && *beg != '=' && *beg != '\0') { - beg++; - } - *beg = '\0'; /* command string terminates here */ + while (*beg != ' ' && *beg != '\t' && *beg != '=' && *beg != '\0') { + beg++; + } + *beg = '\0'; /* command string terminates here */ - /* trim space between command and argument */ - beg++; + /* trim space between command and argument */ + beg++; - if (strlen(beg) > 0){ - while (*beg == ' ' || *beg == '\t' || *beg == '=' || *beg == '\n' || *beg == '\r') { - beg++; - } + if (strlen(beg) > 0) { + while (*beg == ' ' || *beg == '\t' || *beg == '=' || *beg == '\n' || *beg == '\r') { + beg++; + } - /* If argument is in "" we will strip them off - It is important that we can use "" so that we can use - leading spaces in text_left and text_right */ - if ((beg[0]=='"' && beg[strlen(beg)-1]=='"') || - (beg[0]=='\'' && beg[strlen(beg)-1]=='\'')) { - beg[strlen(beg)-1]='\0'; - beg++; - } - - arg1 = beg; /* Argument starts here */ - } - /* else arg1 stays null pointer */ + /* If argument is in "" we will strip them off + It is important that we can use "" so that we can use + leading spaces in text_left and text_right */ + if ((beg[0]=='"' && beg[strlen(beg)-1]=='"') || + (beg[0]=='\'' && beg[strlen(beg)-1]=='\'')) { + beg[strlen(beg)-1]='\0'; + beg++; + } + + arg1 = beg; /* Argument starts here */ + } + /* else arg1 stays null pointer */ - cnt = conf_cmdparse(cnt, cmd, arg1); - } - } + cnt = conf_cmdparse(cnt, cmd, arg1); + } + } - return cnt; + return cnt; } @@ -1525,54 +1527,59 @@ static struct context **conf_process(struct context **cnt, FILE *fp) */ void conf_print(struct context **cnt) { - const char *retval; - char *val; - unsigned short int i, thread; - FILE *conffile; + const char *retval; + char *val; + unsigned short int i, thread; + FILE *conffile; - for (thread=0; cnt[thread]; thread++) { - motion_log(LOG_INFO, 0, "Writing config file to %s",cnt[thread]->conf_filename); - conffile=myfopen(cnt[thread]->conf_filename, "w"); - if (!conffile) - continue; - fprintf(conffile, "# %s\n", cnt[thread]->conf_filename); - fprintf(conffile, "#\n# This config file was generated by motion " VERSION "\n"); - fprintf(conffile, "\n\n"); - for (i=0; config_params[i].param_name; i++) { - retval=config_params[i].print(cnt, NULL, i, thread); - /*If config parameter has a value (not NULL) print it to the config file*/ - if (retval) { - fprintf(conffile, "%s\n", config_params[i].param_help); - /* If the option is a text_* and first char is a space put - quotation marks around to allow leading spaces */ - if (strncmp(config_params[i].param_name, "text", 4) || strncmp(retval, " ", 1)) - fprintf(conffile, "%s %s\n\n", config_params[i].param_name, retval); - else - fprintf(conffile, "%s \"%s\"\n\n", config_params[i].param_name, retval); - } else { - val = NULL; - config_params[i].print(cnt, &val, i, thread); - /* It can either be a thread file parameter or a disabled parameter - If it is a thread parameter write it out - Else write the disabled option to the config file but with a - comment mark in front of the parameter name */ - if (val) { - fprintf(conffile,"%s\n", config_params[i].param_help); - fprintf(conffile, "%s\n", val); - if (strlen(val)==0) - fprintf(conffile,"; thread /usr/local/etc/thread1.conf\n"); - free(val); - } else if (thread==0) { - fprintf(conffile,"%s\n", config_params[i].param_help); - fprintf(conffile,"; %s value\n\n", config_params[i].param_name); - } - } - } + for (thread=0; cnt[thread]; thread++) { + motion_log(LOG_INFO, 0, "Writing config file to %s",cnt[thread]->conf_filename); + conffile=myfopen(cnt[thread]->conf_filename, "w"); - fprintf(conffile, "\n"); - fclose(conffile); - conffile=NULL; - } + if (!conffile) + continue; + + fprintf(conffile, "# %s\n", cnt[thread]->conf_filename); + fprintf(conffile, "#\n# This config file was generated by motion " VERSION "\n"); + fprintf(conffile, "\n\n"); + + for (i = 0; config_params[i].param_name; i++) { + retval=config_params[i].print(cnt, NULL, i, thread); + /*If config parameter has a value (not NULL) print it to the config file*/ + + if (retval) { + fprintf(conffile, "%s\n", config_params[i].param_help); + /* If the option is a text_* and first char is a space put + quotation marks around to allow leading spaces */ + if (strncmp(config_params[i].param_name, "text", 4) || strncmp(retval, " ", 1)) + fprintf(conffile, "%s %s\n\n", config_params[i].param_name, retval); + else + fprintf(conffile, "%s \"%s\"\n\n", config_params[i].param_name, retval); + } else { + val = NULL; + config_params[i].print(cnt, &val, i, thread); + /* It can either be a thread file parameter or a disabled parameter + If it is a thread parameter write it out + Else write the disabled option to the config file but with a + comment mark in front of the parameter name */ + if (val) { + fprintf(conffile,"%s\n", config_params[i].param_help); + fprintf(conffile, "%s\n", val); + + if (strlen(val) == 0) + fprintf(conffile,"; thread /usr/local/etc/thread1.conf\n"); + free(val); + } else if (thread == 0) { + fprintf(conffile,"%s\n", config_params[i].param_help); + fprintf(conffile,"; %s value\n\n", config_params[i].param_name); + } + } + } + + fprintf(conffile, "\n"); + fclose(conffile); + conffile=NULL; + } } /************************************************************************** @@ -1595,98 +1602,98 @@ void conf_print(struct context **cnt) **************************************************************************/ struct context ** conf_load (struct context **cnt) { - FILE *fp=NULL; - char filename[PATH_MAX]; - int i; - /* We preserve argc and argv because they get overwritten by the memcpy command */ - char **argv = cnt[0]->conf.argv; - int argc = cnt[0]->conf.argc; + FILE *fp = NULL; + char filename[PATH_MAX]; + int i; + /* We preserve argc and argv because they get overwritten by the memcpy command */ + char **argv = cnt[0]->conf.argv; + int argc = cnt[0]->conf.argc; - /* Copy the template config structure with all the default config values - * into cnt[0]->conf - */ - memcpy(&cnt[0]->conf, &conf_template, sizeof(struct config)); - - /* For each member of cnt[0] which is a pointer to a string - * if the member points to a string in conf_template and is not NULL - * 1. Reserve (malloc) memory for the string - * 2. Copy the conf_template given string to the reserved memory - * 3. Change the cnt[0] member (char*) pointing to the string in reserved memory - * This ensures that we can free and malloc the string when changed - * via http remote control or config file or command line options - */ - malloc_strings(cnt[0]); + /* Copy the template config structure with all the default config values + * into cnt[0]->conf + */ + memcpy(&cnt[0]->conf, &conf_template, sizeof(struct config)); + + /* For each member of cnt[0] which is a pointer to a string + * if the member points to a string in conf_template and is not NULL + * 1. Reserve (malloc) memory for the string + * 2. Copy the conf_template given string to the reserved memory + * 3. Change the cnt[0] member (char*) pointing to the string in reserved memory + * This ensures that we can free and malloc the string when changed + * via http remote control or config file or command line options + */ + malloc_strings(cnt[0]); - /* Restore the argc and argv */ - cnt[0]->conf.argv = argv; - cnt[0]->conf.argc = argc; + /* Restore the argc and argv */ + cnt[0]->conf.argv = argv; + cnt[0]->conf.argc = argc; - /* Open the motion.conf file. We try in this sequence: - * 1. commandline - * 2. current working directory - * 3. $HOME/.motion/motion.conf - * 4. sysconfig/motion.conf - */ - /* Get filename & pid file from commandline */ - cnt[0]->conf_filename[0] = 0; - cnt[0]->pid_file[0] = 0; + /* Open the motion.conf file. We try in this sequence: + * 1. commandline + * 2. current working directory + * 3. $HOME/.motion/motion.conf + * 4. sysconfig/motion.conf + */ + /* Get filename & pid file from commandline */ + cnt[0]->conf_filename[0] = 0; + cnt[0]->pid_file[0] = 0; - conf_cmdline(cnt[0], -1); - if (cnt[0]->conf_filename[0]){ /* User has supplied filename on commandline*/ - strcpy(filename, cnt[0]->conf_filename); - fp = fopen (filename, "r"); - } - if (!fp){ /* Commandline didn't work, try current dir */ - char *path = NULL; - if (cnt[0]->conf_filename[0]) - motion_log(-1, 1, "Configfile %s not found - trying defaults.", filename); - if ( (path = get_current_dir_name()) == NULL){ - motion_log(LOG_ERR, 1, "Error get_current_dir_name"); - exit(-1); - } - snprintf(filename, PATH_MAX, "%s/motion.conf", path); - fp = fopen (filename, "r"); - free(path); - } - if (!fp) { /* specified file does not exist... try default file */ - snprintf(filename, PATH_MAX, "%s/.motion/motion.conf", getenv("HOME")); - fp = fopen(filename, "r"); - if (!fp) { - snprintf(filename, PATH_MAX, "%s/motion.conf", sysconfdir); - fp = fopen(filename, "r"); - if (!fp) /* there is no config file.... use defaults */ - motion_log(-1, 1, "could not open configfile %s",filename); - } - } + conf_cmdline(cnt[0], -1); + if (cnt[0]->conf_filename[0]){ /* User has supplied filename on commandline*/ + strcpy(filename, cnt[0]->conf_filename); + fp = fopen (filename, "r"); + } + if (!fp){ /* Commandline didn't work, try current dir */ + char *path = NULL; + if (cnt[0]->conf_filename[0]) + motion_log(-1, 1, "Configfile %s not found - trying defaults.", filename); + if ((path = get_current_dir_name()) == NULL){ + motion_log(LOG_ERR, 1, "Error get_current_dir_name"); + exit(-1); + } + snprintf(filename, PATH_MAX, "%s/motion.conf", path); + fp = fopen (filename, "r"); + free(path); + } + if (!fp) { /* specified file does not exist... try default file */ + snprintf(filename, PATH_MAX, "%s/.motion/motion.conf", getenv("HOME")); + fp = fopen(filename, "r"); + if (!fp) { + snprintf(filename, PATH_MAX, "%s/motion.conf", sysconfdir); + fp = fopen(filename, "r"); + if (!fp) /* there is no config file.... use defaults */ + motion_log(-1, 1, "could not open configfile %s",filename); + } + } - /* Now we process the motion.conf config file and close it*/ - if (fp) { - strcpy(cnt[0]->conf_filename, filename); - motion_log(LOG_INFO, 0, "Processing thread 0 - config file %s",filename); - cnt=conf_process(cnt, fp); - fclose(fp); - }else{ - motion_log(LOG_INFO, 0, "Not config file to process using default values"); - } - + /* Now we process the motion.conf config file and close it*/ + if (fp) { + strcpy(cnt[0]->conf_filename, filename); + motion_log(LOG_INFO, 0, "Processing thread 0 - config file %s",filename); + cnt=conf_process(cnt, fp); + fclose(fp); + } else { + motion_log(LOG_INFO, 0, "Not config file to process using default values"); + } + - /* For each thread (given by cnt[i]) being not null - * cnt is an array of pointers to a context type structure - * cnt[0] is the default context structure - * cnt[1], cnt[2], ... are context structures for each thread - * Command line options always wins over config file options - * so we go through each thread and overrides any set command line - * options - */ - i=-1; - while(cnt[++i]) - conf_cmdline(cnt[i], i); + /* For each thread (given by cnt[i]) being not null + * cnt is an array of pointers to a context type structure + * cnt[0] is the default context structure + * cnt[1], cnt[2], ... are context structures for each thread + * Command line options always wins over config file options + * so we go through each thread and overrides any set command line + * options + */ + i=-1; + while(cnt[++i]) + conf_cmdline(cnt[i], i); - /* if pid file was passed from command line copy to main thread conf struct */ - if (cnt[0]->pid_file[0]) - cnt[0]->conf.pid_file = mystrcpy(cnt[0]->conf.pid_file, cnt[0]->pid_file); + /* if pid file was passed from command line copy to main thread conf struct */ + if (cnt[0]->pid_file[0]) + cnt[0]->conf.pid_file = mystrcpy(cnt[0]->conf.pid_file, cnt[0]->pid_file); - return cnt; + return cnt; } /* malloc_strings goes through the members of a context structure. @@ -1699,22 +1706,22 @@ struct context ** conf_load (struct context **cnt) */ void malloc_strings (struct context * cnt) { - unsigned short int i = 0; - char **val; - while( config_params[i].param_name != NULL ) { - if (config_params[i].copy == copy_string) { /* if member is a string */ - /* val is made to point to a pointer to the current string */ - val = (char **)((char *)cnt+config_params[i].conf_value); + unsigned short int i = 0; + char **val; + while (config_params[i].param_name != NULL) { + if (config_params[i].copy == copy_string) { /* if member is a string */ + /* val is made to point to a pointer to the current string */ + val = (char **)((char *)cnt+config_params[i].conf_value); - /* if there is a string, malloc() space for it, copy - * the string to new space, and point to the new - * string. we don't free() because we're copying a - * static string. - */ - *val = mystrdup(*val); - } - i++; - } + /* if there is a string, malloc() space for it, copy + * the string to new space, and point to the new + * string. we don't free() because we're copying a + * static string. + */ + *val = mystrdup(*val); + } + i++; + } } /************************************************************************ @@ -1748,21 +1755,21 @@ void malloc_strings (struct context * cnt) */ static struct context **copy_bool (struct context **cnt, const char *str, int val_ptr) { - void *tmp; - int i; + void *tmp; + int i; - i=-1; - while(cnt[++i]) { - tmp = (char *)cnt[i]+(int)val_ptr; - if ( !strcmp(str, "1") || !strcasecmp(str, "yes") || !strcasecmp(str,"on")) { - *((int *)tmp) = 1; - } else { - *((int *)tmp) = 0; - } - if (cnt[0]->threadnr) - return cnt; - } - return cnt; + i = -1; + while (cnt[++i]) { + tmp = (char *)cnt[i]+(int)val_ptr; + if (!strcmp(str, "1") || !strcasecmp(str, "yes") || !strcasecmp(str,"on")) { + *((int *)tmp) = 1; + } else { + *((int *)tmp) = 0; + } + if (cnt[0]->threadnr) + return cnt; + } + return cnt; } /* copy_int assigns a config option to a new integer value. @@ -1770,17 +1777,17 @@ static struct context **copy_bool (struct context **cnt, const char *str, int va */ static struct context ** copy_int(struct context **cnt, const char *str, int val_ptr) { - void *tmp; - int i; + void *tmp; + int i; - i=-1; - while(cnt[++i]) { - tmp = (char *)cnt[i]+val_ptr; - *((int *)tmp) = atoi(str); - if (cnt[0]->threadnr) - return cnt; - } - return cnt; + i = -1; + while (cnt[++i]) { + tmp = (char *)cnt[i]+val_ptr; + *((int *)tmp) = atoi(str); + if (cnt[0]->threadnr) + return cnt; + } + return cnt; } /* copy_short assigns a config option to a new short value. @@ -1788,17 +1795,17 @@ static struct context ** copy_int(struct context **cnt, const char *str, int val */ static struct context ** copy_short(struct context **cnt, const char *str, int val_ptr) { - void *tmp; - int i; + void *tmp; + int i; - i=-1; - while(cnt[++i]) { - tmp = (char *)cnt[i]+val_ptr; - *((short int *)tmp) = atoi(str); - if (cnt[0]->threadnr) - return cnt; - } - return cnt; + i = -1; + while (cnt[++i]) { + tmp = (char *)cnt[i]+val_ptr; + *((short int *)tmp) = atoi(str); + if (cnt[0]->threadnr) + return cnt; + } + return cnt; } /* copy_string assigns a new string value to a config option. @@ -1810,25 +1817,25 @@ static struct context ** copy_short(struct context **cnt, const char *str, int v */ struct context **copy_string(struct context **cnt, const char *str, int val_ptr) { - char **tmp; - int i; + char **tmp; + int i; - i=-1; - while(cnt[++i]) { - tmp = (char **)((char *)cnt[i] + val_ptr); + i = -1; + while (cnt[++i]) { + tmp = (char **)((char *)cnt[i] + val_ptr); - /* mystrcpy assigns the new string value - * including free'ing and reserving new memory for it. - */ - *tmp = mystrcpy(*tmp, str); + /* mystrcpy assigns the new string value + * including free'ing and reserving new memory for it. + */ + *tmp = mystrcpy(*tmp, str); - /* set the option on all threads if setting the option - * for thread 0; otherwise just set that one thread's option - */ - if (cnt[0]->threadnr) - return cnt; - } - return cnt; + /* set the option on all threads if setting the option + * for thread 0; otherwise just set that one thread's option + */ + if (cnt[0]->threadnr) + return cnt; + } + return cnt; } @@ -1849,15 +1856,15 @@ struct context **copy_string(struct context **cnt, const char *str, int val_ptr) */ char *mystrcpy(char *to, const char *from) { - /* free the memory used by the to string, if such memory exists, - * and return a pointer to a freshly malloc()'d string with the - * same value as from. - */ + /* free the memory used by the to string, if such memory exists, + * and return a pointer to a freshly malloc()'d string with the + * same value as from. + */ - if (to != NULL) - free(to); + if (to != NULL) + free(to); - return mystrdup(from); + return mystrdup(from); } @@ -1870,54 +1877,55 @@ char *mystrcpy(char *to, const char *from) */ char *mystrdup(const char *from) { - char *tmp; - int stringlength; + char *tmp; + int stringlength; - if (from == NULL || !strlen(from)) { - tmp = NULL; - } else { - stringlength = strlen(from); - stringlength = (stringlength < PATH_MAX ? stringlength : PATH_MAX); - tmp = (char *)mymalloc(stringlength + 1); - strncpy(tmp, from, stringlength); + if (from == NULL || !strlen(from)) { + tmp = NULL; + } else { + stringlength = strlen(from); + stringlength = (stringlength < PATH_MAX ? stringlength : PATH_MAX); + tmp = (char *)mymalloc(stringlength + 1); + strncpy(tmp, from, stringlength); - /* We must ensure the string always has a NULL terminator. - * This necessary because strncpy will not append a NULL terminator - * if the original string is greater than stringlength. - */ - tmp += stringlength; - *tmp = '\0'; - tmp -= stringlength; - } - return tmp; + /* We must ensure the string always has a NULL terminator. + * This necessary because strncpy will not append a NULL terminator + * if the original string is greater than stringlength. + */ + tmp += stringlength; + *tmp = '\0'; + tmp -= stringlength; + } + return tmp; } const char *config_type(config_param *configparam) { - if (configparam->copy == copy_string) - return "string"; - if (configparam->copy == copy_int) - return "int"; - if (configparam->copy == copy_short) - return "short"; - if (configparam->copy == copy_bool) - return "bool"; - return "unknown"; + if (configparam->copy == copy_string) + return "string"; + if (configparam->copy == copy_int) + return "int"; + if (configparam->copy == copy_short) + return "short"; + if (configparam->copy == copy_bool) + return "bool"; + + return "unknown"; } static const char *print_bool(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr) { - int val=config_params[parm].conf_value; + int val = config_params[parm].conf_value; - if (threadnr && - *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) - return NULL; + if (threadnr && + *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) + return NULL; - if (*(int*)((char *)cnt[threadnr] + val)) - return "on"; - else - return "off"; + if (*(int*)((char *)cnt[threadnr] + val)) + return "on"; + else + return "off"; } /* print_string returns a pointer to a string containing the value of the config option @@ -1930,66 +1938,67 @@ static const char *print_string(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr) { - int val=config_params[parm].conf_value; - const char **cptr0, **cptr1; - - /* strcmp does not like NULL so we have to check for this also */ - cptr0 = (const char **)((char *)cnt[0] + val); - cptr1 = (const char **)((char *)cnt[threadnr] + val); - if ((threadnr) && (*cptr0 != NULL) && (*cptr1 != NULL) && (!strcmp(*cptr0, *cptr1))) - return NULL; + int val = config_params[parm].conf_value; + const char **cptr0, **cptr1; + + /* strcmp does not like NULL so we have to check for this also */ + cptr0 = (const char **)((char *)cnt[0] + val); + cptr1 = (const char **)((char *)cnt[threadnr] + val); + if ((threadnr) && (*cptr0 != NULL) && (*cptr1 != NULL) && (!strcmp(*cptr0, *cptr1))) + return NULL; - return *cptr1; + return *cptr1; } static const char *print_int(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr) { - static char retval[20]; - int val = config_params[parm].conf_value; + static char retval[20]; + int val = config_params[parm].conf_value; - if (threadnr && - *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) - return NULL; + if (threadnr && + *(int*)((char *)cnt[threadnr] + val) == *(int*)((char *)cnt[0] + val)) + return NULL; - sprintf(retval, "%d", *(int*)((char *)cnt[threadnr] + val)); + sprintf(retval, "%d", *(int*)((char *)cnt[threadnr] + val)); - return retval; + return retval; } static const char *print_short(struct context **cnt, char **str ATTRIBUTE_UNUSED, int parm, unsigned short int threadnr) { - static char retval[20]; - int val = config_params[parm].conf_value; + static char retval[20]; + int val = config_params[parm].conf_value; - if (threadnr && - *(short int*)((char *)cnt[threadnr] + val) == *(short int*)((char *)cnt[0] + val)) - return NULL; - sprintf(retval, "%d", *(short int*)((char *)cnt[threadnr] + val)); + if (threadnr && + *(short int*)((char *)cnt[threadnr] + val) == *(short int*)((char *)cnt[0] + val)) + return NULL; - return retval; + sprintf(retval, "%d", *(short int*)((char *)cnt[threadnr] + val)); + + return retval; } static const char *print_thread(struct context **cnt, char **str, int parm ATTRIBUTE_UNUSED, unsigned short int threadnr) { - char *retval; - unsigned short int i=0; + char *retval; + unsigned short int i=0; - if (!str || threadnr) - return NULL; + if (!str || threadnr) + return NULL; - retval = mymalloc(1); - retval[0] = 0; - while (cnt[++i]) { - retval = myrealloc(retval, strlen(retval) + strlen(cnt[i]->conf_filename)+10, "print_thread"); - sprintf(retval + strlen(retval), "thread %s\n", cnt[i]->conf_filename); - } - *str = retval; + retval = mymalloc(1); + retval[0] = 0; + while (cnt[++i]) { + retval = myrealloc(retval, strlen(retval) + strlen(cnt[i]->conf_filename) + 10, "print_thread"); + sprintf(retval + strlen(retval), "thread %s\n", cnt[i]->conf_filename); + } + *str = retval; - return NULL; + return NULL; } /* config_thread() is called during initial config file loading each time Motion @@ -2005,72 +2014,72 @@ static const char *print_thread(struct context **cnt, char **str, static struct context **config_thread(struct context **cnt, const char *str, int val ATTRIBUTE_UNUSED) { - int i; - FILE *fp; - - if (cnt[0]->threadnr) - return cnt; + int i; + FILE *fp; + + if (cnt[0]->threadnr) + return cnt; - fp=fopen(str, "r"); - if (!fp) { - motion_log(LOG_ERR, 1, "Thread config file %s not found",str); - return cnt; - } + fp = fopen(str, "r"); - /* Find the current number of threads defined. */ - i=-1; - while (cnt[++i]); + if (!fp) { + motion_log(LOG_ERR, 1, "Thread config file %s not found",str); + return cnt; + } - /* Make space for the threads + the terminating NULL pointer - * in the array of pointers to context structures - * First thread is 0 so the number of threads is i+1 - * plus an extra for the NULL pointer. This gives i+2 - */ - cnt = myrealloc(cnt, sizeof(struct context *)*(i+2), "config_thread"); + /* Find the current number of threads defined. */ + i=-1; + while (cnt[++i]); - /* Now malloc space for an additional context structure for thread nr. i */ - cnt[i] = mymalloc(sizeof(struct context)); - - /* And make this an exact clone of the context structure for thread 0 */ - memcpy(cnt[i], cnt[0], sizeof(struct context)); + /* Make space for the threads + the terminating NULL pointer + * in the array of pointers to context structures + * First thread is 0 so the number of threads is i+1 + * plus an extra for the NULL pointer. This gives i+2 + */ + cnt = myrealloc(cnt, sizeof(struct context *) * (i + 2), "config_thread"); - /* All the integers are copies of the actual value. - * The strings are all pointers to strings so we need to create - * unique malloc'ed space for all the strings that are not NULL and - * change the string pointers to point to the new strings. - * malloc_strings takes care of this. - */ - malloc_strings(cnt[i]); - - /* Mark the end if the array of pointers to context structures */ - cnt[i+1] = NULL; + /* Now malloc space for an additional context structure for thread nr. i */ + cnt[i] = mymalloc(sizeof(struct context)); + + /* And make this an exact clone of the context structure for thread 0 */ + memcpy(cnt[i], cnt[0], sizeof(struct context)); - /* process the thread's config file and notify user on console */ - strcpy(cnt[i]->conf_filename, str); - motion_log(LOG_INFO, 0, "Processing config file %s", str); - conf_process(cnt+i, fp); - - /* Finally we close the thread config file */ - fclose(fp); + /* All the integers are copies of the actual value. + * The strings are all pointers to strings so we need to create + * unique malloc'ed space for all the strings that are not NULL and + * change the string pointers to point to the new strings. + * malloc_strings takes care of this. + */ + malloc_strings(cnt[i]); + + /* Mark the end if the array of pointers to context structures */ + cnt[i + 1] = NULL; - return cnt; + /* process the thread's config file and notify user on console */ + strcpy(cnt[i]->conf_filename, str); + motion_log(LOG_INFO, 0, "Processing config file %s", str); + conf_process(cnt+i, fp); + + /* Finally we close the thread config file */ + fclose(fp); + + return cnt; } static void usage () { - printf("motion Version "VERSION", Copyright 2000-2005 Jeroen Vreeken/Folkert van Heusden/Kenneth Lavrsen\n"); - printf("\nusage:\tmotion [options]\n"); - printf("\n\n"); - printf("Possible options:\n\n"); - printf("-n\t\t\tRun in non-daemon mode.\n"); - printf("-s\t\t\tRun in setup mode.\n"); - printf("-c config\t\tFull path and filename of config file.\n"); - printf("-d level\t\tDebug mode.\n"); - printf("-p process_id_file\tFull path and filename of process id file (pid file).\n"); - printf("-h\t\t\tShow this screen.\n"); - printf("\n"); - printf("Motion is configured using a config file only. If none is supplied,\n"); - printf("it will read motion.conf from current directory, ~/.motion or %s.\n", sysconfdir); - printf("\n"); - + printf("motion Version "VERSION", Copyright 2000-2005 Jeroen Vreeken/Folkert van Heusden/Kenneth Lavrsen\n"); + printf("\nusage:\tmotion [options]\n"); + printf("\n\n"); + printf("Possible options:\n\n"); + printf("-n\t\t\tRun in non-daemon mode.\n"); + printf("-s\t\t\tRun in setup mode.\n"); + printf("-c config\t\tFull path and filename of config file.\n"); + printf("-d level\t\tDebug mode.\n"); + printf("-p process_id_file\tFull path and filename of process id file (pid file).\n"); + printf("-h\t\t\tShow this screen.\n"); + printf("\n"); + printf("Motion is configured using a config file only. If none is supplied,\n"); + printf("it will read motion.conf from current directory, ~/.motion or %s.\n", sysconfdir); + printf("\n"); } diff --git a/conf.h b/conf.h index 787c0b01..62b6ac67 100644 --- a/conf.h +++ b/conf.h @@ -16,114 +16,114 @@ #define _INCLUDE_CONF_H /* - more parameters may be added later. + more parameters may be added later. */ struct config { - int setup_mode; - int width; - int height; - int quality; - int rotate_deg; - int max_changes; - int threshold_tune; - const char *output_normal; - int motion_img; - int output_all; - int gap; - int maxmpegtime; - int snapshot_interval; - const char *locate; - int input; - int norm; - int frame_limit; - int quiet; - int ppm; - int noise; - int noise_tune; - int minimum_frame_time; - int lightswitch; - int autobright; - int brightness; - int contrast; - int saturation; - int hue; - int roundrobin_frames; - int roundrobin_skip; - int pre_capture; - int post_capture; - int switchfilter; - int ffmpeg_cap_new; - int ffmpeg_cap_motion; - int ffmpeg_bps; - int ffmpeg_vbr; - int ffmpeg_deinterlace; - const char *ffmpeg_video_codec; - int webcam_port; - int webcam_quality; - int webcam_motion; - int webcam_maxrate; - int webcam_localhost; - int webcam_limit; - int control_port; - int control_localhost; - int control_html_output; - const char *control_authentication; - unsigned long frequency; - int tuner_number; - int timelapse; - const char *timelapse_mode; + int setup_mode; + int width; + int height; + int quality; + int rotate_deg; + int max_changes; + int threshold_tune; + const char *output_normal; + int motion_img; + int output_all; + int gap; + int maxmpegtime; + int snapshot_interval; + const char *locate; + int input; + int norm; + int frame_limit; + int quiet; + int ppm; + int noise; + int noise_tune; + int minimum_frame_time; + int lightswitch; + int autobright; + int brightness; + int contrast; + int saturation; + int hue; + int roundrobin_frames; + int roundrobin_skip; + int pre_capture; + int post_capture; + int switchfilter; + int ffmpeg_cap_new; + int ffmpeg_cap_motion; + int ffmpeg_bps; + int ffmpeg_vbr; + int ffmpeg_deinterlace; + const char *ffmpeg_video_codec; + int webcam_port; + int webcam_quality; + int webcam_motion; + int webcam_maxrate; + int webcam_localhost; + int webcam_limit; + int control_port; + int control_localhost; + int control_html_output; + const char *control_authentication; + unsigned long frequency; + int tuner_number; + int timelapse; + const char *timelapse_mode; #if (defined(BSD)) - const char *tuner_device; + const char *tuner_device; #endif - const char *video_device; - short unsigned int v4l2_palette; - const char *vidpipe; - const char *filepath; - const char *jpegpath; - const char *mpegpath; - const char *snappath; - const char *timepath; - char *on_event_start; - char *on_event_end; - const char *mask_file; - int smart_mask_speed; - int sql_log_image; - int sql_log_snapshot; - int sql_log_mpeg; - int sql_log_timelapse; - const char *sql_query; - const char *mysql_db; - const char *mysql_host; - const char *mysql_user; - const char *mysql_password; - char *on_picture_save; - char *on_area_detected; - char *on_motion_detected; - char *on_movie_start; - char *on_movie_end; - char *on_camera_lost; - const char *motionvidpipe; - const char *netcam_url; - const char *netcam_userpass; - const char *netcam_http; - const char *netcam_proxy; - unsigned int netcam_broken; - const char *pgsql_db; - const char *pgsql_host; - const char *pgsql_user; - const char *pgsql_password; - int pgsql_port; - int text_changes; - const char *text_left; - const char *text_right; - const char *text_event; - int text_double; - const char *despeckle; - const char *area_detect; - int minimum_motion_frames; - char *pid_file; - int argc; - char **argv; + const char *video_device; + short unsigned int v4l2_palette; + const char *vidpipe; + const char *filepath; + const char *jpegpath; + const char *mpegpath; + const char *snappath; + const char *timepath; + char *on_event_start; + char *on_event_end; + const char *mask_file; + int smart_mask_speed; + int sql_log_image; + int sql_log_snapshot; + int sql_log_mpeg; + int sql_log_timelapse; + const char *sql_query; + const char *mysql_db; + const char *mysql_host; + const char *mysql_user; + const char *mysql_password; + char *on_picture_save; + char *on_area_detected; + char *on_motion_detected; + char *on_movie_start; + char *on_movie_end; + char *on_camera_lost; + const char *motionvidpipe; + const char *netcam_url; + const char *netcam_userpass; + const char *netcam_http; + const char *netcam_proxy; + unsigned int netcam_broken; + const char *pgsql_db; + const char *pgsql_host; + const char *pgsql_user; + const char *pgsql_password; + int pgsql_port; + int text_changes; + const char *text_left; + const char *text_right; + const char *text_event; + int text_double; + const char *despeckle; + const char *area_detect; + int minimum_motion_frames; + char *pid_file; + int argc; + char **argv; }; /** @@ -136,12 +136,12 @@ typedef const char *(* conf_print_func)(struct context **, char **, int, unsigne * description for parameters in the config file */ typedef struct { - const char * param_name; /* name for this parameter */ - const char * param_help; /* short explanation for parameter */ - unsigned short int main_thread; /* belong only to main thread when value>0 */ - int conf_value; /* pointer to a field in struct context */ - conf_copy_func copy; /* a function to set the value in 'config' */ - conf_print_func print; /* a function to output the value to a file */ + const char * param_name; /* name for this parameter */ + const char * param_help; /* short explanation for parameter */ + unsigned short int main_thread; /* belong only to main thread when value>0 */ + int conf_value; /* pointer to a field in struct context */ + conf_copy_func copy; /* a function to set the value in 'config' */ + conf_print_func print; /* a function to output the value to a file */ } config_param; diff --git a/mmx.h b/mmx.h index 18a98b02..b47b17de 100644 --- a/mmx.h +++ b/mmx.h @@ -11,171 +11,171 @@ * values by ULL, lest they be truncated by the compiler) */ -typedef union { - long long q; /* Quadword (64-bit) value */ - unsigned long long uq; /* Unsigned Quadword */ - int d[2]; /* 2 Doubleword (32-bit) values */ - unsigned int ud[2]; /* 2 Unsigned Doubleword */ - short w[4]; /* 4 Word (16-bit) values */ - unsigned short uw[4]; /* 4 Unsigned Word */ - char b[8]; /* 8 Byte (8-bit) values */ - unsigned char ub[8]; /* 8 Unsigned Byte */ - float s[2]; /* Single-precision (32-bit) value */ -} mmx_t; /* On an 8-byte (64-bit) boundary */ +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} mmx_t; /* On an 8-byte (64-bit) boundary */ -#define mmx_i2r(op,imm,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "i" (imm) ) +#define mmx_i2r(op,imm,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "i" (imm) ) -#define mmx_m2r(op,mem,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem)) +#define mmx_m2r(op,mem,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) -#define mmx_r2m(op,reg,mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=m" (mem) \ - : /* nothing */ ) +#define mmx_r2m(op,reg,mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) -#define mmx_r2r(op,regs,regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) +#define mmx_r2r(op,regs,regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) -#define emms() __asm__ __volatile__ ("emms") +#define emms() __asm__ __volatile__ ("emms") -#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) -#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) -#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) +#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) +#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) +#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) -#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) -#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) -#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) +#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) +#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) +#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) -#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) -#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) -#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) -#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) +#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) +#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) +#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) +#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) -#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) -#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) +#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) +#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) -#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) -#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) -#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) -#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) -#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) -#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) +#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) +#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) +#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) +#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) +#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) +#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) -#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) -#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) -#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) -#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) +#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) +#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) +#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) +#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) -#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) -#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) -#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) -#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) +#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) +#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) +#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) +#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) -#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) -#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) +#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) +#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) -#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) -#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) +#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) +#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) -#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) -#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) -#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) -#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) -#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) -#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) +#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) -#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) -#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) -#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) -#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) -#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) -#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) +#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) -#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) -#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) +#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) +#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) -#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) -#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) +#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) +#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) -#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) -#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) +#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) +#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) -#define por_m2r(var,reg) mmx_m2r (por, var, reg) -#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) +#define por_m2r(var,reg) mmx_m2r (por, var, reg) +#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) -#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) -#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) -#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) -#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) -#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) -#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) -#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) -#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) -#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) +#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) +#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) +#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) +#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) +#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) +#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) +#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) +#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) +#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) -#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) -#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) -#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) -#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) -#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) -#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) +#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) +#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) +#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) +#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) +#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) +#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) -#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) -#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) -#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) -#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) -#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) -#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) -#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) -#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) -#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) +#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) +#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) +#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) +#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) +#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) +#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) +#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) +#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) +#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) -#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) -#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) -#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) -#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) -#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) -#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) +#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) +#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) +#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) +#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) +#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) +#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) -#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) -#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) -#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) -#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) +#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) +#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) +#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) +#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) -#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) -#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) -#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) -#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) +#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) +#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) +#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) +#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) -#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) -#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) -#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) -#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) -#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) -#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) +#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) +#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) +#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) +#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) +#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) +#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) -#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) -#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) -#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) -#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) -#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) -#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) +#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) +#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) +#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) +#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) +#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) +#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) -#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) -#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) +#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) +#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) /* 3DNOW extensions */ -#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) -#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) +#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) +#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) /* AMD MMX extensions - also available in intel SSE */ @@ -190,78 +190,78 @@ typedef union { : /* nothing */ \ : "X" (imm) ) -#define mmx_fetch(mem,hint) \ - __asm__ __volatile__ ("prefetch" #hint " %0" \ - : /* nothing */ \ - : "X" (mem)) +#define mmx_fetch(mem,hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "X" (mem)) -#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) +#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) -#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) +#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) -#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) -#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) -#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) -#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) +#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) +#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) +#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) +#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) -#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) +#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) -#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) +#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) -#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) -#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) +#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) +#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) -#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) -#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) +#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) +#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) -#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) -#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) +#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) +#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) -#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) -#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) +#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) +#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) -#define pmovmskb(mmreg,reg) \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) +#define pmovmskb(mmreg,reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) -#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) -#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) +#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) +#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) -#define prefetcht0(mem) mmx_fetch (mem, t0) -#define prefetcht1(mem) mmx_fetch (mem, t1) -#define prefetcht2(mem) mmx_fetch (mem, t2) -#define prefetchnta(mem) mmx_fetch (mem, nta) +#define prefetcht0(mem) mmx_fetch (mem, t0) +#define prefetcht1(mem) mmx_fetch (mem, t1) +#define prefetcht2(mem) mmx_fetch (mem, t2) +#define prefetchnta(mem) mmx_fetch (mem, nta) -#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) -#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) +#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) +#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) -#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) -#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) +#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) -#define sfence() __asm__ __volatile__ ("sfence\n\t") +#define sfence() __asm__ __volatile__ ("sfence\n\t") /* SSE2 */ -#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm) -#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm) -#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm) -#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm) +#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm) +#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm) +#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm) +#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm) -#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm) +#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm) -#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg) -#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var) -#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd) -#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg) -#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var) -#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd) +#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg) +#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var) +#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd) +#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg) +#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var) +#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd) -#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var) +#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var) -#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg) -#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg) +#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg) +#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg) -#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd) -#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd) +#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd) +#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd) #endif /* I386MMX_H */ diff --git a/netcam_jpeg.c b/netcam_jpeg.c index 7301b374..0c21d8c5 100644 --- a/netcam_jpeg.c +++ b/netcam_jpeg.c @@ -1,18 +1,18 @@ /* - * netcam_jpeg.c + * netcam_jpeg.c * - * Module for handling JPEG decompression for network cameras. + * Module for handling JPEG decompression for network cameras. * - * This code was inspired by the original module written by - * Jeroen Vreeken and enhanced by several Motion project - * contributors, particularly Angel Carpintero and - * Christopher Price. + * This code was inspired by the original module written by + * Jeroen Vreeken and enhanced by several Motion project + * contributors, particularly Angel Carpintero and + * Christopher Price. * - * Copyright 2005, William M. Brack - * This program is published under the GNU Public license + * Copyright 2005, William M. Brack + * This program is published under the GNU Public license */ -#include "rotate.h" /* already includes motion.h */ +#include "rotate.h" /* already includes motion.h */ #include #include @@ -23,11 +23,11 @@ * pointer to the standard information) */ typedef struct { - struct jpeg_source_mgr pub; - char *data; - int length; - JOCTET *buffer; - boolean start_of_file; + struct jpeg_source_mgr pub; + char *data; + int length; + JOCTET *buffer; + boolean start_of_file; } netcam_source_mgr; typedef netcam_source_mgr *netcam_src_ptr; @@ -48,68 +48,68 @@ static void netcam_error_exit(j_common_ptr); static void netcam_init_source(j_decompress_ptr cinfo) { - /* - * Get our "private" structure from the libjpeg structure - */ - netcam_src_ptr src = (netcam_src_ptr) cinfo->src; - /* - * Set the 'start_of_file' flag in our private structure - * (used by my_fill_input_buffer) - */ - src->start_of_file = TRUE; + /* + * Get our "private" structure from the libjpeg structure + */ + netcam_src_ptr src = (netcam_src_ptr) cinfo->src; + /* + * Set the 'start_of_file' flag in our private structure + * (used by my_fill_input_buffer) + */ + src->start_of_file = TRUE; } static boolean netcam_fill_input_buffer(j_decompress_ptr cinfo) { - netcam_src_ptr src = (netcam_src_ptr) cinfo->src; - size_t nbytes; + netcam_src_ptr src = (netcam_src_ptr) cinfo->src; + size_t nbytes; - /* - * start_of_file is set any time netcam_init_source has been called - * since the last entry to this routine. This would be the normal - * path when a new image is to be processed. It is assumed that - * this routine will only be called once for the entire image. - * If an unexpected call (with start_of_file FALSE) occurs, the - * routine will insert a "fake" "end of image" marker and return - * to the library to process whatever data remains from the original - * image (the one with errors). - * - * I'm not yet clear on what the result (from the application's - * point of view) will be from this logic. If the application - * expects that a completely new image will be started, this will - * give trouble. - */ - if (src->start_of_file) { - nbytes = src->length; - src->buffer = (JOCTET *) src->data; - } else { - /* Insert a fake EOI marker - as per jpeglib recommendation */ - if (debug_level > CAMERA_VERBOSE) - motion_log(LOG_INFO, 0, "%s: **fake EOI inserted**", __FUNCTION__); - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; /* 0xD9 */ - nbytes = 2; - } + /* + * start_of_file is set any time netcam_init_source has been called + * since the last entry to this routine. This would be the normal + * path when a new image is to be processed. It is assumed that + * this routine will only be called once for the entire image. + * If an unexpected call (with start_of_file FALSE) occurs, the + * routine will insert a "fake" "end of image" marker and return + * to the library to process whatever data remains from the original + * image (the one with errors). + * + * I'm not yet clear on what the result (from the application's + * point of view) will be from this logic. If the application + * expects that a completely new image will be started, this will + * give trouble. + */ + if (src->start_of_file) { + nbytes = src->length; + src->buffer = (JOCTET *) src->data; + } else { + /* Insert a fake EOI marker - as per jpeglib recommendation */ + if (debug_level > CAMERA_VERBOSE) + motion_log(LOG_INFO, 0, "%s: **fake EOI inserted**", __FUNCTION__); + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; /* 0xD9 */ + nbytes = 2; + } - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; - return TRUE; + return TRUE; } static void netcam_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - netcam_src_ptr src = (netcam_src_ptr) cinfo->src; + netcam_src_ptr src = (netcam_src_ptr) cinfo->src; - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) netcam_fill_input_buffer (cinfo); - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) netcam_fill_input_buffer (cinfo); + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } } static void netcam_term_source(j_decompress_ptr cinfo ATTRIBUTE_UNUSED) @@ -119,50 +119,50 @@ static void netcam_term_source(j_decompress_ptr cinfo ATTRIBUTE_UNUSED) /** * netcam_memory_src * - * Routine to setup for fetching data from a netcam buffer, used by the - * JPEG library decompression routine. + * Routine to setup for fetching data from a netcam buffer, used by the + * JPEG library decompression routine. * * Parameters: - * cinfo pointer to the jpeg decompression object - * data pointer to the image data received from a netcam - * length total size of the image + * cinfo pointer to the jpeg decompression object + * data pointer to the image data received from a netcam + * length total size of the image * * Returns: Nothing * */ static void netcam_memory_src(j_decompress_ptr cinfo, char *data, int length) { - netcam_src_ptr src; + netcam_src_ptr src; - if (cinfo->src == NULL) { - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof (netcam_source_mgr)); - } + if (cinfo->src == NULL) { + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof (netcam_source_mgr)); + } - src = (netcam_src_ptr)cinfo->src; - src->data = data; - src->length = length; - src->pub.init_source = netcam_init_source; - src->pub.fill_input_buffer = netcam_fill_input_buffer; - src->pub.skip_input_data = netcam_skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = netcam_term_source; - src->pub.bytes_in_buffer = 0; - src->pub.next_input_byte = NULL; + src = (netcam_src_ptr)cinfo->src; + src->data = data; + src->length = length; + src->pub.init_source = netcam_init_source; + src->pub.fill_input_buffer = netcam_fill_input_buffer; + src->pub.skip_input_data = netcam_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = netcam_term_source; + src->pub.bytes_in_buffer = 0; + src->pub.next_input_byte = NULL; } /** * netcam_error_exit * - * Routine to override the libjpeg error exit routine so - * that we can just throw away the bad frame and continue - * with more data from the netcam. + * Routine to override the libjpeg error exit routine so + * that we can just throw away the bad frame and continue + * with more data from the netcam. * * Parameters * - * cinfo pointer to the decompression control structure + * cinfo pointer to the decompression control structure * * Returns: does an (ugly) longjmp to get back to netcam_jpeg * code @@ -170,254 +170,259 @@ static void netcam_memory_src(j_decompress_ptr cinfo, char *data, int length) */ static void netcam_error_exit(j_common_ptr cinfo) { - /* fetch our pre-stored pointer to the netcam context */ - netcam_context_ptr netcam = cinfo->client_data; - /* output the message associated with the error */ - (*cinfo->err->output_message)(cinfo); - /* set flag to show the decompression had errors */ - netcam->jpeg_error |= 1; - /* need to "cleanup" the aborted decompression */ - jpeg_destroy (cinfo); + /* fetch our pre-stored pointer to the netcam context */ + netcam_context_ptr netcam = cinfo->client_data; + /* output the message associated with the error */ + (*cinfo->err->output_message)(cinfo); + /* set flag to show the decompression had errors */ + netcam->jpeg_error |= 1; + /* need to "cleanup" the aborted decompression */ + jpeg_destroy (cinfo); - if (debug_level > CAMERA_VERBOSE) - motion_log(LOG_ERR, 0, "%s: netcam->jpeg_error %d", __FUNCTION__, netcam->jpeg_error); - - /* jump back to wherever we started */ - longjmp(netcam->setjmp_buffer, 1); + if (debug_level > CAMERA_VERBOSE) + motion_log(LOG_ERR, 0, "%s: netcam->jpeg_error %d", + __FUNCTION__, netcam->jpeg_error); + + /* jump back to wherever we started */ + longjmp(netcam->setjmp_buffer, 1); } /** * netcam_output_message * - * Routine to override the libjpeg error message output routine. - * We do this so that we can output our module and thread i.d., - * as well as put the message to the motion log. + * Routine to override the libjpeg error message output routine. + * We do this so that we can output our module and thread i.d., + * as well as put the message to the motion log. * * Parameters * - * cinfo pointer to the decompression control structure + * cinfo pointer to the decompression control structure * * Returns Nothing * */ static void netcam_output_message(j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; - - /* fetch our pre-stored pointer to the netcam context */ - netcam_context_ptr netcam = cinfo->client_data; + char buffer[JMSG_LENGTH_MAX]; + + /* fetch our pre-stored pointer to the netcam context */ + netcam_context_ptr netcam = cinfo->client_data; - /* - * While experimenting with a "appro" netcam it was discovered - * that the jpeg data produced by the camera caused warning - * messages from libjpeg (JWRN_EXTRANEOUS_DATA). The following - * code is to assure that specific warning is ignored. - * - * NOTE: It's likely that we will discover other error message - * codes which we want to ignore. In that case, we should have - * some sort of table-lookup to decide which messages we really - * care about. - */ - if ( (cinfo->err->msg_code != JWRN_EXTRANEOUS_DATA) && - (cinfo->err->msg_code == JWRN_NOT_SEQUENTIAL) && (!netcam->netcam_broken) ) - netcam->jpeg_error |= 2; /* Set flag to show problem */ - /* - * We only display and log errors when debug_level - * is non-zero. The reasoning here is that these kinds - * of errors are only produced when the input data is - * wrong, and that indicates a network problem rather - * than a problem with the content. - */ - if (debug_level > CAMERA_VERBOSE) { - /* - * Format the message according to library standards. - * Write it out to the motion log. - */ - (*cinfo->err->format_message)(cinfo, buffer); - motion_log(LOG_ERR, 0, "%s: %s", __FUNCTION__, buffer); - } + /* + * While experimenting with a "appro" netcam it was discovered + * that the jpeg data produced by the camera caused warning + * messages from libjpeg (JWRN_EXTRANEOUS_DATA). The following + * code is to assure that specific warning is ignored. + * + * NOTE: It's likely that we will discover other error message + * codes which we want to ignore. In that case, we should have + * some sort of table-lookup to decide which messages we really + * care about. + */ + if ((cinfo->err->msg_code != JWRN_EXTRANEOUS_DATA) && + (cinfo->err->msg_code == JWRN_NOT_SEQUENTIAL) && (!netcam->netcam_broken)) + netcam->jpeg_error |= 2; /* Set flag to show problem */ + /* + * We only display and log errors when debug_level + * is non-zero. The reasoning here is that these kinds + * of errors are only produced when the input data is + * wrong, and that indicates a network problem rather + * than a problem with the content. + */ + if (debug_level > CAMERA_VERBOSE) { + /* + * Format the message according to library standards. + * Write it out to the motion log. + */ + (*cinfo->err->format_message)(cinfo, buffer); + motion_log(LOG_ERR, 0, "%s: %s", __FUNCTION__, buffer); + } } /** * netcam_init_jpeg * - * Initialises the JPEG library prior to doing a - * decompression. + * Initialises the JPEG library prior to doing a + * decompression. * * Parameters: - * netcam pointer to netcam_context - * cinfo pointer to JPEG decompression context + * netcam pointer to netcam_context + * cinfo pointer to JPEG decompression context * * Returns: Error code */ static int netcam_init_jpeg(netcam_context_ptr netcam, j_decompress_ptr cinfo) { - netcam_buff_ptr buff; + netcam_buff_ptr buff; - /* - * First we check whether a new image has arrived. If not, we - * setup to wait for 1/2 a frame time. This will (hopefully) - * help in synchronizing the camera frames with the motion main - * loop. - */ - pthread_mutex_lock(&netcam->mutex); + /* + * First we check whether a new image has arrived. If not, we + * setup to wait for 1/2 a frame time. This will (hopefully) + * help in synchronizing the camera frames with the motion main + * loop. + */ + pthread_mutex_lock(&netcam->mutex); - if (netcam->imgcnt_last == netcam->imgcnt) { /* need to wait */ - struct timespec waittime; - struct timeval curtime; - int retcode; - - /* - * We calculate the delay time (representing the desired frame - * rate). This delay time is in *nanoseconds*. - * We will wait 0.5 seconds which gives a practical minimum - * framerate of 2 which is desired for the motion_loop to - * function. - */ - gettimeofday(&curtime, NULL); - curtime.tv_usec += 500000; + if (netcam->imgcnt_last == netcam->imgcnt) { /* need to wait */ + struct timespec waittime; + struct timeval curtime; + int retcode; + + /* + * We calculate the delay time (representing the desired frame + * rate). This delay time is in *nanoseconds*. + * We will wait 0.5 seconds which gives a practical minimum + * framerate of 2 which is desired for the motion_loop to + * function. + */ + gettimeofday(&curtime, NULL); + curtime.tv_usec += 500000; - if (curtime.tv_usec > 1000000) { - curtime.tv_usec -= 1000000; - curtime.tv_sec++; - } - - waittime.tv_sec = curtime.tv_sec; - waittime.tv_nsec = 1000L * curtime.tv_usec; - - do { - retcode = pthread_cond_timedwait(&netcam->pic_ready, - &netcam->mutex, &waittime); - } while (retcode == EINTR); - - if (retcode) { /* we assume a non-zero reply is ETIMEOUT */ - pthread_mutex_unlock(&netcam->mutex); - - if (debug_level > CAMERA_WARNINGS) - motion_log(-1, 0, "%s: no new pic, no signal rcvd", __FUNCTION__); - - return NETCAM_GENERAL_ERROR | NETCAM_NOTHING_NEW_ERROR; - } - - if (debug_level > CAMERA_VERBOSE) - motion_log(-1, 0, "%s: ***new pic delay successful***", __FUNCTION__); - } - - netcam->imgcnt_last = netcam->imgcnt; + if (curtime.tv_usec > 1000000) { + curtime.tv_usec -= 1000000; + curtime.tv_sec++; + } + + waittime.tv_sec = curtime.tv_sec; + waittime.tv_nsec = 1000L * curtime.tv_usec; + + do { + retcode = pthread_cond_timedwait(&netcam->pic_ready, + &netcam->mutex, &waittime); + } while (retcode == EINTR); + + if (retcode) { /* we assume a non-zero reply is ETIMEOUT */ + pthread_mutex_unlock(&netcam->mutex); + + if (debug_level > CAMERA_WARNINGS) + motion_log(-1, 0, "%s: no new pic, no signal rcvd", __FUNCTION__); + + return NETCAM_GENERAL_ERROR | NETCAM_NOTHING_NEW_ERROR; + } + + if (debug_level > CAMERA_VERBOSE) + motion_log(-1, 0, "%s: ***new pic delay successful***", __FUNCTION__); + } + + netcam->imgcnt_last = netcam->imgcnt; - /* set latest buffer as "current" */ - buff = netcam->latest; - netcam->latest = netcam->jpegbuf; - netcam->jpegbuf = buff; - pthread_mutex_unlock(&netcam->mutex); + /* set latest buffer as "current" */ + buff = netcam->latest; + netcam->latest = netcam->jpegbuf; + netcam->jpegbuf = buff; + pthread_mutex_unlock(&netcam->mutex); - /* clear any error flag from previous work */ - netcam->jpeg_error = 0; - - buff = netcam->jpegbuf; - /* prepare for the decompression */ - /* Initialize the JPEG decompression object */ - jpeg_create_decompress(cinfo); + /* clear any error flag from previous work */ + netcam->jpeg_error = 0; + + buff = netcam->jpegbuf; + /* prepare for the decompression */ + /* Initialize the JPEG decompression object */ + jpeg_create_decompress(cinfo); - /* Set up own error exit routine */ - cinfo->err = jpeg_std_error(&netcam->jerr); - cinfo->client_data = netcam; - netcam->jerr.error_exit = netcam_error_exit; - netcam->jerr.output_message = netcam_output_message; + /* Set up own error exit routine */ + cinfo->err = jpeg_std_error(&netcam->jerr); + cinfo->client_data = netcam; + netcam->jerr.error_exit = netcam_error_exit; + netcam->jerr.output_message = netcam_output_message; - /* Specify the data source as our own routine */ - netcam_memory_src(cinfo, buff->ptr, buff->used); + /* Specify the data source as our own routine */ + netcam_memory_src(cinfo, buff->ptr, buff->used); - /* Read file parameters (rejecting tables-only) */ - jpeg_read_header(cinfo, TRUE); + /* Read file parameters (rejecting tables-only) */ + jpeg_read_header(cinfo, TRUE); - /* Override the desired colour space */ - cinfo->out_color_space = JCS_YCbCr; + /* Override the desired colour space */ + cinfo->out_color_space = JCS_YCbCr; - /* Start the decompressor */ - jpeg_start_decompress(cinfo); + /* Start the decompressor */ + jpeg_start_decompress(cinfo); - if (debug_level > CAMERA_VERBOSE) - motion_log(LOG_INFO, 0, "%s: jpeg_error %d", __FUNCTION__, netcam->jpeg_error); + if (debug_level > CAMERA_VERBOSE) + motion_log(LOG_INFO, 0, "%s: jpeg_error %d", __FUNCTION__, netcam->jpeg_error); - return netcam->jpeg_error; + return netcam->jpeg_error; } static int netcam_image_conv(netcam_context_ptr netcam, - struct jpeg_decompress_struct *cinfo, - unsigned char *image) + struct jpeg_decompress_struct *cinfo, + unsigned char *image) { - JSAMPARRAY line; /* array of decomp data lines */ - unsigned char *wline; /* will point to line[0] */ + JSAMPARRAY line; /* array of decomp data lines */ + unsigned char *wline; /* will point to line[0] */ /* Working variables */ - int linesize, i; - unsigned char *upic, *vpic; - unsigned char *pic = image; - unsigned char y; /* switch for decoding YUV data */ - unsigned int width, height; + int linesize, i; + unsigned char *upic, *vpic; + unsigned char *pic = image; + unsigned char y; /* switch for decoding YUV data */ + unsigned int width, height; - width = cinfo->output_width; - height = cinfo->output_height; - if (width && ((width != netcam->width) || (height != netcam->height))) { - motion_log(LOG_ERR, 0, - "%s: JPEG image size %dx%d, JPEG was %dx%d", - __FUNCTION__, netcam->width, netcam->height, width, height); - jpeg_destroy_decompress (cinfo); - netcam->jpeg_error |= 4; - return netcam->jpeg_error; - } - /* Set the output pointers (these come from YUV411P definition */ - upic = pic + width * height; - vpic = upic + (width * height) / 4; + width = cinfo->output_width; + height = cinfo->output_height; + + if (width && ((width != netcam->width) || (height != netcam->height))) { + motion_log(LOG_ERR, 0, + "%s: JPEG image size %dx%d, JPEG was %dx%d", + __FUNCTION__, netcam->width, netcam->height, width, height); + jpeg_destroy_decompress (cinfo); + netcam->jpeg_error |= 4; + return netcam->jpeg_error; + } + /* Set the output pointers (these come from YUV411P definition */ + upic = pic + width * height; + vpic = upic + (width * height) / 4; - /* YCbCr format will give us one byte each for YUV */ - linesize = cinfo->output_width * 3; + /* YCbCr format will give us one byte each for YUV */ + linesize = cinfo->output_width * 3; - /* Allocate space for one line */ - line = (cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->output_components, 1); + /* Allocate space for one line */ + line = (cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->output_components, 1); - wline = line[0]; - y = 0; - while (cinfo->output_scanline < height) { - jpeg_read_scanlines (cinfo, line, 1); + wline = line[0]; + y = 0; - for (i = 0; i < linesize; i += 3) { - pic[i / 3] = wline[i]; - if (i & 1) { - upic[(i / 3) / 2] = wline[i + 1]; - vpic[(i / 3) / 2] = wline[i + 2]; - } - } - pic += linesize / 3; - if (y++ & 1) { - upic += width / 2; - vpic += width / 2; - } - } + while (cinfo->output_scanline < height) { + jpeg_read_scanlines (cinfo, line, 1); - jpeg_finish_decompress (cinfo); - jpeg_destroy_decompress (cinfo); - if (netcam->cnt->rotate_data.degrees > 0) { - /* rotate as specified */ - rotate_map(netcam->cnt, image); - } + for (i = 0; i < linesize; i += 3) { + pic[i / 3] = wline[i]; + if (i & 1) { + upic[(i / 3) / 2] = wline[i + 1]; + vpic[(i / 3) / 2] = wline[i + 2]; + } + } + pic += linesize / 3; + if (y++ & 1) { + upic += width / 2; + vpic += width / 2; + } + } - if (debug_level > CAMERA_VERBOSE) - motion_log(LOG_INFO, 0, "%s: jpeg_error %d", __FUNCTION__, netcam->jpeg_error); + jpeg_finish_decompress (cinfo); + jpeg_destroy_decompress (cinfo); + + /* rotate as specified */ + if (netcam->cnt->rotate_data.degrees > 0) + rotate_map(netcam->cnt, image); + + + if (debug_level > CAMERA_VERBOSE) + motion_log(LOG_INFO, 0, "%s: jpeg_error %d", + __FUNCTION__, netcam->jpeg_error); - return netcam->jpeg_error; + return netcam->jpeg_error; } /** * netcam_proc_jpeg * - * Routine to decode an image received from a netcam into a YUV420P buffer - * suitable for processing by motion. + * Routine to decode an image received from a netcam into a YUV420P buffer + * suitable for processing by motion. * * Parameters: - * netcam pointer to the netcam_context structure + * netcam pointer to the netcam_context structure * image Pointer to a buffer for the returned image * * Returns: @@ -429,86 +434,86 @@ static int netcam_image_conv(netcam_context_ptr netcam, */ int netcam_proc_jpeg(netcam_context_ptr netcam, unsigned char *image) { - struct jpeg_decompress_struct cinfo; /* decompression control struct */ - int retval = 0; /* value returned to caller */ - int ret; /* working var */ + struct jpeg_decompress_struct cinfo; /* decompression control struct */ + int retval = 0; /* value returned to caller */ + int ret; /* working var */ - /* - * This routine is only called from the main thread. - * We need to "protect" the "latest" image while we - * decompress it. netcam_init_jpeg uses - * netcam->mutex to do this; - */ - if (debug_level > CAMERA_INFO) { - motion_log(LOG_INFO, 0, "%s: processing jpeg image - content length " - "%d", __FUNCTION__, netcam->latest->content_length); - } - - ret = netcam_init_jpeg(netcam, &cinfo); - - if (ret != 0) { - if (debug_level > CAMERA_INFO) - motion_log(LOG_ERR, 0, "%s: ret %d", __FUNCTION__, ret); - return ret; - } + /* + * This routine is only called from the main thread. + * We need to "protect" the "latest" image while we + * decompress it. netcam_init_jpeg uses + * netcam->mutex to do this; + */ + if (debug_level > CAMERA_INFO) + motion_log(LOG_INFO, 0, "%s: processing jpeg image - content length " + "%d", __FUNCTION__, netcam->latest->content_length); + + ret = netcam_init_jpeg(netcam, &cinfo); + + if (ret != 0) { + if (debug_level > CAMERA_INFO) + motion_log(LOG_ERR, 0, "%s: ret %d", __FUNCTION__, ret); + return ret; + } - /* Do a sanity check on dimensions - * If dimensions have changed we throw an - * error message that will cause - * restart of Motion - */ - if (netcam->width) { /* 0 means not yet init'ed */ - if ((cinfo.output_width != netcam->width) || - (cinfo.output_height != netcam->height)) { - retval = NETCAM_RESTART_ERROR; - motion_log(LOG_ERR, 0, - "%s: Camera width/height mismatch " - "with JPEG image - expected %dx%d, JPEG %dx%d", - " retval %d", __FUNCTION__, netcam->width, netcam->height, - cinfo.output_width, cinfo.output_height, retval); - return retval; - } - } + /* Do a sanity check on dimensions + * If dimensions have changed we throw an + * error message that will cause + * restart of Motion + */ + if (netcam->width) { /* 0 means not yet init'ed */ + if ((cinfo.output_width != netcam->width) || + (cinfo.output_height != netcam->height)) { + retval = NETCAM_RESTART_ERROR; + motion_log(LOG_ERR, 0, + "%s: Camera width/height mismatch " + "with JPEG image - expected %dx%d, JPEG %dx%d", + " retval %d", __FUNCTION__, netcam->width, netcam->height, + cinfo.output_width, cinfo.output_height, retval); + return retval; + } + } - /* do the conversion */ - ret = netcam_image_conv(netcam, &cinfo, image); - - if (ret != 0) { - retval |= NETCAM_JPEG_CONV_ERROR; - if (debug_level > CAMERA_INFO) - motion_log(LOG_ERR, 0, "%s: ret %d retval %d", __FUNCTION__, - ret, retval); - } + /* do the conversion */ + ret = netcam_image_conv(netcam, &cinfo, image); + + if (ret != 0) { + retval |= NETCAM_JPEG_CONV_ERROR; + if (debug_level > CAMERA_INFO) + motion_log(LOG_ERR, 0, "%s: ret %d retval %d", __FUNCTION__, + ret, retval); + } - return retval; + return retval; } /** * netcam_get_dimensions * - * This function gets the height and width of the JPEG image - * located in the supplied netcam_image_buffer + * This function gets the height and width of the JPEG image + * located in the supplied netcam_image_buffer * * Parameters * - * netcam pointer to the netcam context + * netcam pointer to the netcam context * * Returns: Nothing, but fills in width and height into context * */ void netcam_get_dimensions(netcam_context_ptr netcam) { - struct jpeg_decompress_struct cinfo; /* decompression control struct */ - int ret; + struct jpeg_decompress_struct cinfo; /* decompression control struct */ + int ret; - ret = netcam_init_jpeg(netcam, &cinfo); + ret = netcam_init_jpeg(netcam, &cinfo); - netcam->width = cinfo.output_width; - netcam->height = cinfo.output_height; - netcam->JFIF_marker = cinfo.saw_JFIF_marker; + netcam->width = cinfo.output_width; + netcam->height = cinfo.output_height; + netcam->JFIF_marker = cinfo.saw_JFIF_marker; - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); - if (debug_level > CAMERA_INFO) - motion_log(LOG_ERR, 0, "%s: JFIF_marker %s PRESENT ret %d", __FUNCTION__, netcam->JFIF_marker ? "IS" : "NOT", ret); + if (debug_level > CAMERA_INFO) + motion_log(LOG_ERR, 0, "%s: JFIF_marker %s PRESENT ret %d", + __FUNCTION__, netcam->JFIF_marker ? "IS" : "NOT", ret); } diff --git a/netcam_wget.h b/netcam_wget.h index f8ed9984..9b38bce2 100644 --- a/netcam_wget.h +++ b/netcam_wget.h @@ -1,6 +1,6 @@ /* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002 - Free Software Foundation, Inc. + Free Software Foundation, Inc. Additional Copyright (C) 2004-2005 Christopher Price, Angel Carpintero, and other contributing authors. @@ -31,11 +31,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Retrieval stream */ struct rbuf { - char buffer[4096]; /* the input buffer */ - char *buffer_pos; /* current position in the buffer */ - size_t buffer_left; /* number of bytes left in the buffer: - buffer_left = buffer_end - buffer_pos */ - int ret; /* used by RBUF_READCHAR macro */ + char buffer[4096]; /* the input buffer */ + char *buffer_pos; /* current position in the buffer */ + size_t buffer_left; /* number of bytes left in the buffer: + buffer_left = buffer_end - buffer_pos */ + int ret; /* used by RBUF_READCHAR macro */ }; /* Read a character from RBUF. If there is anything in the buffer, @@ -50,12 +50,12 @@ struct rbuf should return the character or EOF, and in case of error store it to rbuf->err or something. */ -#define RBUF_READCHAR(netcam, store) \ -((netcam)->response->buffer_left ? (--(netcam)->response->buffer_left, \ -*((char *) (store)) = *(netcam)->response->buffer_pos++, 1) \ -: ((netcam)->response->buffer_pos = (netcam)->response->buffer, \ -((((netcam)->response->ret = rbuf_read_bufferful (netcam)) <= 0) \ -? (netcam)->response->ret : ((netcam)->response->buffer_left = (netcam->response)->ret - 1, \ +#define RBUF_READCHAR(netcam, store) \ +((netcam)->response->buffer_left ? (--(netcam)->response->buffer_left, \ +*((char *) (store)) = *(netcam)->response->buffer_pos++, 1) \ +: ((netcam)->response->buffer_pos = (netcam)->response->buffer, \ +((((netcam)->response->ret = rbuf_read_bufferful (netcam)) <= 0) \ +? (netcam)->response->ret : ((netcam)->response->buffer_left = (netcam->response)->ret - 1, \ *((char *) (store)) = *(netcam)->response->buffer_pos++,1)))) /* Function declarations */ @@ -76,8 +76,16 @@ void base64_encode(const char *, char *, int); char *strdupdelim(const char *, const char *); int http_process_type(const char *, void *); -enum { HG_OK, HG_ERROR, HG_EOF}; -enum header_get_flags{ HG_NONE = 0,HG_NO_CONTINUATIONS = 0x2 }; +enum { + HG_OK, + HG_ERROR, + HG_EOF +}; + +enum header_get_flags { + HG_NONE = 0, + HG_NO_CONTINUATIONS = 0x2 +}; int header_get (netcam_context_ptr, char **, enum header_get_flags); int header_process (const char *, const char *, diff --git a/track.c b/track.c index 3ebca486..56b74b66 100644 --- a/track.c +++ b/track.c @@ -1,9 +1,9 @@ -/* track.c +/* track.c * - * Experimental motion tracking. + * Experimental motion tracking. * - * Copyright 2000, Jeroen Vreeken - * This program is published under the GNU Public license + * Copyright 2000, Jeroen Vreeken + * This program is published under the GNU Public license */ #include @@ -16,823 +16,848 @@ struct trackoptions track_template = { - dev: -1, /* dev open */ - port: NULL, /* char *port */ - motorx: 0, /* int motorx */ - motory: 0, /* int motory */ - maxx: 0, /* int maxx; */ - maxy: 0, /* int maxy; */ - speed: TRACK_SPEED, /* speed */ - stepsize: TRACK_STEPSIZE, /* stepsize */ - active: 0, /* auto tracking active */ - minmaxfound: 0, /* flag for minmax values stored for pwc based camera */ - step_angle_x: 10, /* step angle in degrees X-axis that camera moves during auto tracking */ - step_angle_y: 10, /* step angle in degrees Y-axis that camera moves during auto tracking */ - move_wait: 10 /* number of frames to disable motion detection after camera moving */ + dev: -1, /* dev open */ + port: NULL, /* char *port */ + motorx: 0, /* int motorx */ + motory: 0, /* int motory */ + maxx: 0, /* int maxx; */ + maxy: 0, /* int maxy; */ + speed: TRACK_SPEED, /* speed */ + stepsize: TRACK_STEPSIZE, /* stepsize */ + active: 0, /* auto tracking active */ + minmaxfound: 0, /* flag for minmax values stored for pwc based camera */ + step_angle_x: 10, /* step angle in degrees X-axis that camera moves during auto tracking */ + step_angle_y: 10, /* step angle in degrees Y-axis that camera moves during auto tracking */ + move_wait: 10 /* number of frames to disable motion detection after camera moving */ }; /* Add your own center and move functions here: */ -static unsigned short int stepper_center(struct context *cnt, int xoff, int yoff ATTRIBUTE_UNUSED); -static unsigned short int stepper_move(struct context *cnt, struct coord *cent, struct images *imgs); -static unsigned short int iomojo_center(struct context *cnt, int xoff, int yoff); -static unsigned short int iomojo_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs); +static unsigned short int stepper_center(struct context *, int xoff, int yoff ATTRIBUTE_UNUSED); +static unsigned short int stepper_move(struct context *, struct coord *, struct images *); +static unsigned short int iomojo_center(struct context *, int xoff, int yoff); +static unsigned short int iomojo_move(struct context *, int dev, struct coord *, struct images *); #ifndef WITHOUT_V4L -static unsigned short int lqos_center(struct context *cnt, int dev, int xoff, int yoff); -static unsigned short int lqos_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs, unsigned short int manual); +static unsigned short int lqos_center(struct context *, int dev, int xoff, int yoff); +static unsigned short int lqos_move(struct context *, int dev, struct coord *, struct images *, + unsigned short int); #ifdef MOTION_V4L2 -static unsigned short int uvc_center(struct context *cnt, int dev, int xoff, int yoff); -static unsigned short int uvc_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs, unsigned short int manual); +static unsigned short int uvc_center(struct context *, int dev, int xoff, int yoff); +static unsigned short int uvc_move(struct context *, int dev, struct coord *, struct images *, + unsigned short int); #endif /* MOTION_V4L2 */ #endif /* WITHOUT_V4L */ /* Add a call to your functions here: */ -unsigned short int track_center(struct context *cnt, int dev ATTRIBUTE_UNUSED, unsigned short int manual, int xoff, int yoff) +unsigned short int track_center(struct context *cnt, int dev ATTRIBUTE_UNUSED, + unsigned short int manual, int xoff, int yoff) { - if (!manual && !cnt->track.active) - return 0; - if (cnt->track.type == TRACK_TYPE_STEPPER){ - unsigned short int ret; - ret = stepper_center(cnt, xoff, yoff); - if (!ret) { - motion_log(LOG_ERR, 1, "track_center: internal error (stepper_center)"); - return 0; - } - else return ret; - } -#ifndef WITHOUT_V4L - else if (cnt->track.type == TRACK_TYPE_PWC) - return lqos_center(cnt, dev, xoff, yoff); + if (!manual && !cnt->track.active) + return 0; + + if (cnt->track.type == TRACK_TYPE_STEPPER){ + unsigned short int ret; + ret = stepper_center(cnt, xoff, yoff); + if (!ret) { + motion_log(LOG_ERR, 1, "track_center: internal error (stepper_center)"); + return 0; + } + else return ret; + } +#ifndef WITHOUT_V4L + else if (cnt->track.type == TRACK_TYPE_PWC) + return lqos_center(cnt, dev, xoff, yoff); #ifdef MOTION_V4L2 - else if (cnt->track.type == TRACK_TYPE_UVC) - return uvc_center(cnt, dev, xoff, yoff); + else if (cnt->track.type == TRACK_TYPE_UVC) + return uvc_center(cnt, dev, xoff, yoff); #endif /* MOTION_V4L2 */ #endif /* WITHOUT_V4L */ - else if (cnt->track.type == TRACK_TYPE_IOMOJO) - return iomojo_center(cnt, xoff, yoff); - else if (cnt->track.type == TRACK_TYPE_GENERIC) - return 10; // FIX ME. I chose to return something reasonable. + else if (cnt->track.type == TRACK_TYPE_IOMOJO) + return iomojo_center(cnt, xoff, yoff); + else if (cnt->track.type == TRACK_TYPE_GENERIC) + return 10; // FIX ME. I chose to return something reasonable. - motion_log(LOG_ERR, 1, "track_center: internal error, %hu is not a known track-type", cnt->track.type); + motion_log(LOG_ERR, 1, "track_center: internal error, %hu is not a known track-type", + cnt->track.type); - return 0; + return 0; } /* Add a call to your functions here: */ -unsigned short int track_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs, unsigned short int manual) +unsigned short int track_move(struct context *cnt, int dev, struct coord *cent, + struct images *imgs, unsigned short int manual) { - if (!manual && !cnt->track.active) - return 0; - if (cnt->track.type == TRACK_TYPE_STEPPER) - return stepper_move(cnt, cent, imgs); + if (!manual && !cnt->track.active) + return 0; + + if (cnt->track.type == TRACK_TYPE_STEPPER) + return stepper_move(cnt, cent, imgs); #ifndef WITHOUT_V4L - else if (cnt->track.type == TRACK_TYPE_PWC) - return lqos_move(cnt, dev, cent, imgs, manual); + else if (cnt->track.type == TRACK_TYPE_PWC) + return lqos_move(cnt, dev, cent, imgs, manual); #ifdef MOTION_V4L2 - else if (cnt->track.type == TRACK_TYPE_UVC) - return uvc_move(cnt, dev, cent, imgs, manual); + else if (cnt->track.type == TRACK_TYPE_UVC) + return uvc_move(cnt, dev, cent, imgs, manual); #endif /* MOTION_V4L2 */ #endif /* WITHOUT_V4L */ - else if (cnt->track.type == TRACK_TYPE_IOMOJO) - return iomojo_move(cnt, dev, cent, imgs); - else if (cnt->track.type == TRACK_TYPE_GENERIC) - return cnt->track.move_wait; // FIX ME. I chose to return something reasonable. + else if (cnt->track.type == TRACK_TYPE_IOMOJO) + return iomojo_move(cnt, dev, cent, imgs); + else if (cnt->track.type == TRACK_TYPE_GENERIC) + return cnt->track.move_wait; // FIX ME. I chose to return something reasonable. - motion_log(LOG_ERR, 1, "track_move: internal error, %hu is not a known track-type", cnt->track.type); + motion_log(LOG_ERR, 1, "track_move: internal error, %hu is not a known track-type", cnt->track.type); - return 0; + return 0; } /****************************************************************************** - Stepper motor on serial port - http://www.lavrsen.dk/twiki/bin/view/Motion/MotionTracking - http://www.lavrsen.dk/twiki/bin/view/Motion/MotionTrackerAPI + Stepper motor on serial port + http://www.lavrsen.dk/twiki/bin/view/Motion/MotionTracking + http://www.lavrsen.dk/twiki/bin/view/Motion/MotionTrackerAPI ******************************************************************************/ -static unsigned short int stepper_command(struct context *cnt, unsigned short int motor, unsigned short int command, - unsigned short int data) +static unsigned short int stepper_command(struct context *cnt, unsigned short int motor, + unsigned short int command, unsigned short int data) { - char buffer[3]; - time_t timeout=time(NULL); + char buffer[3]; + time_t timeout = time(NULL); - buffer[0]=motor; - buffer[1]=command; - buffer[2]=data; - if (write(cnt->track.dev, buffer, 3)!=3){ - motion_log(LOG_ERR, 1, "stepper_command port %s dev fd %i, motor %hu command %hu data %hu", - cnt->track.port, cnt->track.dev, motor, command, data); - return 0; - } + buffer[0] = motor; + buffer[1] = command; + buffer[2] = data; + if (write(cnt->track.dev, buffer, 3) != 3){ + motion_log(LOG_ERR, 1, "stepper_command port %s dev fd %i, motor %hu command %hu data %hu", + cnt->track.port, cnt->track.dev, motor, command, data); + return 0; + } - while (read(cnt->track.dev, buffer, 1)!=1 && time(NULL) < timeout+1); - if (time(NULL) >= timeout+2) { - motion_log(LOG_ERR, 1, "Status byte timeout!"); - return 0; - } + while (read(cnt->track.dev, buffer, 1) != 1 && time(NULL) < timeout + 1); - return buffer[0]; + if (time(NULL) >= timeout + 2) { + motion_log(LOG_ERR, 1, "Status byte timeout!"); + return 0; + } + + return buffer[0]; } static unsigned short int stepper_status(struct context *cnt, unsigned short int motor) { - return stepper_command(cnt, motor, STEPPER_COMMAND_STATUS, 0); + return stepper_command(cnt, motor, STEPPER_COMMAND_STATUS, 0); } static unsigned short int stepper_center(struct context *cnt, int x_offset, int y_offset) { - struct termios adtio; + struct termios adtio; - if (cnt->track.dev<0) { - motion_log(LOG_INFO, 0, "Try to open serial device %s", cnt->track.port); - - if ((cnt->track.dev=open(cnt->track.port, O_RDWR | O_NOCTTY)) < 0) { - motion_log(LOG_ERR, 1, "Unable to open serial device %s", cnt->track.port); - return 0; - } + if (cnt->track.dev < 0) { + motion_log(LOG_INFO, 0, "Try to open serial device %s", cnt->track.port); + + if ((cnt->track.dev=open(cnt->track.port, O_RDWR | O_NOCTTY)) < 0) { + motion_log(LOG_ERR, 1, "Unable to open serial device %s", cnt->track.port); + return 0; + } - bzero (&adtio, sizeof(adtio)); - adtio.c_cflag= STEPPER_BAUDRATE | CS8 | CLOCAL | CREAD; - adtio.c_iflag= IGNPAR; - adtio.c_oflag= 0; - adtio.c_lflag= 0; /* non-canon, no echo */ - adtio.c_cc[VTIME]=0; /* timer unused */ - adtio.c_cc[VMIN]=0; /* blocking read until 1 char */ - tcflush (cnt->track.dev, TCIFLUSH); + bzero (&adtio, sizeof(adtio)); + adtio.c_cflag = STEPPER_BAUDRATE | CS8 | CLOCAL | CREAD; + adtio.c_iflag = IGNPAR; + adtio.c_oflag = 0; + adtio.c_lflag = 0; /* non-canon, no echo */ + adtio.c_cc[VTIME] = 0; /* timer unused */ + adtio.c_cc[VMIN] = 0; /* blocking read until 1 char */ + tcflush (cnt->track.dev, TCIFLUSH); - if (tcsetattr(cnt->track.dev, TCSANOW, &adtio) < 0) { - motion_log(LOG_ERR, 1, "Unable to initialize serial device %s", cnt->track.port); - return 0; - } - motion_log(LOG_INFO, 0, "Opened serial device %s and initialize, fd %i", cnt->track.port, cnt->track.dev); - } + if (tcsetattr(cnt->track.dev, TCSANOW, &adtio) < 0) { + motion_log(LOG_ERR, 1, "Unable to initialize serial device %s", cnt->track.port); + return 0; + } + motion_log(LOG_INFO, 0, "Opened serial device %s and initialize, fd %i", + cnt->track.port, cnt->track.dev); + } - /* x-axis */ - - stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_SPEED, cnt->track.speed); - stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_LEFT_N, cnt->track.maxx); + /* x-axis */ + + stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_SPEED, cnt->track.speed); + stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_LEFT_N, cnt->track.maxx); - while (stepper_status(cnt, cnt->track.motorx) & STEPPER_STATUS_LEFT); + while (stepper_status(cnt, cnt->track.motorx) & STEPPER_STATUS_LEFT); - stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_RIGHT_N, - cnt->track.maxx / 2 + x_offset * cnt->track.stepsize); + stepper_command(cnt, cnt->track.motorx, STEPPER_COMMAND_RIGHT_N, + cnt->track.maxx / 2 + x_offset * cnt->track.stepsize); - while (stepper_status(cnt, cnt->track.motorx) & STEPPER_STATUS_RIGHT); + while (stepper_status(cnt, cnt->track.motorx) & STEPPER_STATUS_RIGHT); - /* y-axis */ + /* y-axis */ - stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_SPEED, cnt->track.speed); - stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_UP_N, cnt->track.maxy); + stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_SPEED, cnt->track.speed); + stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_UP_N, cnt->track.maxy); - while (stepper_status(cnt, cnt->track.motory) & STEPPER_STATUS_UP) - - stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_DOWN_N, - cnt->track.maxy / 2 + y_offset * cnt->track.stepsize); - - while (stepper_status(cnt, cnt->track.motory) & STEPPER_STATUS_DOWN); - - return cnt->track.move_wait; + while (stepper_status(cnt, cnt->track.motory) & STEPPER_STATUS_UP) + + stepper_command(cnt, cnt->track.motory, STEPPER_COMMAND_DOWN_N, + cnt->track.maxy / 2 + y_offset * cnt->track.stepsize); + + while (stepper_status(cnt, cnt->track.motory) & STEPPER_STATUS_DOWN); + + return cnt->track.move_wait; } static unsigned short int stepper_move(struct context *cnt, struct coord *cent, struct images *imgs) { - unsigned short int command = 0, data = 0; + unsigned short int command = 0, data = 0; - if (cnt->track.dev < 0){ - motion_log(LOG_INFO, 0, "No device %s started yet , trying stepper_center()", cnt->track.port); - if (!stepper_center(cnt, 0, 0)){ - motion_log(LOG_ERR, 1, "Stepper_center() failed to initialize stepper device on %s , fd [%i].", - cnt->track.port, cnt->track.dev); - return 0; - } - motion_log(LOG_INFO, 0, "stepper_center() succeed , device started %s , fd [%i]", cnt->track.port, cnt->track.dev); - } + if (cnt->track.dev < 0) { + motion_log(LOG_INFO, 0, "No device %s started yet , trying stepper_center()", cnt->track.port); + if (!stepper_center(cnt, 0, 0)){ + motion_log(LOG_ERR, 1, "Stepper_center() failed to initialize stepper device on %s , fd [%i].", + cnt->track.port, cnt->track.dev); + return 0; + } + motion_log(LOG_INFO, 0, "stepper_center() succeed , device started %s , fd [%i]", cnt->track.port, cnt->track.dev); + } - /* x-axis */ - - if (cent->x < imgs->width / 2) { - command = STEPPER_COMMAND_LEFT_N; - data = imgs->width / 2 - cent->x; - } + /* x-axis */ + + if (cent->x < imgs->width / 2) { + command = STEPPER_COMMAND_LEFT_N; + data = imgs->width / 2 - cent->x; + } - if (cent->x > imgs->width / 2) { - command = STEPPER_COMMAND_RIGHT_N; - data = cent->x - imgs->width / 2; - } + if (cent->x > imgs->width / 2) { + command = STEPPER_COMMAND_RIGHT_N; + data = cent->x - imgs->width / 2; + } - data = data * cnt->track.stepsize / imgs->width; + data = data * cnt->track.stepsize / imgs->width; - if (data) stepper_command(cnt, cnt->track.motorx, command, data); + if (data) + stepper_command(cnt, cnt->track.motorx, command, data); - /* y-axis */ + /* y-axis */ - if (cent->y < imgs->height / 2) { - command = STEPPER_COMMAND_UP_N; - data = imgs->height / 2 - cent->y; - } + if (cent->y < imgs->height / 2) { + command = STEPPER_COMMAND_UP_N; + data = imgs->height / 2 - cent->y; + } - if (cent->y > imgs->height / 2) { - command = STEPPER_COMMAND_DOWN_N; - data = cent->y - imgs->height / 2; - } - - data = data * cnt->track.stepsize / imgs->height; + if (cent->y > imgs->height / 2) { + command = STEPPER_COMMAND_DOWN_N; + data = cent->y - imgs->height / 2; + } + + data = data * cnt->track.stepsize / imgs->height; - if (data) stepper_command(cnt, cnt->track.motory, command, data); - - - return cnt->track.move_wait; + if (data) + stepper_command(cnt, cnt->track.motory, command, data); + + + return cnt->track.move_wait; } /****************************************************************************** - Iomojo Smilecam on serial port + Iomojo Smilecam on serial port ******************************************************************************/ static char iomojo_command(struct context *cnt, char *command, unsigned short int len, unsigned short int ret) { - char buffer[1]; - time_t timeout = time(NULL); + char buffer[1]; + time_t timeout = time(NULL); - if (write(cnt->track.dev, command, len) != len) - return 0; + if (write(cnt->track.dev, command, len) != len) + return 0; - if (ret) { - while (read(cnt->track.dev, buffer, 1) != 1 && time(NULL) < timeout + 2); - - if (time(NULL) >= timeout + 2) { - motion_log(LOG_ERR, 1, "Return byte timeout!"); - return 0; - } - } - /* range values ? */ - return buffer[0]; + if (ret) { + while (read(cnt->track.dev, buffer, 1) != 1 && time(NULL) < timeout + 2); + + if (time(NULL) >= timeout + 2) { + motion_log(LOG_ERR, 1, "Return byte timeout!"); + return 0; + } + } + /* range values ? */ + return buffer[0]; } static void iomojo_setspeed(struct context *cnt, unsigned short int speed) { - char command[3]; - - command[0] = IOMOJO_SETSPEED_CMD; - command[1] = cnt->track.iomojo_id; - command[2] = speed; - - if (iomojo_command(cnt, command, 3, 1)!=IOMOJO_SETSPEED_RET) - motion_log(LOG_ERR, 1, "Unable to set camera speed"); + char command[3]; + + command[0] = IOMOJO_SETSPEED_CMD; + command[1] = cnt->track.iomojo_id; + command[2] = speed; + + if (iomojo_command(cnt, command, 3, 1)!=IOMOJO_SETSPEED_RET) + motion_log(LOG_ERR, 1, "Unable to set camera speed"); } static void iomojo_movehome(struct context *cnt) { - char command[2]; - - command[0] = IOMOJO_MOVEHOME; - command[1] = cnt->track.iomojo_id; + char command[2]; + + command[0] = IOMOJO_MOVEHOME; + command[1] = cnt->track.iomojo_id; - iomojo_command(cnt, command, 2, 0); + iomojo_command(cnt, command, 2, 0); } static unsigned short int iomojo_center(struct context *cnt, int x_offset, int y_offset) { - struct termios adtio; - char command[5], direction=0; + struct termios adtio; + char command[5], direction = 0; - if (cnt->track.dev<0) { - if ((cnt->track.dev=open(cnt->track.port, O_RDWR | O_NOCTTY)) < 0) { - motion_log(LOG_ERR, 1, "Unable to open serial device %s", cnt->track.port); - return 0; - } - bzero (&adtio, sizeof(adtio)); - adtio.c_cflag = IOMOJO_BAUDRATE | CS8 | CLOCAL | CREAD; - adtio.c_iflag = IGNPAR; - adtio.c_oflag = 0; - adtio.c_lflag = 0; /* non-canon, no echo */ - adtio.c_cc[VTIME] = 0; /* timer unused */ - adtio.c_cc[VMIN] = 0; /* blocking read until 1 char */ - tcflush(cnt->track.dev, TCIFLUSH); - if (tcsetattr(cnt->track.dev, TCSANOW, &adtio) < 0) { - motion_log(LOG_ERR, 1, "Unable to initialize serial device %s", cnt->track.port); - return 0; - } - } + if (cnt->track.dev<0) { + if ((cnt->track.dev=open(cnt->track.port, O_RDWR | O_NOCTTY)) < 0) { + motion_log(LOG_ERR, 1, "Unable to open serial device %s", cnt->track.port); + return 0; + } - iomojo_setspeed(cnt, 40); - iomojo_movehome(cnt); + bzero (&adtio, sizeof(adtio)); + adtio.c_cflag = IOMOJO_BAUDRATE | CS8 | CLOCAL | CREAD; + adtio.c_iflag = IGNPAR; + adtio.c_oflag = 0; + adtio.c_lflag = 0; /* non-canon, no echo */ + adtio.c_cc[VTIME] = 0; /* timer unused */ + adtio.c_cc[VMIN] = 0; /* blocking read until 1 char */ + tcflush(cnt->track.dev, TCIFLUSH); + if (tcsetattr(cnt->track.dev, TCSANOW, &adtio) < 0) { + motion_log(LOG_ERR, 1, "Unable to initialize serial device %s", cnt->track.port); + return 0; + } + } - if (x_offset || y_offset) { - if (x_offset > 0) - direction |= IOMOJO_DIRECTION_RIGHT; - else { - direction |= IOMOJO_DIRECTION_LEFT; - x_offset *= -1; - } + iomojo_setspeed(cnt, 40); + iomojo_movehome(cnt); - if (y_offset > 0) - direction |= IOMOJO_DIRECTION_UP; - else { - direction |= IOMOJO_DIRECTION_DOWN; - y_offset *= -1; - } + if (x_offset || y_offset) { + if (x_offset > 0) + direction |= IOMOJO_DIRECTION_RIGHT; + else { + direction |= IOMOJO_DIRECTION_LEFT; + x_offset *= -1; + } - if (x_offset > 180) - x_offset = 180; + if (y_offset > 0) + direction |= IOMOJO_DIRECTION_UP; + else { + direction |= IOMOJO_DIRECTION_DOWN; + y_offset *= -1; + } - if (y_offset > 60) - y_offset = 60; + if (x_offset > 180) + x_offset = 180; - command[0] = IOMOJO_MOVEOFFSET_CMD; - command[1] = cnt->track.iomojo_id; - command[2] = direction; - command[3] = x_offset; - command[4] = y_offset; - iomojo_command(cnt, command, 5, 0); - } + if (y_offset > 60) + y_offset = 60; - motion_log(LOG_INFO, 0, "iomojo_center() succeed"); + command[0] = IOMOJO_MOVEOFFSET_CMD; + command[1] = cnt->track.iomojo_id; + command[2] = direction; + command[3] = x_offset; + command[4] = y_offset; + iomojo_command(cnt, command, 5, 0); + } - return cnt->track.move_wait; + motion_log(LOG_INFO, 0, "iomojo_center() succeed"); + + return cnt->track.move_wait; } static unsigned short int iomojo_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs) { - char command[5]; - int direction = 0; - int nx = 0, ny = 0; - int i; - - if (dev < 0) - if (!iomojo_center(cnt, 0, 0)) - return 0; + char command[5]; + int direction = 0; + int nx = 0, ny = 0; + int i; + + if (dev < 0) + if (!iomojo_center(cnt, 0, 0)) + return 0; - if (cent->x < imgs->width / 2) { - direction |= IOMOJO_DIRECTION_LEFT; - nx = imgs->width / 2 - cent->x; - } + if (cent->x < imgs->width / 2) { + direction |= IOMOJO_DIRECTION_LEFT; + nx = imgs->width / 2 - cent->x; + } - if (cent->x > imgs->width / 2) { - direction |= IOMOJO_DIRECTION_RIGHT; - nx = cent->x - imgs->width / 2; - } + if (cent->x > imgs->width / 2) { + direction |= IOMOJO_DIRECTION_RIGHT; + nx = cent->x - imgs->width / 2; + } - if (cent->y < imgs->height / 2) { - direction |= IOMOJO_DIRECTION_DOWN; - ny = imgs->height / 2 - cent->y; - } + if (cent->y < imgs->height / 2) { + direction |= IOMOJO_DIRECTION_DOWN; + ny = imgs->height / 2 - cent->y; + } - if (cent->y > imgs->height / 2) { - direction |= IOMOJO_DIRECTION_UP; - ny = cent->y - imgs->height / 2; - } + if (cent->y > imgs->height / 2) { + direction |= IOMOJO_DIRECTION_UP; + ny = cent->y - imgs->height / 2; + } - nx = nx * 72 / imgs->width; - ny = ny * 72 / imgs->height; + nx = nx * 72 / imgs->width; + ny = ny * 72 / imgs->height; - if (nx || ny) { - if (nx > 180) - nx = 180; + if (nx || ny) { + if (nx > 180) + nx = 180; - if (ny > 60) - ny = 60; + if (ny > 60) + ny = 60; - command[0] = IOMOJO_MOVEOFFSET_CMD; - command[1] = cnt->track.iomojo_id; - command[2] = direction; - command[3] = nx; - command[4] = ny; - iomojo_command(cnt, command, 5, 0); + command[0] = IOMOJO_MOVEOFFSET_CMD; + command[1] = cnt->track.iomojo_id; + command[2] = direction; + command[3] = nx; + command[4] = ny; + iomojo_command(cnt, command, 5, 0); - /* Number of frames to skip while moving */ - if (ny >= nx) - i = 25 * ny / 90; - else - i = 25 * nx / 90; - return i; - } + /* Number of frames to skip while moving */ + if (ny >= nx) + i = 25 * ny / 90; + else + i = 25 * nx / 90; + return i; + } - return 0; + return 0; } /****************************************************************************** - Logitech QuickCam Orbit camera tracking code by folkert@vanheusden.com + Logitech QuickCam Orbit camera tracking code by folkert@vanheusden.com ******************************************************************************/ #ifndef WITHOUT_V4L static unsigned short int lqos_center(struct context *cnt, int dev, int x_angle, int y_angle) { - int reset = 3; - struct pwc_mpt_angles pma; - struct pwc_mpt_range pmr; + int reset = 3; + struct pwc_mpt_angles pma; + struct pwc_mpt_range pmr; - if (cnt->track.dev==-1) { + if (cnt->track.dev == -1) { - if (ioctl(dev, VIDIOCPWCMPTRESET, &reset) == -1) { - motion_log(LOG_ERR, 1, "Failed to reset pwc camera to starting position! Reason"); - return 0; - } + if (ioctl(dev, VIDIOCPWCMPTRESET, &reset) == -1) { + motion_log(LOG_ERR, 1, "Failed to reset pwc camera to starting position! Reason"); + return 0; + } - SLEEP(6,0) + SLEEP(6,0) - if (ioctl(dev, VIDIOCPWCMPTGRANGE, &pmr) == -1) { - motion_log(LOG_ERR, 1, "failed VIDIOCPWCMPTGRANGE"); - return 0; - } + if (ioctl(dev, VIDIOCPWCMPTGRANGE, &pmr) == -1) { + motion_log(LOG_ERR, 1, "failed VIDIOCPWCMPTGRANGE"); + return 0; + } - cnt->track.dev = dev; - cnt->track.minmaxfound = 1; - cnt->track.panmin = pmr.pan_min; - cnt->track.panmax = pmr.pan_max; - cnt->track.tiltmin = pmr.tilt_min; - cnt->track.tiltmax = pmr.tilt_max; - } + cnt->track.dev = dev; + cnt->track.minmaxfound = 1; + cnt->track.panmin = pmr.pan_min; + cnt->track.panmax = pmr.pan_max; + cnt->track.tiltmin = pmr.tilt_min; + cnt->track.tiltmax = pmr.tilt_max; + } - if (ioctl(dev, VIDIOCPWCMPTGANGLE, &pma) == -1) - motion_log(LOG_ERR, 1, "ioctl VIDIOCPWCMPTGANGLE"); - - pma.absolute = 1; + if (ioctl(dev, VIDIOCPWCMPTGANGLE, &pma) == -1) + motion_log(LOG_ERR, 1, "ioctl VIDIOCPWCMPTGANGLE"); + + pma.absolute = 1; - if (x_angle * 100 < cnt->track.panmax && x_angle * 100 > cnt->track.panmin) - pma.pan = x_angle * 100; + if (x_angle * 100 < cnt->track.panmax && x_angle * 100 > cnt->track.panmin) + pma.pan = x_angle * 100; - if (y_angle * 100 < cnt->track.tiltmax && y_angle * 100 > cnt->track.tiltmin) - pma.tilt = y_angle * 100; + if (y_angle * 100 < cnt->track.tiltmax && y_angle * 100 > cnt->track.tiltmin) + pma.tilt = y_angle * 100; - if (ioctl(dev, VIDIOCPWCMPTSANGLE, &pma) == -1) { - motion_log(LOG_ERR, 1, "Failed to pan/tilt pwc camera! Reason"); - return 0; - } + if (ioctl(dev, VIDIOCPWCMPTSANGLE, &pma) == -1) { + motion_log(LOG_ERR, 1, "Failed to pan/tilt pwc camera! Reason"); + return 0; + } - motion_log(LOG_INFO, 0, "lqos_center succeed"); + motion_log(LOG_INFO, 0, "lqos_center succeed"); - return cnt->track.move_wait; + return cnt->track.move_wait; } -static unsigned short int lqos_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs, unsigned short int manual) +static unsigned short int lqos_move(struct context *cnt, int dev, struct coord *cent, + struct images *imgs, unsigned short int manual) { - int delta_x = cent->x - (imgs->width / 2); - int delta_y = cent->y - (imgs->height / 2); - int move_x_degrees, move_y_degrees; - struct pwc_mpt_angles pma; - struct pwc_mpt_range pmr; + int delta_x = cent->x - (imgs->width / 2); + int delta_y = cent->y - (imgs->height / 2); + int move_x_degrees, move_y_degrees; + struct pwc_mpt_angles pma; + struct pwc_mpt_range pmr; - /* If we are on auto track we calculate delta, otherwise we use user input in degrees times 100 */ - if (!manual) { - if (delta_x > imgs->width * 3/8 && delta_x < imgs->width * 5/8) - return 0; - if (delta_y > imgs->height * 3/8 && delta_y < imgs->height * 5/8) - return 0; + /* If we are on auto track we calculate delta, otherwise we use user input in degrees times 100 */ + if (!manual) { + if (delta_x > imgs->width * 3 / 8 && delta_x < imgs->width * 5 / 8) + return 0; + if (delta_y > imgs->height * 3 / 8 && delta_y < imgs->height * 5 / 8) + return 0; - move_x_degrees = delta_x * cnt->track.step_angle_x * 100 / (imgs->width / 2); - move_y_degrees = -delta_y * cnt->track.step_angle_y * 100 / (imgs->height / 2); - } else { - move_x_degrees = cent->x * 100; - move_y_degrees = cent->y * 100; - } - - /* If we never checked for the min/max values for pan/tilt we do it now */ - if (cnt->track.minmaxfound == 0) { - if (ioctl(dev, VIDIOCPWCMPTGRANGE, &pmr) == -1) { - motion_log(LOG_ERR, 1, "failed VIDIOCPWCMPTGRANGE"); - return 0; - } - cnt->track.minmaxfound = 1; - cnt->track.panmin = pmr.pan_min; - cnt->track.panmax = pmr.pan_max; - cnt->track.tiltmin = pmr.tilt_min; - cnt->track.tiltmax = pmr.tilt_max; - } + move_x_degrees = delta_x * cnt->track.step_angle_x * 100 / (imgs->width / 2); + move_y_degrees = -delta_y * cnt->track.step_angle_y * 100 / (imgs->height / 2); + } else { + move_x_degrees = cent->x * 100; + move_y_degrees = cent->y * 100; + } + + /* If we never checked for the min/max values for pan/tilt we do it now */ + if (cnt->track.minmaxfound == 0) { + if (ioctl(dev, VIDIOCPWCMPTGRANGE, &pmr) == -1) { + motion_log(LOG_ERR, 1, "failed VIDIOCPWCMPTGRANGE"); + return 0; + } + cnt->track.minmaxfound = 1; + cnt->track.panmin = pmr.pan_min; + cnt->track.panmax = pmr.pan_max; + cnt->track.tiltmin = pmr.tilt_min; + cnt->track.tiltmax = pmr.tilt_max; + } - /* Get current camera position */ - if (ioctl(dev, VIDIOCPWCMPTGANGLE, &pma) == -1) - motion_log(LOG_ERR, 1, "ioctl VIDIOCPWCMPTGANGLE"); + /* Get current camera position */ + if (ioctl(dev, VIDIOCPWCMPTGANGLE, &pma) == -1) + motion_log(LOG_ERR, 1, "ioctl VIDIOCPWCMPTGANGLE"); - /* Check current position of camera and see if we need to adjust - values down to what is left to move */ - if (move_x_degrees<0 && (cnt->track.panmin - pma.pan) > move_x_degrees) - move_x_degrees = (cnt->track.panmin - pma.pan); + /* Check current position of camera and see if we need to adjust + values down to what is left to move */ + if (move_x_degrees<0 && (cnt->track.panmin - pma.pan) > move_x_degrees) + move_x_degrees = (cnt->track.panmin - pma.pan); - if (move_x_degrees>0 && (cnt->track.panmax - pma.pan) < move_x_degrees) - move_x_degrees = (cnt->track.panmax - pma.pan); + if (move_x_degrees>0 && (cnt->track.panmax - pma.pan) < move_x_degrees) + move_x_degrees = (cnt->track.panmax - pma.pan); - if (move_y_degrees<0 && (cnt->track.tiltmin - pma.tilt) > move_y_degrees) - move_y_degrees = (cnt->track.tiltmin - pma.tilt); + if (move_y_degrees<0 && (cnt->track.tiltmin - pma.tilt) > move_y_degrees) + move_y_degrees = (cnt->track.tiltmin - pma.tilt); - if (move_y_degrees>0 && (cnt->track.tiltmax - pma.tilt) < move_y_degrees) - move_y_degrees = (cnt->track.tiltmax - pma.tilt); - - /* Move camera relative to current position */ - pma.absolute = 0; - pma.pan = move_x_degrees; - pma.tilt = move_y_degrees; + if (move_y_degrees>0 && (cnt->track.tiltmax - pma.tilt) < move_y_degrees) + move_y_degrees = (cnt->track.tiltmax - pma.tilt); + + /* Move camera relative to current position */ + pma.absolute = 0; + pma.pan = move_x_degrees; + pma.tilt = move_y_degrees; - if (ioctl(dev, VIDIOCPWCMPTSANGLE, &pma) == -1) { - motion_log(LOG_ERR, 1, "Failed to pan/tilt pwc camera! Reason"); - return 0; - } + if (ioctl(dev, VIDIOCPWCMPTSANGLE, &pma) == -1) { + motion_log(LOG_ERR, 1, "Failed to pan/tilt pwc camera! Reason"); + return 0; + } - return cnt->track.move_wait; + return cnt->track.move_wait; } /****************************************************************************** - Logitech QuickCam Sphere camera tracking code by oBi - - Modify by Dirk Wesenberg(Munich) 30.03.07 - - for new API in uvcvideo - - add Trace-steps for investigation + Logitech QuickCam Sphere camera tracking code by oBi + + Modify by Dirk Wesenberg(Munich) 30.03.07 + - for new API in uvcvideo + - add Trace-steps for investigation ******************************************************************************/ #ifdef MOTION_V4L2 static unsigned short int uvc_center(struct context *cnt, int dev, int x_angle, int y_angle) { - /* CALC ABSOLUTE MOVING : Act.Position +/- delta to request X and Y */ - int move_x_degrees = 0, move_y_degrees = 0; + /* CALC ABSOLUTE MOVING : Act.Position +/- delta to request X and Y */ + int move_x_degrees = 0, move_y_degrees = 0; - union pantilt { - struct { - short pan; - short tilt; - } s16; - int value; - }; - union pantilt pan; + union pantilt { + struct { + short pan; + short tilt; + } s16; + int value; + }; + union pantilt pan; - if (cnt->track.dev==-1) { + if (cnt->track.dev==-1) { - int reset = 3; //0-non reset, 1-reset pan, 2-reset tilt, 3-reset pan&tilt - struct v4l2_control control_s; + int reset = 3; //0-non reset, 1-reset pan, 2-reset tilt, 3-reset pan&tilt + struct v4l2_control control_s; - control_s.id = V4L2_CID_PANTILT_RESET; - control_s.value = (unsigned char) reset; + control_s.id = V4L2_CID_PANTILT_RESET; + control_s.value = (unsigned char) reset; - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to reset UVC camera to starting position! Reason"); - return 0; - } - motion_log(LOG_DEBUG, 0, "Reseting UVC camera to starting position"); + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to reset UVC camera to starting position! Reason"); + return 0; + } + motion_log(LOG_DEBUG, 0, "Reseting UVC camera to starting position"); - SLEEP(8,0) + SLEEP(8,0) - /* Get camera range */ - struct v4l2_queryctrl queryctrl; + /* Get camera range */ + struct v4l2_queryctrl queryctrl; - queryctrl.id = V4L2_CID_PAN_RELATIVE; - if (ioctl(dev, VIDIOC_QUERYCTRL, &queryctrl) < 0 ) { - motion_log(LOG_ERR, 1, "ioctl querycontrol error %d",errno); - return 0; - } - motion_log(LOG_DEBUG, 0, "Getting camera range"); - + queryctrl.id = V4L2_CID_PAN_RELATIVE; - /* DWe 30.03.07 The orig request failed : - * must be VIDIOC_G_CTRL separate for pan and tilt or via VIDIOC_G_EXT_CTRLS - now for 1st manual - * Range X = -70 to +70 degrees - * Y = -30 to +30 degrees - */ - -// //get mininum -// pan.value = queryctrl.minimum; + if (ioctl(dev, VIDIOC_QUERYCTRL, &queryctrl) < 0) { + motion_log(LOG_ERR, 1, "ioctl querycontrol error %d",errno); + return 0; + } + motion_log(LOG_DEBUG, 0, "Getting camera range"); + - cnt->track.panmin = -4480 / INCPANTILT; - cnt->track.tiltmin = -1920 / INCPANTILT; -// //get maximum - cnt->track.panmax = 4480 / INCPANTILT; - cnt->track.tiltmax = 1920 / INCPANTILT; -// pan.value = queryctrl.maximum; + /* DWe 30.03.07 The orig request failed : + * must be VIDIOC_G_CTRL separate for pan and tilt or via VIDIOC_G_EXT_CTRLS - now for 1st manual + * Range X = -70 to +70 degrees + * Y = -30 to +30 degrees + */ + +// //get mininum +// pan.value = queryctrl.minimum; - cnt->track.dev = dev; - cnt->track.pan_angle = 0; - cnt->track.tilt_angle = 0; - cnt->track.minmaxfound = 1; + cnt->track.panmin = -4480 / INCPANTILT; + cnt->track.tiltmin = -1920 / INCPANTILT; +// //get maximum + cnt->track.panmax = 4480 / INCPANTILT; + cnt->track.tiltmax = 1920 / INCPANTILT; +// pan.value = queryctrl.maximum; - } + cnt->track.dev = dev; + cnt->track.pan_angle = 0; + cnt->track.tilt_angle = 0; + cnt->track.minmaxfound = 1; - struct v4l2_control control_s; + } - motion_log(LOG_DEBUG, 0, "INPUT_PARAM_ABS pan_min %d,pan_max %d,tilt_min %d,tilt_max %d ", cnt->track.panmin, cnt->track.panmax, cnt->track.tiltmin, cnt->track.tiltmax ); - motion_log(LOG_DEBUG, 0, "INPUT_PARAM_ABS X_Angel %d, Y_Angel %d ", x_angle, y_angle); + struct v4l2_control control_s; - if (x_angle <= cnt->track.panmax && x_angle >= cnt->track.panmin) - move_x_degrees = x_angle - (cnt->track.pan_angle); + motion_log(LOG_DEBUG, 0, "INPUT_PARAM_ABS pan_min %d,pan_max %d,tilt_min %d,tilt_max %d ", + cnt->track.panmin, cnt->track.panmax, cnt->track.tiltmin, cnt->track.tiltmax ); + motion_log(LOG_DEBUG, 0, "INPUT_PARAM_ABS X_Angel %d, Y_Angel %d ", x_angle, y_angle); - if (y_angle <= cnt->track.tiltmax && y_angle >= cnt->track.tiltmin) - move_y_degrees = y_angle - (cnt->track.tilt_angle); - + if (x_angle <= cnt->track.panmax && x_angle >= cnt->track.panmin) + move_x_degrees = x_angle - (cnt->track.pan_angle); - /* - tilt up: - value - tilt down: + value - pan left: - value - pan right: + value - */ - pan.s16.pan = -move_x_degrees * INCPANTILT; - pan.s16.tilt = -move_y_degrees * INCPANTILT; - - motion_log(LOG_DEBUG, 0, "For_SET_ABS move_X %d,move_Y %d", move_x_degrees, move_y_degrees); - - /* DWe 30.03.07 Must be broken in diff calls, because - - one call for both is not accept via VIDIOC_S_CTRL -> maybe via VIDIOC_S_EXT_CTRLS - - The Webcam or uvcvideo does not like a call with a zero-move - */ + if (y_angle <= cnt->track.tiltmax && y_angle >= cnt->track.tiltmin) + move_y_degrees = y_angle - (cnt->track.tilt_angle); + + + /* + tilt up: - value + tilt down: + value + pan left: - value + pan right: + value + */ + pan.s16.pan = -move_x_degrees * INCPANTILT; + pan.s16.tilt = -move_y_degrees * INCPANTILT; - if (move_x_degrees != 0 ) { - control_s.id = V4L2_CID_PAN_RELATIVE; - // control_s.value = pan.value; - control_s.value = pan.s16.pan; - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); - return 0; - } - } + motion_log(LOG_DEBUG, 0, "For_SET_ABS move_X %d,move_Y %d", move_x_degrees, move_y_degrees); + + /* DWe 30.03.07 Must be broken in diff calls, because + - one call for both is not accept via VIDIOC_S_CTRL -> maybe via VIDIOC_S_EXT_CTRLS + - The Webcam or uvcvideo does not like a call with a zero-move + */ + + if (move_x_degrees != 0) { + control_s.id = V4L2_CID_PAN_RELATIVE; + // control_s.value = pan.value; + control_s.value = pan.s16.pan; + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); + return 0; + } + } - /* DWe 30.03.07 We must wait a little,before we set the next CMD, otherwise PAN is mad ... */ - if ((move_x_degrees != 0) && (move_y_degrees != 0)) { - SLEEP (1,0); - } - - if (move_y_degrees != 0 ) { - control_s.id = V4L2_CID_TILT_RELATIVE; - // control_s.value = pan.value; - control_s.value = pan.s16.tilt; - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); - return 0; - } - - } + /* DWe 30.03.07 We must wait a little,before we set the next CMD, otherwise PAN is mad ... */ + if ((move_x_degrees != 0) && (move_y_degrees != 0)) + SLEEP (1,0); + + + if (move_y_degrees != 0) { + control_s.id = V4L2_CID_TILT_RELATIVE; + // control_s.value = pan.value; + control_s.value = pan.s16.tilt; + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); + return 0; + } + + } - motion_log(LOG_DEBUG, 0,"Found MINMAX = %d", cnt->track.minmaxfound); + motion_log(LOG_DEBUG, 0,"Found MINMAX = %d", cnt->track.minmaxfound); - if (cnt->track.dev!=-1) { - motion_log(LOG_DEBUG, 0," Before_ABS_Y_Angel : x= %d , Y= %d , ", cnt->track.pan_angle, cnt->track.tilt_angle ); - if (move_x_degrees != -1) { - cnt->track.pan_angle += move_x_degrees; - } - if (move_x_degrees != -1) { - cnt->track.tilt_angle += move_y_degrees; - } - motion_log(LOG_DEBUG, 0," After_ABS_Y_Angel : x= %d , Y= %d , ", cnt->track.pan_angle, cnt->track.tilt_angle ); - } + if (cnt->track.dev!=-1) { + motion_log(LOG_DEBUG, 0," Before_ABS_Y_Angel : x= %d , Y= %d , ", + cnt->track.pan_angle, cnt->track.tilt_angle ); + if (move_x_degrees != -1) + cnt->track.pan_angle += move_x_degrees; + + if (move_x_degrees != -1) + cnt->track.tilt_angle += move_y_degrees; + + motion_log(LOG_DEBUG, 0," After_ABS_Y_Angel : x= %d , Y= %d , ", + cnt->track.pan_angle, cnt->track.tilt_angle ); + } - return cnt->track.move_wait; + return cnt->track.move_wait; } static unsigned short int uvc_move(struct context *cnt, int dev, struct coord *cent, struct images *imgs, unsigned short int manual) { - /* RELATIVE MOVING : Act.Position +/- X and Y */ - - int delta_x = cent->x - (imgs->width / 2); - int delta_y = cent->y - (imgs->height / 2); - int move_x_degrees, move_y_degrees; - - /* DWe 30.03.07 Does the request of act.position from WebCam work ? luvcview shows at every position 180 :( */ - /* Now we init the Web by call Reset, so we can sure, that we are at x/y = 0,0 */ - /* Don't worry, if the WebCam make a sound - over End at PAN - hmmm, should it be normal ...? */ - /* PAN Value 7777 in relative will init also a want reset for CAM - it will be "0" after that */ - if (( cnt->track.minmaxfound != 1) || (cent->x == 7777 )) { - unsigned short int reset = 3; //0-non reset, 1-reset pan, 2-reset tilt, 3-reset pan&tilt - struct v4l2_control control_s; + /* RELATIVE MOVING : Act.Position +/- X and Y */ + + int delta_x = cent->x - (imgs->width / 2); + int delta_y = cent->y - (imgs->height / 2); + int move_x_degrees, move_y_degrees; + + /* DWe 30.03.07 Does the request of act.position from WebCam work ? luvcview shows at every position 180 :( */ + /* Now we init the Web by call Reset, so we can sure, that we are at x/y = 0,0 */ + /* Don't worry, if the WebCam make a sound - over End at PAN - hmmm, should it be normal ...? */ + /* PAN Value 7777 in relative will init also a want reset for CAM - it will be "0" after that */ + if ((cnt->track.minmaxfound != 1) || (cent->x == 7777)) { + unsigned short int reset = 3; //0-non reset, 1-reset pan, 2-reset tilt, 3-reset pan&tilt + struct v4l2_control control_s; - control_s.id = V4L2_CID_PANTILT_RESET; - control_s.value = (unsigned char) reset; + control_s.id = V4L2_CID_PANTILT_RESET; + control_s.value = (unsigned char) reset; - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to reset UVC camera to starting position! Reason"); - return 0; - } - motion_log(LOG_DEBUG, 0, "Reseting UVC camera to starting position"); - - /* set the "helpvalue" back to null because after reset CAM should be in x=0 and not 70 */ - cent->x = 0; - SLEEP(8,0); - - /* DWe 30.03.07 The orig request failed : - * must be VIDIOC_G_CTRL separate for pan and tilt or via VIDIOC_G_EXT_CTRLS - now for 1st manual - * Range X = -70 to +70 degrees - * Y = -30 to +30 degrees - */ + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to reset UVC camera to starting position! Reason"); + return 0; + } - cnt->track.panmin = -4480 / INCPANTILT; - cnt->track.tiltmin = -1920 / INCPANTILT; - cnt->track.panmax = 4480 / INCPANTILT; - cnt->track.tiltmax = 1920 / INCPANTILT; - cnt->track.dev = dev; - cnt->track.pan_angle = 0; - cnt->track.tilt_angle = 0; - cnt->track.minmaxfound = 1; - } + motion_log(LOG_DEBUG, 0, "Reseting UVC camera to starting position"); + + /* set the "helpvalue" back to null because after reset CAM should be in x=0 and not 70 */ + cent->x = 0; + SLEEP(8,0); + + /* DWe 30.03.07 The orig request failed : + * must be VIDIOC_G_CTRL separate for pan and tilt or via VIDIOC_G_EXT_CTRLS - now for 1st manual + * Range X = -70 to +70 degrees + * Y = -30 to +30 degrees + */ - - /* If we are on auto track we calculate delta, otherwise we use user input in degrees */ - if (!manual) { - if (delta_x > imgs->width * 3/8 && delta_x < imgs->width * 5/8) - return 0; - if (delta_y > imgs->height * 3/8 && delta_y < imgs->height * 5/8) - return 0; + cnt->track.panmin = -4480 / INCPANTILT; + cnt->track.tiltmin = -1920 / INCPANTILT; + cnt->track.panmax = 4480 / INCPANTILT; + cnt->track.tiltmax = 1920 / INCPANTILT; + cnt->track.dev = dev; + cnt->track.pan_angle = 0; + cnt->track.tilt_angle = 0; + cnt->track.minmaxfound = 1; + } - move_x_degrees = delta_x * cnt->track.step_angle_x / (imgs->width / 2); - move_y_degrees = -delta_y * cnt->track.step_angle_y / (imgs->height / 2); - } else { - move_x_degrees = cent->x; - move_y_degrees = cent->y; - } + + /* If we are on auto track we calculate delta, otherwise we use user input in degrees */ + if (!manual) { + if (delta_x > imgs->width * 3 / 8 && delta_x < imgs->width * 5 / 8) + return 0; + if (delta_y > imgs->height * 3 / 8 && delta_y < imgs->height * 5 / 8) + return 0; - union pantilt { - struct { - short pan; - short tilt; - } s16; - int value; - }; + move_x_degrees = delta_x * cnt->track.step_angle_x / (imgs->width / 2); + move_y_degrees = -delta_y * cnt->track.step_angle_y / (imgs->height / 2); + } else { + move_x_degrees = cent->x; + move_y_degrees = cent->y; + } - struct v4l2_control control_s; - union pantilt pan; + union pantilt { + struct { + short pan; + short tilt; + } s16; + int value; + }; - if (cnt->track.minmaxfound == 1) { - /* Check current position of camera and see if we need to adjust - values down to what is left to move */ - if (move_x_degrees<0 && (cnt->track.panmin - cnt->track.pan_angle) > move_x_degrees) - move_x_degrees = (cnt->track.panmin - cnt->track.pan_angle); + struct v4l2_control control_s; + union pantilt pan; - if (move_x_degrees>0 && (cnt->track.panmax - cnt->track.pan_angle) < move_x_degrees) - move_x_degrees = (cnt->track.panmax - cnt->track.pan_angle); + if (cnt->track.minmaxfound == 1) { + /* Check current position of camera and see if we need to adjust + values down to what is left to move */ + if (move_x_degrees<0 && (cnt->track.panmin - cnt->track.pan_angle) > move_x_degrees) + move_x_degrees = (cnt->track.panmin - cnt->track.pan_angle); - if (move_y_degrees<0 && (cnt->track.tiltmin - cnt->track.tilt_angle) > move_y_degrees) - move_y_degrees = (cnt->track.tiltmin - cnt->track.tilt_angle); + if (move_x_degrees>0 && (cnt->track.panmax - cnt->track.pan_angle) < move_x_degrees) + move_x_degrees = (cnt->track.panmax - cnt->track.pan_angle); - if (move_y_degrees>0 && (cnt->track.tiltmax - cnt->track.tilt_angle) < move_y_degrees) - move_y_degrees = (cnt->track.tiltmax - cnt->track.tilt_angle); - } + if (move_y_degrees<0 && (cnt->track.tiltmin - cnt->track.tilt_angle) > move_y_degrees) + move_y_degrees = (cnt->track.tiltmin - cnt->track.tilt_angle); + + if (move_y_degrees>0 && (cnt->track.tiltmax - cnt->track.tilt_angle) < move_y_degrees) + move_y_degrees = (cnt->track.tiltmax - cnt->track.tilt_angle); + } - motion_log(LOG_DEBUG, 0, "For_SET_REL pan_min %d,pan_max %d,tilt_min %d,tilt_max %d ", cnt->track.panmin, cnt->track.panmax, cnt->track.tiltmin, cnt->track.tiltmax ); - motion_log(LOG_DEBUG, 0, "For_SET_REL track_pan_Angel %d, track_tilt_Angel %d ", cnt->track.pan_angle, cnt->track.tilt_angle); - motion_log(LOG_DEBUG, 0, "For_SET_REL move_X %d,move_Y %d", move_x_degrees, move_y_degrees); - /* - tilt up: - value - tilt down: + value - pan left: - value - pan right: + value - */ + motion_log(LOG_DEBUG, 0, "For_SET_REL pan_min %d,pan_max %d,tilt_min %d,tilt_max %d ", + cnt->track.panmin, cnt->track.panmax, cnt->track.tiltmin, cnt->track.tiltmax ); + motion_log(LOG_DEBUG, 0, "For_SET_REL track_pan_Angel %d, track_tilt_Angel %d ", + cnt->track.pan_angle, cnt->track.tilt_angle); + motion_log(LOG_DEBUG, 0, "For_SET_REL move_X %d,move_Y %d", + move_x_degrees, move_y_degrees); + /* + tilt up: - value + tilt down: + value + pan left: - value + pan right: + value + */ - pan.s16.pan = -move_x_degrees * INCPANTILT; - pan.s16.tilt = -move_y_degrees * INCPANTILT; - - /* DWe 30.03.07 Must be broken in diff calls, because - - one call for both is not accept via VIDIOC_S_CTRL -> maybe via VIDIOC_S_EXT_CTRLS - - The Webcam or uvcvideo does not like a call with a zero-move - */ + pan.s16.pan = -move_x_degrees * INCPANTILT; + pan.s16.tilt = -move_y_degrees * INCPANTILT; + + /* DWe 30.03.07 Must be broken in diff calls, because + - one call for both is not accept via VIDIOC_S_CTRL -> maybe via VIDIOC_S_EXT_CTRLS + - The Webcam or uvcvideo does not like a call with a zero-move + */ - if (move_x_degrees != 0) { + if (move_x_degrees != 0) { - control_s.id = V4L2_CID_PAN_RELATIVE; + control_s.id = V4L2_CID_PAN_RELATIVE; -// control_s.value = pan.value; - control_s.value = pan.s16.pan; - motion_log(LOG_DEBUG, 0," dev %d,addr= %d, control_S= %d,Wert= %d,", dev,VIDIOC_S_CTRL, &control_s, pan.s16.pan ); - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); - return 0; - } - } - - /* DWe 30.03.07 We must wait a little,before we set the next CMD, otherwise PAN is mad ... */ - if ((move_x_degrees != 0) && (move_y_degrees != 0)) { - SLEEP (1,0); - } + control_s.value = pan.s16.pan; + motion_log(LOG_DEBUG, 0," dev %d,addr= %d, control_S= %d,Wert= %d,", + dev,VIDIOC_S_CTRL, &control_s, pan.s16.pan ); + + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); + return 0; + } + } + + /* DWe 30.03.07 We must wait a little,before we set the next CMD, otherwise PAN is mad ... */ + if ((move_x_degrees != 0) && (move_y_degrees != 0)) + SLEEP (1,0); + - if (move_y_degrees != 0) { + if (move_y_degrees != 0) { - control_s.id = V4L2_CID_TILT_RELATIVE; + control_s.id = V4L2_CID_TILT_RELATIVE; + control_s.value = pan.s16.tilt; + motion_log(LOG_DEBUG, 0," dev %d,addr= %d, control_S= %d, Wert= %d, ", + dev,VIDIOC_S_CTRL, &control_s, pan.s16.tilt); -// control_s.value = pan.value; - control_s.value = pan.s16.tilt; - motion_log(LOG_DEBUG, 0," dev %d,addr= %d, control_S= %d, Wert= %d, ", dev,VIDIOC_S_CTRL, &control_s, pan.s16.tilt ); - if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { - motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); - return 0; - } - } - + if (ioctl(dev, VIDIOC_S_CTRL, &control_s) < 0) { + motion_log(LOG_ERR, 1, "Failed to move UVC camera!"); + return 0; + } + } + - motion_log(LOG_DEBUG, 0,"Found MINMAX = %d", cnt->track.minmaxfound); - if (cnt->track.minmaxfound == 1) { - motion_log(LOG_DEBUG, 0," Before_REL_Y_Angel : x= %d , Y= %d", cnt->track.pan_angle, cnt->track.tilt_angle ); - - if (move_x_degrees != 0){ - cnt->track.pan_angle += -pan.s16.pan / INCPANTILT; - } - if (move_y_degrees != 0){ - cnt->track.tilt_angle += -pan.s16.tilt / INCPANTILT; - } - motion_log(LOG_DEBUG, 0," After_REL_Y_Angel : x= %d , Y= %d", cnt->track.pan_angle, cnt->track.tilt_angle ); - } + motion_log(LOG_DEBUG, 0,"Found MINMAX = %d", cnt->track.minmaxfound); + + if (cnt->track.minmaxfound == 1) { + motion_log(LOG_DEBUG, 0," Before_REL_Y_Angel : x= %d , Y= %d", + cnt->track.pan_angle, cnt->track.tilt_angle); + + if (move_x_degrees != 0) + cnt->track.pan_angle += -pan.s16.pan / INCPANTILT; + + if (move_y_degrees != 0) + cnt->track.tilt_angle += -pan.s16.tilt / INCPANTILT; + + motion_log(LOG_DEBUG, 0," After_REL_Y_Angel : x= %d , Y= %d", + cnt->track.pan_angle, cnt->track.tilt_angle); + } - return cnt->track.move_wait; + return cnt->track.move_wait; } #endif /* MOTION_V4L2 */ #endif /* WITHOUT_V4L */ diff --git a/track.h b/track.h index 96aeb195..c15f9d60 100644 --- a/track.h +++ b/track.h @@ -1,9 +1,9 @@ -/* track.h +/* track.h * - * Experimental motion tracking. + * Experimental motion tracking. * - * Copyright 2000, Jeroen Vreeken - * This program is published under the GNU Public license + * Copyright 2000, Jeroen Vreeken + * This program is published under the GNU Public license */ #ifndef _INCLUDE_TRACK_H @@ -12,29 +12,29 @@ #include "alg.h" struct trackoptions { - int dev; - /* Config options: */ - unsigned short int type; - char *port; - unsigned short int motorx; - unsigned short int motory; - unsigned short int maxx; - unsigned short int maxy; - unsigned short int stepsize; - unsigned short int speed; - unsigned short int iomojo_id; - unsigned short int active; - int panmin; - int panmax; - int tiltmin; - int tiltmax; - unsigned short int minmaxfound; - unsigned short int step_angle_x; - unsigned short int step_angle_y; - unsigned short int move_wait; + int dev; + /* Config options: */ + unsigned short int type; + char *port; + unsigned short int motorx; + unsigned short int motory; + unsigned short int maxx; + unsigned short int maxy; + unsigned short int stepsize; + unsigned short int speed; + unsigned short int iomojo_id; + unsigned short int active; + int panmin; + int panmax; + int tiltmin; + int tiltmax; + unsigned short int minmaxfound; + unsigned short int step_angle_x; + unsigned short int step_angle_y; + unsigned short int move_wait; // UVC - int pan_angle; // degrees - int tilt_angle; // degrees + int pan_angle; // degrees + int tilt_angle; // degrees }; extern struct trackoptions track_template; @@ -43,7 +43,7 @@ unsigned short int track_center(struct context *, int, unsigned short int, int, unsigned short int track_move(struct context *, int, struct coord *, struct images *, unsigned short int); /* - Some default values: + Some default values: */ #define TRACK_SPEED 255 #define TRACK_STEPSIZE 40 @@ -55,7 +55,7 @@ unsigned short int track_move(struct context *, int, struct coord *, struct imag #define TRACK_TYPE_UVC 5 /* - Some defines for the Serial stepper motor: + Some defines for the Serial stepper motor: */ #define STEPPER_BAUDRATE B9600 @@ -88,10 +88,10 @@ unsigned short int track_move(struct context *, int, struct coord *, struct imag /* - Some defines for the Iomojo Smilecam: + Some defines for the Iomojo Smilecam: */ -#define IOMOJO_BAUDRATE B19200 +#define IOMOJO_BAUDRATE B19200 #define IOMOJO_CHECKPOWER_CMD 0xff #define IOMOJO_CHECKPOWER_RET 'Q' @@ -109,7 +109,7 @@ unsigned short int track_move(struct context *, int, struct coord *, struct imag #ifndef WITHOUT_V4L /* - Defines for the Logitech QuickCam Orbit/Sphere USB webcam + Defines for the Logitech QuickCam Orbit/Sphere USB webcam */ #define LQOS_VERTICAL_DEGREES 180 @@ -120,9 +120,9 @@ unsigned short int track_move(struct context *, int, struct coord *, struct imag */ #ifdef MOTION_V4L2 -#define V4L2_CID_PAN_RELATIVE (V4L2_CID_PRIVATE_BASE+7) -#define V4L2_CID_TILT_RELATIVE (V4L2_CID_PRIVATE_BASE+8) -#define V4L2_CID_PANTILT_RESET (V4L2_CID_PRIVATE_BASE+9) +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_PRIVATE_BASE+7) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_PRIVATE_BASE+8) +#define V4L2_CID_PANTILT_RESET (V4L2_CID_PRIVATE_BASE+9) #define INCPANTILT 64 // 1 degree #endif /* MOTION_V4L2 */ diff --git a/video_freebsd.c b/video_freebsd.c index 11b3be66..6aeb0f94 100644 --- a/video_freebsd.c +++ b/video_freebsd.c @@ -1,9 +1,9 @@ -/* video_freebsd.c +/* video_freebsd.c * - * BSD Video stream functions for motion. - * Copyright 2004 by Angel Carpintero (ack@telefonica.net) - * This software is distributed under the GNU public license version 2 - * See also the file 'COPYING'. + * BSD Video stream functions for motion. + * Copyright 2004 by Angel Carpintero (ack@telefonica.net) + * This software is distributed under the GNU public license version 2 + * See also the file 'COPYING'. * */ @@ -71,42 +71,42 @@ volatile sig_atomic_t bktr_frame_waiting; static void catchsignal(int sig) { - bktr_frame_waiting++; + bktr_frame_waiting++; } /* Not tested yet */ static void yuv422to420p(unsigned char *map, unsigned char *cap_map, int width, int height) { - unsigned char *src, *dest, *src2, *dest2; - int i, j; + unsigned char *src, *dest, *src2, *dest2; + int i, j; - /* Create the Y plane */ - src = cap_map; - dest = map; - for (i = width * height; i; i--) { - *dest++ = *src; - src += 2; - } - /* Create U and V planes */ - src = cap_map + 1; - src2 = cap_map + width * 2 + 1; - dest = map + width* height; - dest2 = dest + (width * height) / 4; - for (i = height / 2; i; i--) { - for (j = width / 2; j; j--) { - *dest = ((int)*src + (int)*src2) / 2; - src += 2; - src2 += 2; - dest++; - *dest2 = ((int)*src + (int)*src2) / 2; - src += 2; - src2 += 2; - dest2++; - } - src += width * 2; - src2 += width * 2; - } + /* Create the Y plane */ + src = cap_map; + dest = map; + for (i = width * height; i; i--) { + *dest++ = *src; + src += 2; + } + /* Create U and V planes */ + src = cap_map + 1; + src2 = cap_map + width * 2 + 1; + dest = map + width* height; + dest2 = dest + (width * height) / 4; + for (i = height / 2; i; i--) { + for (j = width / 2; j; j--) { + *dest = ((int)*src + (int)*src2) / 2; + src += 2; + src2 += 2; + dest++; + *dest2 = ((int)*src + (int)*src2) / 2; + src += 2; + src2 += 2; + dest2++; + } + src += width * 2; + src2 += width * 2; + } } @@ -114,42 +114,42 @@ static void yuv422to420p(unsigned char *map, unsigned char *cap_map, int width, static void rgb24toyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height) { - unsigned char *y, *u, *v; - unsigned char *r, *g, *b; - int i, loop; + unsigned char *y, *u, *v; + unsigned char *r, *g, *b; + int i, loop; - b = cap_map; - g = b + 1; - r = g + 1; - y = map; - u = y + width * height; - v = u + (width * height) / 4; - memset(u, 0, width * height / 4); - memset(v, 0, width * height / 4); + b = cap_map; + g = b + 1; + r = g + 1; + y = map; + u = y + width * height; + v = u + (width * height) / 4; + memset(u, 0, width * height / 4); + memset(v, 0, width * height / 4); - for (loop = 0; loop < height; loop++) { - for (i = 0; i < width; i += 2) { - *y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15; - *u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32; - *v += ((20218 ** r - 16941**g - 3277 ** b) >> 17) + 32; - r += 3; - g += 3; - b += 3; - *y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15; - *u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32; - *v += ((20218 ** r - 16941 ** g - 3277 ** b) >> 17) + 32; - r += 3; - g += 3; - b += 3; - u++; - v++; - } + for (loop = 0; loop < height; loop++) { + for (i = 0; i < width; i += 2) { + *y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15; + *u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32; + *v += ((20218 ** r - 16941**g - 3277 ** b) >> 17) + 32; + r += 3; + g += 3; + b += 3; + *y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15; + *u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32; + *v += ((20218 ** r - 16941 ** g - 3277 ** b) >> 17) + 32; + r += 3; + g += 3; + b += 3; + u++; + v++; + } - if ((loop & 1) == 0) { - u -= width / 2; - v -= width / 2; - } - } + if ((loop & 1) == 0) { + u -= width / 2; + v -= width / 2; + } + } } @@ -160,165 +160,166 @@ static void rgb24toyuv420p(unsigned char *map, unsigned char *cap_map, int width /* NOT TESTED YET FIXME */ /* -static int camparam_normalize( int param, int cfg_value, int *ioctl_val ) +static int camparam_normalize(int param, int cfg_value, int *ioctl_val) { - int val; + int val; - cfg_value = MIN( CamParams[ param ].max, MAX( CamParams[ param ].min, cfg_value ) ); - val = (cfg_value - CamParams[ param ].min ) / - (CamParams[ param ].range + 0.01) * CamParams[param].drv_range + CamParams[param].drv_min; - val = MAX( CamParams[ param ].min, - MIN( CamParams[ param ].drv_min + CamParams[ param ].drv_range-1, val )); - *ioctl_val = val; - return cfg_value; + cfg_value = MIN(CamParams[ param ].max, MAX( CamParams[ param ].min, cfg_value)); + val = (cfg_value - CamParams[ param ].min ) / + (CamParams[ param ].range + 0.01) * CamParams[param].drv_range + CamParams[param].drv_min; + val = MAX(CamParams[param].min, + MIN(CamParams[param].drv_min + CamParams[ param ].drv_range-1, val)); + *ioctl_val = val; + return cfg_value; } */ -static int set_hue( int viddev, int new_hue ) +static int set_hue(int viddev, int new_hue) { - signed char ioctlval = new_hue; + signed char ioctlval = new_hue; - if (ioctl(viddev, METEORSHUE, &ioctlval) < 0) { + if (ioctl(viddev, METEORSHUE, &ioctlval) < 0) { motion_log(LOG_ERR, 1, "%s: METEORSHUE Error setting hue [%d]", __FUNCTION__, new_hue); return -1; } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - return ioctlval; + return ioctlval; } static int get_hue(int viddev , int *hue) { - signed char ioctlval; + signed char ioctlval; - if (ioctl(viddev, METEORGHUE, &ioctlval) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORGHUE Error getting hue", __FUNCTION__); - return -1; - } + if (ioctl(viddev, METEORGHUE, &ioctlval) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORGHUE Error getting hue", __FUNCTION__); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - - *hue = ioctlval; - return ioctlval; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + + *hue = ioctlval; + return ioctlval; } static int set_saturation(int viddev, int new_saturation) { - unsigned char ioctlval= new_saturation; + unsigned char ioctlval= new_saturation; - if (ioctl(viddev, METEORSCSAT, &ioctlval) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORSCSAT Error setting saturation [%d]", - __FUNCTION__, new_saturation); - return -1; - } + if (ioctl(viddev, METEORSCSAT, &ioctlval) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORSCSAT Error setting saturation [%d]", + __FUNCTION__, new_saturation); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - return ioctlval; + return ioctlval; } static int get_saturation(int viddev , int *saturation) { - unsigned char ioctlval; + unsigned char ioctlval; - if (ioctl(viddev, METEORGCSAT, &ioctlval) < 0) { + if (ioctl(viddev, METEORGCSAT, &ioctlval) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORGCSAT Error getting saturation", __FUNCTION__); - return -1; - } + motion_log(LOG_ERR, 1, "%s: METEORGCSAT Error getting saturation", __FUNCTION__); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - - *saturation = ioctlval; - return ioctlval; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + + *saturation = ioctlval; + return ioctlval; } static int set_contrast(int viddev, int new_contrast) { - unsigned char ioctlval = new_contrast; + unsigned char ioctlval = new_contrast; - if (ioctl(viddev, METEORSCONT, &ioctlval) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORSCONT Error setting contrast [%d]", __FUNCTION__, new_contrast); - return 0; - } + if (ioctl(viddev, METEORSCONT, &ioctlval) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORSCONT Error setting contrast [%d]", + __FUNCTION__, new_contrast); + return 0; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - return ioctlval; + return ioctlval; } static int get_contrast(int viddev, int *contrast) { - unsigned char ioctlval; + unsigned char ioctlval; - if (ioctl (viddev, METEORGCONT, &ioctlval ) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORGCONT Error getting contrast", __FUNCTION__); - return -1; - } + if (ioctl (viddev, METEORGCONT, &ioctlval ) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORGCONT Error getting contrast", __FUNCTION__); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - - *contrast = ioctlval; - return ioctlval; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + + *contrast = ioctlval; + return ioctlval; } static int set_brightness(int viddev, int new_bright) { - unsigned char ioctlval = new_bright; + unsigned char ioctlval = new_bright; - if (ioctl(viddev, METEORSBRIG, &ioctlval) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORSBRIG brightness [%d]", __FUNCTION__, new_bright); - return -1; - } + if (ioctl(viddev, METEORSBRIG, &ioctlval) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORSBRIG brightness [%d]", __FUNCTION__, new_bright); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - - return ioctlval; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + + return ioctlval; } static int get_brightness(int viddev, int *brightness) { - unsigned char ioctlval; + unsigned char ioctlval; - if (ioctl(viddev, METEORGBRIG, &ioctlval) < 0) { + if (ioctl(viddev, METEORGBRIG, &ioctlval) < 0) { motion_log(LOG_ERR, 1, "%s: METEORGBRIG getting brightness", __FUNCTION__); return -1; } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); - - *brightness = ioctlval; - return ioctlval; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, ioctlval); + + *brightness = ioctlval; + return ioctlval; } // Set channel needed ? FIXME /* -static int set_channel( struct video_dev *viddev, int new_channel ) +static int set_channel(struct video_dev *viddev, int new_channel) { - int ioctlval; + int ioctlval; - ioctlval = new_channel; - if( ioctl( viddev->fd_tuner, TVTUNER_SETCHNL, &ioctlval ) < 0 ) { - motion_log(LOG_ERR, 1, "Error channel %d", ioctlval); - return -1; - } else { - motion_log(LOG_DEBUG, 0, "channel set to %d", ioctlval); - } + ioctlval = new_channel; + if (ioctl(viddev->fd_tuner, TVTUNER_SETCHNL, &ioctlval) < 0) { + motion_log(LOG_ERR, 1, "Error channel %d", ioctlval); + return -1; + } else { + motion_log(LOG_DEBUG, 0, "channel set to %d", ioctlval); + } - viddev->channel = new_channel; + viddev->channel = new_channel; - return 0; + return 0; } */ @@ -326,114 +327,120 @@ static int set_channel( struct video_dev *viddev, int new_channel ) static int set_freq(struct video_dev *viddev, unsigned long freq) { - int tuner_fd = viddev->fd_tuner; - int old_audio; + int tuner_fd = viddev->fd_tuner; + int old_audio; - motion_log(LOG_DEBUG, 0, "%s: Not implemented", __FUNCTION__); - - return 0; - - /* HACK maybe not need it , but seems that is needed to mute before changing frequency */ + motion_log(LOG_DEBUG, 0, "%s: Not implemented", __FUNCTION__); + + return 0; + + /* HACK maybe not need it , but seems that is needed to mute before changing frequency */ - if (ioctl(tuner_fd, BT848_GAUDIO, &old_audio) < 0) { - motion_log(LOG_ERR, 1, "%s: BT848_GAUDIO", __FUNCTION__); - return -1; - } - - if (ioctl(tuner_fd, TVTUNER_SETFREQ, &freq) < 0) { - motion_log(LOG_ERR, 1, "%s: Tuning (TVTUNER_SETFREQ) failed , freq [%lu]", __FUNCTION__, freq); - return -1; - } + if (ioctl(tuner_fd, BT848_GAUDIO, &old_audio) < 0) { + motion_log(LOG_ERR, 1, "%s: BT848_GAUDIO", __FUNCTION__); + return -1; + } + + if (ioctl(tuner_fd, TVTUNER_SETFREQ, &freq) < 0) { + motion_log(LOG_ERR, 1, "%s: Tuning (TVTUNER_SETFREQ) failed , freq [%lu]", __FUNCTION__, freq); + return -1; + } - old_audio &= AUDIO_MUTE; - if (old_audio) { - old_audio = AUDIO_MUTE; - if (ioctl(tuner_fd , BT848_SAUDIO, &old_audio) < 0) { - motion_log(LOG_ERR, 1, "%s: BT848_SAUDIO %i", __FUNCTION__, old_audio); - return -1; - } - } - - return 0; + old_audio &= AUDIO_MUTE; + if (old_audio) { + old_audio = AUDIO_MUTE; + if (ioctl(tuner_fd , BT848_SAUDIO, &old_audio) < 0) { + motion_log(LOG_ERR, 1, "%s: BT848_SAUDIO %i", __FUNCTION__, old_audio); + return -1; + } + } + + return 0; } /* set the input to capture images , could be tuner (METEOR_INPUT_DEV1) or any of others input : - RCA/COMPOSITE1 (METEOR_INPUT_DEV0) - COMPOSITE2/S-VIDEO (METEOR_INPUT_DEV2) - S-VIDEO (METEOR_INPUT_DEV3) - VBI ?! (METEOR_INPUT_DEV_SVIDEO) + RCA/COMPOSITE1 (METEOR_INPUT_DEV0) + COMPOSITE2/S-VIDEO (METEOR_INPUT_DEV2) + S-VIDEO (METEOR_INPUT_DEV3) + VBI ?! (METEOR_INPUT_DEV_SVIDEO) */ static int set_input(struct video_dev *viddev, unsigned short input) { - int actport; - int portdata[] = { METEOR_INPUT_DEV0, METEOR_INPUT_DEV1, - METEOR_INPUT_DEV2, METEOR_INPUT_DEV3, - METEOR_INPUT_DEV_SVIDEO }; + int actport; + int portdata[] = { METEOR_INPUT_DEV0, METEOR_INPUT_DEV1, + METEOR_INPUT_DEV2, METEOR_INPUT_DEV3, + METEOR_INPUT_DEV_SVIDEO}; - if (input >= array_elem(portdata)) { - motion_log(LOG_INFO, 0, "%s: Channel Port %d out of range (0-4)", __FUNCTION__, input); - return -1; - } + if (input >= array_elem(portdata)) { + motion_log(LOG_INFO, 0, "%s: Channel Port %d out of range (0-4)", __FUNCTION__, input); + return -1; + } - actport = portdata[ input ]; - if (ioctl(viddev->fd_bktr, METEORSINPUT, &actport) < 0) { - if (input != IN_DEFAULT) { - motion_log(LOG_INFO, 1, "%s: METEORSINPUT %d invalid - Trying default %d", - __FUNCTION__, input, IN_DEFAULT); - input = IN_DEFAULT; - actport = portdata[ input ]; - if (ioctl(viddev->fd_bktr, METEORSINPUT, &actport) < 0) { - motion_log(LOG_ERR, 1, "%s: METEORSINPUT %d init", __FUNCTION__, input); - return -1; - } - } else { - motion_log(LOG_ERR, 1, "%s: METEORSINPUT %d init", __FUNCTION__, input); - return -1; - } - } + actport = portdata[input]; + if (ioctl(viddev->fd_bktr, METEORSINPUT, &actport) < 0) { + if (input != IN_DEFAULT) { + motion_log(LOG_INFO, 1, "%s: METEORSINPUT %d invalid - Trying default %d", + __FUNCTION__, input, IN_DEFAULT); + input = IN_DEFAULT; + actport = portdata[input]; + if (ioctl(viddev->fd_bktr, METEORSINPUT, &actport) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORSINPUT %d init", __FUNCTION__, input); + return -1; + } + } else { + motion_log(LOG_ERR, 1, "%s: METEORSINPUT %d init", __FUNCTION__, input); + return -1; + } + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, input); - - return input; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d]", __FUNCTION__, input); + + return input; } static int set_geometry(struct video_dev *viddev, int width, int height) { - struct meteor_geomet geom; - int h_max; + struct meteor_geomet geom; + int h_max; - geom.columns = width; - geom.rows = height; + geom.columns = width; + geom.rows = height; - geom.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12; + geom.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12; - switch (viddev->norm) { - case PAL: h_max = PAL_HEIGHT; - case NTSC: h_max = NTSC_HEIGHT; - case SECAM: h_max = SECAM_HEIGHT; - default: h_max = PAL_HEIGHT; - } + switch (viddev->norm) { + case PAL: + h_max = PAL_HEIGHT; + break; + case NTSC: + h_max = NTSC_HEIGHT; + break; + case SECAM: + h_max = SECAM_HEIGHT; + break; + default: + h_max = PAL_HEIGHT; + } - if (height <= h_max / 2) { - geom.oformat |= METEOR_GEO_EVEN_ONLY; - } + if (height <= h_max / 2) + geom.oformat |= METEOR_GEO_EVEN_ONLY; - geom.frames = 1; + geom.frames = 1; - if (ioctl(viddev->fd_bktr, METEORSETGEO, &geom) < 0) { - motion_log(LOG_ERR, 1, "%s: Couldn't set the geometry", __FUNCTION__); - return -1; - } + if (ioctl(viddev->fd_bktr, METEORSETGEO, &geom) < 0) { + motion_log(LOG_ERR, 1, "%s: Couldn't set the geometry", __FUNCTION__); + return -1; + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to [%d/%d] Norm %d", __FUNCTION__, width, height, viddev->norm); - - return 0; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to [%d/%d] Norm %d", __FUNCTION__, width, height, viddev->norm); + + return 0; } /* @@ -442,151 +449,149 @@ static int set_geometry(struct video_dev *viddev, int width, int height) static int set_input_format(struct video_dev *viddev, unsigned short newformat) { - int input_format[] = { NORM_PAL_NEW, NORM_NTSC_NEW, NORM_SECAM_NEW, NORM_DEFAULT_NEW}; - int format; + int input_format[] = { NORM_PAL_NEW, NORM_NTSC_NEW, NORM_SECAM_NEW, NORM_DEFAULT_NEW}; + int format; - if (newformat >= array_elem( input_format )) { - motion_log(LOG_WARNING, 0, "%s: Input format %d out of range (0-2)", __FUNCTION__, newformat); - return -1; - } + if (newformat >= array_elem( input_format )) { + motion_log(LOG_WARNING, 0, "%s: Input format %d out of range (0-2)", __FUNCTION__, newformat); + return -1; + } - format = input_format[newformat]; + format = input_format[newformat]; - if( ioctl( viddev->fd_bktr, BT848SFMT, &format ) < 0 ) { - motion_log(LOG_ERR, 1, "%s: BT848SFMT, Couldn't set the input format , try again with default", - __FUNCTION__); - format = NORM_DEFAULT_NEW; - newformat = 3; - - if( ioctl( viddev->fd_bktr, BT848SFMT, &format ) < 0 ) { - motion_log(LOG_ERR, 1, "%s: BT848SFMT, Couldn't set the input format either default", - __FUNCTION__); - return -1; - } - } + if (ioctl( viddev->fd_bktr, BT848SFMT, &format) < 0) { + motion_log(LOG_ERR, 1, "%s: BT848SFMT, Couldn't set the input format , try again with default", + __FUNCTION__); + format = NORM_DEFAULT_NEW; + newformat = 3; + + if (ioctl(viddev->fd_bktr, BT848SFMT, &format) < 0) { + motion_log(LOG_ERR, 1, "%s: BT848SFMT, Couldn't set the input format either default", + __FUNCTION__); + return -1; + } + } - if (debug_level >= CAMERA_VIDEO) - motion_log(-1, 0, "%s: to %d", __FUNCTION__, newformat); - - return newformat; + if (debug_level >= CAMERA_VIDEO) + motion_log(-1, 0, "%s: to %d", __FUNCTION__, newformat); + + return newformat; } /* -statict int setup_pixelformat( int bktr ) +statict int setup_pixelformat(int bktr) { - int i; - struct meteor_pixfmt p; - int format=-1; + int i; + struct meteor_pixfmt p; + int format=-1; - for( i = 0; ; i++ ){ - p.index = i; - if( ioctl( bktr, METEORGSUPPIXFMT, &p ) < 0 ){ - if( errno == EINVAL ) - break; - motion_log(LOG_ERR, 1, "METEORGSUPPIXFMT getting pixformat %d", i); - return -1; - } + for(i = 0; ; i++){ + p.index = i; + if (ioctl(bktr, METEORGSUPPIXFMT, &p ) < 0) { + if (errno == EINVAL) + break; + motion_log(LOG_ERR, 1, "METEORGSUPPIXFMT getting pixformat %d", i); + return -1; + } - // Hack from xawtv 4.x + // Hack from xawtv 4.x - switch ( p.type ){ - case METEOR_PIXTYPE_RGB: - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB"); - switch(p.masks[0]) { - case 31744: // 15 bpp - format = p.swap_bytes ? VIDEO_RGB15_LE : VIDEO_RGB15_BE; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB15"); - break; - case 63488: // 16 bpp - format = p.swap_bytes ? VIDEO_RGB16_LE : VIDEO_RGB16_BE; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB16"); - break; - case 16711680: // 24/32 bpp - if (p.Bpp == 3 && p.swap_bytes == 1) { - format = VIDEO_BGR24; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_BGR24"); - } else if (p.Bpp == 4 && p.swap_bytes == 1 && p.swap_shorts == 1) { - format = VIDEO_BGR32; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_BGR32"); - } else if (p.Bpp == 4 && p.swap_bytes == 0 && p.swap_shorts == 0) { - format = VIDEO_RGB32; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB32"); - } - } - break; - case METEOR_PIXTYPE_YUV: - format = VIDEO_YUV422P; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV"); - break; - case METEOR_PIXTYPE_YUV_12: - format = VIDEO_YUV422P; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV_12"); - break; - case METEOR_PIXTYPE_YUV_PACKED: - format = VIDEO_YUV422P; - motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV_PACKED"); - break; - - } + switch ( p.type ) { + case METEOR_PIXTYPE_RGB: + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB"); + switch(p.masks[0]) { + case 31744: // 15 bpp + format = p.swap_bytes ? VIDEO_RGB15_LE : VIDEO_RGB15_BE; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB15"); + break; + case 63488: // 16 bpp + format = p.swap_bytes ? VIDEO_RGB16_LE : VIDEO_RGB16_BE; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB16"); + break; + case 16711680: // 24/32 bpp + if (p.Bpp == 3 && p.swap_bytes == 1) { + format = VIDEO_BGR24; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_BGR24"); + } else if (p.Bpp == 4 && p.swap_bytes == 1 && p.swap_shorts == 1) { + format = VIDEO_BGR32; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_BGR32"); + } else if (p.Bpp == 4 && p.swap_bytes == 0 && p.swap_shorts == 0) { + format = VIDEO_RGB32; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_RGB VIDEO_RGB32"); + } + break; + case METEOR_PIXTYPE_YUV: + format = VIDEO_YUV422P; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV"); + break; + case METEOR_PIXTYPE_YUV_12: + format = VIDEO_YUV422P; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV_12"); + break; + case METEOR_PIXTYPE_YUV_PACKED: + format = VIDEO_YUV422P; + motion_log(-1, 0, "setup_pixelformat METEOR_PIXTYPE_YUV_PACKED"); + break; + } - if( p.type == METEOR_PIXTYPE_RGB && p.Bpp == 3 ){ - // Found a good pixeltype -- set it up - if( ioctl( bktr, METEORSACTPIXFMT, &i ) < 0 ){ - motion_log(LOG_WARNING, 1, "METEORSACTPIXFMT etting pixformat METEOR_PIXTYPE_RGB Bpp == 3"); - // Not immediately fatal - } - motion_log(LOG_DEBUG, 0, "input format METEOR_PIXTYPE_RGB %i", i); - format = i; - } + if (p.type == METEOR_PIXTYPE_RGB && p.Bpp == 3){ + // Found a good pixeltype -- set it up + if (ioctl(bktr, METEORSACTPIXFMT, &i) < 0){ + motion_log(LOG_WARNING, 1, "METEORSACTPIXFMT etting pixformat METEOR_PIXTYPE_RGB Bpp == 3"); + // Not immediately fatal + } + motion_log(LOG_DEBUG, 0, "input format METEOR_PIXTYPE_RGB %i", i); + format = i; + } - if( p.type == METEOR_PIXTYPE_YUV_PACKED ){ - // Found a good pixeltype -- set it up - if( ioctl( bktr, METEORSACTPIXFMT, &i ) < 0 ){ - motion_log(LOG_WARNING, 1, "METEORSACTPIXFMT setting pixformat METEOR_PIXTYPE_YUV_PACKED"); - // Not immediately fatal - } - motion_log(LOG_DEBUG, 0, "input format METEOR_PIXTYPE_YUV_PACKED %i", i); - format = i; - } + if (p.type == METEOR_PIXTYPE_YUV_PACKED) { + // Found a good pixeltype -- set it up + if (ioctl(bktr, METEORSACTPIXFMT, &i ) < 0){ + motion_log(LOG_WARNING, 1, "METEORSACTPIXFMT setting pixformat METEOR_PIXTYPE_YUV_PACKED"); + // Not immediately fatal + } + motion_log(LOG_DEBUG, 0, "input format METEOR_PIXTYPE_YUV_PACKED %i", i); + format = i; + } - } + } - return format; + return format; } */ static void v4l_picture_controls(struct context *cnt, struct video_dev *viddev) { - int dev = viddev->fd_bktr; + int dev = viddev->fd_bktr; - if ( (cnt->conf.contrast) && (cnt->conf.contrast != viddev->contrast) ) { - set_contrast(dev, cnt->conf.contrast); - viddev->contrast = cnt->conf.contrast; - } + if ((cnt->conf.contrast) && (cnt->conf.contrast != viddev->contrast)) { + set_contrast(dev, cnt->conf.contrast); + viddev->contrast = cnt->conf.contrast; + } - if ( (cnt->conf.hue) && (cnt->conf.hue != viddev->hue) ) { - set_hue(dev, cnt->conf.hue); - viddev->hue = cnt->conf.hue; - } + if ((cnt->conf.hue) && (cnt->conf.hue != viddev->hue)) { + set_hue(dev, cnt->conf.hue); + viddev->hue = cnt->conf.hue; + } - if ( (cnt->conf.brightness) && - (cnt->conf.brightness != viddev->brightness)) { - set_brightness(dev, cnt->conf.brightness); - viddev->brightness = cnt->conf.brightness; - } + if ((cnt->conf.brightness) && + (cnt->conf.brightness != viddev->brightness)) { + set_brightness(dev, cnt->conf.brightness); + viddev->brightness = cnt->conf.brightness; + } - if ( (cnt->conf.saturation ) && - (cnt->conf.saturation != viddev->saturation) ) { - set_saturation(dev, cnt->conf.saturation); - viddev->saturation = cnt->conf.saturation; - } + if ((cnt->conf.saturation) && + (cnt->conf.saturation != viddev->saturation)) { + set_saturation(dev, cnt->conf.saturation); + viddev->saturation = cnt->conf.saturation; + } } /******************************************************************************************* - Video capture routines + Video capture routines - set input - setup_pixelformat @@ -603,178 +608,178 @@ static void v4l_picture_controls(struct context *cnt, struct video_dev *viddev) static unsigned char *v4l_start(struct video_dev *viddev, int width, int height, unsigned short input, unsigned short norm, unsigned long freq) { - int dev_bktr = viddev->fd_bktr; - struct sigaction act, old; - //int dev_tunner = viddev->fd_tuner; - /* to ensure that all device will be support the capture mode - _TODO_ : Autodected the best capture mode . - */ - int dummy = 1; -// int pixelformat = BSD_VIDFMT_I420; + int dev_bktr = viddev->fd_bktr; + struct sigaction act, old; + //int dev_tunner = viddev->fd_tuner; + /* to ensure that all device will be support the capture mode + _TODO_ : Autodected the best capture mode . + */ + int dummy = 1; +// int pixelformat = BSD_VIDFMT_I420; - void *map; + void *map; - /* if we have choose the tuner is needed to setup the frequency */ - if ( (viddev->tuner_device != NULL) && ( input == IN_TV ) ) { - if (!freq) { - motion_log(LOG_ERR, 0, "%s: Not valid Frequency [%lu] for Source input [%i]", - __FUNCTION__, freq, input); - return (NULL); - }else if (set_freq(viddev, freq) == -1) { - motion_log(LOG_ERR, 0, "%s: Frequency [%lu] Source input [%i]", - __FUNCTION__, freq, input); - return (NULL); - } - } - - /* FIXME if we set as input tuner , we need to set option for tuner not for bktr */ + /* if we have choose the tuner is needed to setup the frequency */ + if ((viddev->tuner_device != NULL) && (input == IN_TV)) { + if (!freq) { + motion_log(LOG_ERR, 0, "%s: Not valid Frequency [%lu] for Source input [%i]", + __FUNCTION__, freq, input); + return (NULL); + } else if (set_freq(viddev, freq) == -1) { + motion_log(LOG_ERR, 0, "%s: Frequency [%lu] Source input [%i]", + __FUNCTION__, freq, input); + return (NULL); + } + } + + /* FIXME if we set as input tuner , we need to set option for tuner not for bktr */ - if ((dummy = set_input(viddev, input)) == -1) { - motion_log(LOG_ERR, 0, "%s: set input [%d]", __FUNCTION__, input); - return (NULL); - } + if ((dummy = set_input(viddev, input)) == -1) { + motion_log(LOG_ERR, 0, "%s: set input [%d]", __FUNCTION__, input); + return (NULL); + } - viddev->input = dummy; + viddev->input = dummy; - if ((dummy = set_input_format(viddev, norm)) == -1) { - motion_log(LOG_ERR, 0, "%s: set input format [%d]", __FUNCTION__, norm); - return (NULL); - } + if ((dummy = set_input_format(viddev, norm)) == -1) { + motion_log(LOG_ERR, 0, "%s: set input format [%d]", __FUNCTION__, norm); + return (NULL); + } - viddev->norm = dummy; + viddev->norm = dummy; - if (set_geometry(viddev, width, height) == -1) { - motion_log(LOG_ERR, 0, "%s: set geometry [%d]x[%d]", __FUNCTION__, width, height); - return (NULL); - } + if (set_geometry(viddev, width, height) == -1) { + motion_log(LOG_ERR, 0, "%s: set geometry [%d]x[%d]", __FUNCTION__, width, height); + return (NULL); + } /* - if (ioctl(dev_bktr, METEORSACTPIXFMT, &pixelformat) < 0 ){ - motion_log(LOG_ERR, 1, "set encoding method BSD_VIDFMT_I420"); - return(NULL); + if (ioctl(dev_bktr, METEORSACTPIXFMT, &pixelformat) < 0 ){ + motion_log(LOG_ERR, 1, "set encoding method BSD_VIDFMT_I420"); + return(NULL); } - NEEDED !? FIXME + NEEDED !? FIXME - if ( setup_pixelformat(viddev) == -1) { - return (NULL); - } + if (setup_pixelformat(viddev) == -1) { + return (NULL); + } */ - if (freq) { - if (debug_level >= CAMERA_DEBUG) - motion_log(-1, 0, "%s: Frequency set (no implemented yet", __FUNCTION__); - /* - TODO missing implementation - set_channelset(viddev); - set_channel(viddev); - if (set_freq (viddev, freq) == -1) { - return (NULL); - } - */ - } + if (freq) { + if (debug_level >= CAMERA_DEBUG) + motion_log(-1, 0, "%s: Frequency set (no implemented yet", __FUNCTION__); + /* + TODO missing implementation + set_channelset(viddev); + set_channel(viddev); + if (set_freq (viddev, freq) == -1) { + return (NULL); + } + */ + } - /* set capture mode and capture buffers */ + /* set capture mode and capture buffers */ - /* That is the buffer size for capture images , - so is dependent of color space of input format / FIXME */ + /* That is the buffer size for capture images , + so is dependent of color space of input format / FIXME */ - viddev->v4l_bufsize = (((width * height * 3 / 2)) * sizeof(unsigned char *)); - viddev->v4l_fmt = VIDEO_PALETTE_YUV420P; - + viddev->v4l_bufsize = (((width * height * 3 / 2)) * sizeof(unsigned char *)); + viddev->v4l_fmt = VIDEO_PALETTE_YUV420P; + - map = mmap((caddr_t)0, viddev->v4l_bufsize, PROT_READ|PROT_WRITE, MAP_SHARED, dev_bktr, (off_t)0); + map = mmap((caddr_t)0, viddev->v4l_bufsize, PROT_READ|PROT_WRITE, MAP_SHARED, dev_bktr, (off_t)0); - if (map == MAP_FAILED){ - motion_log(LOG_ERR, 1, "%s: mmap failed", __FUNCTION__); - return (NULL); - } + if (map == MAP_FAILED){ + motion_log(LOG_ERR, 1, "%s: mmap failed", __FUNCTION__); + return (NULL); + } - /* FIXME double buffer */ - if (0) { - viddev->v4l_maxbuffer = 2; - viddev->v4l_buffers[0] = map; - viddev->v4l_buffers[1] = (unsigned char *)map + 0; /* 0 is not valid just a test */ - //viddev->v4l_buffers[1] = map+vid_buf.offsets[1]; - } else { - viddev->v4l_buffers[0] = map; - viddev->v4l_maxbuffer = 1; - } + /* FIXME double buffer */ + if (0) { + viddev->v4l_maxbuffer = 2; + viddev->v4l_buffers[0] = map; + viddev->v4l_buffers[1] = (unsigned char *)map + 0; /* 0 is not valid just a test */ + //viddev->v4l_buffers[1] = map+vid_buf.offsets[1]; + } else { + viddev->v4l_buffers[0] = map; + viddev->v4l_maxbuffer = 1; + } - viddev->v4l_curbuffer = 0; + viddev->v4l_curbuffer = 0; - /* Clear the buffer */ + /* Clear the buffer */ if (ioctl(dev_bktr, BT848SCBUF, &dummy) < 0) { motion_log(LOG_ERR, 1, "%s: BT848SCBUF", __FUNCTION__); return NULL; } - /* signal handler to know when data is ready to be read() */ + /* signal handler to know when data is ready to be read() */ - memset(&act, 0, sizeof(act)); - sigemptyset(&act.sa_mask); - act.sa_handler = catchsignal; - sigaction(SIGUSR2, &act, &old); + memset(&act, 0, sizeof(act)); + sigemptyset(&act.sa_mask); + act.sa_handler = catchsignal; + sigaction(SIGUSR2, &act, &old); - dummy = SIGUSR2; + dummy = SIGUSR2; - //viddev->capture_method = METEOR_CAP_CONTINOUS; - //viddev->capture_method = METEOR_CAP_SINGLE; - - if ((viddev->capture_method == METEOR_CAP_CONTINOUS) && (ioctl(dev_bktr, METEORSSIGNAL, &dummy) < 0)) { - motion_log(LOG_ERR, 1, "%s: METEORSSIGNAL", __FUNCTION__); - motion_log(LOG_INFO, 0 , "%s: METEORSSIGNAL", __FUNCTION__); - viddev->capture_method = METEOR_CAP_SINGLE; - if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0){ - motion_log(LOG_ERR, 1, "%s: METEORCAPTUR using single method " - "Error capturing", __FUNCTION__); - motion_log(LOG_INFO, 0, "%s: METEORCAPTUR using single method " - "Error capturing", __FUNCTION__); - } - } else { - if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0) { - viddev->capture_method = METEOR_CAP_SINGLE; - if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0){ - motion_log(LOG_ERR, 1, "%s: METEORCAPTUR using single method " - "Error capturing", __FUNCTION__); - motion_log(LOG_INFO, 0, "%s: METEORCAPTUR using single method " - "Error capturing", __FUNCTION__); - } - } - } + //viddev->capture_method = METEOR_CAP_CONTINOUS; + //viddev->capture_method = METEOR_CAP_SINGLE; + + if ((viddev->capture_method == METEOR_CAP_CONTINOUS) && (ioctl(dev_bktr, METEORSSIGNAL, &dummy) < 0)) { + motion_log(LOG_ERR, 1, "%s: METEORSSIGNAL", __FUNCTION__); + motion_log(LOG_INFO, 0 , "%s: METEORSSIGNAL", __FUNCTION__); + viddev->capture_method = METEOR_CAP_SINGLE; + if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORCAPTUR using single method " + "Error capturing", __FUNCTION__); + motion_log(LOG_INFO, 0, "%s: METEORCAPTUR using single method " + "Error capturing", __FUNCTION__); + } + } else { + if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0) { + viddev->capture_method = METEOR_CAP_SINGLE; + if (ioctl(dev_bktr, METEORCAPTUR, &viddev->capture_method) < 0) { + motion_log(LOG_ERR, 1, "%s: METEORCAPTUR using single method " + "Error capturing", __FUNCTION__); + motion_log(LOG_INFO, 0, "%s: METEORCAPTUR using single method " + "Error capturing", __FUNCTION__); + } + } + } - if (viddev->capture_method == METEOR_CAP_CONTINOUS) - motion_log(LOG_INFO, 0, "%s: METEORCAPTUR METEOR_CAP_CONTINOUS", __FUNCTION__); - else - motion_log(LOG_INFO, 0, "%s: METEORCAPTUR METEOR_CAP_SINGLE", __FUNCTION__); - - // settle , sleep(1) replaced - SLEEP(1, 0); + if (viddev->capture_method == METEOR_CAP_CONTINOUS) + motion_log(LOG_INFO, 0, "%s: METEORCAPTUR METEOR_CAP_CONTINOUS", __FUNCTION__); + else + motion_log(LOG_INFO, 0, "%s: METEORCAPTUR METEOR_CAP_SINGLE", __FUNCTION__); + + // settle , sleep(1) replaced + SLEEP(1, 0); - /* FIXME*/ - switch (viddev->v4l_fmt) { - case VIDEO_PALETTE_YUV420P: - viddev->v4l_bufsize = (width * height * 3) / 2; - break; - case VIDEO_PALETTE_YUV422: - viddev->v4l_bufsize = (width * height * 2); - break; - case VIDEO_PALETTE_RGB24: - viddev->v4l_bufsize = (width * height * 3); - break; - case VIDEO_PALETTE_GREY: - viddev->v4l_bufsize = width * height; - break; - } - - motion_log(LOG_INFO, 0, "HUE [%d]", get_hue(dev_bktr, &dummy)); - motion_log(LOG_INFO, 0, "SATURATION [%d]", get_saturation(dev_bktr, &dummy)); - motion_log(LOG_INFO, 0, "BRIGHTNESS [%d]", get_brightness(dev_bktr, &dummy)); - motion_log(LOG_INFO, 0, "CONTRAST [%d]", get_contrast(dev_bktr, &dummy)); - - return map; + /* FIXME*/ + switch (viddev->v4l_fmt) { + case VIDEO_PALETTE_YUV420P: + viddev->v4l_bufsize = (width * height * 3) / 2; + break; + case VIDEO_PALETTE_YUV422: + viddev->v4l_bufsize = (width * height * 2); + break; + case VIDEO_PALETTE_RGB24: + viddev->v4l_bufsize = (width * height * 3); + break; + case VIDEO_PALETTE_GREY: + viddev->v4l_bufsize = width * height; + break; + } + + motion_log(LOG_INFO, 0, "HUE [%d]", get_hue(dev_bktr, &dummy)); + motion_log(LOG_INFO, 0, "SATURATION [%d]", get_saturation(dev_bktr, &dummy)); + motion_log(LOG_INFO, 0, "BRIGHTNESS [%d]", get_brightness(dev_bktr, &dummy)); + motion_log(LOG_INFO, 0, "CONTRAST [%d]", get_contrast(dev_bktr, &dummy)); + + return map; } @@ -793,56 +798,56 @@ static unsigned char *v4l_start(struct video_dev *viddev, int width, int height, */ static int v4l_next(struct video_dev *viddev, unsigned char *map, int width, int height) { - int dev_bktr = viddev->fd_bktr; - unsigned char *cap_map = NULL; - int single = METEOR_CAP_SINGLE; - sigset_t set, old; + int dev_bktr = viddev->fd_bktr; + unsigned char *cap_map = NULL; + int single = METEOR_CAP_SINGLE; + sigset_t set, old; - /* ONLY MMAP method is used to Capture */ + /* ONLY MMAP method is used to Capture */ - /* Allocate a new mmap buffer */ - /* Block signals during IOCTL */ - sigemptyset (&set); - sigaddset (&set, SIGCHLD); - sigaddset (&set, SIGALRM); - sigaddset (&set, SIGUSR1); - sigaddset (&set, SIGTERM); - sigaddset (&set, SIGHUP); - pthread_sigmask(SIG_BLOCK, &set, &old); - cap_map = viddev->v4l_buffers[viddev->v4l_curbuffer]; + /* Allocate a new mmap buffer */ + /* Block signals during IOCTL */ + sigemptyset (&set); + sigaddset (&set, SIGCHLD); + sigaddset (&set, SIGALRM); + sigaddset (&set, SIGUSR1); + sigaddset (&set, SIGTERM); + sigaddset (&set, SIGHUP); + pthread_sigmask(SIG_BLOCK, &set, &old); + cap_map = viddev->v4l_buffers[viddev->v4l_curbuffer]; - viddev->v4l_curbuffer++; - if (viddev->v4l_curbuffer >= viddev->v4l_maxbuffer) - viddev->v4l_curbuffer = 0; + viddev->v4l_curbuffer++; + if (viddev->v4l_curbuffer >= viddev->v4l_maxbuffer) + viddev->v4l_curbuffer = 0; - /* capture */ - - if (viddev->capture_method == METEOR_CAP_CONTINOUS) { - if (bktr_frame_waiting) - bktr_frame_waiting = 0; - - } else if (ioctl(dev_bktr, METEORCAPTUR, &single) < 0) { - motion_log(LOG_ERR, 1, "%s: Error capturing using single method", __FUNCTION__); - sigprocmask(SIG_UNBLOCK, &old, NULL); - return (-1); - } + /* capture */ + + if (viddev->capture_method == METEOR_CAP_CONTINOUS) { + if (bktr_frame_waiting) + bktr_frame_waiting = 0; + + } else if (ioctl(dev_bktr, METEORCAPTUR, &single) < 0) { + motion_log(LOG_ERR, 1, "%s: Error capturing using single method", __FUNCTION__); + sigprocmask(SIG_UNBLOCK, &old, NULL); + return (-1); + } - /*undo the signal blocking*/ - pthread_sigmask(SIG_UNBLOCK, &old, NULL); - - switch (viddev->v4l_fmt) { - case VIDEO_PALETTE_RGB24: - rgb24toyuv420p(map, cap_map, width, height); - break; - case VIDEO_PALETTE_YUV422: - yuv422to420p(map, cap_map, width, height); - break; - default: - memcpy(map, cap_map, viddev->v4l_bufsize); - } - - return 0; + /*undo the signal blocking*/ + pthread_sigmask(SIG_UNBLOCK, &old, NULL); + + switch (viddev->v4l_fmt) { + case VIDEO_PALETTE_RGB24: + rgb24toyuv420p(map, cap_map, width, height); + break; + case VIDEO_PALETTE_YUV422: + yuv422to420p(map, cap_map, width, height); + break; + default: + memcpy(map, cap_map, viddev->v4l_bufsize); + } + + return 0; } @@ -852,54 +857,55 @@ static void v4l_set_input(struct context *cnt, struct video_dev *viddev, unsigne unsigned short input, unsigned short norm, int skip, unsigned long freq) { - if (input != viddev->input || norm != viddev->norm || freq != viddev->freq) { - int dummy; - unsigned long frequnits = freq; + if (input != viddev->input || norm != viddev->norm || freq != viddev->freq) { + int dummy; + unsigned long frequnits = freq; - - if ((dummy = set_input(viddev, input)) == -1) - return; + + if ((dummy = set_input(viddev, input)) == -1) + return; - viddev->input = dummy; - - if ((dummy = set_input_format(viddev, norm)) == -1) - return; - - viddev->norm = dummy; - - if ((viddev->tuner_device != NULL) && ( viddev->input == IN_TV ) && (frequnits > 0)) { - if (set_freq(viddev, freq) == -1) - return; - } + viddev->input = dummy; + + if ((dummy = set_input_format(viddev, norm)) == -1) + return; + + viddev->norm = dummy; + + if ((viddev->tuner_device != NULL) && (viddev->input == IN_TV) && (frequnits > 0)) { + if (set_freq(viddev, freq) == -1) + return; + } - // FIXME - /* - if ( setup_pixelformat(viddev) == -1) { - motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)"); - return - } - */ + // FIXME + /* + if (setup_pixelformat(viddev) == -1) { + motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)"); + return + } + */ - /* - if (set_geometry(viddev, width, height) == -1) - return; - */ - - v4l_picture_controls(cnt, viddev); + /* + if (set_geometry(viddev, width, height) == -1) + return; + */ + + v4l_picture_controls(cnt, viddev); - viddev->freq = freq; + viddev->freq = freq; - /* skip a few frames if needed */ - for (dummy = 0; dummy < skip; dummy++) - v4l_next(viddev, map, width, height); - }else{ - /* No round robin - we only adjust picture controls */ - v4l_picture_controls(cnt, viddev); - } + /* skip a few frames if needed */ + for (dummy = 0; dummy < skip; dummy++) + v4l_next(viddev, map, width, height); + + } else { + /* No round robin - we only adjust picture controls */ + v4l_picture_controls(cnt, viddev); + } } /***************************************************************************** - Wrappers calling the current capture routines + Wrappers calling the current capture routines *****************************************************************************/ /* @@ -932,7 +938,7 @@ static struct video_dev *viddevs = NULL; */ void vid_init(void) { - pthread_mutex_init(&vid_mutex, NULL); + pthread_mutex_init(&vid_mutex, NULL); } /** @@ -942,7 +948,7 @@ void vid_init(void) */ void vid_cleanup(void) { - pthread_mutex_destroy(&vid_mutex); + pthread_mutex_destroy(&vid_mutex); } #endif /*WITHOUT_V4L*/ @@ -987,47 +993,51 @@ void vid_close(struct context *cnt) return; } - if( --dev->usage_count == 0) { - motion_log(LOG_INFO, 0, "%s: Closing video device %s", __FUNCTION__, dev->video_device); - if (dev->fd_tuner > 0) - close(dev->fd_tuner); - - if (dev->fd_bktr > 0) { - if (dev->capture_method == METEOR_CAP_CONTINOUS) { - dev->fd_tuner = METEOR_CAP_STOP_CONT; - ioctl(dev->fd_bktr, METEORCAPTUR, &dev->fd_tuner); - } - close(dev->fd_bktr); - dev->fd_tuner = -1; - } + if (--dev->usage_count == 0) { + motion_log(LOG_INFO, 0, "%s: Closing video device %s", + __FUNCTION__, dev->video_device); - - munmap(viddevs->v4l_buffers[0], viddevs->v4l_bufsize); - viddevs->v4l_buffers[0] = MAP_FAILED; - - dev->fd_bktr = -1; - pthread_mutex_lock(&vid_mutex); - /* Remove from list */ - if (prev == NULL) - viddevs = dev->next; - else - prev->next = dev->next; - pthread_mutex_unlock(&vid_mutex); - - pthread_mutexattr_destroy(&dev->attr); - pthread_mutex_destroy(&dev->mutex); - free(dev); - } else { - motion_log(LOG_INFO, 0, "%s: Still %d users of video device %s, so we don't close it now", - __FUNCTION__, dev->usage_count, dev->video_device); - /* There is still at least one thread using this device - * If we own it, release it - */ - if (dev->owner == cnt->threadnr) { - dev->frames = 0; - dev->owner = -1; - pthread_mutex_unlock(&dev->mutex); + if (dev->fd_tuner > 0) + close(dev->fd_tuner); + + if (dev->fd_bktr > 0) { + if (dev->capture_method == METEOR_CAP_CONTINOUS) { + dev->fd_tuner = METEOR_CAP_STOP_CONT; + ioctl(dev->fd_bktr, METEORCAPTUR, &dev->fd_tuner); } + close(dev->fd_bktr); + dev->fd_tuner = -1; + } + + + munmap(viddevs->v4l_buffers[0], viddevs->v4l_bufsize); + viddevs->v4l_buffers[0] = MAP_FAILED; + + dev->fd_bktr = -1; + pthread_mutex_lock(&vid_mutex); + + /* Remove from list */ + if (prev == NULL) + viddevs = dev->next; + else + prev->next = dev->next; + + pthread_mutex_unlock(&vid_mutex); + + pthread_mutexattr_destroy(&dev->attr); + pthread_mutex_destroy(&dev->mutex); + free(dev); + } else { + motion_log(LOG_INFO, 0, "%s: Still %d users of video device %s, so we don't close it now", + __FUNCTION__, dev->usage_count, dev->video_device); + /* There is still at least one thread using this device + * If we own it, release it + */ + if (dev->owner == cnt->threadnr) { + dev->frames = 0; + dev->owner = -1; + pthread_mutex_unlock(&dev->mutex); + } } #endif /* WITHOUT_V4L */ } @@ -1036,201 +1046,202 @@ void vid_close(struct context *cnt) int vid_start(struct context *cnt) { - struct config *conf = &cnt->conf; - int fd_bktr = -1; + struct config *conf = &cnt->conf; + int fd_bktr = -1; - if (conf->netcam_url) { - fd_bktr = netcam_start(cnt); - if (fd_bktr < 0) { - netcam_cleanup(cnt->netcam, 1); - cnt->netcam = NULL; - } - } + if (conf->netcam_url) { + fd_bktr = netcam_start(cnt); + if (fd_bktr < 0) { + netcam_cleanup(cnt->netcam, 1); + cnt->netcam = NULL; + } + } #ifdef WITHOUT_V4L - else - motion_log(LOG_ERR, 0, "%s: You must setup netcam_url", __FUNCTION__); + else + motion_log(LOG_ERR, 0, "%s: You must setup netcam_url", __FUNCTION__); #else - else{ - struct video_dev *dev; - int fd_tuner = -1; - int width, height, capture_method; - unsigned short input, norm; - unsigned long frequency; + else { + struct video_dev *dev; + int fd_tuner = -1; + int width, height, capture_method; + unsigned short input, norm; + unsigned long frequency; - motion_log(-1, 0, "%s: [%s]", __FUNCTION__, conf->video_device); + motion_log(-1, 0, "%s: [%s]", __FUNCTION__, conf->video_device); - /* We use width and height from conf in this function. They will be assigned - * to width and height in imgs here, and cap_width and cap_height in - * rotate_data won't be set until in rotate_init. - * Motion requires that width and height are multiples of 16 so we check for this - */ - if (conf->width % 16) { - motion_log(LOG_ERR, 0, - "%s: config image width (%d) is not modulo 16", - __FUNCTION__, conf->width); - return -1; - } - if (conf->height % 16) { - motion_log(LOG_ERR, 0, - "%s: config image height (%d) is not modulo 16", - __FUNCTION__, conf->height); - return -1; - } - width = conf->width; - height = conf->height; - input = conf->input; - norm = conf->norm; - frequency = conf->frequency; - capture_method = METEOR_CAP_CONTINOUS; - - pthread_mutex_lock(&vid_mutex); + /* We use width and height from conf in this function. They will be assigned + * to width and height in imgs here, and cap_width and cap_height in + * rotate_data won't be set until in rotate_init. + * Motion requires that width and height are multiples of 16 so we check for this + */ + if (conf->width % 16) { + motion_log(LOG_ERR, 0, + "%s: config image width (%d) is not modulo 16", + __FUNCTION__, conf->width); + return -1; + } + if (conf->height % 16) { + motion_log(LOG_ERR, 0, + "%s: config image height (%d) is not modulo 16", + __FUNCTION__, conf->height); + return -1; + } - /* Transfer width and height from conf to imgs. The imgs values are the ones - * that is used internally in Motion. That way, setting width and height via - * http remote control won't screw things up. - */ - cnt->imgs.width = width; - cnt->imgs.height = height; + width = conf->width; + height = conf->height; + input = conf->input; + norm = conf->norm; + frequency = conf->frequency; + capture_method = METEOR_CAP_CONTINOUS; + + pthread_mutex_lock(&vid_mutex); - /* First we walk through the already discovered video devices to see - * if we have already setup the same device before. If this is the case - * the device is a Round Robin device and we set the basic settings - * and return the file descriptor - */ - dev = viddevs; - while (dev) { - if (!strcmp(conf->video_device, dev->video_device)) { - int dummy = METEOR_CAP_STOP_CONT; - dev->usage_count++; - cnt->imgs.type = dev->v4l_fmt; + /* Transfer width and height from conf to imgs. The imgs values are the ones + * that is used internally in Motion. That way, setting width and height via + * http remote control won't screw things up. + */ + cnt->imgs.width = width; + cnt->imgs.height = height; - if (ioctl(dev->fd_bktr, METEORCAPTUR, &dummy) < 0) { - motion_log(LOG_ERR, 1, "%s Stopping capture", __FUNCTION__); - return -1; - } - - motion_log(-1, 0, "%s Reusing [%s] inputs [%d,%d] Change capture method " - "METEOR_CAP_SINGLE", __FUNCTION__, dev->video_device, - dev->input, conf->input); + /* First we walk through the already discovered video devices to see + * if we have already setup the same device before. If this is the case + * the device is a Round Robin device and we set the basic settings + * and return the file descriptor + */ + dev = viddevs; + while (dev) { + if (!strcmp(conf->video_device, dev->video_device)) { + int dummy = METEOR_CAP_STOP_CONT; + dev->usage_count++; + cnt->imgs.type = dev->v4l_fmt; - dev->capture_method = METEOR_CAP_SINGLE; - - switch (cnt->imgs.type) { - case VIDEO_PALETTE_GREY: - cnt->imgs.motionsize = width * height; - cnt->imgs.size = width * height; - break; - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_YUV422: - cnt->imgs.type = VIDEO_PALETTE_YUV420P; - case VIDEO_PALETTE_YUV420P: - motion_log(-1, 0, - "%s VIDEO_PALETTE_YUV420P setting imgs.size " - "and imgs.motionsize", __FUNCTION__); - cnt->imgs.motionsize = width * height; - cnt->imgs.size = (width * height * 3) / 2; - break; - } - pthread_mutex_unlock(&vid_mutex); - return dev->fd_bktr; // FIXME return fd_tuner ?! - } - dev = dev->next; - } + if (ioctl(dev->fd_bktr, METEORCAPTUR, &dummy) < 0) { + motion_log(LOG_ERR, 1, "%s Stopping capture", __FUNCTION__); + return -1; + } + + motion_log(-1, 0, "%s Reusing [%s] inputs [%d,%d] Change capture method " + "METEOR_CAP_SINGLE", __FUNCTION__, dev->video_device, + dev->input, conf->input); + + dev->capture_method = METEOR_CAP_SINGLE; + + switch (cnt->imgs.type) { + case VIDEO_PALETTE_GREY: + cnt->imgs.motionsize = width * height; + cnt->imgs.size = width * height; + break; + case VIDEO_PALETTE_RGB24: + case VIDEO_PALETTE_YUV422: + cnt->imgs.type = VIDEO_PALETTE_YUV420P; + case VIDEO_PALETTE_YUV420P: + motion_log(-1, 0, + "%s VIDEO_PALETTE_YUV420P setting imgs.size " + "and imgs.motionsize", __FUNCTION__); + cnt->imgs.motionsize = width * height; + cnt->imgs.size = (width * height * 3) / 2; + break; + } + pthread_mutex_unlock(&vid_mutex); + return dev->fd_bktr; // FIXME return fd_tuner ?! + } + dev = dev->next; + } - dev = mymalloc(sizeof(struct video_dev)); - memset(dev, 0, sizeof(struct video_dev)); + dev = mymalloc(sizeof(struct video_dev)); + memset(dev, 0, sizeof(struct video_dev)); - fd_bktr = open(conf->video_device, O_RDWR); + fd_bktr = open(conf->video_device, O_RDWR); - if (fd_bktr < 0) { - motion_log(LOG_ERR, 1, "%s: open video device %s", __FUNCTION__, conf->video_device); - free(dev); - pthread_mutex_unlock(&vid_mutex); - return -1; - } + if (fd_bktr < 0) { + motion_log(LOG_ERR, 1, "%s: open video device %s", __FUNCTION__, conf->video_device); + free(dev); + pthread_mutex_unlock(&vid_mutex); + return -1; + } - /* Only open tuner if conf->tuner_device has set , freq and input is 1 */ - if ( (conf->tuner_device != NULL) && (frequency > 0) && ( input == IN_TV )) { - fd_tuner = open(conf->tuner_device, O_RDWR); - if (fd_tuner < 0) { - motion_log(LOG_ERR, 1, "%s: open tuner device %s", - __FUNCTION__, conf->tuner_device); - free(dev); - pthread_mutex_unlock(&vid_mutex); - return -1; - } - } + /* Only open tuner if conf->tuner_device has set , freq and input is 1 */ + if ((conf->tuner_device != NULL) && (frequency > 0) && (input == IN_TV)) { + fd_tuner = open(conf->tuner_device, O_RDWR); + if (fd_tuner < 0) { + motion_log(LOG_ERR, 1, "%s: open tuner device %s", + __FUNCTION__, conf->tuner_device); + free(dev); + pthread_mutex_unlock(&vid_mutex); + return -1; + } + } - pthread_mutexattr_init(&dev->attr); - pthread_mutex_init(&dev->mutex, &dev->attr); + pthread_mutexattr_init(&dev->attr); + pthread_mutex_init(&dev->mutex, &dev->attr); - dev->usage_count = 1; - dev->video_device = conf->video_device; - dev->tuner_device = conf->tuner_device; - dev->fd_bktr = fd_bktr; - dev->fd_tuner = fd_tuner; - dev->input = input; - dev->height = height; - dev->width = width; - dev->freq = frequency; - dev->owner = -1; - dev->capture_method = capture_method; - - /* We set brightness, contrast, saturation and hue = 0 so that they only get + dev->usage_count = 1; + dev->video_device = conf->video_device; + dev->tuner_device = conf->tuner_device; + dev->fd_bktr = fd_bktr; + dev->fd_tuner = fd_tuner; + dev->input = input; + dev->height = height; + dev->width = width; + dev->freq = frequency; + dev->owner = -1; + dev->capture_method = capture_method; + + /* We set brightness, contrast, saturation and hue = 0 so that they only get * set if the config is not zero. */ - - dev->brightness = 0; - dev->contrast = 0; - dev->saturation = 0; - dev->hue = 0; - dev->owner = -1; + + dev->brightness = 0; + dev->contrast = 0; + dev->saturation = 0; + dev->hue = 0; + dev->owner = -1; - /* default palette */ - dev->v4l_fmt = VIDEO_PALETTE_YUV420P; - dev->v4l_curbuffer = 0; - dev->v4l_maxbuffer = 1; + /* default palette */ + dev->v4l_fmt = VIDEO_PALETTE_YUV420P; + dev->v4l_curbuffer = 0; + dev->v4l_maxbuffer = 1; - if (!v4l_start(dev, width, height, input, norm, frequency)) { - close(dev->fd_bktr); - pthread_mutexattr_destroy(&dev->attr); + if (!v4l_start(dev, width, height, input, norm, frequency)) { + close(dev->fd_bktr); + pthread_mutexattr_destroy(&dev->attr); pthread_mutex_destroy(&dev->mutex); free(dev); - pthread_mutex_unlock(&vid_mutex); - return -1; - } - - cnt->imgs.type = dev->v4l_fmt; - - switch (cnt->imgs.type) { - case VIDEO_PALETTE_GREY: - cnt->imgs.size = width * height; - cnt->imgs.motionsize = width * height; - break; - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_YUV422: - cnt->imgs.type = VIDEO_PALETTE_YUV420P; - case VIDEO_PALETTE_YUV420P: - motion_log(-1, 0, "%s: VIDEO_PALETTE_YUV420P imgs.type", __FUNCTION__); - cnt->imgs.size = (width * height * 3) / 2; - cnt->imgs.motionsize = width * height; - break; - } + pthread_mutex_unlock(&vid_mutex); + return -1; + } + + cnt->imgs.type = dev->v4l_fmt; + + switch (cnt->imgs.type) { + case VIDEO_PALETTE_GREY: + cnt->imgs.size = width * height; + cnt->imgs.motionsize = width * height; + break; + case VIDEO_PALETTE_RGB24: + case VIDEO_PALETTE_YUV422: + cnt->imgs.type = VIDEO_PALETTE_YUV420P; + case VIDEO_PALETTE_YUV420P: + motion_log(-1, 0, "%s: VIDEO_PALETTE_YUV420P imgs.type", __FUNCTION__); + cnt->imgs.size = (width * height * 3) / 2; + cnt->imgs.motionsize = width * height; + break; + } - /* Insert into linked list */ - dev->next = viddevs; - viddevs = dev; - - pthread_mutex_unlock(&vid_mutex); - } + /* Insert into linked list */ + dev->next = viddevs; + viddevs = dev; + + pthread_mutex_unlock(&vid_mutex); + } #endif /* WITHOUT_V4L */ - /* FIXME needed tuner device ?! */ - return fd_bktr; + /* FIXME needed tuner device ?! */ + return fd_bktr; } @@ -1249,64 +1260,63 @@ int vid_start(struct context *cnt) */ int vid_next(struct context *cnt, unsigned char *map) { - struct config *conf = &cnt->conf; - int ret = -1; + struct config *conf = &cnt->conf; + int ret = -1; - if (conf->netcam_url) { - if (cnt->video_dev == -1) - return NETCAM_GENERAL_ERROR; + if (conf->netcam_url) { + if (cnt->video_dev == -1) + return NETCAM_GENERAL_ERROR; - ret = netcam_next(cnt, map); - return ret; - } + ret = netcam_next(cnt, map); + return ret; + } #ifndef WITHOUT_V4L - struct video_dev *dev; - int width, height; - int dev_bktr = cnt->video_dev; + struct video_dev *dev; + int width, height; + int dev_bktr = cnt->video_dev; - /* NOTE: Since this is a capture, we need to use capture dimensions. */ - width = cnt->rotate_data.cap_width; - height = cnt->rotate_data.cap_height; - - pthread_mutex_lock(&vid_mutex); - dev = viddevs; - while (dev) { - if (dev->fd_bktr == dev_bktr) - break; - dev = dev->next; - } - - pthread_mutex_unlock(&vid_mutex); + /* NOTE: Since this is a capture, we need to use capture dimensions. */ + width = cnt->rotate_data.cap_width; + height = cnt->rotate_data.cap_height; + + pthread_mutex_lock(&vid_mutex); + dev = viddevs; + while (dev) { + if (dev->fd_bktr == dev_bktr) + break; + dev = dev->next; + } + + pthread_mutex_unlock(&vid_mutex); - if (dev == NULL) - return V4L_FATAL_ERROR; - //return -1; + if (dev == NULL) + return V4L_FATAL_ERROR; + //return -1; - if (dev->owner != cnt->threadnr) { - pthread_mutex_lock(&dev->mutex); - dev->owner = cnt->threadnr; - dev->frames = conf->roundrobin_frames; - } + if (dev->owner != cnt->threadnr) { + pthread_mutex_lock(&dev->mutex); + dev->owner = cnt->threadnr; + dev->frames = conf->roundrobin_frames; + } - v4l_set_input(cnt, dev, map, width, height, conf->input, conf->norm, - conf->roundrobin_skip, conf->frequency); - - ret = v4l_next(dev, map, width, height); + v4l_set_input(cnt, dev, map, width, height, conf->input, conf->norm, + conf->roundrobin_skip, conf->frequency); + + ret = v4l_next(dev, map, width, height); - if (--dev->frames <= 0) { - dev->owner = -1; - dev->frames = 0; - pthread_mutex_unlock(&dev->mutex); - } - - if (cnt->rotate_data.degrees > 0) { - /* rotate the image as specified */ - rotate_map(cnt, map); - } - + if (--dev->frames <= 0) { + dev->owner = -1; + dev->frames = 0; + pthread_mutex_unlock(&dev->mutex); + } + + /* rotate the image as specified */ + if (cnt->rotate_data.degrees > 0) + rotate_map(cnt, map); + #endif /*WITHOUT_V4L*/ - return ret; + return ret; } diff --git a/video_freebsd.h b/video_freebsd.h index b548fbb5..1437ebbd 100644 --- a/video_freebsd.h +++ b/video_freebsd.h @@ -1,6 +1,6 @@ -/* video_freebsd.h +/* video_freebsd.h * - * Include file for video_freebsd.c + * Include file for video_freebsd.c * Copyright 2004 by Angel Carpintero (ack@telefonica.net) * This software is distributed under the GNU public license version 2 * See also the file 'COPYING'. @@ -37,30 +37,30 @@ */ /* video4linux error codes */ -#define V4L_GENERAL_ERROR 0x01 /* binary 000001 */ -#define V4L_BTTVLOST_ERROR 0x05 /* binary 000101 */ +#define V4L_GENERAL_ERROR 0x01 /* binary 000001 */ +#define V4L_BTTVLOST_ERROR 0x05 /* binary 000101 */ #define V4L_FATAL_ERROR -1 -#define NORM_DEFAULT 0x00800 // METEOR_FMT_AUTOMODE -#define NORM_PAL 0x00200 // METEOR_FMT_PAL -#define NORM_NTSC 0x00100 // METEOR_FMT_NTSC -#define NORM_SECAM 0x00400 // METEOR_FMT_SECAM -#define NORM_PAL_NC 0x00200 // METEOR_FMT_PAL /* Greyscale howto ?! FIXME */ +#define NORM_DEFAULT 0x00800 /* METEOR_FMT_AUTOMODE */ +#define NORM_PAL 0x00200 /* METEOR_FMT_PAL */ +#define NORM_NTSC 0x00100 /* METEOR_FMT_NTSC */ +#define NORM_SECAM 0x00400 /* METEOR_FMT_SECAM */ +#define NORM_PAL_NC 0x00200 /* METEOR_FMT_PAL */ -#define NORM_DEFAULT_NEW BT848_IFORM_F_AUTO -#define NORM_PAL_NEW BT848_IFORM_F_PALBDGHI -#define NORM_NTSC_NEW BT848_IFORM_F_NTSCM -#define NORM_SECAM_NEW BT848_IFORM_F_SECAM -#define NORM_PAL_NC_NEW BT848_IFORM_F_AUTO /* FIXME */ +#define NORM_DEFAULT_NEW BT848_IFORM_F_AUTO +#define NORM_PAL_NEW BT848_IFORM_F_PALBDGHI +#define NORM_NTSC_NEW BT848_IFORM_F_NTSCM +#define NORM_SECAM_NEW BT848_IFORM_F_SECAM +#define NORM_PAL_NC_NEW BT848_IFORM_F_AUTO /* FIXME */ -#define PAL 0 -#define NTSC 1 -#define SECAM 2 -#define PAL_NC 3 +#define PAL 0 +#define NTSC 1 +#define SECAM 2 +#define PAL_NC 3 -#define PAL_HEIGHT 576 -#define SECAM_HEIGHT 576 -#define NTSC_HEIGHT 480 +#define PAL_HEIGHT 576 +#define SECAM_HEIGHT 576 +#define NTSC_HEIGHT 480 #define BSD_VIDFMT_NONE 0 #define BSD_VIDFMT_YV12 1 @@ -73,50 +73,50 @@ #define BSD_VIDFMT_LAST 8 -#define IN_DEFAULT 0 -#define IN_COMPOSITE 0 -#define IN_TV 1 -#define IN_COMPOSITE2 2 -#define IN_SVIDEO 3 +#define IN_DEFAULT 0 +#define IN_COMPOSITE 0 +#define IN_TV 1 +#define IN_COMPOSITE2 2 +#define IN_SVIDEO 3 -#define CAPTURE_SINGLE 0 -#define CAPTURE_CONTINOUS 1 +#define CAPTURE_SINGLE 0 +#define CAPTURE_CONTINOUS 1 -#define VIDEO_DEVICE "/dev/bktr0" -#define TUNER_DEVICE "/dev/tuner0" +#define VIDEO_DEVICE "/dev/bktr0" +#define TUNER_DEVICE "/dev/tuner0" struct video_dev { - struct video_dev *next; - int usage_count; - int fd_bktr; - int fd_tuner; - const char *video_device; - const char *tuner_device; - unsigned short input; - unsigned short norm; - int width; - int height; - int contrast; - int saturation; - int hue; - int brightness; - int channel; - int channelset; - unsigned long freq; + struct video_dev *next; + int usage_count; + int fd_bktr; + int fd_tuner; + const char *video_device; + const char *tuner_device; + unsigned short input; + unsigned short norm; + int width; + int height; + int contrast; + int saturation; + int hue; + int brightness; + int channel; + int channelset; + unsigned long freq; - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - int owner; - int frames; - - /* Device type specific stuff: */ -#ifndef WITHOUT_V4L - int capture_method; - int v4l_fmt; - unsigned char *v4l_buffers[2]; - int v4l_curbuffer; - int v4l_maxbuffer; - int v4l_bufsize; + pthread_mutex_t mutex; + pthread_mutexattr_t attr; + int owner; + int frames; + + /* Device type specific stuff: */ +#ifndef WITHOUT_V4L + int capture_method; + int v4l_fmt; + unsigned char *v4l_buffers[2]; + int v4l_curbuffer; + int v4l_maxbuffer; + int v4l_bufsize; #endif }; diff --git a/webcam.c b/webcam.c index 42d9e693..ca39f742 100644 --- a/webcam.c +++ b/webcam.c @@ -1,21 +1,21 @@ /* - * webcam.c - * Streaming webcam using jpeg images over a multipart/x-mixed-replace stream - * Copyright (C) 2002 Jeroen Vreeken (pe1rxq@amsat.org) + * webcam.c + * Streaming webcam using jpeg images over a multipart/x-mixed-replace stream + * Copyright (C) 2002 Jeroen Vreeken (pe1rxq@amsat.org) * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "picture.h" @@ -34,57 +34,57 @@ */ int http_bindsock(int port, int local) { - int sl, optval=1; - struct sockaddr_in sin; + int sl, optval = 1; + struct sockaddr_in sin; - if ((sl=socket(PF_INET, SOCK_STREAM, 0))<0) { - motion_log(LOG_ERR, 1, "socket()"); - return -1; - } + if ((sl = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + motion_log(LOG_ERR, 1, "socket()"); + return -1; + } - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family=AF_INET; - sin.sin_port=htons(port); - - if (local) - sin.sin_addr.s_addr=htonl(INADDR_LOOPBACK); - else - sin.sin_addr.s_addr=htonl(INADDR_ANY); + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family=AF_INET; + sin.sin_port=htons(port); + + if (local) + sin.sin_addr.s_addr=htonl(INADDR_LOOPBACK); + else + sin.sin_addr.s_addr=htonl(INADDR_ANY); - setsockopt(sl, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(sl, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - if (bind(sl, (struct sockaddr *)&sin, sizeof(struct sockaddr_in))==-1) { - motion_log(LOG_ERR, 1, "bind()"); - close(sl); - return -1; - } + if (bind(sl, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == -1) { + motion_log(LOG_ERR, 1, "bind()"); + close(sl); + return -1; + } - if (listen(sl, DEF_MAXWEBQUEUE)==-1) { - motion_log(LOG_ERR, 1, "listen()"); - close(sl); - return -1; - } + if (listen(sl, DEF_MAXWEBQUEUE) == -1) { + motion_log(LOG_ERR, 1, "listen()"); + close(sl); + return -1; + } - return sl; + return sl; } static int http_acceptsock(int sl) { - int sc; - unsigned long i; - struct sockaddr_in sin; - socklen_t addrlen=sizeof(struct sockaddr_in); + int sc; + unsigned long i; + struct sockaddr_in sin; + socklen_t addrlen = sizeof(struct sockaddr_in); - if ((sc=accept(sl, (struct sockaddr *)&sin, &addrlen))>=0) { - i=1; - ioctl(sc, FIONBIO, &i); - return sc; - } - - motion_log(LOG_ERR, 1, "accept()"); + if ((sc = accept(sl, (struct sockaddr *)&sin, &addrlen)) >= 0) { + i = 1; + ioctl(sc, FIONBIO, &i); + return sc; + } + + motion_log(LOG_ERR, 1, "accept()"); - return -1; + return -1; } @@ -95,98 +95,98 @@ static int http_acceptsock(int sl) */ static void webcam_flush(struct webcam *list, int *stream_count, int lim) { - int written; /* the number of bytes actually written */ - struct webcam *client; /* pointer to the client being served */ - int workdone = 0; /* flag set any time data is successfully - written */ + int written; /* the number of bytes actually written */ + struct webcam *client; /* pointer to the client being served */ + int workdone = 0; /* flag set any time data is successfully + written */ - client = list->next; + client = list->next; - while (client) { - - /* If data waiting for client, try to send it */ - if (client->tmpbuffer) { - - /* We expect that list->filepos < list->tmpbuffer->size - * should always be true. The check is more for safety, - * in case of trouble is some other part of the code. - * Note that if it is false, the following section will - * clean up. - */ - if (client->filepos < client->tmpbuffer->size) { - - /* Here we are finally ready to write out the - * data. Remember that (because the socket - * has been set non-blocking) we may only - * write out part of the buffer. The var - * 'filepos' contains how much of the buffer - * has already been written. - */ - written=write(client->socket, - client->tmpbuffer->ptr + client->filepos, - client->tmpbuffer->size - client->filepos); - - /* If any data has been written, update the - * data pointer and set the workdone flag - */ - if (written>0) { - client->filepos+=written; - workdone = 1; - } - } else - written = 0; - - /* If we have written the entire buffer to the socket, - * or if there was some error (other than EAGAIN, which - * means the system couldn't take it), this request is - * finished. - */ - if ( (client->filepos >= client->tmpbuffer->size) || - (written < 0 && errno!=EAGAIN)) { - /* If no other clients need this buffer, free it */ - if (--client->tmpbuffer->ref <= 0) { - free(client->tmpbuffer->ptr); - free(client->tmpbuffer); - } - - /* Mark this client's buffer as empty */ - client->tmpbuffer=NULL; - client->nr++; - } - - /* If the client is no longer connected, or the total - * number of frames already sent to this client is - * greater than our configuration limit, disconnect - * the client and free the webcam struct - */ - if ( (written<0 && errno!=EAGAIN) || - (lim && !client->tmpbuffer && client->nr>lim) ) { - void *tmp; + while (client) { + + /* If data waiting for client, try to send it */ + if (client->tmpbuffer) { + + /* We expect that list->filepos < list->tmpbuffer->size + * should always be true. The check is more for safety, + * in case of trouble is some other part of the code. + * Note that if it is false, the following section will + * clean up. + */ + if (client->filepos < client->tmpbuffer->size) { + + /* Here we are finally ready to write out the + * data. Remember that (because the socket + * has been set non-blocking) we may only + * write out part of the buffer. The var + * 'filepos' contains how much of the buffer + * has already been written. + */ + written = write(client->socket, + client->tmpbuffer->ptr + client->filepos, + client->tmpbuffer->size - client->filepos); + + /* If any data has been written, update the + * data pointer and set the workdone flag + */ + if (written > 0) { + client->filepos += written; + workdone = 1; + } + } else { + written = 0; + } + /* If we have written the entire buffer to the socket, + * or if there was some error (other than EAGAIN, which + * means the system couldn't take it), this request is + * finished. + */ + if ((client->filepos >= client->tmpbuffer->size) || + (written < 0 && errno != EAGAIN)) { + /* If no other clients need this buffer, free it */ + if (--client->tmpbuffer->ref <= 0) { + free(client->tmpbuffer->ptr); + free(client->tmpbuffer); + } + + /* Mark this client's buffer as empty */ + client->tmpbuffer = NULL; + client->nr++; + } + + /* If the client is no longer connected, or the total + * number of frames already sent to this client is + * greater than our configuration limit, disconnect + * the client and free the webcam struct + */ + if ((written < 0 && errno != EAGAIN) || + (lim && !client->tmpbuffer && client->nr > lim)) { + void *tmp; - close(client->socket); - - if (client->next) - client->next->prev=client->prev; - - client->prev->next=client->next; - tmp=client; - client=client->prev; - free(tmp); - (*stream_count)--; - } - } /* end if (client->tmpbuffer) */ - - /* Step the the next client in the list. If we get to the - * end of the list, check if anything was written during - * that loop; (if so) reset the 'workdone' flag and go back - * to the beginning - */ - client = client->next; - if (!client && workdone) { - client = list->next; - workdone = 0; - } - } /* end while (client) */ + close(client->socket); + + if (client->next) + client->next->prev = client->prev; + + client->prev->next = client->next; + tmp = client; + client = client->prev; + free(tmp); + (*stream_count)--; + } + } /* end if (client->tmpbuffer) */ + + /* Step the the next client in the list. If we get to the + * end of the list, check if anything was written during + * that loop; (if so) reset the 'workdone' flag and go back + * to the beginning + */ + client = client->next; + if (!client && workdone) { + client = list->next; + workdone = 0; + } + } /* end while (client) */ } /* Routine to create a new "tmpbuffer", which is a common @@ -194,69 +194,69 @@ static void webcam_flush(struct webcam *list, int *stream_count, int lim) */ static struct webcam_buffer *webcam_tmpbuffer(int size) { - struct webcam_buffer *tmpbuffer=mymalloc(sizeof(struct webcam_buffer)); - tmpbuffer->ref=0; - tmpbuffer->ptr=mymalloc(size); - - return tmpbuffer; + struct webcam_buffer *tmpbuffer=mymalloc(sizeof(struct webcam_buffer)); + tmpbuffer->ref = 0; + tmpbuffer->ptr = mymalloc(size); + + return tmpbuffer; } static void webcam_add_client(struct webcam *list, int sc) { - struct webcam *new = mymalloc(sizeof(struct webcam)); - static const char header[] = "HTTP/1.0 200 OK\r\n" - "Server: Motion/"VERSION"\r\n" - "Connection: close\r\n" - "Max-Age: 0\r\n" - "Expires: 0\r\n" - "Cache-Control: no-cache, private\r\n" - "Pragma: no-cache\r\n" - "Content-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n"; + struct webcam *new = mymalloc(sizeof(struct webcam)); + static const char header[] = "HTTP/1.0 200 OK\r\n" + "Server: Motion/"VERSION"\r\n" + "Connection: close\r\n" + "Max-Age: 0\r\n" + "Expires: 0\r\n" + "Cache-Control: no-cache, private\r\n" + "Pragma: no-cache\r\n" + "Content-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n"; - memset(new, 0, sizeof(struct webcam)); - new->socket=sc; - - if ((new->tmpbuffer = webcam_tmpbuffer(sizeof(header))) == NULL) { - motion_log(LOG_ERR, 1, "Error creating tmpbuffer in webcam_add_client"); - } else { - memcpy(new->tmpbuffer->ptr, header, sizeof(header)-1); - new->tmpbuffer->size = sizeof(header)-1; - } - - new->prev=list; - new->next=list->next; - - if (new->next) - new->next->prev=new; - - list->next=new; + memset(new, 0, sizeof(struct webcam)); + new->socket = sc; + + if ((new->tmpbuffer = webcam_tmpbuffer(sizeof(header))) == NULL) { + motion_log(LOG_ERR, 1, "Error creating tmpbuffer in webcam_add_client"); + } else { + memcpy(new->tmpbuffer->ptr, header, sizeof(header)-1); + new->tmpbuffer->size = sizeof(header)-1; + } + + new->prev = list; + new->next = list->next; + + if (new->next) + new->next->prev=new; + + list->next = new; } static void webcam_add_write(struct webcam *list, struct webcam_buffer *tmpbuffer, unsigned int fps) { - struct timeval curtimeval; - unsigned long int curtime; + struct timeval curtimeval; + unsigned long int curtime; - gettimeofday(&curtimeval, NULL); - curtime=curtimeval.tv_usec+1000000L*curtimeval.tv_sec; - - while (list->next) { - list=list->next; - - if (list->tmpbuffer==NULL && ((curtime-list->last) >= 1000000L/fps)) { - list->last=curtime; - list->tmpbuffer=tmpbuffer; - tmpbuffer->ref++; - list->filepos=0; - } - } - - if (tmpbuffer->ref<=0) { - free(tmpbuffer->ptr); - free(tmpbuffer); - } + gettimeofday(&curtimeval, NULL); + curtime = curtimeval.tv_usec + 1000000L * curtimeval.tv_sec; + + while (list->next) { + list = list->next; + + if (list->tmpbuffer == NULL && ((curtime-list->last) >= 1000000L / fps)) { + list->last = curtime; + list->tmpbuffer = tmpbuffer; + tmpbuffer->ref++; + list->filepos = 0; + } + } + + if (tmpbuffer->ref <= 0) { + free(tmpbuffer->ptr); + free(tmpbuffer); + } } @@ -267,13 +267,13 @@ static void webcam_add_write(struct webcam *list, struct webcam_buffer *tmpbuffe */ static int webcam_check_write(struct webcam *list) { - while (list->next) { - list=list->next; - - if (list->tmpbuffer==NULL) - return 1; - } - return 0; + while (list->next) { + list = list->next; + + if (list->tmpbuffer == NULL) + return 1; + } + return 0; } @@ -283,41 +283,41 @@ static int webcam_check_write(struct webcam *list) */ int webcam_init(struct context *cnt) { - cnt->webcam.socket=http_bindsock(cnt->conf.webcam_port, cnt->conf.webcam_localhost); - cnt->webcam.next=NULL; - cnt->webcam.prev=NULL; - return cnt->webcam.socket; + cnt->webcam.socket = http_bindsock(cnt->conf.webcam_port, cnt->conf.webcam_localhost); + cnt->webcam.next = NULL; + cnt->webcam.prev = NULL; + return cnt->webcam.socket; } /* This function is called from the motion_loop when it ends * and motion is terminated or restarted */ void webcam_stop(struct context *cnt) -{ - struct webcam *list; - struct webcam *next = cnt->webcam.next; +{ + struct webcam *list; + struct webcam *next = cnt->webcam.next; - if (cnt->conf.setup_mode) - motion_log(-1, 0, "Closing webcam listen socket"); - - close(cnt->webcam.socket); - cnt->webcam.socket = -1; - - if (cnt->conf.setup_mode) - motion_log(LOG_INFO, 0, "Closing active webcam sockets"); + if (cnt->conf.setup_mode) + motion_log(-1, 0, "Closing webcam listen socket"); + + close(cnt->webcam.socket); + cnt->webcam.socket = -1; + + if (cnt->conf.setup_mode) + motion_log(LOG_INFO, 0, "Closing active webcam sockets"); - while (next) { - list=next; - next=list->next; - - if (list->tmpbuffer) { - free(list->tmpbuffer->ptr); - free(list->tmpbuffer); - } - - close(list->socket); - free(list); - } + while (next) { + list = next; + next = list->next; + + if (list->tmpbuffer) { + free(list->tmpbuffer->ptr); + free(list->tmpbuffer); + } + + close(list->socket); + free(list); + } } /* webcam_put is the starting point of the webcam loop. It is called from @@ -336,101 +336,101 @@ void webcam_stop(struct context *cnt) */ void webcam_put(struct context *cnt, unsigned char *image) { - struct timeval timeout; - struct webcam_buffer *tmpbuffer; - fd_set fdread; - int sl=cnt->webcam.socket; - int sc; - /* the following string has an extra 16 chars at end for length */ - const char jpeghead[] = "--BoundaryString\r\n" - "Content-type: image/jpeg\r\n" - "Content-Length: "; - int headlength = sizeof(jpeghead) - 1; /* don't include terminator */ - char len[20]; /* will be used for sprintf, must be >= 16 */ - - /* timeout struct used to timeout the time we wait for a client - * and we do not wait at all - */ - timeout.tv_sec=0; - timeout.tv_usec=0; - FD_ZERO(&fdread); - FD_SET(cnt->webcam.socket, &fdread); - - /* If we have not reached the max number of allowed clients per - * thread we will check to see if new clients are waiting to connect. - * If this is the case we add the client as a new webcam struct and - * add this to the end of the chain of webcam structs that are linked - * to each other. - */ - if ((cnt->stream_count < DEF_MAXSTREAMS) && - (select(sl+1, &fdread, NULL, NULL, &timeout)>0)) { - sc=http_acceptsock(sl); - webcam_add_client(&cnt->webcam, sc); - cnt->stream_count++; - } - - /* call flush to send any previous partial-sends which are waiting */ - webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit); - - /* Check if any clients have available buffers */ - if (webcam_check_write(&cnt->webcam)) { - /* yes - create a new tmpbuffer for current image. - * Note that this should create a buffer which is *much* larger - * than necessary, but it is difficult to estimate the - * minimum size actually required. - */ - tmpbuffer = webcam_tmpbuffer(cnt->imgs.size); - - /* check if allocation went ok */ - if (tmpbuffer) { - int imgsize; + struct timeval timeout; + struct webcam_buffer *tmpbuffer; + fd_set fdread; + int sl=cnt->webcam.socket; + int sc; + /* the following string has an extra 16 chars at end for length */ + const char jpeghead[] = "--BoundaryString\r\n" + "Content-type: image/jpeg\r\n" + "Content-Length: "; + int headlength = sizeof(jpeghead) - 1; /* don't include terminator */ + char len[20]; /* will be used for sprintf, must be >= 16 */ + + /* timeout struct used to timeout the time we wait for a client + * and we do not wait at all + */ + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&fdread); + FD_SET(cnt->webcam.socket, &fdread); + + /* If we have not reached the max number of allowed clients per + * thread we will check to see if new clients are waiting to connect. + * If this is the case we add the client as a new webcam struct and + * add this to the end of the chain of webcam structs that are linked + * to each other. + */ + if ((cnt->stream_count < DEF_MAXSTREAMS) && + (select(sl+1, &fdread, NULL, NULL, &timeout) > 0)) { + sc = http_acceptsock(sl); + webcam_add_client(&cnt->webcam, sc); + cnt->stream_count++; + } + + /* call flush to send any previous partial-sends which are waiting */ + webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit); + + /* Check if any clients have available buffers */ + if (webcam_check_write(&cnt->webcam)) { + /* yes - create a new tmpbuffer for current image. + * Note that this should create a buffer which is *much* larger + * than necessary, but it is difficult to estimate the + * minimum size actually required. + */ + tmpbuffer = webcam_tmpbuffer(cnt->imgs.size); + + /* check if allocation went ok */ + if (tmpbuffer) { + int imgsize; - /* We need a pointer that points to the picture buffer - * just after the mjpeg header. We create a working pointer wptr - * to be used in the call to put_picture_memory which we can change - * and leave tmpbuffer->ptr intact. - */ - unsigned char *wptr = tmpbuffer->ptr; - - /* For web protocol, our image needs to be preceded - * with a little HTTP, so we put that into the buffer - * first. - */ - memcpy(wptr, jpeghead, headlength); + /* We need a pointer that points to the picture buffer + * just after the mjpeg header. We create a working pointer wptr + * to be used in the call to put_picture_memory which we can change + * and leave tmpbuffer->ptr intact. + */ + unsigned char *wptr = tmpbuffer->ptr; + + /* For web protocol, our image needs to be preceded + * with a little HTTP, so we put that into the buffer + * first. + */ + memcpy(wptr, jpeghead, headlength); - /* update our working pointer to point past header */ - wptr += headlength; + /* update our working pointer to point past header */ + wptr += headlength; - /* create a jpeg image and place into tmpbuffer */ - tmpbuffer->size = put_picture_memory(cnt, wptr, cnt->imgs.size, image, - cnt->conf.webcam_quality); + /* create a jpeg image and place into tmpbuffer */ + tmpbuffer->size = put_picture_memory(cnt, wptr, cnt->imgs.size, image, + cnt->conf.webcam_quality); - /* fill in the image length into the header */ - imgsize = sprintf(len, "%9ld\r\n\r\n", tmpbuffer->size); - memcpy(wptr - imgsize, len, imgsize); - - /* append a CRLF for good measure */ - memcpy(wptr + tmpbuffer->size, "\r\n", 2); - - /* now adjust tmpbuffer->size to reflect the - * header at the beginning and the extra CRLF - * at the end. - */ - tmpbuffer->size += headlength + 2; - - /* and finally put this buffer to all clients with - * no outstanding data from previous frames. - */ - webcam_add_write(&cnt->webcam, tmpbuffer, cnt->conf.webcam_maxrate); - } else { - motion_log(LOG_ERR, 1, "Error creating tmpbuffer"); - } - } - - /* Now we call flush again. This time (assuming some clients were - * ready for the new frame) the new data will be written out. - */ - webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit); - - return; + /* fill in the image length into the header */ + imgsize = sprintf(len, "%9ld\r\n\r\n", tmpbuffer->size); + memcpy(wptr - imgsize, len, imgsize); + + /* append a CRLF for good measure */ + memcpy(wptr + tmpbuffer->size, "\r\n", 2); + + /* now adjust tmpbuffer->size to reflect the + * header at the beginning and the extra CRLF + * at the end. + */ + tmpbuffer->size += headlength + 2; + + /* and finally put this buffer to all clients with + * no outstanding data from previous frames. + */ + webcam_add_write(&cnt->webcam, tmpbuffer, cnt->conf.webcam_maxrate); + } else { + motion_log(LOG_ERR, 1, "Error creating tmpbuffer"); + } + } + + /* Now we call flush again. This time (assuming some clients were + * ready for the new frame) the new data will be written out. + */ + webcam_flush(&cnt->webcam, &cnt->stream_count, cnt->conf.webcam_limit); + + return; } diff --git a/webcam.h b/webcam.h index db0d1d8e..37a5a0b9 100644 --- a/webcam.h +++ b/webcam.h @@ -22,20 +22,20 @@ #define _INCLUDE_WEBCAM_H_ struct webcam_buffer { - unsigned char *ptr; - int ref; - long size; + unsigned char *ptr; + int ref; + long size; }; struct webcam { - int socket; - FILE *fwrite; - struct webcam_buffer *tmpbuffer; - long filepos; - int nr; - unsigned long int last; - struct webcam *prev; - struct webcam *next; + int socket; + FILE *fwrite; + struct webcam_buffer *tmpbuffer; + long filepos; + int nr; + unsigned long int last; + struct webcam *prev; + struct webcam *next; }; int webcam_init(struct context *);