|
|
|
@ -117,6 +117,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
|
|
|
|
|
snprintf(sql, sizeof(sql),
|
|
|
|
|
"SELECT `MonitorId`, `StorageId`, `Frames`, unix_timestamp( `StartTime` ) AS StartTimestamp, "
|
|
|
|
|
"unix_timestamp( `EndTime` ) AS EndTimestamp, "
|
|
|
|
|
"(SELECT max(`Delta`)-min(`Delta`) FROM `Frames` WHERE `EventId`=`Events`.`Id`) AS Duration, "
|
|
|
|
|
"`DefaultVideo`, `Scheme`, `SaveJPEGs`, `Orientation`+0 FROM `Events` WHERE `Id` = %" PRIu64, event_id);
|
|
|
|
|
|
|
|
|
@ -150,9 +151,10 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0;
|
|
|
|
|
event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]);
|
|
|
|
|
event_data->start_time = atoi(dbrow[3]);
|
|
|
|
|
event_data->duration = dbrow[4] ? atof(dbrow[4]) : 0.0;
|
|
|
|
|
strncpy(event_data->video_file, dbrow[5], sizeof(event_data->video_file)-1);
|
|
|
|
|
std::string scheme_str = std::string(dbrow[6]);
|
|
|
|
|
event_data->end_time = dbrow[4] ? atoi(dbrow[4]) : 0;
|
|
|
|
|
event_data->duration = dbrow[5] ? atof(dbrow[5]) : 0.0;
|
|
|
|
|
strncpy(event_data->video_file, dbrow[6], sizeof(event_data->video_file)-1);
|
|
|
|
|
std::string scheme_str = std::string(dbrow[7]);
|
|
|
|
|
if ( scheme_str == "Deep" ) {
|
|
|
|
|
event_data->scheme = Storage::DEEP;
|
|
|
|
|
} else if ( scheme_str == "Medium" ) {
|
|
|
|
@ -160,8 +162,8 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
} else {
|
|
|
|
|
event_data->scheme = Storage::SHALLOW;
|
|
|
|
|
}
|
|
|
|
|
event_data->SaveJPEGs = dbrow[7] == nullptr ? 0 : atoi(dbrow[7]);
|
|
|
|
|
event_data->Orientation = (Monitor::Orientation)(dbrow[8] == nullptr ? 0 : atoi(dbrow[8]));
|
|
|
|
|
event_data->SaveJPEGs = dbrow[8] == nullptr ? 0 : atoi(dbrow[8]);
|
|
|
|
|
event_data->Orientation = (Monitor::Orientation)(dbrow[9] == nullptr ? 0 : atoi(dbrow[9]));
|
|
|
|
|
mysql_free_result(result);
|
|
|
|
|
|
|
|
|
|
if ( !monitor ) {
|
|
|
|
@ -223,8 +225,6 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateFrameRate((double)event_data->frame_count/event_data->duration);
|
|
|
|
|
Debug(3, "fps set by frame_count(%d)/duration(%f)",
|
|
|
|
|
event_data->frame_count, event_data->duration);
|
|
|
|
|
|
|
|
|
|
snprintf(sql, sizeof(sql), "SELECT `FrameId`, unix_timestamp(`TimeStamp`), `Delta` "
|
|
|
|
|
"FROM `Frames` WHERE `EventId` = %" PRIu64 " ORDER BY `FrameId` ASC", event_id);
|
|
|
|
@ -284,11 +284,13 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
event_data->frames[id-1].in_db
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
// Incomplete events might not have any frame data
|
|
|
|
|
event_data->last_frame_id = last_id;
|
|
|
|
|
|
|
|
|
|
if ( mysql_errno(&dbconn) ) {
|
|
|
|
|
Error("Can't fetch row: %s", mysql_error(&dbconn));
|
|
|
|
|
exit(mysql_errno(&dbconn));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mysql_free_result(result);
|
|
|
|
|
|
|
|
|
|
if ( event_data->video_file[0] || (monitor->GetOptVideoWriter() > 0) ) {
|
|
|
|
@ -296,9 +298,10 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
snprintf(event_data->video_file, sizeof(event_data->video_file), "%" PRIu64 "-%s", event_data->event_id, "video.mp4");
|
|
|
|
|
}
|
|
|
|
|
std::string filepath = std::string(event_data->path) + "/" + std::string(event_data->video_file);
|
|
|
|
|
//char filepath[PATH_MAX];
|
|
|
|
|
//snprintf(filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file);
|
|
|
|
|
Debug(1, "Loading video file from %s", filepath.c_str());
|
|
|
|
|
if ( ffmpeg_input )
|
|
|
|
|
delete ffmpeg_input;
|
|
|
|
|
|
|
|
|
|
ffmpeg_input = new FFmpeg_Input();
|
|
|
|
|
if ( 0 > ffmpeg_input->Open(filepath.c_str()) ) {
|
|
|
|
|
Warning("Unable to open ffmpeg_input %s", filepath.c_str());
|
|
|
|
@ -307,14 +310,15 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Not sure about this
|
|
|
|
|
if ( forceEventChange || mode == MODE_ALL_GAPLESS ) {
|
|
|
|
|
if ( replay_rate > 0 )
|
|
|
|
|
curr_stream_time = event_data->frames[0].timestamp;
|
|
|
|
|
else
|
|
|
|
|
curr_stream_time = event_data->frames[event_data->frame_count-1].timestamp;
|
|
|
|
|
curr_stream_time = event_data->frames[event_data->last_frame_id-1].timestamp;
|
|
|
|
|
}
|
|
|
|
|
Debug(2, "Event:%" PRIu64 ", Frames:%ld, Duration: %.2f",
|
|
|
|
|
event_data->event_id, event_data->frame_count, event_data->duration);
|
|
|
|
|
Debug(2, "Event:%" PRIu64 ", Frames:%ld, Last Frame ID(%ld, Duration: %.2f",
|
|
|
|
|
event_data->event_id, event_data->frame_count, event_data->last_frame_id, event_data->duration);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
} // bool EventStream::loadEventData( int event_id )
|
|
|
|
@ -341,12 +345,12 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|
|
|
|
if (
|
|
|
|
|
(mode == MODE_SINGLE || mode == MODE_NONE)
|
|
|
|
|
&&
|
|
|
|
|
((unsigned int)curr_frame_id == event_data->frame_count)
|
|
|
|
|
((unsigned int)curr_frame_id == event_data->last_frame_id)
|
|
|
|
|
) {
|
|
|
|
|
Debug(1, "Was in single or no replay mode, and at last frame, so jumping to 1st frame");
|
|
|
|
|
curr_frame_id = 1;
|
|
|
|
|
} else {
|
|
|
|
|
Debug(1, "mode is %s, current frame is %d, frame count is %d",
|
|
|
|
|
Debug(1, "mode is %s, current frame is %ld, frame count is %ld, last frame id is %ld",
|
|
|
|
|
(mode == MODE_SINGLE ? "single" : "not single"),
|
|
|
|
|
curr_frame_id, event_data->frame_count );
|
|
|
|
|
}
|
|
|
|
@ -401,7 +405,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|
|
|
|
paused = true;
|
|
|
|
|
replay_rate = ZM_RATE_BASE;
|
|
|
|
|
step = 1;
|
|
|
|
|
if ( (unsigned int)curr_frame_id < event_data->frame_count )
|
|
|
|
|
if ( (unsigned int)curr_frame_id < event_data->last_frame_id )
|
|
|
|
|
curr_frame_id += 1;
|
|
|
|
|
Debug(1, "Got SLOWFWD command new frame id %d", curr_frame_id);
|
|
|
|
|
break;
|
|
|
|
@ -498,14 +502,14 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|
|
|
|
if ( replay_rate >= 0 )
|
|
|
|
|
curr_frame_id = 0;
|
|
|
|
|
else
|
|
|
|
|
curr_frame_id = event_data->frame_count+1;
|
|
|
|
|
curr_frame_id = event_data->last_frame_id+1;
|
|
|
|
|
paused = false;
|
|
|
|
|
forceEventChange = true;
|
|
|
|
|
break;
|
|
|
|
|
case CMD_NEXT :
|
|
|
|
|
Debug(1, "Got NEXT command");
|
|
|
|
|
if ( replay_rate >= 0 )
|
|
|
|
|
curr_frame_id = event_data->frame_count+1;
|
|
|
|
|
curr_frame_id = event_data->last_frame_id+1;
|
|
|
|
|
else
|
|
|
|
|
curr_frame_id = 0;
|
|
|
|
|
paused = false;
|
|
|
|
@ -543,6 +547,7 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
uint64_t event_id;
|
|
|
|
|
double duration;
|
|
|
|
|
double progress;
|
|
|
|
|
int rate;
|
|
|
|
|
int zoom;
|
|
|
|
@ -550,12 +555,14 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|
|
|
|
} status_data;
|
|
|
|
|
|
|
|
|
|
status_data.event_id = event_data->event_id;
|
|
|
|
|
status_data.duration = event_data->duration;
|
|
|
|
|
status_data.progress = event_data->frames[curr_frame_id-1].offset;
|
|
|
|
|
status_data.rate = replay_rate;
|
|
|
|
|
status_data.zoom = zoom;
|
|
|
|
|
status_data.paused = paused;
|
|
|
|
|
Debug(2, "Event:%" PRIu64 ", Paused:%d, progress:%f Rate:%d, Zoom:%d",
|
|
|
|
|
Debug(2, "Event:%" PRIu64 ", Duration %f, Paused:%d, progress:%f Rate:%d, Zoom:%d",
|
|
|
|
|
status_data.event_id,
|
|
|
|
|
status_data.duration,
|
|
|
|
|
status_data.paused,
|
|
|
|
|
status_data.progress,
|
|
|
|
|
status_data.rate,
|
|
|
|
@ -587,7 +594,14 @@ bool EventStream::checkEventLoaded() {
|
|
|
|
|
snprintf(sql, sizeof(sql),
|
|
|
|
|
"SELECT `Id` FROM `Events` WHERE `MonitorId` = %d AND `Id` < %" PRIu64 " ORDER BY `Id` DESC LIMIT 1",
|
|
|
|
|
event_data->monitor_id, event_data->event_id);
|
|
|
|
|
} else if ( (unsigned int)curr_frame_id > event_data->frame_count ) {
|
|
|
|
|
} else if ( (unsigned int)curr_frame_id > event_data->last_frame_id ) {
|
|
|
|
|
if ( !event_data->end_time ) {
|
|
|
|
|
// We are viewing an in-process event, so just reload it.
|
|
|
|
|
loadEventData(event_data->event_id);
|
|
|
|
|
if ( (unsigned int)curr_frame_id > event_data->last_frame_id )
|
|
|
|
|
curr_frame_id = event_data->last_frame_id;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
snprintf(sql, sizeof(sql),
|
|
|
|
|
"SELECT `Id` FROM `Events` WHERE `MonitorId` = %d AND `Id` > %" PRIu64 " ORDER BY `Id` ASC LIMIT 1",
|
|
|
|
|
event_data->monitor_id, event_data->event_id);
|
|
|
|
@ -600,6 +614,7 @@ bool EventStream::checkEventLoaded() {
|
|
|
|
|
|
|
|
|
|
// Event change required.
|
|
|
|
|
if ( forceEventChange || ( (mode != MODE_SINGLE) && (mode != MODE_NONE) ) ) {
|
|
|
|
|
Debug(1, "Checking for next event %s", sql);
|
|
|
|
|
if ( mysql_query(&dbconn, sql) ) {
|
|
|
|
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
|
|
|
|
exit(mysql_errno(&dbconn));
|
|
|
|
@ -610,6 +625,9 @@ bool EventStream::checkEventLoaded() {
|
|
|
|
|
Error("Can't use query result: %s", mysql_error(&dbconn));
|
|
|
|
|
exit(mysql_errno(&dbconn));
|
|
|
|
|
}
|
|
|
|
|
if ( mysql_num_rows(result) != 1 ) {
|
|
|
|
|
Debug(1, "No rows returned for %s", sql);
|
|
|
|
|
}
|
|
|
|
|
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
|
|
|
|
|
|
|
|
|
if ( mysql_errno(&dbconn)) {
|
|
|
|
@ -624,7 +642,7 @@ bool EventStream::checkEventLoaded() {
|
|
|
|
|
loadEventData(event_id);
|
|
|
|
|
|
|
|
|
|
if ( replay_rate < 0 ) // rewind
|
|
|
|
|
curr_frame_id = event_data->frame_count;
|
|
|
|
|
curr_frame_id = event_data->last_frame_id;
|
|
|
|
|
else
|
|
|
|
|
curr_frame_id = 1;
|
|
|
|
|
Debug(2, "New frame id = %d", curr_frame_id);
|
|
|
|
@ -645,7 +663,7 @@ bool EventStream::checkEventLoaded() {
|
|
|
|
|
if ( curr_frame_id <= 0 )
|
|
|
|
|
curr_frame_id = 1;
|
|
|
|
|
else
|
|
|
|
|
curr_frame_id = event_data->frame_count;
|
|
|
|
|
curr_frame_id = event_data->last_frame_id;
|
|
|
|
|
paused = true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
@ -795,7 +813,7 @@ bool EventStream::sendFrame(int delta_us) {
|
|
|
|
|
|
|
|
|
|
} // end if stream MPEG or other
|
|
|
|
|
|
|
|
|
|
fputs("\r\n\r\n", stdout);
|
|
|
|
|
fputs("\r\n", stdout);
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
last_frame_sent = TV_2_FLOAT(now);
|
|
|
|
|
return true;
|
|
|
|
@ -814,7 +832,6 @@ void EventStream::runStream() {
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug(3, "frame rate is: (%f)", (double)event_data->frame_count/event_data->duration);
|
|
|
|
|
updateFrameRate((double)event_data->frame_count/event_data->duration);
|
|
|
|
|
gettimeofday(&start, nullptr);
|
|
|
|
|
uint64_t start_usec = start.tv_sec * 1000000 + start.tv_usec;
|
|
|
|
@ -871,11 +888,11 @@ void EventStream::runStream() {
|
|
|
|
|
} // end if streaming stepping or doing nothing
|
|
|
|
|
|
|
|
|
|
// time_to_event > 0 means that we are not in the event
|
|
|
|
|
if ( time_to_event > 0 ) {
|
|
|
|
|
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
|
|
|
|
|
Debug(1, "Actual delta time = %f = %f - %f", actual_delta_time, TV_2_FLOAT(now), last_frame_sent);
|
|
|
|
|
if ( ( time_to_event > 0 ) and ( mode == MODE_ALL ) ) {
|
|
|
|
|
double time_since_last_send = TV_2_FLOAT(now) - last_frame_sent;
|
|
|
|
|
Debug(1, "Time since last send = %f = %f - %f", time_since_last_send, TV_2_FLOAT(now), last_frame_sent);
|
|
|
|
|
// > 1 second
|
|
|
|
|
if ( actual_delta_time > 1 ) {
|
|
|
|
|
if ( time_since_last_send > 1 ) {
|
|
|
|
|
Debug(1, "Sending time to next event frame");
|
|
|
|
|
static char frame_text[64];
|
|
|
|
|
|
|
|
|
@ -1074,6 +1091,10 @@ bool EventStream::send_file(const char * filepath) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return send_buffer(img_buffer, img_buffer_size);
|
|
|
|
|
} // end bool EventStream::send_file(const char * filepath)
|
|
|
|
|
|
|
|
|
|
bool EventStream::send_buffer(uint8_t* buffer, int size) {
|
|
|
|
|
if ( 0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) ) {
|
|
|
|
|
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
|
|
|
|
return false;
|
|
|
|
@ -1084,16 +1105,6 @@ bool EventStream::send_file(const char * filepath) {
|
|
|
|
|
Error("Unable to send raw frame %u: %s %d", curr_frame_id, strerror(errno), rc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
} // end bool EventStream::send_file(const char * filepath)
|
|
|
|
|
|
|
|
|
|
bool EventStream::send_buffer(uint8_t* buffer, int size) {
|
|
|
|
|
fprintf(stdout, "Content-Length: %d\r\n\r\n", size);
|
|
|
|
|
if ( fwrite(buffer, size, 1, stdout) != 1 ) {
|
|
|
|
|
Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
} // end bool EventStream::send_buffer(uint8_t* buffer, int size)
|
|
|
|
|
|
|
|
|
|