Here's a simple patch I developed for more reliable streaming
of remote cameras at lower frame rates. The patch actively
drops frames if there are too many buffered up on the
connection.
David
Code: Select all
diff -u -r ./src/zm_remote_camera.cpp ../ZoneMinder-1.22.3.new/src/zm_remote_camera.cpp
--- ./src/zm_remote_camera.cpp 2006-10-19 01:14:10.000000000 +1000
+++ ../ZoneMinder-1.22.3.new/src/zm_remote_camera.cpp 2007-09-30 15:48:13.000000000 +1000
@@ -52,7 +52,7 @@
request[0] = '\0';
timeout.tv_sec = 0;
timeout.tv_usec = 0;
-
+ last_image_size = 0;
if ( capture )
{
Initialise();
@@ -1051,8 +1051,45 @@
return( 0 );
}
+
+// Patch by David Austin to reduce buffered images for a continuous
+// streamed remote camera. Especially significant when zoneminder is
+// capturing images at relatively low rates.
+
+int RemoteCamera::ReduceBuffer( int expected_image_size ) {
+ int total_bytes_pending = 0;
+ int content_length;
+
+ if ( expected_image_size == 0 ) {
+ return( 0 );
+ }
+
+ if ( ioctl( sd, FIONREAD, &total_bytes_pending ) < 0 )
+ {
+ Error(( "Can't ioctl(): %s", strerror(errno) ));
+ return( -1 );
+ }
+
+ Debug( 3, ( "Found %d bytes pending", total_bytes_pending));
+
+ if ( total_bytes_pending > 5 * expected_image_size ) {
+ while ( total_bytes_pending > 2.5 * expected_image_size ) {
+ content_length = GetResponse();
+ if ( content_length < 0 ) {
+ return ( -1 );
+ }
+ buffer.Consume(content_length);
+ Debug( 3, ( "Dropping frame of %d bytes", content_length ));
+ total_bytes_pending -= content_length;
+ }
+ }
+
+ return( 0 );
+}
+
int RemoteCamera::PreCapture()
{
+ int do_clear_buffer = true;
if ( sd < 0 )
{
Connect();
@@ -1062,6 +1099,7 @@
}
mode = SINGLE_IMAGE;
buffer.Empty();
+ do_clear_buffer = false;
}
if ( mode == SINGLE_IMAGE )
{
@@ -1070,7 +1108,16 @@
Disconnect();
return( -1 );
}
+ do_clear_buffer = false;
}
+
+ if ( do_clear_buffer ) {
+ if ( ReduceBuffer(last_image_size) < 0 ) {
+ Disconnect();
+ return( -1 );
+ }
+ }
+
return( 0 );
}
@@ -1082,6 +1129,9 @@
Disconnect();
return( -1 );
}
+
+ last_image_size = content_length;
+
switch( format )
{
case JPEG :
diff -u -r ./src/zm_remote_camera.h ../ZoneMinder-1.22.3.new/src/zm_remote_camera.h
--- ./src/zm_remote_camera.h 2006-01-22 04:58:46.000000000 +1100
+++ ../ZoneMinder-1.22.3.new/src/zm_remote_camera.h 2007-09-30 15:46:48.000000000 +1000
@@ -45,6 +45,7 @@
struct hostent *hp;
struct sockaddr_in sa;
int sd;
+ int last_image_size;
Buffer buffer;
enum { SINGLE_IMAGE, MULTI_IMAGE } mode;
enum { UNDEF, JPEG, X_RGB, X_RGBZ } format;
@@ -165,6 +166,7 @@
int SendRequest();
int ReadData( Buffer &buffer, int bytes_expected=0 );
int GetResponse();
+ int ReduceBuffer( int expected_image_size );
int PreCapture();
int PostCapture( Image &image );
};