Sorted out monitor streaming and removed old config.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@958 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan 2004-03-15 09:37:21 +00:00
parent eb2363747b
commit 4d6b69a499
11 changed files with 87 additions and 143 deletions

View File

@ -358,7 +358,7 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
}
}
void Event::StreamEvent( int event_id, int maxfps, int rate, int scale )
void Event::StreamEvent( int event_id, int scale, int rate, int maxfps )
{
static char sql[BUFSIZ];
static char eventpath[PATH_MAX];
@ -504,7 +504,7 @@ void Event::StreamEvent( int event_id, int maxfps, int rate, int scale )
#if HAVE_LIBAVCODEC
void Event::StreamMpeg( int event_id, const char *format, int bitrate, int maxfps, int rate, int scale )
void Event::StreamMpeg( int event_id, const char *format, int scale, int rate, int maxfps, int bitrate )
{
static char sql[BUFSIZ];
static char eventpath[PATH_MAX];
@ -639,7 +639,7 @@ void Event::StreamMpeg( int event_id, const char *format, int bitrate, int maxfp
{
last_id = db_id;
last_delta = db_delta;
}
}
if ( mysql_errno( &dbconn ) )
{

View File

@ -91,9 +91,9 @@ public:
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
static void StreamEvent( int event_id, int maxfps=10, int rate=100, int scale=100 );
static void StreamEvent( int event_id, int scale=100, int rate=100, int maxfps=10 );
#if HAVE_LIBAVCODEC
static void StreamMpeg( int event_id, const char *format, int bitrate=100000, int maxfps=10, int rate=100, int scale=100 );
static void StreamMpeg( int event_id, const char *format, int scale=100, int rate=100, int maxfps=10, int bitrate=100000 );
#endif // HAVE_LIBAVCODEC
};

View File

@ -1075,19 +1075,41 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
return( monitor );
}
void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t ttl, int scale )
void Monitor::StreamImages( int scale, int maxfps, time_t ttl )
{
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
fprintf( stdout, "--ZoneMinderFrame\r\n" );
int fps = int(GetFPS());
if ( !fps )
fps = 5;
int min_fps = 1;
int max_fps = maxfps;
int base_fps = int(GetFPS());
int effective_fps = base_fps;
int frame_mod = 1;
// Min frame repeat?
while( effective_fps > max_fps )
{
effective_fps /= 2;
frame_mod *= 2;
}
Debug( 1, ( "BFPS:%d, EFPS:%d, FM:%d", base_fps, effective_fps, frame_mod ));
int last_read_index = image_buffer_count;
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
int img_buffer_size = 0;
int loop_count = (idle/refresh)-1;
time_t stream_start_time;
time( &stream_start_time );
int frame_count = 0;
struct timeval base_time;
struct DeltaTimeval delta_time;
int img_buffer_size = 0;
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image;
while ( true )
{
if ( feof( stdout ) || ferror( stdout ) )
@ -1096,62 +1118,54 @@ void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t tt
}
if ( last_read_index != shared_data->last_write_index )
{
// Send the next frame
last_read_index = shared_data->last_write_index;
int index = shared_data->last_write_index%image_buffer_count;
//Info(( "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ));
Snapshot *snap = &image_buffer[index];
Image *snap_image = snap->image;
if ( scale == 100 )
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) )
{
// Send the next frame
last_read_index = shared_data->last_write_index;
int index = shared_data->last_write_index%image_buffer_count;
//Info(( "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ));
Snapshot *snap = &image_buffer[index];
Image *snap_image = snap->image;
if ( scale != 100 )
{
scaled_image.Assign( *snap_image );
scaled_image.Scale( scale );
snap_image = &scaled_image;
}
if ( !timestamp_on_capture )
{
TimestampImage( snap_image, snap->timestamp->tv_sec );
}
snap_image->EncodeJpeg( img_buffer, &img_buffer_size );
}
else
{
Image scaled_image( *snap_image );
scaled_image.Scale( scale );
fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size );
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
fwrite( img_buffer, img_buffer_size, 1, stdout );
fprintf( stdout, "\r\n\r\n--ZoneMinderFrame\r\n" );
if ( !timestamp_on_capture )
if ( ttl )
{
TimestampImage( &scaled_image, snap->timestamp->tv_sec );
time_t now;
time( &now );
if ( (now - stream_start_time) > ttl )
{
break;
}
}
scaled_image.EncodeJpeg( img_buffer, &img_buffer_size );
}
fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size );
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
fwrite( img_buffer, img_buffer_size, 1, stdout );
fprintf( stdout, "\r\n\r\n--ZoneMinderFrame\r\n" );
}
usleep( refresh*1000 );
for ( int i = 0; shared_data->state == IDLE && i < loop_count; i++ )
{
usleep( refresh*1000 );
}
if ( ttl )
{
time_t now;
time( &now );
if ( (now - stream_start_time) > ttl )
{
break;
}
frame_count++;
}
usleep( ZM_SAMPLE_RATE );
}
}
#if HAVE_LIBAVCODEC
void Monitor::StreamMpeg( const char *format, int bitrate, int maxfps, int scale, int buffer )
void Monitor::StreamMpeg( const char *format, int scale, int maxfps, int bitrate )
{
// Warning, most of these won't work for real-time streaming
const char *mime_type = "video/mpeg";
@ -1196,7 +1210,7 @@ void Monitor::StreamMpeg( const char *format, int bitrate, int maxfps, int scale
frame_mod *= 2;
}
Info(( "BFPS:%d, EFPS:%d, FM:%d", base_fps, effective_fps, frame_mod ));
Debug( 1, ( "BFPS:%d, EFPS:%d, FM:%d", base_fps, effective_fps, frame_mod ));
VideoStream vid_stream( "pipe:", format, bitrate, fps, camera->Colours(), (width*scale)/ZM_SCALE_SCALE, (height*scale)/ZM_SCALE_SCALE );
@ -1226,25 +1240,18 @@ void Monitor::StreamMpeg( const char *format, int bitrate, int maxfps, int scale
Snapshot *snap = &image_buffer[index];
Image *snap_image = snap->image;
if ( scale == 100 )
{
if ( !timestamp_on_capture )
{
TimestampImage( snap_image, snap->timestamp->tv_sec );
}
}
else
if ( scale != 100 )
{
scaled_image.Assign( *snap_image );
scaled_image.Scale( scale );
if ( !timestamp_on_capture )
{
TimestampImage( &scaled_image, snap->timestamp->tv_sec );
}
snap_image = &scaled_image;
}
if ( !timestamp_on_capture )
{
TimestampImage( snap_image, snap->timestamp->tv_sec );
}
if ( !frame_count )
{

View File

@ -287,9 +287,9 @@ public:
static int Load( int device, Monitor **&monitors, Purpose purpose=QUERY );
static int Load( const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose=QUERY );
static Monitor *Load( int id, bool load_zones=false, Purpose purpose=QUERY );
void StreamImages( unsigned long idle=5000, unsigned long refresh=50, time_t ttl=0, int scale=100 );
void StreamImages( int scale=100, int maxfps=10, time_t ttl=0 );
#if HAVE_LIBAVCODEC
void StreamMpeg( const char *format, int bitrate=100000, int maxfps=10, int scale=100, int buffer=0 );
void StreamMpeg( const char *format, int scale=100, int maxfps=10, int bitrate=100000 );
#endif // HAVE_LIBAVCODEC
};

View File

@ -27,14 +27,11 @@ int main( int argc, const char *argv[] )
char format[32] = "";
int id = 1;
int event = 0;
unsigned int bitrate = 100000;
unsigned int maxfps = 10;
unsigned int rate = 100;
unsigned int scale = 100;
unsigned int buffer = 0;
unsigned int rate = 100;
unsigned int maxfps = 10;
unsigned int bitrate = 100000;
unsigned int ttl = 0;
unsigned long idle = 5000;
unsigned long refresh = 50;
zm_dbg_name = "zms";
@ -77,22 +74,16 @@ int main( int argc, const char *argv[] )
event = strtoull( value, (char **)NULL, 10 );
else if ( !strcmp( name, "format" ) )
strncpy( format, value, sizeof(format) );
else if ( !strcmp( name, "bitrate" ) )
bitrate = atoi( value );
else if ( !strcmp( name, "maxfps" ) )
maxfps = atoi( value );
else if ( !strcmp( name, "rate" ) )
rate = atoi( value );
else if ( !strcmp( name, "scale" ) )
scale = atoi( value );
else if ( !strcmp( name, "buffer" ) )
buffer = atol( value );
else if ( !strcmp( name, "rate" ) )
rate = atoi( value );
else if ( !strcmp( name, "maxfps" ) )
maxfps = atoi( value );
else if ( !strcmp( name, "bitrate" ) )
bitrate = atoi( value );
else if ( !strcmp( name, "ttl" ) )
ttl = atoi(value);
else if ( !strcmp( name, "refresh" ) )
refresh = atol( value );
else if ( !strcmp( name, "idle" ) )
idle = atol( value );
}
}
@ -127,12 +118,12 @@ int main( int argc, const char *argv[] )
{
if ( mode == ZMS_JPEG )
{
monitor->StreamImages( idle, refresh, ttl, scale );
monitor->StreamImages( scale, maxfps, ttl );
}
else
{
#if HAVE_LIBAVCODEC
monitor->StreamMpeg( format, bitrate, maxfps, scale, buffer );
monitor->StreamMpeg( format, scale, maxfps, bitrate );
#else // HAVE_LIBAVCODEC
Error(( "MPEG streaming of '%s' attempted while disabled", query ));
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );
@ -145,12 +136,12 @@ int main( int argc, const char *argv[] )
{
if ( mode == ZMS_JPEG )
{
Event::StreamEvent( event, maxfps, rate, scale );
Event::StreamEvent( event, scale, rate, maxfps );
}
else
{
#if HAVE_LIBAVCODEC
Event::StreamMpeg( event, format, bitrate, maxfps, rate, scale );
Event::StreamMpeg( event, format, scale, rate, maxfps, bitrate );
#else // HAVE_LIBAVCODEC
Error(( "MPEG streaming of '%s' attempted while disabled", query ));
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );

View File

@ -59,8 +59,6 @@ switch ( $bandwidth )
define( "REFRESH_EVENTS", ZM_WEB_H_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "VIDEO_BITRATE", ZM_WEB_H_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "VIDEO_MAXFPS", ZM_WEB_H_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "STREAM_IDLE_DELAY", ZM_WEB_H_STREAM_IDLE_DELAY ); // How long (in milliseconds) between streamed frames in the watch window
define( "STREAM_FRAME_DELAY", ZM_WEB_H_STREAM_FRAME_DELAY ); // How long (in milliseconds) to wait before looking for the next streamed frame
define( "IMAGE_SCALING", ZM_WEB_H_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
break;
}
@ -73,8 +71,6 @@ switch ( $bandwidth )
define( "REFRESH_EVENTS", ZM_WEB_M_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "VIDEO_BITRATE", ZM_WEB_M_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "VIDEO_MAXFPS", ZM_WEB_M_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "STREAM_IDLE_DELAY", ZM_WEB_M_STREAM_IDLE_DELAY ); // How long (in milliseconds) between streamed frames in the watch window
define( "STREAM_FRAME_DELAY", ZM_WEB_M_STREAM_FRAME_DELAY ); // How long (in milliseconds) to wait before looking for the next streamed frame
define( "IMAGE_SCALING", ZM_WEB_M_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
break;
}
@ -87,8 +83,6 @@ switch ( $bandwidth )
define( "REFRESH_EVENTS", ZM_WEB_L_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "VIDEO_BITRATE", ZM_WEB_L_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "VIDEO_MAXFPS", ZM_WEB_L_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "STREAM_IDLE_DELAY", ZM_WEB_L_STREAM_IDLE_DELAY ); // How long (in milliseconds) between streamed frames in the watch window
define( "STREAM_FRAME_DELAY", ZM_WEB_L_STREAM_FRAME_DELAY ); // How long (in milliseconds) to wait before looking for the next streamed frame
define( "IMAGE_SCALING", ZM_WEB_L_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
break;
}

View File

@ -111,7 +111,7 @@ window.setTimeout( "window.location.replace( '<?= "$PHP_SELF?view=cycle&mid=$nex
<?php
if ( $mode == "stream" )
{
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&idle=".STREAM_IDLE_DELAY."&refresh=".STREAM_FRAME_DELAY."&ttl=".REFRESH_CYCLE."&scale=".$scale;
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&scale=".$scale."&maxfps=".VIDEO_MAXFPS."&ttl=".REFRESH_CYCLE;
if ( canStreamNative() )
{
?>

View File

@ -265,7 +265,7 @@ if ( $mode == "stream" )
<?php
if ( ZM_VIDEO_STREAM_METHOD == 'mpeg' && ZM_VIDEO_REPLAY_FORMAT )
{
$stream_src = ZM_PATH_ZMS."?mode=mpeg&event=$eid&rate=$rate&scale=$scale&bitrate=".VIDEO_BITRATE."&maxfps=".VIDEO_MAXFPS."&format=".ZM_VIDEO_REPLAY_FORMAT;
$stream_src = ZM_PATH_ZMS."?mode=mpeg&event=$eid&scale=$scale&rate=$rate&bitrate=".VIDEO_BITRATE."&maxfps=".VIDEO_MAXFPS."&format=".ZM_VIDEO_REPLAY_FORMAT;
if ( isWindows() )
{
if ( isInternetExplorer() )
@ -312,7 +312,7 @@ AutoStart=true>
}
else
{
$stream_src = ZM_PATH_ZMS."?mode=jpeg&event=$eid&rate=$rate&scale=$scale&maxfps=".VIDEO_MAXFPS;
$stream_src = ZM_PATH_ZMS."?mode=jpeg&event=$eid&scale=$scale&rate=$rate&maxfps=".VIDEO_MAXFPS;
if ( canStreamNative() )
{
?>

View File

@ -151,7 +151,7 @@ AutoStart=true>
}
else
{
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&idle=".STREAM_IDLE_DELAY."&refresh=".STREAM_FRAME_DELAY."&scale=$scale";
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&scale=$scale&maxfps=".VIDEO_MAXFPS;
if ( canStreamNative() )
{
?>

View File

@ -148,7 +148,7 @@ AutoStart=true>
}
else
{
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&idle=".STREAM_IDLE_DELAY."&refresh=".STREAM_FRAME_DELAY."&scale=$scale";
$stream_src = ZM_PATH_ZMS."?mode=jpeg&monitor=".$monitor['Id']."&scale=$scale&maxfps=".VIDEO_MAXFPS;
if ( canStreamNative() )
{
?>

View File

@ -993,22 +993,6 @@ my @options =
type => $types{integer},
category => 'highband',
},
{
name => "ZM_WEB_H_STREAM_IDLE_DELAY",
default => "250",
description => "How long (in milliseconds) between streamed frames in the watch window",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when the monitor is idle, ie. not in alarm state. It makes little sense to set this too small as if it results in frames being sent much faster than they are being captured you will just get the same ones over and over. It should be set to be less or equal to the capture rate of the cameras you are using which will normally be between 2 and 25 Frames Per Second which maps to values between 500 and 40 being used here though your bandwidth may well limit how much can actually be sent. Note also that this is the update rate when no alarms are being generated, if an alarm situation occurs then the rate speeds up as per the next option so this can be set to a longer delay without you missing anything.",
type => $types{integer},
category => 'highband',
},
{
name => "ZM_WEB_H_STREAM_FRAME_DELAY",
default => "50",
description => "How long (in milliseconds) to wait before looking for the next streamed frame",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when an alarm is being generated. It makes little sense to set this too small as if it results in frames being sent much faster than they are being captured you will just get the same ones over and over. It should be set to roughly match the capture rate of the cameras you are using which will normally be between 2 and 25 Frames Per Second which maps to values between 500 and 40 being used here though your bandwidth may well limit how much can actually be sent.",
type => $types{integer},
category => 'highband',
},
{
name => "ZM_WEB_H_IMAGE_SCALING",
default => "1",
@ -1075,22 +1059,6 @@ my @options =
type => $types{integer},
category => 'medband',
},
{
name => "ZM_WEB_M_STREAM_IDLE_DELAY",
default => "2500",
description => "How long (in milliseconds) between streamed frames in the watch window",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when the monitor is idle, ie. not in alarm state. It makes little sense to set this too small as if it exceeds the available bandwidth and results in frames being sent much faster than they are able to be displayed. In medium bandwidth mode it should be set to be rather less than the capture rate of the cameras you are using. Note also that this is the update rate when no alarms are being generated, if an alarm situation occurs then the rate speeds up as per the next option so this can be set to a longer delay without you missing anything.",
type => $types{integer},
category => 'medband',
},
{
name => "ZM_WEB_M_STREAM_FRAME_DELAY",
default => "100",
description => "How long (in milliseconds) to wait before looking for the next streamed frame",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when an alarm is being generated. It makes little sense to set this too small as if it exceeds the available bandwidth and results in frames being sent much faster than they are able to be displayed though as should be only for a short period it may be possible to catch up. In medium bandwidth mode it should be set to maybe half the capture rate of the cameras you are using.",
type => $types{integer},
category => 'medband',
},
{
name => "ZM_WEB_M_IMAGE_SCALING",
default => "4",
@ -1157,22 +1125,6 @@ my @options =
type => $types{integer},
category => 'lowband',
},
{
name => "ZM_WEB_L_STREAM_IDLE_DELAY",
default => "10000",
description => "How long (in milliseconds) between streamed frames in the watch window",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when the monitor is idle, ie. not in alarm state. It makes little sense to set this too small as if it exceeds the available bandwidth and results in frames being sent much faster than they are able to be displayed. In low bandwidth mode it should be set to be far less than the capture rate of the cameras you are using. Note also that this is the update rate when no alarms are being generated, if an alarm situation occurs then the rate speeds up as per the next option so this can be set to a longer delay without you missing anything.",
type => $types{integer},
category => 'lowband',
},
{
name => "ZM_WEB_L_STREAM_FRAME_DELAY",
default => "250",
description => "How long (in milliseconds) to wait before looking for the next streamed frame",
help => "The top frame of the monitor window when monitoring a live feed in streaming mode contains a continuous stream of images. This option controls how often a new frame is sent to the browser when an alarm is being generated. It makes little sense to set this too small as if it exceeds the available bandwidth and results in frames being sent much faster than they are able to be displayed though as should be only for a short period it may be possible to catch up. In low bandwidth mode it should be set to maybe a quarter the capture rate of the cameras you are using.",
type => $types{integer},
category => 'lowband',
},
{
name => "ZM_WEB_L_IMAGE_SCALING",
default => "4",