Added maximum fps and timed option to video streaming.
git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@942 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
parent
b9dbe6f381
commit
e6ef3bbcd7
|
@ -404,7 +404,6 @@ void Event::StreamEvent( int event_id, int rate, int scale )
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
|
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
|
||||||
fprintf( stdout, "--ZoneMinderFrame\n" );
|
|
||||||
|
|
||||||
//int n_frames = mysql_num_rows( result );
|
//int n_frames = mysql_num_rows( result );
|
||||||
//Info(( "Got %d frames, at rate %d, scale %d", n_frames, rate, scale ));
|
//Info(( "Got %d frames, at rate %d, scale %d", n_frames, rate, scale ));
|
||||||
|
@ -442,7 +441,6 @@ void Event::StreamEvent( int event_id, int rate, int scale )
|
||||||
static char filepath[PATH_MAX];
|
static char filepath[PATH_MAX];
|
||||||
sprintf( filepath, "%s/%03d-capture.jpg", eventpath, atoi(dbrow[0]) );
|
sprintf( filepath, "%s/%03d-capture.jpg", eventpath, atoi(dbrow[0]) );
|
||||||
|
|
||||||
fprintf( stdout, "Content-type: image/jpeg\n\n" );
|
|
||||||
if ( scale == 100 )
|
if ( scale == 100 )
|
||||||
{
|
{
|
||||||
if ( (fdj = fopen( filepath, "r" )) )
|
if ( (fdj = fopen( filepath, "r" )) )
|
||||||
|
@ -468,7 +466,9 @@ void Event::StreamEvent( int event_id, int rate, int scale )
|
||||||
|
|
||||||
write( fileno(stdout), buffer, n_bytes );
|
write( fileno(stdout), buffer, n_bytes );
|
||||||
}
|
}
|
||||||
fprintf( stdout, "\n--ZoneMinderFrame\n" );
|
fprintf( stdout, "\r\n--ZoneMinderFrame\r\n" );
|
||||||
|
fprintf( stdout, "Content-length: %d\r\n", n_bytes );
|
||||||
|
fprintf( stdout, "Content-type: image/jpeg\r\n\r\n" );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
}
|
}
|
||||||
if ( mysql_errno( &dbconn ) )
|
if ( mysql_errno( &dbconn ) )
|
||||||
|
@ -482,12 +482,13 @@ void Event::StreamEvent( int event_id, int rate, int scale )
|
||||||
|
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
|
|
||||||
void Event::StreamMpeg( int event_id, const char *format, int bitrate, int rate, int scale )
|
void Event::StreamMpeg( int event_id, const char *format, int bitrate, int maxfps, int rate, int scale )
|
||||||
{
|
{
|
||||||
static char sql[BUFSIZ];
|
static char sql[BUFSIZ];
|
||||||
static char eventpath[PATH_MAX];
|
static char eventpath[PATH_MAX];
|
||||||
|
|
||||||
//sprintf( sql, "select M.Id, M.Name,max(F.Delta)-min(F.Delta) as Duration, count(F.Id) as Frames from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on F.EventId = E.Id where E.Id = %d group by F.EventId", event_id );
|
bool timed_frames = (bool)config.Item( ZM_WEB_VIDEO_TIMED_FRAMES );
|
||||||
|
|
||||||
sprintf( sql, "select M.Id, M.Name, E.Length, E.Frames from Events as E inner join Monitors as M on E.MonitorId = M.Id where E.Id = %d", event_id );
|
sprintf( sql, "select M.Id, M.Name, E.Length, E.Frames from Events as E inner join Monitors as M on E.MonitorId = M.Id where E.Id = %d", event_id );
|
||||||
if ( mysql_query( &dbconn, sql ) )
|
if ( mysql_query( &dbconn, sql ) )
|
||||||
{
|
{
|
||||||
|
@ -514,7 +515,7 @@ void Event::StreamMpeg( int event_id, const char *format, int bitrate, int rate,
|
||||||
int frames = atoi(dbrow[3]);
|
int frames = atoi(dbrow[3]);
|
||||||
|
|
||||||
int min_fps = 1;
|
int min_fps = 1;
|
||||||
int max_fps = 30;
|
int max_fps = maxfps;
|
||||||
int base_fps = frames/duration;
|
int base_fps = frames/duration;
|
||||||
int effective_fps = (base_fps*rate)/ZM_RATE_SCALE;
|
int effective_fps = (base_fps*rate)/ZM_RATE_SCALE;
|
||||||
|
|
||||||
|
@ -582,7 +583,7 @@ void Event::StreamMpeg( int event_id, const char *format, int bitrate, int rate,
|
||||||
delta_ms = (unsigned int)((last_delta+temp_delta)*1000);
|
delta_ms = (unsigned int)((last_delta+temp_delta)*1000);
|
||||||
if ( rate != ZM_RATE_SCALE )
|
if ( rate != ZM_RATE_SCALE )
|
||||||
delta_ms = (delta_ms*ZM_RATE_SCALE)/rate;
|
delta_ms = (delta_ms*ZM_RATE_SCALE)/rate;
|
||||||
double pts = vid_stream->EncodeFrame( image.Buffer(), image.Size(), true, delta_ms );
|
double pts = vid_stream->EncodeFrame( image.Buffer(), image.Size(), timed_frames, delta_ms );
|
||||||
|
|
||||||
//Info(( "I:%d, DI:%d, LI:%d, DD:%lf, LD:%lf, TD:%lf, DM:%d, PTS:%lf", id, db_id, last_id, db_delta, last_delta, temp_delta, delta_ms, pts ));
|
//Info(( "I:%d, DI:%d, LI:%d, DD:%lf, LD:%lf, TD:%lf, DM:%d, PTS:%lf", id, db_id, last_id, db_delta, last_delta, temp_delta, delta_ms, pts ));
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public:
|
||||||
|
|
||||||
static void StreamEvent( int event_id, int rate=100, int scale=100 );
|
static void StreamEvent( int event_id, int rate=100, int scale=100 );
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
static void StreamMpeg( int event_id, const char *format, int bitrate=100000, int rate=100, int scale=100 );
|
static void StreamMpeg( int event_id, const char *format, int bitrate=100000, int maxfps=10, int rate=100, int scale=100 );
|
||||||
#endif // HAVE_LIBAVCODEC
|
#endif // HAVE_LIBAVCODEC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1078,7 +1078,6 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
||||||
void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t ttl, int scale )
|
void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t ttl, int scale )
|
||||||
{
|
{
|
||||||
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
|
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
|
||||||
fprintf( stdout, "--ZoneMinderFrame\n" );
|
|
||||||
|
|
||||||
int last_read_index = image_buffer_count;
|
int last_read_index = image_buffer_count;
|
||||||
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
|
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
|
||||||
|
@ -1126,9 +1125,10 @@ void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t tt
|
||||||
scaled_image.EncodeJpeg( img_buffer, &img_buffer_size );
|
scaled_image.EncodeJpeg( img_buffer, &img_buffer_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( stdout, "Content-type: image/jpeg\n\n" );
|
fprintf( stdout, "\r\n--ZoneMinderFrame\r\n" );
|
||||||
|
fprintf( stdout, "Content-type: image/jpeg\r\n" );
|
||||||
|
fprintf( stdout, "Content-length: %d\r\n\r\n", img_buffer_size );
|
||||||
fwrite( img_buffer, img_buffer_size, 1, stdout );
|
fwrite( img_buffer, img_buffer_size, 1, stdout );
|
||||||
fprintf( stdout, "\n--ZoneMinderFrame\n" );
|
|
||||||
}
|
}
|
||||||
usleep( refresh*1000 );
|
usleep( refresh*1000 );
|
||||||
for ( int i = 0; shared_data->state == IDLE && i < loop_count; i++ )
|
for ( int i = 0; shared_data->state == IDLE && i < loop_count; i++ )
|
||||||
|
@ -1150,14 +1150,31 @@ void Monitor::StreamImages( unsigned long idle, unsigned long refresh, time_t tt
|
||||||
|
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
|
|
||||||
void Monitor::StreamMpeg( const char *format, int bitrate, int scale, int buffer )
|
void Monitor::StreamMpeg( const char *format, int bitrate, int maxfps, int scale, int buffer )
|
||||||
{
|
{
|
||||||
fprintf( stdout, "Content-type: video/x-ms-asf\r\n\r\n");
|
fprintf( stdout, "Content-type: video/x-ms-asf\r\n\r\n");
|
||||||
|
|
||||||
|
bool timed_frames = (bool)config.Item( ZM_WEB_VIDEO_TIMED_FRAMES );
|
||||||
|
|
||||||
int fps = int(GetFPS());
|
int fps = int(GetFPS());
|
||||||
if ( !fps )
|
if ( !fps )
|
||||||
fps = 5;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info(( "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 );
|
VideoStream vid_stream( "pipe:", format, bitrate, fps, camera->Colours(), (width*scale)/ZM_SCALE_SCALE, (height*scale)/ZM_SCALE_SCALE );
|
||||||
|
|
||||||
int last_read_index = image_buffer_count;
|
int last_read_index = image_buffer_count;
|
||||||
|
@ -1165,60 +1182,10 @@ void Monitor::StreamMpeg( const char *format, int bitrate, int scale, int buffer
|
||||||
time_t stream_start_time;
|
time_t stream_start_time;
|
||||||
time( &stream_start_time );
|
time( &stream_start_time );
|
||||||
|
|
||||||
Image scaled_image;
|
|
||||||
|
|
||||||
// Do any catching up
|
|
||||||
if ( buffer )
|
|
||||||
{
|
|
||||||
int index = shared_data->last_write_index;
|
|
||||||
int offset = buffer*fps;
|
|
||||||
if ( offset > image_buffer_count )
|
|
||||||
{
|
|
||||||
last_read_index = (index+1)%image_buffer_count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last_read_index = (index-offset+image_buffer_count)%image_buffer_count;
|
|
||||||
}
|
|
||||||
Info(( "LWI:%d", shared_data->last_write_index ));
|
|
||||||
Info(( "LRI:%d", last_read_index ));
|
|
||||||
|
|
||||||
while ( last_read_index != shared_data->last_write_index )
|
|
||||||
{
|
|
||||||
Info(( "LRI+:%d", last_read_index ));
|
|
||||||
|
|
||||||
Snapshot *snap = &image_buffer[last_read_index];
|
|
||||||
Image *snap_image = snap->image;
|
|
||||||
|
|
||||||
if ( scale == 100 )
|
|
||||||
{
|
|
||||||
if ( !timestamp_on_capture )
|
|
||||||
{
|
|
||||||
TimestampImage( snap_image, snap->timestamp->tv_sec );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scaled_image.Assign( *snap_image );
|
|
||||||
|
|
||||||
scaled_image.Scale( scale );
|
|
||||||
|
|
||||||
if ( !timestamp_on_capture )
|
|
||||||
{
|
|
||||||
TimestampImage( &scaled_image, snap->timestamp->tv_sec );
|
|
||||||
}
|
|
||||||
snap_image = &scaled_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
double pts = vid_stream.EncodeFrame( snap_image->Buffer(), snap_image->Size() );
|
|
||||||
|
|
||||||
last_read_index = (last_read_index+1)%image_buffer_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int frame_count = 0;
|
int frame_count = 0;
|
||||||
struct timeval base_time;
|
struct timeval base_time;
|
||||||
struct DeltaTimeval delta_time;
|
struct DeltaTimeval delta_time;
|
||||||
|
Image scaled_image;
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
if ( feof( stdout ) || ferror( stdout ) )
|
if ( feof( stdout ) || ferror( stdout ) )
|
||||||
|
@ -1227,43 +1194,46 @@ void Monitor::StreamMpeg( const char *format, int bitrate, int scale, int buffer
|
||||||
}
|
}
|
||||||
if ( last_read_index != shared_data->last_write_index )
|
if ( last_read_index != shared_data->last_write_index )
|
||||||
{
|
{
|
||||||
// Send the next frame
|
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) )
|
||||||
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 ( !timestamp_on_capture )
|
// 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 )
|
||||||
{
|
{
|
||||||
TimestampImage( snap_image, snap->timestamp->tv_sec );
|
if ( !timestamp_on_capture )
|
||||||
|
{
|
||||||
|
TimestampImage( snap_image, snap->timestamp->tv_sec );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
scaled_image.Assign( *snap_image );
|
|
||||||
|
|
||||||
scaled_image.Scale( scale );
|
|
||||||
|
|
||||||
if ( !timestamp_on_capture )
|
|
||||||
{
|
{
|
||||||
TimestampImage( &scaled_image, snap->timestamp->tv_sec );
|
scaled_image.Assign( *snap_image );
|
||||||
}
|
|
||||||
snap_image = &scaled_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !frame_count )
|
scaled_image.Scale( scale );
|
||||||
{
|
|
||||||
base_time = *(snap->timestamp);
|
if ( !timestamp_on_capture )
|
||||||
|
{
|
||||||
|
TimestampImage( &scaled_image, snap->timestamp->tv_sec );
|
||||||
|
}
|
||||||
|
snap_image = &scaled_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !frame_count )
|
||||||
|
{
|
||||||
|
base_time = *(snap->timestamp);
|
||||||
|
}
|
||||||
|
DELTA_TIMEVAL( delta_time, *(snap->timestamp), base_time, DT_PREC_3 );
|
||||||
|
double pts = vid_stream.EncodeFrame( snap_image->Buffer(), snap_image->Size(), timed_frames, delta_time.delta );
|
||||||
|
//Info(( "DTD:%d, PTS:%lf", delta_time.delta, pts ));
|
||||||
}
|
}
|
||||||
DELTA_TIMEVAL( delta_time, *(snap->timestamp), base_time, DT_PREC_3 );
|
frame_count++;
|
||||||
double pts = vid_stream.EncodeFrame( snap_image->Buffer(), snap_image->Size(), true, delta_time.delta );
|
|
||||||
//Info(( "DTD:%d, PTS:%lf", delta_time.delta, pts ));
|
|
||||||
}
|
}
|
||||||
frame_count++;
|
usleep( ZM_SAMPLE_RATE );
|
||||||
usleep( 10000 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // HAVE_LIBAVCODEC
|
#endif // HAVE_LIBAVCODEC
|
||||||
|
|
|
@ -289,7 +289,7 @@ public:
|
||||||
static Monitor *Load( int id, bool load_zones=false, 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( unsigned long idle=5000, unsigned long refresh=50, time_t ttl=0, int scale=100 );
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
void StreamMpeg( const char *format, int bitrate=100000, int scale=100, int buffer=0 );
|
void StreamMpeg( const char *format, int bitrate=100000, int maxfps=10, int scale=100, int buffer=0 );
|
||||||
#endif // HAVE_LIBAVCODEC
|
#endif // HAVE_LIBAVCODEC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ int main(void )
|
||||||
int id = 1;
|
int id = 1;
|
||||||
int event = 0;
|
int event = 0;
|
||||||
unsigned int bitrate = 100000;
|
unsigned int bitrate = 100000;
|
||||||
|
unsigned int maxfps = 100000;
|
||||||
unsigned int rate = 100;
|
unsigned int rate = 100;
|
||||||
unsigned int scale = 100;
|
unsigned int scale = 100;
|
||||||
unsigned int buffer = 0;
|
unsigned int buffer = 0;
|
||||||
|
@ -69,6 +70,8 @@ int main(void )
|
||||||
strncpy( format, value, sizeof(format) );
|
strncpy( format, value, sizeof(format) );
|
||||||
else if ( !strcmp( name, "bitrate" ) )
|
else if ( !strcmp( name, "bitrate" ) )
|
||||||
bitrate = atoi( value );
|
bitrate = atoi( value );
|
||||||
|
else if ( !strcmp( name, "maxfps" ) )
|
||||||
|
maxfps = atoi( value );
|
||||||
else if ( !strcmp( name, "rate" ) )
|
else if ( !strcmp( name, "rate" ) )
|
||||||
rate = atoi( value );
|
rate = atoi( value );
|
||||||
else if ( !strcmp( name, "scale" ) )
|
else if ( !strcmp( name, "scale" ) )
|
||||||
|
@ -112,7 +115,7 @@ int main(void )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
monitor->StreamMpeg( format, bitrate, scale, buffer );
|
monitor->StreamMpeg( format, bitrate, maxfps, scale, buffer );
|
||||||
#else // HAVE_LIBAVCODEC
|
#else // HAVE_LIBAVCODEC
|
||||||
Error(( "MPEG streaming of '%s' attempted while disabled", query ));
|
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" );
|
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );
|
||||||
|
@ -130,7 +133,7 @@ int main(void )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if HAVE_LIBAVCODEC
|
#if HAVE_LIBAVCODEC
|
||||||
Event::StreamMpeg( event, format, bitrate, rate, scale );
|
Event::StreamMpeg( event, format, bitrate, maxfps, rate, scale );
|
||||||
#else // HAVE_LIBAVCODEC
|
#else // HAVE_LIBAVCODEC
|
||||||
Error(( "MPEG streaming of '%s' attempted while disabled", query ));
|
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" );
|
fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" );
|
||||||
|
|
|
@ -57,7 +57,8 @@ switch ( $bandwidth )
|
||||||
define( "REFRESH_IMAGE", ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
define( "REFRESH_IMAGE", ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||||
define( "REFRESH_STATUS", ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
define( "REFRESH_STATUS", ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||||
define( "REFRESH_EVENTS", ZM_WEB_H_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
|
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 generated video should be
|
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_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( "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
|
define( "IMAGE_SCALING", ZM_WEB_H_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
|
||||||
|
@ -70,7 +71,8 @@ switch ( $bandwidth )
|
||||||
define( "REFRESH_IMAGE", ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
define( "REFRESH_IMAGE", ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||||
define( "REFRESH_STATUS", ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
define( "REFRESH_STATUS", ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||||
define( "REFRESH_EVENTS", ZM_WEB_M_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
|
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 generated video should be
|
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_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( "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
|
define( "IMAGE_SCALING", ZM_WEB_M_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
|
||||||
|
@ -83,7 +85,8 @@ switch ( $bandwidth )
|
||||||
define( "REFRESH_IMAGE", ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
define( "REFRESH_IMAGE", ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||||
define( "REFRESH_STATUS", ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
define( "REFRESH_STATUS", ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||||
define( "REFRESH_EVENTS", ZM_WEB_L_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
|
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 generated video should be
|
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_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( "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
|
define( "IMAGE_SCALING", ZM_WEB_L_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
|
||||||
|
|
|
@ -265,7 +265,7 @@ if ( $mode == "stream" )
|
||||||
<?php
|
<?php
|
||||||
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
||||||
{
|
{
|
||||||
$stream_src = ZM_PATH_ZMS."?mode=mpeg&event=$eid&rate=$rate&scale=$scale&bitrate=".VIDEO_BITRATE;
|
$stream_src = ZM_PATH_ZMS."?mode=mpeg&event=$eid&rate=$rate&scale=$scale&bitrate=".VIDEO_BITRATE."&maxfps=".VIDEO_MAXFPS
|
||||||
if ( isWindows() )
|
if ( isWindows() )
|
||||||
{
|
{
|
||||||
if ( isInternetExplorer() )
|
if ( isInternetExplorer() )
|
||||||
|
|
|
@ -104,7 +104,7 @@ if ( $mode == "stream" )
|
||||||
{
|
{
|
||||||
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
||||||
{
|
{
|
||||||
$stream_src = ZM_PATH_ZMS."?mode=mpeg&monitor=".$monitor['Id']."&scale=$scale&bitrate=".VIDEO_BITRATE."&buffer=0";
|
$stream_src = ZM_PATH_ZMS."?mode=mpeg&monitor=".$monitor['Id']."&scale=$scale&bitrate=".VIDEO_BITRATE."&maxfps=".VIDEO_MAXFPS."&buffer=0";
|
||||||
if ( isWindows() )
|
if ( isWindows() )
|
||||||
{
|
{
|
||||||
if ( isInternetExplorer() )
|
if ( isInternetExplorer() )
|
||||||
|
|
|
@ -101,7 +101,7 @@ if ( $mode == "stream" )
|
||||||
{
|
{
|
||||||
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
if ( ZM_WEB_VIDEO_STREAM_METHOD == 'mpeg' )
|
||||||
{
|
{
|
||||||
$stream_src = ZM_PATH_ZMS."?mode=mpeg&monitor=".$monitor['Id']."&scale=$scale&bitrate=".VIDEO_BITRATE."&buffer=0";
|
$stream_src = ZM_PATH_ZMS."?mode=mpeg&monitor=".$monitor['Id']."&scale=$scale&bitrate=".VIDEO_BITRATE."&maxfps=".VIDEO_MAXFPS."&buffer=0";
|
||||||
if ( isWindows() )
|
if ( isWindows() )
|
||||||
{
|
{
|
||||||
if ( isInternetExplorer() )
|
if ( isInternetExplorer() )
|
||||||
|
|
|
@ -460,6 +460,15 @@ my @options =
|
||||||
type => { db_type=>'string', hint=>'mpeg|jpeg', pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? 'mpeg' : 'jpeg' ) },
|
type => { db_type=>'string', hint=>'mpeg|jpeg', pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? 'mpeg' : 'jpeg' ) },
|
||||||
category => 'web',
|
category => 'web',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => "ZM_WEB_VIDEO_TIMED_FRAMES",
|
||||||
|
default => "yes",
|
||||||
|
description => "Whether video frames are sent tagged with a timestamp for more realistic streaming",
|
||||||
|
help => "When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it's capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it's 'real' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.",
|
||||||
|
requires => [ { name=>"ZM_WEB_VIDEO_STREAM_METHOD", value=>"mpeg" } ],
|
||||||
|
type => $types{boolean},
|
||||||
|
category => 'web',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name => "ZM_WEB_POPUP_ON_ALARM",
|
name => "ZM_WEB_POPUP_ON_ALARM",
|
||||||
default => "yes",
|
default => "yes",
|
||||||
|
@ -942,6 +951,14 @@ my @options =
|
||||||
type => $types{integer},
|
type => $types{integer},
|
||||||
category => 'highband',
|
category => 'highband',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => "ZM_WEB_H_VIDEO_MAXFPS",
|
||||||
|
default => "10",
|
||||||
|
description => "What the maximum frame rate for streamed video should be",
|
||||||
|
help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.",
|
||||||
|
type => $types{integer},
|
||||||
|
category => 'highband',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name => "ZM_WEB_H_STREAM_IDLE_DELAY",
|
name => "ZM_WEB_H_STREAM_IDLE_DELAY",
|
||||||
default => "250",
|
default => "250",
|
||||||
|
@ -1016,6 +1033,14 @@ my @options =
|
||||||
type => $types{integer},
|
type => $types{integer},
|
||||||
category => 'medband',
|
category => 'medband',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => "ZM_WEB_M_VIDEO_MAXFPS",
|
||||||
|
default => "10",
|
||||||
|
description => "What the maximum frame rate for streamed video should be",
|
||||||
|
help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.",
|
||||||
|
type => $types{integer},
|
||||||
|
category => 'medband',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name => "ZM_WEB_M_STREAM_IDLE_DELAY",
|
name => "ZM_WEB_M_STREAM_IDLE_DELAY",
|
||||||
default => "2500",
|
default => "2500",
|
||||||
|
@ -1090,6 +1115,14 @@ my @options =
|
||||||
type => $types{integer},
|
type => $types{integer},
|
||||||
category => 'lowband',
|
category => 'lowband',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => "ZM_WEB_L_VIDEO_MAXFPS",
|
||||||
|
default => "5",
|
||||||
|
description => "What the maximum frame rate for streamed video should be",
|
||||||
|
help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.",
|
||||||
|
type => $types{integer},
|
||||||
|
category => 'lowband',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name => "ZM_WEB_L_STREAM_IDLE_DELAY",
|
name => "ZM_WEB_L_STREAM_IDLE_DELAY",
|
||||||
default => "10000",
|
default => "10000",
|
||||||
|
|
Loading…
Reference in New Issue