mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-05-18 19:46:12 -04:00
Merge branch 'master' into zma_to_thread
This commit is contained in:
@@ -330,14 +330,16 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
|
||||
struct timeval frameStartTime;
|
||||
gettimeofday(&frameStartTime, NULL);
|
||||
|
||||
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
fputs("--" BOUNDARY "\r\nContent-Type: image/jpeg\r\n", stdout);
|
||||
fprintf(stdout, "Content-Length: %d\r\n"
|
||||
"X-Timestamp: %d.%06d\r\n"
|
||||
"\r\n", img_buffer_size, (int)timestamp->tv_sec, (int)timestamp->tv_usec);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if ( !zm_terminate )
|
||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
fputs("\r\n\r\n", stdout);
|
||||
fputs("\r\n", stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct timeval frameEndTime;
|
||||
@@ -361,6 +363,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||
if ( !config.timestamp_on_capture && timestamp )
|
||||
monitor->TimestampImage(send_image, timestamp);
|
||||
|
||||
fputs("--" BOUNDARY "\r\n", stdout);
|
||||
#if HAVE_LIBAVCODEC
|
||||
if ( type == STREAM_MPEG ) {
|
||||
if ( !vid_stream ) {
|
||||
@@ -386,7 +389,6 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||
struct timeval frameStartTime;
|
||||
gettimeofday(&frameStartTime, NULL);
|
||||
|
||||
fputs("--ZoneMinderFrame\r\n", stdout);
|
||||
switch( type ) {
|
||||
case STREAM_JPEG :
|
||||
send_image->EncodeJpeg(img_buffer, &img_buffer_size);
|
||||
@@ -404,15 +406,17 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||
send_image->Zip(img_buffer, &zip_buffer_size);
|
||||
img_buffer_size = zip_buffer_size;
|
||||
#else
|
||||
Error("zlib is required for zipped images. Falling back to raw image");
|
||||
type = STREAM_RAW;
|
||||
Error("zlib is required for zipped images. Falling back to raw image");
|
||||
type = STREAM_RAW;
|
||||
#endif // HAVE_ZLIB_H
|
||||
break;
|
||||
default :
|
||||
Error("Unexpected frame type %d", type);
|
||||
return false;
|
||||
}
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
fprintf(stdout, "Content-Length: %d\r\n"
|
||||
"X-Timestamp: %d.%06d\r\n"
|
||||
"\r\n", img_buffer_size, (int)timestamp->tv_sec, (int)timestamp->tv_usec);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if ( !zm_terminate ) {
|
||||
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
|
||||
@@ -420,7 +424,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
fputs("\r\n\r\n", stdout);
|
||||
fputs("\r\n", stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct timeval frameEndTime;
|
||||
@@ -454,7 +458,7 @@ void MonitorStream::runStream() {
|
||||
updateFrameRate(monitor->GetFPS());
|
||||
|
||||
if ( type == STREAM_JPEG )
|
||||
fputs("Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n", stdout);
|
||||
fputs("Content-Type: multipart/x-mixed-replace; boundary=" BOUNDARY "\r\n\r\n", stdout);
|
||||
|
||||
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
|
||||
unsigned int last_read_index = monitor->image_buffer_count;
|
||||
@@ -520,7 +524,6 @@ void MonitorStream::runStream() {
|
||||
Debug(2, "Not using playback_buffer");
|
||||
} // 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();
|
||||
@@ -529,15 +532,6 @@ void MonitorStream::runStream() {
|
||||
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) ) {
|
||||
@@ -673,7 +667,7 @@ void MonitorStream::runStream() {
|
||||
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
|
||||
if ( !paused && !delayed ) {
|
||||
last_read_index = monitor->shared_data->last_write_index;
|
||||
Debug(2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
|
||||
Debug(2, "Sending frame index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
|
||||
index, frame_mod, frame_count, paused, delayed);
|
||||
// Send the next frame
|
||||
//
|
||||
@@ -688,6 +682,15 @@ void MonitorStream::runStream() {
|
||||
// Perhaps we should use NOW instead.
|
||||
last_frame_timestamp = *timestamp;
|
||||
//frame_sent = true;
|
||||
//
|
||||
if ( frame_count == 0 ) {
|
||||
// Chrome will not display the first frame until it receives another.
|
||||
// Firefox is fine. So just send the first frame twice.
|
||||
if ( !sendFrame(snap->image, snap->timestamp) ) {
|
||||
Debug(2, "sendFrame failed, quiting.");
|
||||
zm_terminate = true;
|
||||
}
|
||||
}
|
||||
|
||||
temp_read_index = temp_write_index;
|
||||
} else {
|
||||
@@ -756,13 +759,13 @@ void MonitorStream::runStream() {
|
||||
} // 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(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 MAX_SLEEP_USEC %dus", sleep_time);
|
||||
} else {
|
||||
Debug(3, "Sleeping for %dus", sleep_time);
|
||||
}
|
||||
Debug(3, "Sleeping for %dus", sleep_time);
|
||||
usleep(sleep_time);
|
||||
if ( ttl ) {
|
||||
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
||||
@@ -775,14 +778,6 @@ void MonitorStream::runStream() {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
} // end while
|
||||
|
||||
|
||||
Reference in New Issue
Block a user