Merge branch 'master' of github.com:zoneminder/ZoneMinder
This commit is contained in:
commit
e6f366c5cb
|
@ -72,7 +72,7 @@ New installs
|
|||
6. Configure the web server
|
||||
|
||||
This package uses the HTTPS protocol by default to access the web portal,
|
||||
using rhe default self signed certificate on your system. Requests using
|
||||
using the default self signed certificate on your system. Requests using
|
||||
HTTP will auto-redirect to HTTPS.
|
||||
|
||||
Inspect the web server configuration file and verify it meets your needs:
|
||||
|
@ -129,7 +129,7 @@ New installs
|
|||
Upgrades
|
||||
========
|
||||
|
||||
1. Conf.d folder support has been added to ZoneMinder 1.31.0. Any custom
|
||||
1. Conf.d folder support has been added to ZoneMinder. Any custom
|
||||
changes previously made to zm.conf must now be made in one or more custom
|
||||
config files, created under the conf.d folder. Do this now. See
|
||||
/etc/zm/conf.d/README for details. Once you recreate any custom config changes
|
||||
|
@ -151,6 +151,10 @@ Upgrades
|
|||
exists, inspect it and merge anything new in that file with zoneminder.conf.
|
||||
Verify the SSL REquirements meet your needs. Read README.https if necessary.
|
||||
|
||||
The contents of this file must be merged into your Apache configuration.
|
||||
See step 6 of the installation section if you have not already done this
|
||||
during a previous upgrade.
|
||||
|
||||
4. Upgrade the database before starting ZoneMinder.
|
||||
|
||||
Most upgrades can be performed by executing the following command:
|
||||
|
|
|
@ -72,7 +72,7 @@ New installs
|
|||
6. Configure the web server
|
||||
|
||||
This package uses the HTTPS protocol by default to access the web portal,
|
||||
using rhe default self signed certificate on your system. Requests using
|
||||
using the default self signed certificate on your system. Requests using
|
||||
HTTP will auto-redirect to HTTPS.
|
||||
|
||||
Inspect the web server configuration file and verify it meets your needs:
|
||||
|
@ -129,7 +129,7 @@ New installs
|
|||
Upgrades
|
||||
========
|
||||
|
||||
1. Conf.d folder support has been added to ZoneMinder 1.31.0. Any custom
|
||||
1. Conf.d folder support has been added to ZoneMinder. Any custom
|
||||
changes previously made to zm.conf must now be made in one or more custom
|
||||
config files, created under the conf.d folder. Do this now. See
|
||||
/etc/zm/conf.d/README for details. Once you recreate any custom config changes
|
||||
|
@ -147,10 +147,14 @@ Upgrades
|
|||
|
||||
3. Verify the ZoneMinder Apache configuration file in the folder
|
||||
/etc/zm/www. You will have a file called "zoneminder.conf" and there
|
||||
may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file
|
||||
may also be a file called "zoneminder.conf.rpmnew". If an rpmnew file
|
||||
exists, inspect it and merge anything new in that file with zoneminder.conf.
|
||||
Verify the SSL REquirements meet your needs. Read README.https if necessary.
|
||||
|
||||
The contents of this file must be merged into your Apache configuration.
|
||||
See step 6 of the installation section if you have not already done this
|
||||
during a previous upgrade.
|
||||
|
||||
4. Upgrade the database before starting ZoneMinder.
|
||||
|
||||
Most upgrades can be performed by executing the following command:
|
||||
|
|
|
@ -28,7 +28,7 @@ override_dh_auto_configure:
|
|||
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
|
||||
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
||||
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean $(MANPAGES1)
|
||||
|
|
|
@ -22,7 +22,7 @@ if [ "$1" = "configure" ]; then
|
|||
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
|
||||
if [ -e "/lib/systemd/system/mysql.service" ] || [ -e "/lib/systemd/system/mariadb.service" ]; then
|
||||
if [ -e "/lib/systemd/system/mysql.service" ] || [ -e "/lib/systemd/system/mariadb.service" ] || [ -e "/etc/init.d/mysql" ]; then
|
||||
# Ensure zoneminder is stopped
|
||||
deb-systemd-invoke stop zoneminder.service || exit $?
|
||||
|
||||
|
@ -68,6 +68,7 @@ if [ "$1" = "configure" ]; then
|
|||
|
||||
# Add any new PTZ control configurations to the database (will not overwrite)
|
||||
zmcamtool.pl --import >/dev/null 2>&1
|
||||
echo "Done Updating; starting ZoneMinder."
|
||||
else
|
||||
echo 'NOTE: MySQL/MariaDB not running; please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
|
@ -78,7 +79,6 @@ if [ "$1" = "configure" ]; then
|
|||
else
|
||||
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)."
|
||||
fi
|
||||
echo "Done Updating; starting ZoneMinder."
|
||||
deb-systemd-invoke restart zoneminder.service
|
||||
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# This configuration is only needed for compatibility with zmninja
|
||||
|
||||
# If not using VirtualHosts, copy or symlink this file into the Apache config folder
|
||||
# If using VirtualHosts, then this config must be placed inside the appropriate
|
||||
# <VirtualHost> directive.
|
||||
|
||||
# Make sure you have enabled/loaded header manipulation modules
|
||||
# For example, in Debian based distros the command is "sudo a2enmod headers"
|
||||
|
||||
# zmNinja header permissions. Tweak to your needs
|
||||
|
||||
Header always set Access-Control-Allow-Credentials true
|
||||
#zmNinja's WKWebView will set the origin header as localhost:8080
|
||||
Header always set Access-Control-Allow-Origin "http://localhost:8080"
|
||||
Header always set Access-Control-Request-Methods "Authorization"
|
||||
Header always set Access-Control-Methods "OPTIONS,GET,POST,DELETE,PUT"
|
||||
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization, Origin, Accept, client-security-token"
|
||||
Header always set Access-Control-Expose-Headers "Content-Security-Policy, Location"
|
||||
Header always set Access-Control-Max-Age "1000"
|
||||
RewriteCond %{REQUEST_METHOD} OPTIONS
|
||||
RewriteRule ^(.*)$ $1 [R=200,L]
|
|
@ -570,7 +570,7 @@ sub logPrint {
|
|||
$this->{databaseLevel} = $oldlevel;
|
||||
}
|
||||
|
||||
my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )';
|
||||
my $sql = 'INSERT INTO Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, NULL )';
|
||||
$this->{sth} = $this->{dbh}->prepare_cached($sql) if ! $this->{sth};
|
||||
if ( !$this->{sth} ) {
|
||||
$this->{databaseLevel} = NOLOG;
|
||||
|
@ -578,13 +578,15 @@ sub logPrint {
|
|||
return;
|
||||
}
|
||||
|
||||
my $res = $this->{sth}->execute($seconds+($microseconds/1000000.0)
|
||||
, $this->{id}
|
||||
, $$
|
||||
, $level
|
||||
, $codes{$level}
|
||||
, $string
|
||||
, $this->{fileName}
|
||||
my $res = $this->{sth}->execute(
|
||||
$seconds+($microseconds/1000000.0),
|
||||
$this->{id},
|
||||
($Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : undef),
|
||||
$$,
|
||||
$level,
|
||||
$codes{$level},
|
||||
$string,
|
||||
$this->{fileName},
|
||||
);
|
||||
if ( !$res ) {
|
||||
$this->{databaseLevel} = NOLOG;
|
||||
|
|
|
@ -482,7 +482,7 @@ sub start {
|
|||
logTerm();
|
||||
zmDbDisconnect();
|
||||
|
||||
my $fd = 0;
|
||||
my $fd = 3; # leave stdin,stdout,stderr open. Closing them causes problems with libx264
|
||||
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
|
||||
POSIX::close($fd++);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ class Camera;
|
|||
// Abstract base class for cameras. This is intended just to express
|
||||
// common attributes
|
||||
//
|
||||
class Camera
|
||||
{
|
||||
class Camera {
|
||||
protected:
|
||||
typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType;
|
||||
|
||||
|
@ -53,49 +52,48 @@ protected:
|
|||
int contrast;
|
||||
bool capture;
|
||||
bool record_audio;
|
||||
unsigned int bytes;
|
||||
|
||||
unsigned int bytes;
|
||||
|
||||
public:
|
||||
Camera( unsigned int p_monitor_id, SourceType p_type, unsigned int p_width, unsigned int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
virtual ~Camera();
|
||||
|
||||
unsigned int getId() const { return( monitor_id ); }
|
||||
unsigned int getId() const { return monitor_id; }
|
||||
Monitor *getMonitor();
|
||||
void setMonitor( Monitor *p_monitor );
|
||||
SourceType Type() const { return( type ); }
|
||||
bool IsLocal() const { return( type == LOCAL_SRC ); }
|
||||
bool IsRemote() const { return( type == REMOTE_SRC ); }
|
||||
bool IsFile() const { return( type == FILE_SRC ); }
|
||||
bool IsFfmpeg() const { return( type == FFMPEG_SRC ); }
|
||||
bool IsLibvlc() const { return( type == LIBVLC_SRC ); }
|
||||
bool IscURL() const { return( type == CURL_SRC ); }
|
||||
unsigned int Width() const { return( width ); }
|
||||
unsigned int Height() const { return( height ); }
|
||||
unsigned int Colours() const { return( colours ); }
|
||||
unsigned int SubpixelOrder() const { return( subpixelorder ); }
|
||||
unsigned int Pixels() const { return( pixels ); }
|
||||
unsigned int ImageSize() const { return( imagesize ); }
|
||||
SourceType Type() const { return type; }
|
||||
bool IsLocal() const { return type == LOCAL_SRC; }
|
||||
bool IsRemote() const { return type == REMOTE_SRC; }
|
||||
bool IsFile() const { return type == FILE_SRC; }
|
||||
bool IsFfmpeg() const { return type == FFMPEG_SRC; }
|
||||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||
bool IscURL() const { return type == CURL_SRC; }
|
||||
unsigned int Width() const { return width; }
|
||||
unsigned int Height() const { return height; }
|
||||
unsigned int Colours() const { return colours; }
|
||||
unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||
unsigned int Pixels() const { return pixels; }
|
||||
unsigned int ImageSize() const { return imagesize; }
|
||||
unsigned int Bytes() const { return bytes; };
|
||||
|
||||
virtual int Brightness( int/*p_brightness*/=-1 ) { return( -1 ); }
|
||||
virtual int Hue( int/*p_hue*/=-1 ) { return( -1 ); }
|
||||
virtual int Colour( int/*p_colour*/=-1 ) { return( -1 ); }
|
||||
virtual int Contrast( int/*p_contrast*/=-1 ) { return( -1 ); }
|
||||
virtual int Brightness( int/*p_brightness*/=-1 ) { return -1; }
|
||||
virtual int Hue( int/*p_hue*/=-1 ) { return -1; }
|
||||
virtual int Colour( int/*p_colour*/=-1 ) { return -1; }
|
||||
virtual int Contrast( int/*p_contrast*/=-1 ) { return -1; }
|
||||
|
||||
bool CanCapture() const { return( capture ); }
|
||||
bool CanCapture() const { return capture; }
|
||||
|
||||
bool SupportsNativeVideo() const {
|
||||
return (type == FFMPEG_SRC);
|
||||
//return (type == FFMPEG_SRC )||(type == REMOTE_SRC);
|
||||
}
|
||||
|
||||
virtual int PrimeCapture() { return( 0 ); }
|
||||
virtual int PreCapture()=0;
|
||||
virtual int Capture( Image &image )=0;
|
||||
virtual int PostCapture()=0;
|
||||
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) = 0;
|
||||
virtual int Close()=0;
|
||||
virtual int PrimeCapture() { return 0; }
|
||||
virtual int PreCapture() = 0;
|
||||
virtual int Capture(Image &image) = 0;
|
||||
virtual int PostCapture() = 0;
|
||||
virtual int CaptureAndRecord(Image &image, timeval recording, char* event_directory) = 0;
|
||||
virtual int Close() = 0;
|
||||
};
|
||||
|
||||
#endif // ZM_CAMERA_H
|
||||
|
|
|
@ -147,9 +147,8 @@ Event::Event(
|
|||
errno = 0;
|
||||
if ( mkdir(path, 0755) ) {
|
||||
// FIXME This should not be fatal. Should probably move to a different storage area.
|
||||
if ( errno != EEXIST ) {
|
||||
if ( errno != EEXIST )
|
||||
Error("Can't mkdir %s: %s", path, strerror(errno));
|
||||
}
|
||||
}
|
||||
if ( i == 2 )
|
||||
strncpy(date_path, path, sizeof(date_path));
|
||||
|
|
|
@ -225,8 +225,9 @@ static void zm_log_fps(double d, const char *postfix) {
|
|||
Debug(1, "%3.2f %s", d, postfix);
|
||||
} else if (v % (100 * 1000)) {
|
||||
Debug(1, "%1.0f %s", d, postfix);
|
||||
} else
|
||||
} else {
|
||||
Debug(1, "%1.0fk %s", d / 1000, postfix);
|
||||
}
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
|
@ -355,9 +356,8 @@ int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) {
|
|||
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
||||
#else
|
||||
unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
|
||||
dst->size = (src->size + FF_INPUT_BUFFER_PADDING_SIZE)/sizeof(uint64_t) + 1;
|
||||
dst->data = reinterpret_cast<uint8_t*>(new uint64_t[dst->size]);
|
||||
memcpy(dst->data, src->data, src->size );
|
||||
av_new_packet(dst,src->size);
|
||||
memcpy(dst->data, src->data, src->size);
|
||||
dst->flags = src->flags;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -303,8 +303,8 @@ void zm_dump_codecpar ( const AVCodecParameters *par );
|
|||
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
||||
#define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src )
|
||||
#else
|
||||
unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src );
|
||||
#define zm_av_packet_unref( packet ) av_free_packet( packet )
|
||||
unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src );
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
#define zm_avcodec_decode_video( context, rawFrame, frameComplete, packet ) avcodec_decode_video2( context, rawFrame, frameComplete, packet )
|
||||
|
|
|
@ -331,6 +331,8 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
ret = av_dict_set(&opts, "rtsp_transport", "tcp", 0);
|
||||
} else if ( method == "rtpRtspHttp" ) {
|
||||
ret = av_dict_set(&opts, "rtsp_transport", "http", 0);
|
||||
} else if ( method == "rtpUni" ) {
|
||||
ret = av_dict_set(&opts, "rtsp_transport", "udp", 0);
|
||||
} else {
|
||||
Warning("Unknown method (%s)", method.c_str() );
|
||||
}
|
||||
|
@ -606,7 +608,8 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
mConvertContext = sws_getContext(mVideoCodecContext->width,
|
||||
mConvertContext = sws_getContext(
|
||||
mVideoCodecContext->width,
|
||||
mVideoCodecContext->height,
|
||||
mVideoCodecContext->pix_fmt,
|
||||
width, height,
|
||||
|
@ -722,7 +725,8 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
|
||||
if ( last_event_id != video_writer_event_id ) {
|
||||
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
|
||||
Debug(2, "Have change of event. last_event(%d), our current (%d)",
|
||||
last_event_id, video_writer_event_id);
|
||||
|
||||
if ( videoStore ) {
|
||||
Info("Re-starting video storage module");
|
||||
|
@ -731,7 +735,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
// Also don't know how much it matters for audio.
|
||||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
//Write the packet to our video store
|
||||
int ret = videoStore->writeVideoFramePacket( &packet );
|
||||
int ret = videoStore->writeVideoFramePacket(&packet);
|
||||
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||
Warning("Error writing last packet to videostore.");
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class FfmpegCamera : public Camera {
|
|||
bool hwaccel;
|
||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||
AVFrame *hwFrame;
|
||||
DecodeContext decode;
|
||||
DecodeContext decode;
|
||||
#endif
|
||||
|
||||
// Need to keep track of these because apparently the stream can start with values for pts/dts and then subsequent packets start at zero.
|
||||
|
|
|
@ -649,11 +649,9 @@ void Image::Assign( const Image &image ) {
|
|||
(*fptr_imgbufcpy)(buffer, image.buffer, size);
|
||||
}
|
||||
|
||||
Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits )
|
||||
{
|
||||
if ( colours != ZM_COLOUR_GRAY8 )
|
||||
{
|
||||
Panic( "Attempt to highlight image edges when colours = %d", colours );
|
||||
Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits ) {
|
||||
if ( colours != ZM_COLOUR_GRAY8 ) {
|
||||
Panic("Attempt to highlight image edges when colours = %d", colours);
|
||||
}
|
||||
|
||||
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
|
||||
|
|
|
@ -160,16 +160,16 @@ public:
|
|||
static void Initialise();
|
||||
static void Deinitialise();
|
||||
|
||||
inline unsigned int Width() const { return( width ); }
|
||||
inline unsigned int Height() const { return( height ); }
|
||||
inline unsigned int Pixels() const { return( pixels ); }
|
||||
inline unsigned int Colours() const { return( colours ); }
|
||||
inline unsigned int SubpixelOrder() const { return( subpixelorder ); }
|
||||
inline unsigned int Size() const { return( size ); }
|
||||
inline unsigned int Width() const { return width; }
|
||||
inline unsigned int Height() const { return height; }
|
||||
inline unsigned int Pixels() const { return pixels; }
|
||||
inline unsigned int Colours() const { return colours; }
|
||||
inline unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||
inline unsigned int Size() const { return size; }
|
||||
|
||||
/* Internal buffer should not be modified from functions outside of this class */
|
||||
inline const uint8_t* Buffer() const { return( buffer ); }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return( &buffer[colours*((y*width)+x)] ); }
|
||||
inline const uint8_t* Buffer() const { return buffer; }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[colours*((y*width)+x)]; }
|
||||
/* Request writeable buffer */
|
||||
uint8_t* WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
|
||||
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
}
|
||||
inline Image &operator=( const unsigned char *new_buffer ) {
|
||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||
return( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ReadRaw( const char *filename );
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,7 +38,7 @@
|
|||
#endif
|
||||
|
||||
bool Logger::smInitialised = false;
|
||||
Logger *Logger::smInstance = 0;
|
||||
Logger *Logger::smInstance = NULL;
|
||||
|
||||
Logger::StringMap Logger::smCodes;
|
||||
Logger::IntMap Logger::smSyslogPriorities;
|
||||
|
@ -57,10 +57,10 @@ static void subtractTime( struct timeval * const tp1, struct timeval * const tp2
|
|||
|
||||
void Logger::usrHandler( int sig ) {
|
||||
Logger *logger = fetch();
|
||||
if ( sig == SIGUSR1 )
|
||||
logger->level( logger->level()+1 );
|
||||
else if ( sig == SIGUSR2 )
|
||||
logger->level( logger->level()-1 );
|
||||
if ( sig == SIGUSR1 ) {
|
||||
logger->level(logger->level()+1);
|
||||
} else if ( sig == SIGUSR2 )
|
||||
logger->level(logger->level()-1);
|
||||
Info("Logger - Level changed to %d", logger->level());
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ Logger::Logger() :
|
|||
mFlush(false) {
|
||||
|
||||
if ( smInstance ) {
|
||||
Panic( "Attempt to create second instance of Logger class" );
|
||||
Panic("Attempt to create second instance of Logger class");
|
||||
}
|
||||
|
||||
if ( !smInitialised ) {
|
||||
|
@ -133,11 +133,11 @@ void Logger::initialise(const std::string &id, const Options &options) {
|
|||
|
||||
std::string tempLogFile;
|
||||
|
||||
if ( (envPtr = getTargettedEnv("LOG_FILE")) )
|
||||
if ( (envPtr = getTargettedEnv("LOG_FILE")) ) {
|
||||
tempLogFile = envPtr;
|
||||
else if ( options.mLogFile.size() )
|
||||
} else if ( options.mLogFile.size() ) {
|
||||
tempLogFile = options.mLogFile;
|
||||
else {
|
||||
} else {
|
||||
if ( options.mLogPath.size() ) {
|
||||
mLogPath = options.mLogPath;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
|
|||
tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog;
|
||||
|
||||
// Legacy
|
||||
if ( (envPtr = getenv( "LOG_PRINT" )) )
|
||||
if ( (envPtr = getenv("LOG_PRINT")) )
|
||||
tempTerminalLevel = atoi(envPtr) ? DEBUG9 : NOLOG;
|
||||
|
||||
if ( (envPtr = getTargettedEnv("LOG_LEVEL")) )
|
||||
|
@ -218,7 +218,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
|
|||
|
||||
mFlush = false;
|
||||
if ( (envPtr = getenv("LOG_FLUSH")) ) {
|
||||
mFlush = atoi( envPtr );
|
||||
mFlush = atoi(envPtr);
|
||||
} else if ( config.log_debug ) {
|
||||
mFlush = true;
|
||||
}
|
||||
|
@ -335,6 +335,10 @@ Logger::Level Logger::level(Logger::Level level) {
|
|||
mEffectiveLevel = mSyslogLevel;
|
||||
if ( mEffectiveLevel > mLevel)
|
||||
mEffectiveLevel = mLevel;
|
||||
|
||||
// DEBUG levels should flush
|
||||
if ( mLevel > INFO )
|
||||
mFlush = true;
|
||||
}
|
||||
return mLevel;
|
||||
}
|
||||
|
@ -577,12 +581,12 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
}
|
||||
}
|
||||
|
||||
void logInit( const char *name, const Logger::Options &options ) {
|
||||
void logInit(const char *name, const Logger::Options &options) {
|
||||
if ( !Logger::smInstance )
|
||||
Logger::smInstance = new Logger();
|
||||
Logger::Options tempOptions = options;
|
||||
tempOptions.mLogPath = staticConfig.PATH_LOGS;
|
||||
Logger::smInstance->initialise( name, tempOptions );
|
||||
Logger::smInstance->initialise(name, tempOptions);
|
||||
}
|
||||
|
||||
void logTerm() {
|
||||
|
|
|
@ -423,15 +423,9 @@ Monitor::Monitor(
|
|||
snprintf(monitor_dir, sizeof(monitor_dir), "%s/%d", storage->Path(), id);
|
||||
|
||||
if ( purpose == CAPTURE ) {
|
||||
struct stat statbuf;
|
||||
|
||||
if ( stat(monitor_dir, &statbuf) ) {
|
||||
if ( errno == ENOENT || errno == ENOTDIR ) {
|
||||
if ( mkdir(monitor_dir, 0755) ) {
|
||||
Error("Can't mkdir %s: %s", monitor_dir, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
Warning("Error stat'ing %s, may be fatal. error is %s", monitor_dir, strerror(errno));
|
||||
if ( mkdir(monitor_dir, 0755) ) {
|
||||
if ( errno != EEXIST ) {
|
||||
Error("Can't mkdir %s: %s", monitor_dir, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,16 +603,23 @@ bool Monitor::connect() {
|
|||
next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
next_buffer.timestamp = new struct timeval;
|
||||
}
|
||||
if ( ( purpose == ANALYSIS ) && analysis_fps ) {
|
||||
// Size of pre event buffer must be greater than pre_event_count
|
||||
// if alarm_frame_count > 1, because in this case the buffer contains
|
||||
// alarmed images that must be discarded when event is created
|
||||
pre_event_buffer_count = pre_event_count + alarm_frame_count - 1;
|
||||
pre_event_buffer = new Snapshot[pre_event_buffer_count];
|
||||
for ( int i = 0; i < pre_event_buffer_count; i++ ) {
|
||||
pre_event_buffer[i].timestamp = new struct timeval;
|
||||
pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
}
|
||||
if ( purpose == ANALYSIS ) {
|
||||
if ( analysis_fps ) {
|
||||
// Size of pre event buffer must be greater than pre_event_count
|
||||
// if alarm_frame_count > 1, because in this case the buffer contains
|
||||
// alarmed images that must be discarded when event is created
|
||||
pre_event_buffer_count = pre_event_count + alarm_frame_count - 1;
|
||||
pre_event_buffer = new Snapshot[pre_event_buffer_count];
|
||||
for ( int i = 0; i < pre_event_buffer_count; i++ ) {
|
||||
pre_event_buffer[i].timestamp = new struct timeval;
|
||||
*pre_event_buffer[i].timestamp = {0,0};
|
||||
pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
}
|
||||
}
|
||||
|
||||
timestamps = new struct timeval *[pre_event_count];
|
||||
images = new Image *[pre_event_count];
|
||||
last_signal = shared_data->signal;
|
||||
}
|
||||
Debug(3, "Success connecting");
|
||||
return true;
|
||||
|
@ -1261,6 +1262,7 @@ bool Monitor::Analyse() {
|
|||
|
||||
int index;
|
||||
if ( adaptive_skip ) {
|
||||
// I think the idea behind adaptive skip is if we are falling behind, then skip a bunch, but not all
|
||||
int read_margin = shared_data->last_read_index - shared_data->last_write_index;
|
||||
if ( read_margin < 0 ) read_margin += image_buffer_count;
|
||||
|
||||
|
@ -1274,7 +1276,10 @@ bool Monitor::Analyse() {
|
|||
int pending_frames = shared_data->last_write_index - shared_data->last_read_index;
|
||||
if ( pending_frames < 0 ) pending_frames += image_buffer_count;
|
||||
|
||||
Debug( 4, "ReadIndex:%d, WriteIndex: %d, PendingFrames = %d, ReadMargin = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step );
|
||||
Debug(4,
|
||||
"ReadIndex:%d, WriteIndex: %d, PendingFrames = %d, ReadMargin = %d, Step = %d",
|
||||
shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step
|
||||
);
|
||||
if ( step <= pending_frames ) {
|
||||
index = (shared_data->last_read_index+step)%image_buffer_count;
|
||||
} else {
|
||||
|
@ -1294,17 +1299,17 @@ bool Monitor::Analyse() {
|
|||
if ( shared_data->action ) {
|
||||
// Can there be more than 1 bit set in the action? Shouldn't these be elseifs?
|
||||
if ( shared_data->action & RELOAD ) {
|
||||
Info( "Received reload indication at count %d", image_count );
|
||||
Info("Received reload indication at count %d", image_count);
|
||||
shared_data->action &= ~RELOAD;
|
||||
Reload();
|
||||
}
|
||||
if ( shared_data->action & SUSPEND ) {
|
||||
if ( Active() ) {
|
||||
Info( "Received suspend indication at count %d", image_count );
|
||||
Info("Received suspend indication at count %d", image_count);
|
||||
shared_data->active = false;
|
||||
//closeEvent();
|
||||
} else {
|
||||
Info( "Received suspend indication at count %d, but wasn't active", image_count );
|
||||
Info("Received suspend indication at count %d, but wasn't active", image_count);
|
||||
}
|
||||
if ( config.max_suspend_time ) {
|
||||
auto_resume_time = now.tv_sec + config.max_suspend_time;
|
||||
|
@ -1313,7 +1318,7 @@ bool Monitor::Analyse() {
|
|||
}
|
||||
if ( shared_data->action & RESUME ) {
|
||||
if ( Enabled() && !Active() ) {
|
||||
Info( "Received resume indication at count %d", image_count );
|
||||
Info("Received resume indication at count %d", image_count);
|
||||
shared_data->active = true;
|
||||
ref_image = *snap_image;
|
||||
ready_count = image_count+(warmup_count/2);
|
||||
|
@ -1324,24 +1329,14 @@ bool Monitor::Analyse() {
|
|||
} // end if shared_data->action
|
||||
|
||||
if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) {
|
||||
Info( "Auto resuming at count %d", image_count );
|
||||
Info("Auto resuming at count %d", image_count);
|
||||
shared_data->active = true;
|
||||
ref_image = *snap_image;
|
||||
ready_count = image_count+(warmup_count/2);
|
||||
auto_resume_time = 0;
|
||||
}
|
||||
|
||||
static bool static_undef = true;
|
||||
static int last_section_mod = 0;
|
||||
static bool last_signal;
|
||||
|
||||
if ( static_undef ) {
|
||||
// Sure would be nice to be able to assume that these were already initialized. It's just 1 compare/branch, but really not neccessary.
|
||||
static_undef = false;
|
||||
timestamps = new struct timeval *[pre_event_count];
|
||||
images = new Image *[pre_event_count];
|
||||
last_signal = shared_data->signal;
|
||||
}
|
||||
|
||||
if ( Enabled() ) {
|
||||
bool signal = shared_data->signal;
|
||||
|
@ -1394,27 +1389,24 @@ bool Monitor::Analyse() {
|
|||
|
||||
} else if ( signal && Active() && (function == MODECT || function == MOCORD) ) {
|
||||
Event::StringSet zoneSet;
|
||||
int motion_score = last_motion_score;
|
||||
if ( !(image_count % (motion_frame_skip+1) ) ) {
|
||||
// Get new score.
|
||||
motion_score = DetectMotion(*snap_image, zoneSet);
|
||||
int new_motion_score = DetectMotion(*snap_image, zoneSet);
|
||||
|
||||
Debug(3,
|
||||
"After motion detection, last_motion_score(%d), new motion score(%d)",
|
||||
last_motion_score, motion_score
|
||||
last_motion_score, new_motion_score
|
||||
);
|
||||
// Why are we updating the last_motion_score too?
|
||||
last_motion_score = motion_score;
|
||||
last_motion_score = new_motion_score;
|
||||
}
|
||||
//int motion_score = DetectBlack( *snap_image, zoneSet );
|
||||
if ( motion_score ) {
|
||||
if ( last_motion_score ) {
|
||||
if ( !event ) {
|
||||
score += motion_score;
|
||||
score += last_motion_score;
|
||||
if ( cause.length() )
|
||||
cause += ", ";
|
||||
cause += MOTION_CAUSE;
|
||||
} else {
|
||||
score += motion_score;
|
||||
score += last_motion_score;
|
||||
}
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
} // end if motion_score
|
||||
|
@ -1436,7 +1428,7 @@ bool Monitor::Analyse() {
|
|||
first_link = false;
|
||||
}
|
||||
}
|
||||
noteSet.insert( linked_monitors[i]->Name() );
|
||||
noteSet.insert(linked_monitors[i]->Name());
|
||||
score += 50;
|
||||
}
|
||||
} else {
|
||||
|
@ -1450,14 +1442,15 @@ bool Monitor::Analyse() {
|
|||
//TODO: What happens is the event closes and sets recording to false then recording to true again so quickly that our capture daemon never picks it up. Maybe need a refresh flag?
|
||||
if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) {
|
||||
if ( event ) {
|
||||
//TODO: We shouldn't have to do this every time. Not sure why it clears itself if this isn't here??
|
||||
//snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
||||
Debug( 3, "Detected new event at (%d.%d)", timestamp->tv_sec,timestamp->tv_usec );
|
||||
Debug(3, "Detected new event at (%d.%d)", timestamp->tv_sec, timestamp->tv_usec);
|
||||
|
||||
if ( section_length && ( timestamp->tv_sec >= section_length ) ) {
|
||||
// TODO: Wouldn't this be clearer if we just did something like if now - event->start > section_length ?
|
||||
int section_mod = timestamp->tv_sec % section_length;
|
||||
Debug( 3, "Section length (%d) Last Section Mod(%d), new section mod(%d)", section_length, last_section_mod, section_mod );
|
||||
Debug(3,
|
||||
"Section length (%d) Last Section Mod(%d), new section mod(%d)",
|
||||
section_length, last_section_mod, section_mod
|
||||
);
|
||||
if ( section_mod < last_section_mod ) {
|
||||
//if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) {
|
||||
//if ( state == TAPE ) {
|
||||
|
@ -1480,7 +1473,7 @@ bool Monitor::Analyse() {
|
|||
if ( ! event ) {
|
||||
|
||||
// Create event
|
||||
event = new Event( this, *timestamp, "Continuous", noteSetMap, videoRecording );
|
||||
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
|
||||
shared_data->last_event = event->Id();
|
||||
//set up video store data
|
||||
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
||||
|
@ -1554,6 +1547,10 @@ bool Monitor::Analyse() {
|
|||
int pre_index;
|
||||
int pre_event_images = pre_event_count;
|
||||
|
||||
if ( event ) {
|
||||
// SHouldn't be able to happen because
|
||||
Error("Creating new event when one exists");
|
||||
}
|
||||
if ( analysis_fps && pre_event_count ) {
|
||||
// If analysis fps is set,
|
||||
// compute the index for pre event images in the dedicated buffer
|
||||
|
@ -1576,8 +1573,8 @@ bool Monitor::Analyse() {
|
|||
else
|
||||
pre_index = ((index + image_buffer_count) - pre_event_count)%image_buffer_count;
|
||||
|
||||
Debug(4,"Resulting pre_index(%d) from index(%d) + image_buffer_count(%d) - pre_event_count(%d) % %d",
|
||||
pre_index, index, image_buffer_count, pre_event_count, image_buffer_count);
|
||||
Debug(4,"Resulting pre_index(%d) from index(%d) + image_buffer_count(%d) - pre_event_count(%d)",
|
||||
pre_index, index, image_buffer_count, pre_event_count);
|
||||
|
||||
// Seek forward the next filled slot in to the buffer (oldest data)
|
||||
// from the current position
|
||||
|
@ -1622,7 +1619,6 @@ bool Monitor::Analyse() {
|
|||
pre_index = (pre_index + 1)%image_buffer_count;
|
||||
}
|
||||
}
|
||||
|
||||
event->AddFrames( pre_event_images, images, timestamps );
|
||||
}
|
||||
if ( alarm_frame_count ) {
|
||||
|
@ -2388,10 +2384,9 @@ int Monitor::Capture() {
|
|||
}
|
||||
|
||||
if ( captureResult < 0 ) {
|
||||
Warning("Return from Capture (%d), signal loss", captureResult);
|
||||
Info("Return from Capture (%d), signal loss", captureResult);
|
||||
// Tell zma to end the event. zma will reset TRIGGER
|
||||
trigger_data->trigger_state = TRIGGER_OFF;
|
||||
|
||||
// Unable to capture image for temporary reason
|
||||
// Fake a signal loss image
|
||||
Rgb signalcolor;
|
||||
|
@ -2477,19 +2472,17 @@ int Monitor::Capture() {
|
|||
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
|
||||
Info("%s: images:%d - Capturing at %.2lf fps, capturing bandwidth %ubytes/sec", name, image_count, new_fps, new_capture_bandwidth);
|
||||
last_fps_time = now;
|
||||
if ( new_fps != fps ) {
|
||||
fps = new_fps;
|
||||
|
||||
db_mutex.lock();
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth) VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf, CaptureBandwidth=%u",
|
||||
id, fps, new_capture_bandwidth, fps, new_capture_bandwidth);
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
}
|
||||
db_mutex.unlock();
|
||||
} // end if new_fps != fps
|
||||
fps = new_fps;
|
||||
db_mutex.lock();
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth) VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf, CaptureBandwidth=%u",
|
||||
id, fps, new_capture_bandwidth, fps, new_capture_bandwidth);
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
}
|
||||
db_mutex.unlock();
|
||||
Debug(4,sql);
|
||||
} // end if time has changed since last update
|
||||
} // end if it might be time to report the fps
|
||||
} // end if captureResult
|
||||
|
|
|
@ -254,39 +254,41 @@ protected:
|
|||
VideoWriter videowriter;
|
||||
std::string encoderparams;
|
||||
std::vector<EncoderParameter_t> encoderparamsvec;
|
||||
bool record_audio; // Whether to store the audio that we receive
|
||||
bool record_audio; // Whether to store the audio that we receive
|
||||
|
||||
int brightness; // The statically saved brightness of the camera
|
||||
int contrast; // The statically saved contrast of the camera
|
||||
int hue; // The statically saved hue of the camera
|
||||
int colour; // The statically saved colour of the camera
|
||||
char event_prefix[64]; // The prefix applied to event names as they are created
|
||||
char label_format[64]; // The format of the timestamp on the images
|
||||
Coord label_coord; // The coordinates of the timestamp on the images
|
||||
int label_size; // Size of the timestamp on the images
|
||||
int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count
|
||||
int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate,
|
||||
int brightness; // The statically saved brightness of the camera
|
||||
int contrast; // The statically saved contrast of the camera
|
||||
int hue; // The statically saved hue of the camera
|
||||
int colour; // The statically saved colour of the camera
|
||||
char event_prefix[64]; // The prefix applied to event names as they are created
|
||||
char label_format[64]; // The format of the timestamp on the images
|
||||
Coord label_coord; // The coordinates of the timestamp on the images
|
||||
int label_size; // Size of the timestamp on the images
|
||||
int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count
|
||||
int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate,
|
||||
// value is pre_event_count + alarm_frame_count - 1
|
||||
int warmup_count; // How many images to process before looking for events
|
||||
int pre_event_count; // How many images to hold and prepend to an alarm event
|
||||
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
|
||||
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
|
||||
int section_length; // How long events should last in continuous modes
|
||||
bool adaptive_skip; // Whether to use the newer adaptive algorithm for this monitor
|
||||
int frame_skip; // How many frames to skip in continuous modes
|
||||
int motion_frame_skip; // How many frames to skip in motion detection
|
||||
double analysis_fps; // Target framerate for video analysis
|
||||
int warmup_count; // How many images to process before looking for events
|
||||
int pre_event_count; // How many images to hold and prepend to an alarm event
|
||||
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
|
||||
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
|
||||
int section_length; // How long events should last in continuous modes
|
||||
bool adaptive_skip; // Whether to use the newer adaptive algorithm for this monitor
|
||||
int frame_skip; // How many frames to skip in continuous modes
|
||||
int motion_frame_skip; // How many frames to skip in motion detection
|
||||
double analysis_fps; // Target framerate for video analysis
|
||||
unsigned int analysis_update_delay; // How long we wait before updating analysis parameters
|
||||
int capture_delay; // How long we wait between capture frames
|
||||
int alarm_capture_delay; // How long we wait between capture frames when in alarm state
|
||||
int alarm_frame_count; // How many alarm frames are required before an event is triggered
|
||||
int fps_report_interval; // How many images should be captured/processed between reporting the current FPS
|
||||
int ref_blend_perc; // Percentage of new image going into reference image.
|
||||
int alarm_ref_blend_perc; // Percentage of new image going into reference image during alarm.
|
||||
bool track_motion; // Whether this monitor tries to track detected motion
|
||||
int signal_check_points; // Number of points in the image to check for signal
|
||||
Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected
|
||||
bool embed_exif; // Whether to embed Exif data into each image frame or not
|
||||
int capture_delay; // How long we wait between capture frames
|
||||
int alarm_capture_delay; // How long we wait between capture frames when in alarm state
|
||||
int alarm_frame_count; // How many alarm frames are required before an event is triggered
|
||||
int fps_report_interval; // How many images should be captured/processed between reporting the current FPS
|
||||
int ref_blend_perc; // Percentage of new image going into reference image.
|
||||
int alarm_ref_blend_perc; // Percentage of new image going into reference image during alarm.
|
||||
bool track_motion; // Whether this monitor tries to track detected motion
|
||||
int signal_check_points; // Number of points in the image to check for signal
|
||||
Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected
|
||||
bool embed_exif; // Whether to embed Exif data into each image frame or not
|
||||
|
||||
bool last_signal;
|
||||
|
||||
double fps;
|
||||
unsigned int last_camera_bytes;
|
||||
|
|
|
@ -482,7 +482,7 @@ void MonitorStream::runStream() {
|
|||
swap_path = staticConfig.PATH_SWAP;
|
||||
|
||||
Debug( 3, "Checking swap path folder: %s", swap_path.c_str() );
|
||||
if ( checkSwapPath(swap_path.c_str(), false) ) {
|
||||
if ( checkSwapPath(swap_path.c_str(), true) ) {
|
||||
swap_path += stringtf("/zmswap-m%d", monitor->Id());
|
||||
|
||||
Debug(4, "Checking swap path subfolder: %s", swap_path.c_str());
|
||||
|
@ -633,7 +633,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
|
|||
// Send the next frame
|
||||
Monitor::Snapshot *snap = &monitor->image_buffer[index];
|
||||
|
||||
//Debug(2, "sending Frame.");
|
||||
Debug(2, "sending Frame.");
|
||||
if ( !sendFrame(snap->image, snap->timestamp) ) {
|
||||
Debug(2, "sendFrame failed, quiting.");
|
||||
zm_terminate = true;
|
||||
|
@ -687,7 +687,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
|
|||
} // end if buffered playback
|
||||
frame_count++;
|
||||
} else {
|
||||
Debug(5,"Waiting for capture");
|
||||
Debug(4,"Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
|
||||
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
|
||||
|
||||
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
||||
|
|
|
@ -267,7 +267,20 @@ bool StreamBase::sendTextFrame( const char *frame_text ) {
|
|||
void StreamBase::openComms() {
|
||||
if ( connkey > 0 ) {
|
||||
|
||||
unsigned int length = snprintf(sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", staticConfig.PATH_SOCKS.c_str(), connkey);
|
||||
// Have to mkdir because systemd is now chrooting and the dir may not exist
|
||||
if ( mkdir(staticConfig.PATH_SOCKS.c_str(), 0755) ) {
|
||||
if ( errno != EEXIST ) {
|
||||
Error("Can't mkdir ZM_PATH_SOCKS %s: %s.", staticConfig.PATH_SOCKS.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int length = snprintf(
|
||||
sock_path_lock,
|
||||
sizeof(sock_path_lock),
|
||||
"%s/zms-%06d.lock",
|
||||
staticConfig.PATH_SOCKS.c_str(),
|
||||
connkey
|
||||
);
|
||||
if ( length >= sizeof(sock_path_lock) ) {
|
||||
Warning("Socket lock path was truncated.");
|
||||
}
|
||||
|
@ -275,14 +288,14 @@ void StreamBase::openComms() {
|
|||
|
||||
lock_fd = open(sock_path_lock, O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if ( lock_fd <= 0 ) {
|
||||
Error("Unable to open sock lock file %s: %s", sock_path_lock, strerror(errno) );
|
||||
Error("Unable to open sock lock file %s: %s", sock_path_lock, strerror(errno));
|
||||
lock_fd = 0;
|
||||
} else if ( flock(lock_fd, LOCK_EX) != 0 ) {
|
||||
Error("Unable to lock sock lock file %s: %s", sock_path_lock, strerror(errno) );
|
||||
Error("Unable to lock sock lock file %s: %s", sock_path_lock, strerror(errno));
|
||||
close(lock_fd);
|
||||
lock_fd = 0;
|
||||
} else {
|
||||
Debug( 1, "We have obtained a lock on %s fd: %d", sock_path_lock, lock_fd);
|
||||
Debug(1, "We have obtained a lock on %s fd: %d", sock_path_lock, lock_fd);
|
||||
}
|
||||
|
||||
sd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
|
@ -292,7 +305,13 @@ void StreamBase::openComms() {
|
|||
Debug(1, "Have socket %d", sd);
|
||||
}
|
||||
|
||||
length = snprintf(loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", staticConfig.PATH_SOCKS.c_str(), connkey);
|
||||
length = snprintf(
|
||||
loc_sock_path,
|
||||
sizeof(loc_sock_path),
|
||||
"%s/zms-%06ds.sock",
|
||||
staticConfig.PATH_SOCKS.c_str(),
|
||||
connkey
|
||||
);
|
||||
if ( length >= sizeof(loc_sock_path) ) {
|
||||
Warning("Socket path was truncated.");
|
||||
length = sizeof(loc_sock_path)-1;
|
||||
|
|
|
@ -64,7 +64,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
}
|
||||
|
||||
// Couldn't deduce format from filename, trying from format name
|
||||
if (!oc) {
|
||||
if ( !oc ) {
|
||||
avformat_alloc_output_context2(&oc, NULL, format, filename);
|
||||
if (!oc) {
|
||||
Error(
|
||||
|
@ -108,7 +108,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
Debug(2, "Success creating video out stream");
|
||||
}
|
||||
|
||||
if (!video_out_ctx->codec_tag) {
|
||||
if ( !video_out_ctx->codec_tag ) {
|
||||
video_out_ctx->codec_tag =
|
||||
av_codec_get_tag(oc->oformat->codec_tag, video_in_ctx->codec_id);
|
||||
Debug(2, "No codec_tag, setting to %d", video_out_ctx->codec_tag);
|
||||
|
@ -127,9 +127,10 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
|
||||
#else
|
||||
video_out_stream =
|
||||
avformat_new_stream(oc,(AVCodec *)(video_in_ctx->codec));
|
||||
avformat_new_stream(oc, NULL);
|
||||
//(AVCodec *)(video_in_ctx->codec));
|
||||
//avformat_new_stream(oc,(const AVCodec *)(video_in_ctx->codec));
|
||||
if (!video_out_stream) {
|
||||
if ( !video_out_stream ) {
|
||||
Fatal("Unable to create video out stream\n");
|
||||
} else {
|
||||
Debug(2, "Success creating video out stream");
|
||||
|
@ -158,6 +159,9 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
|
||||
// Just copy them from the in, no reason to choose different
|
||||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
if ( ! (video_out_ctx->time_base.num && video_out_ctx->time_base.den) ) {
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
}
|
||||
video_out_stream->time_base = video_in_stream->time_base;
|
||||
|
||||
Debug(3,
|
||||
|
@ -339,6 +343,9 @@ bool VideoStore::open() {
|
|||
if (ret < 0) {
|
||||
Error("Error occurred when writing out file header to %s: %s\n",
|
||||
filename, av_make_error_string(ret).c_str());
|
||||
/* free the stream */
|
||||
avio_closep(&oc->pb);
|
||||
//avformat_free_context(oc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -412,7 +419,7 @@ VideoStore::~VideoStore() {
|
|||
if (int rc = av_write_trailer(oc)) {
|
||||
Error("Error writing trailer %s", av_err2str(rc));
|
||||
} else {
|
||||
Debug(3, "Sucess Writing trailer");
|
||||
Debug(3, "Success Writing trailer");
|
||||
}
|
||||
|
||||
// When will we not be using a file ?
|
||||
|
@ -426,7 +433,7 @@ VideoStore::~VideoStore() {
|
|||
} else {
|
||||
Debug(3, "Not closing avio because we are not writing to a file.");
|
||||
}
|
||||
}
|
||||
} // end if ( oc->pb )
|
||||
// I wonder if we should be closing the file first.
|
||||
// I also wonder if we really need to be doing all the ctx
|
||||
// allocation/de-allocation constantly, or whether we can just re-use it.
|
||||
|
@ -535,7 +542,10 @@ bool VideoStore::setup_resampler() {
|
|||
audio_out_ctx->channels = audio_in_ctx->channels;
|
||||
audio_out_ctx->channel_layout = audio_in_ctx->channel_layout;
|
||||
audio_out_ctx->sample_fmt = audio_in_ctx->sample_fmt;
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
#else
|
||||
audio_out_ctx->refcounted_frames = 1;
|
||||
#endif
|
||||
|
||||
if (audio_out_codec->supported_samplerates) {
|
||||
int found = 0;
|
||||
|
|
|
@ -83,7 +83,7 @@ int main( int argc, char *argv[] ) {
|
|||
while (1) {
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
|
||||
int c = getopt_long(argc, argv, "m:h:v", long_options, &option_index);
|
||||
if ( c == -1 ) {
|
||||
break;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ int main( int argc, char *argv[] ) {
|
|||
unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay();
|
||||
time_t last_analysis_update_time, cur_time;
|
||||
monitor->UpdateAdaptiveSkip();
|
||||
last_analysis_update_time = time( 0 );
|
||||
last_analysis_update_time = time(0);
|
||||
|
||||
while( (!zm_terminate) && monitor->ShmValid() ) {
|
||||
// Process the next image
|
||||
|
@ -181,5 +181,5 @@ int main( int argc, char *argv[] ) {
|
|||
Image::Deinitialise();
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -300,19 +300,22 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) {
|
||||
if ( monitors[i]->PreCapture() < 0 ) {
|
||||
Error("Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
Error("Failed to pre-capture monitor %d %d (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if ( monitors[i]->Capture() < 0 ) {
|
||||
Error("Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
Info("Failed to capture image from monitor %d %s (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if ( monitors[i]->PostCapture() < 0 ) {
|
||||
Error("Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
Error("Failed to post-capture monitor %d %s (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
result = -1;
|
||||
break;
|
||||
|
|
|
@ -93,7 +93,8 @@ if [ "$RELEASE" != "" ]; then
|
|||
else
|
||||
GITHUB_FORK="ZoneMinder";
|
||||
fi
|
||||
BRANCH="release-$RELEASE"
|
||||
# We use a tag instead of a branch atm.
|
||||
BRANCH=$RELEASE
|
||||
else
|
||||
if [ "$GITHUB_FORK" == "" ]; then
|
||||
echo "Defaulting to ZoneMinder upstream git"
|
||||
|
@ -162,8 +163,19 @@ if [ $? -ne 0 ]; then
|
|||
fi;
|
||||
cd "$DIRECTORY.orig";
|
||||
|
||||
# Init submodules
|
||||
git submodule init
|
||||
git submodule update --init --recursive
|
||||
|
||||
# Cleanup
|
||||
rm -rf .git
|
||||
rm .gitignore
|
||||
cd ../
|
||||
|
||||
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
|
||||
cd $DIRECTORY.orig
|
||||
|
||||
# Generate Changlog
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then
|
||||
mv distros/ubuntu1204 debian
|
||||
else
|
||||
|
@ -221,12 +233,6 @@ zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY
|
|||
EOF
|
||||
fi;
|
||||
|
||||
rm -rf .git
|
||||
rm .gitignore
|
||||
cd ../
|
||||
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
|
||||
cd $DIRECTORY.orig
|
||||
|
||||
if [ $TYPE == "binary" ]; then
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control file
|
||||
sudo apt-get install devscripts equivs
|
||||
|
@ -287,7 +293,8 @@ else
|
|||
SC="zoneminder_${VERSION}-${DISTRO}${PACKAGE_VERSION}_source.changes";
|
||||
PPA="";
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder";
|
||||
IFS='.' read -r -a VERSION <<< "$RELEASE"
|
||||
PPA="ppa:iconnor/zoneminder-${VERSION[0]}.${VERSION[1]}"
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-master";
|
||||
|
|
|
@ -110,7 +110,7 @@ class Monitor extends AppModel {
|
|||
);
|
||||
public $actsAs = array(
|
||||
'CakePHP-Enum-Behavior.Enum' => array(
|
||||
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL'),
|
||||
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite'),
|
||||
'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'),
|
||||
'Orientation' => array('0','90','180','270','hori','vert'),
|
||||
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
ZoneMinder uses certain 3rd party media assets/libraries for UI display purposes. Their licenses are listed in this file
|
||||
|
||||
### Material Design icons
|
||||
|
||||
Origin: https://github.com/google/material-design-icons
|
||||
|
||||
License: Apache 2.0 (https://github.com/google/material-design-icons/blob/master/LICENSE)
|
||||
|
||||
### Glyphicon halflings font
|
||||
|
||||
Origin: http://www.glyphicons.com/
|
||||
|
||||
License: MIT, As clarified below (http://www.glyphicons.com/license/)
|
||||
|
||||
```
|
||||
License for GLYPHICONS Halflings in Bootstrap
|
||||
|
||||
GLYPHICONS Halflings font is also released as an extension of a Bootstrap www.getbootstrap.com for free and
|
||||
it is released under the same license as Bootstrap. While you are not required to include attribution on your
|
||||
Bootstrap-based projects, I would certainly appreciate any form of support, even a nice Tweet is enough.
|
||||
Of course if you want, you can say thank you and support me by buying more icons on GLYPHICONS.com.
|
||||
|
||||
Jan Kovařík
|
||||
```
|
||||
|
||||
ZoneMinder uses Bootstrap for UI and qualifies as a Bootstrap-based project.
|
||||
Bootstrap is MIT licensed (https://github.com/twbs/bootstrap/blob/v4.1.3/LICENSE)
|
||||
|
||||
|
||||
|
|
@ -190,6 +190,12 @@ echo output_link_if_exists( array(
|
|||
<?php } ?>
|
||||
<script src="<?php echo cache_bust($skinJsFile) ?>"></script>
|
||||
<script src="js/logger.js"></script>
|
||||
<?php
|
||||
if ($basename == 'watch') {
|
||||
// This is used in the log popup for the export function. Not sure if it's used anywhere else
|
||||
?>
|
||||
<script type="text/javascript" src="js/overlay.js"></script>
|
||||
<?php } ?>
|
||||
<?php
|
||||
if ( $viewJsFile ) {
|
||||
?>
|
||||
|
|
|
@ -44,7 +44,7 @@ if ( $_REQUEST['filter']['sql'] ) {
|
|||
$countSql .= $_REQUEST['filter']['sql'];
|
||||
$eventsSql .= $_REQUEST['filter']['sql'];
|
||||
}
|
||||
$eventsSql .= " ORDER BY $sortColumn $sortOrder";
|
||||
$eventsSql .= " ORDER BY $sortColumn $sortOrder,Id $sortOrder";
|
||||
|
||||
$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 0;
|
||||
$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : 0;
|
||||
|
|
|
@ -70,8 +70,8 @@ session_start();
|
|||
$layout_id = '';
|
||||
if ( isset($_COOKIE['zmMontageLayout']) ) {
|
||||
$layout_id = $_SESSION['zmMontageLayout'] = $_COOKIE['zmMontageLayout'];
|
||||
} elseif ( isset($_SESSION['zmMontageLayout']) ) {
|
||||
$layout_id = $_SESSION['zmMontageLayout'];
|
||||
#} elseif ( isset($_SESSION['zmMontageLayout']) ) {
|
||||
#$layout_id = $_SESSION['zmMontageLayout'];
|
||||
}
|
||||
|
||||
$options = array();
|
||||
|
@ -87,15 +87,15 @@ if ( $Layout and ( $Layout->Name() != 'Freeform' ) ) {
|
|||
|
||||
if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] ) {
|
||||
$_SESSION['zmMontageWidth'] = $options['width'] = $_COOKIE['zmMontageWidth'];
|
||||
} elseif ( isset($_SESSION['zmMontageWidth']) and $_SESSION['zmMontageWidth'] ) {
|
||||
$options['width'] = $_SESSION['zmMontageWidth'];
|
||||
#} elseif ( isset($_SESSION['zmMontageWidth']) and $_SESSION['zmMontageWidth'] ) {
|
||||
#$options['width'] = $_SESSION['zmMontageWidth'];
|
||||
} else
|
||||
$options['width'] = '';
|
||||
|
||||
if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] )
|
||||
$_SESSION['zmMontageHeight'] = $options['height'] = $_COOKIE['zmMontageHeight'];
|
||||
else if ( isset($_SESSION['zmMontageHeight']) and $_SESSION['zmMontageHeight'] )
|
||||
$options['height'] = $_SESSION['zmMontageHeight'];
|
||||
#else if ( isset($_SESSION['zmMontageHeight']) and $_SESSION['zmMontageHeight'] )
|
||||
#$options['height'] = $_SESSION['zmMontageHeight'];
|
||||
else
|
||||
$options['height'] = '';
|
||||
|
||||
|
@ -134,7 +134,7 @@ xhtmlHeaders(__FILE__, translate('Montage'));
|
|||
<body>
|
||||
<div id="page">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">  
|
||||
<div id="header">
|
||||
<a href="#"><span id="hdrbutton" class="glyphicon glyphicon-menu-up pull-right"></span></a>
|
||||
<div id="flipMontageHeader">
|
||||
<div id="headerButtons">
|
||||
|
|
Loading…
Reference in New Issue