diff --git a/.travis.yml b/.travis.yml index 80541eaab..e41dcb35f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index cc6158334..1a2c6c9e0 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index fc19eb7d9..b5a89e601 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -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."); diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 839b69e0f..57c660342 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -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) ) { diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 68c9eae08..7d75042ba 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -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; diff --git a/src/zm_db.cpp b/src/zm_db.cpp index 806ef8e5c..77c149f03 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -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; } diff --git a/src/zm_event.cpp b/src/zm_event.cpp index ef39dfa7a..a4117729c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -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 { diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index bd8643335..339b54c6c 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -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; +} + diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index f6443f797..c65bb38a0 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -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 #include #include +#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 diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index c9298fe77..cf55a75d4 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -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 // for ESRCH -#include -#include -#endif #include @@ -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; diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index 03d89348d..ab7cbe8d3 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -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); diff --git a/src/zm_file_camera.cpp b/src/zm_file_camera.cpp index 1bc861b23..a7883c5d5 100644 --- a/src/zm_file_camera.cpp +++ b/src/zm_file_camera.cpp @@ -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 #include #include #include #include -#include -#include -#include -#include #include #include #include @@ -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; } diff --git a/src/zm_image.cpp b/src/zm_image.cpp index f8ad1ab70..9cf4ada94 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -1,21 +1,21 @@ // // ZoneMinder Image 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 "zm.h" #include "zm_font.h" #include "zm_bigfont.h" @@ -126,7 +126,7 @@ Image::Image( const char *filename ) { height = 0; pixels = 0; colours = 0; - subpixelorder = 0; + subpixelorder = 0; size = 0; allocation = 0; buffer = 0; @@ -279,7 +279,7 @@ void Image::Initialise() { fptr_blend = &std_blend; Debug(4,"Blend: Using standard blend function"); } - + __attribute__((aligned(64))) uint8_t blend1[128] = { 86,58,54,63,149,62,209,34,148,46,186,176,9,236,193,254,113,146,228,220,123,164,92,98,9,72,67,156,63,118,96,167, 48,224,106,176,201,245,223,219,198,50,100,31,68,77,33,76,166,90,254,128,191,82,84,32,3,171,147,248,14,196,141,179, @@ -413,7 +413,7 @@ void Image::Initialise() { } } - /* + /* SSSE3 deinterlacing functions were removed because they were usually equal or slower than the standard code (compiled with -O2 or better) The function is too complicated to be vectorized efficiently on SSSE3 @@ -528,7 +528,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei size = newsize; } // end if need to re-alloc buffer - return buffer; + return buffer; } /* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */ @@ -623,7 +623,7 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons return; } } else { - if ( new_size > allocation || !buffer ) { + if ( new_size > allocation || !buffer ) { DumpImgBuffer(); AllocImgBuffer(new_size); } @@ -663,7 +663,7 @@ void Image::Assign( const Image &image ) { return; } } else { - if(new_size > allocation || !buffer) { + if(new_size > allocation || !buffer) { // DumpImgBuffer(); This is also done in AllocImgBuffer AllocImgBuffer(new_size); } @@ -802,25 +802,25 @@ bool Image::ReadRaw( const char *filename ) { return false; } - fclose( infile ); + fclose(infile); return true; } -bool Image::WriteRaw( const char *filename ) const { +bool Image::WriteRaw(const char *filename) const { FILE *outfile; - if ( (outfile = fopen( filename, "wb" )) == NULL ) { - Error( "Can't open %s: %s", filename, strerror(errno) ); + if ( (outfile = fopen(filename, "wb")) == NULL ) { + Error("Can't open %s: %s", filename, strerror(errno)); return false; } if ( fwrite( buffer, size, 1, outfile ) != 1 ) { - Error( "Unable to write to '%s': %s", filename, strerror(errno) ); - fclose( outfile ); + Error("Unable to write to '%s': %s", filename, strerror(errno)); + fclose(outfile); return false; } - fclose( outfile ); + fclose(outfile); return true; } @@ -885,13 +885,13 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int { #ifdef JCS_EXTENSIONS new_colours = ZM_COLOUR_RGB32; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { cinfo->out_color_space = JCS_EXT_BGRX; new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + } else if ( p_subpixelorder == ZM_SUBPIX_ORDER_ARGB ) { cinfo->out_color_space = JCS_EXT_XRGB; new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + } else if ( p_subpixelorder == ZM_SUBPIX_ORDER_ABGR ) { cinfo->out_color_space = JCS_EXT_XBGR; new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; } else { @@ -899,7 +899,7 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int cinfo->out_color_space = JCS_EXT_RGBX; new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; } - break; + break; #else Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); #endif @@ -908,13 +908,13 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int default: { new_colours = ZM_COLOUR_RGB24; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_BGR; + if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; new_subpixelorder = ZM_SUBPIX_ORDER_BGR; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); - cinfo->out_color_space = JCS_RGB; + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; new_subpixelorder = ZM_SUBPIX_ORDER_RGB; #endif } else { @@ -933,28 +933,27 @@ cinfo->out_color_space = JCS_RGB; } } - if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { + if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) { Error("Failed requesting writeable buffer for reading JPEG image."); - jpeg_abort_decompress( cinfo ); - fclose( infile ); - return( false ); + jpeg_abort_decompress(cinfo); + fclose(infile); + return false; } - jpeg_start_decompress( cinfo ); + jpeg_start_decompress(cinfo); JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = width * colours; /* physical row width in buffer */ - while ( cinfo->output_scanline < cinfo->output_height ) - { + while ( cinfo->output_scanline < cinfo->output_height ) { row_pointer = &buffer[cinfo->output_scanline * row_stride]; - jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + jpeg_read_scanlines(cinfo, &row_pointer, 1); } - jpeg_finish_decompress( cinfo ); + jpeg_finish_decompress(cinfo); - fclose( infile ); + fclose(infile); - return( true ); + return true; } // Multiple calling formats to permit inclusion (or not) of non blocking, quality_override and timestamp (exif), with suitable defaults. @@ -977,7 +976,7 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval return Image::WriteJpeg(filename, quality_override, timestamp, false); } bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp, bool on_blocking_abort) const { - if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { + if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) { Image temp_image(*this); temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB); return temp_image.WriteJpeg(filename, quality_override, timestamp, on_blocking_abort); @@ -985,66 +984,63 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval int quality = quality_override?quality_override:config.jpeg_file_quality; struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality]; - FILE *outfile =NULL; + FILE *outfile = NULL; static int raw_fd = 0; bool need_create_comp = false; raw_fd = 0; if ( !cinfo ) { cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); - jpeg_create_compress( cinfo ); - need_create_comp=true; + cinfo->err = jpeg_std_error(&jpg_err.pub); + jpeg_create_compress(cinfo); + need_create_comp = true; } - if (! on_blocking_abort) { - jpg_err.pub.error_exit = zm_jpeg_error_exit; - jpg_err.pub.emit_message = zm_jpeg_emit_message; + if ( !on_blocking_abort ) { + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; } else { jpg_err.pub.error_exit = zm_jpeg_error_silent; jpg_err.pub.emit_message = zm_jpeg_emit_silence; - if (setjmp( jpg_err.setjmp_buffer ) ) { - jpeg_abort_compress( cinfo ); - Debug( 5, "Aborted a write mid-stream and %s and %d", (outfile == NULL) ? "closing file" : "file not opened", raw_fd ); - if (raw_fd) + if ( setjmp(jpg_err.setjmp_buffer) ) { + jpeg_abort_compress(cinfo); + Debug(1, "Aborted a write mid-stream and %s and %d", (outfile == NULL) ? "closing file" : "file not opened", raw_fd); + if ( raw_fd ) close(raw_fd); - if (outfile) - fclose( outfile ); - return ( false ); + if ( outfile ) + fclose(outfile); + return false; } } - if (need_create_comp) - jpeg_create_compress( cinfo ); + if ( need_create_comp ) + jpeg_create_compress(cinfo); - if (! on_blocking_abort) { + if ( !on_blocking_abort ) { if ( (outfile = fopen(filename, "wb")) == NULL ) { - Error( "Can't open %s for writing: %s", filename, strerror(errno) ); + Error("Can't open %s for writing: %s", filename, strerror(errno)); return false; } } else { - raw_fd = open(filename,O_WRONLY|O_NONBLOCK|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (raw_fd < 0) - return ( false ); - outfile = fdopen(raw_fd,"wb"); - if (outfile == NULL) { + raw_fd = open(filename, O_WRONLY|O_NONBLOCK|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if ( raw_fd < 0 ) + return false; + outfile = fdopen(raw_fd, "wb"); + if ( outfile == NULL ) { close(raw_fd); - return( false ); + return false; } } - jpeg_stdio_dest( cinfo, outfile ); + jpeg_stdio_dest(cinfo, outfile); cinfo->image_width = width; /* image width and height, in pixels */ cinfo->image_height = height; - switch(colours) { + switch (colours) { case ZM_COLOUR_GRAY8: - { cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; break; - } case ZM_COLOUR_RGB32: - { #ifdef JCS_EXTENSIONS cinfo->input_components = 4; if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { @@ -1056,27 +1052,25 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval } else { /* Assume RGBA */ cinfo->in_color_space = JCS_EXT_RGBX; - } + } + break; #else Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); - jpeg_abort_compress( cinfo ); + jpeg_abort_compress(cinfo); fclose(outfile); return false; #endif - break; - } case ZM_COLOUR_RGB24: default: - { cinfo->input_components = 3; if ( subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS +#ifdef JCS_EXTENSIONS cinfo->in_color_space = JCS_EXT_BGR; #else Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); - jpeg_abort_compress( cinfo ); + jpeg_abort_compress(cinfo); fclose(outfile); - return false; + return false; #endif } else { /* Assume RGB */ @@ -1090,16 +1084,15 @@ cinfo->out_color_space = JCS_RGB; cinfo->in_color_space = JCS_RGB; } break; - } - } + } // end switch(colours) - jpeg_set_defaults( cinfo ); - jpeg_set_quality( cinfo, quality, FALSE ); + jpeg_set_defaults(cinfo); + jpeg_set_quality(cinfo, quality, FALSE); cinfo->dct_method = JDCT_FASTEST; - jpeg_start_compress( cinfo, TRUE ); + jpeg_start_compress(cinfo, TRUE); if ( config.add_jpeg_comments && text[0] ) { - jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); + jpeg_write_marker(cinfo, JPEG_COM, (const JOCTET *)text, strlen(text)); } // If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal // No timestamp just leave off the exif section. @@ -1123,14 +1116,14 @@ cinfo->out_color_space = JCS_RGB; 0xff, 0x00 }; memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); memcpy(&exiftimes[EXIFTIMES_MS_OFFSET], msbuf, EXIFTIMES_MS_LEN); - jpeg_write_marker( cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); + jpeg_write_marker(cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes)); } JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) { row_pointer = &buffer[cinfo->next_scanline * row_stride]; - jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + jpeg_write_scanlines(cinfo, &row_pointer, 1); } jpeg_finish_compress(cinfo); @@ -1140,13 +1133,16 @@ cinfo->out_color_space = JCS_RGB; return true; } -bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder) +bool Image::DecodeJpeg( + const JOCTET *inbuffer, + int inbuffer_size, + unsigned int p_colours, + unsigned int p_subpixelorder) { unsigned int new_width, new_height, new_colours, new_subpixelorder; struct jpeg_decompress_struct *cinfo = decodejpg_dcinfo; - if ( !cinfo ) - { + if ( !cinfo ) { cinfo = decodejpg_dcinfo = new jpeg_decompress_struct; cinfo->err = jpeg_std_error( &jpg_err.pub ); jpg_err.pub.error_exit = zm_jpeg_error_exit; @@ -1154,25 +1150,24 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int jpeg_create_decompress( cinfo ); } - if ( setjmp( jpg_err.setjmp_buffer ) ) - { - jpeg_abort_decompress( cinfo ); - return( false ); + if ( setjmp(jpg_err.setjmp_buffer) ) { + jpeg_abort_decompress(cinfo); + return false; } - zm_jpeg_mem_src( cinfo, inbuffer, inbuffer_size ); + zm_jpeg_mem_src(cinfo, inbuffer, inbuffer_size); - jpeg_read_header( cinfo, TRUE ); + jpeg_read_header(cinfo, TRUE); - if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) { - Error( "Unexpected colours when reading jpeg image: %d", colours ); - jpeg_abort_decompress( cinfo ); - return( false ); + if ( (cinfo->num_components != 1) && (cinfo->num_components != 3) ) { + Error("Unexpected colours when reading jpeg image: %d", colours); + jpeg_abort_decompress(cinfo); + return false; } /* Check if the image has at least one huffman table defined. If not, use the standard ones */ /* This is required for the MJPEG capture palette of USB devices */ - if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { + if ( cinfo->dc_huff_tbl_ptrs[0] == NULL ) { zm_use_std_huff_tables(cinfo); } @@ -1180,28 +1175,26 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int new_height = cinfo->image_height; if ( width != new_width || height != new_height ) { - Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); + Debug(9, "Image dimensions differ. Old: %ux%u New: %ux%u", + width, height, new_width, new_height); } - switch(p_colours) { + switch (p_colours) { case ZM_COLOUR_GRAY8: - { cinfo->out_color_space = JCS_GRAYSCALE; new_colours = ZM_COLOUR_GRAY8; new_subpixelorder = ZM_SUBPIX_ORDER_NONE; break; - } case ZM_COLOUR_RGB32: - { #ifdef JCS_EXTENSIONS new_colours = ZM_COLOUR_RGB32; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { cinfo->out_color_space = JCS_EXT_BGRX; new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + } else if ( p_subpixelorder == ZM_SUBPIX_ORDER_ARGB ) { cinfo->out_color_space = JCS_EXT_XRGB; new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + } else if ( p_subpixelorder == ZM_SUBPIX_ORDER_ABGR ) { cinfo->out_color_space = JCS_EXT_XBGR; new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; } else { @@ -1209,22 +1202,20 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int cinfo->out_color_space = JCS_EXT_RGBX; new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; } - break; + break; #else Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); #endif - } case ZM_COLOUR_RGB24: default: - { new_colours = ZM_COLOUR_RGB24; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_BGR; + if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; new_subpixelorder = ZM_SUBPIX_ORDER_BGR; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); - cinfo->out_color_space = JCS_RGB; + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; new_subpixelorder = ZM_SUBPIX_ORDER_RGB; #endif } else { @@ -1240,34 +1231,33 @@ cinfo->out_color_space = JCS_RGB; new_subpixelorder = ZM_SUBPIX_ORDER_RGB; } break; - } } // end switch - if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { + if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) { Error("Failed requesting writeable buffer for reading JPEG image."); - jpeg_abort_decompress( cinfo ); - return( false ); + jpeg_abort_decompress(cinfo); + return false; } - jpeg_start_decompress( cinfo ); + jpeg_start_decompress(cinfo); JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = width * colours; /* physical row width in buffer */ while ( cinfo->output_scanline < cinfo->output_height ) { row_pointer = &buffer[cinfo->output_scanline * row_stride]; - jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + jpeg_read_scanlines(cinfo, &row_pointer, 1); } - jpeg_finish_decompress( cinfo ); + jpeg_finish_decompress(cinfo); return true; } -bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override ) const { - if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { - Image temp_image( *this ); - temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); - return( temp_image.EncodeJpeg( outbuffer, outbuffer_size, quality_override ) ); +bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_override) const { + if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) { + Image temp_image(*this); + temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB); + return temp_image.EncodeJpeg(outbuffer, outbuffer_size, quality_override); } int quality = quality_override?quality_override:config.jpeg_stream_quality; @@ -1276,56 +1266,51 @@ bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_over if ( !cinfo ) { cinfo = encodejpg_ccinfo[quality] = new jpeg_compress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); + cinfo->err = jpeg_std_error(&jpg_err.pub); jpg_err.pub.error_exit = zm_jpeg_error_exit; jpg_err.pub.emit_message = zm_jpeg_emit_message; - jpeg_create_compress( cinfo ); + jpeg_create_compress(cinfo); } - zm_jpeg_mem_dest( cinfo, outbuffer, outbuffer_size ); + zm_jpeg_mem_dest(cinfo, outbuffer, outbuffer_size); cinfo->image_width = width; /* image width and height, in pixels */ cinfo->image_height = height; - switch(colours) { + switch (colours) { case ZM_COLOUR_GRAY8: - { cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; break; - } case ZM_COLOUR_RGB32: - { #ifdef JCS_EXTENSIONS cinfo->input_components = 4; - if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { cinfo->in_color_space = JCS_EXT_BGRX; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + } else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) { cinfo->in_color_space = JCS_EXT_XRGB; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + } else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) { cinfo->in_color_space = JCS_EXT_XBGR; } else { /* Assume RGBA */ cinfo->in_color_space = JCS_EXT_RGBX; - } + } + break; #else Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); - jpeg_abort_compress( cinfo ); - return(false); + jpeg_abort_compress(cinfo); + return false; #endif - break; - } case ZM_COLOUR_RGB24: default: - { cinfo->input_components = 3; - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS + if ( subpixelorder == ZM_SUBPIX_ORDER_BGR ) { +#ifdef JCS_EXTENSIONS cinfo->in_color_space = JCS_EXT_BGR; #else Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); - jpeg_abort_compress( cinfo ); - return(false); + jpeg_abort_compress(cinfo); + return false; #endif } else { /* Assume RGB */ @@ -1339,23 +1324,22 @@ cinfo->out_color_space = JCS_RGB; cinfo->in_color_space = JCS_RGB; } break; - } } // end switch - jpeg_set_defaults( cinfo ); - jpeg_set_quality( cinfo, quality, FALSE ); + jpeg_set_defaults(cinfo); + jpeg_set_quality(cinfo, quality, FALSE); cinfo->dct_method = JDCT_FASTEST; - jpeg_start_compress( cinfo, TRUE ); + jpeg_start_compress(cinfo, TRUE); JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) { row_pointer = &buffer[cinfo->next_scanline * row_stride]; - jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + jpeg_write_scanlines(cinfo, &row_pointer, 1); } - jpeg_finish_compress( cinfo ); + jpeg_finish_compress(cinfo); return true; } @@ -1470,7 +1454,7 @@ void Image::Overlay( const Image &image ) { Colourise(image.colours, image.subpixelorder); const Rgb* const max_ptr = (Rgb*)(buffer+size); - const Rgb* prsrc = (Rgb*)image.buffer; + const Rgb* prsrc = (Rgb*)image.buffer; Rgb* prdest = (Rgb*)buffer; if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { @@ -1521,7 +1505,7 @@ void Image::Overlay( const Image &image ) { } pdest += 3; psrc += 3; - } + } /* RGB32 ontop of RGB24 - TO BE DONE */ } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB32 ) { @@ -1561,7 +1545,7 @@ void Image::Overlay( const Image &image ) { } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB32 ) { const Rgb* const max_ptr = (Rgb*)(buffer+size); Rgb* prdest = (Rgb*)buffer; - const Rgb* prsrc = (Rgb*)image.buffer; + const Rgb* prsrc = (Rgb*)image.buffer; if ( image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ @@ -2035,7 +2019,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int } } } - } + } } else { Panic("Annotate called with unexpected colours: %d",colours); @@ -2088,7 +2072,7 @@ void Image::Colourise(const unsigned int p_reqcolours, const unsigned int p_reqs newpixel = (newpixel<<8) | subpixel; newpixel = (newpixel<<8) | subpixel; pdest[i] = (newpixel<<8); - } + } } else { /* RGBA\BGRA subpixel order, alpha byte is last (mem+3) */ for ( unsigned int i=0; i < pixels; i++ ) { @@ -2128,7 +2112,7 @@ void Image::DeColourise() { size = width * height; if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sseversion >= 35 ) { - /* Use SSSE3 functions */ + /* Use SSSE3 functions */ switch (subpixelorder) { case ZM_SUBPIX_ORDER_BGRA: ssse3_convert_bgra_gray8(buffer,buffer,pixels); @@ -2241,7 +2225,7 @@ void Image::Fill( Rgb colour, const Box *limits ) { Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) { - /* Fast, copies the entire pixel in a single pass */ + /* Fast, copies the entire pixel in a single pass */ *p = colour; } } @@ -2294,7 +2278,7 @@ void Image::Fill( Rgb colour, int density, const Box *limits ) { *p = colour; } } - } + } } /* RGB32 compatible: complete */ @@ -2469,7 +2453,7 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) { } else if ( colours == ZM_COLOUR_RGB24 ) { unsigned char *p = &buffer[colours*((y*width)+lo_x)]; for ( int x = lo_x; x <= hi_x; x++, p += 3) { - if ( !(x%density) ) { + if ( !(x%density) ) { RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); @@ -2675,7 +2659,7 @@ void Image::Flip( bool leftright ) { } s_ptr += line_bytes2; } - } + } } else { // Vertical flip, top to bottom unsigned char *s_ptr = buffer+(height*line_bytes); @@ -2883,7 +2867,7 @@ void Image::Deinterlace_Linear() { for (unsigned int x = 0; x < (unsigned int)width; x++) { *pcurrent++ = *pabove++; *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; *pcurrent++ = *pabove++; } } else { @@ -3068,7 +3052,7 @@ void Image::Deinterlace_4Field(const Image* next_image, unsigned int threshold) __attribute__((noinline,__target__("sse2"))) #endif void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) static uint32_t divider = 0; static uint32_t clearmask = 0; static double current_blendpercent = 0.0; @@ -3361,14 +3345,14 @@ __attribute__((noinline)) void std_blend(const uint8_t* col1, const uint8_t* col while ( result < max_ptr ) { *result++ = (*col1++ * opacity) + (*col2++ * divide); - } + } } /************************************************* DELTA FUNCTIONS *************************************************/ /* Grayscale */ __attribute__((noinline)) void fast_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (16 grayscale pixels) at a time */ + /* Loop unrolling is used to work on 16 bytes (16 grayscale pixels) at a time */ const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3392,7 +3376,7 @@ __attribute__((noinline)) void fast_delta8_gray8(const uint8_t* col1, const uint col1 += 16; col2 += 16; result += 16; - } + } } __attribute__((noinline)) void std_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { @@ -3404,13 +3388,13 @@ __attribute__((noinline)) void std_delta8_gray8(const uint8_t* col1, const uint8 col1 += 1; col2 += 1; result += 1; - } + } } /* RGB24: RGB */ __attribute__((noinline)) void fast_delta8_rgb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3439,7 +3423,7 @@ __attribute__((noinline)) void fast_delta8_rgb(const uint8_t* col1, const uint8_ __attribute__((noinline)) void std_delta8_rgb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while (result < max_ptr) { @@ -3457,7 +3441,7 @@ __attribute__((noinline)) void std_delta8_rgb(const uint8_t* col1, const uint8_t /* RGB24: BGR */ __attribute__((noinline)) void fast_delta8_bgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3486,7 +3470,7 @@ __attribute__((noinline)) void fast_delta8_bgr(const uint8_t* col1, const uint8_ __attribute__((noinline)) void std_delta8_bgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3504,7 +3488,7 @@ __attribute__((noinline)) void std_delta8_bgr(const uint8_t* col1, const uint8_t /* RGB32: RGBA */ __attribute__((noinline)) void fast_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3533,7 +3517,7 @@ __attribute__((noinline)) void fast_delta8_rgba(const uint8_t* col1, const uint8 __attribute__((noinline)) void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3551,7 +3535,7 @@ __attribute__((noinline)) void std_delta8_rgba(const uint8_t* col1, const uint8_ /* RGB32: BGRA */ __attribute__((noinline)) void fast_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3579,7 +3563,7 @@ __attribute__((noinline)) void fast_delta8_bgra(const uint8_t* col1, const uint8 } __attribute__((noinline)) void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3597,7 +3581,7 @@ __attribute__((noinline)) void std_delta8_bgra(const uint8_t* col1, const uint8_ /* RGB32: ARGB */ __attribute__((noinline)) void fast_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3625,7 +3609,7 @@ __attribute__((noinline)) void fast_delta8_argb(const uint8_t* col1, const uint8 } __attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3643,7 +3627,7 @@ __attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_ /* RGB32: ABGR */ __attribute__((noinline)) void fast_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3670,7 +3654,7 @@ __attribute__((noinline)) void fast_delta8_abgr(const uint8_t* col1, const uint8 } } __attribute__((noinline)) void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - int r,g,b; + int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -3919,7 +3903,7 @@ void neon64_armv8_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* __attribute__((noinline,__target__("sse2"))) #endif void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) __asm__ __volatile__ ( "sub $0x10, %0\n\t" @@ -3950,7 +3934,7 @@ void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result __attribute__((noinline,__target__("sse2"))) #endif void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) __asm__ __volatile__ ( "mov $0x1F1F1F1F, %%eax\n\t" @@ -4008,7 +3992,7 @@ void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, __attribute__((noinline,__target__("sse2"))) #endif void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) __asm__ __volatile__ ( "mov $0x1F1F1F1F, %%eax\n\t" @@ -4066,7 +4050,7 @@ void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, __attribute__((noinline,__target__("sse2"))) #endif void sse2_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) __asm__ __volatile__ ( "mov $0x1F1F1F1F, %%eax\n\t" @@ -4125,7 +4109,7 @@ void sse2_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, __attribute__((noinline,__target__("sse2"))) #endif void sse2_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) __asm__ __volatile__ ( "mov $0x1F1F1F1F, %%eax\n\t" @@ -4184,7 +4168,7 @@ void sse2_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_delta8_rgb32(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, uint32_t multiplier) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) /* XMM0 - zero */ /* XMM1 - col1 */ @@ -4253,7 +4237,7 @@ void ssse3_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result /* RGB24 to grayscale */ __attribute__((noinline)) void fast_convert_rgb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4279,7 +4263,7 @@ __attribute__((noinline)) void fast_convert_rgb_gray8(const uint8_t* col1, uint8 } } __attribute__((noinline)) void std_convert_rgb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4295,7 +4279,7 @@ __attribute__((noinline)) void std_convert_rgb_gray8(const uint8_t* col1, uint8_ /* BGR24 to grayscale */ __attribute__((noinline)) void fast_convert_bgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4321,7 +4305,7 @@ __attribute__((noinline)) void fast_convert_bgr_gray8(const uint8_t* col1, uint8 } } __attribute__((noinline)) void std_convert_bgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4337,7 +4321,7 @@ __attribute__((noinline)) void std_convert_bgr_gray8(const uint8_t* col1, uint8_ /* RGBA to grayscale */ __attribute__((noinline)) void fast_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4363,7 +4347,7 @@ __attribute__((noinline)) void fast_convert_rgba_gray8(const uint8_t* col1, uint } } __attribute__((noinline)) void std_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4379,7 +4363,7 @@ __attribute__((noinline)) void std_convert_rgba_gray8(const uint8_t* col1, uint8 /* BGRA to grayscale */ __attribute__((noinline)) void fast_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4406,7 +4390,7 @@ __attribute__((noinline)) void fast_convert_bgra_gray8(const uint8_t* col1, uint } __attribute__((noinline)) void std_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4421,7 +4405,7 @@ __attribute__((noinline)) void std_convert_bgra_gray8(const uint8_t* col1, uint8 } /* ARGB to grayscale */ __attribute__((noinline)) void fast_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4447,7 +4431,7 @@ __attribute__((noinline)) void fast_convert_argb_gray8(const uint8_t* col1, uint } } __attribute__((noinline)) void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4463,7 +4447,7 @@ __attribute__((noinline)) void std_convert_argb_gray8(const uint8_t* col1, uint8 /* ABGR to grayscale */ __attribute__((noinline)) void fast_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4489,7 +4473,7 @@ __attribute__((noinline)) void fast_convert_abgr_gray8(const uint8_t* col1, uint } } __attribute__((noinline)) void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; + unsigned int r,g,b; const uint8_t* const max_ptr = result + count; while(result < max_ptr) { @@ -4547,7 +4531,7 @@ __attribute__((noinline)) void std_convert_yuyv_gray8(const uint8_t* col1, uint8 __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_convert_rgb32_gray8(const uint8_t* col1, uint8_t* result, unsigned long count, uint32_t multiplier) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) /* XMM0 - zero */ /* XMM1 - col1 */ @@ -4609,7 +4593,7 @@ void ssse3_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned lon __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { -#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) unsigned long i = 0; __attribute__((aligned(16))) static const uint8_t movemask1[16] = {0,2,4,6,8,10,12,14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; @@ -4712,8 +4696,8 @@ __attribute__((noinline)) void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t /* RGB555 to RGB24 - relocated from zm_local_camera.cpp */ __attribute__((noinline)) void zm_convert_rgb555_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { b = ((*col1)<<3)&0xf8; g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; r = ((*(col1+1))<<1)&0xf8; @@ -4725,8 +4709,8 @@ __attribute__((noinline)) void zm_convert_rgb555_rgb(const uint8_t* col1, uint8_ /* RGB555 to RGBA - modified the one above */ __attribute__((noinline)) void zm_convert_rgb555_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { b = ((*col1)<<3)&0xf8; g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; r = ((*(col1+1))<<1)&0xf8; @@ -4738,8 +4722,8 @@ __attribute__((noinline)) void zm_convert_rgb555_rgba(const uint8_t* col1, uint8 /* RGB565 to RGB24 - relocated from zm_local_camera.cpp */ __attribute__((noinline)) void zm_convert_rgb565_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { b = ((*col1)<<3)&0xf8; g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; r = (*(col1+1))&0xf8; @@ -4751,8 +4735,8 @@ __attribute__((noinline)) void zm_convert_rgb565_rgb(const uint8_t* col1, uint8_ /* RGB565 to RGBA - modified the one above */ __attribute__((noinline)) void zm_convert_rgb565_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + unsigned int r,g,b; + for ( unsigned int i=0; i < count; i++, col1 += 2, result += 4 ) { b = ((*col1)<<3)&0xf8; g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; r = (*(col1+1))&0xf8; diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 2089fecc3..1b8afc517 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -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() { diff --git a/src/zm_logger.h b/src/zm_logger.h index f65c5ec31..82144a1c9 100644 --- a/src/zm_logger.h +++ b/src/zm_logger.h @@ -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; } diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp index 49b4d5ffc..d4bb48b73 100644 --- a/src/zm_utils.cpp +++ b/src/zm_utils.cpp @@ -22,6 +22,7 @@ #include "zm_utils.h" #include +#include #include #include #include /* 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, diff --git a/src/zm_utils.h b/src/zm_utils.h index d1340cf4b..9a8dd1948 100644 --- a/src/zm_utils.h +++ b/src/zm_utils.h @@ -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& items); int pairsplit(const char* string, const char delim, std::string& name, std::string& value); diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 647920789..c3e19a193 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -20,13 +20,14 @@ #define __STDC_FORMAT_MACROS 1 -#include -#include -#include #include "zm.h" #include "zm_videostore.h" +#include +#include +#include + 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(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(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) diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 2940bc2e7..f8a2f2a97 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -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: diff --git a/src/zmc.cpp b/src/zmc.cpp index bebc0bc7d..65a8d3e12 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -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(); diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index fd84a3923..ea1aa0e8b 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -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 diff --git a/web/includes/Event.php b/web/includes/Event.php index e8b6d15be..02ebf50c0 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -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 diff --git a/web/includes/Server.php b/web/includes/Server.php index 535ea44ed..2f9d038a9 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -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 ) { diff --git a/web/includes/actions/events.php b/web/includes/actions/events.php index 08782a8a2..abea69b60 100644 --- a/web/includes/actions/events.php +++ b/web/includes/actions/events.php @@ -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; } ?> diff --git a/web/includes/actions/user.php b/web/includes/actions/user.php index a786f78d7..bdbafd176 100644 --- a/web/includes/actions/user.php +++ b/web/includes/actions/user.php @@ -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'; } diff --git a/web/includes/database.php b/web/includes/database.php index d941a01e0..5ec54f163 100644 --- a/web/includes/database.php +++ b/web/includes/database.php @@ -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; diff --git a/web/includes/functions.php b/web/includes/functions.php index ff578eff7..7f5e32aaa 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -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 ' '; } - } case 'video/quicktime' : - { return ' '; - } case 'application/x-shockwave-flash' : - { return ' '; - } } # end switch } # end if use object tags return '
- - - + + + - + - + - + - +
- - - + + + - + - + - + - - + +
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 ) { diff --git a/web/includes/session.php b/web/includes/session.php index 8d4c28a68..dec414fec 100644 --- a/web/includes/session.php +++ b/web/includes/session.php @@ -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(); diff --git a/web/index.php b/web/index.php index f2fd0660e..5c2448291 100644 --- a/web/index.php +++ b/web/index.php @@ -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); diff --git a/web/skins/classic/views/image-ffmpeg.php b/web/skins/classic/views/image-ffmpeg.php deleted file mode 100644 index 496b4c695..000000000 --- a/web/skins/classic/views/image-ffmpeg.php +++ /dev/null @@ -1,76 +0,0 @@ -$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); -?> diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index 1599e0dd7..e217bcc89 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -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++ ) { diff --git a/web/skins/classic/views/js/onvifprobe.js b/web/skins/classic/views/js/onvifprobe.js index b49ac5754..cfe0939d0 100644 --- a/web/skins/classic/views/js/onvifprobe.js +++ b/web/skins/classic/views/js/onvifprobe.js @@ -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); } } diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index d8bd27ae6..fee8a84be 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -180,11 +180,11 @@ if ( $showZones ) { 'selectLayout(this);')); ?> - + diff --git a/web/skins/classic/views/onvifprobe.php b/web/skins/classic/views/onvifprobe.php index e1c4c8ef7..8c5feb50b 100644 --- a/web/skins/classic/views/onvifprobe.php +++ b/web/skins/classic/views/onvifprobe.php @@ -41,18 +41,18 @@ function execONVIF( $cmd ) { Please the following command from a command line for more information:

$shell_command" ); } else { - ZM\Logger::Debug( "Results from probe: " . implode( '
', $output ) ); + ZM\Logger::Debug('Results from probe: '.implode('
', $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])."
"; $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') ) {

- 'configureButtons(this)')); ?> + 'configureButtons')); ?>

- - + +

- - + +

- - + +
- $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']."
"; - $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') ) {

- 'configureButtons(this)')); ?> + 'configureButtons')); ?>

- - - + + +
- + diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index ea400339a..102ba2af3 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -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 ""; -} # end if tab == skins - ?> @@ -104,12 +79,14 @@ if ( $tab == 'skins' ) {
- +
- '.$dir.''; + echo ''; } ?> @@ -117,12 +94,12 @@ foreach ( $skin_options as $dir ) {
- +
- '.$dir.''; +foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $dir ) { + echo ''; } ?> @@ -325,40 +302,37 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI ?>
-
- + + +
".translate('AllTokensRevoked').""; + dbQuery('UPDATE `Users` SET `TokenMinExpiry`=?', array($minTokenTime)); + echo ''.translate('AllTokensRevoked').''; } - 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 "".translate('Updated').""; + echo ''.translate('Updated').''; } - 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(); } ?> - -

@@ -375,7 +349,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI @@ -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 ?>
- +