Fix 2673 (#2675)
* Change MaxFPS to DECIMAL(5,3) to handle values like 1/60 = 0.017 * When fps < 1 we may need to wait longer than 10s. Also, we cannot sleep for a long time, because we may need to send a keep alive or check the command queue. So limit the sleep to 1s * Bump version * Update MaxFPS to Decimal(5,3) * Fix missing ;
This commit is contained in:
parent
48ad8d47fc
commit
90cb5d018a
|
@ -413,7 +413,7 @@ CREATE TABLE `MonitorPresets` (
|
||||||
`Width` smallint(5) unsigned default NULL,
|
`Width` smallint(5) unsigned default NULL,
|
||||||
`Height` smallint(5) unsigned default NULL,
|
`Height` smallint(5) unsigned default NULL,
|
||||||
`Palette` int(10) unsigned default NULL,
|
`Palette` int(10) unsigned default NULL,
|
||||||
`MaxFPS` decimal(5,2) default NULL,
|
`MaxFPS` decimal(5,3) default NULL,
|
||||||
`Controllable` tinyint(3) unsigned NOT NULL default '0',
|
`Controllable` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`ControlId` varchar(16) default NULL,
|
`ControlId` varchar(16) default NULL,
|
||||||
`ControlDevice` varchar(255) default NULL,
|
`ControlDevice` varchar(255) default NULL,
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
--
|
||||||
|
-- Add primary keys for Logs and Stats tables
|
||||||
|
--
|
||||||
|
|
||||||
|
SELECT "Modifying Monitors MaxFPS to DECIMAL(5,3)";
|
||||||
|
ALTER TABLE `Monitors` MODIFY `MaxFPS` decimal(5,3) default NULL;
|
|
@ -27,6 +27,8 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
|
||||||
|
const int MAX_SLEEP_USEC=1000000; // 1 sec
|
||||||
|
|
||||||
bool MonitorStream::checkSwapPath(const char *path, bool create_path) {
|
bool MonitorStream::checkSwapPath(const char *path, bool create_path) {
|
||||||
|
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
|
@ -416,20 +418,21 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fputs("\r\n\r\n",stdout);
|
fputs("\r\n\r\n", stdout);
|
||||||
fflush( stdout );
|
fflush(stdout);
|
||||||
|
|
||||||
struct timeval frameEndTime;
|
struct timeval frameEndTime;
|
||||||
gettimeofday( &frameEndTime, NULL );
|
gettimeofday(&frameEndTime, NULL);
|
||||||
|
|
||||||
int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime );
|
int frameSendTime = tvDiffMsec(frameStartTime, frameEndTime);
|
||||||
if ( frameSendTime > 1000/maxfps ) {
|
if ( frameSendTime > 1000/maxfps ) {
|
||||||
maxfps /= 1.5;
|
maxfps /= 1.5;
|
||||||
Warning("Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps);
|
Warning("Frame send time %d msec too slow, throttling maxfps to %.2f",
|
||||||
|
frameSendTime, maxfps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_frame_sent = TV_2_FLOAT( now );
|
last_frame_sent = TV_2_FLOAT(now);
|
||||||
return( true );
|
return true;
|
||||||
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
|
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
|
||||||
|
|
||||||
void MonitorStream::runStream() {
|
void MonitorStream::runStream() {
|
||||||
|
@ -515,16 +518,33 @@ void MonitorStream::runStream() {
|
||||||
} // end if connkey & playback_buffer
|
} // end if connkey & playback_buffer
|
||||||
|
|
||||||
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
|
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
|
||||||
|
// if MaxFPS < 0 as in 1/60 = 0.017 then we won't get another frame for 60 sec.
|
||||||
|
double capture_fps = monitor->GetFPS();
|
||||||
|
double capture_max_fps = monitor->GetCaptureMaxFPS();
|
||||||
|
if ( capture_max_fps && ( capture_fps > capture_max_fps ) ) {
|
||||||
|
Debug(1, "Using %.3f for fps instead of current fps %.3f", capture_max_fps, capture_fps);
|
||||||
|
capture_fps = capture_max_fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( capture_fps < 1 ) {
|
||||||
|
max_secs_since_last_sent_frame = 10/capture_fps;
|
||||||
|
Debug(1, "Adjusting max_secs_since_last_sent_frame to %.2f from current fps %.2f",
|
||||||
|
max_secs_since_last_sent_frame, monitor->GetFPS());
|
||||||
|
} else {
|
||||||
|
Debug(1, "Not Adjusting max_secs_since_last_sent_frame to %.2f from current fps %.2f",
|
||||||
|
max_secs_since_last_sent_frame, monitor->GetFPS());
|
||||||
|
}
|
||||||
|
|
||||||
while ( !zm_terminate ) {
|
while ( !zm_terminate ) {
|
||||||
bool got_command = false;
|
bool got_command = false;
|
||||||
if ( feof(stdout) ) {
|
if ( feof(stdout) ) {
|
||||||
Debug(2,"feof stdout");
|
Debug(2, "feof stdout");
|
||||||
break;
|
break;
|
||||||
} else if ( ferror(stdout) ) {
|
} else if ( ferror(stdout) ) {
|
||||||
Debug(2,"ferror stdout");
|
Debug(2, "ferror stdout");
|
||||||
break;
|
break;
|
||||||
} else if ( !monitor->ShmValid() ) {
|
} else if ( !monitor->ShmValid() ) {
|
||||||
Debug(2,"monitor not valid.... maybe we should wait until it comes back.");
|
Debug(2, "monitor not valid.... maybe we should wait until it comes back.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,12 +567,12 @@ void MonitorStream::runStream() {
|
||||||
if ( paused ) {
|
if ( paused ) {
|
||||||
if ( !was_paused ) {
|
if ( !was_paused ) {
|
||||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
||||||
Debug(1,"Saving paused image from index %d",index);
|
Debug(1, "Saving paused image from index %d",index);
|
||||||
paused_image = new Image( *monitor->image_buffer[index].image );
|
paused_image = new Image(*monitor->image_buffer[index].image);
|
||||||
paused_timestamp = *(monitor->image_buffer[index].timestamp);
|
paused_timestamp = *(monitor->image_buffer[index].timestamp);
|
||||||
}
|
}
|
||||||
} else if ( paused_image ) {
|
} else if ( paused_image ) {
|
||||||
Debug(1,"Clearing paused_image");
|
Debug(1, "Clearing paused_image");
|
||||||
delete paused_image;
|
delete paused_image;
|
||||||
paused_image = NULL;
|
paused_image = NULL;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +580,7 @@ void MonitorStream::runStream() {
|
||||||
if ( buffered_playback && delayed ) {
|
if ( buffered_playback && delayed ) {
|
||||||
if ( temp_read_index == temp_write_index ) {
|
if ( temp_read_index == temp_write_index ) {
|
||||||
// Go back to live viewing
|
// Go back to live viewing
|
||||||
Debug( 1, "Exceeded temporary streaming buffer" );
|
Debug(1, "Exceeded temporary streaming buffer");
|
||||||
// Clear paused flag
|
// Clear paused flag
|
||||||
paused = false;
|
paused = false;
|
||||||
// Clear delayed_play flag
|
// Clear delayed_play flag
|
||||||
|
@ -611,10 +631,10 @@ void MonitorStream::runStream() {
|
||||||
//paused?
|
//paused?
|
||||||
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
|
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
|
||||||
|
|
||||||
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
|
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
|
||||||
if ( got_command || actual_delta_time > 5 ) {
|
if ( got_command || actual_delta_time > 5 ) {
|
||||||
// Send keepalive
|
// Send keepalive
|
||||||
Debug( 2, "Sending keepalive frame %d", temp_index );
|
Debug(2, "Sending keepalive frame %d", temp_index);
|
||||||
// Send the next frame
|
// Send the next frame
|
||||||
if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) )
|
if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) )
|
||||||
zm_terminate = true;
|
zm_terminate = true;
|
||||||
|
@ -625,7 +645,7 @@ void MonitorStream::runStream() {
|
||||||
|
|
||||||
if ( temp_read_index == temp_write_index ) {
|
if ( temp_read_index == temp_write_index ) {
|
||||||
// Go back to live viewing
|
// Go back to live viewing
|
||||||
Warning( "Rewound over write index, resuming live play" );
|
Warning("Rewound over write index, resuming live play");
|
||||||
// Clear paused flag
|
// Clear paused flag
|
||||||
paused = false;
|
paused = false;
|
||||||
// Clear delayed_play flag
|
// Clear delayed_play flag
|
||||||
|
@ -638,7 +658,8 @@ void MonitorStream::runStream() {
|
||||||
// have a new image to send
|
// have a new image to send
|
||||||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
|
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
|
||||||
last_read_index = monitor->shared_data->last_write_index;
|
last_read_index = monitor->shared_data->last_write_index;
|
||||||
Debug( 2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)", index, frame_mod, frame_count, paused, delayed );
|
Debug(2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
|
||||||
|
index, frame_mod, frame_count, paused, delayed );
|
||||||
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
|
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
|
||||||
if ( !paused && !delayed ) {
|
if ( !paused && !delayed ) {
|
||||||
// Send the next frame
|
// Send the next frame
|
||||||
|
@ -655,18 +676,19 @@ void MonitorStream::runStream() {
|
||||||
|
|
||||||
temp_read_index = temp_write_index;
|
temp_read_index = temp_write_index;
|
||||||
} else {
|
} else {
|
||||||
|
Debug(2, "Paused %d, delayed %d", paused, delayed);
|
||||||
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
|
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
|
||||||
if ( actual_delta_time > 5 ) {
|
if ( actual_delta_time > 5 ) {
|
||||||
if ( paused_image ) {
|
if ( paused_image ) {
|
||||||
// Send keepalive
|
// Send keepalive
|
||||||
Debug(2, "Sending keepalive frame ");
|
Debug(2, "Sending keepalive frame because delta time %.2f > 5", actual_delta_time);
|
||||||
// Send the next frame
|
// Send the next frame
|
||||||
if ( !sendFrame(paused_image, &paused_timestamp) )
|
if ( !sendFrame(paused_image, &paused_timestamp) )
|
||||||
zm_terminate = true;
|
zm_terminate = true;
|
||||||
} else {
|
} else {
|
||||||
Debug(2, "Would have sent keepalive frame, but had no paused_image ");
|
Debug(2, "Would have sent keepalive frame, but had no paused_image ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end if should send frame
|
} // end if should send frame
|
||||||
|
|
||||||
|
@ -698,11 +720,17 @@ void MonitorStream::runStream() {
|
||||||
} // end if buffered playback
|
} // end if buffered playback
|
||||||
frame_count++;
|
frame_count++;
|
||||||
} else {
|
} else {
|
||||||
Debug(4,"Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
|
Debug(3, "Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
|
||||||
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
|
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
|
||||||
|
|
||||||
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
||||||
Debug(4, "Sleeping for (%d)", sleep_time);
|
Debug(3, "Sleeping for (%d)", sleep_time);
|
||||||
|
|
||||||
|
if ( sleep_time > MAX_SLEEP_USEC ) {
|
||||||
|
// Shouldn't sleep for long because we need to check command queue, etc.
|
||||||
|
sleep_time = MAX_SLEEP_USEC;
|
||||||
|
}
|
||||||
|
Debug(3, "Sleeping for %dus", sleep_time);
|
||||||
usleep(sleep_time);
|
usleep(sleep_time);
|
||||||
if ( ttl ) {
|
if ( ttl ) {
|
||||||
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
||||||
|
@ -713,9 +741,15 @@ void MonitorStream::runStream() {
|
||||||
if ( ! last_frame_sent ) {
|
if ( ! last_frame_sent ) {
|
||||||
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
|
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
|
||||||
last_frame_sent = now.tv_sec;
|
last_frame_sent = now.tv_sec;
|
||||||
Warning( "no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", frame_mod, frame_count );
|
Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ",
|
||||||
} else if ( (!paused) && ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) ) {
|
frame_mod, frame_count);
|
||||||
Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame );
|
} else if (
|
||||||
|
(!paused)
|
||||||
|
&&
|
||||||
|
( (TV_2_FLOAT(now) - last_frame_sent) > max_secs_since_last_sent_frame )
|
||||||
|
) {
|
||||||
|
Error("Terminating, last frame sent time %f secs more than maximum of %f",
|
||||||
|
TV_2_FLOAT(now) - last_frame_sent, max_secs_since_last_sent_frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // end while
|
} // end while
|
||||||
|
|
Loading…
Reference in New Issue