diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index d1952f66a..ed81489da 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -413,7 +413,7 @@ CREATE TABLE `MonitorPresets` ( `Width` smallint(5) unsigned default NULL, `Height` smallint(5) 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', `ControlId` varchar(16) default NULL, `ControlDevice` varchar(255) default NULL, diff --git a/db/zm_update-1.33.13.sql b/db/zm_update-1.33.13.sql new file mode 100644 index 000000000..8114205c0 --- /dev/null +++ b/db/zm_update-1.33.13.sql @@ -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; diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 264749201..15406c456 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -27,6 +27,8 @@ #include #include +const int MAX_SLEEP_USEC=1000000; // 1 sec + bool MonitorStream::checkSwapPath(const char *path, bool create_path) { struct stat stat_buf; @@ -416,20 +418,21 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) { } return false; } - fputs("\r\n\r\n",stdout); - fflush( stdout ); + fputs("\r\n\r\n", stdout); + fflush(stdout); struct timeval frameEndTime; - gettimeofday( &frameEndTime, NULL ); + gettimeofday(&frameEndTime, NULL); - int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + int frameSendTime = tvDiffMsec(frameStartTime, frameEndTime); if ( frameSendTime > 1000/maxfps ) { 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 ); - return( true ); + last_frame_sent = TV_2_FLOAT(now); + return true; } // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) void MonitorStream::runStream() { @@ -515,16 +518,33 @@ void MonitorStream::runStream() { } // end if connkey & playback_buffer 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 ) { bool got_command = false; if ( feof(stdout) ) { - Debug(2,"feof stdout"); + Debug(2, "feof stdout"); break; } else if ( ferror(stdout) ) { - Debug(2,"ferror stdout"); + Debug(2, "ferror stdout"); break; } 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; } @@ -547,12 +567,12 @@ void MonitorStream::runStream() { if ( paused ) { if ( !was_paused ) { int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; - Debug(1,"Saving paused image from index %d",index); - paused_image = new Image( *monitor->image_buffer[index].image ); + Debug(1, "Saving paused image from index %d",index); + paused_image = new Image(*monitor->image_buffer[index].image); paused_timestamp = *(monitor->image_buffer[index].timestamp); } } else if ( paused_image ) { - Debug(1,"Clearing paused_image"); + Debug(1, "Clearing paused_image"); delete paused_image; paused_image = NULL; } @@ -560,7 +580,7 @@ void MonitorStream::runStream() { if ( buffered_playback && delayed ) { if ( temp_read_index == temp_write_index ) { // Go back to live viewing - Debug( 1, "Exceeded temporary streaming buffer" ); + Debug(1, "Exceeded temporary streaming buffer"); // Clear paused flag paused = false; // Clear delayed_play flag @@ -611,10 +631,10 @@ void MonitorStream::runStream() { //paused? int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count); - double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - if ( got_command || actual_delta_time > 5 ) { + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( got_command || actual_delta_time > 5 ) { // Send keepalive - Debug( 2, "Sending keepalive frame %d", temp_index ); + Debug(2, "Sending keepalive frame %d", temp_index); // Send the next frame if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) zm_terminate = true; @@ -625,7 +645,7 @@ void MonitorStream::runStream() { if ( temp_read_index == temp_write_index ) { // Go back to live viewing - Warning( "Rewound over write index, resuming live play" ); + Warning("Rewound over write index, resuming live play"); // Clear paused flag paused = false; // Clear delayed_play flag @@ -638,7 +658,8 @@ void MonitorStream::runStream() { // have a new image to send 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; - 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 ( !paused && !delayed ) { // Send the next frame @@ -655,18 +676,19 @@ void MonitorStream::runStream() { temp_read_index = temp_write_index; } else { + Debug(2, "Paused %d, delayed %d", paused, delayed); double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent; if ( actual_delta_time > 5 ) { if ( paused_image ) { // Send keepalive - Debug(2, "Sending keepalive frame "); + Debug(2, "Sending keepalive frame because delta time %.2f > 5", actual_delta_time); // Send the next frame if ( !sendFrame(paused_image, &paused_timestamp) ) zm_terminate = true; } else { Debug(2, "Would have sent keepalive frame, but had no paused_image "); } - } + } } } // end if should send frame @@ -698,11 +720,17 @@ void MonitorStream::runStream() { } // end if buffered playback frame_count++; } 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 ) 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); if ( ttl ) { if ( (now.tv_sec - stream_start_time) > ttl ) { @@ -713,9 +741,15 @@ void MonitorStream::runStream() { if ( ! last_frame_sent ) { // 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; - Warning( "no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", frame_mod, frame_count ); - } 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 ); + Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", + frame_mod, frame_count); + } 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; } } // end while diff --git a/version b/version index 325da8275..91a50ee09 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.33.12 +1.33.13