mirror of
https://github.com/Motion-Project/motion.git
synced 2026-05-19 12:05:54 -04:00
Apply code standard
This commit is contained in:
@@ -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.
|
||||
|
||||
220
conf.h
220
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;
|
||||
|
||||
|
||||
|
||||
358
mmx.h
358
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 */
|
||||
|
||||
679
netcam_jpeg.c
679
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 <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 *,
|
||||
|
||||
68
track.h
68
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 */
|
||||
|
||||
1668
video_freebsd.c
1668
video_freebsd.c
File diff suppressed because it is too large
Load Diff
120
video_freebsd.h
120
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
|
||||
};
|
||||
|
||||
|
||||
638
webcam.c
638
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;
|
||||
}
|
||||
|
||||
22
webcam.h
22
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 *);
|
||||
|
||||
Reference in New Issue
Block a user