Merge branch 'master' into update_monitor_saving
commit
458268d866
|
@ -37,8 +37,16 @@ env:
|
|||
- SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=disco
|
||||
- SMPFLAGS=-j4 OS=debian DIST=buster
|
||||
- SMPFLAGS=-j4 OS=debian DIST=stretch
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=ubuntu DIST=disco ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=debian DIST=stretch ARCH=i386
|
||||
- SMPFLAGS=-j4 OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack
|
||||
|
||||
compiler:
|
||||
|
|
|
@ -7,6 +7,7 @@ Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh
|
|||
,cmake
|
||||
,libx264-dev, libmp4v2-dev
|
||||
,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev
|
||||
,libavresample-dev
|
||||
,libbz2-dev
|
||||
,libgcrypt-dev
|
||||
,libcurl4-gnutls-dev
|
||||
|
|
|
@ -134,7 +134,7 @@ sub Path {
|
|||
|
||||
if ( ! $$event{Path} ) {
|
||||
my $Storage = $event->Storage();
|
||||
if ( defined $Storage->Id() ) {
|
||||
if ( (!$$event{StorageId}) or defined $Storage->Id() ) {
|
||||
$$event{Path} = join('/', $Storage->Path(), $event->RelativePath());
|
||||
} else {
|
||||
Error("Storage area for $$event{StorageId} no longer exists in db.");
|
||||
|
|
|
@ -282,6 +282,7 @@ MAIN: while( $loop ) {
|
|||
}
|
||||
#Event path is hour/minute/sec
|
||||
my $event_path = readlink($event_link);
|
||||
$event_path = '' if ! defined($event_path);
|
||||
Debug("Checking link $event_link points to: $event_path");
|
||||
|
||||
if ( !($event_path and -e $event_path) ) {
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
#include "zm_utils.h"
|
||||
|
||||
// Note that Error and Debug calls won't actually go anywhere unless you
|
||||
// set the relevant ENV vars because the logger gets it's setting from the
|
||||
// config.
|
||||
|
||||
void zmLoadConfig() {
|
||||
|
||||
// Process name, value pairs from the main config file first
|
||||
|
@ -40,22 +44,22 @@ void zmLoadConfig() {
|
|||
DIR* configSubFolder = opendir(ZM_CONFIG_SUBDIR);
|
||||
if ( configSubFolder ) { // subfolder exists and is readable
|
||||
char glob_pattern[PATH_MAX] = "";
|
||||
snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.conf", ZM_CONFIG_SUBDIR );
|
||||
snprintf(glob_pattern, sizeof(glob_pattern), "%s/*.conf", ZM_CONFIG_SUBDIR);
|
||||
|
||||
glob_t pglob;
|
||||
int glob_status = glob( glob_pattern, 0, 0, &pglob );
|
||||
int glob_status = glob(glob_pattern, 0, 0, &pglob);
|
||||
if ( glob_status != 0 ) {
|
||||
if ( glob_status < 0 ) {
|
||||
Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) );
|
||||
Error("Can't glob '%s': %s", glob_pattern, strerror(errno));
|
||||
} else {
|
||||
Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status );
|
||||
Debug(1, "Can't glob '%s': %d", glob_pattern, glob_status);
|
||||
}
|
||||
} else {
|
||||
for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) {
|
||||
process_configfile(pglob.gl_pathv[i]);
|
||||
}
|
||||
}
|
||||
globfree( &pglob );
|
||||
globfree(&pglob);
|
||||
closedir(configSubFolder);
|
||||
}
|
||||
|
||||
|
@ -64,59 +68,60 @@ void zmLoadConfig() {
|
|||
config.Assign();
|
||||
|
||||
// Populate the server config entries
|
||||
if ( ! staticConfig.SERVER_ID ) {
|
||||
if ( ! staticConfig.SERVER_NAME.empty() ) {
|
||||
if ( !staticConfig.SERVER_ID ) {
|
||||
if ( !staticConfig.SERVER_NAME.empty() ) {
|
||||
|
||||
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
|
||||
std::string sql = stringtf("SELECT `Id` FROM `Servers` WHERE `Name`='%s'", staticConfig.SERVER_NAME.c_str() );
|
||||
Debug(1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str());
|
||||
std::string sql = stringtf("SELECT `Id` FROM `Servers` WHERE `Name`='%s'",
|
||||
staticConfig.SERVER_NAME.c_str());
|
||||
zmDbRow dbrow;
|
||||
if ( dbrow.fetch( sql.c_str() ) ) {
|
||||
if ( dbrow.fetch(sql.c_str()) ) {
|
||||
staticConfig.SERVER_ID = atoi(dbrow[0]);
|
||||
} else {
|
||||
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() );
|
||||
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str());
|
||||
}
|
||||
|
||||
} // end if has SERVER_NAME
|
||||
} else if ( staticConfig.SERVER_NAME.empty() ) {
|
||||
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
|
||||
std::string sql = stringtf("SELECT `Name` FROM `Servers` WHERE `Id`='%d'", staticConfig.SERVER_ID );
|
||||
Debug(1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID);
|
||||
std::string sql = stringtf("SELECT `Name` FROM `Servers` WHERE `Id`='%d'", staticConfig.SERVER_ID);
|
||||
|
||||
zmDbRow dbrow;
|
||||
if ( dbrow.fetch( sql.c_str() ) ) {
|
||||
if ( dbrow.fetch(sql.c_str()) ) {
|
||||
staticConfig.SERVER_NAME = std::string(dbrow[0]);
|
||||
} else {
|
||||
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
|
||||
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID);
|
||||
}
|
||||
|
||||
if ( staticConfig.SERVER_ID ) {
|
||||
Debug( 3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID );
|
||||
Debug(3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID);
|
||||
} else {
|
||||
Debug( 3, "Single server configuration assumed because no Server ID or Name was specified." );
|
||||
Debug(3, "Single server configuration assumed because no Server ID or Name was specified.");
|
||||
}
|
||||
}
|
||||
|
||||
snprintf( staticConfig.capture_file_format, sizeof(staticConfig.capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits );
|
||||
snprintf( staticConfig.analyse_file_format, sizeof(staticConfig.analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits );
|
||||
snprintf( staticConfig.general_file_format, sizeof(staticConfig.general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits );
|
||||
snprintf( staticConfig.video_file_format, sizeof(staticConfig.video_file_format), "%%s/%%s");
|
||||
snprintf(staticConfig.capture_file_format, sizeof(staticConfig.capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits);
|
||||
snprintf(staticConfig.analyse_file_format, sizeof(staticConfig.analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits);
|
||||
snprintf(staticConfig.general_file_format, sizeof(staticConfig.general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits);
|
||||
snprintf(staticConfig.video_file_format, sizeof(staticConfig.video_file_format), "%%s/%%s");
|
||||
}
|
||||
|
||||
void process_configfile( char* configFile) {
|
||||
void process_configfile(char* configFile) {
|
||||
FILE *cfg;
|
||||
char line[512];
|
||||
if ( (cfg = fopen( configFile, "r")) == NULL ) {
|
||||
Fatal( "Can't open %s: %s", configFile, strerror(errno) );
|
||||
if ( (cfg = fopen(configFile, "r")) == NULL ) {
|
||||
Fatal("Can't open %s: %s", configFile, strerror(errno));
|
||||
return;
|
||||
}
|
||||
while ( fgets( line, sizeof(line), cfg ) != NULL ) {
|
||||
while ( fgets(line, sizeof(line), cfg) != NULL ) {
|
||||
char *line_ptr = line;
|
||||
|
||||
// Trim off any cr/lf line endings
|
||||
int chomp_len = strcspn( line_ptr, "\r\n" );
|
||||
int chomp_len = strcspn(line_ptr, "\r\n");
|
||||
line_ptr[chomp_len] = '\0';
|
||||
|
||||
// Remove leading white space
|
||||
int white_len = strspn( line_ptr, " \t" );
|
||||
int white_len = strspn(line_ptr, " \t");
|
||||
line_ptr += white_len;
|
||||
|
||||
// Check for comment or empty line
|
||||
|
@ -131,9 +136,9 @@ void process_configfile( char* configFile) {
|
|||
}
|
||||
|
||||
// Now look for the '=' in the middle of the line
|
||||
temp_ptr = strchr( line_ptr, '=' );
|
||||
temp_ptr = strchr(line_ptr, '=');
|
||||
if ( !temp_ptr ) {
|
||||
Warning( "Invalid data in %s: '%s'", configFile, line );
|
||||
Warning("Invalid data in %s: '%s'", configFile, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -148,49 +153,49 @@ void process_configfile( char* configFile) {
|
|||
} while ( *temp_ptr == ' ' || *temp_ptr == '\t' );
|
||||
|
||||
// Remove leading white space and leading quotes from the value part
|
||||
white_len = strspn( val_ptr, " \t" );
|
||||
white_len += strspn( val_ptr, "\'\"" );
|
||||
white_len = strspn(val_ptr, " \t");
|
||||
white_len += strspn(val_ptr, "\'\"");
|
||||
val_ptr += white_len;
|
||||
|
||||
if ( strcasecmp( name_ptr, "ZM_DB_HOST" ) == 0 )
|
||||
if ( strcasecmp(name_ptr, "ZM_DB_HOST") == 0 )
|
||||
staticConfig.DB_HOST = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_NAME" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_NAME") == 0 )
|
||||
staticConfig.DB_NAME = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_USER" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_USER") == 0 )
|
||||
staticConfig.DB_USER = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_PASS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_PASS") == 0 )
|
||||
staticConfig.DB_PASS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_SSL_CA_CERT" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_SSL_CA_CERT") == 0 )
|
||||
staticConfig.DB_SSL_CA_CERT = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_SSL_CLIENT_KEY" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_SSL_CLIENT_KEY") == 0 )
|
||||
staticConfig.DB_SSL_CLIENT_KEY = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DB_SSL_CLIENT_CERT" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DB_SSL_CLIENT_CERT") == 0 )
|
||||
staticConfig.DB_SSL_CLIENT_CERT = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_WEB") == 0 )
|
||||
staticConfig.PATH_WEB = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_SERVER_HOST" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_SERVER_HOST") == 0 )
|
||||
staticConfig.SERVER_NAME = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_SERVER_NAME" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_SERVER_NAME") == 0 )
|
||||
staticConfig.SERVER_NAME = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_SERVER_ID") == 0 )
|
||||
staticConfig.SERVER_ID = atoi(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DIR_EVENTS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DIR_EVENTS") == 0 )
|
||||
staticConfig.DIR_EVENTS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DIR_SOUNDS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DIR_SOUNDS") == 0 )
|
||||
staticConfig.DIR_SOUNDS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_DIR_EXPORTS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_DIR_EXPORTS") == 0 )
|
||||
staticConfig.DIR_EXPORTS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_ZMS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_ZMS") == 0 )
|
||||
staticConfig.PATH_ZMS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_MAP" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_MAP") == 0 )
|
||||
staticConfig.PATH_MAP = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_SOCKS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_SOCKS") == 0 )
|
||||
staticConfig.PATH_SOCKS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_LOGS" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_LOGS") == 0 )
|
||||
staticConfig.PATH_LOGS = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_SWAP" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_SWAP") == 0 )
|
||||
staticConfig.PATH_SWAP = std::string(val_ptr);
|
||||
else if ( strcasecmp( name_ptr, "ZM_PATH_ARP" ) == 0 )
|
||||
else if ( strcasecmp(name_ptr, "ZM_PATH_ARP") == 0 )
|
||||
staticConfig.PATH_ARP = std::string(val_ptr);
|
||||
else {
|
||||
// We ignore this now as there may be more parameters than the
|
||||
|
@ -198,18 +203,18 @@ void process_configfile( char* configFile) {
|
|||
// Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG );
|
||||
}
|
||||
} // end foreach line of the config
|
||||
fclose( cfg );
|
||||
fclose(cfg);
|
||||
}
|
||||
|
||||
StaticConfig staticConfig;
|
||||
|
||||
ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *const p_type ) {
|
||||
ConfigItem::ConfigItem(const char *p_name, const char *p_value, const char *const p_type) {
|
||||
name = new char[strlen(p_name)+1];
|
||||
strcpy( name, p_name );
|
||||
strcpy(name, p_name);
|
||||
value = new char[strlen(p_value)+1];
|
||||
strcpy( value, p_value );
|
||||
strcpy(value, p_value);
|
||||
type = new char[strlen(p_type)+1];
|
||||
strcpy( type, p_type );
|
||||
strcpy(type, p_type);
|
||||
|
||||
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
|
||||
|
||||
|
@ -217,28 +222,28 @@ ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *con
|
|||
accessed = false;
|
||||
}
|
||||
|
||||
ConfigItem::ConfigItem( const ConfigItem &item ) {
|
||||
ConfigItem::ConfigItem(const ConfigItem &item) {
|
||||
name = new char[strlen(item.name)+1];
|
||||
strcpy( name, item.name );
|
||||
strcpy(name, item.name);
|
||||
value = new char[strlen(item.value)+1];
|
||||
strcpy( value, item.value );
|
||||
strcpy(value, item.value);
|
||||
type = new char[strlen(item.type)+1];
|
||||
strcpy( type, item.type );
|
||||
strcpy(type, item.type);
|
||||
|
||||
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
|
||||
|
||||
accessed = false;
|
||||
}
|
||||
void ConfigItem::Copy( const ConfigItem &item ) {
|
||||
void ConfigItem::Copy(const ConfigItem &item) {
|
||||
if (name) delete name;
|
||||
name = new char[strlen(item.name)+1];
|
||||
strcpy( name, item.name );
|
||||
strcpy(name, item.name);
|
||||
if (value) delete value;
|
||||
value = new char[strlen(item.value)+1];
|
||||
strcpy( value, item.value );
|
||||
strcpy(value, item.value);
|
||||
if (type) delete type;
|
||||
type = new char[strlen(item.type)+1];
|
||||
strcpy( type, item.type );
|
||||
strcpy(type, item.type);
|
||||
|
||||
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
|
||||
accessed = false;
|
||||
|
@ -253,16 +258,16 @@ ConfigItem::~ConfigItem() {
|
|||
void ConfigItem::ConvertValue() const {
|
||||
if ( !strcmp( type, "boolean" ) ) {
|
||||
cfg_type = CFG_BOOLEAN;
|
||||
cfg_value.boolean_value = (bool)strtol( value, 0, 0 );
|
||||
} else if ( !strcmp( type, "integer" ) ) {
|
||||
cfg_value.boolean_value = (bool)strtol(value, 0, 0);
|
||||
} else if ( !strcmp(type, "integer") ) {
|
||||
cfg_type = CFG_INTEGER;
|
||||
cfg_value.integer_value = strtol( value, 0, 10 );
|
||||
} else if ( !strcmp( type, "hexadecimal" ) ) {
|
||||
cfg_value.integer_value = strtol(value, 0, 10);
|
||||
} else if ( !strcmp(type, "hexadecimal") ) {
|
||||
cfg_type = CFG_INTEGER;
|
||||
cfg_value.integer_value = strtol( value, 0, 16 );
|
||||
} else if ( !strcmp( type, "decimal" ) ) {
|
||||
cfg_value.integer_value = strtol(value, 0, 16);
|
||||
} else if ( !strcmp(type, "decimal") ) {
|
||||
cfg_type = CFG_DECIMAL;
|
||||
cfg_value.decimal_value = strtod( value, 0 );
|
||||
cfg_value.decimal_value = strtod(value, 0);
|
||||
} else {
|
||||
cfg_type = CFG_STRING;
|
||||
cfg_value.string_value = value;
|
||||
|
@ -275,11 +280,11 @@ bool ConfigItem::BooleanValue() const {
|
|||
ConvertValue();
|
||||
|
||||
if ( cfg_type != CFG_BOOLEAN ) {
|
||||
Error( "Attempt to fetch boolean value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type );
|
||||
exit( -1 );
|
||||
Error("Attempt to fetch boolean value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return( cfg_value.boolean_value );
|
||||
return cfg_value.boolean_value;
|
||||
}
|
||||
|
||||
int ConfigItem::IntegerValue() const {
|
||||
|
@ -287,11 +292,11 @@ int ConfigItem::IntegerValue() const {
|
|||
ConvertValue();
|
||||
|
||||
if ( cfg_type != CFG_INTEGER ) {
|
||||
Error( "Attempt to fetch integer value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type );
|
||||
exit( -1 );
|
||||
Error("Attempt to fetch integer value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return( cfg_value.integer_value );
|
||||
return cfg_value.integer_value;
|
||||
}
|
||||
|
||||
double ConfigItem::DecimalValue() const {
|
||||
|
@ -299,11 +304,11 @@ double ConfigItem::DecimalValue() const {
|
|||
ConvertValue();
|
||||
|
||||
if ( cfg_type != CFG_DECIMAL ) {
|
||||
Error( "Attempt to fetch decimal value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type );
|
||||
exit( -1 );
|
||||
Error("Attempt to fetch decimal value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return( cfg_value.decimal_value );
|
||||
return cfg_value.decimal_value;
|
||||
}
|
||||
|
||||
const char *ConfigItem::StringValue() const {
|
||||
|
@ -311,11 +316,11 @@ const char *ConfigItem::StringValue() const {
|
|||
ConvertValue();
|
||||
|
||||
if ( cfg_type != CFG_STRING ) {
|
||||
Error( "Attempt to fetch string value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type );
|
||||
exit( -1 );
|
||||
Error("Attempt to fetch string value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return( cfg_value.string_value );
|
||||
return cfg_value.string_value;
|
||||
}
|
||||
|
||||
Config::Config() {
|
||||
|
@ -337,54 +342,54 @@ Config::~Config() {
|
|||
void Config::Load() {
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
|
||||
strncpy( sql, "select Name, Value, Type from Config order by Id", sizeof(sql) );
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
strncpy(sql, "SELECT `Name`, `Value`, `Type` FROM `Config` ORDER BY `Id`", sizeof(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 );
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if ( !result ) {
|
||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
n_items = mysql_num_rows( result );
|
||||
n_items = mysql_num_rows(result);
|
||||
|
||||
if ( n_items <= ZM_MAX_CFG_ID ) {
|
||||
Error( "Config mismatch, expected %d items, read %d. Try running 'zmupdate.pl -f' to reload config.", ZM_MAX_CFG_ID+1, n_items );
|
||||
exit( -1 );
|
||||
Error("Config mismatch, expected %d items, read %d. Try running 'zmupdate.pl -f' to reload config.", ZM_MAX_CFG_ID+1, n_items);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
items = new ConfigItem *[n_items];
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
|
||||
items[i] = new ConfigItem( dbrow[0], dbrow[1], dbrow[2] );
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
|
||||
items[i] = new ConfigItem(dbrow[0], dbrow[1], dbrow[2]);
|
||||
}
|
||||
mysql_free_result( result );
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
void Config::Assign() {
|
||||
ZM_CFG_ASSIGN_LIST
|
||||
}
|
||||
|
||||
const ConfigItem &Config::Item( int id ) {
|
||||
const ConfigItem &Config::Item(int id) {
|
||||
if ( !n_items ) {
|
||||
Load();
|
||||
Assign();
|
||||
}
|
||||
|
||||
if ( id < 0 || id > ZM_MAX_CFG_ID ) {
|
||||
Error( "Attempt to access invalid config, id = %d. Try running 'zmupdate.pl -f' to reload config.", id );
|
||||
exit( -1 );
|
||||
Error("Attempt to access invalid config, id = %d. Try running 'zmupdate.pl -f' to reload config.", id);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ConfigItem *item = items[id];
|
||||
|
||||
if ( !item ) {
|
||||
Error( "Can't find config item %d", id );
|
||||
exit( -1 );
|
||||
Error("Can't find config item %d", id);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return( *item );
|
||||
return *item;
|
||||
}
|
||||
|
||||
Config config;
|
||||
|
|
|
@ -32,7 +32,7 @@ bool zmDbConnect() {
|
|||
// For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu
|
||||
// But they really need to be here in order to prevent a double open of mysql
|
||||
if ( zmDbConnected ) {
|
||||
Warning("Calling zmDbConnect when already connected");
|
||||
//Warning("Calling zmDbConnect when already connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -294,7 +294,6 @@ bool Event::WriteFrameImage(Image *image, struct timeval timestamp, const char *
|
|||
|
||||
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
|
||||
bool rc;
|
||||
Debug(3, "Writing image to %s", event_file);
|
||||
|
||||
if ( !config.timestamp_on_capture ) {
|
||||
// stash the image we plan to use in another pointer regardless if timestamped.
|
||||
|
@ -550,7 +549,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
|
|||
static char event_file[PATH_MAX];
|
||||
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
|
||||
Debug(1, "Writing capture frame %d to %s", frames, event_file);
|
||||
if ( ! WriteFrameImage(image, timestamp, event_file) ) {
|
||||
if ( !WriteFrameImage(image, timestamp, event_file) ) {
|
||||
Error("Failed to write frame image");
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -289,9 +289,10 @@ static void zm_log_fps(double d, const char *postfix) {
|
|||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
void zm_dump_codecpar ( const AVCodecParameters *par ) {
|
||||
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)",
|
||||
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d %s) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)",
|
||||
par->codec_type,
|
||||
par->codec_id,
|
||||
avcodec_get_name(par->codec_id),
|
||||
par->codec_tag,
|
||||
par->width,
|
||||
par->height,
|
||||
|
@ -303,10 +304,11 @@ void zm_dump_codecpar ( const AVCodecParameters *par ) {
|
|||
#endif
|
||||
|
||||
void zm_dump_codec(const AVCodecContext *codec) {
|
||||
Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)\n"
|
||||
Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d %s) width(%d) height(%d) timebase(%d/%d) format(%s) "
|
||||
"gop_size %d max_b_frames %d me_cmp %d me_range %d qmin %d qmax %d",
|
||||
codec->codec_type,
|
||||
codec->codec_id,
|
||||
avcodec_get_name(codec->codec_id),
|
||||
codec->width,
|
||||
codec->height,
|
||||
codec->time_base.num,
|
||||
|
@ -327,7 +329,6 @@ void zm_dump_codec(const AVCodecContext *codec) {
|
|||
|
||||
/* "user interface" functions */
|
||||
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
|
||||
char buf[256];
|
||||
Debug(1, "Dumping stream index i(%d) index(%d)", i, index );
|
||||
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
|
||||
AVStream *st = ic->streams[i];
|
||||
|
@ -350,8 +351,14 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
|
|||
st->codec_info_nb_frames, codec->frame_size,
|
||||
st->time_base.num, st->time_base.den
|
||||
);
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
Debug(1, "codec: %s", avcodec_get_name(st->codecpar->codec_id));
|
||||
#else
|
||||
char buf[256];
|
||||
avcodec_string(buf, sizeof(buf), st->codec, is_output);
|
||||
Debug(1, "codec: %s", buf);
|
||||
#endif
|
||||
|
||||
if ( st->sample_aspect_ratio.num && // default
|
||||
av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio)
|
||||
|
@ -427,6 +434,35 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
|
|||
dst->stream_index = src->stream_index;
|
||||
return 0;
|
||||
}
|
||||
const char *avcodec_get_name(enum AVCodecID id) {
|
||||
const AVCodecDescriptor *cd;
|
||||
if ( id == AV_CODEC_ID_NONE)
|
||||
return "none";
|
||||
cd = avcodec_descriptor_get(id);
|
||||
if (cd)
|
||||
return cd->name;
|
||||
AVCodec *codec;
|
||||
codec = avcodec_find_decoder(id);
|
||||
if (codec)
|
||||
return codec->name;
|
||||
codec = avcodec_find_encoder(id);
|
||||
if (codec)
|
||||
return codec->name;
|
||||
return "unknown codec";
|
||||
}
|
||||
|
||||
void av_packet_rescale_ts(
|
||||
AVPacket *pkt,
|
||||
AVRational src_tb,
|
||||
AVRational dst_tb
|
||||
) {
|
||||
if ( pkt->pts != AV_NOPTS_VALUE)
|
||||
pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb);
|
||||
if ( pkt->dts != AV_NOPTS_VALUE)
|
||||
pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
|
||||
if ( pkt->duration != AV_NOPTS_VALUE)
|
||||
pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_video_stream( AVStream * stream ) {
|
||||
|
@ -477,7 +513,31 @@ bool is_audio_context( AVCodecContext *codec_context ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet) {
|
||||
int zm_receive_packet(AVCodecContext *context, AVPacket &packet) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
int ret = avcodec_receive_packet(context, &packet);
|
||||
if ( ret < 0 ) {
|
||||
if ( AVERROR_EOF != ret ) {
|
||||
Error("Error encoding (%d) (%s)", ret,
|
||||
av_err2str(ret));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
int got_packet = 0;
|
||||
int ret = avcodec_encode_audio2(context, &packet, NULL, &got_packet);
|
||||
if ( ret < 0 ) {
|
||||
Error("Error encoding (%d) (%s)", ret, av_err2str(ret));
|
||||
}
|
||||
return got_packet;
|
||||
#endif
|
||||
} // end int zm_receive_packet(AVCodecContext *context, AVPacket &packet)
|
||||
|
||||
int zm_send_packet_receive_frame(
|
||||
AVCodecContext *context,
|
||||
AVFrame *frame,
|
||||
AVPacket &packet) {
|
||||
int ret;
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
if ( (ret = avcodec_send_packet(context, &packet)) < 0 ) {
|
||||
|
@ -487,8 +547,14 @@ int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
|
|||
}
|
||||
|
||||
if ( (ret = avcodec_receive_frame(context, frame)) < 0 ) {
|
||||
Error("Unable to send packet %s, continuing",
|
||||
av_make_error_string(ret).c_str());
|
||||
if ( AVERROR(EAGAIN) == ret ) {
|
||||
// The codec may need more samples than it has, perfectly valid
|
||||
Debug(2, "Codec not ready to give us a frame");
|
||||
return 0;
|
||||
} else {
|
||||
Error("Could not recieve frame (error %d = '%s')", ret,
|
||||
av_make_error_string(ret).c_str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
# else
|
||||
|
@ -505,29 +571,31 @@ int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
|
|||
}
|
||||
} // end while !frameComplete
|
||||
#endif
|
||||
return 0;
|
||||
} // end int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
|
||||
return 1;
|
||||
} // end int zm_send_packet_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
|
||||
|
||||
int zm_send_frame(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
|
||||
/* Returns < 0 on error, 0 if codec not ready, 1 on success
|
||||
*/
|
||||
int zm_send_frame_receive_packet(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
|
||||
int ret;
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
if ( (ret = avcodec_send_frame(ctx, frame)) < 0 ) {
|
||||
Error("Could not send frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&packet);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( (ret = avcodec_receive_packet(ctx, &packet)) < 0 ) {
|
||||
if ( AVERROR(EAGAIN) == ret ) {
|
||||
// The codec may need more samples than it has, perfectly valid
|
||||
Debug(2, "Codec not ready to give us a packet");
|
||||
return 0;
|
||||
} else {
|
||||
Error("Could not recieve packet (error %d = '%s')", ret,
|
||||
av_make_error_string(ret).c_str());
|
||||
}
|
||||
zm_av_packet_unref(&packet);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int data_present;
|
||||
|
@ -536,7 +604,7 @@ int zm_send_frame(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
|
|||
Error("Could not encode frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&packet);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
if ( !data_present ) {
|
||||
Debug(2, "Not ready to out a frame yet.");
|
||||
|
@ -545,7 +613,7 @@ int zm_send_frame(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
|
|||
}
|
||||
#endif
|
||||
return 1;
|
||||
} // wend zm_send_frame
|
||||
} // end int zm_send_frame_receive_packet
|
||||
|
||||
void dumpPacket(AVStream *stream, AVPacket *pkt, const char *text) {
|
||||
char b[10240];
|
||||
|
@ -600,3 +668,117 @@ void dumpPacket(AVPacket *pkt, const char *text) {
|
|||
pkt->duration);
|
||||
Debug(2, "%s:%d:%s: %s", __FILE__, __LINE__, text, b);
|
||||
}
|
||||
|
||||
void zm_packet_copy_rescale_ts(const AVPacket *ipkt, AVPacket *opkt, const AVRational src_tb, const AVRational dst_tb) {
|
||||
opkt->pts = ipkt->pts;
|
||||
opkt->dts = ipkt->dts;
|
||||
opkt->duration = ipkt->duration;
|
||||
av_packet_rescale_ts(opkt, src_tb, dst_tb);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
|
||||
int zm_resample_audio(
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
SwrContext *resample_ctx,
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
AVAudioResampleContext *resample_ctx,
|
||||
#endif
|
||||
#endif
|
||||
AVFrame *in_frame,
|
||||
AVFrame *out_frame
|
||||
) {
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
// Resample the in_frame into the audioSampleBuffer until we process the whole
|
||||
// decoded data. Note: pts does not survive resampling or converting
|
||||
Debug(2, "Converting %d to %d samples using swresample",
|
||||
in_frame->nb_samples, out_frame->nb_samples);
|
||||
int ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not resample frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
Debug(3,"swr_get_delay %d",
|
||||
swr_get_delay(resample_ctx, out_frame->sample_rate));
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
int ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
|
||||
0, in_frame->nb_samples);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not resample frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
int samples_available = avresample_available(resample_ctx);
|
||||
if ( samples_available < out_frame->nb_samples ) {
|
||||
Debug(1, "Not enough samples yet (%d)", samples_available);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read a frame audio data from the resample fifo
|
||||
if ( avresample_read(resample_ctx, out_frame->data, out_frame->nb_samples) !=
|
||||
out_frame->nb_samples) {
|
||||
Warning("Error reading resampled audio.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
zm_dump_frame(out_frame, "Out frame after resample");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zm_resample_get_delay(
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
SwrContext *resample_ctx,
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
AVAudioResampleContext *resample_ctx,
|
||||
#endif
|
||||
#endif
|
||||
int time_base
|
||||
) {
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
return swr_get_delay(resample_ctx, time_base);
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
return avresample_available(resample_ctx);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int zm_add_samples_to_fifo(AVAudioFifo *fifo, AVFrame *frame) {
|
||||
int ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not reallocate FIFO to %d samples",
|
||||
av_audio_fifo_size(fifo) + frame->nb_samples);
|
||||
return 0;
|
||||
}
|
||||
/** Store the new samples in the FIFO buffer. */
|
||||
ret = av_audio_fifo_write(fifo, (void **)frame->data, frame->nb_samples);
|
||||
if ( ret < frame->nb_samples ) {
|
||||
Error("Could not write data to FIFO. %d written, expecting %d. Reason %s",
|
||||
ret, frame->nb_samples, av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zm_get_samples_from_fifo(AVAudioFifo *fifo, AVFrame *frame) {
|
||||
// AAC requires 1024 samples per encode. Our input tends to be something else, so need to buffer them.
|
||||
if ( frame->nb_samples > av_audio_fifo_size(fifo) ) {
|
||||
Debug(1, "Not enough samples in fifo for AAC codec frame_size %d > fifo size %d",
|
||||
frame->nb_samples, av_audio_fifo_size(fifo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( av_audio_fifo_read(fifo, (void **)frame->data, frame->nb_samples) < frame->nb_samples ) {
|
||||
Error("Could not read data from FIFO");
|
||||
return 0;
|
||||
}
|
||||
//out_frame->nb_samples = frame_size;
|
||||
zm_dump_frame(frame, "Out frame after fifo read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
#ifdef HAVE_LIBSWRESAMPLE
|
||||
#include "libswresample/swresample.h"
|
||||
#else
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
#include "libavresample/avresample.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// AVUTIL
|
||||
#if HAVE_LIBAVUTIL_AVUTIL_H
|
||||
#include "libavutil/avassert.h"
|
||||
|
@ -31,6 +39,7 @@ extern "C" {
|
|||
#include <libavutil/base64.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/avstring.h>
|
||||
#include "libavutil/audio_fifo.h"
|
||||
|
||||
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
||||
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
||||
|
@ -299,23 +308,6 @@ void zm_dump_codec(const AVCodecContext *codec);
|
|||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
void zm_dump_codecpar(const AVCodecParameters *par);
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
||||
#define zm_dump_frame(frame, text) Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d" \
|
||||
" duration %" PRId64 \
|
||||
" layout %d pts %" PRId64 " pkt_pts %" PRId64 " pkt_dts %" PRId64, \
|
||||
text, \
|
||||
frame->format, \
|
||||
av_get_sample_fmt_name((AVSampleFormat)frame->format), \
|
||||
frame->sample_rate, \
|
||||
frame->nb_samples, \
|
||||
frame->channels, \
|
||||
frame->pkt_duration, \
|
||||
frame->channel_layout, \
|
||||
frame->pts, \
|
||||
frame->pkt_pts, \
|
||||
frame->pkt_dts \
|
||||
);
|
||||
#else
|
||||
#define zm_dump_frame(frame, text) Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d" \
|
||||
" duration %" PRId64 \
|
||||
" layout %d pts %" PRId64, \
|
||||
|
@ -329,8 +321,6 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
|||
frame->pts \
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
|
||||
text, \
|
||||
frame->format, \
|
||||
|
@ -347,6 +337,9 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
|||
#else
|
||||
unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src );
|
||||
#define zm_av_packet_unref( packet ) av_free_packet( packet )
|
||||
const char *avcodec_get_name(AVCodecID id);
|
||||
|
||||
void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb);
|
||||
#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 )
|
||||
|
@ -371,9 +364,42 @@ bool is_audio_stream(AVStream *);
|
|||
bool is_video_context(AVCodec *);
|
||||
bool is_audio_context(AVCodec *);
|
||||
|
||||
int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
||||
int zm_send_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
||||
int zm_receive_packet(AVCodecContext *context, AVPacket &packet);
|
||||
|
||||
int zm_send_packet_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
||||
int zm_send_frame_receive_packet(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
||||
|
||||
void dumpPacket(AVStream *, AVPacket *,const char *text="");
|
||||
void dumpPacket(AVPacket *,const char *text="");
|
||||
void zm_packet_copy_rescale_ts(const AVPacket *ipkt, AVPacket *opkt, const AVRational src_tb, const AVRational dst_tb);
|
||||
|
||||
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
|
||||
int zm_resample_audio(
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
SwrContext *resample_ctx,
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
AVAudioResampleContext *resample_ctx,
|
||||
#endif
|
||||
#endif
|
||||
AVFrame *in_frame,
|
||||
AVFrame *out_frame
|
||||
);
|
||||
int zm_resample_get_delay(
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
SwrContext *resample_ctx,
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
AVAudioResampleContext *resample_ctx,
|
||||
#endif
|
||||
#endif
|
||||
int time_base
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
int zm_add_samples_to_fifo(AVAudioFifo *fifo, AVFrame *frame);
|
||||
int zm_get_samples_from_fifo(AVAudioFifo *fifo, AVFrame *frame);
|
||||
|
||||
|
||||
#endif // ZM_FFMPEG_H
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "zm.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_utils.h"
|
||||
|
||||
#if HAVE_LIBAVFORMAT
|
||||
|
||||
|
@ -35,11 +36,6 @@ extern "C" {
|
|||
#define AV_ERROR_MAX_STRING_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
#include <sys/errno.h> // for ESRCH
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
|
||||
|
@ -260,8 +256,8 @@ int FfmpegCamera::Capture(Image &image) {
|
|||
&&
|
||||
(keyframe || have_video_keyframe)
|
||||
) {
|
||||
ret = zm_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
||||
if ( ret < 0 ) {
|
||||
ret = zm_send_packet_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
||||
if ( ret <= 0 ) {
|
||||
Error("Unable to get frame at frame %d: %s, continuing",
|
||||
frameCount, av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&packet);
|
||||
|
@ -337,24 +333,27 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
}
|
||||
|
||||
// Set transport method as specified by method field, rtpUni is default
|
||||
const std::string method = Method();
|
||||
if ( method == "rtpMulti" ) {
|
||||
ret = av_dict_set(&opts, "rtsp_transport", "udp_multicast", 0);
|
||||
} else if ( method == "rtpRtsp" ) {
|
||||
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());
|
||||
}
|
||||
std::string protocol = mPath.substr(0, 4);
|
||||
string_toupper(protocol);
|
||||
if ( protocol == "RTSP" ) {
|
||||
const std::string method = Method();
|
||||
if ( method == "rtpMulti" ) {
|
||||
ret = av_dict_set(&opts, "rtsp_transport", "udp_multicast", 0);
|
||||
} else if ( method == "rtpRtsp" ) {
|
||||
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());
|
||||
}
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not set rtsp_transport method '%s'", method.c_str());
|
||||
}
|
||||
} // end if RTSP
|
||||
// #av_dict_set(&opts, "timeout", "10000000", 0); // in microseconds.
|
||||
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not set rtsp_transport method '%s'", method.c_str());
|
||||
}
|
||||
|
||||
Debug(1, "Calling avformat_open_input for %s", mPath.c_str());
|
||||
|
||||
mFormatContext = avformat_alloc_context();
|
||||
|
@ -650,6 +649,9 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
) {
|
||||
Warning("Monitor dimensions are %dx%d but camera is sending %dx%d",
|
||||
width, height, mVideoCodecContext->width, mVideoCodecContext->height);
|
||||
} else {
|
||||
Warning("Monitor dimensions are %dx%d and camera is sending %dx%d",
|
||||
width, height, mVideoCodecContext->width, mVideoCodecContext->height);
|
||||
}
|
||||
|
||||
mCanCapture = true;
|
||||
|
@ -952,8 +954,8 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
}
|
||||
} // end if keyframe or have_video_keyframe
|
||||
|
||||
ret = zm_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
||||
if ( ret < 0 ) {
|
||||
ret = zm_send_packet_receive_frame(mVideoCodecContext, mRawFrame, packet);
|
||||
if ( ret <= 0 ) {
|
||||
Warning("Unable to receive frame %d: %s. error count is %d",
|
||||
frameCount, av_make_error_string(ret).c_str(), error_count);
|
||||
error_count += 1;
|
||||
|
|
|
@ -137,8 +137,8 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
|
|||
} else {
|
||||
frame = zm_av_frame_alloc();
|
||||
}
|
||||
ret = zm_receive_frame(context, frame, packet);
|
||||
if ( ret < 0 ) {
|
||||
ret = zm_send_packet_receive_frame(context, frame, packet);
|
||||
if ( ret <= 0 ) {
|
||||
Error("Unable to decode frame at frame %d: %s, continuing",
|
||||
streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&packet);
|
||||
|
|
|
@ -1,31 +1,27 @@
|
|||
//
|
||||
// ZoneMinder File Camera Class Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -45,8 +41,20 @@ FileCamera::FileCamera(
|
|||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio
|
||||
) : Camera( p_id, FILE_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 )
|
||||
bool p_record_audio)
|
||||
: Camera(
|
||||
p_id,
|
||||
FILE_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)
|
||||
{
|
||||
strncpy( path, p_path, sizeof(path)-1 );
|
||||
if ( capture ) {
|
||||
|
@ -62,8 +70,7 @@ FileCamera::~FileCamera() {
|
|||
|
||||
void FileCamera::Initialise() {
|
||||
if ( !path[0] ) {
|
||||
Error( "No path specified for file image" );
|
||||
exit( -1 );
|
||||
Fatal("No path specified for file image");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,21 +79,25 @@ void FileCamera::Terminate() {
|
|||
|
||||
int FileCamera::PreCapture() {
|
||||
struct stat statbuf;
|
||||
if ( stat( path, &statbuf ) < 0 ) {
|
||||
Error( "Can't stat %s: %s", path, strerror(errno) );
|
||||
return( -1 );
|
||||
if ( stat(path, &statbuf) < 0 ) {
|
||||
Error("Can't stat %s: %s", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
bytes += statbuf.st_size;
|
||||
|
||||
// This waits until 1 second has passed since it was modified. Effectively limiting fps to 60.
|
||||
// Which is kinda bogus. If we were writing to this jpg constantly faster than we are monitoring it here
|
||||
// we would never break out of this loop
|
||||
while ( (time(0) - statbuf.st_mtime) < 1 ) {
|
||||
usleep( 100000 );
|
||||
usleep(100000);
|
||||
}
|
||||
return( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileCamera::Capture( Image &image ) {
|
||||
return( image.ReadJpeg( path, colours, subpixelorder )?1:-1 );
|
||||
int FileCamera::Capture(Image &image) {
|
||||
return image.ReadJpeg(path, colours, subpixelorder)?1:-1;
|
||||
}
|
||||
|
||||
int FileCamera::PostCapture() {
|
||||
return( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
|
398
src/zm_image.cpp
398
src/zm_image.cpp
File diff suppressed because it is too large
Load Diff
|
@ -55,7 +55,7 @@ static void subtractTime( struct timeval * const tp1, struct timeval * const tp2
|
|||
}
|
||||
#endif
|
||||
|
||||
void Logger::usrHandler( int sig ) {
|
||||
void Logger::usrHandler(int sig) {
|
||||
Logger *logger = fetch();
|
||||
if ( sig == SIGUSR1 )
|
||||
logger->level(logger->level()+1);
|
||||
|
@ -71,9 +71,9 @@ Logger::Logger() :
|
|||
mFileLevel(NOLOG),
|
||||
mSyslogLevel(NOLOG),
|
||||
mEffectiveLevel(NOLOG),
|
||||
//mLogPath( staticConfig.PATH_LOGS.c_str() ),
|
||||
//mLogFile( mLogPath+"/"+mId+".log" ),
|
||||
mDbConnected(false),
|
||||
mLogPath(staticConfig.PATH_LOGS.c_str()),
|
||||
//mLogFile( mLogPath+"/"+mId+".log" ),
|
||||
mLogFileFP(NULL),
|
||||
mHasTerminal(false),
|
||||
mFlush(false) {
|
||||
|
@ -106,9 +106,11 @@ Logger::Logger() :
|
|||
smInitialised = true;
|
||||
}
|
||||
|
||||
if ( fileno(stderr) && isatty(fileno(stderr)) )
|
||||
if ( fileno(stderr) && isatty(fileno(stderr)) ) {
|
||||
mHasTerminal = true;
|
||||
}
|
||||
mTerminalLevel = WARNING;
|
||||
}
|
||||
} // End Logger::Logger
|
||||
|
||||
Logger::~Logger() {
|
||||
terminate();
|
||||
|
@ -138,7 +140,8 @@ void Logger::initialise(const std::string &id, const Options &options) {
|
|||
} else if ( options.mLogFile.size() ) {
|
||||
tempLogFile = options.mLogFile;
|
||||
} else {
|
||||
if ( options.mLogPath.size() ) {
|
||||
// options.mLogPath defaults to '.' so only use it if we don't already have a path
|
||||
if ( (!mLogPath.size()) || options.mLogPath != "." ) {
|
||||
mLogPath = options.mLogPath;
|
||||
}
|
||||
tempLogFile = mLogPath+"/"+mId+".log";
|
||||
|
@ -240,7 +243,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
|
|||
|
||||
mInitialised = true;
|
||||
|
||||
Debug(1, "LogOpts: level=%s/%s, screen=%s, database=%s, logfile=%s->%s, syslog=%s",
|
||||
Debug(1, "LogOpts: level=%s effective=%s, screen=%s, database=%s, logfile=%s->%s, syslog=%s",
|
||||
smCodes[mLevel].c_str(),
|
||||
smCodes[mEffectiveLevel].c_str(),
|
||||
smCodes[mTerminalLevel].c_str(),
|
||||
|
@ -297,7 +300,7 @@ const std::string &Logger::id(const std::string &id) {
|
|||
|
||||
size_t pos;
|
||||
// Remove whitespace
|
||||
while ( (pos = tempId.find_first_of( " \t" )) != std::string::npos ) {
|
||||
while ( (pos = tempId.find_first_of(" \t")) != std::string::npos ) {
|
||||
tempId.replace(pos, 1, "");
|
||||
}
|
||||
// Replace non-alphanum with underscore
|
||||
|
@ -341,7 +344,7 @@ Logger::Level Logger::level(Logger::Level level) {
|
|||
return mLevel;
|
||||
}
|
||||
|
||||
Logger::Level Logger::terminalLevel( Logger::Level terminalLevel ) {
|
||||
Logger::Level Logger::terminalLevel(Logger::Level terminalLevel) {
|
||||
if ( terminalLevel > NOOPT ) {
|
||||
if ( !mHasTerminal )
|
||||
terminalLevel = NOLOG;
|
||||
|
@ -352,34 +355,35 @@ Logger::Level Logger::terminalLevel( Logger::Level terminalLevel ) {
|
|||
return mTerminalLevel;
|
||||
}
|
||||
|
||||
Logger::Level Logger::databaseLevel( Logger::Level databaseLevel ) {
|
||||
Logger::Level Logger::databaseLevel(Logger::Level databaseLevel) {
|
||||
if ( databaseLevel > NOOPT ) {
|
||||
databaseLevel = limit(databaseLevel);
|
||||
if ( mDatabaseLevel != databaseLevel ) {
|
||||
if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) {
|
||||
zmDbConnect();
|
||||
} // end if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG )
|
||||
if ( !zmDbConnect() ) {
|
||||
databaseLevel = NOLOG;
|
||||
}
|
||||
} // end if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG )
|
||||
mDatabaseLevel = databaseLevel;
|
||||
} // end if ( mDatabaseLevel != databaseLevel )
|
||||
} // end if ( databaseLevel > NOOPT )
|
||||
} // end if ( mDatabaseLevel != databaseLevel )
|
||||
} // end if ( databaseLevel > NOOPT )
|
||||
|
||||
return mDatabaseLevel;
|
||||
}
|
||||
|
||||
Logger::Level Logger::fileLevel( Logger::Level fileLevel ) {
|
||||
Logger::Level Logger::fileLevel(Logger::Level fileLevel) {
|
||||
if ( fileLevel > NOOPT ) {
|
||||
fileLevel = limit(fileLevel);
|
||||
// Always close, because we may have changed file names
|
||||
if ( mFileLevel > NOLOG )
|
||||
closeFile();
|
||||
mFileLevel = fileLevel;
|
||||
if ( mFileLevel > NOLOG )
|
||||
openFile();
|
||||
// Don't try to open it here because it will create the log file even if we never write to it.
|
||||
}
|
||||
return mFileLevel;
|
||||
}
|
||||
|
||||
Logger::Level Logger::syslogLevel( Logger::Level syslogLevel ) {
|
||||
Logger::Level Logger::syslogLevel(Logger::Level syslogLevel) {
|
||||
if ( syslogLevel > NOOPT ) {
|
||||
syslogLevel = limit(syslogLevel);
|
||||
if ( mSyslogLevel != syslogLevel ) {
|
||||
|
@ -393,7 +397,7 @@ Logger::Level Logger::syslogLevel( Logger::Level syslogLevel ) {
|
|||
return mSyslogLevel;
|
||||
}
|
||||
|
||||
void Logger::logFile( const std::string &logFile ) {
|
||||
void Logger::logFile(const std::string &logFile) {
|
||||
bool addLogPid = false;
|
||||
std::string tempLogFile = logFile;
|
||||
if ( tempLogFile[tempLogFile.length()-1] == '+' ) {
|
||||
|
@ -401,16 +405,16 @@ void Logger::logFile( const std::string &logFile ) {
|
|||
addLogPid = true;
|
||||
}
|
||||
if ( addLogPid )
|
||||
mLogFile = stringtf( "%s.%05d", tempLogFile.c_str(), getpid() );
|
||||
mLogFile = stringtf("%s.%05d", tempLogFile.c_str(), getpid());
|
||||
else
|
||||
mLogFile = tempLogFile;
|
||||
}
|
||||
|
||||
void Logger::openFile() {
|
||||
if ( mLogFile.size() ) {
|
||||
if ( (mLogFileFP = fopen(mLogFile.c_str() ,"a")) == (FILE *)NULL ) {
|
||||
if ( (mLogFileFP = fopen(mLogFile.c_str(), "a")) == (FILE *)NULL ) {
|
||||
mFileLevel = NOLOG;
|
||||
Fatal( "fopen() for %s, error = %s", mLogFile.c_str(), strerror(errno) );
|
||||
Error("fopen() for %s, error = %s", mLogFile.c_str(), strerror(errno));
|
||||
}
|
||||
} else {
|
||||
puts("Called Logger::openFile() without a filename");
|
||||
|
@ -419,29 +423,33 @@ void Logger::openFile() {
|
|||
|
||||
void Logger::closeFile() {
|
||||
if ( mLogFileFP ) {
|
||||
fflush( mLogFileFP );
|
||||
if ( fclose( mLogFileFP ) < 0 ) {
|
||||
Fatal( "fclose(), error = %s",strerror(errno) );
|
||||
fflush(mLogFileFP);
|
||||
if ( fclose(mLogFileFP) < 0 ) {
|
||||
mLogFileFP = (FILE *)NULL;
|
||||
Error("fclose(), error = %s", strerror(errno));
|
||||
}
|
||||
mLogFileFP = (FILE *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::closeDatabase() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Logger::openSyslog() {
|
||||
(void) openlog( mId.c_str(), LOG_PID|LOG_NDELAY, LOG_LOCAL1 );
|
||||
(void) openlog(mId.c_str(), LOG_PID|LOG_NDELAY, LOG_LOCAL1);
|
||||
}
|
||||
|
||||
void Logger::closeSyslog() {
|
||||
(void) closelog();
|
||||
}
|
||||
|
||||
void Logger::logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ) {
|
||||
if ( level > mEffectiveLevel )
|
||||
void Logger::logPrint(bool hex, const char * const filepath, const int line, const int level, const char *fstring, ...) {
|
||||
|
||||
if ( level > mEffectiveLevel ) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_mutex.lock();
|
||||
char timeString[64];
|
||||
char logString[8192];
|
||||
|
@ -479,24 +487,24 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
thr_self(&lwpid);
|
||||
tid = lwpid;
|
||||
|
||||
if (tid < 0 ) // Thread/Process id
|
||||
if ( tid < 0 ) // Thread/Process id
|
||||
#else
|
||||
#ifdef HAVE_SYSCALL
|
||||
#ifdef __FreeBSD_kernel__
|
||||
#ifdef HAVE_SYSCALL
|
||||
#ifdef __FreeBSD_kernel__
|
||||
if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id
|
||||
|
||||
# else
|
||||
# else
|
||||
// SOLARIS doesn't have SYS_gettid; don't assume
|
||||
#ifdef SYS_gettid
|
||||
if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id
|
||||
#endif // SYS_gettid
|
||||
#ifdef SYS_gettid
|
||||
if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id
|
||||
#endif // SYS_gettid
|
||||
#endif
|
||||
#endif // HAVE_SYSCALL
|
||||
#endif
|
||||
#endif // HAVE_SYSCALL
|
||||
#endif
|
||||
tid = getpid(); // Process id
|
||||
tid = getpid(); // Process id
|
||||
|
||||
char *logPtr = logString;
|
||||
logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [",
|
||||
logPtr += snprintf(logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [",
|
||||
timeString,
|
||||
mId.c_str(),
|
||||
tid,
|
||||
|
@ -520,32 +528,39 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
}
|
||||
va_end(argPtr);
|
||||
char *syslogEnd = logPtr;
|
||||
strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) );
|
||||
strncpy(logPtr, "]\n", sizeof(logString)-(logPtr-logString));
|
||||
|
||||
if ( level <= mTerminalLevel ) {
|
||||
puts( logString );
|
||||
fflush( stdout );
|
||||
puts(logString);
|
||||
fflush(stdout);
|
||||
}
|
||||
if ( level <= mFileLevel ) {
|
||||
if ( !mLogFileFP )
|
||||
openFile();
|
||||
if ( mLogFileFP ) {
|
||||
fputs( logString, mLogFileFP );
|
||||
fputs(logString, mLogFileFP);
|
||||
if ( mFlush )
|
||||
fflush( mLogFileFP );
|
||||
fflush(mLogFileFP);
|
||||
} else {
|
||||
puts("Logging to file, but file not open\n");
|
||||
puts("Logging to file, but failed to open it\n");
|
||||
}
|
||||
#if 0
|
||||
} else {
|
||||
printf("Not writing to log file because level %d %s <= mFileLevel %d %s\nstring: %s\n",
|
||||
level, smCodes[level].c_str(), mFileLevel, smCodes[mFileLevel].c_str(), logString);
|
||||
#endif
|
||||
}
|
||||
*syslogEnd = '\0';
|
||||
if ( level <= mDatabaseLevel ) {
|
||||
char sql[ZM_SQL_MED_BUFSIZ];
|
||||
char escapedString[(strlen(syslogStart)*2)+1];
|
||||
|
||||
if ( ! db_mutex.trylock() ) {
|
||||
mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) );
|
||||
if ( !db_mutex.trylock() ) {
|
||||
mysql_real_escape_string(&dbconn, escapedString, syslogStart, strlen(syslogStart));
|
||||
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Logs "
|
||||
"( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line )"
|
||||
"INSERT INTO `Logs` "
|
||||
"( `TimeKey`, `Component`, `ServerId`, `Pid`, `Level`, `Code`, `Message`, `File`, `Line` )"
|
||||
" VALUES "
|
||||
"( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )",
|
||||
timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line
|
||||
|
@ -567,7 +582,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
if ( level <= mSyslogLevel ) {
|
||||
int priority = smSyslogPriorities[level];
|
||||
//priority |= LOG_DAEMON;
|
||||
syslog( priority, "%s [%s] [%s]", classString, mId.c_str(), syslogStart );
|
||||
syslog(priority, "%s [%s] [%s]", classString, mId.c_str(), syslogStart);
|
||||
}
|
||||
|
||||
free(filecopy);
|
||||
|
@ -580,15 +595,16 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
exit(-1);
|
||||
}
|
||||
log_mutex.unlock();
|
||||
}
|
||||
|
||||
} // end logPrint
|
||||
|
||||
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);
|
||||
if ( Logger::smInstance ) {
|
||||
delete Logger::smInstance;
|
||||
Logger::smInstance = NULL;
|
||||
}
|
||||
|
||||
Logger::smInstance = new Logger();
|
||||
Logger::smInstance->initialise(name, options);
|
||||
}
|
||||
|
||||
void logTerm() {
|
||||
|
|
|
@ -36,12 +36,12 @@ class Logger {
|
|||
public:
|
||||
enum {
|
||||
NOOPT=-6,
|
||||
NOLOG,
|
||||
PANIC,
|
||||
FATAL,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
NOLOG, // -5
|
||||
PANIC, // -4
|
||||
FATAL, // -3
|
||||
ERROR, // -2
|
||||
WARNING, // -1
|
||||
INFO, // 0
|
||||
DEBUG1,
|
||||
DEBUG2,
|
||||
DEBUG3,
|
||||
|
@ -68,14 +68,20 @@ public:
|
|||
std::string mLogPath;
|
||||
std::string mLogFile;
|
||||
|
||||
public:
|
||||
Options( Level terminalLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) :
|
||||
mTerminalLevel( terminalLevel ),
|
||||
mDatabaseLevel( databaseLevel ),
|
||||
mFileLevel( fileLevel ),
|
||||
mSyslogLevel( syslogLevel ),
|
||||
mLogPath( logPath ),
|
||||
mLogFile( logFile )
|
||||
Options(
|
||||
Level terminalLevel=NOOPT,
|
||||
Level databaseLevel=NOOPT,
|
||||
Level fileLevel=NOOPT,
|
||||
Level syslogLevel=NOOPT,
|
||||
const std::string &logPath=".",
|
||||
const std::string &logFile=""
|
||||
) :
|
||||
mTerminalLevel(terminalLevel),
|
||||
mDatabaseLevel(databaseLevel),
|
||||
mFileLevel(fileLevel),
|
||||
mSyslogLevel(syslogLevel),
|
||||
mLogPath(logPath),
|
||||
mLogFile(logFile)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -89,21 +95,21 @@ private:
|
|||
static StringMap smCodes;
|
||||
static IntMap smSyslogPriorities;
|
||||
|
||||
private:
|
||||
bool mInitialised;
|
||||
|
||||
std::string mId;
|
||||
std::string mIdRoot;
|
||||
std::string mIdArgs;
|
||||
|
||||
Level mLevel; // Level that is currently in operation
|
||||
Level mLevel; // Level that is currently in operation
|
||||
Level mTerminalLevel; // Maximum level output via terminal
|
||||
Level mDatabaseLevel; // Maximum level output via database
|
||||
Level mFileLevel; // Maximum level output via file
|
||||
Level mSyslogLevel; // Maximum level output via syslog
|
||||
Level mEffectiveLevel; // Level optimised to take account of maxima
|
||||
Level mDatabaseLevel; // Maximum level output via database
|
||||
Level mFileLevel; // Maximum level output via file
|
||||
Level mSyslogLevel; // Maximum level output via syslog
|
||||
Level mEffectiveLevel; // Level optimised to take account of maxima
|
||||
|
||||
bool mDbConnected;
|
||||
|
||||
std::string mLogPath;
|
||||
std::string mLogFile;
|
||||
FILE *mLogFileFP;
|
||||
|
@ -111,31 +117,10 @@ private:
|
|||
bool mHasTerminal;
|
||||
bool mFlush;
|
||||
|
||||
private:
|
||||
static void usrHandler(int sig);
|
||||
|
||||
public:
|
||||
friend void logInit(const char *name, const Options &options);
|
||||
friend void logTerm();
|
||||
|
||||
static Logger *fetch() {
|
||||
if ( !smInstance ) {
|
||||
smInstance = new Logger();
|
||||
Options options;
|
||||
smInstance->initialise( "undef", options );
|
||||
}
|
||||
return smInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
public:
|
||||
void initialise(const std::string &id, const Options &options);
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
int limit(int level) {
|
||||
if ( level > DEBUG9 )
|
||||
return DEBUG9;
|
||||
|
@ -150,14 +135,29 @@ private:
|
|||
char *getTargettedEnv(const std::string &name);
|
||||
|
||||
void loadEnv();
|
||||
static void usrHandler(int sig);
|
||||
|
||||
public:
|
||||
friend void logInit(const char *name, const Options &options);
|
||||
friend void logTerm();
|
||||
|
||||
static Logger *fetch() {
|
||||
if ( !smInstance ) {
|
||||
smInstance = new Logger();
|
||||
Options options;
|
||||
smInstance->initialise("undef", options);
|
||||
}
|
||||
return smInstance;
|
||||
}
|
||||
|
||||
void initialise(const std::string &id, const Options &options);
|
||||
void terminate();
|
||||
|
||||
const std::string &id(const std::string &id);
|
||||
const std::string &id() const {
|
||||
return mId;
|
||||
}
|
||||
|
||||
const std::string &id(const std::string &id);
|
||||
|
||||
Level level() const {
|
||||
return mLevel;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "zm_utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h> /* Definition of AT_* constants */
|
||||
|
@ -416,6 +417,10 @@ Warning("ZM Compiled without LIBCURL. UriDecoding not implemented.");
|
|||
#endif
|
||||
}
|
||||
|
||||
void string_toupper( std::string& str) {
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
||||
}
|
||||
|
||||
void touch(const char *pathname) {
|
||||
int fd = open(pathname,
|
||||
O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK,
|
||||
|
|
|
@ -40,6 +40,7 @@ StringVector split( const std::string &string, const std::string &chars, int lim
|
|||
const std::string join( const StringVector &, const char * );
|
||||
|
||||
const std::string base64Encode( const std::string &inString );
|
||||
void string_toupper(std::string& str);
|
||||
|
||||
int split(const char* string, const char delim, std::vector<std::string>& items);
|
||||
int pairsplit(const char* string, const char delim, std::string& name, std::string& value);
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
|
||||
#include <cinttypes>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_videostore.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cinttypes>
|
||||
|
||||
extern "C" {
|
||||
#include "libavutil/time.h"
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ VideoStore::VideoStore(
|
|||
|
||||
Info("Opening video storage stream %s format: %s", filename, format);
|
||||
|
||||
ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
|
||||
int ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
|
||||
if ( ret < 0 ) {
|
||||
Warning(
|
||||
"Could not create video storage stream %s as no out ctx"
|
||||
|
@ -91,7 +92,7 @@ VideoStore::VideoStore(
|
|||
|
||||
oc->metadata = pmetadata;
|
||||
out_format = oc->oformat;
|
||||
out_format->flags |= AVFMT_TS_NONSTRICT; // allow non increasing dts
|
||||
out_format->flags |= AVFMT_TS_NONSTRICT; // allow non increasing dts
|
||||
|
||||
video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
|
||||
if ( !video_out_codec ) {
|
||||
|
@ -136,7 +137,7 @@ VideoStore::VideoStore(
|
|||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
if ( ! (video_out_ctx->time_base.num && video_out_ctx->time_base.den) ) {
|
||||
Debug(2,"No timebase found in video in context, defaulting to Q");
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
}
|
||||
|
||||
zm_dump_codec(video_out_ctx);
|
||||
|
@ -162,7 +163,7 @@ VideoStore::VideoStore(
|
|||
|
||||
if ( !video_out_ctx->codec_tag ) {
|
||||
Debug(2, "No codec_tag");
|
||||
if (
|
||||
if (
|
||||
!oc->oformat->codec_tag
|
||||
||
|
||||
av_codec_get_id(oc->oformat->codec_tag, video_in_ctx->codec_tag) == video_out_ctx->codec_id
|
||||
|
@ -178,32 +179,20 @@ VideoStore::VideoStore(
|
|||
video_out_stream->time_base = video_in_stream->time_base;
|
||||
if ( video_in_stream->avg_frame_rate.num ) {
|
||||
Debug(3,"Copying avg_frame_rate (%d/%d)",
|
||||
video_in_stream->avg_frame_rate.num,
|
||||
video_in_stream->avg_frame_rate.den
|
||||
video_in_stream->avg_frame_rate.num,
|
||||
video_in_stream->avg_frame_rate.den
|
||||
);
|
||||
video_out_stream->avg_frame_rate = video_in_stream->avg_frame_rate;
|
||||
}
|
||||
if ( video_in_stream->r_frame_rate.num ) {
|
||||
Debug(3,"Copying r_frame_rate (%d/%d) to out (%d/%d)",
|
||||
video_in_stream->r_frame_rate.num,
|
||||
video_in_stream->r_frame_rate.num,
|
||||
video_in_stream->r_frame_rate.den ,
|
||||
video_out_stream->r_frame_rate.num,
|
||||
video_out_stream->r_frame_rate.den
|
||||
video_out_stream->r_frame_rate.num,
|
||||
video_out_stream->r_frame_rate.den
|
||||
);
|
||||
video_out_stream->r_frame_rate = video_in_stream->r_frame_rate;
|
||||
}
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not initialize video_out_ctx parameters");
|
||||
return;
|
||||
} else {
|
||||
zm_dump_codec(video_out_ctx);
|
||||
}
|
||||
|
||||
zm_dump_codecpar(video_in_stream->codecpar);
|
||||
zm_dump_codecpar(video_out_stream->codecpar);
|
||||
#endif
|
||||
Debug(3,
|
||||
"Time bases: VIDEO in stream (%d/%d) in codec: (%d/%d) out "
|
||||
"stream: (%d/%d) out codec (%d/%d)",
|
||||
|
@ -221,6 +210,10 @@ VideoStore::VideoStore(
|
|||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
/* I'm not entirely sure that this is a good idea. We may have to do it someday but really only when transcoding
|
||||
* * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
|
||||
* */
|
||||
#if 0
|
||||
AVDictionary *opts = 0;
|
||||
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
|
||||
Warning("Can't open video codec (%s) %s",
|
||||
|
@ -234,6 +227,24 @@ VideoStore::VideoStore(
|
|||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
|
||||
}
|
||||
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not initialize video_out_ctx parameters");
|
||||
return;
|
||||
} else {
|
||||
zm_dump_codec(video_out_ctx);
|
||||
}
|
||||
#else
|
||||
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_in_ctx);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not initialize video_out_ctx parameters");
|
||||
return;
|
||||
} else {
|
||||
zm_dump_codec(video_out_ctx);
|
||||
}
|
||||
#endif
|
||||
zm_dump_codecpar(video_in_stream->codecpar);
|
||||
zm_dump_codecpar(video_out_stream->codecpar);
|
||||
#endif
|
||||
|
||||
Monitor::Orientation orientation = monitor->getOrientation();
|
||||
|
@ -262,9 +273,7 @@ VideoStore::VideoStore(
|
|||
out_frame = NULL;
|
||||
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
|
||||
resample_ctx = NULL;
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
fifo = NULL;
|
||||
#endif
|
||||
#endif
|
||||
video_first_pts = 0;
|
||||
video_first_dts = 0;
|
||||
|
@ -273,6 +282,7 @@ VideoStore::VideoStore(
|
|||
|
||||
audio_first_pts = 0;
|
||||
audio_first_dts = 0;
|
||||
/* When encoding audio, these are used to tell us what the correct pts is, because it gets lost during resampling. */
|
||||
audio_next_pts = 0;
|
||||
audio_next_dts = 0;
|
||||
|
||||
|
@ -301,7 +311,7 @@ VideoStore::VideoStore(
|
|||
audio_out_stream = NULL;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
audio_out_stream = avformat_new_stream(oc, audio_out_codec);
|
||||
audio_out_ctx = audio_out_stream->codec;
|
||||
#endif
|
||||
|
@ -375,6 +385,7 @@ VideoStore::VideoStore(
|
|||
} // VideoStore::VideoStore
|
||||
|
||||
bool VideoStore::open() {
|
||||
int ret;
|
||||
/* open the out file, if needed */
|
||||
if ( !(out_format->flags & AVFMT_NOFILE) ) {
|
||||
ret = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL);
|
||||
|
@ -419,6 +430,7 @@ VideoStore::~VideoStore() {
|
|||
if ( oc->pb ) {
|
||||
|
||||
if ( audio_out_codec ) {
|
||||
|
||||
// The codec queues data. We need to send a flush command and out
|
||||
// whatever we get. Failures are not fatal.
|
||||
AVPacket pkt;
|
||||
|
@ -426,105 +438,75 @@ VideoStore::~VideoStore() {
|
|||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
int frame_size = audio_out_ctx->frame_size;
|
||||
/*
|
||||
* At the end of the file, we pass the remaining samples to
|
||||
* the encoder. */
|
||||
while ( zm_resample_get_delay(resample_ctx, audio_out_ctx->sample_rate) ) {
|
||||
zm_resample_audio(resample_ctx, out_frame, NULL);
|
||||
|
||||
if ( zm_add_samples_to_fifo(fifo, out_frame) ) {
|
||||
// Should probably set the frame size to what is reported FIXME
|
||||
if ( zm_get_samples_from_fifo(fifo, out_frame) ) {
|
||||
if ( zm_send_frame_receive_packet(audio_out_ctx, out_frame, pkt) ) {
|
||||
pkt.stream_index = audio_out_stream->index;
|
||||
|
||||
av_packet_rescale_ts(&pkt,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
write_packet(&pkt, audio_out_stream);
|
||||
}
|
||||
} // end if data returned from fifo
|
||||
}
|
||||
|
||||
} // end if have buffered samples in the resampler
|
||||
|
||||
Debug(2, "av_audio_fifo_size = %d", av_audio_fifo_size(fifo));
|
||||
while ( av_audio_fifo_size(fifo) > 0 ) {
|
||||
/* Take one frame worth of audio samples from the FIFO buffer,
|
||||
* encode it and write it to the output file. */
|
||||
|
||||
Debug(1, "Remaining samples in fifo for AAC codec frame_size %d > fifo size %d",
|
||||
frame_size, av_audio_fifo_size(fifo));
|
||||
|
||||
// SHould probably set the frame size to what is reported FIXME
|
||||
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) ) {
|
||||
if ( zm_send_frame_receive_packet(audio_out_ctx, out_frame, pkt) ) {
|
||||
pkt.stream_index = audio_out_stream->index;
|
||||
|
||||
av_packet_rescale_ts(&pkt,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
write_packet(&pkt, audio_out_stream);
|
||||
}
|
||||
} // end if data returned from fifo
|
||||
} // end while still data in the fifo
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// Put encoder into flushing mode
|
||||
avcodec_send_frame(audio_out_ctx, NULL);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
ret = avcodec_receive_packet(audio_out_ctx, &pkt);
|
||||
if ( ret < 0 ) {
|
||||
if ( AVERROR_EOF != ret ) {
|
||||
Error("Error encoding audio while flushing (%d) (%s)", ret,
|
||||
av_err2str(ret));
|
||||
}
|
||||
if ( ! zm_receive_packet(audio_out_ctx, pkt) ) {
|
||||
Debug(1, "No more packets");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
int got_packet = 0;
|
||||
ret = avcodec_encode_audio2(audio_out_ctx, &pkt, NULL, &got_packet);
|
||||
if ( ret < 0 ) {
|
||||
Error("Error encoding audio while flushing (%d) (%s)", ret,
|
||||
av_err2str(ret));
|
||||
break;
|
||||
}
|
||||
Debug(1, "Have audio encoder, need to flush it's out");
|
||||
if ( !got_packet ) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
dumpPacket(&pkt, "raw from encoder");
|
||||
// Need to adjust pts and dts and duration
|
||||
|
||||
pkt.stream_index = audio_out_stream->index;
|
||||
|
||||
pkt.duration = av_rescale_q(
|
||||
pkt.duration,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
// Scale the PTS of the outgoing packet to be the correct time base
|
||||
if ( pkt.pts != AV_NOPTS_VALUE ) {
|
||||
#if 0
|
||||
pkt.pts = av_rescale_q(
|
||||
pkt.pts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_in_stream->time_base);
|
||||
// audio_first_pts is in audio_in_stream time base
|
||||
pkt.pts -= audio_first_pts;
|
||||
pkt.pts = av_rescale_q(
|
||||
pkt.pts,
|
||||
audio_in_stream->time_base,
|
||||
audio_out_stream->time_base);
|
||||
#else
|
||||
pkt.pts = av_rescale_q(
|
||||
pkt.pts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
#endif
|
||||
|
||||
Debug(2, "audio pkt.pts = %" PRId64 " from first_pts(%" PRId64 ")",
|
||||
pkt.pts, audio_first_pts);
|
||||
} else {
|
||||
Debug(2, "pkt.pts = undef");
|
||||
pkt.pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
if ( pkt.dts != AV_NOPTS_VALUE ) {
|
||||
#if 0
|
||||
pkt.dts = av_rescale_q(
|
||||
pkt.dts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_in_stream->time_base);
|
||||
pkt.dts -= audio_first_dts;
|
||||
pkt.dts = av_rescale_q(
|
||||
pkt.dts,
|
||||
audio_in_stream->time_base,
|
||||
audio_out_stream->time_base);
|
||||
#else
|
||||
pkt.dts = av_rescale_q(
|
||||
pkt.dts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
#endif
|
||||
Debug(2, "pkt.dts = %" PRId64 " - first_dts(%" PRId64 ")",
|
||||
pkt.dts, audio_first_dts);
|
||||
} else {
|
||||
pkt.dts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
av_packet_rescale_ts(&pkt, audio_out_ctx->time_base, audio_out_stream->time_base);
|
||||
dumpPacket(audio_out_stream, &pkt, "writing flushed packet");
|
||||
av_interleaved_write_frame(oc, &pkt);
|
||||
write_packet(&pkt, audio_out_stream);
|
||||
zm_av_packet_unref(&pkt);
|
||||
} // while have buffered frames
|
||||
} // end if audio_out_codec
|
||||
} // while have buffered frames
|
||||
} // end if audio_out_codec
|
||||
|
||||
// Flush Queues
|
||||
Debug(1,"Flushing interleaved queues");
|
||||
Debug(1, "Flushing interleaved queues");
|
||||
av_interleaved_write_frame(oc, NULL);
|
||||
|
||||
Debug(1,"Writing trailer");
|
||||
Debug(1, "Writing trailer");
|
||||
/* Write the trailer before close */
|
||||
if ( int rc = av_write_trailer(oc) ) {
|
||||
Error("Error writing trailer %s", av_err2str(rc));
|
||||
|
@ -593,11 +575,11 @@ VideoStore::~VideoStore() {
|
|||
|
||||
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
|
||||
if ( resample_ctx ) {
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
if ( fifo ) {
|
||||
av_audio_fifo_free(fifo);
|
||||
fifo = NULL;
|
||||
}
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
swr_free(&resample_ctx);
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
|
@ -632,6 +614,7 @@ bool VideoStore::setup_resampler() {
|
|||
"Cannot do audio conversion to AAC");
|
||||
return false;
|
||||
#else
|
||||
int ret;
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// Newer ffmpeg wants to keep everything separate... so have to lookup our own
|
||||
|
@ -650,8 +633,13 @@ bool VideoStore::setup_resampler() {
|
|||
#else
|
||||
// codec is already open in ffmpeg_camera
|
||||
audio_in_ctx = audio_in_stream->codec;
|
||||
audio_in_codec = (AVCodec *)audio_in_ctx->codec;
|
||||
//audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
|
||||
audio_in_codec = reinterpret_cast<const AVCodec *>(audio_in_ctx->codec);
|
||||
if ( !audio_in_codec ) {
|
||||
audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
|
||||
}
|
||||
if ( !audio_in_codec ) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
|
@ -707,7 +695,7 @@ bool VideoStore::setup_resampler() {
|
|||
}
|
||||
}
|
||||
if ( found ) {
|
||||
Debug(3, "Sample rate is good");
|
||||
Debug(3, "Sample rate is good %d", audio_out_ctx->sample_rate);
|
||||
} else {
|
||||
audio_out_ctx->sample_rate =
|
||||
audio_out_codec->supported_samplerates[0];
|
||||
|
@ -739,6 +727,7 @@ bool VideoStore::setup_resampler() {
|
|||
audio_out_stream = NULL;
|
||||
return false;
|
||||
}
|
||||
zm_dump_codec(audio_out_ctx);
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
ret = avcodec_parameters_from_context(
|
||||
|
@ -747,6 +736,7 @@ bool VideoStore::setup_resampler() {
|
|||
Error("Could not initialize stream parameteres");
|
||||
return false;
|
||||
}
|
||||
zm_dump_codecpar(audio_out_stream->codecpar);
|
||||
#endif
|
||||
|
||||
Debug(3,
|
||||
|
@ -783,13 +773,13 @@ bool VideoStore::setup_resampler() {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
if ( !(fifo = av_audio_fifo_alloc(
|
||||
audio_out_ctx->sample_fmt,
|
||||
audio_out_ctx->channels, 1)) ) {
|
||||
Error("Could not allocate FIFO");
|
||||
return false;
|
||||
}
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
resample_ctx = swr_alloc_set_opts(NULL,
|
||||
audio_out_ctx->channel_layout,
|
||||
audio_out_ctx->sample_fmt,
|
||||
|
@ -864,7 +854,7 @@ bool VideoStore::setup_resampler() {
|
|||
NULL, audio_out_ctx->channels,
|
||||
audio_out_ctx->frame_size,
|
||||
audio_out_ctx->sample_fmt, 0);
|
||||
converted_in_samples = (uint8_t *)av_malloc(audioSampleBuffer_size);
|
||||
converted_in_samples = reinterpret_cast<uint8_t *>(av_malloc(audioSampleBuffer_size));
|
||||
|
||||
if ( !converted_in_samples ) {
|
||||
Error("Could not allocate converted in sample pointers");
|
||||
|
@ -890,131 +880,31 @@ bool VideoStore::setup_resampler() {
|
|||
int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
||||
av_init_packet(&opkt);
|
||||
|
||||
dumpPacket(video_in_stream, ipkt, "input packet");
|
||||
dumpPacket(video_in_stream, ipkt, "video input packet");
|
||||
|
||||
int64_t duration;
|
||||
if ( ipkt->duration != AV_NOPTS_VALUE ) {
|
||||
duration = av_rescale_q(
|
||||
ipkt->duration,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base);
|
||||
Debug(1, "duration from ipkt: %" PRId64 ") => (%" PRId64 ") (%d/%d) (%d/%d)",
|
||||
ipkt->duration,
|
||||
duration,
|
||||
video_in_stream->time_base.num,
|
||||
video_in_stream->time_base.den,
|
||||
video_out_stream->time_base.num,
|
||||
video_out_stream->time_base.den
|
||||
);
|
||||
} else {
|
||||
duration = av_rescale_q(
|
||||
ipkt->pts - video_last_pts,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base);
|
||||
Debug(1, "duration calc: pts(%" PRId64 ") - last_pts(%" PRId64 ") = (%" PRId64 ") => (%" PRId64 ")",
|
||||
ipkt->pts,
|
||||
video_last_pts,
|
||||
ipkt->pts - video_last_pts,
|
||||
duration
|
||||
);
|
||||
if ( duration <= 0 ) {
|
||||
// Why are we setting the duration to 1?
|
||||
duration = ipkt->duration ? ipkt->duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base);
|
||||
}
|
||||
}
|
||||
opkt.duration = duration;
|
||||
opkt.flags = ipkt->flags;
|
||||
opkt.data = ipkt->data;
|
||||
opkt.size = ipkt->size;
|
||||
opkt.duration = ipkt->duration;
|
||||
|
||||
// Scale the PTS of the outgoing packet to be the correct time base
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
|
||||
if ( (!video_first_pts) && (ipkt->pts >= 0) ) {
|
||||
// This is the first packet.
|
||||
opkt.pts = 0;
|
||||
Debug(2, "Starting video first_pts will become %" PRId64, ipkt->pts);
|
||||
video_first_pts = ipkt->pts;
|
||||
#if 1
|
||||
if ( audio_in_stream ) {
|
||||
// Since audio starts after the start of the video, need to set this here.
|
||||
audio_first_pts = av_rescale_q(
|
||||
ipkt->pts,
|
||||
video_in_stream->time_base,
|
||||
audio_in_stream->time_base
|
||||
);
|
||||
Debug(2, "Starting audio first_pts will become %" PRId64, audio_first_pts);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
opkt.pts = av_rescale_q(
|
||||
ipkt->pts - video_first_pts,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base
|
||||
);
|
||||
}
|
||||
Debug(3, "opkt.pts = %" PRId64 " from ipkt->pts(%" PRId64 ") - first_pts(%" PRId64 ")",
|
||||
opkt.pts, ipkt->pts, video_first_pts);
|
||||
video_last_pts = ipkt->pts;
|
||||
} else {
|
||||
Debug(3, "opkt.pts = undef");
|
||||
opkt.pts = AV_NOPTS_VALUE;
|
||||
// can't set 0, it will get rejected
|
||||
//AV_NOPTS_VALUE;
|
||||
}
|
||||
// Just because the in stream wraps, doesn't mean the out needs to.
|
||||
// Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out.
|
||||
// So need to handle in wrap, without causing out wrap.
|
||||
// Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out.
|
||||
// So need to handle in wrap, without causing out wrap.
|
||||
// The cameras that Icon has seem to do EOF instead of wrapping
|
||||
|
||||
if ( ipkt->dts != AV_NOPTS_VALUE ) {
|
||||
if ( !video_first_dts ) {
|
||||
// && ( ipkt->dts >= 0 ) ) {
|
||||
// This is the first packet.
|
||||
opkt.dts = 0;
|
||||
Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
|
||||
Debug(2, "Starting video first_dts will become %" PRId64, ipkt->dts);
|
||||
video_first_dts = ipkt->dts;
|
||||
#if 1
|
||||
if ( audio_in_stream ) {
|
||||
// Since audio starts after the start of the video, need to set this here.
|
||||
audio_first_dts = av_rescale_q(
|
||||
ipkt->dts,
|
||||
video_in_stream->time_base,
|
||||
audio_in_stream->time_base
|
||||
);
|
||||
Debug(2, "Starting audio first dts will become %" PRId64, audio_first_dts);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
opkt.dts = av_rescale_q(
|
||||
ipkt->dts - video_first_dts,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base
|
||||
);
|
||||
Debug(3, "opkt.dts = %" PRId64 " from ipkt->dts(%" PRId64 ") - first_pts(%" PRId64 ")",
|
||||
opkt.dts, ipkt->dts, video_first_dts);
|
||||
}
|
||||
if ( (opkt.pts != AV_NOPTS_VALUE) && (opkt.dts > opkt.pts) ) {
|
||||
Debug(1,
|
||||
"opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 "). Decompression must happen "
|
||||
"before presentation.",
|
||||
opkt.dts, opkt.pts);
|
||||
opkt.dts = opkt.pts;
|
||||
}
|
||||
} else {
|
||||
Debug(3, "opkt.dts = undef");
|
||||
opkt.dts = video_out_stream->cur_dts;
|
||||
opkt.dts = ipkt->dts - video_first_dts;
|
||||
}
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
opkt.pts = ipkt->pts - video_first_dts;
|
||||
}
|
||||
av_packet_rescale_ts(&opkt, video_in_stream->time_base, video_out_stream->time_base);
|
||||
|
||||
if ( opkt.dts < video_out_stream->cur_dts ) {
|
||||
Debug(1, "Fixing non-monotonic dts/pts dts %" PRId64 " pts %" PRId64 " stream %" PRId64,
|
||||
opkt.dts, opkt.pts, video_out_stream->cur_dts);
|
||||
opkt.dts = video_out_stream->cur_dts;
|
||||
if ( opkt.dts > opkt.pts ) {
|
||||
opkt.pts = opkt.dts;
|
||||
}
|
||||
}
|
||||
|
||||
opkt.flags = ipkt->flags;
|
||||
opkt.pos = -1;
|
||||
opkt.data = ipkt->data;
|
||||
opkt.size = ipkt->size;
|
||||
dumpPacket(video_out_stream, &opkt, "after pts adjustment");
|
||||
write_packet(&opkt, video_out_stream);
|
||||
zm_av_packet_unref(&opkt);
|
||||
|
||||
|
@ -1022,6 +912,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
|||
} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
|
||||
|
||||
int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
||||
int ret;
|
||||
|
||||
if ( !audio_out_stream ) {
|
||||
Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
|
||||
|
@ -1030,151 +921,57 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
|||
}
|
||||
dumpPacket(audio_in_stream, ipkt, "input packet");
|
||||
|
||||
if ( !audio_first_dts ) {
|
||||
audio_first_dts = ipkt->dts;
|
||||
audio_next_pts = audio_out_ctx->frame_size;
|
||||
}
|
||||
|
||||
// Need to adjust pts before feeding to decoder.... should really copy the pkt instead of modifying it
|
||||
ipkt->pts -= audio_first_dts;
|
||||
ipkt->dts -= audio_first_dts;
|
||||
dumpPacket(audio_in_stream, ipkt, "after pts adjustment");
|
||||
|
||||
if ( audio_out_codec ) {
|
||||
if ( ( ret = zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) < 0 ) {
|
||||
// I wonder if we can get multiple frames per packet? Probably
|
||||
ret = zm_send_packet_receive_frame(audio_in_ctx, in_frame, *ipkt);
|
||||
if ( ret <= 0 ) {
|
||||
Debug(3, "Not ready to receive frame");
|
||||
return 0;
|
||||
}
|
||||
|
||||
zm_dump_frame(in_frame, "In frame from decode");
|
||||
if ( in_frame->pts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_pts ) {
|
||||
audio_first_pts = in_frame->pts;
|
||||
Debug(1, "No audio_first_pts setting to %" PRId64, audio_first_pts);
|
||||
in_frame->pts = 0;
|
||||
} else {
|
||||
// out_frame_pts is in codec->timebase, audio_first_pts is in packet timebase.
|
||||
in_frame->pts = in_frame->pts - audio_first_pts;
|
||||
zm_dump_frame(in_frame, "in frame after pts adjustment");
|
||||
}
|
||||
} else {
|
||||
// sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
|
||||
in_frame->pts = audio_next_pts;
|
||||
}
|
||||
|
||||
if ( !resample_audio() ) {
|
||||
//av_frame_unref(in_frame);
|
||||
return 0;
|
||||
}
|
||||
AVFrame *input_frame = in_frame;
|
||||
|
||||
while ( zm_resample_audio(resample_ctx, input_frame, out_frame) ) {
|
||||
//out_frame->pkt_duration = in_frame->pkt_duration; // resampling doesn't alter duration
|
||||
if ( zm_add_samples_to_fifo(fifo, out_frame) <= 0 )
|
||||
break;
|
||||
|
||||
if ( zm_get_samples_from_fifo(fifo, out_frame) <= 0 )
|
||||
break;
|
||||
|
||||
zm_dump_frame(out_frame, "Out frame after resample");
|
||||
#if 0
|
||||
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
|
||||
if ( out_frame->pts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_pts ) {
|
||||
audio_first_pts = out_frame->pts;
|
||||
Debug(1, "No audio_first_pts setting to %" PRId64, audio_first_pts);
|
||||
out_frame->pts = 0;
|
||||
} else {
|
||||
// out_frame_pts is in codec->timebase, audio_first_pts is in packet timebase.
|
||||
out_frame->pts = out_frame->pts - audio_first_pts;
|
||||
zm_dump_frame(out_frame, "Out frame after pts adjustment");
|
||||
}
|
||||
//
|
||||
} else {
|
||||
// sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
|
||||
out_frame->pts = audio_next_pts;
|
||||
}
|
||||
audio_next_pts = out_frame->pts + out_frame->nb_samples;
|
||||
#endif
|
||||
audio_next_pts += out_frame->nb_samples;
|
||||
|
||||
av_init_packet(&opkt);
|
||||
if ( !zm_send_frame(audio_out_ctx, out_frame, opkt) ) {
|
||||
return 0;
|
||||
}
|
||||
zm_dump_frame(out_frame, "Out frame after resample");
|
||||
|
||||
dumpPacket(audio_out_stream, &opkt, "raw opkt");
|
||||
Debug(1, "Duration before %d in %d/%d", opkt.duration,
|
||||
audio_out_ctx->time_base.num,
|
||||
audio_out_ctx->time_base.den);
|
||||
av_init_packet(&opkt);
|
||||
if ( zm_send_frame_receive_packet(audio_out_ctx, out_frame, opkt) <= 0 )
|
||||
break;
|
||||
|
||||
opkt.duration = av_rescale_q(
|
||||
opkt.duration,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
Debug(1, "Duration after %d in %d/%d", opkt.duration,
|
||||
audio_out_stream->time_base.num,
|
||||
audio_out_stream->time_base.den);
|
||||
// Scale the PTS of the outgoing packet to be the correct time base
|
||||
#if 0
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_pts ) {
|
||||
opkt.pts = 0;
|
||||
audio_first_pts = ipkt->pts;
|
||||
Debug(1, "No audio_first_pts");
|
||||
} else {
|
||||
opkt.pts = av_rescale_q(
|
||||
opkt.pts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
opkt.pts -= audio_first_pts;
|
||||
Debug(2, "audio opkt.pts = %" PRId64 " from first_pts %" PRId64,
|
||||
opkt.pts, audio_first_pts);
|
||||
}
|
||||
} else {
|
||||
Debug(2, "opkt.pts = undef");
|
||||
opkt.pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
if ( opkt.dts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_dts ) {
|
||||
opkt.dts = 0;
|
||||
audio_first_dts = opkt.dts;
|
||||
} else {
|
||||
opkt.dts = av_rescale_q(
|
||||
opkt.dts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
opkt.dts -= audio_first_dts;
|
||||
Debug(2, "audio opkt.dts = %" PRId64 " from first_dts %" PRId64,
|
||||
opkt.dts, audio_first_dts);
|
||||
}
|
||||
audio_last_dts = opkt.dts;
|
||||
} else {
|
||||
opkt.dts = AV_NOPTS_VALUE;
|
||||
}
|
||||
#else
|
||||
opkt.pts = av_rescale_q(
|
||||
opkt.pts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
opkt.dts = av_rescale_q(
|
||||
opkt.dts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
#endif
|
||||
|
||||
write_packet(&opkt, audio_out_stream);
|
||||
zm_av_packet_unref(&opkt);
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// While the encoder still has packets for us
|
||||
while ( !avcodec_receive_packet(audio_out_ctx, &opkt) ) {
|
||||
opkt.pts = av_rescale_q(
|
||||
opkt.pts,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
opkt.dts = av_rescale_q(
|
||||
opkt.dts,
|
||||
// Scale the PTS of the outgoing packet to be the correct time base
|
||||
av_packet_rescale_ts(&opkt,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
|
||||
dumpPacket(audio_out_stream, &opkt, "raw opkt");
|
||||
Debug(1, "Duration before %d in %d/%d", opkt.duration,
|
||||
audio_out_ctx->time_base.num,
|
||||
audio_out_ctx->time_base.den);
|
||||
|
||||
opkt.duration = av_rescale_q(
|
||||
opkt.duration,
|
||||
audio_out_ctx->time_base,
|
||||
audio_out_stream->time_base);
|
||||
Debug(1, "Duration after %d in %d/%d", opkt.duration,
|
||||
audio_out_stream->time_base.num,
|
||||
audio_out_stream->time_base.den);
|
||||
write_packet(&opkt, audio_out_stream);
|
||||
}
|
||||
#endif
|
||||
zm_av_packet_unref(&opkt);
|
||||
zm_av_packet_unref(&opkt);
|
||||
|
||||
if ( zm_resample_get_delay(resample_ctx, out_frame->sample_rate) < out_frame->nb_samples)
|
||||
break;
|
||||
// This will send a null frame, emptying out the resample buffer
|
||||
input_frame = NULL;
|
||||
} // end while there is data in the resampler
|
||||
|
||||
} else {
|
||||
Debug(2,"copying");
|
||||
|
@ -1183,171 +980,50 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
|||
opkt.size = ipkt->size;
|
||||
opkt.flags = ipkt->flags;
|
||||
|
||||
if ( ipkt->duration && (ipkt->duration != AV_NOPTS_VALUE) ) {
|
||||
opkt.duration = av_rescale_q(
|
||||
ipkt->duration,
|
||||
audio_in_stream->time_base,
|
||||
audio_out_stream->time_base);
|
||||
}
|
||||
// Scale the PTS of the outgoing packet to be the correct time base
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_pts ) {
|
||||
opkt.pts = 0;
|
||||
audio_first_pts = ipkt->pts;
|
||||
Debug(1, "No audio_first_pts");
|
||||
} else {
|
||||
opkt.pts = av_rescale_q(
|
||||
ipkt->pts - audio_first_pts,
|
||||
audio_in_stream->time_base,
|
||||
audio_out_stream->time_base);
|
||||
Debug(2, "audio opkt.pts = %" PRId64 " from ipkt->pts(%" PRId64 ") - first_pts(%" PRId64 ")",
|
||||
opkt.pts, ipkt->pts, audio_first_pts);
|
||||
}
|
||||
} else {
|
||||
Debug(2, "opkt.pts = undef");
|
||||
opkt.pts = AV_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
if ( ipkt->dts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_first_dts ) {
|
||||
opkt.dts = 0;
|
||||
audio_first_dts = ipkt->dts;
|
||||
} else {
|
||||
opkt.dts = av_rescale_q(
|
||||
ipkt->dts - audio_first_dts,
|
||||
audio_in_stream->time_base,
|
||||
audio_out_stream->time_base);
|
||||
Debug(2, "opkt.dts = %" PRId64 " from ipkt.dts(%" PRId64 ") - first_dts(%" PRId64 ")",
|
||||
opkt.dts, ipkt->dts, audio_first_dts);
|
||||
}
|
||||
audio_last_dts = ipkt->dts;
|
||||
} else {
|
||||
opkt.dts = AV_NOPTS_VALUE;
|
||||
}
|
||||
opkt.duration = ipkt->duration;
|
||||
opkt.pts = ipkt->pts;
|
||||
opkt.dts = ipkt->dts;
|
||||
av_packet_rescale_ts(&opkt, audio_in_stream->time_base, audio_out_stream->time_base);
|
||||
write_packet(&opkt, audio_out_stream);
|
||||
|
||||
zm_av_packet_unref(&opkt);
|
||||
} // end if encoding or copying
|
||||
} // end if encoding or copying
|
||||
|
||||
return 0;
|
||||
} // end int VideoStore::writeAudioFramePacket(AVPacket *ipkt)
|
||||
} // end int VideoStore::writeAudioFramePacket(AVPacket *ipkt)
|
||||
|
||||
int VideoStore::write_packet(AVPacket *pkt, AVStream *stream) {
|
||||
pkt->pos = -1;
|
||||
pkt->stream_index = stream->index;
|
||||
|
||||
if ( pkt->dts < stream->cur_dts ) {
|
||||
Warning("non increasing dts, fixing");
|
||||
Debug(1, "non increasing dts, fixing. our dts %" PRId64 " stream cur_dts %" PRId64, pkt->dts, stream->cur_dts);
|
||||
pkt->dts = stream->cur_dts;
|
||||
if ( pkt->dts > pkt->pts ) {
|
||||
if ( (pkt->pts != AV_NOPTS_VALUE) && (pkt->dts > pkt->pts) ) {
|
||||
Debug(1,
|
||||
"pkt.dts(%" PRId64 ") must be <= pkt.pts(%" PRId64 ")."
|
||||
"pkt.dts %" PRId64 " must be <= pkt.pts %" PRId64 "."
|
||||
"Decompression must happen before presentation.",
|
||||
pkt->dts, pkt->pts);
|
||||
pkt->pts = pkt->dts;
|
||||
}
|
||||
} else if ( pkt->dts > pkt->pts ) {
|
||||
} else if ( (pkt->pts != AV_NOPTS_VALUE) && (pkt->dts > pkt->pts) ) {
|
||||
Debug(1,
|
||||
"pkt.dts(%" PRId64 ") must be <= pkt.pts(%" PRId64 ")."
|
||||
"Decompression must happen before presentation.",
|
||||
pkt->dts, pkt->pts);
|
||||
pkt->dts = pkt->pts;
|
||||
} else {
|
||||
Debug(1, "Acceptable pts and dts. cur_dts = %" PRId64, stream->cur_dts);
|
||||
}
|
||||
|
||||
dumpPacket(stream, pkt, "finished pkt");
|
||||
|
||||
ret = av_interleaved_write_frame(oc, pkt);
|
||||
int ret = av_interleaved_write_frame(oc, pkt);
|
||||
if ( ret != 0 ) {
|
||||
Error("Error writing packet: %s",
|
||||
av_make_error_string(ret).c_str());
|
||||
} else {
|
||||
Debug(2, "Success writing packet");
|
||||
}
|
||||
} // end int VideoStore::write_packet(AVPacket *pkt, AVStream *stream)
|
||||
|
||||
int VideoStore::resample_audio() {
|
||||
// Resample the in_frame into the audioSampleBuffer until we process the whole
|
||||
// decoded data. Note: pts does not survive resampling or converting
|
||||
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
|
||||
#if defined(HAVE_LIBSWRESAMPLE)
|
||||
Debug(2, "Converting %d to %d samples using swresample",
|
||||
in_frame->nb_samples, out_frame->nb_samples);
|
||||
ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not resample frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
zm_dump_frame(out_frame, "Out frame after resample");
|
||||
out_frame->pkt_duration = in_frame->pkt_duration; // resampling doesn't alter duration
|
||||
|
||||
ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not reallocate FIFO");
|
||||
return 0;
|
||||
}
|
||||
/** Store the new samples in the FIFO buffer. */
|
||||
ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
|
||||
if ( ret < out_frame->nb_samples ) {
|
||||
Error("Could not write data to FIFO. %d written, expecting %d. Reason %s",
|
||||
ret, out_frame->nb_samples, av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reset frame_size to output_frame_size
|
||||
int frame_size = audio_out_ctx->frame_size;
|
||||
|
||||
// AAC requires 1024 samples per encode. Our input tends to be something else, so need to buffer them.
|
||||
if ( frame_size > av_audio_fifo_size(fifo) ) {
|
||||
Debug(1, "Not enough samples in fifo for AAC codec frame_size %d > fifo size %d",
|
||||
frame_size, av_audio_fifo_size(fifo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
|
||||
Error("Could not read data from FIFO");
|
||||
return 0;
|
||||
}
|
||||
out_frame->nb_samples = frame_size;
|
||||
zm_dump_frame(out_frame, "Out frame after fifo read");
|
||||
// resampling changes the duration because the timebase is 1/samples
|
||||
// I think we should be dealing in codec timebases not stream
|
||||
if ( in_frame->pts != AV_NOPTS_VALUE ) {
|
||||
out_frame->pts = av_rescale_q(
|
||||
in_frame->pts,
|
||||
audio_in_ctx->time_base,
|
||||
audio_out_ctx->time_base);
|
||||
}
|
||||
zm_dump_frame(out_frame, "Out frame after timestamp conversion");
|
||||
#else
|
||||
#if defined(HAVE_LIBAVRESAMPLE)
|
||||
ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
|
||||
0, in_frame->nb_samples);
|
||||
if ( ret < 0 ) {
|
||||
Error("Could not resample frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int frame_size = audio_out_ctx->frame_size;
|
||||
|
||||
int samples_available = avresample_available(resample_ctx);
|
||||
if ( samples_available < frame_size ) {
|
||||
Debug(1, "Not enough samples yet (%d)", samples_available);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read a frame audio data from the resample fifo
|
||||
if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
|
||||
frame_size) {
|
||||
Warning("Error reading resampled audio.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
Error("Have audio codec but no resampler?!");
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
} // end int VideoStore::resample_audio
|
||||
return ret;
|
||||
} // end int VideoStore::write_packet(AVPacket *pkt, AVStream *stream)
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
extern "C" {
|
||||
#ifdef HAVE_LIBSWRESAMPLE
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libavutil/audio_fifo.h"
|
||||
#else
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
#include "libavresample/avresample.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "libavutil/audio_fifo.h"
|
||||
}
|
||||
|
||||
#if HAVE_LIBAVCODEC
|
||||
|
@ -38,9 +38,8 @@ private:
|
|||
AVFrame *out_frame;
|
||||
|
||||
AVCodecContext *video_in_ctx;
|
||||
AVCodec *audio_in_codec;
|
||||
const AVCodec *audio_in_codec;
|
||||
AVCodecContext *audio_in_ctx;
|
||||
int ret;
|
||||
|
||||
// The following are used when encoding the audio stream to AAC
|
||||
AVStream *audio_out_stream;
|
||||
|
@ -48,12 +47,12 @@ private:
|
|||
AVCodecContext *audio_out_ctx;
|
||||
#ifdef HAVE_LIBSWRESAMPLE
|
||||
SwrContext *resample_ctx;
|
||||
AVAudioFifo *fifo;
|
||||
#else
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
AVAudioResampleContext* resample_ctx;
|
||||
#endif
|
||||
#endif
|
||||
AVAudioFifo *fifo;
|
||||
uint8_t *converted_in_samples;
|
||||
|
||||
const char *filename;
|
||||
|
@ -77,8 +76,6 @@ private:
|
|||
int64_t audio_next_dts;
|
||||
|
||||
bool setup_resampler();
|
||||
int resample_audio();
|
||||
|
||||
int write_packet(AVPacket *pkt, AVStream *stream);
|
||||
|
||||
public:
|
||||
|
|
|
@ -187,8 +187,8 @@ int main(int argc, char *argv[]) {
|
|||
snprintf(log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id);
|
||||
}
|
||||
|
||||
logInit(log_id_string);
|
||||
zmLoadConfig();
|
||||
|
||||
logInit(log_id_string);
|
||||
|
||||
hwcaps_detect();
|
||||
|
|
|
@ -138,7 +138,7 @@ movecrud () {
|
|||
|
||||
# previsouly part of installzm.sh
|
||||
# install the trusty deb and test zoneminder
|
||||
installtrusty () {
|
||||
install_deb () {
|
||||
|
||||
# Check we've got gdebi installed
|
||||
type gdebi 2>&1 > /dev/null
|
||||
|
@ -347,8 +347,8 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
|
|||
echo "Starting packpack..."
|
||||
execpackpack
|
||||
|
||||
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
|
||||
installtrusty
|
||||
if [ "${TRAVIS}" == "true" ]; then
|
||||
install_deb
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -369,7 +369,7 @@ elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86
|
|||
|
||||
# If we are running inside Travis then attempt to install the deb we just built
|
||||
if [ "${TRAVIS}" == "true" ]; then
|
||||
installtrusty
|
||||
install_deb
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -142,16 +142,14 @@ class Event extends ZM_Object {
|
|||
# Assumption: All events have a start time
|
||||
$start_date = date_parse($this->{'StartTime'});
|
||||
if ( ! $start_date ) {
|
||||
Error('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.');
|
||||
return;
|
||||
throw new Exception('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.');
|
||||
}
|
||||
$start_date['year'] = $start_date['year'] % 100;
|
||||
|
||||
# So this is because ZM creates a link under the day pointing to the time that the event happened.
|
||||
$link_path = $this->Link_Path();
|
||||
if ( ! $link_path ) {
|
||||
Error('Unable to determine link path for event '.$this->{'Id'}.' not deleting files.');
|
||||
return;
|
||||
throw new Exception('Unable to determine link path for event '.$this->{'Id'}.' not deleting files.');
|
||||
}
|
||||
|
||||
$Storage = $this->Storage();
|
||||
|
@ -159,8 +157,7 @@ class Event extends ZM_Object {
|
|||
|
||||
if ( $id_files = glob($eventlink_path) ) {
|
||||
if ( ! $eventPath = readlink($id_files[0]) ) {
|
||||
Error("Unable to read link at $id_files[0]");
|
||||
return;
|
||||
throw new Exception("Unable to read link at $id_files[0]");
|
||||
}
|
||||
# I know we are using arrays here, but really there can only ever be 1 in the array
|
||||
$eventPath = preg_replace('/\.'.$this->{'Id'}.'$/', $eventPath, $id_files[0]);
|
||||
|
@ -179,8 +176,7 @@ class Event extends ZM_Object {
|
|||
} else {
|
||||
$eventPath = $this->Path();
|
||||
if ( ! $eventPath ) {
|
||||
Error('No event Path in Event delete. Not deleting');
|
||||
return;
|
||||
throw new Exception('No event Path in Event delete. Not deleting');
|
||||
}
|
||||
deletePath($eventPath);
|
||||
if ( $this->SecondaryStorageId() ) {
|
||||
|
@ -199,6 +195,9 @@ class Event extends ZM_Object {
|
|||
$dbConn->commit();
|
||||
} catch (PDOException $e) {
|
||||
$dbConn->rollback();
|
||||
} catch (Exception $e) {
|
||||
Error($e->getMessage());
|
||||
$dbConn->rollback();
|
||||
}
|
||||
} # end Event->delete
|
||||
|
||||
|
@ -254,7 +253,7 @@ class Event extends ZM_Object {
|
|||
}
|
||||
}
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args,'', $querySep);
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
||||
return $streamSrc;
|
||||
} // end function getStreamSrc
|
||||
|
|
|
@ -103,6 +103,11 @@ class Server {
|
|||
}
|
||||
|
||||
public function Url( $port = null ) {
|
||||
if ( !$this->Id() ) {
|
||||
# Trying to guess and make up values tends to break proxies. So just return nothing
|
||||
# so that the resulting url will be something like "?view="
|
||||
return '';
|
||||
}
|
||||
$url = $this->Protocol().'://';
|
||||
$url .= $this->Hostname();
|
||||
if ( $port ) {
|
||||
|
|
|
@ -44,11 +44,9 @@ if ( $action == 'archive' ) {
|
|||
$dbConn->commit();
|
||||
$refreshParent = true;
|
||||
} else if ( $action == 'delete' ) {
|
||||
$dbConn->beginTransaction();
|
||||
foreach ( getAffectedIds('eids') as $markEid ) {
|
||||
deleteEvent($markEid);
|
||||
}
|
||||
$dbConn->commit();
|
||||
$refreshParent = true;
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -37,7 +37,6 @@ if ( $action == 'user' ) {
|
|||
|
||||
if ( $_REQUEST['newUser']['Password'] ) {
|
||||
$changes['Password'] = 'Password = '.$pass_hash;
|
||||
ZM\Info('PASS CMD='.$changes['Password']);
|
||||
} else {
|
||||
unset($changes['Password']);
|
||||
}
|
||||
|
@ -47,7 +46,7 @@ if ( $action == 'user' ) {
|
|||
dbQuery('UPDATE Users SET '.implode(', ', $changes).' WHERE Id = ?', array($_REQUEST['uid']));
|
||||
# If we are updating the logged in user, then update our session user data.
|
||||
if ( $user and ( $dbUser['Username'] == $user['Username'] ) )
|
||||
userLogin($dbUser['Username'], $dbUser['Password']);
|
||||
generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} else {
|
||||
dbQuery('INSERT INTO Users SET '.implode(', ', $changes));
|
||||
}
|
||||
|
@ -71,13 +70,13 @@ if ( $action == 'user' ) {
|
|||
|
||||
if ( !empty($_REQUEST['newUser']['Password']) ) {
|
||||
$changes['Password'] = 'Password = '.$pass_hash;
|
||||
}
|
||||
|
||||
else
|
||||
} else {
|
||||
unset($changes['Password']);
|
||||
}
|
||||
if ( count($changes) ) {
|
||||
dbQuery('UPDATE Users SET '.implode(', ', $changes).' WHERE Id=?', array($uid));
|
||||
$refreshParent = true;
|
||||
generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
}
|
||||
$view = 'none';
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ function dbConnect() {
|
|||
|
||||
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch(PDOException $ex ) {
|
||||
} catch(PDOException $ex) {
|
||||
echo 'Unable to connect to ZM db.' . $ex->getMessage();
|
||||
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
||||
$dbConn = null;
|
||||
|
|
|
@ -120,33 +120,6 @@ function CORSHeaders() {
|
|||
}
|
||||
}
|
||||
|
||||
function getStreamSrc( $args, $querySep='&' ) {
|
||||
$streamSrc = ZM_BASE_URL.ZM_PATH_ZMS;
|
||||
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$args[] = 'auth='.generateAuthHash( ZM_AUTH_HASH_IPS );
|
||||
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
$args[] = 'user='.$_SESSION['username'];
|
||||
$args[] = 'pass='.$_SESSION['password'];
|
||||
} elseif ( ZM_AUTH_RELAY == 'none' ) {
|
||||
$args[] = 'user='.$_SESSION['username'];
|
||||
}
|
||||
}
|
||||
if ( !in_array( 'mode=single', $args ) && !empty($GLOBALS['connkey']) ) {
|
||||
$args[] = 'connkey='.$GLOBALS['connkey'];
|
||||
}
|
||||
if ( ZM_RAND_STREAM ) {
|
||||
$args[] = 'rand='.time();
|
||||
}
|
||||
|
||||
if ( count($args) ) {
|
||||
$streamSrc .= '?'.join( $querySep, $args );
|
||||
}
|
||||
|
||||
return( $streamSrc );
|
||||
}
|
||||
|
||||
function getMimeType( $file ) {
|
||||
if ( function_exists('mime_content_type') ) {
|
||||
return( mime_content_type( $file ) );
|
||||
|
@ -156,7 +129,7 @@ function getMimeType( $file ) {
|
|||
finfo_close($finfo);
|
||||
return( $mimeType );
|
||||
}
|
||||
return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) );
|
||||
return trim(exec('file -bi '.escapeshellarg($file).' 2>/dev/null'));
|
||||
}
|
||||
|
||||
function outputVideoStream( $id, $src, $width, $height, $format, $title='' ) {
|
||||
|
@ -169,8 +142,8 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
$height = validInt($height);
|
||||
$title = validHtmlStr($title);
|
||||
|
||||
if ( file_exists( $src ) ) {
|
||||
$mimeType = getMimeType( $src );
|
||||
if ( file_exists($src) ) {
|
||||
$mimeType = getMimeType($src);
|
||||
} else {
|
||||
switch( $format ) {
|
||||
case 'asf' :
|
||||
|
@ -205,7 +178,6 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
case 'video/x-ms-asf' :
|
||||
case 'video/x-msvideo' :
|
||||
case 'video/mp4' :
|
||||
{
|
||||
if ( isWindows() ) {
|
||||
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'
|
||||
classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
|
||||
|
@ -226,9 +198,7 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
</embed>
|
||||
</object>';
|
||||
}
|
||||
}
|
||||
case 'video/quicktime' :
|
||||
{
|
||||
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
|
||||
classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
|
||||
codebase="'.ZM_BASE_PROTOCOL.'://www.apple.com/qtactivex/qtplugin.cab"
|
||||
|
@ -244,9 +214,7 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
controller="true">
|
||||
</embed>
|
||||
</object>';
|
||||
}
|
||||
case 'application/x-shockwave-flash' :
|
||||
{
|
||||
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
|
||||
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
|
||||
codebase="'.ZM_BASE_PROTOCOL.'://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
|
||||
|
@ -264,7 +232,6 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
bgcolor="#ffffff">
|
||||
</embed>
|
||||
</object>';
|
||||
}
|
||||
} # end switch
|
||||
} # end if use object tags
|
||||
return '<embed'. ( isset($mimeType)?(' type="'.$mimeType.'"'):'' ). '
|
||||
|
@ -295,25 +262,25 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
|
|||
function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) {
|
||||
?>
|
||||
<form name="ctrlForm" method="post" action="?" target="<?php echo $target ?>">
|
||||
<input type="hidden" name="view" value="blank">
|
||||
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>">
|
||||
<input type="hidden" name="action" value="control">
|
||||
<input type="hidden" name="view" value="blank"/>
|
||||
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>"/>
|
||||
<input type="hidden" name="action" value="control"/>
|
||||
<?php
|
||||
if ( $monitor['CanMoveMap'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="moveMap">
|
||||
<input type="hidden" name="control" value="moveMap"/>
|
||||
<?php
|
||||
} elseif ( $monitor['CanMoveRel'] ) {
|
||||
} else if ( $monitor['CanMoveRel'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="movePseudoMap">
|
||||
<input type="hidden" name="control" value="movePseudoMap"/>
|
||||
<?php
|
||||
} elseif ( $monitor['CanMoveCon'] ) {
|
||||
} else if ( $monitor['CanMoveCon'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="moveConMap">
|
||||
<input type="hidden" name="control" value="moveConMap"/>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<input type="hidden" name="scale" value="<?php echo $scale ?>">
|
||||
<input type="hidden" name="scale" value="<?php echo $scale ?>"/>
|
||||
<input type="image" src="<?php echo $src ?>" width="<?php echo $width ?>" height="<?php echo $height ?>">
|
||||
</form>
|
||||
<?php
|
||||
|
@ -365,26 +332,26 @@ function getWebSiteUrl( $id, $src, $width, $height, $title='' ) {
|
|||
function outputControlStill( $src, $width, $height, $monitor, $scale, $target ) {
|
||||
?>
|
||||
<form name="ctrlForm" method="post" action="?" target="<?php echo $target ?>">
|
||||
<input type="hidden" name="view" value="blank">
|
||||
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>">
|
||||
<input type="hidden" name="action" value="control">
|
||||
<input type="hidden" name="view" value="blank"/>
|
||||
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>"/>
|
||||
<input type="hidden" name="action" value="control"/>
|
||||
<?php
|
||||
if ( $monitor['CanMoveMap'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="moveMap">
|
||||
<input type="hidden" name="control" value="moveMap"/>
|
||||
<?php
|
||||
} elseif ( $monitor['CanMoveRel'] ) {
|
||||
} else if ( $monitor['CanMoveRel'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="movePseudoMap">
|
||||
<input type="hidden" name="control" value="movePseudoMap"/>
|
||||
<?php
|
||||
} elseif ( $monitor['CanMoveCon'] ) {
|
||||
} else if ( $monitor['CanMoveCon'] ) {
|
||||
?>
|
||||
<input type="hidden" name="control" value="moveConMap">
|
||||
<input type="hidden" name="control" value="moveConMap"/>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<input type="hidden" name="scale" value="<?php echo $scale ?>">
|
||||
<input type="image" src="<?php echo $src ?>" width="<?php echo $width ?>" height="<?php echo $height ?>">
|
||||
<input type="hidden" name="scale" value="<?php echo $scale ?>"/>
|
||||
<input type="image" src="<?php echo $src ?>" width="<?php echo $width ?>" height="<?php echo $height ?>"/>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
@ -405,12 +372,12 @@ function getZmuCommand( $args ) {
|
|||
|
||||
$zmuCommand .= $args;
|
||||
|
||||
return( $zmuCommand );
|
||||
return $zmuCommand;
|
||||
}
|
||||
|
||||
function getEventDefaultVideoPath( $event ) {
|
||||
$Event = new ZM\Event( $event );
|
||||
return $Event->getStreamSrc( array( 'mode'=>'mpeg', 'format'=>'h264' ) );
|
||||
function getEventDefaultVideoPath($event) {
|
||||
$Event = new ZM\Event($event);
|
||||
return $Event->getStreamSrc(array('mode'=>'mpeg', 'format'=>'h264'));
|
||||
}
|
||||
|
||||
function deletePath( $path ) {
|
||||
|
|
|
@ -28,7 +28,6 @@ function zm_session_start() {
|
|||
session_destroy();
|
||||
session_start();
|
||||
} else if ( !empty($_SESSION['generated_at']) ) {
|
||||
ZM\Logger::Debug("Have generated_at: " . $_SESSION['generated_at']);
|
||||
if ( $_SESSION['generated_at']<($now-(ZM_COOKIE_LIFETIME/2)) ) {
|
||||
ZM\Logger::Debug("Regenerating session because generated_at " . $_SESSION['generated_at'] . ' < ' . $now . '-'.ZM_COOKIE_LIFETIME.'/2 = '.($now-ZM_COOKIE_LIFETIME/2));
|
||||
zm_session_regenerate_id();
|
||||
|
|
|
@ -87,27 +87,38 @@ if ( isset($_GET['skin']) ) {
|
|||
$skin = 'classic';
|
||||
}
|
||||
|
||||
$skins = array_map('basename', glob('skins/*', GLOB_ONLYDIR));
|
||||
if ( ! is_dir("skins/$skin") ) {
|
||||
$skins = array_map('basename', glob('skins/*', GLOB_ONLYDIR));
|
||||
|
||||
if ( ! in_array($skin, $skins) ) {
|
||||
ZM\Error("Invalid skin '$skin' setting to " . $skins[0]);
|
||||
$skin = $skins[0];
|
||||
if ( !in_array($skin, $skins) ) {
|
||||
ZM\Error("Invalid skin '$skin' setting to ".$skins[0]);
|
||||
$skin = $skins[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset($_GET['css']) ) {
|
||||
$css = $_GET['css'];
|
||||
} elseif ( isset($_COOKIE['zmCSS']) ) {
|
||||
} else if ( isset($_COOKIE['zmCSS']) ) {
|
||||
$css = $_COOKIE['zmCSS'];
|
||||
} elseif ( defined('ZM_CSS_DEFAULT') ) {
|
||||
} else if ( defined('ZM_CSS_DEFAULT') ) {
|
||||
$css = ZM_CSS_DEFAULT;
|
||||
} else {
|
||||
$css = 'classic';
|
||||
}
|
||||
|
||||
$css_skins = array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR));
|
||||
if ( !in_array($css, $css_skins) ) {
|
||||
ZM\Error("Invalid skin css '$css' setting to " . $css_skins[0]);
|
||||
$css = $css_skins[0];
|
||||
if ( !is_dir("skins/$skin/css/$css") ) {
|
||||
$css_skins = array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR));
|
||||
if ( count($css_skins) ) {
|
||||
if ( !in_array($css, $css_skins) ) {
|
||||
ZM\Error("Invalid skin css '$css' setting to " . $css_skins[0]);
|
||||
$css = $css_skins[0];
|
||||
} else {
|
||||
$css = '';
|
||||
}
|
||||
} else {
|
||||
ZM\Error("No css options found at skins/$skin/css");
|
||||
$css = '';
|
||||
}
|
||||
}
|
||||
|
||||
define('ZM_BASE_PATH', dirname($_SERVER['REQUEST_URI']));
|
||||
|
@ -116,7 +127,7 @@ define('ZM_SKIN_NAME', $skin);
|
|||
|
||||
$skinBase = array(); // To allow for inheritance of skins
|
||||
if ( !file_exists(ZM_SKIN_PATH) )
|
||||
Fatal("Invalid skin '$skin'");
|
||||
ZM\Fatal("Invalid skin '$skin'");
|
||||
$skinBase[] = $skin;
|
||||
|
||||
zm_session_start();
|
||||
|
@ -125,7 +136,7 @@ if (
|
|||
!isset($_SESSION['skin']) ||
|
||||
isset($_REQUEST['skin']) ||
|
||||
!isset($_COOKIE['zmSkin']) ||
|
||||
$_COOKIE['zmSkin'] != $skin
|
||||
($_COOKIE['zmSkin'] != $skin)
|
||||
) {
|
||||
$_SESSION['skin'] = $skin;
|
||||
setcookie('zmSkin', $skin, time()+3600*24*30*12*10);
|
||||
|
@ -135,7 +146,7 @@ if (
|
|||
!isset($_SESSION['css']) ||
|
||||
isset($_REQUEST['css']) ||
|
||||
!isset($_COOKIE['zmCSS']) ||
|
||||
$_COOKIE['zmCSS'] != $css
|
||||
($_COOKIE['zmCSS'] != $css)
|
||||
) {
|
||||
$_SESSION['css'] = $css;
|
||||
setcookie('zmCSS', $css, time()+3600*24*30*12*10);
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web frame view file, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView( 'Events' ) )
|
||||
{
|
||||
$view = "error";
|
||||
return;
|
||||
}
|
||||
|
||||
$eid = validInt($_REQUEST['eid']);
|
||||
if ( !empty($_REQUEST['fid']) )
|
||||
$fid = validInt($_REQUEST['fid']);
|
||||
|
||||
$sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultScale,M.VideoWriter,M.Orientation FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?';
|
||||
$event = dbFetchOne( $sql, NULL, array($eid) );
|
||||
|
||||
if ( !empty($fid) ) {
|
||||
$sql = 'SELECT * FROM Frames WHERE EventId = ? AND FrameId = ?';
|
||||
if ( !($frame = dbFetchOne( $sql, NULL, array($eid, $fid) )) )
|
||||
$frame = array( 'FrameId'=>$fid, 'Type'=>'Normal', 'Score'=>0 );
|
||||
} else {
|
||||
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $event['MaxScore'] ) );
|
||||
}
|
||||
|
||||
$maxFid = $event['Frames'];
|
||||
|
||||
$firstFid = 1;
|
||||
$prevFid = $frame['FrameId']-1;
|
||||
$nextFid = $frame['FrameId']+1;
|
||||
$lastFid = $maxFid;
|
||||
|
||||
$alarmFrame = $frame['Type']=='Alarm';
|
||||
|
||||
if ( isset( $_REQUEST['scale'] ) )
|
||||
$scale = validInt($_REQUEST['scale']);
|
||||
else
|
||||
$scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||
|
||||
$Transpose = '';
|
||||
if ( $event['VideoWriter'] == "2" ) { // PASSTHROUGH
|
||||
$Rotation = $event['Orientation'];
|
||||
// rotate right
|
||||
if ( in_array($event['Orientation'],array("90")))
|
||||
$Transpose = 'transpose=1,';
|
||||
// rotate 180 // upside down cam
|
||||
if ( in_array($event['Orientation'],array("180")))
|
||||
$Transpose = 'transpose=2,transpose=2,';
|
||||
// rotate left
|
||||
if ( in_array($event['Orientation'],array("270")))
|
||||
$Transpose = 'transpose=2,';
|
||||
}
|
||||
$focusWindow = true;
|
||||
$Scale = 100/$scale;
|
||||
$fid = $fid - 1;
|
||||
#$command = 'ffmpeg -v 0 -i '.getEventDefaultVideoPath($event).' -vf "select=gte(selected_n\,'.$fid.'),setpts=PTS-STARTPTS" '.$Transpose.',scale=iw/'.$Scale.':-1" -frames:v 1 -f mjpeg -';
|
||||
$command = 'ffmpeg -v 0 -i '.getEventDefaultVideoPath($event).' -vf "select=gte(n\\,'.$fid.'),setpts=PTS-STARTPTS,'.$Transpose.'scale=iw/'.$Scale.':-1" -f image2 -';
|
||||
header('Content-Type: image/jpeg');
|
||||
system($command);
|
||||
?>
|
|
@ -215,7 +215,6 @@ function selectLayout(element) {
|
|||
|
||||
if ( layout_id = parseInt(layout) ) {
|
||||
layout = layouts[layout];
|
||||
console.log(layout);
|
||||
|
||||
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
||||
monitor = monitors[i];
|
||||
|
@ -396,6 +395,16 @@ function edit_layout(button) {
|
|||
|
||||
function save_layout(button) {
|
||||
var form = button.form;
|
||||
var name = form.elements['Name'].value;
|
||||
|
||||
if ( !name )
|
||||
name = form.elements['zmMontageLayout'].options[form.elements['zmMontageLayout'].selectedIndex].text;
|
||||
|
||||
if ( name=='Freeform' || name=='2 Wide' || name=='3 Wide' || name=='4 Wide' || name=='5 Wide' ) {
|
||||
alert('You cannot edit the built in layouts. Please give the layout a new name.');
|
||||
return;
|
||||
}
|
||||
|
||||
// In fixed positioning, order doesn't matter. In floating positioning, it does.
|
||||
var Positions = {};
|
||||
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
||||
|
|
|
@ -22,14 +22,14 @@ function gotoStep2( element ) {
|
|||
form.submit();
|
||||
}
|
||||
|
||||
function configureButtons( element ) {
|
||||
function configureButtons(element) {
|
||||
var form = element.form;
|
||||
if (form.elements.namedItem("nextBtn")) {
|
||||
if (form.elements.namedItem('nextBtn')) {
|
||||
form.nextBtn.disabled = (form.probe.selectedIndex==0) ||
|
||||
(form.username == "") || (form.username == null) ||
|
||||
(form.password == "") || (form.password == null);
|
||||
(form.Username == '') || (form.Username == null) ||
|
||||
(form.Password == '') || (form.Password == null);
|
||||
}
|
||||
if (form.elements.namedItem("saveBtn")) {
|
||||
if (form.elements.namedItem('saveBtn')) {
|
||||
form.saveBtn.disabled = (form.probe.selectedIndex==0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,11 +180,11 @@ if ( $showZones ) {
|
|||
<?php echo htmlSelect('zmMontageLayout', $layoutsById, $layout_id, array('onchange'=>'selectLayout(this);')); ?>
|
||||
</span>
|
||||
<input type="hidden" name="Positions"/>
|
||||
<input type="button" id="EditLayout" value="<?php echo translate('EditLayout') ?>" data-on-click-this="edit_layout"/>
|
||||
<button type="button" id="EditLayout" data-on-click-this="edit_layout"><?php echo translate('EditLayout') ?></button>
|
||||
<span id="SaveLayout" style="display:none;">
|
||||
<input type="text" name="Name" placeholder="Enter new name for layout if desired" />
|
||||
<input type="button" value="<?php echo translate('Save') ?>" data-on-click-this="save_layout"/>
|
||||
<input type="button" value="Cancel" data-on-click-this="cancel_layout"/>
|
||||
<button type="button" value="Save" data-on-click-this="save_layout"><?php echo translate('Save') ?></button>
|
||||
<button type="button" value="Cancel" data-on-click-this="cancel_layout"><?php echo translate('Cancel') ?></button>
|
||||
</span>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -41,18 +41,18 @@ function execONVIF( $cmd ) {
|
|||
Please the following command from a command line for more information:<br/><br/>$shell_command"
|
||||
);
|
||||
} else {
|
||||
ZM\Logger::Debug( "Results from probe: " . implode( '<br/>', $output ) );
|
||||
ZM\Logger::Debug('Results from probe: '.implode('<br/>', $output));
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function probeCameras( $localIp ) {
|
||||
function probeCameras($localIp) {
|
||||
$cameras = array();
|
||||
if ( $lines = @execONVIF( 'probe' ) ) {
|
||||
if ( $lines = @execONVIF('probe') ) {
|
||||
foreach ( $lines as $line ) {
|
||||
$line = rtrim( $line );
|
||||
if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) {
|
||||
$line = rtrim($line);
|
||||
if ( preg_match('|^(.+),(.+),\s\((.*)\)$|', $line, $matches) ) {
|
||||
$device_ep = $matches[1];
|
||||
$soapversion = $matches[2];
|
||||
$camera = array(
|
||||
|
@ -65,7 +65,7 @@ function probeCameras( $localIp ) {
|
|||
),
|
||||
);
|
||||
foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) {
|
||||
if ( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) {
|
||||
if ( preg_match('|(.+)=\'(.*)\'|', $attr_val, $tokens) ) {
|
||||
if ( $tokens[1] == 'hardware' ) {
|
||||
$camera['model'] = $tokens[2];
|
||||
} elseif ( $tokens[1] == 'name' ) {
|
||||
|
@ -84,7 +84,7 @@ function probeCameras( $localIp ) {
|
|||
return $cameras;
|
||||
} // end function probeCameras
|
||||
|
||||
function probeProfiles( $device_ep, $soapversion, $username, $password ) {
|
||||
function probeProfiles($device_ep, $soapversion, $username, $password) {
|
||||
$profiles = array();
|
||||
if ( $lines = @execONVIF("profiles $device_ep $soapversion $username $password") ) {
|
||||
foreach ( $lines as $line ) {
|
||||
|
@ -94,7 +94,7 @@ function probeProfiles( $device_ep, $soapversion, $username, $password ) {
|
|||
// add user@pass to URI
|
||||
if ( preg_match('|^(\S+://)(.+)$|', $stream_uri, $tokens) ) {
|
||||
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
|
||||
}
|
||||
}
|
||||
|
||||
$profile = array( # 'monitor' part of camera
|
||||
'Type' => 'Ffmpeg',
|
||||
|
@ -125,8 +125,8 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );
|
|||
if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
||||
|
||||
$monitors = array();
|
||||
foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) {
|
||||
if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) ) {
|
||||
foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type='Remote' ORDER BY Host") as $monitor ) {
|
||||
if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) {
|
||||
//echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."<br/>";
|
||||
$monitors[gethostbyname($matches[2])] = $monitor;
|
||||
} else {
|
||||
|
@ -137,26 +137,12 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
|||
|
||||
$detcameras = probeCameras('');
|
||||
foreach ( $detcameras as $camera ) {
|
||||
if ( preg_match( '|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches ) ) {
|
||||
if ( preg_match('|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches) ) {
|
||||
$ip = $matches[1];
|
||||
}
|
||||
$host = $ip;
|
||||
/*
|
||||
if ( isset($monitors[$ip]) )
|
||||
{
|
||||
$monitor = $monitors[$ip];
|
||||
$sourceString .= " (".$monitor['Name'].")";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sourceString .= " - ".translate('Available');
|
||||
}
|
||||
$cameras[$sourceDesc] = $sourceString;
|
||||
}
|
||||
*/
|
||||
// $sourceDesc = htmlspecialchars(serialize($camera['monitor']));
|
||||
$sourceDesc = base64_encode(json_encode($camera['monitor']));
|
||||
$sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ;
|
||||
$sourceString = $camera['model'].' @ '.$host.' using version '.$camera['monitor']['SOAP'];
|
||||
$cameras[$sourceDesc] = $sourceString;
|
||||
}
|
||||
|
||||
|
@ -179,39 +165,38 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
|||
</p>
|
||||
<p>
|
||||
<label for="probe"><?php echo translate('DetectedCameras') ?></label>
|
||||
<?php echo htmlSelect('probe', $cameras, null, array('onchange'=>'configureButtons(this)')); ?>
|
||||
<?php echo htmlSelect('probe', $cameras, null, array('data-on-change-this'=>'configureButtons')); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo translate('OnvifCredentialsIntro') ?>
|
||||
</p>
|
||||
<p>
|
||||
<label for="username"><?php echo translate('Username') ?></label>
|
||||
<input type="text" name="username" value="" onChange="configureButtons(this)"/>
|
||||
<label for="Username"><?php echo translate('Username') ?></label>
|
||||
<input type="text" name="Username" data-on-change-this="configureButtons"/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password"><?php echo translate('Password') ?></label>
|
||||
<input type="password" name="password" value="" onChange="configureButtons(this)"/>
|
||||
<label for="Password"><?php echo translate('Password') ?></label>
|
||||
<input type="password" name="Password" data-on-change-this="configureButtons"/>
|
||||
</p>
|
||||
<div id="contentButtons">
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" data-on-click="closeWindow"/>
|
||||
<input type="submit" name="nextBtn" value="<?php echo translate('Next') ?>" data-on-click-this="gotoStep2" disabled="disabled"/>
|
||||
<button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
|
||||
<button type="button" name="nextBtn" data-on-click-this="gotoStep2" disabled="disabled"><?php echo translate('Next') ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
//==== STEP 2 ============================================================
|
||||
} else if($_REQUEST['step'] == '2') {
|
||||
} else if ( $_REQUEST['step'] == '2' ) {
|
||||
if ( empty($_REQUEST['probe']) )
|
||||
ZM\Fatal('No probe passed in request. Please go back and try again.');
|
||||
#|| empty($_REQUEST['username']) ||
|
||||
#empty($_REQUEST['password']) )
|
||||
|
||||
$probe = json_decode(base64_decode($_REQUEST['probe']));
|
||||
ZM\Logger::Debug(print_r($probe,true));
|
||||
ZM\Logger::Debug(print_r($probe, true));
|
||||
foreach ( $probe as $name=>$value ) {
|
||||
if ( isset($value) ) {
|
||||
$monitor[$name] = $value;
|
||||
|
@ -221,7 +206,7 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
|||
|
||||
//print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']."<br/>";
|
||||
|
||||
$detprofiles = probeProfiles($monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']);
|
||||
$detprofiles = probeProfiles($monitor['Host'], $monitor['SOAP'], $_REQUEST['Username'], $_REQUEST['Password']);
|
||||
foreach ( $detprofiles as $profile ) {
|
||||
$monitor = $camera['monitor'];
|
||||
|
||||
|
@ -258,18 +243,18 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
|||
</p>
|
||||
<p>
|
||||
<label for="probe"><?php echo translate('DetectedProfiles') ?></label>
|
||||
<?php echo htmlSelect('probe', $profiles, null, array('onchange'=>'configureButtons(this)')); ?>
|
||||
<?php echo htmlSelect('probe', $profiles, null, array('data-on-change-this'=>'configureButtons')); ?>
|
||||
</p>
|
||||
<div id="contentButtons">
|
||||
<input type="button" name="prevBtn" value="<?php echo translate('Prev') ?>" data-on-click-this="gotoStep1"/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" data-on-click="closeWindow"/>
|
||||
<input type="submit" name="saveBtn" value="<?php echo translate('Save') ?>" data-on-click-this="submitCamera" disabled="disabled"/>
|
||||
<button type="button" name="prevBtn" data-on-click-this="gotoStep1"><?php echo translate('Prev') ?></button>
|
||||
<button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
|
||||
<button type="button" name="saveBtn" data-on-click-this="submitCamera" disabled="disabled"><?php echo translate('Save') ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
} // end if step 1 or 2
|
||||
?>
|
||||
</html>
|
||||
|
|
|
@ -53,31 +53,6 @@ $focusWindow = true;
|
|||
|
||||
xhtmlHeaders(__FILE__, translate('Options'));
|
||||
|
||||
# Have to do this stuff up here before including header.php because fof the cookie setting
|
||||
$skin_options = array_map('basename', glob('skins/*',GLOB_ONLYDIR));
|
||||
if ( $tab == 'skins' ) {
|
||||
$current_skin = $_COOKIE['zmSkin'];
|
||||
$reload = false;
|
||||
if ( isset($_GET['skin-choice']) && ( $_GET['skin-choice'] != $current_skin ) ) {
|
||||
setcookie('zmSkin',$_GET['skin-choice'], time()+3600*24*30*12*10 );
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
$current_css = $_COOKIE['zmCSS'];
|
||||
if ( isset($_GET['css-choice']) and ( $_GET['css-choice'] != $current_css ) ) {
|
||||
setcookie('zmCSS',$_GET['css-choice'], time()+3600*24*30*12*10 );
|
||||
array_map('unlink', glob(ZM_PATH_WEB.'/cache/*')); //cleanup symlinks from cache_bust
|
||||
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
|
||||
$reload = true;
|
||||
}
|
||||
if ( $reload )
|
||||
echo "<script nonce=\"$cspNonce\">if (window.opener) {
|
||||
window.opener.location.reload();
|
||||
}
|
||||
window.location.href=\"?view={$view}&tab={$tab}\";
|
||||
</script>";
|
||||
} # end if tab == skins
|
||||
|
||||
?>
|
||||
<body>
|
||||
<?php echo getNavBarHTML(); ?>
|
||||
|
@ -104,12 +79,14 @@ if ( $tab == 'skins' ) {
|
|||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="tab" value="<?php echo $tab ?>"/>
|
||||
<div class="form-group">
|
||||
<label for="skin-choice" class="col-sm-3 control-label">SKIN</label>
|
||||
<label for="skin" class="col-sm-3 control-label">SKIN</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="skin-choice" class="form-control chosen">
|
||||
<select name="skin" class="form-control chosen">
|
||||
<?php
|
||||
# Have to do this stuff up here before including header.php because fof the cookie setting
|
||||
$skin_options = array_map('basename', glob('skins/*',GLOB_ONLYDIR));
|
||||
foreach ( $skin_options as $dir ) {
|
||||
echo '<option value="'.$dir.'" '.($current_skin==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
echo '<option value="'.$dir.'" '.($skin==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
@ -117,12 +94,12 @@ foreach ( $skin_options as $dir ) {
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="css-choice" class="col-sm-3 control-label">CSS</label>
|
||||
<label for="css" class="col-sm-3 control-label">CSS</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="css-choice" class="form-control chosen">
|
||||
<select name="css" class="form-control chosen">
|
||||
<?php
|
||||
foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDIR)) as $dir ) {
|
||||
echo '<option value="'.$dir.'" '.($current_css==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $dir ) {
|
||||
echo '<option value="'.$dir.'" '.($css==$dir ? 'SELECTED="SELECTED"' : '').'>'.$dir.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
@ -325,40 +302,37 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
?>
|
||||
|
||||
<form name="userForm" method="post" action="?">
|
||||
<button class="pull-left" type="submit" name="updateSelected" id="updateSelected"><?php echo translate("Update")?> </button><button class="btn-danger pull-right" type="submit" name="revokeAllTokens" id="revokeAllTokens"> <?php echo translate("RevokeAllTokens")?></button><br/>
|
||||
|
||||
<button class="pull-left" type="submit" name="updateSelected" id="updateSelected"><?php echo translate('Update')?></button>
|
||||
<button class="btn-danger pull-right" type="submit" name="revokeAllTokens" id="revokeAllTokens"><?php echo translate('RevokeAllTokens')?></button>
|
||||
<br/>
|
||||
<?php
|
||||
function revokeAllTokens()
|
||||
{
|
||||
function revokeAllTokens() {
|
||||
$minTokenTime = time();
|
||||
dbQuery ('UPDATE Users SET TokenMinExpiry=?', array ($minTokenTime));
|
||||
echo "<span class='timedSuccessBox'>".translate('AllTokensRevoked')."</span>";
|
||||
dbQuery('UPDATE `Users` SET `TokenMinExpiry`=?', array($minTokenTime));
|
||||
echo '<span class="timedSuccessBox">'.translate('AllTokensRevoked').'</span>';
|
||||
}
|
||||
|
||||
function updateSelected()
|
||||
{
|
||||
dbQuery("UPDATE Users SET APIEnabled=0");
|
||||
foreach( $_REQUEST["tokenUids"] as $markUid ) {
|
||||
function updateSelected() {
|
||||
dbQuery('UPDATE `Users` SET `APIEnabled`=0');
|
||||
foreach ( $_REQUEST["tokenUids"] as $markUid ) {
|
||||
$minTime = time();
|
||||
dbQuery('UPDATE Users SET TokenMinExpiry=? WHERE Id=?', array($minTime, $markUid));
|
||||
dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid));
|
||||
}
|
||||
foreach( $_REQUEST["apiUids"] as $markUid ) {
|
||||
dbQuery('UPDATE Users SET APIEnabled=1 WHERE Id=?', array($markUid));
|
||||
foreach ( $_REQUEST["apiUids"] as $markUid ) {
|
||||
dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid));
|
||||
|
||||
}
|
||||
echo "<span class='timedSuccessBox'>".translate('Updated')."</span>";
|
||||
echo '<span class="timedSuccessBox">'.translate('Updated').'</span>';
|
||||
}
|
||||
|
||||
if(array_key_exists('revokeAllTokens',$_POST)){
|
||||
if ( array_key_exists('revokeAllTokens',$_POST) ) {
|
||||
revokeAllTokens();
|
||||
}
|
||||
|
||||
if(array_key_exists('updateSelected',$_POST)){
|
||||
if ( array_key_exists('updateSelected',$_POST) ) {
|
||||
updateSelected();
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<br/><br/>
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="tab" value="<?php echo $tab ?>"/>
|
||||
|
@ -375,7 +349,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
<?php
|
||||
|
||||
$sql = 'SELECT * FROM Users ORDER BY Username';
|
||||
foreach( dbFetchAll($sql) as $row ) {
|
||||
foreach ( dbFetchAll($sql) as $row ) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="colUsername"><?php echo validHtmlStr($row['Username']) ?></td>
|
||||
|
@ -398,7 +372,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
$configCat = array();
|
||||
$configCats = array();
|
||||
|
||||
$result = $dbConn->query('SELECT * FROM Config ORDER BY Id ASC');
|
||||
$result = $dbConn->query('SELECT * FROM `Config` ORDER BY `Id` ASC');
|
||||
if ( !$result )
|
||||
echo mysql_error();
|
||||
while( $row = dbFetchNext($result) ) {
|
||||
|
@ -411,9 +385,9 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
}
|
||||
|
||||
if ( $tab == 'system' ) {
|
||||
$configCats[$tab]['ZM_LANG_DEFAULT']['Hint'] = join( '|', getLanguages() );
|
||||
$configCats[$tab]['ZM_SKIN_DEFAULT']['Hint'] = join( '|', $skin_options );
|
||||
$configCats[$tab]['ZM_CSS_DEFAULT']['Hint'] = join( '|', array_map ( 'basename', glob('skins/'.ZM_SKIN_DEFAULT.'/css/*',GLOB_ONLYDIR) ) );
|
||||
$configCats[$tab]['ZM_LANG_DEFAULT']['Hint'] = join('|', getLanguages());
|
||||
$configCats[$tab]['ZM_SKIN_DEFAULT']['Hint'] = join('|', array_map('basename', glob('skins/*',GLOB_ONLYDIR)));
|
||||
$configCats[$tab]['ZM_CSS_DEFAULT']['Hint'] = join('|', array_map ( 'basename', glob('skins/'.ZM_SKIN_DEFAULT.'/css/*',GLOB_ONLYDIR) ));
|
||||
$configCats[$tab]['ZM_BANDWIDTH_DEFAULT']['Hint'] = $bandwidth_options;
|
||||
}
|
||||
?>
|
||||
|
@ -508,7 +482,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
?>
|
||||
|
||||
<div id="contentButtons">
|
||||
<button type="submit" value="Save"<?php echo $canEdit?'':' disabled="disabled"' ?>><?php echo translate('Save') ?></button>
|
||||
<button type="submit" <?php echo $canEdit?'':' disabled="disabled"' ?>><?php echo translate('Save') ?></button>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
|
|
|
@ -132,7 +132,7 @@ $chart = array(
|
|||
$monitors = array();
|
||||
$monitorsSql = 'SELECT * FROM Monitors ORDER BY Sequence ASC';
|
||||
//srand( 97981 );
|
||||
foreach( dbFetchAll( $monitorsSql ) as $row ) {
|
||||
foreach( dbFetchAll($monitorsSql) as $row ) {
|
||||
//if ( empty($row['WebColour']) )
|
||||
//{
|
||||
//$row['WebColour'] = sprintf( "#%02x%02x%02x", rand( 0, 255 ), rand( 0, 255), rand( 0, 255 ) );
|
||||
|
@ -312,9 +312,9 @@ $chart['data']['x']['density'] = $chart['data']['x']['range']/$chart['graph']['w
|
|||
$monEventSlots = array();
|
||||
$monFrameSlots = array();
|
||||
$monitorIds = array();
|
||||
$events_result = dbQuery( $eventsSql );
|
||||
if ( ! $events_result ) {
|
||||
Fatal( "SQL-ERR");
|
||||
$events_result = dbQuery($eventsSql);
|
||||
if ( !$events_result ) {
|
||||
Fatal("SQL-ERR");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue