Merge branch 'feature-h264-videostorage' into storageareas

This commit is contained in:
Isaac Connor committed 2016-06-21 13:48:32 -04:00
commit e29a0ebe71
25 files changed
+1139 -1147

No files matched your search

+1
View File
@@ -266,4 +266,5 @@ if ( $concat_name ) {
#unlink $input_file_list;
#print( STDOUT $event->{MonitorId}.'/'.$event->{Id}.'/'.$video_file."\n" );
#print( STDOUT $event_path . '/' . $video_file ."\n" );
#print( STDOUT $video_file."\n" );
exit( 0 );
+2 -3
View File
@@ -32,7 +32,7 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co
colour( p_colour ),
contrast( p_contrast ),
capture( p_capture ),
record_audio( p_record_audio )
record_audio( p_record_audio )
{
pixels = width * height;
imagesize = pixels * colours;
@@ -47,8 +47,7 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co
}
}
Camera::~Camera()
{
Camera::~Camera() {
}
Monitor *Camera::getMonitor() {
+2 -2
View File
@@ -80,9 +80,9 @@ public:
virtual int Contrast( int/*p_contrast*/=-1 ) { return( -1 ); }
bool CanCapture() const { return( capture ); }
bool SupportsNativeVideo() const { return( (type == FFMPEG_SRC )||(type == REMOTE_SRC)); }
virtual int PrimeCapture() { return( 0 ); }
virtual int PreCapture()=0;
virtual int Capture( Image &image )=0;
+21 -40
View File
@@ -31,27 +31,23 @@ size_t content_length_match_len;
size_t content_type_match_len;
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
{
if ( capture )
{
if ( capture ) {
Initialise();
}
}
cURLCamera::~cURLCamera()
{
if ( capture )
{
cURLCamera::~cURLCamera() {
if ( capture ) {
Terminate();
}
}
void cURLCamera::Initialise()
{
void cURLCamera::Initialise() {
content_length_match_len = strlen(content_length_match);
content_type_match_len = strlen(content_type_match);
@@ -88,8 +84,7 @@ void cURLCamera::Initialise()
}
}
void cURLCamera::Terminate()
{
void cURLCamera::Terminate() {
/* Signal the thread to terminate */
bTerminate = true;
@@ -108,20 +103,17 @@ void cURLCamera::Terminate()
}
int cURLCamera::PrimeCapture()
{
int cURLCamera::PrimeCapture() {
//Info( "Priming capture from %s", mPath.c_str() );
return 0;
}
int cURLCamera::PreCapture()
{
int cURLCamera::PreCapture() {
// Nothing to do here
return( 0 );
}
int cURLCamera::Capture( Image &image )
{
int cURLCamera::Capture( Image &image ) {
bool frameComplete = false;
/* MODE_STREAM specific variables */
@@ -305,22 +297,19 @@ int cURLCamera::Capture( Image &image )
return 0;
}
int cURLCamera::PostCapture()
{
int cURLCamera::PostCapture() {
// Nothing to do here
return( 0 );
}
int cURLCamera::CaptureAndRecord( Image &image, bool recording, char* event_directory )
{
int cURLCamera::CaptureAndRecord( Image &image, bool recording, char* event_directory ) {
Error("Capture and Record not implemented for the cURL camera type");
// Nothing to do here
return( 0 );
// Nothing to do here
return( 0 );
}
size_t cURLCamera::data_callback(void *buffer, size_t size, size_t nmemb, void *userdata)
{
size_t cURLCamera::data_callback(void *buffer, size_t size, size_t nmemb, void *userdata) {
lock();
/* Append the data we just received to our buffer */
@@ -341,8 +330,7 @@ size_t cURLCamera::data_callback(void *buffer, size_t size, size_t nmemb, void *
size_t cURLCamera::header_callback( void *buffer, size_t size, size_t nmemb, void *userdata)
{
size_t cURLCamera::header_callback( void *buffer, size_t size, size_t nmemb, void *userdata) {
std::string header;
header.assign((const char*)buffer, size*nmemb);
@@ -382,8 +370,7 @@ size_t cURLCamera::header_callback( void *buffer, size_t size, size_t nmemb, voi
return size*nmemb;
}
void* cURLCamera::thread_func()
{
void* cURLCamera::thread_func() {
long tRet;
double dSize;
@@ -529,8 +516,7 @@ int cURLCamera::unlock() {
return nRet;
}
int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
/* Signal the curl thread to terminate */
if(bTerminate)
return -10;
@@ -539,18 +525,15 @@ int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow,
}
/* These functions call the functions in the class for the correct object */
size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata)
{
size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata);
}
size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata)
{
size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata);
}
int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
}
@@ -558,6 +541,4 @@ void* thread_func_dispatcher(void* object) {
return ((cURLCamera*)object)->thread_func();
}
#endif // HAVE_LIBCURL
+2 -4
View File
@@ -39,8 +39,7 @@
// Class representing 'curl' cameras, i.e. those which are
// accessed using the curl library
//
class cURLCamera : public Camera
{
class cURLCamera : public Camera {
protected:
typedef enum {MODE_UNSET, MODE_SINGLE, MODE_STREAM} mode_t;
@@ -79,8 +78,7 @@ public:
int PreCapture();
int Capture( Image &image );
int PostCapture();
int CaptureAndRecord( Image &image, bool recording, char* event_directory);
int CaptureAndRecord( Image &image, bool recording, char* event_directory);
size_t data_callback(void *buffer, size_t size, size_t nmemb, void *userdata);
size_t header_callback(void *buffer, size_t size, size_t nmemb, void *userdata);
+135 -284
View File
@@ -74,8 +74,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
createNotes( notes );
bool untimedEvent = false;
if ( !start_time.tv_sec )
{
if ( !start_time.tv_sec ) {
untimedEvent = true;
gettimeofday( &start_time, 0 );
}
@@ -86,14 +85,12 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
struct tm *stime = localtime( &start_time.tv_sec );
snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, Videoed ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d )", monitor->Id(), storage->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str(), videoEvent );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert event: %s. sql was (%s)", mysql_error( &dbconn ), sql );
exit( mysql_errno( &dbconn ) );
}
id = mysql_insert_id( &dbconn );
if ( untimedEvent )
{
if ( untimedEvent ) {
Warning( "Event %d has zero time, setting to current", id );
}
end_time.tv_sec = 0;
@@ -102,8 +99,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
tot_score = 0;
max_score = 0;
if ( config.use_deep_storage )
{
if ( config.use_deep_storage ) {
char *path_ptr = path;
path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", storage->Path(), monitor->Id() );
@@ -118,17 +114,14 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
char date_path[PATH_MAX] = "";
char time_path[PATH_MAX] = "";
char *time_path_ptr = time_path;
for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ )
{
for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) {
path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] );
struct stat statbuf;
errno = 0;
if ( stat( path, &statbuf ) ) {
if ( errno == ENOENT || errno == ENOTDIR )
{
if ( mkdir( path, 0755 ) )
{
if ( errno == ENOENT || errno == ENOTDIR ) {
if ( mkdir( path, 0755 ) ) {
Fatal( "Can't mkdir %s: %s", path, strerror(errno));
}
} else {
@@ -151,18 +144,14 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
fclose( id_fp );
else
Fatal( "Can't fopen %s: %s", id_file, strerror(errno));
}
else
{
} else {
snprintf( path, sizeof(path), "%s/%d/%d", storage->Path(), monitor->Id(), id );
struct stat statbuf;
errno = 0;
stat( path, &statbuf );
if ( errno == ENOENT || errno == ENOTDIR )
{
if ( mkdir( path, 0755 ) )
{
if ( errno == ENOENT || errno == ENOTDIR ) {
if ( mkdir( path, 0755 ) ) {
Error( "Can't mkdir %s: %s", path, strerror(errno));
}
}
@@ -187,7 +176,6 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
snprintf( timecodes_name, sizeof(timecodes_name), "%d-%s", id, "video.timecodes" );
snprintf( timecodes_file, sizeof(timecodes_file), video_file_format, path, timecodes_name );
/* X264 MP4 video writer */
if(monitor->GetOptVideoWriter() == 1) {
#if ZM_HAVE_VIDEOWRITER_X264MP4
@@ -220,18 +208,15 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
}
Event::~Event()
{
if ( frames > last_db_frame )
{
Event::~Event() {
if ( frames > last_db_frame ) {
struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 );
Debug( 1, "Adding closing frame %d to DB", frames );
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -266,16 +251,13 @@ Event::~Event()
}
}
void Event::createNotes( std::string &notes )
{
void Event::createNotes( std::string &notes ) {
notes.clear();
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ )
{
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) {
notes += mapIter->first;
notes += ": ";
const StringSet &stringSet = mapIter->second;
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ )
{
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) {
if ( setIter != stringSet.begin() )
notes += ", ";
notes += *setIter;
@@ -285,25 +267,20 @@ void Event::createNotes( std::string &notes )
int Event::sd = -1;
bool Event::OpenFrameSocket( int monitor_id )
{
if ( sd > 0 )
{
bool Event::OpenFrameSocket( int monitor_id ) {
if ( sd > 0 ) {
close( sd );
}
sd = socket( AF_UNIX, SOCK_STREAM, 0);
if ( sd < 0 )
{
if ( sd < 0 ) {
Error( "Can't create socket: %s", strerror(errno) );
return( false );
}
int socket_buffer_size = config.frame_socket_size;
if ( socket_buffer_size > 0 )
{
if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 )
{
if ( socket_buffer_size > 0 ) {
if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 ) {
Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) );
close( sd );
sd = -1;
@@ -312,16 +289,14 @@ bool Event::OpenFrameSocket( int monitor_id )
}
int flags;
if ( (flags = fcntl( sd, F_GETFL )) < 0 )
{
if ( (flags = fcntl( sd, F_GETFL )) < 0 ) {
Error( "Can't get socket flags, error = %s", strerror(errno) );
close( sd );
sd = -1;
return( false );
}
flags |= O_NONBLOCK;
if ( fcntl( sd, F_SETFL, flags ) < 0 )
{
if ( fcntl( sd, F_SETFL, flags ) < 0 ) {
Error( "Can't set socket flags, error = %s", strerror(errno) );
close( sd );
sd = -1;
@@ -336,8 +311,7 @@ bool Event::OpenFrameSocket( int monitor_id )
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
addr.sun_family = AF_UNIX;
if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)+1) < 0 )
{
if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)+1) < 0 ) {
Warning( "Can't connect to frame server: %s", strerror(errno) );
close( sd );
sd = -1;
@@ -348,19 +322,15 @@ bool Event::OpenFrameSocket( int monitor_id )
return( true );
}
bool Event::ValidateFrameSocket( int monitor_id )
{
if ( sd < 0 )
{
bool Event::ValidateFrameSocket( int monitor_id ) {
if ( sd < 0 ) {
return( OpenFrameSocket( monitor_id ) );
}
return( true );
}
bool Event::SendFrameImage( const Image *image, bool alarm_frame )
{
if ( !ValidateFrameSocket( monitor->Id() ) )
{
bool Event::SendFrameImage( const Image *image, bool alarm_frame ) {
if ( !ValidateFrameSocket( monitor->Id() ) ) {
return( false );
}
@@ -386,23 +356,16 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame )
ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size;
ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs));
if ( writev_result != writev_size )
{
if ( writev_result < 0 )
{
if ( errno == EAGAIN )
{
if ( writev_result != writev_size ) {
if ( writev_result < 0 ) {
if ( errno == EAGAIN ) {
Warning( "Blocking write detected" );
}
else
{
} else {
Error( "Can't write frame: %s", strerror(errno) );
close( sd );
sd = -1;
}
}
else
{
} else {
Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size );
close( sd );
sd = -1;
@@ -414,8 +377,7 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame )
return( true );
}
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame )
{
bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) {
Image* ImgToWrite;
Image* ts_image = NULL;
@@ -424,12 +386,10 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char
ts_image = new Image(*image);
monitor->TimestampImage( ts_image, &timestamp );
ImgToWrite=ts_image;
}
else
} else
ImgToWrite=image;
if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) )
{
if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) ) {
int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default
ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write
}
@@ -437,8 +397,7 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char
return( true );
}
bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow )
{
bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow ) {
const Image* frameimg = image;
Image ts_image;
@@ -471,56 +430,43 @@ bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp,
return( true );
}
void Event::updateNotes( const StringSetMap &newNoteSetMap )
{
void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
bool update = false;
//Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() );
if ( newNoteSetMap.size() > 0 )
{
if ( noteSetMap.size() == 0 )
{
if ( newNoteSetMap.size() > 0 ) {
if ( noteSetMap.size() == 0 ) {
noteSetMap = newNoteSetMap;
update = true;
}
else
{
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ )
{
} else {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) {
const std::string &newNoteGroup = newNoteSetMapIter->first;
const StringSet &newNoteSet = newNoteSetMapIter->second;
//Info( "Got %d new strings", newNoteSet.size() );
if ( newNoteSet.size() > 0 )
{
if ( newNoteSet.size() > 0 ) {
StringSetMap::iterator noteSetMapIter = noteSetMap.find( newNoteGroup );
if ( noteSetMapIter == noteSetMap.end() )
{
if ( noteSetMapIter == noteSetMap.end() ) {
//Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() );
noteSetMap.insert( StringSetMap::value_type( newNoteGroup, newNoteSet ) );
update = true;
}
else
{
} else {
StringSet &noteSet = noteSetMapIter->second;
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() );
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ )
{
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) {
const std::string &newNote = *newNoteSetIter;
StringSet::iterator noteSetIter = noteSet.find( newNote );
if ( noteSetIter == noteSet.end() )
{
if ( noteSetIter == noteSet.end() ) {
noteSet.insert( newNote );
update = true;
}
}
}
}
}
}
}
} // end for
} // end if ( noteSetMap.size() == 0
} // end if newNoteSetupMap.size() > 0
if ( update )
{
if ( update ) {
std::string notes;
createNotes( notes );
@@ -532,19 +478,16 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
char notesStr[ZM_SQL_MED_BUFSIZ] = "";
unsigned long notesLen = 0;
if ( !stmt )
{
if ( !stmt ) {
const char *sql = "update Events set Notes = ? where Id = ?";
stmt = mysql_stmt_init( &dbconn );
if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) )
{
if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) ) {
Fatal( "Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt) );
}
/* Get the parameter count from the statement */
if ( mysql_stmt_param_count( stmt ) != 2 )
{
if ( mysql_stmt_param_count( stmt ) != 2 ) {
Fatal( "Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count( stmt ), sql );
}
@@ -564,8 +507,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
bind[1].length= 0;
/* Bind the buffers */
if ( mysql_stmt_bind_param( stmt, bind ) )
{
if ( mysql_stmt_bind_param( stmt, bind ) ) {
Fatal( "Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt) );
}
}
@@ -573,8 +515,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
strncpy( notesStr, notes.c_str(), sizeof(notesStr) );
notesLen = notes.length();
if ( mysql_stmt_execute( stmt ) )
{
if ( mysql_stmt_execute( stmt ) ) {
Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) );
}
#else
@@ -583,30 +524,25 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap )
mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() );
snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert event: %s", mysql_error( &dbconn ) );
}
#endif
}
}
void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps )
{
void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps ) {
for (int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE) {
AddFramesInternal(n_frames, i, images, timestamps);
}
}
void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps )
{
void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ) {
static char sql[ZM_SQL_LGE_BUFSIZ];
strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) );
int frameCount = 0;
for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ )
{
if ( !timestamps[i]->tv_sec )
{
for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ ) {
if ( !timestamps[i]->tv_sec ) {
Debug( 1, "Not adding pre-capture frame %d, zero timestamp", i );
continue;
}
@@ -640,27 +576,21 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
frameCount++;
}
if ( frameCount )
{
if ( frameCount ) {
Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames );
*(sql+strlen(sql)-2) = '\0';
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frames: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
last_db_frame = frames;
}
else
{
} else {
Debug( 1, "No valid pre-capture frames to add" );
}
}
void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image )
{
if ( !timestamp.tv_sec )
{
void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image ) {
if ( !timestamp.tv_sec ) {
Debug( 1, "Not adding new frame, zero timestamp" );
return;
}
@@ -694,25 +624,21 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
score = 0;
bool db_frame = (strcmp(frame_type,"Bulk") != 0) || ((frames%config.bulk_frame_interval)==0) || !frames;
if ( db_frame )
{
if ( db_frame ) {
Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, frame_type );
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type, timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
last_db_frame = frames;
// We are writing a Bulk frame
if ( !strcmp( frame_type,"Bulk") )
{
if ( !strcmp( frame_type,"Bulk") ) {
snprintf( sql, sizeof(sql), "update Events set Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't update event: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -722,16 +648,14 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *
end_time = timestamp;
// We are writing an Alarm frame
if ( !strcmp( frame_type,"Alarm") )
{
if ( !strcmp( frame_type,"Alarm") ) {
alarm_frames++;
tot_score += score;
if ( score > (int)max_score )
max_score = score;
if ( alarm_image )
{
if ( alarm_image ) {
snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames );
Debug( 1, "Writing analysis frame %d", frames );
@@ -798,15 +722,13 @@ bool EventStream::loadInitialEventData( int monitor_id, time_t event_time )
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_ROW dbrow = mysql_fetch_row( result );
if ( mysql_errno( &dbconn ) )
{
if ( mysql_errno( &dbconn ) ) {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -817,17 +739,13 @@ bool EventStream::loadInitialEventData( int monitor_id, time_t event_time )
loadEventData( init_event_id );
if ( event_time )
{
if ( event_time ) {
curr_stream_time = event_time;
curr_frame_id = 1;
if ( event_time >= event_data->start_time )
{
for (unsigned int i = 0; i < event_data->frame_count; i++ )
{
if ( event_time >= event_data->start_time ) {
for (unsigned int i = 0; i < event_data->frame_count; i++ ) {
//Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time );
if ( event_data->frames[i].timestamp >= event_time )
{
if ( event_data->frames[i].timestamp >= event_time ) {
curr_frame_id = i+1;
Debug( 3, "Set cst:%.2f", curr_stream_time );
Debug( 3, "Set cfid:%d", curr_frame_id );
@@ -840,51 +758,42 @@ bool EventStream::loadInitialEventData( int monitor_id, time_t event_time )
return( true );
}
bool EventStream::loadInitialEventData( int init_event_id, unsigned int init_frame_id )
{
bool EventStream::loadInitialEventData( int init_event_id, unsigned int init_frame_id ) {
loadEventData( init_event_id );
if ( init_frame_id )
{
if ( init_frame_id ) {
curr_stream_time = event_data->frames[init_frame_id-1].timestamp;
curr_frame_id = init_frame_id;
}
else
{
} else {
curr_stream_time = event_data->start_time;
}
return( true );
}
bool EventStream::loadEventData( int event_id )
{
bool EventStream::loadEventData( int event_id ) {
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "select M.Id, M.Name, E.StorageId, E.Frames, unix_timestamp( StartTime ) as StartTimestamp, max(F.Delta)-min(F.Delta) as Duration,E.DefaultVideo from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id", event_id );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
if ( !mysql_num_rows( result ) )
{
if ( !mysql_num_rows( result ) ) {
Fatal( "Unable to load event %d, not found in DB", event_id );
}
MYSQL_ROW dbrow = mysql_fetch_row( result );
if ( mysql_errno( &dbconn ) )
{
if ( mysql_errno( &dbconn ) ) {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -899,16 +808,13 @@ bool EventStream::loadEventData( int event_id )
Storage * storage = new Storage( event_data->storage_id );
const char *storage_path = storage->Path();
if ( config.use_deep_storage )
{
if ( config.use_deep_storage ) {
struct tm *event_time = localtime( &event_data->start_time );
if ( storage_path[0] == '/' )
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
else
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
}
else
{
} else {
if ( storage_path[0] == '/' )
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", storage_path, event_data->monitor_id, event_data->event_id );
else
@@ -923,15 +829,13 @@ bool EventStream::loadEventData( int event_id )
mysql_free_result( result );
snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -942,17 +846,14 @@ bool EventStream::loadEventData( int event_id )
int id, last_id = 0;
time_t timestamp, last_timestamp = event_data->start_time;
double delta, last_delta = 0.0;
while ( ( dbrow = mysql_fetch_row( result ) ) )
{
while ( ( dbrow = mysql_fetch_row( result ) ) ) {
id = atoi(dbrow[0]);
timestamp = atoi(dbrow[1]);
delta = atof(dbrow[2]);
int id_diff = id - last_id;
double frame_delta = (delta-last_delta)/id_diff;
if ( id_diff > 1 )
{
for ( int i = last_id+1; i < id; i++ )
{
if ( id_diff > 1 ) {
for ( int i = last_id+1; i < id; i++ ) {
event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta));
event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time);
event_data->frames[i-1].delta = frame_delta;
@@ -967,8 +868,7 @@ bool EventStream::loadEventData( int event_id )
last_delta = delta;
last_timestamp = timestamp;
}
if ( mysql_errno( &dbconn ) )
{
if ( mysql_errno( &dbconn ) ) {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
@@ -980,8 +880,7 @@ bool EventStream::loadEventData( int event_id )
mysql_free_result( result );
if ( forceEventChange || mode == MODE_ALL_GAPLESS )
{
if ( forceEventChange || mode == MODE_ALL_GAPLESS ) {
if ( replay_rate > 0 )
curr_stream_time = event_data->frames[0].timestamp;
else
@@ -992,12 +891,10 @@ bool EventStream::loadEventData( int event_id )
return( true );
}
void EventStream::processCommand( const CmdMsg *msg )
{
void EventStream::processCommand( const CmdMsg *msg ) {
Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] )
// Check for incoming command
switch( (MsgCommand)msg->msg_data[0] )
{
switch( (MsgCommand)msg->msg_data[0] ) {
case CMD_PAUSE :
{
Debug( 1, "Got PAUSE command" );
@@ -1256,8 +1153,7 @@ void EventStream::processCommand( const CmdMsg *msg )
DataMsg status_msg;
status_msg.msg_type = MSG_DATA_EVENT;
memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) );
if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 )
{
if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 ) {
//if ( errno != EAGAIN )
{
Error( "Can't sendto on sd %d: %s", sd, strerror(errno) );
@@ -1271,49 +1167,39 @@ void EventStream::processCommand( const CmdMsg *msg )
updateFrameRate( (double)event_data->frame_count/event_data->duration );
}
void EventStream::checkEventLoaded()
{
void EventStream::checkEventLoaded() {
bool reload_event = false;
static char sql[ZM_SQL_SML_BUFSIZ];
if ( curr_frame_id <= 0 )
{
if ( curr_frame_id <= 0 ) {
snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id < %ld order by Id desc limit 1", event_data->monitor_id, event_data->event_id );
reload_event = true;
}
else if ( (unsigned int)curr_frame_id > event_data->frame_count )
{
} else if ( (unsigned int)curr_frame_id > event_data->frame_count ) {
snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id > %ld order by Id asc limit 1", event_data->monitor_id, event_data->event_id );
reload_event = true;
}
if ( reload_event )
{
if ( forceEventChange || mode != MODE_SINGLE )
{
if ( reload_event ) {
if ( forceEventChange || mode != MODE_SINGLE ) {
//Info( "SQL:%s", sql );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_ROW dbrow = mysql_fetch_row( result );
if ( mysql_errno( &dbconn ) )
{
if ( mysql_errno( &dbconn ) ) {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
if ( dbrow )
{
if ( dbrow ) {
int event_id = atoi(dbrow[0]);
Debug( 1, "Loading new event %d", event_id );
@@ -1325,9 +1211,7 @@ void EventStream::checkEventLoaded()
else
curr_frame_id = 1;
Debug( 2, "New frame id = %d", curr_frame_id );
}
else
{
} else {
if ( curr_frame_id <= 0 )
curr_frame_id = 1;
else
@@ -1336,9 +1220,7 @@ void EventStream::checkEventLoaded()
}
mysql_free_result( result );
forceEventChange = false;
}
else
{
} else {
if ( curr_frame_id <= 0 )
curr_frame_id = 1;
else
@@ -1359,8 +1241,7 @@ Image * EventStream::getImage( ) {
return image;
}
bool EventStream::sendFrame( int delta_us )
{
bool EventStream::sendFrame( int delta_us ) {
Debug( 2, "Sending frame %d", curr_frame_id );
static char filepath[PATH_MAX];
@@ -1370,21 +1251,18 @@ bool EventStream::sendFrame( int delta_us )
snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id );
#if HAVE_LIBAVCODEC
if ( type == STREAM_MPEG )
{
if ( type == STREAM_MPEG ) {
Image image( filepath );
Image *send_image = prepareImage( &image );
if ( !vid_stream )
{
if ( !vid_stream ) {
vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() );
fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() );
vid_stream->OpenStream();
}
/* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_us*1000 );
}
else
} else
#endif // HAVE_LIBAVCODEC
{
static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE];
@@ -1399,11 +1277,9 @@ bool EventStream::sendFrame( int delta_us )
if ( type != STREAM_JPEG )
send_raw = false;
if ( send_raw )
{
if ( send_raw ) {
fdj = fopen( filepath, "rb" );
if ( !fdj )
{
if ( !fdj ) {
Error( "Can't open %s: %s", filepath, strerror(errno) );
return( false );
}
@@ -1415,15 +1291,12 @@ bool EventStream::sendFrame( int delta_us )
#else
img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj );
#endif
}
else
{
} else {
Image image( filepath );
Image *send_image = prepareImage( &image );
switch( type )
{
switch( type ) {
case STREAM_JPEG :
send_image->EncodeJpeg( img_buffer, &img_buffer_size );
break;
@@ -1447,8 +1320,7 @@ bool EventStream::sendFrame( int delta_us )
}
}
switch( type )
{
switch( type ) {
case STREAM_JPEG :
fprintf( stdout, "Content-Type: image/jpeg\r\n" );
break;
@@ -1485,8 +1357,7 @@ bool EventStream::sendFrame( int delta_us )
fclose(fdj); /* Close the file handle */
} else {
fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size );
if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 )
{
if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) {
Error( "Unable to send stream frame: %s", strerror(errno) );
return( false );
}
@@ -1499,8 +1370,7 @@ bool EventStream::sendFrame( int delta_us )
return( true );
}
void EventStream::runStream()
{
void EventStream::runStream() {
Event::Initialise();
openComms();
@@ -1512,15 +1382,13 @@ void EventStream::runStream()
if ( type == STREAM_JPEG )
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
if ( !event_data )
{
if ( !event_data ) {
sendTextFrame( "No event data found" );
exit( 0 );
}
unsigned int delta_us = 0;
while( !zm_terminate )
{
while( !zm_terminate ) {
gettimeofday( &now, NULL );
while(checkCommandQueue());
@@ -1536,27 +1404,21 @@ void EventStream::runStream()
//Info( "cst:%.2f", curr_stream_time );
//Info( "cfid:%d", curr_frame_id );
//Info( "fdt:%d", frame_data->timestamp );
if ( !paused )
{
if ( !paused ) {
bool in_event = true;
double time_to_event = 0;
if ( replay_rate > 0 )
{
if ( replay_rate > 0 ) {
time_to_event = event_data->frames[0].timestamp - curr_stream_time;
if ( time_to_event > 0 )
in_event = false;
}
else if ( replay_rate < 0 )
{
} else if ( replay_rate < 0 ) {
time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp;
if ( time_to_event > 0 )
in_event = false;
}
if ( !in_event )
{
if ( !in_event ) {
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
if ( actual_delta_time > 1 )
{
if ( actual_delta_time > 1 ) {
static char frame_text[64];
snprintf( frame_text, sizeof(frame_text), "Time to next event = %d seconds", (int)time_to_event );
if ( !sendTextFrame( frame_text ) )
@@ -1574,11 +1436,9 @@ void EventStream::runStream()
// Figure out if we should send this frame
bool send_frame = false;
if ( !paused )
{
if ( !paused ) {
// If we are streaming and this frame is due to be sent
if ( ((curr_frame_id-1)%frame_mod) == 0 )
{
if ( ((curr_frame_id-1)%frame_mod) == 0 ) {
delta_us = (unsigned int)(frame_data->delta * 1000000);
// if effective > base we should speed up frame delivery
delta_us = (unsigned int)((delta_us * base_fps)/effective_fps);
@@ -1586,19 +1446,14 @@ void EventStream::runStream()
delta_us = max(delta_us, 1000000 / maxfps);
send_frame = true;
}
}
else if ( step != 0 )
{
} else if ( step != 0 ) {
// We are paused and are just stepping forward or backward one frame
step = 0;
send_frame = true;
}
else
{
} else {
// We are paused, and doing nothing
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
if ( actual_delta_time > MAX_STREAM_DELAY )
{
if ( actual_delta_time > MAX_STREAM_DELAY ) {
// Send keepalive
Debug( 2, "Sending keepalive frame" );
send_frame = true;
@@ -1611,17 +1466,13 @@ void EventStream::runStream()
curr_stream_time = frame_data->timestamp;
if ( !paused )
{
if ( !paused ) {
curr_frame_id += replay_rate>0?1:-1;
if ( send_frame && type != STREAM_MPEG )
{
if ( send_frame && type != STREAM_MPEG ) {
Debug( 3, "dUs: %d", delta_us );
usleep( delta_us );
}
}
else
{
} else {
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
}
}
+106 -125
View File
@@ -47,163 +47,149 @@ class Monitor;
//
// Class describing events, i.e. captured periods of activity.
//
class Event
{
class Event {
friend class EventStream;
protected:
static bool initialised;
static char capture_file_format[PATH_MAX];
static char analyse_file_format[PATH_MAX];
static char general_file_format[PATH_MAX];
static char video_file_format[PATH_MAX];
static bool initialised;
static char capture_file_format[PATH_MAX];
static char analyse_file_format[PATH_MAX];
static char general_file_format[PATH_MAX];
static char video_file_format[PATH_MAX];
protected:
static int sd;
static int sd;
public:
typedef std::set<std::string> StringSet;
typedef std::map<std::string,StringSet> StringSetMap;
typedef std::set<std::string> StringSet;
typedef std::map<std::string,StringSet> StringSetMap;
protected:
typedef enum { NORMAL, BULK, ALARM } FrameType;
typedef enum { NORMAL, BULK, ALARM } FrameType;
struct PreAlarmData
{
Image *image;
struct timeval timestamp;
unsigned int score;
Image *alarm_frame;
};
struct PreAlarmData {
Image *image;
struct timeval timestamp;
unsigned int score;
Image *alarm_frame;
};
static int pre_alarm_count;
static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES];
static int pre_alarm_count;
static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES];
protected:
unsigned int id;
Monitor *monitor;
struct timeval start_time;
struct timeval end_time;
std::string cause;
StringSetMap noteSetMap;
bool videoEvent;
int frames;
int alarm_frames;
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
VideoWriter* videowriter;
FILE* timecodes_fd;
char video_name[PATH_MAX];
char video_file[PATH_MAX];
char timecodes_name[PATH_MAX];
char timecodes_file[PATH_MAX];
unsigned int id;
Monitor *monitor;
struct timeval start_time;
struct timeval end_time;
std::string cause;
StringSetMap noteSetMap;
bool videoEvent;
int frames;
int alarm_frames;
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
VideoWriter* videowriter;
FILE* timecodes_fd;
char video_name[PATH_MAX];
char video_file[PATH_MAX];
char timecodes_name[PATH_MAX];
char timecodes_file[PATH_MAX];
protected:
int last_db_frame;
int last_db_frame;
protected:
static void Initialise()
{
if ( initialised )
return;
static void Initialise() {
if ( initialised )
return;
snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
snprintf( video_file_format, sizeof(video_file_format), "%%s/%%s");
snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
snprintf( video_file_format, sizeof(video_file_format), "%%s/%%s");
initialised = true;
}
initialised = true;
}
void createNotes( std::string &notes );
void createNotes( std::string &notes );
public:
static bool OpenFrameSocket( int );
static bool ValidateFrameSocket( int );
static bool OpenFrameSocket( int );
static bool ValidateFrameSocket( int );
public:
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent=false );
~Event();
Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent=false );
~Event();
int Id() const { return( id ); }
const std::string &Cause() { return( cause ); }
int Frames() const { return( frames ); }
int AlarmFrames() const { return( alarm_frames ); }
int Id() const { return( id ); }
const std::string &Cause() { return( cause ); }
int Frames() const { return( frames ); }
int AlarmFrames() const { return( alarm_frames ); }
const struct timeval &StartTime() const { return( start_time ); }
const struct timeval &EndTime() const { return( end_time ); }
struct timeval &EndTime() { return( end_time ); }
const struct timeval &StartTime() const { return( start_time ); }
const struct timeval &EndTime() const { return( end_time ); }
struct timeval &EndTime() { return( end_time ); }
bool SendFrameImage( const Image *image, bool alarm_frame=false );
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow );
bool SendFrameImage( const Image *image, bool alarm_frame=false );
bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false );
bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow );
void updateNotes( const StringSetMap &stringSetMap );
void updateNotes( const StringSetMap &stringSetMap );
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
void AddFrames( int n_frames, Image **images, struct timeval **timestamps );
void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL );
private:
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps );
public:
static const char *getSubPath( struct tm *time )
{
static char subpath[PATH_MAX] = "";
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
return( subpath );
}
static const char *getSubPath( time_t *time )
{
return( Event::getSubPath( localtime( time ) ) );
}
static const char *getSubPath( struct tm *time ) {
static char subpath[PATH_MAX] = "";
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
return( subpath );
}
static const char *getSubPath( time_t *time ) {
return( Event::getSubPath( localtime( time ) ) );
}
char* getEventFile(void){
return video_file;
}
char* getEventFile(void) {
return video_file;
}
public:
static int PreAlarmCount()
{
return( pre_alarm_count );
}
static void EmptyPreAlarmFrames()
{
if ( pre_alarm_count > 0 )
{
for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ )
{
delete pre_alarm_data[i].image;
delete pre_alarm_data[i].alarm_frame;
static int PreAlarmCount() {
return( pre_alarm_count );
}
static void EmptyPreAlarmFrames() {
if ( pre_alarm_count > 0 ) {
for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ ) {
delete pre_alarm_data[i].image;
delete pre_alarm_data[i].alarm_frame;
}
memset( pre_alarm_data, 0, sizeof(pre_alarm_data) );
}
memset( pre_alarm_data, 0, sizeof(pre_alarm_data) );
pre_alarm_count = 0;
}
pre_alarm_count = 0;
}
static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL )
{
pre_alarm_data[pre_alarm_count].image = new Image( *image );
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
pre_alarm_data[pre_alarm_count].score = score;
if ( alarm_frame )
{
pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame );
static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ) {
pre_alarm_data[pre_alarm_count].image = new Image( *image );
pre_alarm_data[pre_alarm_count].timestamp = timestamp;
pre_alarm_data[pre_alarm_count].score = score;
if ( alarm_frame ) {
pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame );
}
pre_alarm_count++;
}
pre_alarm_count++;
}
void SavePreAlarmFrames()
{
for ( int i = 0; i < pre_alarm_count; i++ )
{
AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame );
void SavePreAlarmFrames() {
for ( int i = 0; i < pre_alarm_count; i++ ) {
AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame );
}
EmptyPreAlarmFrames();
}
EmptyPreAlarmFrames();
}
};
class EventStream : public StreamBase
{
class EventStream : public StreamBase {
public:
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
@@ -216,8 +202,7 @@ class EventStream : public StreamBase
bool in_db;
};
struct EventData
{
struct EventData {
unsigned long event_id;
unsigned long monitor_id;
unsigned long storage_id;
@@ -255,8 +240,7 @@ class EventStream : public StreamBase
bool sendFrame( int delta_us );
public:
EventStream()
{
EventStream() {
mode = DEFAULT_MODE;
forceEventChange = false;
@@ -266,18 +250,15 @@ class EventStream : public StreamBase
event_data = 0;
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 )
{
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id );
}
void setStreamStart( int monitor_id, time_t event_time )
{
void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, event_time );
loadMonitor( monitor_id );
}
void setStreamMode( StreamMode p_mode )
{
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;
}
void runStream();
+208 -192
View File
@@ -200,230 +200,246 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
(uint8_t*)in_buffer, in_pf, width, height, 1) <= 0)
{
#else
if(avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer,
in_pf, width, height ) <= 0)
{
if(avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer,
in_pf, width, height ) <= 0)
{
#endif
Error("Failed filling input frame with input buffer");
return -7;
}
if(!avpicture_fill( (AVPicture*)output_avframe, out_buffer, out_pf, width, height ) ) {
Error("Failed filling output frame with output buffer");
return -8;
}
/* Do the conversion */
if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) {
Error("swscale conversion failed");
return -10;
}
return 0;
Error("Failed filling input frame with input buffer");
return -7;
}
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
return -12;
}
if(img->Height() != height) {
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
return -13;
}
return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height);
if(!avpicture_fill( (AVPicture*)output_avframe, out_buffer, out_pf, width, height ) ) {
Error("Failed filling output frame with output buffer");
return -8;
}
int SWScale::ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
/* Do the conversion */
if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) {
Error("swscale conversion failed");
return -10;
}
int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size) {
return 0;
}
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
return -12;
}
if(img->Height() != height) {
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
return -13;
}
return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height);
}
int SWScale::ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
#if HAVE_LIBAVUTIL
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
int64_t a, b, this_thing;
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
int64_t a, b, this_thing;
av_assert0(in_ts != AV_NOPTS_VALUE);
av_assert0(duration >= 0);
av_assert0(in_ts != AV_NOPTS_VALUE);
av_assert0(duration >= 0);
if (*last == AV_NOPTS_VALUE || !duration || in_tb.num*(int64_t)out_tb.den <= out_tb.num*(int64_t)in_tb.den) {
if (*last == AV_NOPTS_VALUE || !duration || in_tb.num*(int64_t)out_tb.den <= out_tb.num*(int64_t)in_tb.den) {
simple_round:
*last = av_rescale_q(in_ts, in_tb, fs_tb) + duration;
return av_rescale_q(in_ts, in_tb, out_tb);
}
a = av_rescale_q_rnd(2*in_ts-1, in_tb, fs_tb, AV_ROUND_DOWN) >>1;
b = (av_rescale_q_rnd(2*in_ts+1, in_tb, fs_tb, AV_ROUND_UP )+1)>>1;
if (*last < 2*a - b || *last > 2*b - a)
goto simple_round;
this_thing = av_clip64(*last, a, b);
*last = this_thing + duration;
return av_rescale_q(this_thing, fs_tb, out_tb);
*last = av_rescale_q(in_ts, in_tb, fs_tb) + duration;
return av_rescale_q(in_ts, in_tb, out_tb);
}
a = av_rescale_q_rnd(2*in_ts-1, in_tb, fs_tb, AV_ROUND_DOWN) >>1;
b = (av_rescale_q_rnd(2*in_ts+1, in_tb, fs_tb, AV_ROUND_UP )+1)>>1;
if (*last < 2*a - b || *last > 2*b - a)
goto simple_round;
this_thing = av_clip64(*last, a, b);
*last = this_thing + duration;
return av_rescale_q(this_thing, fs_tb, out_tb);
}
#endif
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
AVFormatContext *s = avformat_alloc_context();
int ret = 0;
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
AVFormatContext *s = avformat_alloc_context();
int ret = 0;
*avctx = NULL;
if (!s) {
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
return ret;
*avctx = NULL;
if (!s) {
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
return ret;
}
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", filename);
}
}
}
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", filename);
}
}
}
if (ret) {
avformat_free_context(s);
return ret;
} else {
s->oformat = oformat;
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (s->priv_data) {
if (s->oformat->priv_class) {
*(const AVClass**)s->priv_data= s->oformat->priv_class;
av_opt_set_defaults(s->priv_data);
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", filename);
}
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
return ret;
}
s->priv_data = NULL;
}
if (ret) {
avformat_free_context(s);
return ret;
} else {
s->oformat = oformat;
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (s->priv_data) {
if (s->oformat->priv_class) {
*(const AVClass**)s->priv_data= s->oformat->priv_class;
av_opt_set_defaults(s->priv_data);
}
} else {
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
return ret;
}
s->priv_data = NULL;
}
if (filename) strncpy(s->filename, filename, sizeof(s->filename));
*avctx = s;
return 0;
}
}
if (filename) strncpy(s->filename, filename, sizeof(s->filename));
*avctx = s;
return 0;
}
static void zm_log_fps(double d, const char *postfix)
{
uint64_t v = lrintf(d * 100);
if (!v) {
Debug(3, "%1.4f %s", d, postfix);
} else if (v % 100) {
Debug(3, "%3.2f %s", d, postfix);
} else if (v % (100 * 1000)) {
Debug(3, "%1.0f %s", d, postfix);
} else
Debug(3, "%1.0fk %s", d / 1000, postfix);
}
/* "user interface" functions */
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
char buf[256];
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i];
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(3, " Stream #%d:%d", index, i);
/* the pid is an important information, so we display it */
/* XXX: add a generic system */
if (flags & AVFMT_SHOW_IDS)
Debug(3, "[0x%x]", st->id);
if (lang)
Debug(3, "(%s)", lang->value);
av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames,
st->time_base.num, st->time_base.den);
Debug(3, ": %s", buf);
if (st->sample_aspect_ratio.num && // default
av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
st->codec->width * (int64_t)st->sample_aspect_ratio.num,
st->codec->height * (int64_t)st->sample_aspect_ratio.den,
1024 * 1024);
Debug(3, ", SAR %d:%d DAR %d:%d",
st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
display_aspect_ratio.num, display_aspect_ratio.den);
}
static void zm_log_fps(double d, const char *postfix)
{
uint64_t v = lrintf(d * 100);
if (!v) {
Debug(3, "%1.4f %s", d, postfix);
} else if (v % 100) {
Debug(3, "%3.2f %s", d, postfix);
} else if (v % (100 * 1000)) {
Debug(3, "%1.0f %s", d, postfix);
} else
Debug(3, "%1.0fk %s", d / 1000, postfix);
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
int tbn = st->time_base.den && st->time_base.num;
int tbc = st->codec->time_base.den && st->codec->time_base.num;
if (fps || tbr || tbn || tbc)
Debug(3, "\n" );
if (fps)
zm_log_fps(av_q2d(st->avg_frame_rate), tbr || tbn || tbc ? "fps, " : "fps");
if (tbr)
zm_log_fps(av_q2d(st->r_frame_rate), tbn || tbc ? "tbr, " : "tbr");
if (tbn)
zm_log_fps(1 / av_q2d(st->time_base), tbc ? "tbn, " : "tbn");
if (tbc)
zm_log_fps(1 / av_q2d(st->codec->time_base), "tbc");
}
/* "user interface" functions */
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
char buf[256];
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i];
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
if (st->disposition & AV_DISPOSITION_DEFAULT)
Debug(3, " (default)");
if (st->disposition & AV_DISPOSITION_DUB)
Debug(3, " (dub)");
if (st->disposition & AV_DISPOSITION_ORIGINAL)
Debug(3, " (original)");
if (st->disposition & AV_DISPOSITION_COMMENT)
Debug(3, " (comment)");
if (st->disposition & AV_DISPOSITION_LYRICS)
Debug(3, " (lyrics)");
if (st->disposition & AV_DISPOSITION_KARAOKE)
Debug(3, " (karaoke)");
if (st->disposition & AV_DISPOSITION_FORCED)
Debug(3, " (forced)");
if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
Debug(3, " (hearing impaired)");
if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
Debug(3, " (visual impaired)");
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
Debug(3, " (clean effects)");
Debug(3, "\n");
avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(3, " Stream #%d:%d", index, i);
//dump_metadata(NULL, st->metadata, " ");
/* the pid is an important information, so we display it */
/* XXX: add a generic system */
if (flags & AVFMT_SHOW_IDS)
Debug(3, "[0x%x]", st->id);
if (lang)
Debug(3, "(%s)", lang->value);
av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames,
st->time_base.num, st->time_base.den);
Debug(3, ": %s", buf);
if (st->sample_aspect_ratio.num && // default
av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
st->codec->width * (int64_t)st->sample_aspect_ratio.num,
st->codec->height * (int64_t)st->sample_aspect_ratio.den,
1024 * 1024);
Debug(3, ", SAR %d:%d DAR %d:%d",
st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
display_aspect_ratio.num, display_aspect_ratio.den);
}
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
int tbn = st->time_base.den && st->time_base.num;
int tbc = st->codec->time_base.den && st->codec->time_base.num;
if (fps || tbr || tbn || tbc)
Debug(3, "\n" );
if (fps)
zm_log_fps(av_q2d(st->avg_frame_rate), tbr || tbn || tbc ? "fps, " : "fps");
if (tbr)
zm_log_fps(av_q2d(st->r_frame_rate), tbn || tbc ? "tbr, " : "tbr");
if (tbn)
zm_log_fps(1 / av_q2d(st->time_base), tbc ? "tbn, " : "tbn");
if (tbc)
zm_log_fps(1 / av_q2d(st->codec->time_base), "tbc");
}
if (st->disposition & AV_DISPOSITION_DEFAULT)
Debug(3, " (default)");
if (st->disposition & AV_DISPOSITION_DUB)
Debug(3, " (dub)");
if (st->disposition & AV_DISPOSITION_ORIGINAL)
Debug(3, " (original)");
if (st->disposition & AV_DISPOSITION_COMMENT)
Debug(3, " (comment)");
if (st->disposition & AV_DISPOSITION_LYRICS)
Debug(3, " (lyrics)");
if (st->disposition & AV_DISPOSITION_KARAOKE)
Debug(3, " (karaoke)");
if (st->disposition & AV_DISPOSITION_FORCED)
Debug(3, " (forced)");
if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
Debug(3, " (hearing impaired)");
if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
Debug(3, " (visual impaired)");
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
Debug(3, " (clean effects)");
Debug(3, "\n");
//dump_metadata(NULL, st->metadata, " ");
//dump_sidedata(NULL, st, " ");
}
//dump_sidedata(NULL, st, " ");
}
+10 -13
View File
@@ -63,7 +63,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
wasRecording = false;
videoStore = NULL;
#if HAVE_LIBSWSCALE
#if HAVE_LIBSWSCALE
mConvertContext = NULL;
#endif
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
@@ -274,9 +274,7 @@ int FfmpegCamera::OpenFfmpeg() {
Warning( "Error trying to set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str() );
}
}
else
{
} else {
Warning( "Unable to parse ffmpeg option %d '%s', expecting key=value", i, opVect[i].c_str() );
}
}
@@ -356,7 +354,7 @@ int FfmpegCamera::OpenFfmpeg() {
if ( mVideoStreamId == -1 )
Fatal( "Unable to locate video stream in %s", mPath.c_str() );
if ( mAudioStreamId == -1 )
Debug( 2, "Unable to locate audio stream in %s", mPath.c_str() );
Debug( 3, "Unable to locate audio stream in %s", mPath.c_str() );
Debug ( 3, "Found video stream at index %d", mVideoStreamId );
Debug ( 3, "Found audio stream at index %d", mAudioStreamId );
@@ -523,12 +521,11 @@ void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){
}
//Function to handle capture and store
int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_file )
{
int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_file ) {
if (!mCanCapture){
return -1;
}
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
if (mReopenThread != 0) {
void *retval = 0;
@@ -568,9 +565,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
(avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) ||
// Check for Connection failure.
(avResult == -110)
) {
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
ReopenFfmpeg();
) {
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
ReopenFfmpeg();
}
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
@@ -581,9 +578,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
if ( avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ) < 0 )
#else
if ( avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ) < 0 )
if ( avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ) < 0 )
#endif
Fatal( "Unable to decode frame at frame %d", frameCount );
Fatal( "Unable to decode frame at frame %d", frameCount );
Debug( 4, "Decoded video packet at frame %d", frameCount );
+1
View File
@@ -41,6 +41,7 @@ class FfmpegCamera : public Camera
int frameCount;
#if HAVE_LIBAVFORMAT
<<<<<<< HEAD
AVFormatContext *mFormatContext;
int mVideoStreamId;
int mAudioStreamId;
+19 -19
View File
@@ -287,25 +287,25 @@ AVFrame **LocalCamera::capturePictures = 0;
LocalCamera *LocalCamera::last_camera = NULL;
LocalCamera::LocalCamera(
int p_id,
const std::string &p_device,
int p_channel,
int p_standard,
bool p_v4l_multi_buffer,
unsigned int p_v4l_captures_per_frame,
const std::string &p_method,
int p_width,
int p_height,
int p_colours,
int p_palette,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio,
unsigned int p_extras) :
Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
int p_id,
const std::string &p_device,
int p_channel,
int p_standard,
bool p_v4l_multi_buffer,
unsigned int p_v4l_captures_per_frame,
const std::string &p_method,
int p_width,
int p_height,
int p_colours,
int p_palette,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio,
unsigned int p_extras) :
Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
device( p_device ),
channel( p_channel ),
standard( p_standard ),
+5
View File
@@ -36,6 +36,11 @@
#include <linux/videodev2.h>
#endif // HAVE_LINUX_VIDEODEV2_H
// Required on systems with v4l1 but without v4l2 headers
#ifndef VIDEO_MAX_FRAME
#define VIDEO_MAX_FRAME 32
#endif
#include "zm_ffmpeg.h"
//
+28 -17
View File
@@ -75,7 +75,12 @@ std::vector<std::string> split(const std::string &s, char delim) {
<<<<<<< HEAD
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
=======
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id )
{
>>>>>>> feature-h264-videostorage
strncpy( name, p_name, sizeof(name) );
#if ZM_MEM_MAPPED
@@ -232,7 +237,12 @@ bool Monitor::MonitorLink::inAlarm() {
bool Monitor::MonitorLink::hasAlarmed()
{
<<<<<<< HEAD
if ( shared_data->state == ALARM ) {
=======
if ( shared_data->state == ALARM )
{
>>>>>>> feature-h264-videostorage
return( true );
} else if ( shared_data->last_event != (unsigned int)last_event ) {
last_event = shared_data->last_event;
@@ -1303,10 +1313,10 @@ bool Monitor::Analyse()
if ( read_margin < 0 ) read_margin += image_buffer_count;
int step = 1;
// Isn't read_margin always > 0 here?
// Isn't read_margin always > 0 here?
if ( read_margin > 0 )
{
// TODO explain this so... 90% of image buffer / 50% of read margin?
// TODO explain this so... 90% of image buffer / 50% of read margin?
step = (9*image_buffer_count)/(5*read_margin);
}
@@ -1401,10 +1411,11 @@ bool Monitor::Analyse()
{
bool signal = shared_data->signal;
bool signal_change = (signal != last_signal);
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);
//Set video recording flag for event start constructor and easy reference in code
// TODO: Use enum instead of the # 2. Makes for easier reading
// TODO: Use enum instead of the # 2. Makes for easier reading
bool videoRecording = ((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo());
if ( trigger_data->trigger_state != TRIGGER_OFF )
@@ -1561,7 +1572,7 @@ bool Monitor::Analyse()
//set up video store data
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
video_store_data->recording = true;
Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() );
/* To prevent cancelling out an existing alert\prealarm\alarm state */
@@ -2326,7 +2337,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
int videowriter = atoi(dbrow[col]); col++;
std::string encoderparams = dbrow[col]; col++;
bool record_audio = (*dbrow[col] != '0'); col++;
int brightness = atoi(dbrow[col]); col++;
int contrast = atoi(dbrow[col]); col++;
int hue = atoi(dbrow[col]); col++;
@@ -4412,14 +4423,14 @@ void Monitor::SingleImageZip( int scale)
fwrite( img_buffer, img_buffer_size, 1, stdout );
}
unsigned int Monitor::Colours() const { return( camera->Colours() ); }
unsigned int Monitor::SubpixelOrder() const { return( camera->SubpixelOrder() ); }
int Monitor::PrimeCapture() {
return( camera->PrimeCapture() );
}
int Monitor::PreCapture() {
return( camera->PreCapture() );
}
int Monitor::PostCapture() {
return( camera->PostCapture() );
}
Monitor::Orientation Monitor::getOrientation()const { return orientation; }
unsigned int Monitor::SubpixelOrder() const { return( camera->SubpixelOrder() ); }
int Monitor::PrimeCapture() {
return( camera->PrimeCapture() );
}
int Monitor::PreCapture() {
return( camera->PreCapture() );
}
int Monitor::PostCapture() {
return( camera->PostCapture() );
}
Monitor::Orientation Monitor::getOrientation()const { return orientation; }
+2 -2
View File
@@ -505,9 +505,9 @@ public:
class MonitorStream : public StreamBase {
protected:
typedef struct SwapImage {
bool valid;
bool valid;
struct timeval timestamp;
char file_name[PATH_MAX];
char file_name[PATH_MAX];
} SwapImage;
private:
+14 -14
View File
@@ -22,20 +22,20 @@
#include "zm_utils.h"
RemoteCamera::RemoteCamera(
int p_id,
const std::string &p_protocol,
const std::string &p_host,
const std::string &p_port,
const std::string &p_path,
int p_width,
int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio
int p_id,
const std::string &p_protocol,
const std::string &p_host,
const std::string &p_port,
const std::string &p_path,
int p_width,
int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio
) :
Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
protocol( p_protocol ),
+29 -2
View File
@@ -31,8 +31,35 @@
#include <sys/filio.h> // FIONREAD and friends
#endif
RemoteCameraHttp::RemoteCameraHttp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio )
RemoteCameraHttp::RemoteCameraHttp(
int p_id,
const std::string &p_method,
const std::string &p_host,
const std::string &p_port,
const std::string &p_path,
int p_width, int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio ) :
RemoteCamera(
p_id,
"http",
p_host,
p_port,
p_path,
p_width,
p_height,
p_colours,
p_brightness,
p_contrast,
p_hue,
p_colour,
p_capture,
p_record_audio )
{
sd = -1;
+33 -46
View File
@@ -117,7 +117,7 @@ void RemoteCameraRtsp::Initialise()
int max_size = width*height*colours;
// This allocates a buffer able to hold a raw fframe, which is a little artbitrary. Might be nice to get some
// decent data on how large a buffer is really needed. I think in ffmpeg there are now some functions to do that.
// decent data on how large a buffer is really needed. I think in ffmpeg there are now some functions to do that.
buffer.size( max_size );
if ( logDebugging() )
@@ -172,41 +172,41 @@ int RemoteCameraRtsp::PrimeCapture()
// Find first video stream present
mVideoStreamId = -1;
mAudioStreamId = -1;
mAudioStreamId = -1;
// Find the first video stream.
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) {
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
#endif
{
if ( mVideoStreamId == -1 ) {
mVideoStreamId = i;
continue;
} else {
Debug(2, "Have another video stream." );
}
if ( mVideoStreamId == -1 ) {
mVideoStreamId = i;
continue;
} else {
Debug(2, "Have another video stream." );
}
}
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
#endif
{
if ( mAudioStreamId == -1 ) {
mAudioStreamId = i;
} else {
Debug(2, "Have another audio stream." );
}
}
{
if ( mAudioStreamId == -1 ) {
mAudioStreamId = i;
} else {
Debug(2, "Have another audio stream." );
}
}
} // end foreach stream
if ( mVideoStreamId == -1 )
Fatal( "Unable to locate video stream" );
if ( mAudioStreamId == -1 )
Debug( 3, "Unable to locate audio stream" );
if ( mAudioStreamId == -1 )
Debug( 3, "Unable to locate audio stream" );
// Get a pointer to the codec context for the video stream
mCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
@@ -331,17 +331,17 @@ int RemoteCameraRtsp::Capture( Image &image ) {
}
av_init_packet( &packet );
while ( !frameComplete && buffer.size() > 0 ) {
packet.data = buffer.head();
packet.size = buffer.size();
// So I think this is the magic decode step. Result is a raw image?
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet );
#else
#else
int len = avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size );
#endif
#endif
if ( len < 0 ) {
Error( "Error while decoding frame %d", frameCount );
Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() );
@@ -350,8 +350,8 @@ int RemoteCameraRtsp::Capture( Image &image ) {
}
Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() );
//if ( buffer.size() < 400 )
//Hexdump( 0, buffer.head(), buffer.size() );
//Hexdump( 0, buffer.head(), buffer.size() );
buffer -= len;
}
// At this point, we either have a frame or ran out of buffer. What happens if we run out of buffer?
@@ -395,17 +395,6 @@ int RemoteCameraRtsp::Capture( Image &image ) {
return (0) ;
}
//int RemoteCameraRtsp::ReadData(void *opaque, uint8_t *buf, int bufSize) {
//if ( buffer.size() > bufSize ) {
//buf = buffer.head();
//buffer -= bufSize;
//} else {
//Error("Implement me");
//return -1;
//}
//}
//Function to handle capture and store
int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* event_file ) {
AVPacket packet;
@@ -457,7 +446,7 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
av_init_packet( &packet );
// Why are we checking for it being the video stream? Because it might be audio or something else.
// Um... we just initialized packet... we can't be testing for what it is yet....
// Um... we just initialized packet... we can't be testing for what it is yet....
if ( packet.stream_index == mVideoStreamId ) {
while ( !frameComplete && buffer.size() > 0 ) {
@@ -495,7 +484,7 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
imagePixFormat, width, height);
#endif
//Video recording
//Video recording
if ( recording && !wasRecording ) {
//Instantiate the video storage module
@@ -533,7 +522,7 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
}
#if HAVE_LIBSWSCALE
// Why are we re-scaling after writing out the packet?
// Why are we re-scaling after writing out the packet?
if(mConvertContext == NULL) {
mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
@@ -549,7 +538,7 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
frameCount++;
} /* frame complete */
} /* frame complete */
} else if ( packet.stream_index == mAudioStreamId ) {
Debug( 4, "Got audio packet" );
if ( videoStore && recording ) {
@@ -563,10 +552,8 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
#else
av_free_packet( &packet );
#endif
return 0;
return 0;
}
} else {
Debug( 4, "Not storing audio" );
}
}
} // end if video or audio packet
+9 -8
View File
@@ -33,11 +33,11 @@ extern "C"{
}
VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVStream *input_st,
AVStream *inpaud_st,
int64_t nStartTime,
Monitor::Orientation orientation
) {
AVStream *input_st,
AVStream *inpaud_st,
int64_t nStartTime,
Monitor::Orientation orientation
) {
AVDictionary *pmetadata = NULL;
int dsr;
@@ -96,6 +96,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
video_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if ( orientation ) {
if ( orientation == Monitor::ROTATE_90 ) {
dsr = av_dict_set( &video_st->metadata, "rotate", "90", 0);
@@ -112,7 +113,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
}
if (inpaud_st) {
audio_st = avformat_new_stream(oc, (AVCodec *)inpaud_st->codec->codec);
if (!audio_st) {
Error("Unable to create audio out stream\n");
@@ -222,6 +222,9 @@ void VideoStore::dumpPacket( AVPacket *pkt ){
int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AVPacket *lastKeyframePkt){
Debug(3, "before ost_tbcket %d", startTime );
zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
Debug(3, "before ost_tbcket %d", startTime );
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, video_st->time_base);
AVPacket opkt, safepkt;
@@ -285,7 +288,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_st){//, AV
}
}
av_free_packet(&opkt);
return 0;
@@ -310,7 +312,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_st){
av_init_packet(&opkt);
Debug(3, "after init packet" );
//Scale the PTS of the outgoing packet to be the correct time base
if (ipkt->pts != AV_NOPTS_VALUE) {
Debug(3, "Rescaling output pts");
+4
View File
@@ -1 +1,5 @@
<<<<<<< HEAD
1.30.3
=======
1.30.0
>>>>>>> feature-h264-videostorage
+1 -1
View File
@@ -394,7 +394,7 @@ tr.log-dbg td {
}
$exportFile = "zm-log.$exportExt";
$exportPath = "temp/zm-log-$exportKey.$exportExt";
$exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt";
header( "Pragma: public" );
header( "Expires: 0" );
+30 -4
View File
@@ -962,13 +962,18 @@ function zmaCheck( $monitor ) {
}
function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
<<<<<<< HEAD
$Storage = new Storage( $event['StorageId'] );
$Event = new Event( $event );
$eventPath = $Event->Path();
=======
$eventPath = getEventPath( $event );
>>>>>>> feature-h264-videostorage
if ( !is_array($frame) )
$frame = array( 'FrameId'=>$frame, 'Type'=>'' );
<<<<<<< HEAD
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) {
$captImage = "snapshot.jpg";
@@ -987,6 +992,21 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
Error("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() );
}
}
=======
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) {
$captImage = "snapshot.jpg";
} else {
$captImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] );
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
# Generate the frame JPG
if ( $event['DefaultVideo'] ) {
$command ='ffmpeg -v 0 -i '.$eventPath.'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
system( $command, $output, $retval );
} else {
Error("Can't create frame images from video because there is no video file for this event " );
}
}
>>>>>>> feature-h264-videostorage
}
$captPath = $eventPath.'/'.$captImage;
@@ -1000,7 +1020,10 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
$analImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $frame['FrameId'] );
$analPath = $eventPath.'/'.$analImage;
<<<<<<< HEAD
=======
>>>>>>> feature-h264-videostorage
$thumbAnalPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$analImage;
//echo "AI:$analImage, AP:$analPath, TAP:$thumbAnalPath<br>";
@@ -1031,21 +1054,24 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
$thumbPath = $thumbCaptPath;
}
<<<<<<< HEAD
$imageFile = $imagePath;
=======
>>>>>>> feature-h264-videostorage
$thumbFile = $thumbPath;
if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) )
{
// Get new dimensions
list( $imageWidth, $imageHeight ) = getimagesize( $imageFile );
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
$thumbWidth = $imageWidth * $fraction;
$thumbHeight = $imageHeight * $fraction;
// Resample
$thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight );
$image = imagecreatefromjpeg( $imageFile );
$image = imagecreatefromjpeg( $imagePath );
imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight );
if ( !imagejpeg( $thumbImage, $thumbFile ) )
if ( !imagejpeg( $thumbImage, $thumbPath ) )
Error( "Can't create thumbnail '$thumbPath'" );
}
}
@@ -1054,7 +1080,7 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
'eventPath' => $eventPath,
'imagePath' => $imagePath,
'thumbPath' => $thumbPath,
'imageFile' => $imageFile,
'imageFile' => $imagePath,
'thumbFile' => $thumbFile,
'imageClass' => $alarmFrame?"alarm":"normal",
'isAnalImage' => $isAnalImage,
+352 -352
View File
File diff suppressed because it is too large. Load diff
+19 -19
View File
@@ -125,29 +125,29 @@ if ( canEdit( 'Events' ) )
if ( canView( 'Events' ) )
{
?>
<div id="framesEvent"><a href="#" onclick="showEventFrames()"><?php echo translate('Frames') ?></a></div>
<div id="framesEvent"><a href="#" onclick="showEventFrames()"><?php echo translate('Frames') ?></a></div>
<?php
if ( $event['SaveJPEGs'] & 3 )
{
?>
<div id="stillsEvent"<?php if ( $streamMode == 'still' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showStills()"><?php echo translate('Stills') ?></a></div>
<div id="stillsEvent"<?php if ( $streamMode == 'still' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showStills()"><?php echo translate('Stills') ?></a></div>
<?php
}
?>
<div id="videoEvent"<?php if ( $streamMode == 'video' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showVideo()"><?php echo translate('Video') ?></a></div>
<div id="exportEvent"><a href="#" onclick="exportEvent()"><?php echo translate('Export') ?></a></div>
</div>
<div id="eventVideo" class="">
<?php
<div id="videoEvent"<?php if ( $streamMode == 'video' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showVideo()"><?php echo translate('Video') ?></a></div>
<div id="exportEvent"><a href="#" onclick="exportEvent()"><?php echo translate('Export') ?></a></div>
</div>
<div id="eventVideo" class="">
<?php
if ( $event['DefaultVideo'] )
{
{
?>
<div id="videoFeed">
<video id="videoobj" class="video-js vjs-default-skin" width="<?php echo reScale( $event['Width'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $scale ) ?>" data-setup='{ "controls": true, "playbackRates": [0.5, 1, 1.5, 2, 4, 8, 16, 32, 64, 128, 256], "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "rotate": "<?php echo $Rotation ?>", "zoom": "<?php echo $Zoom ?>"}}}'>
<source src="<?php echo getEventDefaultVideoPath($event) ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<div id="videoFeed">
<video id="videoobj" class="video-js vjs-default-skin" width="<?php echo reScale( $event['Width'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $scale ) ?>" data-setup='{ "controls": true, "playbackRates": [0.5, 1, 1.5, 2, 4, 8, 16, 32, 64, 128, 256], "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "rotate": "<?php echo $Rotation ?>", "zoom": "<?php echo $Zoom ?>"}}}'>
<source src="<?php echo getEventDefaultVideoPath($event) ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<!--script>includeVideoJs();</script-->
<link href="//vjs.zencdn.net/4.11/video-js.css" rel="stylesheet">
<script src="//vjs.zencdn.net/4.11/video.js"></script>
@@ -166,7 +166,7 @@ addVideoTimingTrack(document.getElementById('videoobj'), LabelFormat, monitorNam
else
{
?>
<div id="imageFeed">
<div id="imageFeed">
<?php
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT )
{
@@ -213,12 +213,12 @@ else
<?php
}
?>
</div>
<?php
</div>
<?php
}
?>
</div>
</div>
</div>
</div>
<?php
if ($event['SaveJPEGs'] & 3)
{
+6
View File
@@ -83,9 +83,15 @@ xhtmlHeaders(__FILE__, translate('Frame')." - ".$event['Id']." - ".$frame->Frame
<img src="?view=image&eid=<?php echo $event['Id'] ?>&fid=<?php echo $frame->FrameId() ?>&scale=<?php echo $event['DefaultScale'] ?>" class="<?php echo $imageData['imageClass'] ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $frame->EventId()."-".$frame->FrameId() ?>">
<?php } else {
if ( $imageData['hasAnalImage'] ) { ?>
<<<<<<< HEAD
<a href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $frame->FrameId() ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>">
<?php } ?>
<img src="<?php echo $frame->getImageSrc() ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $frame->EventId()."-".$frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
=======
<a href="?view=frame&amp;eid=<?php echo $event['Id'] ?>&amp;fid=<?php echo $frame['FrameId'] ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>">
<?php } ?>
<img src="<?php echo $frame->getImageSrc() ?>" width="<?php echo reScale( $event['Width'], $event['DefaultScale'], $scale ) ?>" height="<?php echo reScale( $event['Height'], $event['DefaultScale'], $scale ) ?>" alt="<?php echo $frame['EventId']."-".$frame['FrameId'] ?>" class="<?php echo $imageData['imageClass'] ?>"/>
>>>>>>> feature-h264-videostorage
<?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
<?php } ?>
</p>
+100
View File
@@ -58,6 +58,7 @@ if ( ! empty($_REQUEST['mid']) ) {
} else {
$nextId = getTableAutoInc( 'Monitors' );
<<<<<<< HEAD
if ( ! empty( $_REQUEST['dupId'] ) ) {
$monitor = new Monitor( $_REQUEST['dupId'] );
if ( ZM_OPT_X10 )
@@ -151,6 +152,105 @@ if ( ZM_OPT_X10 && empty($x10Monitor) ) {
function fourcc( $a, $b, $c, $d ) {
return( ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24) );
=======
$monitor = getMonitorObject($_REQUEST['dupId']);
$clonedName = $monitor['Name'];
$monitor['Name'] = translate('Monitor').'-'.$nextId;
$monitor['Id']='0';
}
if ( ZM_OPT_X10 && empty($x10Monitor) )
{
$x10Monitor = array(
'Activation' => '',
'AlarmInput' => '',
'AlarmOutput' => '',
);
}
function getMonitorObject( $mid = null)
{
if ($mid !== null)
{
$monitor = dbFetchMonitor($mid);
}
else
{
$monitor = array(
'Id' => 0,
'Name' => "willbereplaced",
'Function' => "Monitor",
'Enabled' => true,
'LinkedMonitors' => "",
'Type' => "",
'Device' => "/dev/video0",
'Channel' => "0",
'Format' => 0x000000ff,
'Protocol' => "",
'Method' => "",
'Host' => "",
'Path' => "",
'Options' => "",
'Port' => "80",
'User' => "",
'Pass' => "",
'Colours' => 3,
'Palette' => 0,
'Width' => "320",
'Height' => "240",
'Orientation' => "0",
'Deinterlacing' => 0,
'RTSPDescribe' => 0,
'SaveJPEGs' => "3",
'VideoWriter' => "0",
'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
'RecordAudio' => "0",
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelX' => 0,
'LabelY' => 0,
'LabelSize' => 1,
'ImageBufferCount' => 50,
'WarmupCount' => 25,
'PreEventCount' => 25,
'PostEventCount' => 25,
'StreamReplayBuffer' => 1000,
'AlarmFrameCount' => 1,
'Controllable' => 0,
'ControlId' => "",
'ControlType' => 0,
'ControlDevice' => "",
'ControlAddress' => "",
'AutoStopTimeout' => "",
'TrackMotion' => 0,
'TrackDelay' => "",
'ReturnLocation' => -1,
'ReturnDelay' => "",
'SectionLength' => 600,
'FrameSkip' => 0,
'MotionFrameSkip' => 0,
'EventPrefix' => 'Event-',
'AnalysisFPS' => "",
'AnalysisUpdateDelay' => 0,
'MaxFPS' => "",
'AlarmMaxFPS' => "",
'FPSReportInterval' => 1000,
'RefBlendPerc' => 6,
'AlarmRefBlendPerc' => 6,
'DefaultView' => 'Events',
'DefaultRate' => '100',
'DefaultScale' => '100',
'SignalCheckColour' => '#0000c0',
'WebColour' => 'red',
'Exif' => '0',
'Triggers' => "",
'V4LMultiBuffer' => '',
'V4LCapturesPerFrame' => 1,
'ServerId' => $Server['Id'],
);
}
return ($monitor);
}
>>>>>>> feature-h264-videostorage
}