rework
parent
c70a9f665a
commit
43b71fc49b
|
@ -81,7 +81,7 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
|
||||||
? $Config{ZM_DIR_EVENTS}
|
? $Config{ZM_DIR_EVENTS}
|
||||||
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
|
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
|
||||||
;
|
;
|
||||||
use constant ZM_AUDIT_PID => $Config{ZM_RUNDIR}.'/zm.pid'
|
use constant ZM_AUDIT_PID => '@ZM_RUNDIR@/zmaudit.pid';
|
||||||
|
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
|
||||||
|
|
|
@ -579,7 +579,6 @@ Image * EventStream::getImage( ) {
|
||||||
|
|
||||||
Debug( 2, "EventStream::getImage path(%s) frame(%d)", event_data->path, curr_frame_id );
|
Debug( 2, "EventStream::getImage path(%s) frame(%d)", event_data->path, curr_frame_id );
|
||||||
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
|
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
|
||||||
Debug( 2, "EventStream::getImage path(%s) ", filepath, curr_frame_id );
|
|
||||||
Image *image = new Image( filepath );
|
Image *image = new Image( filepath );
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +656,7 @@ bool EventStream::sendFrame( int delta_us ) {
|
||||||
} else if ( ffmpeg_input ) {
|
} else if ( ffmpeg_input ) {
|
||||||
// Get the frame from the mp4 input
|
// Get the frame from the mp4 input
|
||||||
Debug(1,"Getting frame from ffmpeg");
|
Debug(1,"Getting frame from ffmpeg");
|
||||||
AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id() );
|
AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id(), curr_frame_id );
|
||||||
if ( frame ) {
|
if ( frame ) {
|
||||||
image = new Image( frame );
|
image = new Image( frame );
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
|
|
|
@ -373,3 +373,48 @@ bool is_audio_stream( AVStream * stream ) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet ) {
|
||||||
|
int ret;
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
if ( (ret = avcodec_send_packet(context, &packet)) < 0 ) {
|
||||||
|
Error( "Unable to send packet %s, continuing",
|
||||||
|
av_make_error_string(ret).c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
|
if ( hwaccel ) {
|
||||||
|
if ( (ret = avcodec_receive_frame(context, hwFrame)) < 0 ) {
|
||||||
|
Error( "Unable to receive frame %d: %s, continuing", streams[packet.stream_index].frame_count,
|
||||||
|
av_make_error_string(ret).c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( (ret = av_hwframe_transfer_data(frame, hwFrame, 0)) < 0 ) {
|
||||||
|
Error( "Unable to transfer frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count,
|
||||||
|
av_make_error_string(ret).c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if ( (ret = avcodec_receive_frame(context, frame)) < 0 ) {
|
||||||
|
Error( "Unable to send packet %s, continuing", av_make_error_string(ret).c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
int frameComplete;
|
||||||
|
while ( !frameComplete ) {
|
||||||
|
if ( (ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet )) < 0 ) {
|
||||||
|
Error( "Unable to decode frame at frame %d: %s, continuing",
|
||||||
|
streams[packet.stream_index].frame_count,
|
||||||
|
av_make_error_string(ret).c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
} // end int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet )
|
||||||
|
|
|
@ -237,9 +237,8 @@ enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subp
|
||||||
*/
|
*/
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
inline static const std::string av_make_error_string(int errnum)
|
inline static const std::string av_make_error_string(int errnum) {
|
||||||
{
|
static char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
||||||
char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
|
||||||
#if LIBAVUTIL_VERSION_CHECK(50, 13, 0, 13, 0)
|
#if LIBAVUTIL_VERSION_CHECK(50, 13, 0, 13, 0)
|
||||||
av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
#else
|
#else
|
||||||
|
@ -327,4 +326,5 @@ int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
|
||||||
|
|
||||||
bool is_video_stream( AVStream * stream );
|
bool is_video_stream( AVStream * stream );
|
||||||
bool is_audio_stream( AVStream * stream );
|
bool is_audio_stream( AVStream * stream );
|
||||||
|
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet );
|
||||||
#endif // ZM_FFMPEG_H
|
#endif // ZM_FFMPEG_H
|
||||||
|
|
|
@ -13,6 +13,9 @@ FFmpeg_Input::FFmpeg_Input() {
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpeg_Input::~FFmpeg_Input() {
|
FFmpeg_Input::~FFmpeg_Input() {
|
||||||
|
if ( input_format_context ) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
if ( streams ) {
|
if ( streams ) {
|
||||||
delete streams;
|
delete streams;
|
||||||
streams = NULL;
|
streams = NULL;
|
||||||
|
@ -25,7 +28,6 @@ int FFmpeg_Input::Open( const char *filepath ) {
|
||||||
|
|
||||||
/** Open the input file to read from it. */
|
/** Open the input file to read from it. */
|
||||||
if ( (error = avformat_open_input( &input_format_context, filepath, NULL, NULL)) < 0 ) {
|
if ( (error = avformat_open_input( &input_format_context, filepath, NULL, NULL)) < 0 ) {
|
||||||
|
|
||||||
Error("Could not open input file '%s' (error '%s')\n",
|
Error("Could not open input file '%s' (error '%s')\n",
|
||||||
filepath, av_make_error_string(error).c_str() );
|
filepath, av_make_error_string(error).c_str() );
|
||||||
input_format_context = NULL;
|
input_format_context = NULL;
|
||||||
|
@ -94,94 +96,73 @@ int FFmpeg_Input::Open( const char *filepath ) {
|
||||||
return 0;
|
return 0;
|
||||||
} // end int FFmpeg_Input::Open( const char * filepath )
|
} // end int FFmpeg_Input::Open( const char * filepath )
|
||||||
|
|
||||||
AVFrame *FFmpeg_Input::get_frame( int stream_id ) {
|
int FFmpeg_Input::Close( ) {
|
||||||
Debug(1, "Getting frame from stream %d", stream_id );
|
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
|
||||||
|
if ( streams[i].context ) {
|
||||||
|
avcodec_close( streams[i].context );
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
avcodec_free_context(& streams[i].context );
|
||||||
|
#endif
|
||||||
|
streams[i].context = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( input_format_context ) {
|
||||||
|
#if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0)
|
||||||
|
av_close_input_file( input_format_context );
|
||||||
|
#else
|
||||||
|
avformat_close_input( &input_format_context );
|
||||||
|
#endif
|
||||||
|
input_format_context = NULL;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} // end int FFmpeg_Input::Close()
|
||||||
|
|
||||||
|
AVFrame *FFmpeg_Input::get_frame( int stream_id, int frame_number ) {
|
||||||
|
Debug(1, "Getting frame from stream %d, frame_number(%d)", stream_id, frame_number );
|
||||||
|
|
||||||
int frameComplete = false;
|
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
av_init_packet( &packet );
|
av_init_packet( &packet );
|
||||||
AVFrame *frame = zm_av_frame_alloc();
|
AVFrame *frame = zm_av_frame_alloc();
|
||||||
char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
|
||||||
|
|
||||||
while ( !frameComplete ) {
|
while ( frame_number >= streams[stream_id].frame_count ) {
|
||||||
int ret = av_read_frame( input_format_context, &packet );
|
|
||||||
|
int ret = av_read_frame(input_format_context, &packet);
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
|
||||||
if (
|
if (
|
||||||
// Check if EOF.
|
// Check if EOF.
|
||||||
(ret == AVERROR_EOF || (input_format_context->pb && input_format_context->pb->eof_reached)) ||
|
(ret == AVERROR_EOF || (input_format_context->pb && input_format_context->pb->eof_reached)) ||
|
||||||
// Check for Connection failure.
|
// Check for Connection failure.
|
||||||
(ret == -110)
|
(ret == -110)
|
||||||
) {
|
) {
|
||||||
Info( "av_read_frame returned %s.", errbuf );
|
Info( "av_read_frame returned %s.", av_make_error_string(ret).c_str() );
|
||||||
return NULL;
|
} else {
|
||||||
|
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret,
|
||||||
|
av_make_error_string(ret).c_str() );
|
||||||
}
|
}
|
||||||
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf );
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (stream_id < 0 ) || ( packet.stream_index == stream_id ) ) {
|
if ( ( stream_id < 0 ) || ( packet.stream_index != stream_id ) ) {
|
||||||
Debug(1,"Packet is for our stream (%d)", packet.stream_index );
|
Warning("Packet is not for our stream (%d)", packet.stream_index);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
if ( ! zm_receive_frame( streams[packet.stream_index].context, frame, packet ) ) {
|
||||||
AVCodecContext *context = streams[packet.stream_index].context;
|
Error("Unable to get frame %d, continuing", streams[packet.stream_index].frame_count);
|
||||||
|
|
||||||
ret = avcodec_send_packet( context, &packet );
|
|
||||||
if ( ret < 0 ) {
|
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
|
||||||
Error( "Unable to send packet at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
|
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "Success getting a packet");
|
Debug(1, "Success getting a packet at frame (%d)", streams[packet.stream_index].frame_count);
|
||||||
|
streams[packet.stream_index].frame_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
zm_av_packet_unref( &packet );
|
||||||
if ( hwaccel ) {
|
|
||||||
ret = avcodec_receive_frame( context, hwFrame );
|
|
||||||
if ( ret < 0 ) {
|
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
|
||||||
Error( "Unable to receive frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
|
|
||||||
zm_av_packet_unref( &packet );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = av_hwframe_transfer_data(frame, hwFrame, 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
|
||||||
Error( "Unable to transfer frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
|
|
||||||
zm_av_packet_unref( &packet );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
Debug(1,"Getting a frame?");
|
|
||||||
ret = avcodec_receive_frame( context, frame );
|
|
||||||
if ( ret < 0 ) {
|
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
|
||||||
Error( "Unable to send packet at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
|
|
||||||
zm_av_packet_unref( &packet );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
if ( frame_number == -1 )
|
||||||
}
|
break;
|
||||||
#endif
|
} // end while frame_number > streams.frame_count
|
||||||
|
|
||||||
frameComplete = 1;
|
|
||||||
# else
|
|
||||||
ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet );
|
|
||||||
if ( ret < 0 ) {
|
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
|
||||||
Error( "Unable to decode frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
|
|
||||||
zm_av_packet_unref( &packet );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} // end if it's the right stream
|
|
||||||
|
|
||||||
zm_av_packet_unref( &packet );
|
|
||||||
|
|
||||||
} // end while ! frameComplete
|
|
||||||
return frame;
|
return frame;
|
||||||
|
|
||||||
} // end AVFrame *FFmpeg_Input::get_frame
|
} // end AVFrame *FFmpeg_Input::get_frame
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class FFmpeg_Input {
|
||||||
|
|
||||||
int Open( const char *filename );
|
int Open( const char *filename );
|
||||||
int Close();
|
int Close();
|
||||||
AVFrame *get_frame( int stream_id=-1 );
|
AVFrame *get_frame( int stream_id=-1, int frame_number=-1 );
|
||||||
int get_video_stream_id() {
|
int get_video_stream_id() {
|
||||||
return video_stream_id;
|
return video_stream_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ bool Monitor::Analyse() {
|
||||||
|
|
||||||
// if have event, sent frames until we find a video packet, at which point do analysis. Adaptive skip should only affect which frames we do analysis on.
|
// if have event, sent frames until we find a video packet, at which point do analysis. Adaptive skip should only affect which frames we do analysis on.
|
||||||
|
|
||||||
int skip_index = 0;
|
unsigned int skip_index = 0;
|
||||||
|
|
||||||
if ( adaptive_skip ) {
|
if ( adaptive_skip ) {
|
||||||
int read_margin = shared_data->last_read_index - shared_data->last_write_index;
|
int read_margin = shared_data->last_read_index - shared_data->last_write_index;
|
||||||
|
@ -1295,6 +1295,7 @@ bool Monitor::Analyse() {
|
||||||
|
|
||||||
Debug(3, "Motion detection is enabled signal(%d) signal_change(%d)", signal, signal_change);
|
Debug(3, "Motion detection is enabled signal(%d) signal_change(%d)", signal, signal_change);
|
||||||
|
|
||||||
|
// if we have been told to be OFF, then we are off and don't do any processing.
|
||||||
if ( trigger_data->trigger_state != TRIGGER_OFF ) {
|
if ( trigger_data->trigger_state != TRIGGER_OFF ) {
|
||||||
Debug(4, "Trigger not oFF state is (%d)", trigger_data->trigger_state );
|
Debug(4, "Trigger not oFF state is (%d)", trigger_data->trigger_state );
|
||||||
unsigned int score = 0;
|
unsigned int score = 0;
|
||||||
|
@ -1304,8 +1305,8 @@ Debug(4, "Ready");
|
||||||
std::string cause;
|
std::string cause;
|
||||||
Event::StringSetMap noteSetMap;
|
Event::StringSetMap noteSetMap;
|
||||||
|
|
||||||
|
// Specifically told to be on. Setting the score here will trigger the alarm.
|
||||||
if ( trigger_data->trigger_state == TRIGGER_ON ) {
|
if ( trigger_data->trigger_state == TRIGGER_ON ) {
|
||||||
|
|
||||||
score += trigger_data->trigger_score;
|
score += trigger_data->trigger_score;
|
||||||
if ( !event ) {
|
if ( !event ) {
|
||||||
if ( cause.length() )
|
if ( cause.length() )
|
||||||
|
@ -1372,7 +1373,6 @@ Debug(3,"before DetectMotion");
|
||||||
|
|
||||||
// If we aren't recording, check linked monitors to see if we should be.
|
// If we aren't recording, check linked monitors to see if we should be.
|
||||||
if ( (!(signal_change && signal)) && (n_linked_monitors > 0) ) {
|
if ( (!(signal_change && signal)) && (n_linked_monitors > 0) ) {
|
||||||
bool first_link = true;
|
|
||||||
Event::StringSet noteSet;
|
Event::StringSet noteSet;
|
||||||
for ( int i=0; i < n_linked_monitors; i++ ) {
|
for ( int i=0; i < n_linked_monitors; i++ ) {
|
||||||
if ( ! linked_monitors[i]->isConnected() )
|
if ( ! linked_monitors[i]->isConnected() )
|
||||||
|
@ -1434,6 +1434,7 @@ Debug(3,"before DetectMotion");
|
||||||
}
|
}
|
||||||
} // end if ! event
|
} // end if ! event
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( score ) {
|
if ( score ) {
|
||||||
Debug(9, "Score: (%d)", score );
|
Debug(9, "Score: (%d)", score );
|
||||||
if ( (state == IDLE || state == TAPE || state == PREALARM ) ) {
|
if ( (state == IDLE || state == TAPE || state == PREALARM ) ) {
|
||||||
|
@ -1488,7 +1489,7 @@ Debug(3, "creating new event");
|
||||||
if ( pre_event_images ) {
|
if ( pre_event_images ) {
|
||||||
Debug(2,"Have pre_event_image");
|
Debug(2,"Have pre_event_image");
|
||||||
if ( analysis_fps ) {
|
if ( analysis_fps ) {
|
||||||
Debug(2,"Have analysis_fps");
|
Debug(2,"Have analysis_fps");
|
||||||
for ( int i = 0; i < pre_event_images; i++ ) {
|
for ( int i = 0; i < pre_event_images; i++ ) {
|
||||||
timestamps[i] = &pre_event_buffer[pre_index].timestamp;
|
timestamps[i] = &pre_event_buffer[pre_index].timestamp;
|
||||||
images[i] = pre_event_buffer[pre_index].image;
|
images[i] = pre_event_buffer[pre_index].image;
|
||||||
|
@ -1520,7 +1521,7 @@ Debug(3, "creating new event");
|
||||||
shared_data->state = state = ALARM;
|
shared_data->state = state = ALARM;
|
||||||
}
|
}
|
||||||
last_alarm_count = image_count;
|
last_alarm_count = image_count;
|
||||||
} else {
|
} else { // no score?
|
||||||
if ( state == ALARM ) {
|
if ( state == ALARM ) {
|
||||||
Info( "%s: %03d - Gone into alert state", name, image_count );
|
Info( "%s: %03d - Gone into alert state", name, image_count );
|
||||||
shared_data->state = state = ALERT;
|
shared_data->state = state = ALERT;
|
||||||
|
@ -1536,17 +1537,14 @@ Debug(3, "creating new event");
|
||||||
shared_data->state = state = TAPE;
|
shared_data->state = state = TAPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if ( state == PREALARM ) {
|
||||||
if ( state == PREALARM ) {
|
// Back to IDLE
|
||||||
if ( function != MOCORD ) {
|
shared_data->state = state = function != MOCORD ? IDLE : TAPE;
|
||||||
shared_data->state = state = IDLE;
|
|
||||||
} else {
|
|
||||||
shared_data->state = state = TAPE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( Event::PreAlarmCount() )
|
if ( Event::PreAlarmCount() )
|
||||||
Event::EmptyPreAlarmFrames();
|
Event::EmptyPreAlarmFrames();
|
||||||
}
|
} // end if score or not
|
||||||
|
|
||||||
if ( state != IDLE ) {
|
if ( state != IDLE ) {
|
||||||
if ( state == PREALARM || state == ALARM ) {
|
if ( state == PREALARM || state == ALARM ) {
|
||||||
if ( config.create_analysis_images ) {
|
if ( config.create_analysis_images ) {
|
||||||
|
@ -1565,6 +1563,7 @@ Debug(3, "creating new event");
|
||||||
}
|
}
|
||||||
if ( got_anal_image ) {
|
if ( got_anal_image ) {
|
||||||
if ( state == PREALARM )
|
if ( state == PREALARM )
|
||||||
|
// AddPreAlarmFrame just copies/buffers these frames in the event. If we go back to idle, we will drop them.
|
||||||
Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image );
|
Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image );
|
||||||
else
|
else
|
||||||
//event->AddFrame( snap_image, *timestamp, score, &alarm_image );
|
//event->AddFrame( snap_image, *timestamp, score, &alarm_image );
|
||||||
|
@ -1593,23 +1592,17 @@ Debug(3, "creating new event");
|
||||||
if ( event && noteSetMap.size() > 0 )
|
if ( event && noteSetMap.size() > 0 )
|
||||||
event->updateNotes( noteSetMap );
|
event->updateNotes( noteSetMap );
|
||||||
} else if ( state == ALERT ) {
|
} else if ( state == ALERT ) {
|
||||||
event->AddFrame( snap_image, *timestamp );
|
// Alert means this frame has no motion, but we were alarmed and are still recording.
|
||||||
|
event->AddPacket( snap );
|
||||||
if ( noteSetMap.size() > 0 )
|
if ( noteSetMap.size() > 0 )
|
||||||
event->updateNotes( noteSetMap );
|
event->updateNotes( noteSetMap );
|
||||||
} else if ( state == TAPE ) {
|
} else if ( state == TAPE ) {
|
||||||
//Video Storage: activate only for supported cameras. Event::AddFrame knows whether or not we are recording video and saves frames accordingly
|
|
||||||
//if((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo()) {
|
|
||||||
// I don't think this is required, and causes problems, as the event file hasn't been setup yet.
|
|
||||||
//Warning("In state TAPE,
|
|
||||||
//video_store_data->recording = event->StartTime();
|
|
||||||
//}
|
|
||||||
if ( !(image_count%(frame_skip+1)) ) {
|
if ( !(image_count%(frame_skip+1)) ) {
|
||||||
if ( config.bulk_frame_interval > 1 ) {
|
if ( config.bulk_frame_interval > 1 ) {
|
||||||
event->AddPacket( snap, (event->Frames()<pre_event_count?0:-1) );
|
event->AddPacket( snap, (event->Frames()<pre_event_count?0:-1) );
|
||||||
//event->AddFrame( snap_image, *timestamp, (event->Frames()<pre_event_count?0:-1) );
|
|
||||||
} else {
|
} else {
|
||||||
//event->AddFrame( snap_image, *timestamp );
|
event->AddPacket( snap );
|
||||||
event->AddPacket( snap );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,7 +285,7 @@ protected:
|
||||||
int ready_count;
|
int ready_count;
|
||||||
int first_alarm_count;
|
int first_alarm_count;
|
||||||
int last_alarm_count;
|
int last_alarm_count;
|
||||||
static bool last_signal;
|
bool last_signal;
|
||||||
int buffer_count;
|
int buffer_count;
|
||||||
int prealarm_count;
|
int prealarm_count;
|
||||||
State state;
|
State state;
|
||||||
|
@ -294,7 +294,6 @@ protected:
|
||||||
time_t last_analysis_fps_time;
|
time_t last_analysis_fps_time;
|
||||||
time_t auto_resume_time;
|
time_t auto_resume_time;
|
||||||
unsigned int last_motion_score;
|
unsigned int last_motion_score;
|
||||||
bool last_signal;
|
|
||||||
|
|
||||||
EventCloseMode event_close_mode;
|
EventCloseMode event_close_mode;
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug( 1, "Attempting to authenticate user from auth string '%s'", auth );
|
Debug( 1, "Attempting to authenticate user from auth string '%s', remote addr(%s)", auth, remote_addr );
|
||||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||||
snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" );
|
snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" );
|
||||||
|
|
||||||
|
@ -170,6 +170,17 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getting the time is expensive, so only do it once.
|
||||||
|
time_t now = time( 0 );
|
||||||
|
unsigned int hours = config.auth_hash_ttl;
|
||||||
|
|
||||||
|
if ( ! hours ) {
|
||||||
|
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
||||||
|
hours = 2;
|
||||||
|
} else {
|
||||||
|
Debug( 1, "AUTH_HASH_TTL is %d, time is %d", hours, now );
|
||||||
|
}
|
||||||
|
|
||||||
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) {
|
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) {
|
||||||
const char *user = dbrow[0];
|
const char *user = dbrow[0];
|
||||||
const char *pass = dbrow[1];
|
const char *pass = dbrow[1];
|
||||||
|
@ -179,18 +190,9 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
size_t md5len = 16;
|
size_t md5len = 16;
|
||||||
unsigned char md5sum[md5len];
|
unsigned char md5sum[md5len];
|
||||||
|
|
||||||
time_t now = time( 0 );
|
time_t now_copy = now;
|
||||||
unsigned int hours = config.auth_hash_ttl;
|
for ( unsigned int i = 0; i < hours; i++, now_copy -= 3600 ) {
|
||||||
|
struct tm *now_tm = localtime(&now_copy);
|
||||||
if ( ! hours ) {
|
|
||||||
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
|
||||||
hours = 2;
|
|
||||||
} else {
|
|
||||||
Debug( 1, "AUTH_HASH_TTL is %d", hours );
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < hours; i++, now -= 3600 ) {
|
|
||||||
struct tm *now_tm = localtime( &now );
|
|
||||||
|
|
||||||
snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
|
snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
|
||||||
config.auth_hash_secret,
|
config.auth_hash_secret,
|
||||||
|
@ -221,11 +223,10 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
||||||
mysql_free_result( result );
|
mysql_free_result( result );
|
||||||
return( user );
|
return( user );
|
||||||
} else {
|
|
||||||
Debug(1, "No match for %s", auth );
|
|
||||||
}
|
}
|
||||||
}
|
} // end foreach hours
|
||||||
}
|
} // end foreach user
|
||||||
|
Debug(1, "No match for %s", auth );
|
||||||
mysql_free_result( result );
|
mysql_free_result( result );
|
||||||
#else // HAVE_DECL_MD5
|
#else // HAVE_DECL_MD5
|
||||||
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
||||||
|
|
|
@ -28,13 +28,13 @@ if ( version_compare( phpversion(), '4.3.0', '<') ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
# We are requiring these because this file is getting included from the api, which hasn't already included them.
|
# We are requiring these because this file is getting included from the api, which hasn't already included them.
|
||||||
require_once( 'logger.php' );
|
require_once('logger.php');
|
||||||
require_once( 'database.php' );
|
require_once('database.php');
|
||||||
|
|
||||||
function userLogin( $username, $password='', $passwordHashed=false ) {
|
function userLogin( $username, $password='', $passwordHashed=false ) {
|
||||||
global $user, $cookies;
|
global $user, $cookies;
|
||||||
|
|
||||||
$sql = 'SELECT * FROM Users WHERE Enabled = 1';
|
$sql = 'SELECT * FROM Users WHERE Enabled=1';
|
||||||
$sql_values = NULL;
|
$sql_values = NULL;
|
||||||
if ( ZM_AUTH_TYPE == 'builtin' ) {
|
if ( ZM_AUTH_TYPE == 'builtin' ) {
|
||||||
if ( $passwordHashed ) {
|
if ( $passwordHashed ) {
|
||||||
|
@ -44,7 +44,7 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
|
||||||
}
|
}
|
||||||
$sql_values = array( $username, $password );
|
$sql_values = array( $username, $password );
|
||||||
} else {
|
} else {
|
||||||
$sql .= ' AND Username = ?';
|
$sql .= ' AND Username=?';
|
||||||
$sql_values = array( $username );
|
$sql_values = array( $username );
|
||||||
}
|
}
|
||||||
$_SESSION['username'] = $username;
|
$_SESSION['username'] = $username;
|
||||||
|
@ -138,26 +138,27 @@ function getAuthUser( $auth ) {
|
||||||
$authHash = md5( $authKey );
|
$authHash = md5( $authKey );
|
||||||
|
|
||||||
if ( $auth == $authHash ) {
|
if ( $auth == $authHash ) {
|
||||||
return( $user );
|
return $user;
|
||||||
}
|
}
|
||||||
} // end foreach hour
|
} // end foreach hour
|
||||||
} // end foreach user
|
} // end foreach user
|
||||||
} // end if using auth hash
|
} // end if using auth hash
|
||||||
Error( "Unable to authenticate user from auth hash '$auth'" );
|
Error( "Unable to authenticate user from auth hash '$auth'" );
|
||||||
return( false );
|
return( false );
|
||||||
}
|
} // end getAuthUser($auth)
|
||||||
|
|
||||||
function generateAuthHash( $useRemoteAddr ) {
|
function generateAuthHash( $useRemoteAddr ) {
|
||||||
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
|
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
|
||||||
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
|
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
|
||||||
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < time() - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) {
|
$time = time();
|
||||||
|
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < ( $time - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) ) {
|
||||||
# Don't both regenerating Auth Hash if an hour hasn't gone by yet
|
# Don't both regenerating Auth Hash if an hour hasn't gone by yet
|
||||||
$time = localtime();
|
$local_time = localtime();
|
||||||
$authKey = '';
|
$authKey = '';
|
||||||
if ( $useRemoteAddr ) {
|
if ( $useRemoteAddr ) {
|
||||||
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5];
|
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
|
||||||
} else {
|
} else {
|
||||||
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5];
|
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
|
||||||
}
|
}
|
||||||
$auth = md5( $authKey );
|
$auth = md5( $authKey );
|
||||||
if ( session_status() == PHP_SESSION_NONE ) {
|
if ( session_status() == PHP_SESSION_NONE ) {
|
||||||
|
@ -167,10 +168,10 @@ function generateAuthHash( $useRemoteAddr ) {
|
||||||
Warning("Session is not active. AuthHash will not be cached. called from $file:$line");
|
Warning("Session is not active. AuthHash will not be cached. called from $file:$line");
|
||||||
}
|
}
|
||||||
$_SESSION['AuthHash'] = $auth;
|
$_SESSION['AuthHash'] = $auth;
|
||||||
$_SESSION['AuthHashGeneratedAt'] = time();
|
$_SESSION['AuthHashGeneratedAt'] = $time;
|
||||||
Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
|
Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
|
||||||
} else {
|
} else {
|
||||||
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] );
|
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] ." beacuse " . $_SESSION['AuthHashGeneratedAt'] . ' < '. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '.( $time - (ZM_AUTH_HASH_TTL * 1800) ));
|
||||||
} # end if AuthHash is not cached
|
} # end if AuthHash is not cached
|
||||||
return $_SESSION['AuthHash'];
|
return $_SESSION['AuthHash'];
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue