Merge branch 'storageareas' of github.com:connortechnology/ZoneMinder into storageareas
This commit is contained in:
commit
d5962b11ff
|
@ -27,9 +27,7 @@ override_dh_auto_configure:
|
||||||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
||||||
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
||||||
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
|
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
|
||||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
|
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
|
||||||
-DZM_NO_CURL=1 \
|
|
||||||
-DZM_NO_LIBVLC=1
|
|
||||||
|
|
||||||
override_dh_clean:
|
override_dh_clean:
|
||||||
dh_clean $(MANPAGES1)
|
dh_clean $(MANPAGES1)
|
||||||
|
|
|
@ -4,5 +4,6 @@ var/cache/zoneminder/events
|
||||||
var/cache/zoneminder/images
|
var/cache/zoneminder/images
|
||||||
var/cache/zoneminder/temp
|
var/cache/zoneminder/temp
|
||||||
usr/share/zoneminder/db
|
usr/share/zoneminder/db
|
||||||
|
usr/share/zoneminder/www/cache
|
||||||
etc/zm/
|
etc/zm/
|
||||||
etc/zm/conf.d
|
etc/zm/conf.d
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
d /var/run/zm 0755 www-data www-data
|
d /var/run/zm 0755 www-data www-data
|
||||||
d /tmp/zm 0755 www-data www-data
|
d /tmp/zm 0755 www-data www-data
|
||||||
d /var/tmp/zm 0755 www-data www-data
|
d /var/tmp/zm 0755 www-data www-data
|
||||||
|
d /usr/share/zoneminder/www/cache 0755 www-data www-data
|
||||||
|
|
|
@ -115,7 +115,7 @@ BEGIN {
|
||||||
, $Config{ZM_DB_USER}
|
, $Config{ZM_DB_USER}
|
||||||
, $Config{ZM_DB_PASS}
|
, $Config{ZM_DB_PASS}
|
||||||
) or croak( "Can't connect to db" );
|
) or croak( "Can't connect to db" );
|
||||||
my $sql = 'select * from Config';
|
my $sql = 'SELECT Name,Value FROM Config';
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() );
|
my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() );
|
my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() );
|
||||||
while( my $config = $sth->fetchrow_hashref() ) {
|
while( my $config = $sth->fetchrow_hashref() ) {
|
||||||
|
|
|
@ -48,9 +48,38 @@ use ZoneMinder::Logger qw(:all);
|
||||||
use ZoneMinder::Database qw(:all);
|
use ZoneMinder::Database qw(:all);
|
||||||
require Date::Parse;
|
require Date::Parse;
|
||||||
|
|
||||||
use vars qw/ $table $primary_key /;
|
use vars qw/ $table $primary_key %fields $serial @identified_by/;
|
||||||
$table = 'Events';
|
$table = 'Events';
|
||||||
$primary_key = 'Id';
|
@identified_by = ('Id');
|
||||||
|
$serial = $primary_key = 'Id';
|
||||||
|
%fields = map { $_, $_ } qw(
|
||||||
|
Id
|
||||||
|
MonitorId
|
||||||
|
StorageId
|
||||||
|
Name
|
||||||
|
Cause
|
||||||
|
StartTime
|
||||||
|
EndTime
|
||||||
|
Width
|
||||||
|
Height
|
||||||
|
Length
|
||||||
|
Frames
|
||||||
|
AlarmFrames
|
||||||
|
DefaultVideo
|
||||||
|
TotScore
|
||||||
|
AvgScore
|
||||||
|
MaxScore
|
||||||
|
Archived
|
||||||
|
Videoed
|
||||||
|
Uploaded
|
||||||
|
Emailed
|
||||||
|
Messaged
|
||||||
|
Executed
|
||||||
|
Notes
|
||||||
|
StateId
|
||||||
|
Orientation
|
||||||
|
DiskSpace
|
||||||
|
);
|
||||||
|
|
||||||
use POSIX;
|
use POSIX;
|
||||||
|
|
||||||
|
|
|
@ -224,7 +224,7 @@ sub Sql {
|
||||||
|| $term->{attr} eq 'Notes'
|
|| $term->{attr} eq 'Notes'
|
||||||
) {
|
) {
|
||||||
$value = "'$temp_value'";
|
$value = "'$temp_value'";
|
||||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
|
||||||
$value = DateTimeToSQL( $temp_value );
|
$value = DateTimeToSQL( $temp_value );
|
||||||
if ( !$value ) {
|
if ( !$value ) {
|
||||||
Error( "Error parsing date/time '$temp_value', "
|
Error( "Error parsing date/time '$temp_value', "
|
||||||
|
@ -232,7 +232,7 @@ sub Sql {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$value = "'$value'";
|
$value = "'$value'";
|
||||||
} elsif ( $term->{attr} eq 'Date' ) {
|
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||||
$value = DateTimeToSQL( $temp_value );
|
$value = DateTimeToSQL( $temp_value );
|
||||||
if ( !$value ) {
|
if ( !$value ) {
|
||||||
Error( "Error parsing date/time '$temp_value', "
|
Error( "Error parsing date/time '$temp_value', "
|
||||||
|
@ -240,7 +240,7 @@ sub Sql {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$value = "to_days( '$value' )";
|
$value = "to_days( '$value' )";
|
||||||
} elsif ( $term->{attr} eq 'Time' ) {
|
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
|
||||||
$value = DateTimeToSQL( $temp_value );
|
$value = DateTimeToSQL( $temp_value );
|
||||||
if ( !$value ) {
|
if ( !$value ) {
|
||||||
Error( "Error parsing date/time '$temp_value', "
|
Error( "Error parsing date/time '$temp_value', "
|
||||||
|
|
|
@ -678,7 +678,10 @@ sub Dump {
|
||||||
fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) );
|
fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub debug { $_[0]->logPrint( DEBUG, @_ ); }
|
sub debug {
|
||||||
|
my $log = shift;
|
||||||
|
$log->logPrint( DEBUG, @_ );
|
||||||
|
}
|
||||||
|
|
||||||
sub Debug( @ ) {
|
sub Debug( @ ) {
|
||||||
fetch()->logPrint( DEBUG, @_ );
|
fetch()->logPrint( DEBUG, @_ );
|
||||||
|
@ -688,7 +691,8 @@ sub Info( @ ) {
|
||||||
fetch()->logPrint( INFO, @_ );
|
fetch()->logPrint( INFO, @_ );
|
||||||
}
|
}
|
||||||
sub info {
|
sub info {
|
||||||
$_[0]->logPrint( INFO, @_ );
|
my $log = shift;
|
||||||
|
$log->logPrint( INFO, @_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -696,14 +700,16 @@ sub Warning( @ ) {
|
||||||
fetch()->logPrint( WARNING, @_ );
|
fetch()->logPrint( WARNING, @_ );
|
||||||
}
|
}
|
||||||
sub warn {
|
sub warn {
|
||||||
$_[0]->logPrint( WARNING, @_ );
|
my $log = shift;
|
||||||
|
$log->logPrint( WARNING, @_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub Error( @ ) {
|
sub Error( @ ) {
|
||||||
fetch()->logPrint( ERROR, @_ );
|
fetch()->logPrint( ERROR, @_ );
|
||||||
}
|
}
|
||||||
sub error {
|
sub error {
|
||||||
$_[0]->logPrint( ERROR, @_ );
|
my $log = shift;
|
||||||
|
$log->logPrint( ERROR, @_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub Fatal( @ ) {
|
sub Fatal( @ ) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ use vars qw/ $AUTOLOAD $log $dbh/;
|
||||||
*dbh = \$ZoneMinder::Database::dbh;
|
*dbh = \$ZoneMinder::Database::dbh;
|
||||||
|
|
||||||
my $debug = 1;
|
my $debug = 1;
|
||||||
use constant DEBUG_ALL=>0;
|
use constant DEBUG_ALL=>1;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my ( $parent, $id, $data ) = @_;
|
my ( $parent, $id, $data ) = @_;
|
||||||
|
@ -185,8 +185,11 @@ $log->debug("No serial") if $debug;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ( ! $$self{$id} ) {
|
if ( ! $$self{$id} ) {
|
||||||
($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial{$id} . q{')} );
|
my $s = qq{SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$table'};
|
||||||
$log->debug("SQL statement execution SELECT nextval('$serial{$id}') returned $$self{$id}") if $debug or DEBUG_ALL;
|
|
||||||
|
($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( $s );
|
||||||
|
#($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial{$id} . q{')} );
|
||||||
|
$log->debug("SQL statement execution SELECT $s returned $$self{$id}") if $debug or DEBUG_ALL;
|
||||||
$insert = 1;
|
$insert = 1;
|
||||||
} # end if
|
} # end if
|
||||||
} # end foreach
|
} # end foreach
|
||||||
|
@ -224,22 +227,28 @@ $log->debug("No serial") if $debug;
|
||||||
} # end if
|
} # end if
|
||||||
} # end if
|
} # end if
|
||||||
} else { # not identified_by
|
} else { # not identified_by
|
||||||
@identified_by = ('id') if ! @identified_by;
|
@identified_by = ('Id') if ! @identified_by;
|
||||||
my $need_serial = ! ( @identified_by == map { $$self{$_} ? $_ : () } @identified_by );
|
|
||||||
|
# If the size of the arrays are not equal which means one or more are missing
|
||||||
|
my @identified_by_without_values = map { $$self{$_} ? () : $_ } @identified_by;
|
||||||
|
my $need_serial = @identified_by_without_values > 0;
|
||||||
|
|
||||||
if ( $force_insert or $need_serial ) {
|
if ( $force_insert or $need_serial ) {
|
||||||
|
|
||||||
if ( $need_serial ) {
|
if ( $need_serial ) {
|
||||||
if ( $serial ) {
|
if ( $serial ) {
|
||||||
@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial . q{')} );
|
my $s = qq{SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$table'};
|
||||||
|
@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( $s );
|
||||||
|
#@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial . q{')} );
|
||||||
if ( $local_dbh->errstr() ) {
|
if ( $local_dbh->errstr() ) {
|
||||||
$log->error("Error getting next id. " . $local_dbh->errstr() );
|
$log->error("Error getting next id. " . $local_dbh->errstr() );
|
||||||
$log->error("SQL statement execution SELECT nextval('$serial') returned ".join(',',@$self{@identified_by}));
|
$log->error("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
|
||||||
} elsif ( $debug or DEBUG_ALL ) {
|
} elsif ( $debug or DEBUG_ALL ) {
|
||||||
$log->debug("SQL statement execution SELECT nextval('$serial') returned ".join(',',@$self{@identified_by}));
|
$log->debug("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
|
||||||
} # end if
|
} # end if
|
||||||
} # end if
|
} # end if
|
||||||
} # end if
|
} # end if
|
||||||
|
|
||||||
my @keys = keys %sql;
|
my @keys = keys %sql;
|
||||||
my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')';
|
my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')';
|
||||||
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys} ) ) ) {
|
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys} ) ) ) {
|
||||||
|
@ -257,7 +266,9 @@ $log->debug("No serial") if $debug;
|
||||||
} else {
|
} else {
|
||||||
delete $sql{created_on};
|
delete $sql{created_on};
|
||||||
my @keys = keys %sql;
|
my @keys = keys %sql;
|
||||||
@keys = sets::exclude( [ @$fields{@identified_by} ], \@keys );
|
my %identified_by = map { $_, $_ } @identified_by;
|
||||||
|
|
||||||
|
@keys = map { $identified_by{$_} ? () : $$fields{$_} } @keys;
|
||||||
my $command = "UPDATE $table SET " . join(',', map { $_ . ' = ?' } @keys ) . ' WHERE ' . join(' AND ', map { $$fields{$_} .'= ?' } @identified_by );
|
my $command = "UPDATE $table SET " . join(',', map { $_ . ' = ?' } @keys ) . ' WHERE ' . join(' AND ', map { $$fields{$_} .'= ?' } @identified_by );
|
||||||
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys}, @sql{@$fields{@identified_by}} ) ) ) {
|
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys}, @sql{@$fields{@identified_by}} ) ) ) {
|
||||||
my $error = $local_dbh->errstr;
|
my $error = $local_dbh->errstr;
|
||||||
|
@ -294,30 +305,32 @@ sub set {
|
||||||
my $type = ref $self;
|
my $type = ref $self;
|
||||||
my %fields = eval ('%'.$type.'::fields');
|
my %fields = eval ('%'.$type.'::fields');
|
||||||
if ( ! %fields ) {
|
if ( ! %fields ) {
|
||||||
$log->warn('ZoneMinder::Object::set called on an object with no fields');
|
$log->warn("ZoneMinder::Object::set called on an object ($type) with no fields".$@);
|
||||||
} # end if
|
} # end if
|
||||||
my %defaults = eval('%'.$type.'::defaults');
|
my %defaults = eval('%'.$type.'::defaults');
|
||||||
if ( ref $params ne 'HASH' ) {
|
if ( ref $params ne 'HASH' ) {
|
||||||
my ( $caller, undef, $line ) = caller;
|
my ( $caller, undef, $line ) = caller;
|
||||||
$openprint::log->error("$type -> set called with non-hash params from $caller $line");
|
$log->error("$type -> set called with non-hash params from $caller $line");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $field ( keys %fields ) {
|
foreach my $field ( keys %fields ) {
|
||||||
$log->debug("field: $field, param: ".$$params{$field}) if $debug;
|
if ( $params ) {
|
||||||
if ( exists $$params{$field} ) {
|
$log->debug("field: $field, param: ".$$params{$field}) if $debug;
|
||||||
$openprint::log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug;
|
if ( exists $$params{$field} ) {
|
||||||
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
|
$log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug;
|
||||||
|
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
|
||||||
# Only make changes to fields that have changed
|
# Only make changes to fields that have changed
|
||||||
if ( defined $fields{$field} ) {
|
if ( defined $fields{$field} ) {
|
||||||
$$self{$field} = $$params{$field} if defined $fields{$field};
|
$$self{$field} = $$params{$field} if defined $fields{$field};
|
||||||
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
|
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
|
||||||
} # end if
|
} # end if
|
||||||
$openprint::log->debug("Running $field with $$params{$field}") if $debug;
|
$log->debug("Running $field with $$params{$field}") if $debug;
|
||||||
if ( my $func = $self->can( $field ) ) {
|
if ( my $func = $self->can( $field ) ) {
|
||||||
$func->( $self, $$params{$field} );
|
$func->( $self, $$params{$field} );
|
||||||
} # end if
|
} # end if
|
||||||
} # end if
|
} # end if
|
||||||
} # end if
|
} # end if
|
||||||
|
} # end if $params
|
||||||
|
|
||||||
if ( defined $fields{$field} ) {
|
if ( defined $fields{$field} ) {
|
||||||
if ( $$self{$field} ) {
|
if ( $$self{$field} ) {
|
||||||
|
@ -356,7 +369,7 @@ sub transform {
|
||||||
|
|
||||||
if ( defined $$fields{$_[1]} ) {
|
if ( defined $$fields{$_[1]} ) {
|
||||||
my @transforms = eval('@{$'.$type.'::transforms{$_[1]}}');
|
my @transforms = eval('@{$'.$type.'::transforms{$_[1]}}');
|
||||||
$openprint::log->debug("Transforms for $_[1] before $_[2]: @transforms") if $debug;
|
$log->debug("Transforms for $_[1] before $_[2]: @transforms") if $debug;
|
||||||
if ( @transforms ) {
|
if ( @transforms ) {
|
||||||
foreach my $transform ( @transforms ) {
|
foreach my $transform ( @transforms ) {
|
||||||
if ( $transform =~ /^s\// or $transform =~ /^tr\// ) {
|
if ( $transform =~ /^s\// or $transform =~ /^tr\// ) {
|
||||||
|
@ -366,15 +379,15 @@ sub transform {
|
||||||
$value = undef;
|
$value = undef;
|
||||||
} # end if
|
} # end if
|
||||||
} else {
|
} else {
|
||||||
$openprint::log->debug("evalling $value ".$transform . " Now value is $value" );
|
$log->debug("evalling $value ".$transform . " Now value is $value" );
|
||||||
eval '$value '.$transform;
|
eval '$value '.$transform;
|
||||||
$openprint::log->error("Eval error $@") if $@;
|
$log->error("Eval error $@") if $@;
|
||||||
}
|
}
|
||||||
$openprint::log->debug("After $transform: $value") if $debug;
|
$log->debug("After $transform: $value") if $debug;
|
||||||
} # end foreach
|
} # end foreach
|
||||||
} # end if
|
} # end if
|
||||||
} else {
|
} else {
|
||||||
$openprint::log->error("Object::transform ($_[1]) not in fields for $type");
|
$log->error("Object::transform ($_[1]) not in fields for $type");
|
||||||
} # end if
|
} # end if
|
||||||
return $value;
|
return $value;
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", staticConfig.PATH_SWAP.c_str(), monitor->Id(), connkey );
|
|
||||||
|
|
||||||
int len = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id());
|
|
||||||
|
|
||||||
|
|
||||||
int swap_path_length = strlen(staticConfig.PATH_SWAP.c_str()) + snprintf(NULL, 0, "/zmswap-m%d", monitor->Id() ) + snprintf(NULL, 0, "/zmswap-q%06d", connkey ) + 1; // +1 for NULL terminator
|
|
||||||
|
|
||||||
if ( connkey && playback_buffer > 0 ) {
|
|
||||||
|
|
||||||
if ( swap_path_length + max_swap_len_suffix > PATH_MAX ) {
|
|
||||||
Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX );
|
|
||||||
} else {
|
|
||||||
swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix );
|
|
||||||
Debug( 3, "Checking swap image path %s", staticConfig.PATH_SWAP.c_str() );
|
|
||||||
strncpy( swap_path, staticConfig.PATH_SWAP.c_str(), swap_path_length );
|
|
||||||
if ( checkSwapPath( swap_path, false ) ) {
|
|
||||||
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() );
|
|
||||||
if ( checkSwapPath( swap_path, true ) ) {
|
|
||||||
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-q%06d", connkey );
|
|
||||||
if ( checkSwapPath( swap_path, true ) ) {
|
|
||||||
buffered_playback = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -215,6 +215,18 @@ ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *con
|
||||||
|
|
||||||
accessed = false;
|
accessed = false;
|
||||||
}
|
}
|
||||||
|
ConfigItem::ConfigItem( const ConfigItem &item ) {
|
||||||
|
name = new char[strlen(item.name)+1];
|
||||||
|
strcpy( name, item.name );
|
||||||
|
value = new char[strlen(item.value)+1];
|
||||||
|
strcpy( value, item.value );
|
||||||
|
type = new char[strlen(item.type)+1];
|
||||||
|
strcpy( type, item.type );
|
||||||
|
|
||||||
|
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
|
||||||
|
|
||||||
|
accessed = false;
|
||||||
|
}
|
||||||
|
|
||||||
ConfigItem::~ConfigItem() {
|
ConfigItem::~ConfigItem() {
|
||||||
delete[] name;
|
delete[] name;
|
||||||
|
|
|
@ -107,7 +107,8 @@ private:
|
||||||
mutable bool accessed;
|
mutable bool accessed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigItem( const char *p_name, const char *p_value, const char *const p_type );
|
ConfigItem(const char *p_name, const char *p_value, const char *const p_type);
|
||||||
|
ConfigItem(const ConfigItem &);
|
||||||
~ConfigItem();
|
~ConfigItem();
|
||||||
void ConvertValue() const;
|
void ConvertValue() const;
|
||||||
bool BooleanValue() const;
|
bool BooleanValue() const;
|
||||||
|
@ -116,16 +117,16 @@ public:
|
||||||
const char *StringValue() const;
|
const char *StringValue() const;
|
||||||
|
|
||||||
inline operator bool() const {
|
inline operator bool() const {
|
||||||
return( BooleanValue() );
|
return BooleanValue();
|
||||||
}
|
}
|
||||||
inline operator int() const {
|
inline operator int() const {
|
||||||
return( IntegerValue() );
|
return IntegerValue();
|
||||||
}
|
}
|
||||||
inline operator double() const {
|
inline operator double() const {
|
||||||
return( DecimalValue() );
|
return DecimalValue();
|
||||||
}
|
}
|
||||||
inline operator const char *() const {
|
inline operator const char *() const {
|
||||||
return( StringValue() );
|
return StringValue();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -128,10 +128,10 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
/* Grab the mutex to ensure exclusive access to the shared data */
|
/* Grab the mutex to ensure exclusive access to the shared data */
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
while (!frameComplete) {
|
while ( !frameComplete ) {
|
||||||
|
|
||||||
/* If the work thread did a reset, reset our local variables */
|
/* If the work thread did a reset, reset our local variables */
|
||||||
if(bReset) {
|
if ( bReset ) {
|
||||||
SubHeadersParsingComplete = false;
|
SubHeadersParsingComplete = false;
|
||||||
frame_content_length = 0;
|
frame_content_length = 0;
|
||||||
frame_content_type.clear();
|
frame_content_type.clear();
|
||||||
|
@ -139,25 +139,25 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
bReset = false;
|
bReset = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode == MODE_UNSET) {
|
if ( mode == MODE_UNSET ) {
|
||||||
/* Don't have a mode yet. Sleep while waiting for data */
|
/* Don't have a mode yet. Sleep while waiting for data */
|
||||||
nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex);
|
nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex);
|
||||||
if(nRet != 0) {
|
if ( nRet != 0 ) {
|
||||||
Error("Failed waiting for available data condition variable: %s",strerror(nRet));
|
Error("Failed waiting for available data condition variable: %s",strerror(nRet));
|
||||||
return -20;
|
return -20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode == MODE_STREAM) {
|
if ( mode == MODE_STREAM ) {
|
||||||
|
|
||||||
/* Subheader parsing */
|
/* Subheader parsing */
|
||||||
while(!SubHeadersParsingComplete && !need_more_data) {
|
while( !SubHeadersParsingComplete && !need_more_data ) {
|
||||||
|
|
||||||
size_t crlf_start, crlf_end, crlf_size;
|
size_t crlf_start, crlf_end, crlf_size;
|
||||||
std::string subheader;
|
std::string subheader;
|
||||||
|
|
||||||
/* Check if the buffer contains something */
|
/* Check if the buffer contains something */
|
||||||
if(databuffer.empty()) {
|
if ( databuffer.empty() ) {
|
||||||
/* Empty buffer, wait for data */
|
/* Empty buffer, wait for data */
|
||||||
need_more_data = true;
|
need_more_data = true;
|
||||||
break;
|
break;
|
||||||
|
@ -165,14 +165,14 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
|
|
||||||
/* Find crlf start */
|
/* Find crlf start */
|
||||||
crlf_start = memcspn(databuffer,"\r\n",databuffer.size());
|
crlf_start = memcspn(databuffer,"\r\n",databuffer.size());
|
||||||
if(crlf_start == databuffer.size()) {
|
if ( crlf_start == databuffer.size() ) {
|
||||||
/* Not found, wait for more data */
|
/* Not found, wait for more data */
|
||||||
need_more_data = true;
|
need_more_data = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if we have enough data for determining crlf length */
|
/* See if we have enough data for determining crlf length */
|
||||||
if(databuffer.size() < crlf_start+5) {
|
if ( databuffer.size() < crlf_start+5 ) {
|
||||||
/* Need more data */
|
/* Need more data */
|
||||||
need_more_data = true;
|
need_more_data = true;
|
||||||
break;
|
break;
|
||||||
|
@ -183,13 +183,13 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
crlf_size = (crlf_start + crlf_end) - crlf_start;
|
crlf_size = (crlf_start + crlf_end) - crlf_start;
|
||||||
|
|
||||||
/* Is this the end of a previous stream? (This is just before the boundary) */
|
/* Is this the end of a previous stream? (This is just before the boundary) */
|
||||||
if(crlf_start == 0) {
|
if ( crlf_start == 0 ) {
|
||||||
databuffer.consume(crlf_size);
|
databuffer.consume(crlf_size);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for invalid CRLF size */
|
/* Check for invalid CRLF size */
|
||||||
if(crlf_size > 4) {
|
if ( crlf_size > 4 ) {
|
||||||
Error("Invalid CRLF length");
|
Error("Invalid CRLF length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ int cURLCamera::Capture( Image &image ) {
|
||||||
|
|
||||||
/* Find where the data in this header starts */
|
/* Find where the data in this header starts */
|
||||||
size_t subheader_data_start = subheader.rfind(' ');
|
size_t subheader_data_start = subheader.rfind(' ');
|
||||||
if(subheader_data_start == std::string::npos) {
|
if ( subheader_data_start == std::string::npos ) {
|
||||||
subheader_data_start = subheader.find(':');
|
subheader_data_start = subheader.find(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -593,6 +593,7 @@ bool EventStream::sendFrame( int delta_us ) {
|
||||||
FILE *fdj = NULL;
|
FILE *fdj = NULL;
|
||||||
|
|
||||||
// This needs to be abstracted. If we are saving jpgs, then load the capture file. If we are only saving analysis frames, then send that.
|
// This needs to be abstracted. If we are saving jpgs, then load the capture file. If we are only saving analysis frames, then send that.
|
||||||
|
// // This is also wrong, need to have this info stored in the event! FIXME
|
||||||
if ( monitor->GetOptSaveJPEGs() & 1 ) {
|
if ( monitor->GetOptSaveJPEGs() & 1 ) {
|
||||||
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
|
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
|
||||||
} else if ( monitor->GetOptSaveJPEGs() & 2 ) {
|
} else if ( monitor->GetOptSaveJPEGs() & 2 ) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "zm_stream.h"
|
#include "zm_stream.h"
|
||||||
#include "zm_video.h"
|
#include "zm_video.h"
|
||||||
#include "zm_ffmpeg_input.h"
|
#include "zm_ffmpeg_input.h"
|
||||||
|
#include "zm_monitor.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -108,11 +109,17 @@ class EventStream : public StreamBase {
|
||||||
}
|
}
|
||||||
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
|
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
|
||||||
loadInitialEventData( init_event_id, init_frame_id );
|
loadInitialEventData( init_event_id, init_frame_id );
|
||||||
loadMonitor( event_data->monitor_id );
|
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
|
||||||
|
Fatal( "Unable to load monitor id %d for streaming", event_data->monitor_id );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void setStreamStart( int monitor_id, time_t event_time ) {
|
void setStreamStart( int monitor_id, time_t event_time ) {
|
||||||
loadInitialEventData( monitor_id, event_time );
|
loadInitialEventData( monitor_id, event_time );
|
||||||
loadMonitor( monitor_id );
|
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
|
||||||
|
Fatal( "Unable to load monitor id %d for streaming", monitor_id );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void setStreamMode( StreamMode p_mode ) {
|
void setStreamMode( StreamMode p_mode ) {
|
||||||
mode = p_mode;
|
mode = p_mode;
|
||||||
|
|
|
@ -133,6 +133,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
|
||||||
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
|
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
|
||||||
|
|
||||||
#if HAVE_LIBAVUTIL
|
#if HAVE_LIBAVUTIL
|
||||||
|
#if LIBAVUTIL_VERSION_CHECK(56, 0, 0, 17, 100)
|
||||||
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
|
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
|
||||||
int64_t a, b, this_thing;
|
int64_t a, b, this_thing;
|
||||||
|
|
||||||
|
@ -156,6 +157,7 @@ simple_round:
|
||||||
return av_rescale_q(this_thing, fs_tb, out_tb);
|
return av_rescale_q(this_thing, fs_tb, out_tb);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
|
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
|
||||||
AVFormatContext *s = avformat_alloc_context();
|
AVFormatContext *s = avformat_alloc_context();
|
||||||
|
|
|
@ -317,7 +317,7 @@ int FfmpegCamera::Capture( Image &image ) {
|
||||||
} // end if packet.stream_index == mVideoStreamId
|
} // end if packet.stream_index == mVideoStreamId
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
} // end while ! frameComplete
|
} // end while ! frameComplete
|
||||||
return (0);
|
return 1;
|
||||||
} // FfmpegCamera::Capture
|
} // FfmpegCamera::Capture
|
||||||
|
|
||||||
int FfmpegCamera::PostCapture() {
|
int FfmpegCamera::PostCapture() {
|
||||||
|
@ -458,7 +458,9 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
// STolen from ispy
|
// STolen from ispy
|
||||||
//this fixes issues with rtsp streams!! woot.
|
//this fixes issues with rtsp streams!! woot.
|
||||||
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
|
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
|
||||||
|
#ifdef CODEC_FLAG2_FAST
|
||||||
mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY;
|
mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
||||||
|
@ -495,7 +497,16 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef AV_CODEC_ID_H265
|
||||||
|
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H265 ) {
|
||||||
|
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
|
||||||
|
#ifdef AV_CODEC_ID_H265
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} // end if h264
|
} // end if h264
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -735,22 +746,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
mReopenThread = 0;
|
mReopenThread = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mVideoCodecContext->codec_id != AV_CODEC_ID_H264 ) {
|
|
||||||
#ifdef AV_CODEC_ID_H265
|
|
||||||
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H265 ) {
|
|
||||||
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
|
|
||||||
#ifdef AV_CODEC_ID_H265
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( ! frameComplete ) {
|
while ( ! frameComplete ) {
|
||||||
av_init_packet( &packet );
|
av_init_packet( &packet );
|
||||||
|
|
||||||
|
Debug(4,"before read frame");
|
||||||
ret = av_read_frame( mFormatContext, &packet );
|
ret = av_read_frame( mFormatContext, &packet );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
|
@ -960,11 +961,11 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
||||||
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
|
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
|
Warning( "Unable to receive frame %d: %s, continuing", frameCount, errbuf );
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -980,8 +981,6 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Debug( 4, "Decoded video packet at frame %d", frameCount );
|
|
||||||
|
|
||||||
if ( frameComplete ) {
|
if ( frameComplete ) {
|
||||||
Debug( 4, "Got frame %d", frameCount );
|
Debug( 4, "Got frame %d", frameCount );
|
||||||
|
|
||||||
|
@ -1012,6 +1011,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
||||||
Debug( 3, "Not framecomplete after av_read_frame" );
|
Debug( 3, "Not framecomplete after av_read_frame" );
|
||||||
} // end if frameComplete
|
} // end if frameComplete
|
||||||
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
||||||
|
frameComplete = 1;
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
if ( record_audio ) {
|
if ( record_audio ) {
|
||||||
if ( have_video_keyframe ) {
|
if ( have_video_keyframe ) {
|
||||||
|
@ -1033,6 +1033,8 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
||||||
} else {
|
} else {
|
||||||
Debug(4, "Have audio packet, but not recording atm" );
|
Debug(4, "Have audio packet, but not recording atm" );
|
||||||
}
|
}
|
||||||
|
zm_av_packet_unref( &packet );
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0)
|
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0)
|
||||||
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codecpar->codec_type) );
|
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codecpar->codec_type) );
|
||||||
|
@ -1044,7 +1046,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
||||||
// the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version.
|
// the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version.
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
} // end while ! frameComplete
|
} // end while ! frameComplete
|
||||||
return (frameCount);
|
return frameCount;
|
||||||
} // end FfmpegCamera::CaptureAndRecord
|
} // end FfmpegCamera::CaptureAndRecord
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,7 @@
|
||||||
#if HAVE_LIBVLC
|
#if HAVE_LIBVLC
|
||||||
|
|
||||||
// Do all the buffer checking work here to avoid unnecessary locking
|
// Do all the buffer checking work here to avoid unnecessary locking
|
||||||
void* LibvlcLockBuffer(void* opaque, void** planes)
|
void* LibvlcLockBuffer(void* opaque, void** planes) {
|
||||||
{
|
|
||||||
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
||||||
data->mutex.lock();
|
data->mutex.lock();
|
||||||
|
|
||||||
|
@ -36,15 +35,12 @@ void* LibvlcLockBuffer(void* opaque, void** planes)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
|
||||||
{
|
|
||||||
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
||||||
|
|
||||||
bool newFrame = false;
|
bool newFrame = false;
|
||||||
for(uint32_t i = 0; i < data->bufferSize; i++)
|
for( uint32_t i = 0; i < data->bufferSize; i++ ) {
|
||||||
{
|
if ( data->buffer[i] != data->prevBuffer[i] ) {
|
||||||
if(data->buffer[i] != data->prevBuffer[i])
|
|
||||||
{
|
|
||||||
newFrame = true;
|
newFrame = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -54,8 +50,7 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
||||||
time_t now;
|
time_t now;
|
||||||
time(&now);
|
time(&now);
|
||||||
// Return frames slightly faster than 1fps (if time() supports greater than one second resolution)
|
// Return frames slightly faster than 1fps (if time() supports greater than one second resolution)
|
||||||
if(newFrame || difftime(now, data->prevTime) >= 0.8)
|
if ( newFrame || difftime(now, data->prevTime) >= 0.8 ) {
|
||||||
{
|
|
||||||
data->prevTime = now;
|
data->prevTime = now;
|
||||||
data->newImage.updateValueSignal(true);
|
data->newImage.updateValueSignal(true);
|
||||||
}
|
}
|
||||||
|
@ -90,58 +85,46 @@ LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::stri
|
||||||
Panic("Unexpected colours: %d",colours);
|
Panic("Unexpected colours: %d",colours);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( capture )
|
if ( capture ) {
|
||||||
{
|
|
||||||
Initialise();
|
Initialise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LibvlcCamera::~LibvlcCamera()
|
LibvlcCamera::~LibvlcCamera() {
|
||||||
{
|
if ( capture ) {
|
||||||
if ( capture )
|
|
||||||
{
|
|
||||||
Terminate();
|
Terminate();
|
||||||
}
|
}
|
||||||
if(mLibvlcMediaPlayer != NULL)
|
if ( mLibvlcMediaPlayer != NULL ) {
|
||||||
{
|
|
||||||
libvlc_media_player_release(mLibvlcMediaPlayer);
|
libvlc_media_player_release(mLibvlcMediaPlayer);
|
||||||
mLibvlcMediaPlayer = NULL;
|
mLibvlcMediaPlayer = NULL;
|
||||||
}
|
}
|
||||||
if(mLibvlcMedia != NULL)
|
if ( mLibvlcMedia != NULL ) {
|
||||||
{
|
|
||||||
libvlc_media_release(mLibvlcMedia);
|
libvlc_media_release(mLibvlcMedia);
|
||||||
mLibvlcMedia = NULL;
|
mLibvlcMedia = NULL;
|
||||||
}
|
}
|
||||||
if(mLibvlcInstance != NULL)
|
if ( mLibvlcInstance != NULL ) {
|
||||||
{
|
|
||||||
libvlc_release(mLibvlcInstance);
|
libvlc_release(mLibvlcInstance);
|
||||||
mLibvlcInstance = NULL;
|
mLibvlcInstance = NULL;
|
||||||
}
|
}
|
||||||
if (mOptArgV != NULL)
|
if ( mOptArgV != NULL ) {
|
||||||
{
|
|
||||||
delete[] mOptArgV;
|
delete[] mOptArgV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibvlcCamera::Initialise()
|
void LibvlcCamera::Initialise() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibvlcCamera::Terminate()
|
void LibvlcCamera::Terminate() {
|
||||||
{
|
|
||||||
libvlc_media_player_stop(mLibvlcMediaPlayer);
|
libvlc_media_player_stop(mLibvlcMediaPlayer);
|
||||||
if(mLibvlcData.buffer != NULL)
|
if(mLibvlcData.buffer != NULL) {
|
||||||
{
|
|
||||||
zm_freealigned(mLibvlcData.buffer);
|
zm_freealigned(mLibvlcData.buffer);
|
||||||
}
|
}
|
||||||
if(mLibvlcData.prevBuffer != NULL)
|
if(mLibvlcData.prevBuffer != NULL) {
|
||||||
{
|
|
||||||
zm_freealigned(mLibvlcData.prevBuffer);
|
zm_freealigned(mLibvlcData.prevBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvlcCamera::PrimeCapture()
|
int LibvlcCamera::PrimeCapture() {
|
||||||
{
|
|
||||||
Info("Priming capture from %s", mPath.c_str());
|
Info("Priming capture from %s", mPath.c_str());
|
||||||
|
|
||||||
StringVector opVect = split(Options(), ",");
|
StringVector opVect = split(Options(), ",");
|
||||||
|
@ -154,8 +137,7 @@ int LibvlcCamera::PrimeCapture()
|
||||||
else if ( Method() == "rtpRtspHttp" )
|
else if ( Method() == "rtpRtspHttp" )
|
||||||
opVect.push_back("--rtsp-http");
|
opVect.push_back("--rtsp-http");
|
||||||
|
|
||||||
if (opVect.size() > 0)
|
if ( opVect.size() > 0 ) {
|
||||||
{
|
|
||||||
mOptArgV = new char*[opVect.size()];
|
mOptArgV = new char*[opVect.size()];
|
||||||
Debug(2, "Number of Options: %d",opVect.size());
|
Debug(2, "Number of Options: %d",opVect.size());
|
||||||
for (size_t i=0; i< opVect.size(); i++) {
|
for (size_t i=0; i< opVect.size(); i++) {
|
||||||
|
@ -166,7 +148,7 @@ int LibvlcCamera::PrimeCapture()
|
||||||
}
|
}
|
||||||
|
|
||||||
mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV);
|
mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV);
|
||||||
if(mLibvlcInstance == NULL)
|
if ( mLibvlcInstance == NULL )
|
||||||
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());
|
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());
|
||||||
|
|
||||||
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
|
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
|
||||||
|
@ -189,17 +171,15 @@ int LibvlcCamera::PrimeCapture()
|
||||||
|
|
||||||
libvlc_media_player_play(mLibvlcMediaPlayer);
|
libvlc_media_player_play(mLibvlcMediaPlayer);
|
||||||
|
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvlcCamera::PreCapture()
|
int LibvlcCamera::PreCapture() {
|
||||||
{
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not return -1 as cancels capture. Always wait for image if available.
|
// Should not return -1 as cancels capture. Always wait for image if available.
|
||||||
int LibvlcCamera::Capture( Image &image )
|
int LibvlcCamera::Capture( Image &image ) {
|
||||||
{
|
|
||||||
while(!mLibvlcData.newImage.getValueImmediate())
|
while(!mLibvlcData.newImage.getValueImmediate())
|
||||||
mLibvlcData.newImage.getUpdatedValue(1);
|
mLibvlcData.newImage.getUpdatedValue(1);
|
||||||
|
|
||||||
|
@ -208,25 +188,15 @@ int LibvlcCamera::Capture( Image &image )
|
||||||
mLibvlcData.newImage.setValueImmediate(false);
|
mLibvlcData.newImage.setValueImmediate(false);
|
||||||
mLibvlcData.mutex.unlock();
|
mLibvlcData.mutex.unlock();
|
||||||
|
|
||||||
return (0);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not return -1 as cancels capture. Always wait for image if available.
|
// Should not return -1 as cancels capture. Always wait for image if available.
|
||||||
int LibvlcCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory)
|
int LibvlcCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory) {
|
||||||
{
|
|
||||||
while(!mLibvlcData.newImage.getValueImmediate())
|
|
||||||
mLibvlcData.newImage.getUpdatedValue(1);
|
|
||||||
|
|
||||||
mLibvlcData.mutex.lock();
|
|
||||||
image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp);
|
|
||||||
mLibvlcData.newImage.setValueImmediate(false);
|
|
||||||
mLibvlcData.mutex.unlock();
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvlcCamera::PostCapture()
|
int LibvlcCamera::PostCapture() {
|
||||||
{
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1534,34 +1534,28 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
||||||
return( false );
|
return( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( verbose )
|
if ( verbose ) {
|
||||||
{
|
|
||||||
sprintf( output+strlen(output), " Input %d\n", input.index );
|
sprintf( output+strlen(output), " Input %d\n", input.index );
|
||||||
sprintf( output+strlen(output), " Name: %s\n", input.name );
|
sprintf( output+strlen(output), " Name: %s\n", input.name );
|
||||||
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||||
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
|
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
|
||||||
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
|
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
|
sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
|
||||||
sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||||
sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
|
sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( verbose )
|
if ( verbose ) {
|
||||||
{
|
|
||||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
|
||||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
|
||||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
|
||||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
|
||||||
}
|
} else {
|
||||||
else
|
sprintf( output+strlen(output), "i%dSP:%d|", input.index, (input.status&V4L2_IN_ST_NO_POWER)?0:1 );
|
||||||
{
|
sprintf( output+strlen(output), "i%dSS:%d|", input.index, (input.status&V4L2_IN_ST_NO_SIGNAL)?0:1 );
|
||||||
sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 );
|
sprintf( output+strlen(output), "i%dSC:%d|", input.index, (input.status&V4L2_IN_ST_NO_COLOR)?0:1 );
|
||||||
sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 );
|
sprintf( output+strlen(output), "i%dHP:%d|", input.index, (input.status&V4L2_IN_ST_NO_H_LOCK)?0:1 );
|
||||||
sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 );
|
|
||||||
sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( inputIndex++ >= 0 );
|
while ( inputIndex++ >= 0 );
|
||||||
|
@ -1570,12 +1564,10 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
||||||
}
|
}
|
||||||
#endif // ZM_HAS_V4L2
|
#endif // ZM_HAS_V4L2
|
||||||
#if ZM_HAS_V4L1
|
#if ZM_HAS_V4L1
|
||||||
if ( version == 1 )
|
if ( version == 1 ) {
|
||||||
{
|
|
||||||
struct video_capability vid_cap;
|
struct video_capability vid_cap;
|
||||||
memset( &vid_cap, 0, sizeof(video_capability) );
|
memset( &vid_cap, 0, sizeof(video_capability) );
|
||||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
|
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) {
|
||||||
{
|
|
||||||
Error( "Failed to get video capabilities: %s", strerror(errno) );
|
Error( "Failed to get video capabilities: %s", strerror(errno) );
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
|
sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
|
||||||
|
@ -1583,8 +1575,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
||||||
sprintf( output, "error%d\n", errno );
|
sprintf( output, "error%d\n", errno );
|
||||||
return( false );
|
return( false );
|
||||||
}
|
}
|
||||||
if ( verbose )
|
if ( verbose ) {
|
||||||
{
|
|
||||||
sprintf( output+strlen(output), "Video Capabilities\n" );
|
sprintf( output+strlen(output), "Video Capabilities\n" );
|
||||||
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
|
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
|
||||||
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
|
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
|
||||||
|
@ -1995,17 +1986,14 @@ int LocalCamera::Contrast( int p_contrast )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int LocalCamera::PrimeCapture()
|
int LocalCamera::PrimeCapture() {
|
||||||
{
|
|
||||||
Initialise();
|
Initialise();
|
||||||
|
|
||||||
Debug( 2, "Priming capture" );
|
Debug( 2, "Priming capture" );
|
||||||
#if ZM_HAS_V4L2
|
#if ZM_HAS_V4L2
|
||||||
if ( v4l_version == 2 )
|
if ( v4l_version == 2 ) {
|
||||||
{
|
|
||||||
Debug( 3, "Queueing buffers" );
|
Debug( 3, "Queueing buffers" );
|
||||||
for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ )
|
for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) {
|
||||||
{
|
|
||||||
struct v4l2_buffer vid_buf;
|
struct v4l2_buffer vid_buf;
|
||||||
|
|
||||||
memset( &vid_buf, 0, sizeof(vid_buf) );
|
memset( &vid_buf, 0, sizeof(vid_buf) );
|
||||||
|
@ -2028,13 +2016,10 @@ int LocalCamera::PrimeCapture()
|
||||||
}
|
}
|
||||||
#endif // ZM_HAS_V4L2
|
#endif // ZM_HAS_V4L2
|
||||||
#if ZM_HAS_V4L1
|
#if ZM_HAS_V4L1
|
||||||
if ( v4l_version == 1 )
|
if ( v4l_version == 1 ) {
|
||||||
{
|
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) {
|
||||||
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ )
|
|
||||||
{
|
|
||||||
Debug( 3, "Queueing frame %d", frame );
|
Debug( 3, "Queueing frame %d", frame );
|
||||||
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 )
|
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 ) {
|
||||||
{
|
|
||||||
Error( "Capture failure for frame %d: %s", frame, strerror(errno) );
|
Error( "Capture failure for frame %d: %s", frame, strerror(errno) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -2045,19 +2030,16 @@ int LocalCamera::PrimeCapture()
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int LocalCamera::PreCapture()
|
int LocalCamera::PreCapture() {
|
||||||
{
|
Debug( 5, "Pre-capturing" );
|
||||||
Debug( 2, "Pre-capturing" );
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int LocalCamera::Capture( Image &image )
|
int LocalCamera::Capture( Image &image ) {
|
||||||
{
|
|
||||||
Debug( 3, "Capturing" );
|
Debug( 3, "Capturing" );
|
||||||
static uint8_t* buffer = NULL;
|
static uint8_t* buffer = NULL;
|
||||||
static uint8_t* directbuffer = NULL;
|
|
||||||
static int capture_frame = -1;
|
|
||||||
int buffer_bytesused = 0;
|
int buffer_bytesused = 0;
|
||||||
|
int capture_frame = -1;
|
||||||
|
|
||||||
int captures_per_frame = 1;
|
int captures_per_frame = 1;
|
||||||
if ( channel_count > 1 )
|
if ( channel_count > 1 )
|
||||||
|
@ -2067,13 +2049,10 @@ int LocalCamera::Capture( Image &image )
|
||||||
Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame );
|
Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
|
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
|
||||||
if ( channel_prime )
|
if ( channel_prime ) {
|
||||||
{
|
|
||||||
#if ZM_HAS_V4L2
|
#if ZM_HAS_V4L2
|
||||||
if ( v4l_version == 2 )
|
if ( v4l_version == 2 ) {
|
||||||
{
|
|
||||||
static struct v4l2_buffer vid_buf;
|
static struct v4l2_buffer vid_buf;
|
||||||
|
|
||||||
memset( &vid_buf, 0, sizeof(vid_buf) );
|
memset( &vid_buf, 0, sizeof(vid_buf) );
|
||||||
|
@ -2083,10 +2062,8 @@ int LocalCamera::Capture( Image &image )
|
||||||
vid_buf.memory = v4l2_data.reqbufs.memory;
|
vid_buf.memory = v4l2_data.reqbufs.memory;
|
||||||
|
|
||||||
Debug( 3, "Capturing %d frames", captures_per_frame );
|
Debug( 3, "Capturing %d frames", captures_per_frame );
|
||||||
while ( captures_per_frame )
|
while ( captures_per_frame ) {
|
||||||
{
|
if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) {
|
||||||
if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 )
|
|
||||||
{
|
|
||||||
if ( errno == EIO )
|
if ( errno == EIO )
|
||||||
Warning( "Capture failure, possible signal loss?: %s", strerror(errno) )
|
Warning( "Capture failure, possible signal loss?: %s", strerror(errno) )
|
||||||
else
|
else
|
||||||
|
@ -2096,15 +2073,13 @@ int LocalCamera::Capture( Image &image )
|
||||||
|
|
||||||
v4l2_data.bufptr = &vid_buf;
|
v4l2_data.bufptr = &vid_buf;
|
||||||
capture_frame = v4l2_data.bufptr->index;
|
capture_frame = v4l2_data.bufptr->index;
|
||||||
if ( --captures_per_frame )
|
if ( --captures_per_frame ) {
|
||||||
{
|
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) {
|
||||||
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) );
|
Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // while captures_per_frame
|
||||||
|
|
||||||
Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel );
|
Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel );
|
||||||
|
|
||||||
|
@ -2115,23 +2090,19 @@ int LocalCamera::Capture( Image &image )
|
||||||
Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height);
|
Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // end if v4l2
|
||||||
#endif // ZM_HAS_V4L2
|
#endif // ZM_HAS_V4L2
|
||||||
#if ZM_HAS_V4L1
|
#if ZM_HAS_V4L1
|
||||||
if ( v4l_version == 1 )
|
if ( v4l_version == 1 ) {
|
||||||
{
|
|
||||||
Debug( 3, "Capturing %d frames", captures_per_frame );
|
Debug( 3, "Capturing %d frames", captures_per_frame );
|
||||||
while ( captures_per_frame )
|
while ( captures_per_frame ) {
|
||||||
{
|
|
||||||
Debug( 3, "Syncing frame %d", v4l1_data.active_frame );
|
Debug( 3, "Syncing frame %d", v4l1_data.active_frame );
|
||||||
if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 )
|
if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 ) {
|
||||||
{
|
|
||||||
Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
|
Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
captures_per_frame--;
|
captures_per_frame--;
|
||||||
if ( captures_per_frame )
|
if ( captures_per_frame ) {
|
||||||
{
|
|
||||||
Debug( 3, "Capturing frame %d", v4l1_data.active_frame );
|
Debug( 3, "Capturing frame %d", v4l1_data.active_frame );
|
||||||
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
|
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
|
||||||
{
|
{
|
||||||
|
@ -2148,18 +2119,18 @@ int LocalCamera::Capture( Image &image )
|
||||||
#endif // ZM_HAS_V4L1
|
#endif // ZM_HAS_V4L1
|
||||||
} /* prime capture */
|
} /* prime capture */
|
||||||
|
|
||||||
if(conversion_type != 0) {
|
if ( conversion_type != 0 ) {
|
||||||
|
|
||||||
Debug( 3, "Performing format conversion" );
|
Debug( 3, "Performing format conversion" );
|
||||||
|
|
||||||
/* Request a writeable buffer of the target image */
|
/* Request a writeable buffer of the target image */
|
||||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
uint8_t* directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||||
if(directbuffer == NULL) {
|
if ( directbuffer == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for the captured image.");
|
Error("Failed requesting writeable buffer for the captured image.");
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
#if HAVE_LIBSWSCALE
|
#if HAVE_LIBSWSCALE
|
||||||
if(conversion_type == 1) {
|
if ( conversion_type == 1 ) {
|
||||||
|
|
||||||
Debug( 9, "Calling sws_scale to perform the conversion" );
|
Debug( 9, "Calling sws_scale to perform the conversion" );
|
||||||
/* Use swscale to convert the image directly into the shared memory */
|
/* Use swscale to convert the image directly into the shared memory */
|
||||||
|
@ -2171,17 +2142,20 @@ int LocalCamera::Capture( Image &image )
|
||||||
avpicture_fill( (AVPicture *)tmpPicture, directbuffer,
|
avpicture_fill( (AVPicture *)tmpPicture, directbuffer,
|
||||||
imagePixFormat, width, height );
|
imagePixFormat, width, height );
|
||||||
#endif
|
#endif
|
||||||
sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
|
sws_scale( imgConversionContext,
|
||||||
|
capturePictures[capture_frame]->data,
|
||||||
|
capturePictures[capture_frame]->linesize,
|
||||||
|
0,
|
||||||
|
height,
|
||||||
|
tmpPicture->data,
|
||||||
|
tmpPicture->linesize );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(conversion_type == 2) {
|
if ( conversion_type == 2 ) {
|
||||||
|
|
||||||
Debug( 9, "Calling the conversion function" );
|
Debug( 9, "Calling the conversion function" );
|
||||||
/* Call the image conversion function and convert directly into the shared memory */
|
/* Call the image conversion function and convert directly into the shared memory */
|
||||||
(*conversion_fptr)(buffer, directbuffer, pixels);
|
(*conversion_fptr)(buffer, directbuffer, pixels);
|
||||||
}
|
} else if ( conversion_type == 3 ) {
|
||||||
else if(conversion_type == 3) {
|
|
||||||
|
|
||||||
Debug( 9, "Decoding the JPEG image" );
|
Debug( 9, "Decoding the JPEG image" );
|
||||||
/* JPEG decoding */
|
/* JPEG decoding */
|
||||||
image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder);
|
image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder);
|
||||||
|
@ -2192,15 +2166,14 @@ int LocalCamera::Capture( Image &image )
|
||||||
|
|
||||||
/* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
|
/* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
|
||||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
|
image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( 0 );
|
return 1;
|
||||||
}
|
} // end int LocalCamera::Capture()
|
||||||
|
|
||||||
int LocalCamera::PostCapture()
|
int LocalCamera::PostCapture()
|
||||||
{
|
{
|
||||||
Debug( 2, "Post-capturing" );
|
Debug( 4, "Post-capturing" );
|
||||||
// Requeue the buffer unless we need to switch or are a duplicate camera on a channel
|
// Requeue the buffer unless we need to switch or are a duplicate camera on a channel
|
||||||
if ( channel_count > 1 || channel_prime )
|
if ( channel_count > 1 || channel_prime )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1178,7 +1178,7 @@ bool Monitor::Analyse() {
|
||||||
gettimeofday( &now, NULL );
|
gettimeofday( &now, NULL );
|
||||||
|
|
||||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
||||||
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
|
fps = double(fps_report_interval)/(now.tv_sec - last_fps_time);
|
||||||
Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps );
|
Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps );
|
||||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||||
snprintf( sql, sizeof(sql), "UPDATE Monitors SET AnalysisFPS = '%.2lf' WHERE Id = '%d'", fps, id );
|
snprintf( sql, sizeof(sql), "UPDATE Monitors SET AnalysisFPS = '%.2lf' WHERE Id = '%d'", fps, id );
|
||||||
|
@ -2889,33 +2889,27 @@ int Monitor::Capture() {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Check if FFMPEG camera
|
//Check if FFMPEG camera
|
||||||
if ( (videowriter == H264PASSTHROUGH ) && camera->SupportsNativeVideo() ) {
|
if ( (videowriter == H264PASSTHROUGH) && camera->SupportsNativeVideo() ) {
|
||||||
//Warning("ZMC: Recording: %d", video_store_data->recording);
|
//Warning("ZMC: Recording: %d", video_store_data->recording);
|
||||||
captureResult = camera->CaptureAndRecord(*capture_image, video_store_data->recording, video_store_data->event_file);
|
// Should return -1 on error, like loss of signal. Should return 0 if ok but no video frame. > 0 for received a frame.
|
||||||
}else{
|
captureResult = camera->CaptureAndRecord(
|
||||||
|
*capture_image,
|
||||||
|
video_store_data->recording,
|
||||||
|
video_store_data->event_file
|
||||||
|
);
|
||||||
|
} else {
|
||||||
/* Capture directly into image buffer, avoiding the need to memcpy() */
|
/* Capture directly into image buffer, avoiding the need to memcpy() */
|
||||||
captureResult = camera->Capture(*capture_image);
|
captureResult = camera->Capture(*capture_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Debug(4, "Return from Capture (%d)", captureResult);
|
||||||
// CaptureAndRecord returns # of frames captured I think
|
if ( captureResult < 0 ) {
|
||||||
if ( ( videowriter == H264PASSTHROUGH ) && ( captureResult > 0 ) ) {
|
|
||||||
//video_store_data->frameNumber = captureResult;
|
|
||||||
captureResult = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( captureResult != 0 ) {
|
|
||||||
// Unable to capture image for temporary reason
|
// Unable to capture image for temporary reason
|
||||||
// Fake a signal loss image
|
// Fake a signal loss image
|
||||||
Rgb signalcolor;
|
Rgb signalcolor;
|
||||||
signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */
|
signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */
|
||||||
capture_image->Fill(signalcolor);
|
capture_image->Fill(signalcolor);
|
||||||
captureResult = 0;
|
} else if ( captureResult > 0 ) {
|
||||||
} else {
|
|
||||||
captureResult = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( captureResult == 1 ) {
|
|
||||||
|
|
||||||
/* Deinterlacing */
|
/* Deinterlacing */
|
||||||
if ( deinterlacing_value == 1 ) {
|
if ( deinterlacing_value == 1 ) {
|
||||||
|
@ -2969,49 +2963,58 @@ int Monitor::Capture() {
|
||||||
if ( privacy_bitmask )
|
if ( privacy_bitmask )
|
||||||
capture_image->MaskPrivacy( privacy_bitmask );
|
capture_image->MaskPrivacy( privacy_bitmask );
|
||||||
|
|
||||||
|
// Might be able to remove this call, when we start passing around ZMPackets, which will already have a timestamp
|
||||||
gettimeofday( image_buffer[index].timestamp, NULL );
|
gettimeofday( image_buffer[index].timestamp, NULL );
|
||||||
if ( config.timestamp_on_capture ) {
|
if ( config.timestamp_on_capture ) {
|
||||||
TimestampImage( capture_image, image_buffer[index].timestamp );
|
TimestampImage( capture_image, image_buffer[index].timestamp );
|
||||||
}
|
}
|
||||||
|
// Maybe we don't need to do this on all camera types
|
||||||
shared_data->signal = CheckSignal(capture_image);
|
shared_data->signal = CheckSignal(capture_image);
|
||||||
shared_data->last_write_index = index;
|
shared_data->last_write_index = index;
|
||||||
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
|
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
|
||||||
|
|
||||||
image_count++;
|
image_count++;
|
||||||
|
} // end if captureResult
|
||||||
|
|
||||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
||||||
time_t now = image_buffer[index].timestamp->tv_sec;
|
|
||||||
fps = double(fps_report_interval)/(now-last_fps_time);
|
struct timeval now;
|
||||||
//Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
|
if ( !captureResult ) {
|
||||||
|
gettimeofday( &now, NULL );
|
||||||
|
} else {
|
||||||
|
now.tv_sec = image_buffer[index].timestamp->tv_sec;
|
||||||
|
}
|
||||||
|
// If we are too fast, we get div by zero. This seems to happen in the case of audio packets.
|
||||||
|
if ( now.tv_sec != last_fps_time ) {
|
||||||
|
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
|
||||||
|
Info( "%d -> %d -> %d", fps_report_interval, now.tv_sec, last_fps_time );
|
||||||
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
|
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
|
||||||
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
|
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
|
||||||
last_fps_time = now;
|
last_fps_time = now.tv_sec;
|
||||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||||
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS = '%.2lf' WHERE Id = '%d'", fps, id );
|
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
|
||||||
if ( mysql_query( &dbconn, sql ) ) {
|
if ( mysql_query( &dbconn, sql ) ) {
|
||||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Icon: I'm not sure these should be here. They have nothing to do with capturing
|
// Icon: I'm not sure these should be here. They have nothing to do with capturing
|
||||||
if ( shared_data->action & GET_SETTINGS ) {
|
if ( shared_data->action & GET_SETTINGS ) {
|
||||||
shared_data->brightness = camera->Brightness();
|
shared_data->brightness = camera->Brightness();
|
||||||
shared_data->hue = camera->Hue();
|
shared_data->hue = camera->Hue();
|
||||||
shared_data->colour = camera->Colour();
|
shared_data->colour = camera->Colour();
|
||||||
shared_data->contrast = camera->Contrast();
|
shared_data->contrast = camera->Contrast();
|
||||||
shared_data->action &= ~GET_SETTINGS;
|
shared_data->action &= ~GET_SETTINGS;
|
||||||
}
|
}
|
||||||
if ( shared_data->action & SET_SETTINGS ) {
|
if ( shared_data->action & SET_SETTINGS ) {
|
||||||
camera->Brightness( shared_data->brightness );
|
camera->Brightness( shared_data->brightness );
|
||||||
camera->Hue( shared_data->hue );
|
camera->Hue( shared_data->hue );
|
||||||
camera->Colour( shared_data->colour );
|
camera->Colour( shared_data->colour );
|
||||||
camera->Contrast( shared_data->contrast );
|
camera->Contrast( shared_data->contrast );
|
||||||
shared_data->action &= ~SET_SETTINGS;
|
shared_data->action &= ~SET_SETTINGS;
|
||||||
}
|
}
|
||||||
return( 0 );
|
return captureResult;
|
||||||
} // end if captureResults == 1 which is success I think
|
|
||||||
shared_data->signal = false;
|
|
||||||
return( -1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const {
|
void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const {
|
||||||
|
|
|
@ -563,14 +563,22 @@ void MonitorStream::runStream() {
|
||||||
while ( !zm_terminate ) {
|
while ( !zm_terminate ) {
|
||||||
bool got_command = false;
|
bool got_command = false;
|
||||||
if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) {
|
if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) {
|
||||||
|
if ( feof( stdout ) ) {
|
||||||
|
Debug(2,"feof stdout");
|
||||||
|
} else if ( ferror( stdout ) ) {
|
||||||
|
Debug(2,"ferror stdout");
|
||||||
|
} else if ( !monitor->ShmValid() ) {
|
||||||
|
Debug(2,"monitor not valid.... maybe we should wait until it comes back.");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday( &now, NULL );
|
gettimeofday( &now, NULL );
|
||||||
|
|
||||||
if ( connkey ) {
|
if ( connkey ) {
|
||||||
Debug(2, "checking command Queue for connkey: %d", connkey );
|
//Debug(2, "checking command Queue for connkey: %d", connkey );
|
||||||
while(checkCommandQueue()) {
|
while(checkCommandQueue()) {
|
||||||
|
Debug(2, "Have checking command Queue for connkey: %d", connkey );
|
||||||
got_command = true;
|
got_command = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,8 +667,10 @@ Debug(2, "checking command Queue for connkey: %d", connkey );
|
||||||
// Send the next frame
|
// Send the next frame
|
||||||
Monitor::Snapshot *snap = &monitor->image_buffer[index];
|
Monitor::Snapshot *snap = &monitor->image_buffer[index];
|
||||||
|
|
||||||
if ( !sendFrame( snap->image, snap->timestamp ) )
|
if ( !sendFrame( snap->image, snap->timestamp ) ) {
|
||||||
|
Debug(2, "sendFrame failed, quiting.");
|
||||||
zm_terminate = true;
|
zm_terminate = true;
|
||||||
|
}
|
||||||
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
|
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
|
||||||
//frame_sent = true;
|
//frame_sent = true;
|
||||||
|
|
||||||
|
@ -698,10 +708,11 @@ Debug(2, "checking command Queue for connkey: %d", connkey );
|
||||||
frame_count++;
|
frame_count++;
|
||||||
}
|
}
|
||||||
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
||||||
Debug(2,"Sleep for (%d) microseconds");
|
Debug(2, "Sleeping for (%d)", sleep_time);
|
||||||
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
|
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
|
||||||
if ( ttl ) {
|
if ( ttl ) {
|
||||||
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
||||||
|
Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,9 @@ class MonitorStream : public StreamBase {
|
||||||
bool sendFrame( const char *filepath, struct timeval *timestamp );
|
bool sendFrame( const char *filepath, struct timeval *timestamp );
|
||||||
bool sendFrame( Image *image, struct timeval *timestamp );
|
bool sendFrame( Image *image, struct timeval *timestamp );
|
||||||
void processCommand( const CmdMsg *msg );
|
void processCommand( const CmdMsg *msg );
|
||||||
void SingleImage( int scale=100 );
|
void SingleImage( int scale=100 );
|
||||||
void SingleImageRaw( int scale=100 );
|
void SingleImageRaw( int scale=100 );
|
||||||
void SingleImageZip( int scale=100 );
|
void SingleImageZip( int scale=100 );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) {
|
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) {
|
||||||
|
|
133
src/zm_mpeg.cpp
133
src/zm_mpeg.cpp
|
@ -211,39 +211,52 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
|
||||||
|
|
||||||
Debug( 1, "Allocated stream" );
|
Debug( 1, "Allocated stream" );
|
||||||
|
|
||||||
AVCodecContext *c = ost->codec;
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
codec_context = avcodec_alloc_context3(NULL);
|
||||||
|
avcodec_parameters_to_context(codec_context, ost->codecpar);
|
||||||
|
#else
|
||||||
|
codec_context = ost->codec;
|
||||||
|
#endif
|
||||||
|
|
||||||
c->codec_id = codec->id;
|
codec_context->codec_id = codec->id;
|
||||||
c->codec_type = codec->type;
|
codec_context->codec_type = codec->type;
|
||||||
|
|
||||||
c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
|
codec_context->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
|
||||||
if ( bitrate <= 100 ) {
|
if ( bitrate <= 100 ) {
|
||||||
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
|
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
|
||||||
// This gets rid of artifacts in the beginning of the movie; and well, even quality.
|
// This gets rid of artifacts in the beginning of the movie; and well, even quality.
|
||||||
c->flags |= CODEC_FLAG_QSCALE;
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
|
codec_context->flags |= AV_CODEC_FLAG_QSCALE;
|
||||||
|
#else
|
||||||
|
codec_context->flags |= CODEC_FLAG_QSCALE;
|
||||||
|
#endif
|
||||||
|
codec_context->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
|
||||||
} else {
|
} else {
|
||||||
c->bit_rate = bitrate;
|
codec_context->bit_rate = bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* resolution must be a multiple of two */
|
/* resolution must be a multiple of two */
|
||||||
c->width = width;
|
codec_context->width = width;
|
||||||
c->height = height;
|
codec_context->height = height;
|
||||||
/* time base: this is the fundamental unit of time (in seconds) in terms
|
/* time base: this is the fundamental unit of time (in seconds) in terms
|
||||||
of which frame timestamps are represented. for fixed-fps content,
|
of which frame timestamps are represented. for fixed-fps content,
|
||||||
timebase should be 1/framerate and timestamp increments should be
|
timebase should be 1/framerate and timestamp increments should be
|
||||||
identically 1. */
|
identically 1. */
|
||||||
c->time_base.den = frame_rate;
|
codec_context->time_base.den = frame_rate;
|
||||||
c->time_base.num = 1;
|
codec_context->time_base.num = 1;
|
||||||
|
|
||||||
Debug( 1, "Will encode in %d fps.", c->time_base.den );
|
Debug( 1, "Will encode in %d fps.", codec_context->time_base.den );
|
||||||
|
|
||||||
/* emit one intra frame every second */
|
/* emit one intra frame every second */
|
||||||
c->gop_size = frame_rate;
|
codec_context->gop_size = frame_rate;
|
||||||
|
|
||||||
// some formats want stream headers to be separate
|
// some formats want stream headers to be separate
|
||||||
if ( of->flags & AVFMT_GLOBALHEADER )
|
if ( of->flags & AVFMT_GLOBALHEADER )
|
||||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||||
|
codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#else
|
||||||
|
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
|
Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
|
||||||
}
|
}
|
||||||
|
@ -278,13 +291,11 @@ void VideoStream::OpenStream( ) {
|
||||||
/* now that all the parameters are set, we can open the
|
/* now that all the parameters are set, we can open the
|
||||||
video codecs and allocate the necessary encode buffers */
|
video codecs and allocate the necessary encode buffers */
|
||||||
if ( ost ) {
|
if ( ost ) {
|
||||||
AVCodecContext *c = ost->codec;
|
|
||||||
|
|
||||||
/* open the codec */
|
/* open the codec */
|
||||||
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
||||||
if ( (avRet = avcodec_open( c, codec )) < 0 )
|
if ( (avRet = avcodec_open( codec_context, codec )) < 0 )
|
||||||
#else
|
#else
|
||||||
if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 )
|
if ( (avRet = avcodec_open2( codec_context, codec, 0 )) < 0 )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
|
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
|
||||||
|
@ -293,19 +304,15 @@ void VideoStream::OpenStream( ) {
|
||||||
Debug( 1, "Opened codec" );
|
Debug( 1, "Opened codec" );
|
||||||
|
|
||||||
/* allocate the encoded raw picture */
|
/* allocate the encoded raw picture */
|
||||||
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
opicture = zm_av_frame_alloc( );
|
||||||
opicture = av_frame_alloc( );
|
|
||||||
#else
|
|
||||||
opicture = avcodec_alloc_frame( );
|
|
||||||
#endif
|
|
||||||
if ( !opicture ) {
|
if ( !opicture ) {
|
||||||
Panic( "Could not allocate opicture" );
|
Panic( "Could not allocate opicture" );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
int size = av_image_get_buffer_size( c->pix_fmt, c->width, c->height, 1 );
|
int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 );
|
||||||
#else
|
#else
|
||||||
int size = avpicture_get_size( c->pix_fmt, c->width, c->height );
|
int size = avpicture_get_size( codec_context->pix_fmt, codec_context->width, codec_context->height );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
|
uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
|
||||||
|
@ -315,17 +322,17 @@ void VideoStream::OpenStream( ) {
|
||||||
}
|
}
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
av_image_fill_arrays(opicture->data, opicture->linesize,
|
av_image_fill_arrays(opicture->data, opicture->linesize,
|
||||||
opicture_buf, c->pix_fmt, c->width, c->height, 1);
|
opicture_buf, codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
|
||||||
#else
|
#else
|
||||||
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt,
|
avpicture_fill( (AVPicture *)opicture, opicture_buf, codec_context->pix_fmt,
|
||||||
c->width, c->height );
|
codec_context->width, codec_context->height );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* if the output format is not identical to the input format, then a temporary
|
/* if the output format is not identical to the input format, then a temporary
|
||||||
picture is needed too. It is then converted to the required
|
picture is needed too. It is then converted to the required
|
||||||
output format */
|
output format */
|
||||||
tmp_opicture = NULL;
|
tmp_opicture = NULL;
|
||||||
if ( c->pix_fmt != pf ) {
|
if ( codec_context->pix_fmt != pf ) {
|
||||||
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
||||||
tmp_opicture = av_frame_alloc( );
|
tmp_opicture = av_frame_alloc( );
|
||||||
#else
|
#else
|
||||||
|
@ -335,9 +342,9 @@ void VideoStream::OpenStream( ) {
|
||||||
Panic( "Could not allocate tmp_opicture" );
|
Panic( "Could not allocate tmp_opicture" );
|
||||||
}
|
}
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
int size = av_image_get_buffer_size( pf, c->width, c->height,1 );
|
int size = av_image_get_buffer_size( pf, codec_context->width, codec_context->height,1 );
|
||||||
#else
|
#else
|
||||||
int size = avpicture_get_size( pf, c->width, c->height );
|
int size = avpicture_get_size( pf, codec_context->width, codec_context->height );
|
||||||
#endif
|
#endif
|
||||||
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
|
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
|
||||||
if ( !tmp_opicture_buf ) {
|
if ( !tmp_opicture_buf ) {
|
||||||
|
@ -347,10 +354,10 @@ void VideoStream::OpenStream( ) {
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
av_image_fill_arrays(tmp_opicture->data,
|
av_image_fill_arrays(tmp_opicture->data,
|
||||||
tmp_opicture->linesize, tmp_opicture_buf, pf,
|
tmp_opicture->linesize, tmp_opicture_buf, pf,
|
||||||
c->width, c->height, 1);
|
codec_context->width, codec_context->height, 1);
|
||||||
#else
|
#else
|
||||||
avpicture_fill( (AVPicture *)tmp_opicture,
|
avpicture_fill( (AVPicture *)tmp_opicture,
|
||||||
tmp_opicture_buf, pf, c->width, c->height );
|
tmp_opicture_buf, pf, codec_context->width, codec_context->height );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +382,12 @@ void VideoStream::OpenStream( ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
video_outbuf = NULL;
|
video_outbuf = NULL;
|
||||||
|
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||||
|
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
|
||||||
|
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
|
||||||
|
#else
|
||||||
if ( !(of->flags & AVFMT_RAWPICTURE) ) {
|
if ( !(of->flags & AVFMT_RAWPICTURE) ) {
|
||||||
|
#endif
|
||||||
/* allocate output buffer */
|
/* allocate output buffer */
|
||||||
/* XXX: API change will be done */
|
/* XXX: API change will be done */
|
||||||
// TODO: Make buffer dynamic.
|
// TODO: Make buffer dynamic.
|
||||||
|
@ -446,6 +458,8 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
|
||||||
if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) {
|
if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) {
|
||||||
Fatal("pthread_mutex_init failed");
|
Fatal("pthread_mutex_init failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codec_context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoStream::~VideoStream( ) {
|
VideoStream::~VideoStream( ) {
|
||||||
|
@ -481,7 +495,7 @@ VideoStream::~VideoStream( ) {
|
||||||
|
|
||||||
/* close each codec */
|
/* close each codec */
|
||||||
if ( ost ) {
|
if ( ost ) {
|
||||||
avcodec_close( ost->codec );
|
avcodec_close( codec_context );
|
||||||
av_free( opicture->data[0] );
|
av_free( opicture->data[0] );
|
||||||
av_frame_free( &opicture );
|
av_frame_free( &opicture );
|
||||||
if ( tmp_opicture ) {
|
if ( tmp_opicture ) {
|
||||||
|
@ -564,17 +578,15 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
|
||||||
static struct SwsContext *img_convert_ctx = 0;
|
static struct SwsContext *img_convert_ctx = 0;
|
||||||
#endif // HAVE_LIBSWSCALE
|
#endif // HAVE_LIBSWSCALE
|
||||||
|
|
||||||
AVCodecContext *c = ost->codec;
|
if ( codec_context->pix_fmt != pf ) {
|
||||||
|
|
||||||
if ( c->pix_fmt != pf ) {
|
|
||||||
memcpy( tmp_opicture->data[0], buffer, buffer_size );
|
memcpy( tmp_opicture->data[0], buffer, buffer_size );
|
||||||
#ifdef HAVE_LIBSWSCALE
|
#ifdef HAVE_LIBSWSCALE
|
||||||
if ( !img_convert_ctx ) {
|
if ( !img_convert_ctx ) {
|
||||||
img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
|
img_convert_ctx = sws_getCachedContext( NULL, codec_context->width, codec_context->height, pf, codec_context->width, codec_context->height, codec_context->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
|
||||||
if ( !img_convert_ctx )
|
if ( !img_convert_ctx )
|
||||||
Panic( "Unable to initialise image scaling context" );
|
Panic( "Unable to initialise image scaling context" );
|
||||||
}
|
}
|
||||||
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize );
|
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, codec_context->height, opicture->data, opicture->linesize );
|
||||||
#else // HAVE_LIBSWSCALE
|
#else // HAVE_LIBSWSCALE
|
||||||
Fatal( "swscale is required for MPEG mode" );
|
Fatal( "swscale is required for MPEG mode" );
|
||||||
#endif // HAVE_LIBSWSCALE
|
#endif // HAVE_LIBSWSCALE
|
||||||
|
@ -586,7 +598,13 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
|
||||||
AVPacket *pkt = packet_buffers[packet_index];
|
AVPacket *pkt = packet_buffers[packet_index];
|
||||||
av_init_packet( pkt );
|
av_init_packet( pkt );
|
||||||
int got_packet = 0;
|
int got_packet = 0;
|
||||||
|
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||||
|
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
|
||||||
|
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
|
||||||
|
#else
|
||||||
if ( of->flags & AVFMT_RAWPICTURE ) {
|
if ( of->flags & AVFMT_RAWPICTURE ) {
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
|
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
|
||||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||||
#else
|
#else
|
||||||
|
@ -597,19 +615,34 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
|
||||||
pkt->size = sizeof (AVPicture);
|
pkt->size = sizeof (AVPicture);
|
||||||
got_packet = 1;
|
got_packet = 1;
|
||||||
} else {
|
} else {
|
||||||
opicture_ptr->pts = c->frame_number;
|
opicture_ptr->pts = codec_context->frame_number;
|
||||||
opicture_ptr->quality = c->global_quality;
|
opicture_ptr->quality = codec_context->global_quality;
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
// Put encoder into flushing mode
|
||||||
|
avcodec_send_frame(codec_context, opicture_ptr);
|
||||||
|
int ret = avcodec_receive_packet(codec_context, pkt);
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
if ( AVERROR_EOF != ret ) {
|
||||||
|
Error("ERror encoding video (%d) (%s)", ret,
|
||||||
|
av_err2str(ret));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
got_packet = 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100)
|
#if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100)
|
||||||
int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet );
|
int ret = avcodec_encode_video2( codec_context, pkt, opicture_ptr, &got_packet );
|
||||||
if ( ret != 0 ) {
|
if ( ret != 0 ) {
|
||||||
Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) );
|
Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr );
|
int out_size = avcodec_encode_video( codec_context, video_outbuf, video_outbuf_size, opicture_ptr );
|
||||||
got_packet = out_size > 0 ? 1 : 0;
|
got_packet = out_size > 0 ? 1 : 0;
|
||||||
pkt->data = got_packet ? video_outbuf : NULL;
|
pkt->data = got_packet ? video_outbuf : NULL;
|
||||||
pkt->size = got_packet ? out_size : 0;
|
pkt->size = got_packet ? out_size : 0;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if ( got_packet ) {
|
if ( got_packet ) {
|
||||||
// if ( c->coded_frame->key_frame )
|
// if ( c->coded_frame->key_frame )
|
||||||
|
@ -622,12 +655,12 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) {
|
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) {
|
||||||
pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base );
|
pkt->pts = av_rescale_q( pkt->pts, codec_context->time_base, ost->time_base );
|
||||||
}
|
}
|
||||||
if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) {
|
if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) {
|
||||||
pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base );
|
pkt->dts = av_rescale_q( pkt->dts, codec_context->time_base, ost->time_base );
|
||||||
}
|
}
|
||||||
pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base );
|
pkt->duration = av_rescale_q( pkt->duration, codec_context->time_base, ost->time_base );
|
||||||
pkt->stream_index = ost->index;
|
pkt->stream_index = ost->index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -658,8 +691,12 @@ void *VideoStream::StreamingThreadCallback(void *ctx){
|
||||||
VideoStream* videoStream = reinterpret_cast<VideoStream*>(ctx);
|
VideoStream* videoStream = reinterpret_cast<VideoStream*>(ctx);
|
||||||
|
|
||||||
const uint64_t nanosecond_multiplier = 1000000000;
|
const uint64_t nanosecond_multiplier = 1000000000;
|
||||||
|
|
||||||
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) );
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
|
||||||
|
#else
|
||||||
|
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
|
||||||
|
#endif
|
||||||
uint64_t frame_count = 0;
|
uint64_t frame_count = 0;
|
||||||
timespec start_time;
|
timespec start_time;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &start_time);
|
clock_gettime(CLOCK_MONOTONIC, &start_time);
|
||||||
|
|
|
@ -46,6 +46,7 @@ protected:
|
||||||
AVOutputFormat *of;
|
AVOutputFormat *of;
|
||||||
AVFormatContext *ofc;
|
AVFormatContext *ofc;
|
||||||
AVStream *ost;
|
AVStream *ost;
|
||||||
|
AVCodecContext *codec_context;
|
||||||
AVCodec *codec;
|
AVCodec *codec;
|
||||||
AVFrame *opicture;
|
AVFrame *opicture;
|
||||||
AVFrame *tmp_opicture;
|
AVFrame *tmp_opicture;
|
||||||
|
|
|
@ -103,6 +103,7 @@ int RemoteCamera::Read( int fd, char *buf, int size ) {
|
||||||
int bytes_to_recv = size - ReceivedBytes;
|
int bytes_to_recv = size - ReceivedBytes;
|
||||||
if ( SOCKET_BUF_SIZE < bytes_to_recv )
|
if ( SOCKET_BUF_SIZE < bytes_to_recv )
|
||||||
bytes_to_recv = SOCKET_BUF_SIZE;
|
bytes_to_recv = SOCKET_BUF_SIZE;
|
||||||
|
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
|
||||||
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
|
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
|
||||||
if ( bytes <= 0 ) {
|
if ( bytes <= 0 ) {
|
||||||
Error("RemoteCamera::Read Recv error. Closing Socket\n");
|
Error("RemoteCamera::Read Recv error. Closing Socket\n");
|
||||||
|
|
|
@ -87,7 +87,8 @@ public:
|
||||||
virtual void Terminate() = 0;
|
virtual void Terminate() = 0;
|
||||||
virtual int Connect() = 0;
|
virtual int Connect() = 0;
|
||||||
virtual int Disconnect() = 0;
|
virtual int Disconnect() = 0;
|
||||||
virtual int PreCapture() = 0;
|
virtual int PreCapture() { return 0; };
|
||||||
|
virtual int PrimeCapture() { return 0; };
|
||||||
virtual int Capture( Image &image ) = 0;
|
virtual int Capture( Image &image ) = 0;
|
||||||
virtual int PostCapture() = 0;
|
virtual int PostCapture() = 0;
|
||||||
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;
|
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;
|
||||||
|
|
|
@ -1063,23 +1063,18 @@ int RemoteCameraHttp::GetResponse()
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraHttp::PreCapture()
|
int RemoteCameraHttp::PreCapture() {
|
||||||
{
|
if ( sd < 0 ) {
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
Connect();
|
Connect();
|
||||||
if ( sd < 0 )
|
if ( sd < 0 ) {
|
||||||
{
|
|
||||||
Error( "Unable to connect to camera" );
|
Error( "Unable to connect to camera" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
mode = SINGLE_IMAGE;
|
mode = SINGLE_IMAGE;
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
}
|
}
|
||||||
if ( mode == SINGLE_IMAGE )
|
if ( mode == SINGLE_IMAGE ) {
|
||||||
{
|
if ( SendRequest() < 0 ) {
|
||||||
if ( SendRequest() < 0 )
|
|
||||||
{
|
|
||||||
Error( "Unable to send request" );
|
Error( "Unable to send request" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -1088,50 +1083,43 @@ int RemoteCameraHttp::PreCapture()
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraHttp::Capture( Image &image )
|
int RemoteCameraHttp::Capture( Image &image ) {
|
||||||
{
|
|
||||||
int content_length = GetResponse();
|
int content_length = GetResponse();
|
||||||
if ( content_length == 0 )
|
if ( content_length == 0 ) {
|
||||||
{
|
|
||||||
Warning( "Unable to capture image, retrying" );
|
Warning( "Unable to capture image, retrying" );
|
||||||
return( 1 );
|
return 0;
|
||||||
}
|
}
|
||||||
if ( content_length < 0 )
|
if ( content_length < 0 ) {
|
||||||
{
|
|
||||||
Error( "Unable to get response, disconnecting" );
|
Error( "Unable to get response, disconnecting" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
switch( format )
|
switch( format ) {
|
||||||
{
|
|
||||||
case JPEG :
|
case JPEG :
|
||||||
{
|
{
|
||||||
if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) )
|
if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) {
|
||||||
{
|
|
||||||
Error( "Unable to decode jpeg" );
|
Error( "Unable to decode jpeg" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X_RGB :
|
case X_RGB :
|
||||||
{
|
{
|
||||||
if ( content_length != (long)image.Size() )
|
if ( content_length != (long)image.Size() ) {
|
||||||
{
|
|
||||||
Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length );
|
Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X_RGBZ :
|
case X_RGBZ :
|
||||||
{
|
{
|
||||||
if ( !image.Unzip( buffer.extract( content_length ), content_length ) )
|
if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) {
|
||||||
{
|
|
||||||
Error( "Unable to unzip RGB image" );
|
Error( "Unable to unzip RGB image" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||||
break;
|
break;
|
||||||
|
@ -1140,13 +1128,12 @@ int RemoteCameraHttp::Capture( Image &image )
|
||||||
{
|
{
|
||||||
Error( "Unexpected image format encountered" );
|
Error( "Unexpected image format encountered" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return( 0 );
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraHttp::PostCapture()
|
int RemoteCameraHttp::PostCapture() {
|
||||||
{
|
return 0;
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ RemoteCameraNVSocket::RemoteCameraNVSocket(
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
||||||
|
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
Initialise();
|
Initialise();
|
||||||
|
@ -97,43 +98,39 @@ void RemoteCameraNVSocket::Initialise() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraNVSocket::Connect() {
|
int RemoteCameraNVSocket::Connect() {
|
||||||
|
int port_num = atoi(port.c_str());
|
||||||
//struct addrinfo *p;
|
//struct addrinfo *p;
|
||||||
struct sockaddr_in servaddr;
|
struct sockaddr_in servaddr;
|
||||||
bzero( &servaddr, sizeof(servaddr));
|
bzero( &servaddr, sizeof(servaddr));
|
||||||
servaddr.sin_family = AF_INET;
|
servaddr.sin_family = AF_INET;
|
||||||
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
|
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||||
servaddr.sin_port = htons(atoi(port.c_str()));
|
servaddr.sin_port = htons(port_num);
|
||||||
|
|
||||||
|
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
//for(p = hp; p != NULL; p = p->ai_next) {
|
//for(p = hp; p != NULL; p = p->ai_next) {
|
||||||
//sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
|
//sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol );
|
||||||
if ( sd < 0 ) {
|
if ( sd < 0 ) {
|
||||||
Warning("Can't create socket: %s", strerror(errno) );
|
Warning("Can't create socket: %s", strerror(errno) );
|
||||||
//continue;
|
//continue;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
//if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) {
|
|
||||||
if ( connect( sd, (struct sockaddr *)&servaddr , sizeof(servaddr) ) < 0 ) {
|
|
||||||
close(sd);
|
|
||||||
sd = -1;
|
|
||||||
|
|
||||||
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
|
|
||||||
return -1;
|
|
||||||
//continue;
|
|
||||||
//}
|
|
||||||
/* If we got here, we must have connected successfully */
|
|
||||||
//break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if ( p == NULL ) {
|
//if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) {
|
||||||
//Error("Unable to connect to the remote camera, aborting");
|
if ( connect( sd, (struct sockaddr *)&servaddr , sizeof(servaddr) ) < 0 ) {
|
||||||
//return( -1 );
|
close(sd);
|
||||||
//}
|
sd = -1;
|
||||||
|
|
||||||
Debug( 3, "Connected to host, socket = %d", sd );
|
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
|
||||||
return( sd );
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ( p == NULL ) {
|
||||||
|
//Error("Unable to connect to the remote camera, aborting");
|
||||||
|
//return( -1 );
|
||||||
|
//}
|
||||||
|
|
||||||
|
Debug( 3, "Connected to host:%d, socket = %d", port_num, sd );
|
||||||
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraNVSocket::Disconnect() {
|
int RemoteCameraNVSocket::Disconnect() {
|
||||||
|
@ -144,132 +141,33 @@ int RemoteCameraNVSocket::Disconnect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraNVSocket::SendRequest( std::string request ) {
|
int RemoteCameraNVSocket::SendRequest( std::string request ) {
|
||||||
Debug( 2, "Sending request: %s", request.c_str() );
|
Debug( 4, "Sending request: %s", request.c_str() );
|
||||||
if ( write( sd, request.data(), request.length() ) < 0 ) {
|
if ( write( sd, request.data(), request.length() ) < 0 ) {
|
||||||
Error( "Can't write: %s", strerror(errno) );
|
Error( "Can't write: %s", strerror(errno) );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
Debug( 3, "Request sent" );
|
Debug( 4, "Request sent" );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return codes are as follows:
|
int RemoteCameraNVSocket::PrimeCapture() {
|
||||||
* -1 means there was an error
|
|
||||||
* 0 means no bytes were returned but there wasn't actually an error.
|
|
||||||
* > 0 is the # of bytes read.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int RemoteCameraNVSocket::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
|
||||||
fd_set rfds;
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(sd, &rfds);
|
|
||||||
|
|
||||||
struct timeval temp_timeout = timeout;
|
|
||||||
|
|
||||||
int n_found = select(sd+1, &rfds, NULL, NULL, &temp_timeout);
|
|
||||||
if ( n_found == 0 ) {
|
|
||||||
Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec );
|
|
||||||
int error = 0;
|
|
||||||
socklen_t len = sizeof(error);
|
|
||||||
int retval = getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &len);
|
|
||||||
if ( retval != 0 ) {
|
|
||||||
Debug(1, "error getting socket error code %s", strerror(retval));
|
|
||||||
}
|
|
||||||
if ( error != 0 ) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Why are we disconnecting? It's just a timeout, meaning that data wasn't available.
|
|
||||||
//Disconnect();
|
|
||||||
return 0;
|
|
||||||
} else if ( n_found < 0 ) {
|
|
||||||
Error("Select error: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int total_bytes_to_read = 0;
|
|
||||||
|
|
||||||
if ( bytes_expected ) {
|
|
||||||
total_bytes_to_read = bytes_expected;
|
|
||||||
} else {
|
|
||||||
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
|
|
||||||
Error( "Can't ioctl(): %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( total_bytes_to_read == 0 ) {
|
|
||||||
if ( mode == SINGLE_IMAGE ) {
|
|
||||||
int error = 0;
|
|
||||||
socklen_t len = sizeof (error);
|
|
||||||
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
|
|
||||||
if(retval != 0 ) {
|
|
||||||
Debug( 1, "error getting socket error code %s", strerror(retval) );
|
|
||||||
}
|
|
||||||
if (error != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Case where we are grabbing a single jpg, but no content-length was given, so the expectation is that we read until close.
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
// If socket is closed locally, then select will fail, but if it is closed remotely
|
|
||||||
// then we have an exception on our socket.. but no data.
|
|
||||||
Debug( 3, "Socket closed remotely" );
|
|
||||||
//Disconnect(); // Disconnect is done outside of ReadData now.
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
|
|
||||||
if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) {
|
|
||||||
total_bytes_to_read = ZM_NETWORK_BUFSIZ;
|
|
||||||
Debug(3, "Just getting 32K" );
|
|
||||||
} else {
|
|
||||||
Debug(3, "Just getting %d", total_bytes_to_read );
|
|
||||||
}
|
|
||||||
} // end if bytes_expected or not
|
|
||||||
Debug( 3, "Expecting %d bytes", total_bytes_to_read );
|
|
||||||
|
|
||||||
int total_bytes_read = 0;
|
|
||||||
do {
|
|
||||||
int bytes_read = buffer.read_into( sd, total_bytes_to_read );
|
|
||||||
if ( bytes_read < 0 ) {
|
|
||||||
Error( "Read error: %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
} else if ( bytes_read == 0 ) {
|
|
||||||
Debug( 2, "Socket closed" );
|
|
||||||
//Disconnect(); // Disconnect is done outside of ReadData now.
|
|
||||||
return( -1 );
|
|
||||||
} else if ( (unsigned int)bytes_read < total_bytes_to_read ) {
|
|
||||||
Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
Debug( 3, "Read %d bytes", bytes_read );
|
|
||||||
total_bytes_read += bytes_read;
|
|
||||||
total_bytes_to_read -= bytes_read;
|
|
||||||
} while ( total_bytes_to_read );
|
|
||||||
|
|
||||||
Debug( 4, buffer );
|
|
||||||
|
|
||||||
return( total_bytes_read );
|
|
||||||
}
|
|
||||||
|
|
||||||
int RemoteCameraNVSocket::PreCapture() {
|
|
||||||
if ( sd < 0 ) {
|
if ( sd < 0 ) {
|
||||||
Connect();
|
Connect();
|
||||||
if ( sd < 0 ) {
|
if ( sd < 0 ) {
|
||||||
Error( "Unable to connect to camera" );
|
Error( "Unable to connect to camera" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
mode = SINGLE_IMAGE;
|
|
||||||
buffer.clear();
|
|
||||||
}
|
}
|
||||||
struct image_def {
|
buffer.clear();
|
||||||
uint16_t width;
|
struct image_def {
|
||||||
uint16_t height;
|
uint16_t width;
|
||||||
uint16_t type;
|
uint16_t height;
|
||||||
};
|
uint16_t type;
|
||||||
struct image_def image_def;
|
};
|
||||||
|
struct image_def image_def;
|
||||||
|
|
||||||
if ( SendRequest("GetImageParams") < 0 ) {
|
if ( SendRequest("GetImageParams\n") < 0 ) {
|
||||||
Error( "Unable to send request" );
|
Error( "Unable to send request" );
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -289,20 +187,28 @@ struct image_def image_def;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraNVSocket::Capture( Image &image ) {
|
int RemoteCameraNVSocket::Capture( Image &image ) {
|
||||||
if ( SendRequest("GetNextImage") < 0 ) {
|
if ( SendRequest("GetNextImage\n") < 0 ) {
|
||||||
Warning( "Unable to capture image, retrying" );
|
Warning( "Unable to capture image, retrying" );
|
||||||
return( 1 );
|
return 0;
|
||||||
}
|
}
|
||||||
if ( Read( sd, buffer, imagesize ) < imagesize ) {
|
if ( Read( sd, buffer, imagesize ) < imagesize ) {
|
||||||
Warning( "Unable to capture image, retrying" );
|
Warning( "Unable to capture image, retrying" );
|
||||||
return( 1 );
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t end;
|
||||||
|
if ( Read(sd, (char *) &end , sizeof(end)) < 0 ) {
|
||||||
|
Warning( "Unable to capture image, retrying" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( end != 0xFFFFFFFF) {
|
||||||
|
Warning("End Bytes Failed\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||||
return( 0 );
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RemoteCameraNVSocket::PostCapture()
|
int RemoteCameraNVSocket::PostCapture() {
|
||||||
{
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ bool p_record_audio );
|
||||||
int SendRequest( std::string );
|
int SendRequest( std::string );
|
||||||
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
||||||
int GetResponse();
|
int GetResponse();
|
||||||
int PreCapture();
|
int PrimeCapture();
|
||||||
int Capture( Image &image );
|
int Capture( Image &image );
|
||||||
int PostCapture();
|
int PostCapture();
|
||||||
int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);};
|
int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);};
|
||||||
|
|
|
@ -266,15 +266,15 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
||||||
|
|
||||||
/* Request a writeable buffer of the target image */
|
/* Request a writeable buffer of the target image */
|
||||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||||
if(directbuffer == NULL) {
|
if ( directbuffer == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for the captured image.");
|
Error("Failed requesting writeable buffer for the captured image.");
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
if ( !rtspThread->isRunning() )
|
if ( !rtspThread->isRunning() )
|
||||||
return (-1);
|
return -1;
|
||||||
|
|
||||||
if ( rtspThread->getFrame( buffer ) ) {
|
if ( rtspThread->getFrame( buffer ) ) {
|
||||||
Debug( 3, "Read frame %d bytes", buffer.size() );
|
Debug( 3, "Read frame %d bytes", buffer.size() );
|
||||||
|
@ -282,21 +282,21 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
||||||
Hexdump( 4, buffer.head(), 16 );
|
Hexdump( 4, buffer.head(), 16 );
|
||||||
|
|
||||||
if ( !buffer.size() )
|
if ( !buffer.size() )
|
||||||
return( -1 );
|
return -1;
|
||||||
|
|
||||||
if(mCodecContext->codec_id == AV_CODEC_ID_H264) {
|
if ( mCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
||||||
// SPS and PPS frames should be saved and appended to IDR frames
|
// SPS and PPS frames should be saved and appended to IDR frames
|
||||||
int nalType = (buffer.head()[3] & 0x1f);
|
int nalType = (buffer.head()[3] & 0x1f);
|
||||||
|
|
||||||
// SPS The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures
|
// SPS The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures
|
||||||
if(nalType == 7) {
|
if ( nalType == 7 ) {
|
||||||
lastSps = buffer;
|
lastSps = buffer;
|
||||||
continue;
|
continue;
|
||||||
} else if(nalType == 8) {
|
} else if ( nalType == 8 ) {
|
||||||
// PPS The PPS NAL unit contains parameters that apply to the decoding of one or more individual pictures inside a coded video sequence
|
// PPS The PPS NAL unit contains parameters that apply to the decoding of one or more individual pictures inside a coded video sequence
|
||||||
lastPps = buffer;
|
lastPps = buffer;
|
||||||
continue;
|
continue;
|
||||||
} else if(nalType == 5) {
|
} else if ( nalType == 5 ) {
|
||||||
// IDR
|
// IDR
|
||||||
buffer += lastSps;
|
buffer += lastSps;
|
||||||
buffer += lastPps;
|
buffer += lastPps;
|
||||||
|
@ -357,13 +357,13 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
} /* getFrame() */
|
} /* getFrame() */
|
||||||
|
|
||||||
if(frameComplete)
|
if ( frameComplete )
|
||||||
return (0);
|
return 1;
|
||||||
|
|
||||||
} // end while true
|
} // end while true
|
||||||
|
|
||||||
// can never get here.
|
// can never get here.
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Function to handle capture and store
|
//Function to handle capture and store
|
||||||
|
|
|
@ -379,21 +379,31 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
|
||||||
stream->id = i;
|
stream->id = i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AVCodecContext *codec_context = NULL;
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
codec_context = avcodec_alloc_context3(NULL);
|
||||||
|
avcodec_parameters_to_context(codec_context, stream->codecpar);
|
||||||
|
#else
|
||||||
|
codec_context = stream->codec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() );
|
Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() );
|
||||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||||
if ( mediaDesc->getType() == "video" )
|
if ( mediaDesc->getType() == "video" )
|
||||||
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
else if ( mediaDesc->getType() == "audio" )
|
else if ( mediaDesc->getType() == "audio" )
|
||||||
stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
else if ( mediaDesc->getType() == "application" )
|
else if ( mediaDesc->getType() == "application" )
|
||||||
stream->codec->codec_type = AVMEDIA_TYPE_DATA;
|
codec_context->codec_type = AVMEDIA_TYPE_DATA;
|
||||||
#else
|
#else
|
||||||
if ( mediaDesc->getType() == "video" )
|
if ( mediaDesc->getType() == "video" )
|
||||||
stream->codec->codec_type = CODEC_TYPE_VIDEO;
|
codec_context->codec_type = CODEC_TYPE_VIDEO;
|
||||||
else if ( mediaDesc->getType() == "audio" )
|
else if ( mediaDesc->getType() == "audio" )
|
||||||
stream->codec->codec_type = CODEC_TYPE_AUDIO;
|
codec_context->codec_type = CODEC_TYPE_AUDIO;
|
||||||
else if ( mediaDesc->getType() == "application" )
|
else if ( mediaDesc->getType() == "application" )
|
||||||
stream->codec->codec_type = CODEC_TYPE_DATA;
|
codec_context->codec_type = CODEC_TYPE_DATA;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
||||||
|
@ -410,31 +420,27 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
|
||||||
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
||||||
codec_name = std::string( smStaticPayloads[i].payloadName );
|
codec_name = std::string( smStaticPayloads[i].payloadName );
|
||||||
#else
|
#else
|
||||||
strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );;
|
strncpy( codec_context->codec_name, smStaticPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
|
||||||
#endif
|
#endif
|
||||||
stream->codec->codec_type = smStaticPayloads[i].codecType;
|
codec_context->codec_type = smStaticPayloads[i].codecType;
|
||||||
stream->codec->codec_id = smStaticPayloads[i].codecId;
|
codec_context->codec_id = smStaticPayloads[i].codecId;
|
||||||
stream->codec->sample_rate = smStaticPayloads[i].clockRate;
|
codec_context->sample_rate = smStaticPayloads[i].clockRate;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Look in dynamic table
|
// Look in dynamic table
|
||||||
for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ )
|
for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) {
|
||||||
{
|
if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) {
|
||||||
if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() )
|
|
||||||
{
|
|
||||||
Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName );
|
Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName );
|
||||||
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
|
||||||
codec_name = std::string( smStaticPayloads[i].payloadName );
|
codec_name = std::string( smStaticPayloads[i].payloadName );
|
||||||
#else
|
#else
|
||||||
strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );;
|
strncpy( codec_context->codec_name, smDynamicPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
|
||||||
#endif
|
#endif
|
||||||
stream->codec->codec_type = smDynamicPayloads[i].codecType;
|
codec_context->codec_type = smDynamicPayloads[i].codecType;
|
||||||
stream->codec->codec_id = smDynamicPayloads[i].codecId;
|
codec_context->codec_id = smDynamicPayloads[i].codecId;
|
||||||
stream->codec->sample_rate = mediaDesc->getClock();
|
codec_context->sample_rate = mediaDesc->getClock();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,14 +456,13 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
|
||||||
//return( 0 );
|
//return( 0 );
|
||||||
}
|
}
|
||||||
if ( mediaDesc->getWidth() )
|
if ( mediaDesc->getWidth() )
|
||||||
stream->codec->width = mediaDesc->getWidth();
|
codec_context->width = mediaDesc->getWidth();
|
||||||
if ( mediaDesc->getHeight() )
|
if ( mediaDesc->getHeight() )
|
||||||
stream->codec->height = mediaDesc->getHeight();
|
codec_context->height = mediaDesc->getHeight();
|
||||||
if ( stream->codec->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size())
|
if ( codec_context->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) {
|
||||||
{
|
|
||||||
uint8_t start_sequence[]= { 0, 0, 1 };
|
uint8_t start_sequence[]= { 0, 0, 1 };
|
||||||
stream->codec->extradata_size= 0;
|
codec_context->extradata_size= 0;
|
||||||
stream->codec->extradata= NULL;
|
codec_context->extradata= NULL;
|
||||||
char pvalue[1024], *value = pvalue;
|
char pvalue[1024], *value = pvalue;
|
||||||
|
|
||||||
strcpy(pvalue, mediaDesc->getSprops().c_str());
|
strcpy(pvalue, mediaDesc->getSprops().c_str());
|
||||||
|
@ -482,22 +487,33 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
|
||||||
if (packet_size) {
|
if (packet_size) {
|
||||||
uint8_t *dest =
|
uint8_t *dest =
|
||||||
(uint8_t *)av_malloc(packet_size + sizeof(start_sequence) +
|
(uint8_t *)av_malloc(packet_size + sizeof(start_sequence) +
|
||||||
stream->codec->extradata_size +
|
codec_context->extradata_size +
|
||||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||||
|
AV_INPUT_BUFFER_PADDING_SIZE
|
||||||
|
#else
|
||||||
|
FF_INPUT_BUFFER_PADDING_SIZE
|
||||||
|
#endif
|
||||||
|
);
|
||||||
if(dest) {
|
if(dest) {
|
||||||
if(stream->codec->extradata_size) {
|
if(codec_context->extradata_size) {
|
||||||
// av_realloc?
|
// av_realloc?
|
||||||
memcpy(dest, stream->codec->extradata, stream->codec->extradata_size);
|
memcpy(dest, codec_context->extradata, codec_context->extradata_size);
|
||||||
av_free(stream->codec->extradata);
|
av_free(codec_context->extradata);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dest+stream->codec->extradata_size, start_sequence, sizeof(start_sequence));
|
memcpy(dest+codec_context->extradata_size, start_sequence, sizeof(start_sequence));
|
||||||
memcpy(dest+stream->codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
|
memcpy(dest+codec_context->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
|
||||||
memset(dest+stream->codec->extradata_size+sizeof(start_sequence)+
|
memset(dest+codec_context->extradata_size+sizeof(start_sequence)+
|
||||||
packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
packet_size, 0,
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||||
|
AV_INPUT_BUFFER_PADDING_SIZE
|
||||||
|
#else
|
||||||
|
FF_INPUT_BUFFER_PADDING_SIZE
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
stream->codec->extradata= dest;
|
codec_context->extradata= dest;
|
||||||
stream->codec->extradata_size+= sizeof(start_sequence)+packet_size;
|
codec_context->extradata_size+= sizeof(start_sequence)+packet_size;
|
||||||
// } else {
|
// } else {
|
||||||
// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
|
// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
|
||||||
// return AVERROR(ENOMEM);
|
// return AVERROR(ENOMEM);
|
||||||
|
|
18
src/zm_sdp.h
18
src/zm_sdp.h
|
@ -31,13 +31,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class SessionDescriptor
|
class SessionDescriptor {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
enum { PAYLOAD_TYPE_DYNAMIC=96 };
|
enum { PAYLOAD_TYPE_DYNAMIC=96 };
|
||||||
|
|
||||||
struct StaticPayloadDesc
|
struct StaticPayloadDesc {
|
||||||
{
|
|
||||||
int payloadType;
|
int payloadType;
|
||||||
const char payloadName[6];
|
const char payloadName[6];
|
||||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||||
|
@ -50,8 +48,7 @@ protected:
|
||||||
int autoChannels;
|
int autoChannels;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DynamicPayloadDesc
|
struct DynamicPayloadDesc {
|
||||||
{
|
|
||||||
const char payloadName[32];
|
const char payloadName[32];
|
||||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||||
AVMediaType codecType;
|
AVMediaType codecType;
|
||||||
|
@ -65,8 +62,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class ConnInfo
|
class ConnInfo {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
std::string mNetworkType;
|
std::string mNetworkType;
|
||||||
std::string mAddressType;
|
std::string mAddressType;
|
||||||
|
@ -78,8 +74,7 @@ public:
|
||||||
ConnInfo( const std::string &connInfo );
|
ConnInfo( const std::string &connInfo );
|
||||||
};
|
};
|
||||||
|
|
||||||
class BandInfo
|
class BandInfo {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
std::string mType;
|
std::string mType;
|
||||||
int mValue;
|
int mValue;
|
||||||
|
@ -88,8 +83,7 @@ public:
|
||||||
BandInfo( const std::string &bandInfo );
|
BandInfo( const std::string &bandInfo );
|
||||||
};
|
};
|
||||||
|
|
||||||
class MediaDescriptor
|
class MediaDescriptor {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
std::string mType;
|
std::string mType;
|
||||||
int mPort;
|
int mPort;
|
||||||
|
|
|
@ -312,7 +312,7 @@ void StreamBase::openComms() {
|
||||||
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
|
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
|
||||||
rem_addr.sun_family = AF_UNIX;
|
rem_addr.sun_family = AF_UNIX;
|
||||||
} // end if connKey > 0
|
} // end if connKey > 0
|
||||||
Debug(3, "comms open" );
|
Debug(2, "comms open" );
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBase::closeComms() {
|
void StreamBase::closeComms() {
|
||||||
|
|
|
@ -90,12 +90,12 @@ bool User::canAccess( int monitor_id ) {
|
||||||
User *zmLoadUser( const char *username, const char *password ) {
|
User *zmLoadUser( const char *username, const char *password ) {
|
||||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||||
char safer_username[65]; // current db username size is 32
|
char safer_username[65]; // current db username size is 32
|
||||||
char safer_password[129]; // current db password size is 64
|
|
||||||
|
|
||||||
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
|
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
|
||||||
mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) );
|
mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) );
|
||||||
|
|
||||||
if ( password ) {
|
if ( password ) {
|
||||||
|
char safer_password[129]; // current db password size is 64
|
||||||
mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) );
|
mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) );
|
||||||
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password );
|
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password );
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -80,7 +80,7 @@ const std::string stringtf( const char *format, ... )
|
||||||
return( tempString );
|
return( tempString );
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string stringtf( const std::string &format, ... )
|
const std::string stringtf( const std::string format, ... )
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char tempBuffer[8192];
|
char tempBuffer[8192];
|
||||||
|
@ -100,7 +100,7 @@ bool startsWith( const std::string &haystack, const std::string &needle )
|
||||||
return( haystack.substr( 0, needle.length() ) == needle );
|
return( haystack.substr( 0, needle.length() ) == needle );
|
||||||
}
|
}
|
||||||
|
|
||||||
StringVector split( const std::string &string, const std::string chars, int limit )
|
StringVector split( const std::string &string, const std::string &chars, int limit )
|
||||||
{
|
{
|
||||||
StringVector stringVector;
|
StringVector stringVector;
|
||||||
std::string tempString = string;
|
std::string tempString = string;
|
||||||
|
@ -134,7 +134,7 @@ StringVector split( const std::string &string, const std::string chars, int limi
|
||||||
return( stringVector );
|
return( stringVector );
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string join(const StringVector v, const char * delim ) {
|
const std::string join(const StringVector &v, const char * delim ) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
for(size_t i = 0; i < v.size(); ++i) {
|
for(size_t i = 0; i < v.size(); ++i) {
|
||||||
|
|
|
@ -33,11 +33,11 @@ std::string trimSet(std::string str, std::string trimset);
|
||||||
std::string replaceAll(std::string str, std::string from, std::string to);
|
std::string replaceAll(std::string str, std::string from, std::string to);
|
||||||
|
|
||||||
const std::string stringtf( const char *format, ... );
|
const std::string stringtf( const char *format, ... );
|
||||||
const std::string stringtf( const std::string &format, ... );
|
const std::string stringtf( const std::string format, ... );
|
||||||
|
|
||||||
bool startsWith( const std::string &haystack, const std::string &needle );
|
bool startsWith( const std::string &haystack, const std::string &needle );
|
||||||
StringVector split( const std::string &string, const std::string chars, int limit=0 );
|
StringVector split( const std::string &string, const std::string &chars, int limit=0 );
|
||||||
const std::string join( const StringVector, const char * );
|
const std::string join( const StringVector &, const char * );
|
||||||
|
|
||||||
const std::string base64Encode( const std::string &inString );
|
const std::string base64Encode( const std::string &inString );
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
video_out_ctx->time_base.den);
|
video_out_ctx->time_base.den);
|
||||||
|
|
||||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||||
|
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||||
|
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#else
|
||||||
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor::Orientation orientation = monitor->getOrientation();
|
Monitor::Orientation orientation = monitor->getOrientation();
|
||||||
|
@ -274,7 +278,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
|
|
||||||
if (audio_out_stream) {
|
if (audio_out_stream) {
|
||||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||||
audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||||
|
audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#else
|
||||||
|
audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end if audio_in_stream
|
} // end if audio_in_stream
|
||||||
|
@ -823,19 +831,19 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
||||||
int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
||||||
Debug(4, "writeAudioFrame");
|
Debug(4, "writeAudioFrame");
|
||||||
|
|
||||||
if (!audio_out_stream) {
|
if ( !audio_out_stream ) {
|
||||||
Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
|
Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
|
||||||
return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
|
return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
|
||||||
// the moment
|
// the moment
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audio_out_codec) {
|
if ( audio_out_codec ) {
|
||||||
Debug(3, "Have audio codec");
|
Debug(3, "Have audio codec");
|
||||||
#ifdef HAVE_LIBAVRESAMPLE
|
#ifdef HAVE_LIBAVRESAMPLE
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
ret = avcodec_send_packet(audio_in_ctx, ipkt);
|
ret = avcodec_send_packet(audio_in_ctx, ipkt);
|
||||||
if (ret < 0) {
|
if ( ret < 0 ) {
|
||||||
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
|
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,6 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
||||||
int diff_width = diff_image->Width();
|
int diff_width = diff_image->Width();
|
||||||
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
|
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
|
||||||
uint8_t* pdiff;
|
uint8_t* pdiff;
|
||||||
const uint8_t* ppoly;
|
|
||||||
|
|
||||||
unsigned int pixel_diff_count = 0;
|
unsigned int pixel_diff_count = 0;
|
||||||
|
|
||||||
|
@ -267,6 +266,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
||||||
int bx1 = bx-1;
|
int bx1 = bx-1;
|
||||||
int by1 = by-1;
|
int by1 = by-1;
|
||||||
|
|
||||||
|
|
||||||
Debug( 5, "Checking for filtered pixels" );
|
Debug( 5, "Checking for filtered pixels" );
|
||||||
if ( bx > 1 || by > 1 ) {
|
if ( bx > 1 || by > 1 ) {
|
||||||
// Now remove any pixels smaller than our filter size
|
// Now remove any pixels smaller than our filter size
|
||||||
|
@ -679,7 +679,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ppoly = pg_image->Buffer( lo_x2, y );
|
const uint8_t* ppoly = pg_image->Buffer( lo_x2, y );
|
||||||
for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) {
|
for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) {
|
||||||
if ( !*ppoly ) {
|
if ( !*ppoly ) {
|
||||||
*pdiff = BLACK;
|
*pdiff = BLACK;
|
||||||
|
|
|
@ -161,7 +161,7 @@ int main(int argc, char *argv[]) {
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
int modes = (device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id > 0 ? 1 : 0));
|
int modes = ( (device[0]?1:0) + (host[0]?1:0) + (file[0]?1:0) + (monitor_id > 0 ? 1 : 0));
|
||||||
if ( modes > 1 ) {
|
if ( modes > 1 ) {
|
||||||
fprintf(stderr, "Only one of device, host/port/path, file or monitor id allowed\n");
|
fprintf(stderr, "Only one of device, host/port/path, file or monitor id allowed\n");
|
||||||
Usage();
|
Usage();
|
||||||
|
|
353
src/zmf.cpp
353
src/zmf.cpp
|
@ -1,353 +0,0 @@
|
||||||
//
|
|
||||||
// ZoneMinder Image File Writer 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
zmf - The ZoneMinder Frame daemon
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
zmf -m <monitor_id>
|
|
||||||
zmf --monitor <monitor_id>
|
|
||||||
zmf -h
|
|
||||||
zmf --help
|
|
||||||
zmf -v
|
|
||||||
zmf --version
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
This is an optional daemon that can run in concert with the Analysis daemon and
|
|
||||||
whose function it is to actually write captured frames to disk. This frees up
|
|
||||||
the Analysis daemon to do more analysis (!) and so keep up with the Capture
|
|
||||||
daemon better. If it isn't running or dies then the Analysis daemon just writes
|
|
||||||
them itself.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
-m, --monitor_id - ID of the monitor to use
|
|
||||||
-h, --help - Display usage information
|
|
||||||
-v, --version - Print the installed version of ZoneMinder
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "zm.h"
|
|
||||||
#include "zm_db.h"
|
|
||||||
#include "zm_signal.h"
|
|
||||||
#include "zm_monitor.h"
|
|
||||||
|
|
||||||
#include "zmf.h"
|
|
||||||
|
|
||||||
int OpenSocket( int monitor_id )
|
|
||||||
{
|
|
||||||
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if ( sd < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't create socket: %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char sock_path[PATH_MAX] = "";
|
|
||||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
|
||||||
if ( unlink( sock_path ) < 0 )
|
|
||||||
{
|
|
||||||
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
|
|
||||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't bind: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( listen( sd, SOMAXCONN ) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't listen: %s", strerror(errno) );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_un rem_addr;
|
|
||||||
socklen_t rem_addr_len = sizeof(rem_addr);
|
|
||||||
int new_sd = -1;
|
|
||||||
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't accept: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
close( sd );
|
|
||||||
|
|
||||||
sd = new_sd;
|
|
||||||
|
|
||||||
Info( "Frame server socket open, awaiting images" );
|
|
||||||
return( sd );
|
|
||||||
}
|
|
||||||
|
|
||||||
int ReopenSocket( int &sd, int monitor_id )
|
|
||||||
{
|
|
||||||
close( sd );
|
|
||||||
return( sd = OpenSocket( monitor_id ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Usage()
|
|
||||||
{
|
|
||||||
fprintf( stderr, "zmf -m <monitor_id>\n" );
|
|
||||||
fprintf( stderr, "Options:\n" );
|
|
||||||
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
|
|
||||||
fprintf( stderr, " -h, --help : This screen\n" );
|
|
||||||
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
|
|
||||||
exit( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
|
||||||
{
|
|
||||||
self = argv[0];
|
|
||||||
|
|
||||||
srand( getpid() * time( 0 ) );
|
|
||||||
|
|
||||||
int id = -1;
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"monitor", 1, 0, 'm'},
|
|
||||||
{"help", 0, 0, 'h'},
|
|
||||||
{"version", 0, 0, 'v'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int option_index = 0;
|
|
||||||
|
|
||||||
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
|
|
||||||
if (c == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'm':
|
|
||||||
id = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
Usage();
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
std::cout << ZM_VERSION << "\n";
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc)
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Extraneous options, " );
|
|
||||||
while (optind < argc)
|
|
||||||
printf ("%s ", argv[optind++]);
|
|
||||||
printf ("\n");
|
|
||||||
Usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( id < 0 )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Bogus monitor %d\n", id );
|
|
||||||
Usage();
|
|
||||||
exit( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
char log_id_string[16];
|
|
||||||
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
|
|
||||||
|
|
||||||
zmLoadConfig();
|
|
||||||
|
|
||||||
logInit( "zmf" );
|
|
||||||
|
|
||||||
hwcaps_detect();
|
|
||||||
|
|
||||||
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
|
|
||||||
|
|
||||||
if ( !monitor )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Can't find monitor with id of %d\n", id );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
Storage *Storage = monitor->getStorage();
|
|
||||||
|
|
||||||
char capt_path[PATH_MAX];
|
|
||||||
char anal_path[PATH_MAX];
|
|
||||||
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
|
|
||||||
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
|
|
||||||
zmSetDefaultTermHandler();
|
|
||||||
zmSetDefaultDieHandler();
|
|
||||||
|
|
||||||
sigset_t block_set;
|
|
||||||
sigemptyset( &block_set );
|
|
||||||
|
|
||||||
int sd = OpenSocket( monitor->Id() );
|
|
||||||
|
|
||||||
FrameHeader frame_header = { 0, 0, false, 0 };
|
|
||||||
//unsigned char *image_data = 0;
|
|
||||||
|
|
||||||
fd_set rfds;
|
|
||||||
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
while( 1 )
|
|
||||||
{
|
|
||||||
struct timeval temp_timeout = timeout;
|
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(sd, &rfds);
|
|
||||||
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
|
|
||||||
if( n_found == 0 )
|
|
||||||
{
|
|
||||||
Debug( 1, "Select timed out" );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ( n_found < 0)
|
|
||||||
{
|
|
||||||
Error( "Select error: %s", strerror(errno) );
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sigprocmask( SIG_BLOCK, &block_set, 0 );
|
|
||||||
|
|
||||||
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
|
|
||||||
if ( n_bytes != sizeof(frame_header) )
|
|
||||||
{
|
|
||||||
if ( n_bytes < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't read frame header: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
else if ( n_bytes > 0 )
|
|
||||||
{
|
|
||||||
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning( "Socket closed at remote end" );
|
|
||||||
}
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
|
|
||||||
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
|
|
||||||
|
|
||||||
// Read for pipe and loop until bytes expected have been read or an error occurs
|
|
||||||
int bytes_read = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
|
|
||||||
if (n_bytes < 0) break; // break on error
|
|
||||||
if (n_bytes < (int)frame_header.image_length)
|
|
||||||
{
|
|
||||||
// print some informational messages
|
|
||||||
if (bytes_read == 0)
|
|
||||||
{
|
|
||||||
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
|
|
||||||
}
|
|
||||||
else if (bytes_read+n_bytes == (int)frame_header.image_length)
|
|
||||||
{
|
|
||||||
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytes_read+= n_bytes;
|
|
||||||
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
|
|
||||||
|
|
||||||
// Print errors if there was a problem
|
|
||||||
if ( n_bytes < 1 )
|
|
||||||
{
|
|
||||||
|
|
||||||
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
|
|
||||||
if ( n_bytes < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't read frame image data: %s", strerror(errno) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning( "Socket closed at remote end" );
|
|
||||||
}
|
|
||||||
ReopenSocket( sd, monitor->Id() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char subpath[PATH_MAX] = "";
|
|
||||||
if ( config.use_deep_storage )
|
|
||||||
{
|
|
||||||
struct tm *time = localtime( &frame_header.event_time );
|
|
||||||
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
|
|
||||||
}
|
|
||||||
|
|
||||||
static char path[PATH_MAX] = "";
|
|
||||||
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
|
|
||||||
Debug( 1, "Got image, writing to %s", path );
|
|
||||||
|
|
||||||
FILE *fd = 0;
|
|
||||||
if ( (fd = fopen( path, "w" )) < 0 )
|
|
||||||
{
|
|
||||||
Error( "Can't fopen '%s': %s", path, strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
|
|
||||||
{
|
|
||||||
Error( "Can't fwrite image data: %s", strerror(errno) );
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
fclose( fd );
|
|
||||||
|
|
||||||
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
|
|
||||||
}
|
|
||||||
logTerm();
|
|
||||||
zmDbClose();
|
|
||||||
}
|
|
|
@ -37,6 +37,8 @@ if ( $$opts{protocol} eq 'https' ) {
|
||||||
die "https requires a server_name";
|
die "https requires a server_name";
|
||||||
}
|
}
|
||||||
$VirtualHostPorts = ' *:443';
|
$VirtualHostPorts = ' *:443';
|
||||||
|
} else {
|
||||||
|
$VirtualHostPorts = ' *:80';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
<?php
|
||||||
|
function unparse_url($parsed_url, $substitutions = array() ) {
|
||||||
|
$fields = array('scheme','host','port','user','pass','path','query','fragment');
|
||||||
|
|
||||||
|
foreach ( $fields as $field ) {
|
||||||
|
if ( isset( $substitutions[$field] ) ) {
|
||||||
|
$parsed_url[$field] = $substitutions[$field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
|
||||||
|
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
||||||
|
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
|
||||||
|
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
|
||||||
|
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
|
||||||
|
$pass = ($user || $pass) ? "$pass@" : '';
|
||||||
|
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
|
||||||
|
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
|
||||||
|
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
|
||||||
|
return "$scheme$user$pass$host$port$path$query$fragment";
|
||||||
|
}
|
||||||
|
|
||||||
|
$defaultMonitor = new Monitor();
|
||||||
|
$defaultMonitor->set(array(
|
||||||
|
'StorageId' => 1,
|
||||||
|
'ServerId' => 'auto',
|
||||||
|
'Function' => 'Record',
|
||||||
|
'Type' => 'Ffmpeg',
|
||||||
|
'Enabled' => '1',
|
||||||
|
'Colour' => '4', // 32bit
|
||||||
|
'PreEventCount' => 0,
|
||||||
|
) );
|
||||||
|
|
||||||
|
function probe( &$url_bits ) {
|
||||||
|
global $defaultMonitor;
|
||||||
|
$available_streams = array();
|
||||||
|
if ( ! isset($url_bits['port']) ) {
|
||||||
|
// No port given, do a port scan
|
||||||
|
foreach ( range( 2000, 2007 ) as $port ) {
|
||||||
|
$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
|
||||||
|
socket_set_option( $socket,
|
||||||
|
SOL_SOCKET, // socket level
|
||||||
|
SO_SNDTIMEO, // timeout option
|
||||||
|
array(
|
||||||
|
"sec"=>0, // Timeout in seconds
|
||||||
|
"usec"=>500 // I assume timeout in microseconds
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$new_stream = null;
|
||||||
|
Info("Testing connection to " . $url_bits['host'].':'.$port);
|
||||||
|
if ( socket_connect( $socket, $url_bits['host'], $port ) ) {
|
||||||
|
$new_stream = $url_bits; // make a copy
|
||||||
|
$new_stream['port'] = $port;
|
||||||
|
} else {
|
||||||
|
socket_close($socket);
|
||||||
|
Info("No connection to ".$url_bits['host'] . " on port $port");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( $new_stream ) {
|
||||||
|
if ( ! isset($new_stream['scheme'] ) )
|
||||||
|
$new_stream['scheme'] = 'http';
|
||||||
|
$url = unparse_url($new_stream, array('path'=>'/', 'query'=>'action=snapshot'));
|
||||||
|
list($width, $height, $type, $attr) = getimagesize( $url );
|
||||||
|
Info("Got $width x $height from $url");
|
||||||
|
$new_stream['Width'] = $width;
|
||||||
|
$new_stream['Height'] = $height;
|
||||||
|
|
||||||
|
//try {
|
||||||
|
//if ( $response = do_request( 'GET', $url ) ) {
|
||||||
|
//$new_stream['path'] = '/';
|
||||||
|
//$new_stream['query'] = '?action=stream';
|
||||||
|
//$image = imagecreatefromstring($response);
|
||||||
|
////$size = getimagesize( $image );
|
||||||
|
//
|
||||||
|
//} else {
|
||||||
|
//Info("No response from $url");
|
||||||
|
//}
|
||||||
|
//} catch ( EXception $e ) {
|
||||||
|
//Info("No response from $url");
|
||||||
|
//}
|
||||||
|
$available_streams[] = $new_stream;
|
||||||
|
} // end if new_Stream
|
||||||
|
} // end foreach port to scan
|
||||||
|
} else {
|
||||||
|
// A port was specified, so don't need to port scan.
|
||||||
|
$available_streams[] = $url_bits;
|
||||||
|
}
|
||||||
|
foreach ( $available_streams as &$stream ) {
|
||||||
|
# check for existence in db.
|
||||||
|
$stream['url'] = unparse_url( $stream, array( 'path'=>'/','query'=>'action=stream' ) );
|
||||||
|
$monitors = Monitor::find_all( array( 'Path'=>$stream['url'] ) );
|
||||||
|
if ( count($monitors ) ) {
|
||||||
|
$stream['Monitor'] = $monitors[0];
|
||||||
|
if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) {
|
||||||
|
$stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n";
|
||||||
|
}
|
||||||
|
if ( isset( $stream['Height'] ) and ( $stream['Monitor']->Height() != $stream['Height'] ) ) {
|
||||||
|
$stream['Warning'] .= 'Monitor height ('.$stream['Monitor']->Height().') and stream width ('.$stream['Height'].") do not match!\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$stream['Monitor'] = $defaultMonitor;
|
||||||
|
if ( isset($stream['Width']) ) {
|
||||||
|
$stream['Monitor']->Width( $stream['Width'] );
|
||||||
|
$stream['Monitor']->Height( $stream['Height'] );
|
||||||
|
}
|
||||||
|
} // Monitor found or not
|
||||||
|
} // end foreach Stream
|
||||||
|
|
||||||
|
#$macCommandString = 'arp ' . $url_bits['host'] . " | awk 'BEGIN{ i=1; } { i++; if(i==3) print $3 }'";
|
||||||
|
#$mac = exec($macCommandString);
|
||||||
|
#Info("Mac $mac");
|
||||||
|
return $available_streams;
|
||||||
|
} // end function probe
|
||||||
|
|
||||||
|
if ( canEdit( 'Monitors' ) ) {
|
||||||
|
switch ( $_REQUEST['action'] ) {
|
||||||
|
case 'probe' :
|
||||||
|
{
|
||||||
|
$available_streams = array();
|
||||||
|
$url_bits = null;
|
||||||
|
if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $_REQUEST['url'] ) ) {
|
||||||
|
$url_bits = array( 'host'=>$_REQUEST['url'] );
|
||||||
|
} else {
|
||||||
|
$url_bits = parse_url( $_REQUEST['url'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 ) {
|
||||||
|
// Shortcut test
|
||||||
|
$monitors = Monitor::find_all( array( 'Path'=>$_REQUEST['url'] ) );
|
||||||
|
if ( count( $monitors ) ) {
|
||||||
|
Info("Monitor found for " . $_REQUEST['url']);
|
||||||
|
$url_bits['url'] = $_REQUEST['url'];
|
||||||
|
$url_bits['Monitor'] = $monitors[0];
|
||||||
|
$available_stream[] = $url_bits;
|
||||||
|
ajaxResponse( array ( 'Streams'=>$available_streams) );
|
||||||
|
return;
|
||||||
|
} # end url already has a monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $url_bits ) {
|
||||||
|
ajaxError("The given URL was too malformed to parse.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$available_streams = probe( $url_bits );
|
||||||
|
|
||||||
|
ajaxResponse( array('Streams'=>$available_streams) );
|
||||||
|
return;
|
||||||
|
} // end case url_probe
|
||||||
|
case 'import':
|
||||||
|
{
|
||||||
|
|
||||||
|
$file = $_FILES['import_file'];
|
||||||
|
|
||||||
|
if ($file["error"] > 0) {
|
||||||
|
ajaxError($file["error"]);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
$filename = $file["name"];
|
||||||
|
|
||||||
|
$available_streams = array();
|
||||||
|
$row = 1;
|
||||||
|
if (($handle = fopen($file['tmp_name'], 'r')) !== FALSE) {
|
||||||
|
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||||
|
$name = $data[0];
|
||||||
|
$url = $data[1];
|
||||||
|
$group = $data[2];
|
||||||
|
Info("Have the following line data $name $url $group");
|
||||||
|
|
||||||
|
$url_bits = null;
|
||||||
|
if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $url) ) {
|
||||||
|
$url_bits = array( 'host'=>$url, 'scheme'=>'http' );
|
||||||
|
} else {
|
||||||
|
$url_bits = parse_url( $url );
|
||||||
|
}
|
||||||
|
if ( ! $url_bits ) {
|
||||||
|
Info("Bad url, skipping line $name $url $group");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$available_streams += probe( $url_bits );
|
||||||
|
|
||||||
|
//$url_bits['url'] = unparse_url( $url_bits );
|
||||||
|
//$url_bits['Monitor'] = $defaultMonitor;
|
||||||
|
//$url_bits['Monitor']->Name( $name );
|
||||||
|
//$url_bits['Monitor']->merge( $_POST['newMonitor'] );
|
||||||
|
//$available_streams[] = $url_bits;
|
||||||
|
|
||||||
|
} // end while rows
|
||||||
|
fclose($handle);
|
||||||
|
ajaxResponse( array('Streams'=>$available_streams) );
|
||||||
|
} else {
|
||||||
|
ajaxError("Uploaded file does not exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // end case import
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Warning("unknown action " . $_REQUEST['action'] );
|
||||||
|
} // end ddcase default
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Warning("Cannot edit monitors" );
|
||||||
|
}
|
||||||
|
|
||||||
|
ajaxError( 'Unrecognised action or insufficient permissions' );
|
||||||
|
|
||||||
|
?>
|
|
@ -1,170 +1,170 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$statusData = array(
|
$statusData = array(
|
||||||
"system" => array(
|
'system' => array(
|
||||||
"permission" => "System",
|
'permission' => 'System',
|
||||||
"table" => "Monitors",
|
'table' => 'Monitors',
|
||||||
"limit" => 1,
|
'limit' => 1,
|
||||||
"elements" => array(
|
'elements' => array(
|
||||||
"MonitorCount" => array( "sql" => "count(*)" ),
|
'MonitorCount' => array( 'sql' => "count(*)" ),
|
||||||
"ActiveMonitorCount" => array( "sql" => "count(if(Function != 'None',1,NULL))" ),
|
'ActiveMonitorCount' => array( 'sql' => "count(if(Function != 'None',1,NULL))" ),
|
||||||
"State" => array( "func" => "daemonCheck()?".translate('Running').":".translate('Stopped') ),
|
'State' => array( 'func' => "daemonCheck()?".translate('Running').":".translate('Stopped') ),
|
||||||
"Load" => array( "func" => "getLoad()" ),
|
'Load' => array( 'func' => "getLoad()" ),
|
||||||
"Disk" => array( "func" => "getDiskPercent()" ),
|
'Disk' => array( 'func' => "getDiskPercent()" ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"monitor" => array(
|
'monitor' => array(
|
||||||
"permission" => "Monitors",
|
'permission' => 'Monitors',
|
||||||
"table" => "Monitors",
|
'table' => 'Monitors',
|
||||||
"limit" => 1,
|
'limit' => 1,
|
||||||
"selector" => "Monitors.Id",
|
'selector' => "Monitors.Id",
|
||||||
"elements" => array(
|
'elements' => array(
|
||||||
"Id" => array( "sql" => "Monitors.Id" ),
|
'Id' => array( 'sql' => "Monitors.Id" ),
|
||||||
"Name" => array( "sql" => "Monitors.Name" ),
|
'Name' => array( 'sql' => "Monitors.Name" ),
|
||||||
"Type" => true,
|
'Type' => true,
|
||||||
"Function" => true,
|
'Function' => true,
|
||||||
"Enabled" => true,
|
'Enabled' => true,
|
||||||
"LinkedMonitors" => true,
|
'LinkedMonitors' => true,
|
||||||
"Triggers" => true,
|
'Triggers' => true,
|
||||||
"Device" => true,
|
'Device' => true,
|
||||||
"Channel" => true,
|
'Channel' => true,
|
||||||
"Format" => true,
|
'Format' => true,
|
||||||
"Host" => true,
|
'Host' => true,
|
||||||
"Port" => true,
|
'Port' => true,
|
||||||
"Path" => true,
|
'Path' => true,
|
||||||
"Width" => array( "sql" => "Monitors.Width" ),
|
'Width' => array( 'sql' => "Monitors.Width" ),
|
||||||
"Height" => array( "sql" => "Monitors.Height" ),
|
'Height' => array( 'sql' => "Monitors.Height" ),
|
||||||
"Palette" => true,
|
'Palette' => true,
|
||||||
"Orientation" => true,
|
'Orientation' => true,
|
||||||
"Brightness" => true,
|
'Brightness' => true,
|
||||||
"Contrast" => true,
|
'Contrast' => true,
|
||||||
"Hue" => true,
|
'Hue' => true,
|
||||||
"Colour" => true,
|
'Colour' => true,
|
||||||
"EventPrefix" => true,
|
'EventPrefix' => true,
|
||||||
"LabelFormat" => true,
|
'LabelFormat' => true,
|
||||||
"LabelX" => true,
|
'LabelX' => true,
|
||||||
"LabelY" => true,
|
'LabelY' => true,
|
||||||
"LabelSize" => true,
|
'LabelSize' => true,
|
||||||
"ImageBufferCount" => true,
|
'ImageBufferCount' => true,
|
||||||
"WarmupCount" => true,
|
'WarmupCount' => true,
|
||||||
"PreEventCount" => true,
|
'PreEventCount' => true,
|
||||||
"PostEventCount" => true,
|
'PostEventCount' => true,
|
||||||
"AlarmFrameCount" => true,
|
'AlarmFrameCount' => true,
|
||||||
"SectionLength" => true,
|
'SectionLength' => true,
|
||||||
"FrameSkip" => true,
|
'FrameSkip' => true,
|
||||||
"MotionFrameSkip" => true,
|
'MotionFrameSkip' => true,
|
||||||
"MaxFPS" => true,
|
'MaxFPS' => true,
|
||||||
"AlarmMaxFPS" => true,
|
'AlarmMaxFPS' => true,
|
||||||
"FPSReportInterval" => true,
|
'FPSReportInterval' => true,
|
||||||
"RefBlendPerc" => true,
|
'RefBlendPerc' => true,
|
||||||
"Controllable" => true,
|
'Controllable' => true,
|
||||||
"ControlId" => true,
|
'ControlId' => true,
|
||||||
"ControlDevice" => true,
|
'ControlDevice' => true,
|
||||||
"ControlAddress" => true,
|
'ControlAddress' => true,
|
||||||
"AutoStopTimeout" => true,
|
'AutoStopTimeout' => true,
|
||||||
"TrackMotion" => true,
|
'TrackMotion' => true,
|
||||||
"TrackDelay" => true,
|
'TrackDelay' => true,
|
||||||
"ReturnLocation" => true,
|
'ReturnLocation' => true,
|
||||||
"ReturnDelay" => true,
|
'ReturnDelay' => true,
|
||||||
"DefaultView" => true,
|
'DefaultView' => true,
|
||||||
"DefaultRate" => true,
|
'DefaultRate' => true,
|
||||||
"DefaultScale" => true,
|
'DefaultScale' => true,
|
||||||
"WebColour" => true,
|
'WebColour' => true,
|
||||||
"Sequence" => true,
|
'Sequence' => true,
|
||||||
"MinEventId" => array( "sql" => "(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
'MinEventId' => array( 'sql' => "(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||||
"MaxEventId" => array( "sql" => "(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
'MaxEventId' => array( 'sql' => "(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||||
"TotalEvents" => array( "sql" => "(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
'TotalEvents' => array( 'sql' => "(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||||
"Status" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ),
|
'Status' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ),
|
||||||
"FrameRate" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ),
|
'FrameRate' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"events" => array(
|
'events' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"table" => "Events",
|
'table' => 'Events',
|
||||||
"selector" => "Events.MonitorId",
|
'selector' => "Events.MonitorId",
|
||||||
"elements" => array(
|
'elements' => array(
|
||||||
"Id" => true,
|
'Id' => true,
|
||||||
"Name" => true,
|
'Name' => true,
|
||||||
"Cause" => true,
|
'Cause' => true,
|
||||||
"Notes" => true,
|
'Notes' => true,
|
||||||
"StartTime" => true,
|
'StartTime' => true,
|
||||||
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||||
"EndTime" => true,
|
'EndTime' => true,
|
||||||
"Width" => true,
|
'Width' => true,
|
||||||
"Height" => true,
|
'Height' => true,
|
||||||
"Length" => true,
|
'Length' => true,
|
||||||
"Frames" => true,
|
'Frames' => true,
|
||||||
"AlarmFrames" => true,
|
'AlarmFrames' => true,
|
||||||
"TotScore" => true,
|
'TotScore' => true,
|
||||||
"AvgScore" => true,
|
'AvgScore' => true,
|
||||||
"MaxScore" => true,
|
'MaxScore' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"event" => array(
|
'event' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"table" => "Events",
|
'table' => 'Events',
|
||||||
"limit" => 1,
|
'limit' => 1,
|
||||||
"selector" => "Events.Id",
|
'selector' => "Events.Id",
|
||||||
"elements" => array(
|
'elements' => array(
|
||||||
"Id" => array( "sql" => "Events.Id" ),
|
'Id' => array( 'sql' => "Events.Id" ),
|
||||||
"MonitorId" => true,
|
'MonitorId' => true,
|
||||||
"MonitorName" => array("sql" => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"),
|
'MonitorName' => array('sql' => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"),
|
||||||
"Name" => true,
|
'Name' => true,
|
||||||
"Cause" => true,
|
'Cause' => true,
|
||||||
"StartTime" => true,
|
'StartTime' => true,
|
||||||
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||||
"EndTime" => true,
|
'EndTime' => true,
|
||||||
"Width" => true,
|
'Width' => true,
|
||||||
"Height" => true,
|
'Height' => true,
|
||||||
"Length" => true,
|
'Length' => true,
|
||||||
"Frames" => true,
|
'Frames' => true,
|
||||||
"DefaultVideo" => true,
|
'DefaultVideo' => true,
|
||||||
"AlarmFrames" => true,
|
'AlarmFrames' => true,
|
||||||
"TotScore" => true,
|
'TotScore' => true,
|
||||||
"AvgScore" => true,
|
'AvgScore' => true,
|
||||||
"MaxScore" => true,
|
'MaxScore' => true,
|
||||||
"Archived" => true,
|
'Archived' => true,
|
||||||
"Videoed" => true,
|
'Videoed' => true,
|
||||||
"Uploaded" => true,
|
'Uploaded' => true,
|
||||||
"Emailed" => true,
|
'Emailed' => true,
|
||||||
"Messaged" => true,
|
'Messaged' => true,
|
||||||
"Executed" => true,
|
'Executed' => true,
|
||||||
"Notes" => true,
|
'Notes' => true,
|
||||||
"MinFrameId" => array( "sql" => "(SELECT min(Frames.FrameId) FROM Frames WHERE EventId=Events.Id)" ),
|
'MinFrameId' => array( 'sql' => "(SELECT min(Frames.FrameId) FROM Frames WHERE EventId=Events.Id)" ),
|
||||||
"MaxFrameId" => array( "sql" => "(SELECT max(Frames.FrameId) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
'MaxFrameId' => array( 'sql' => "(SELECT max(Frames.FrameId) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||||
"MinFrameDelta" => array( "sql" => "(SELECT min(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
'MinFrameDelta' => array( 'sql' => "(SELECT min(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||||
"MaxFrameDelta" => array( "sql" => "(SELECT max(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
'MaxFrameDelta' => array( 'sql' => "(SELECT max(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||||
//"Path" => array( "postFunc" => "getEventPath" ),
|
//'Path' => array( 'postFunc' => 'getEventPath' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"frame" => array(
|
'frame' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"table" => "Frames",
|
'table' => 'Frames',
|
||||||
"limit" => 1,
|
'limit' => 1,
|
||||||
"selector" => array( array( "table" => "Events", "join" => "Events.Id = Frames.EventId", "selector"=>"Events.Id" ), "Frames.FrameId" ),
|
'selector' => array( array( 'table' => 'Events', 'join' => "Events.Id = Frames.EventId", 'selector'=>"Events.Id" ), "Frames.FrameId" ),
|
||||||
"elements" => array(
|
'elements' => array(
|
||||||
//"Id" => array( "sql" => "Frames.FrameId" ),
|
//'Id' => array( 'sql' => "Frames.FrameId" ),
|
||||||
"FrameId" => true,
|
'FrameId' => true,
|
||||||
"EventId" => true,
|
'EventId' => true,
|
||||||
"Type" => true,
|
'Type' => true,
|
||||||
"TimeStamp" => true,
|
'TimeStamp' => true,
|
||||||
"TimeStampShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
'TimeStampShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||||
"Delta" => true,
|
'Delta' => true,
|
||||||
"Score" => true,
|
'Score' => true,
|
||||||
//"Image" => array( "postFunc" => "getFrameImage" ),
|
//'Image' => array( 'postFunc' => 'getFrameImage' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"frameimage" => array(
|
'frameimage' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"func" => "getFrameImage()"
|
'func' => "getFrameImage()"
|
||||||
),
|
),
|
||||||
"nearframe" => array(
|
'nearframe' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"func" => "getNearFrame()"
|
'func' => "getNearFrame()"
|
||||||
),
|
),
|
||||||
"nearevents" => array(
|
'nearevents' => array(
|
||||||
"permission" => "Events",
|
'permission' => 'Events',
|
||||||
"func" => "getNearEvents()"
|
'func' => "getNearEvents()"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ function collectData() {
|
||||||
$data = collectData();
|
$data = collectData();
|
||||||
|
|
||||||
if ( !isset($_REQUEST['layout']) ) {
|
if ( !isset($_REQUEST['layout']) ) {
|
||||||
$_REQUEST['layout'] = "json";
|
$_REQUEST['layout'] = 'json';
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( $_REQUEST['layout'] ) {
|
switch( $_REQUEST['layout'] ) {
|
||||||
|
@ -331,7 +331,7 @@ function getFrameImage() {
|
||||||
$frame = array();
|
$frame = array();
|
||||||
$frame['EventId'] = $eventId;
|
$frame['EventId'] = $eventId;
|
||||||
$frame['FrameId'] = $frameId;
|
$frame['FrameId'] = $frameId;
|
||||||
$frame['Type'] = "Virtual";
|
$frame['Type'] = 'Virtual';
|
||||||
}
|
}
|
||||||
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $frame['EventId'] ) );
|
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $frame['EventId'] ) );
|
||||||
$frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE );
|
$frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE );
|
||||||
|
@ -349,7 +349,7 @@ function getNearFrame() {
|
||||||
return( array() );
|
return( array() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$_REQUEST['entity'] = "frame";
|
$_REQUEST['entity'] = 'frame';
|
||||||
$_REQUEST['id'][1] = $nearFrameId;
|
$_REQUEST['id'][1] = $nearFrameId;
|
||||||
return( collectData() );
|
return( collectData() );
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ function getNearEvents() {
|
||||||
global $user, $sortColumn, $sortOrder;
|
global $user, $sortColumn, $sortOrder;
|
||||||
|
|
||||||
$eventId = $_REQUEST['id'];
|
$eventId = $_REQUEST['id'];
|
||||||
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $eventId ) );
|
$event = dbFetchOne( 'SELECT * FROM Events WHERE Id=?', NULL, array( $eventId ) );
|
||||||
|
|
||||||
parseFilter( $_REQUEST['filter'] );
|
parseFilter( $_REQUEST['filter'] );
|
||||||
parseSort();
|
parseSort();
|
||||||
|
@ -368,7 +368,7 @@ function getNearEvents() {
|
||||||
else
|
else
|
||||||
$midSql = '';
|
$midSql = '';
|
||||||
|
|
||||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
|
$sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn ".($sortOrder=='asc'?'desc':'asc') . ' LIMIT 2';
|
||||||
$result = dbQuery( $sql );
|
$result = dbQuery( $sql );
|
||||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||||
if ( $id == $eventId ) {
|
if ( $id == $eventId ) {
|
||||||
|
@ -377,7 +377,7 @@ function getNearEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
|
$sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn $sortOrder LIMIT 2";
|
||||||
$result = dbQuery( $sql );
|
$result = dbQuery( $sql );
|
||||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||||
if ( $id == $eventId ) {
|
if ( $id == $eventId ) {
|
||||||
|
|
|
@ -34,17 +34,13 @@ public function beforeFilter() {
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->Event->recursive = -1;
|
$this->Event->recursive = -1;
|
||||||
|
|
||||||
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
if (!empty($allowedMonitors))
|
|
||||||
{
|
|
||||||
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$mon_options='';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!empty($allowedMonitors)) {
|
||||||
|
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
||||||
|
} else {
|
||||||
|
$mon_options='';
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->request->params['named']) {
|
if ($this->request->params['named']) {
|
||||||
$this->FilterComponent = $this->Components->load('Filter');
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
|
@ -81,7 +77,6 @@ public function beforeFilter() {
|
||||||
//$thumbData = $this->createThumbnail($value['Event']['Id']);
|
//$thumbData = $this->createThumbnail($value['Event']['Id']);
|
||||||
$thumbData = "";
|
$thumbData = "";
|
||||||
$events[$key]['thumbData'] = $thumbData;
|
$events[$key]['thumbData'] = $thumbData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set(compact('events'));
|
$this->set(compact('events'));
|
||||||
|
|
|
@ -35,22 +35,24 @@ public function beforeFilter() {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->Monitor->recursive = 0;
|
$this->Monitor->recursive = 0;
|
||||||
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
|
||||||
|
|
||||||
if (!empty($allowedMonitors))
|
if ($this->request->params['named']) {
|
||||||
{
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
$options = array('conditions'=>array('Monitor.Id'=> $allowedMonitors));
|
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
||||||
|
} else {
|
||||||
|
$conditions = array();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
$options='';
|
if (!empty($allowedMonitors)) {
|
||||||
|
$conditions['Monitor.Id' ] = $allowedMonitors;
|
||||||
}
|
}
|
||||||
$monitors = $this->Monitor->find('all',$options);
|
$monitors = $this->Monitor->find('all',array('conditions'=>$conditions));
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'monitors' => $monitors,
|
'monitors' => $monitors,
|
||||||
'_serialize' => array('monitors')
|
'_serialize' => array('monitors')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,6 +14,7 @@ private $defaults = array(
|
||||||
'Width' => null,
|
'Width' => null,
|
||||||
'Height' => null,
|
'Height' => null,
|
||||||
'Orientation' => null,
|
'Orientation' => null,
|
||||||
|
'AnalysisFPSLimit' => null,
|
||||||
);
|
);
|
||||||
private $control_fields = array(
|
private $control_fields = array(
|
||||||
'Name' => '',
|
'Name' => '',
|
||||||
|
@ -301,6 +302,7 @@ private $control_fields = array(
|
||||||
$values[] = $this->{'Id'};
|
$values[] = $this->{'Id'};
|
||||||
dbQuery( $sql, $values );
|
dbQuery( $sql, $values );
|
||||||
} // end function save
|
} // end function save
|
||||||
|
|
||||||
function zmcControl( $mode=false ) {
|
function zmcControl( $mode=false ) {
|
||||||
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) {
|
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) {
|
||||||
if ( $this->{'Type'} == 'Local' ) {
|
if ( $this->{'Type'} == 'Local' ) {
|
||||||
|
@ -315,7 +317,8 @@ private $control_fields = array(
|
||||||
if ( $mode == 'restart' ) {
|
if ( $mode == 'restart' ) {
|
||||||
daemonControl( 'stop', 'zmc', $zmcArgs );
|
daemonControl( 'stop', 'zmc', $zmcArgs );
|
||||||
}
|
}
|
||||||
daemonControl( 'start', 'zmc', $zmcArgs );
|
if ( $this->{'Function'} != 'None' )
|
||||||
|
daemonControl( 'start', 'zmc', $zmcArgs );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$Server = $this->Server();
|
$Server = $this->Server();
|
||||||
|
|
|
@ -141,7 +141,7 @@ if ( 0 ) {
|
||||||
Warning("SQL: $sql: rows:" . $result->rowCount() );
|
Warning("SQL: $sql: rows:" . $result->rowCount() );
|
||||||
}
|
}
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . implode(',',$params) );
|
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') );
|
||||||
}
|
}
|
||||||
return( $result );
|
return( $result );
|
||||||
}
|
}
|
||||||
|
|
|
@ -339,11 +339,11 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function outputImageStream( $id, $src, $width, $height, $title='' ) {
|
function outputImageStream( $id, $src, $width, $height, $title='' ) {
|
||||||
echo getImageStream( $id, $src, $width, $height, $title );
|
echo getImageStreamHTML( $id, $src, $width, $height, $title );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getImageStream( $id, $src, $width, $height, $title='' ) {
|
function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
|
||||||
if ( canStreamIframe() ) {
|
if ( canStreamIframe() ) {
|
||||||
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
|
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
|
||||||
} else {
|
} else {
|
||||||
|
@ -1058,6 +1058,7 @@ function parseSort( $saveToSession=false, $querySep='&' ) {
|
||||||
break;
|
break;
|
||||||
case 'DateTime' :
|
case 'DateTime' :
|
||||||
$sortColumn = 'E.StartTime';
|
$sortColumn = 'E.StartTime';
|
||||||
|
$_REQUEST['sort_field'] = 'StartTime';
|
||||||
break;
|
break;
|
||||||
case 'DiskSpace' :
|
case 'DiskSpace' :
|
||||||
$sortColumn = 'E.DiskSpace';
|
$sortColumn = 'E.DiskSpace';
|
||||||
|
@ -1238,12 +1239,18 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
||||||
$value = dbEscape($value);
|
$value = dbEscape($value);
|
||||||
break;
|
break;
|
||||||
case 'DateTime':
|
case 'DateTime':
|
||||||
|
case 'StartDateTime':
|
||||||
|
case 'EndDateTime':
|
||||||
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
||||||
break;
|
break;
|
||||||
case 'Date':
|
case 'Date':
|
||||||
|
case 'StartDate':
|
||||||
|
case 'EndDate':
|
||||||
$value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
$value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
||||||
break;
|
break;
|
||||||
case 'Time':
|
case 'Time':
|
||||||
|
case 'StartTime':
|
||||||
|
case 'EndTime':
|
||||||
$value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
$value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
|
@ -1276,15 +1283,19 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
||||||
break;
|
break;
|
||||||
case 'IS' :
|
case 'IS' :
|
||||||
$filter['sql'] .= " IS $value";
|
$filter['sql'] .= " IS $value";
|
||||||
|
break;
|
||||||
case 'IS NOT' :
|
case 'IS NOT' :
|
||||||
$filter['sql'] .= " IS NOT $value";
|
$filter['sql'] .= " IS NOT $value";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Warning("Invalid operator in filter: " . $terms[$i]['op'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
|
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
|
||||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][op]\" value=\"".htmlspecialchars($terms[$i]['op'])."\"/>\n";
|
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][op]\" value=\"".htmlspecialchars($terms[$i]['op'])."\"/>\n";
|
||||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($terms[$i]['val']);
|
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($terms[$i]['val']);
|
||||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($terms[$i]['val'])."\"/>\n";
|
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($terms[$i]['val'])."\"/>\n";
|
||||||
}
|
} // end foreach term
|
||||||
if ( isset($terms[$i]['cbr']) ) {
|
if ( isset($terms[$i]['cbr']) ) {
|
||||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($terms[$i]['cbr']);
|
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($terms[$i]['cbr']);
|
||||||
$filter['sql'] .= ' '.str_repeat( ')', $terms[$i]['cbr'] ).' ';
|
$filter['sql'] .= ' '.str_repeat( ')', $terms[$i]['cbr'] ).' ';
|
||||||
|
@ -1299,13 +1310,14 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Please note that the filter is passed in by copy, so you need to use the return value from this function.
|
||||||
|
//
|
||||||
function addFilterTerm( $filter, $position, $term=false ) {
|
function addFilterTerm( $filter, $position, $term=false ) {
|
||||||
if ( $position < 0 )
|
if ( $position < 0 )
|
||||||
$position = 0;
|
$position = 0;
|
||||||
|
|
||||||
if ( ! isset( $filter['Query']['terms'] ) )
|
if ( ! isset( $filter['Query']['terms'] ) )
|
||||||
$filter['Query']['terms'] = array();
|
$filter['Query']['terms'] = array();
|
||||||
|
|
||||||
elseif( $position > count($filter['Query']['terms']) )
|
elseif( $position > count($filter['Query']['terms']) )
|
||||||
$position = count($filter['Query']['terms']);
|
$position = count($filter['Query']['terms']);
|
||||||
if ( $term && $position == 0 )
|
if ( $term && $position == 0 )
|
||||||
|
@ -2064,8 +2076,8 @@ function cache_bust( $file ) {
|
||||||
# Use the last modified timestamp to create a link that gets a different filename
|
# Use the last modified timestamp to create a link that gets a different filename
|
||||||
# To defeat caching. Should probably use md5 hash
|
# To defeat caching. Should probably use md5 hash
|
||||||
$parts = pathinfo($file);
|
$parts = pathinfo($file);
|
||||||
$cacheFile = '/cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
|
$cacheFile = 'cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
|
||||||
if ( file_exists( ZM_PATH_WEB.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.$cacheFile ) ) {
|
if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
|
||||||
return $cacheFile;
|
return $cacheFile;
|
||||||
} else {
|
} else {
|
||||||
Warning("Failed linking $file to $cacheFile");
|
Warning("Failed linking $file to $cacheFile");
|
||||||
|
@ -2138,18 +2150,17 @@ function validHtmlStr( $input ) {
|
||||||
function getStreamHTML( $monitor, $options = array() ) {
|
function getStreamHTML( $monitor, $options = array() ) {
|
||||||
|
|
||||||
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
|
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
|
||||||
|
//Warning("Scale to " . $options['scale'] );
|
||||||
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
|
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
|
||||||
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
|
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
|
||||||
} else {
|
} else {
|
||||||
if ( ! isset( $options['width'] ) ) {
|
# scale is empty or 100
|
||||||
$options['width'] = NULL;
|
# There may be a fixed width applied though, in which case we need to leave the height empty
|
||||||
} else if ( $options['width'] == 100 ) {
|
if ( ! ( isset($options['width']) and $options['width'] ) ) {
|
||||||
$options['width'] = $monitor->Width();
|
$options['width'] = $monitor->Width();
|
||||||
}
|
if ( ! ( isset($options['height']) and $options['height'] ) ) {
|
||||||
if ( ! isset( $options['height'] ) ) {
|
$options['height'] = $monitor->Height();
|
||||||
$options['height'] = NULL;
|
}
|
||||||
} else if ( $options['height'] == 100 ) {
|
|
||||||
$options['height'] = $monitor->Height();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ! isset($options['mode'] ) ) {
|
if ( ! isset($options['mode'] ) ) {
|
||||||
|
@ -2158,17 +2169,24 @@ function getStreamHTML( $monitor, $options = array() ) {
|
||||||
$options['maxfps'] = ZM_WEB_VIDEO_MAXFPS;
|
$options['maxfps'] = ZM_WEB_VIDEO_MAXFPS;
|
||||||
if ( $monitor->StreamReplayBuffer() )
|
if ( $monitor->StreamReplayBuffer() )
|
||||||
$options['buffer'] = $monitor->StreamReplayBuffer();
|
$options['buffer'] = $monitor->StreamReplayBuffer();
|
||||||
|
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
|
||||||
|
|
||||||
//FIXME, the width and height of the image need to be scaled.
|
//FIXME, the width and height of the image need to be scaled.
|
||||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||||
$streamSrc = $monitor->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$options['scale'], 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format' => ZM_MPEG_LIVE_FORMAT ) );
|
$streamSrc = $monitor->getStreamSrc( array(
|
||||||
return getVideoStream( 'liveStream'.$monitor->Id(), $streamSrc, $options, ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
|
'mode'=>'mpeg',
|
||||||
|
'scale'=>$options['scale'],
|
||||||
|
'bitrate'=>ZM_WEB_VIDEO_BITRATE,
|
||||||
|
'maxfps'=>ZM_WEB_VIDEO_MAXFPS,
|
||||||
|
'format' => ZM_MPEG_LIVE_FORMAT
|
||||||
|
) );
|
||||||
|
return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
|
||||||
} else if ( $options['mode'] == 'stream' and canStream() ) {
|
} else if ( $options['mode'] == 'stream' and canStream() ) {
|
||||||
$options['mode'] = 'jpeg';
|
$options['mode'] = 'jpeg';
|
||||||
$streamSrc = $monitor->getStreamSrc( $options );
|
$streamSrc = $monitor->getStreamSrc( $options );
|
||||||
|
|
||||||
if ( canStreamNative() )
|
if ( canStreamNative() )
|
||||||
return getImageStream( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
|
return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
|
||||||
elseif ( canStreamApplet() )
|
elseif ( canStreamApplet() )
|
||||||
// Helper, empty widths and heights really don't work.
|
// Helper, empty widths and heights really don't work.
|
||||||
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
|
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
|
||||||
|
|
|
@ -68,11 +68,7 @@ th {
|
||||||
color: #016A9d;
|
color: #016A9d;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:link {
|
a:link,
|
||||||
color: #7f7fb2;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
a:visited {
|
||||||
color: #7f7fb2;
|
color: #7f7fb2;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
|
@ -48,8 +48,10 @@ function xhtmlHeaders( $file, $title ) {
|
||||||
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
|
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
|
||||||
<?php
|
<?php
|
||||||
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
||||||
echo "<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
|
echo "
|
||||||
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
|
<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>
|
||||||
|
<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>
|
||||||
|
";
|
||||||
} else {
|
} else {
|
||||||
echo '
|
echo '
|
||||||
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
|
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
var popupOptions = "resizable,scrollbars,status=no,toolbar=yes";
|
var popupOptions = "resizable,scrollbars,status=no,toolbar=yes";
|
||||||
|
|
||||||
function checkSize() {
|
function checkSize() {
|
||||||
|
if ( 0 ) {
|
||||||
if (window.outerHeight) {
|
if (window.outerHeight) {
|
||||||
var w = window.outerWidth;
|
var w = window.outerWidth;
|
||||||
var prevW = w;
|
var prevW = w;
|
||||||
|
@ -37,6 +38,7 @@ function checkSize() {
|
||||||
if (w != prevW || h != prevH)
|
if (w != prevW || h != prevH)
|
||||||
window.resizeTo(w, h);
|
window.resizeTo(w, h);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
|
|
@ -118,7 +118,7 @@ $groupSql = Group::get_group_sql( $group_id );
|
||||||
?>
|
?>
|
||||||
</span>
|
</span>
|
||||||
<?php
|
<?php
|
||||||
if ( count($ServersById) > 0 ) {
|
if ( count($ServersById) > 1 ) {
|
||||||
?>
|
?>
|
||||||
<span class="ServerFilter"><label><?php echo translate('Server')?>:</label>
|
<span class="ServerFilter"><label><?php echo translate('Server')?>:</label>
|
||||||
<?php
|
<?php
|
||||||
|
@ -127,7 +127,7 @@ echo htmlSelect( 'ServerFilter', array(''=>'All')+$ServersById, (isset($_SESSION
|
||||||
</span>
|
</span>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
if ( count($StorageById) > 0 ) { ?>
|
if ( count($StorageById) > 1 ) { ?>
|
||||||
<span class="StorageFilter"><label><?php echo translate('Storage')?>:</label>
|
<span class="StorageFilter"><label><?php echo translate('Storage')?>:</label>
|
||||||
<?php
|
<?php
|
||||||
echo htmlSelect( 'StorageFilter', array(''=>'All')+$StorageById, (isset($_SESSION['StorageFilter'])?$_SESSION['StorageFilter']:''), array('onchange'=>'changeFilter(this);') );
|
echo htmlSelect( 'StorageFilter', array(''=>'All')+$StorageById, (isset($_SESSION['StorageFilter'])?$_SESSION['StorageFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<input type="hidden" name="newMonitor[Method]" value="<?php echo validHtmlStr($monitor->Method()) ?>"/>
|
||||||
|
<tr><td><?php echo translate('HostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('Port') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('Path') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||||
|
<input type="hidden" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/>
|
||||||
|
<input type="hidden" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/>
|
||||||
|
<input type="hidden" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/>
|
||||||
|
<tr><td><?php echo translate('TargetColorspace') ?></td><td><select name="newMonitor[Colours]"><?php foreach ( $Colours as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Colours()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||||
|
<tr><td><?php echo translate('CaptureWidth') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('CaptureHeight') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('PreserveAspect') ?></td><td><input type="checkbox" name="preserveAspectRatio" value="1"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('Orientation') ?></td><td><?php echo htmlselect( 'newMonitor[Orientation]', $orientations, $monitor->Orientation() );?></td></tr>
|
||||||
|
<input type="hidden" name="newMonitor[Deinterlacing]" value="<?php echo validHtmlStr($monitor->Deinterlacing()) ?>"/>
|
||||||
|
<input type="hidden" name="newMonitor[RTSPDescribe]" value="<?php echo validHtmlStr($monitor->RTSPDescribe()) ?>"/>
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
//
|
||||||
|
// ZoneMinder web function view file, $Date$, $Revision$
|
||||||
|
// Copyright (C) 2017 ZoneMinder LLC
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
if ( !canEdit( 'Monitors' ) ) {
|
||||||
|
$view = 'error';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$focusWindow = true;
|
||||||
|
$navbar = getNavBarHTML();
|
||||||
|
|
||||||
|
xhtmlHeaders(__FILE__, translate('AddMonitors'));
|
||||||
|
?>
|
||||||
|
<body>
|
||||||
|
<div id="page">
|
||||||
|
<?php echo $navbar ?>
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||||
|
<div style="position:relative;">
|
||||||
|
<div id="results" style="position: absolute; top:0; right: 0; width: 50%; height: 100%;">
|
||||||
|
<fieldset><legend>Results</legend>
|
||||||
|
<div id="url_results">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div style="width:50%;position: absolute; top:0; left: 0;height: 100%;">
|
||||||
|
<fieldset><legend>Enter by IP or URL</legend>
|
||||||
|
<!--<input type="text" name="newMonitor[Name]" />-->
|
||||||
|
<input type="url" name="newMonitor[Url]" oninput="probe(this);"/>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset><legend>Import CSV Spreadsheet</legend>
|
||||||
|
Spreadsheet should have the following format:<br/>
|
||||||
|
<table class="major">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th>Group</th>
|
||||||
|
</tr>
|
||||||
|
<tr title="Example Data">
|
||||||
|
<td>Example Name MN1-30 INQ37.01</td>
|
||||||
|
<td>http://10.34.152.20:2001/?action=stream</td>
|
||||||
|
<td>MN1</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
Defaults to apply to each monitor:<br/>
|
||||||
|
<table><tr><th>Setting</th><th>Value</th></tr>
|
||||||
|
<tr><td><?php echo translate('Function') ?></td><td>
|
||||||
|
<?php
|
||||||
|
$options = array();
|
||||||
|
foreach ( getEnumValues('Monitors', 'Function') as $opt ) {
|
||||||
|
$options[$opt] = translate('Fn'.$opt);
|
||||||
|
}
|
||||||
|
echo htmlSelect( 'newMonitor[Function]', $options, 'Record' );
|
||||||
|
?>
|
||||||
|
</td></tr>
|
||||||
|
<?php
|
||||||
|
$servers = Server::find_all();
|
||||||
|
$ServersById = array();
|
||||||
|
foreach ( $servers as $S ) {
|
||||||
|
$ServersById[$S->Id()] = $S;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( count($ServersById) > 0 ) { ?>
|
||||||
|
<tr class="Server"><td><?php echo translate('Server')?></td><td>
|
||||||
|
<?php echo htmlSelect( 'newMonitor[ServerId]', array(''=>'Auto')+$ServersById, '' ); ?>
|
||||||
|
</td></tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
$storage_areas = Storage::find_all();
|
||||||
|
$StorageById = array();
|
||||||
|
foreach ( $storage_areas as $S ) {
|
||||||
|
$StorageById[$S->Id()] = $S;
|
||||||
|
}
|
||||||
|
if ( count($StorageById) > 0 ) {
|
||||||
|
?>
|
||||||
|
<tr class="Storage"><td><?php echo translate('Storage')?></td><td>
|
||||||
|
<?php echo htmlSelect( 'newMonitor[StorageId]', array(''=>'All')+$StorageById, 1 ); ?>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<input type="file" name="import_file" id="import_file"/>
|
||||||
|
<input type="button" value="Import" onclick="import_csv(this.form);"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php xhtmlFooter() ?>
|
|
@ -25,7 +25,7 @@ $eventCounts = array(
|
||||||
array(
|
array(
|
||||||
'title' => translate('Events'),
|
'title' => translate('Events'),
|
||||||
'filter' => array(
|
'filter' => array(
|
||||||
'Query' => array (
|
'Query' => array(
|
||||||
'terms' => array()
|
'terms' => array()
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -114,7 +114,11 @@ for ( $i = 0; $i < count($displayMonitors); $i++ ) {
|
||||||
|
|
||||||
$counts = array();
|
$counts = array();
|
||||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
$filter = addFilterTerm(
|
||||||
|
$eventCounts[$j]['filter'],
|
||||||
|
count($eventCounts[$j]['filter']['Query']['terms']),
|
||||||
|
array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] )
|
||||||
|
);
|
||||||
parseFilter( $filter );
|
parseFilter( $filter );
|
||||||
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) AS EventCount$j, SUM(if(1".$filter['sql'].",DiskSpace,NULL)) As DiskSpace$j";
|
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) AS EventCount$j, SUM(if(1".$filter['sql'].",DiskSpace,NULL)) As DiskSpace$j";
|
||||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||||
|
@ -122,11 +126,12 @@ for ( $i = 0; $i < count($displayMonitors); $i++ ) {
|
||||||
$sql = 'SELECT '.join($counts,', ').' FROM Events as E where MonitorId = ?';
|
$sql = 'SELECT '.join($counts,', ').' FROM Events as E where MonitorId = ?';
|
||||||
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
||||||
if ( $counts )
|
if ( $counts )
|
||||||
$displayMonitors[$i] = $monitor = array_merge( $monitor, $counts );
|
$monitor = array_merge( $monitor, $counts );
|
||||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||||
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
||||||
}
|
}
|
||||||
}
|
unset($monitor);
|
||||||
|
} // end foreach display monitor
|
||||||
$cycleWidth = $maxWidth;
|
$cycleWidth = $maxWidth;
|
||||||
$cycleHeight = $maxHeight;
|
$cycleHeight = $maxHeight;
|
||||||
|
|
||||||
|
@ -202,11 +207,11 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
<?php
|
<?php
|
||||||
if ( ZM_WEB_ID_ON_CONSOLE ) {
|
if ( ZM_WEB_ID_ON_CONSOLE ) {
|
||||||
?>
|
?>
|
||||||
<td class="colId"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Id'], $running && ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
<td class="colId"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Id'], ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<td class="colName"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
<td class="colName"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
||||||
<td class="colFunction"><?php echo makePopupLink( '?view=function&mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?></td>
|
<td class="colFunction"><?php echo makePopupLink( '?view=function&mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?></td>
|
||||||
<?php
|
<?php
|
||||||
if ( count($servers) ) { ?>
|
if ( count($servers) ) { ?>
|
||||||
|
@ -262,8 +267,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||||
<td class="colId"><?php echo count($displayMonitors) ?></td>
|
<td class="colId"><?php echo count($displayMonitors) ?></td>
|
||||||
<td class="colLeftButtons" colspan="<?php echo $left_columns -1?>">
|
<td class="colLeftButtons" colspan="<?php echo $left_columns -1?>">
|
||||||
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
||||||
<input type="button" value="<?php echo translate('AddNewMonitor') ?>" onclick="location.href='index.php?view=monitor';"/>
|
<input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
|
||||||
<!--<input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>-->
|
|
||||||
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
|
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
|
||||||
<?php echo makePopupButton( '?view=filter&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
|
<?php echo makePopupButton( '?view=filter&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
|
||||||
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
|
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
|
||||||
|
|
|
@ -84,6 +84,7 @@ if ( !empty($page) ) {
|
||||||
$eventsSql .= ' limit 0, '.$limit;
|
$eventsSql .= ' limit 0, '.$limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( 0 ) {
|
||||||
$maxWidth = 0;
|
$maxWidth = 0;
|
||||||
$maxHeight = 0;
|
$maxHeight = 0;
|
||||||
$archived = false;
|
$archived = false;
|
||||||
|
@ -103,6 +104,7 @@ foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
|
||||||
else
|
else
|
||||||
$unarchived = true;
|
$unarchived = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$maxShortcuts = 5;
|
$maxShortcuts = 5;
|
||||||
$pagination = getPagination( $pages, $page, $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$limit );
|
$pagination = getPagination( $pages, $page, $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$limit );
|
||||||
|
@ -160,7 +162,12 @@ if ( $pagination ) {
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$disk_space_total = 0;
|
$disk_space_total = 0;
|
||||||
|
|
||||||
foreach ( $events as $event ) {
|
$results = dbQuery( $eventsSql );
|
||||||
|
while ( $event_row = dbFetchNext( $results ) ) {
|
||||||
|
$event = new Event( $event_row );
|
||||||
|
#foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
|
||||||
|
#$events[] = $event = new Event( $event_row );
|
||||||
|
#foreach ( $events as $event ) {
|
||||||
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
|
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -87,9 +87,11 @@ function get_children($Group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$kids = get_children($newGroup);
|
$kids = get_children($newGroup);
|
||||||
$kids[] = $newGroup->Id();
|
if ( $newGroup->Id() )
|
||||||
|
$kids[] = $newGroup->Id();
|
||||||
|
$sql = 'SELECT Id,Name from Groups'.(count($kids)?' WHERE Id NOT IN ('.implode(',',array_map(function(){return '?';}, $kids )).')' : '').' ORDER BY Name';
|
||||||
$options = array(''=>'None');
|
$options = array(''=>'None');
|
||||||
foreach ( dbFetchAll( 'SELECT Id,Name from Groups WHERE Id NOT IN ('.implode(',',array_map(function(){return '?';}, $kids )).') ORDER BY Name', null, $kids ) as $option ) {
|
foreach ( dbFetchAll( $sql, null, $kids ) as $option ) {
|
||||||
$options[$option['Id']] = $option['Name'];
|
$options[$option['Id']] = $option['Name'];
|
||||||
}
|
}
|
||||||
echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' ));
|
echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' ));
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
var probeReq = new Request.JSON( { url:thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getProbeResponse } );
|
||||||
|
|
||||||
|
function probe( url_e ) {
|
||||||
|
probeReq.send( "request=add_monitors&action=probe&url="+url_e.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
var ProbeResults;
|
||||||
|
|
||||||
|
function getProbeResponse( respObj, respText ) {
|
||||||
|
if ( checkStreamForErrors( "getProbeResponse", respObj ) )
|
||||||
|
return;
|
||||||
|
//alert(respText);
|
||||||
|
|
||||||
|
if ( respObj.Streams ) {
|
||||||
|
parseStreams( respObj.Streams );
|
||||||
|
} else {
|
||||||
|
alert("No Streams");
|
||||||
|
}
|
||||||
|
} // end function getProbeResponse
|
||||||
|
|
||||||
|
function parseStreams( Streams ) {
|
||||||
|
ProbeResults = Array();
|
||||||
|
|
||||||
|
var results_div = $j('#url_results')[0];
|
||||||
|
if ( ! results_div ) {
|
||||||
|
console.log("No results div found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
results_div.innerHTML = '';
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
for( i in Streams ) {
|
||||||
|
var stream = Streams[i];
|
||||||
|
if ( stream.url ) {
|
||||||
|
html += '<p>'+stream.url;
|
||||||
|
if ( stream.Monitor.Id ) {
|
||||||
|
html += ' is already entered into the system by Monitor ' + stream.Monitor.Id + ' ' + stream.Monitor.Name + '<br/>';
|
||||||
|
html += '<input type="button" value="Edit" onclick="addMonitor(\''+stream.url+'\');"/>';
|
||||||
|
} else {
|
||||||
|
html += '<input type="button" value="Add" onclick="addMonitor(\''+stream.url+'\');"/>';
|
||||||
|
}
|
||||||
|
html += '</p>';
|
||||||
|
ProbeResults[stream.url] = stream;
|
||||||
|
} else {
|
||||||
|
//console.log(stream);
|
||||||
|
}
|
||||||
|
} // end for eah Stream
|
||||||
|
|
||||||
|
results_div.innerHTML = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMonitor(url) {
|
||||||
|
if ( ! ProbeResults[url] ) {
|
||||||
|
alert("Monitor for url " + url + " not found in probe results." );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var Stream = ProbeResults[url];
|
||||||
|
var Monitor = Stream.Monitor;
|
||||||
|
|
||||||
|
popup_url = '?view=monitor&newMonitor[Path]='+url;
|
||||||
|
keys = Object.keys( Monitor );
|
||||||
|
for ( i in Monitor ) {
|
||||||
|
if ( ! Monitor[i] )
|
||||||
|
continue;
|
||||||
|
if ( Monitor[i] == 'null' )
|
||||||
|
Monitor[i]='';
|
||||||
|
popup_url += '&newMonitor['+i+']='+Monitor[i];
|
||||||
|
}
|
||||||
|
createPopup( popup_url, 'zmMonitor0', 'monitor' );
|
||||||
|
}
|
||||||
|
|
||||||
|
function import_csv( form ) {
|
||||||
|
var formData = new FormData( form );
|
||||||
|
console.log(formData);
|
||||||
|
//formData.append('file', $('#file')[0].files[0]);
|
||||||
|
|
||||||
|
$j.ajax({
|
||||||
|
url : thisUrl+"?request=add_monitors&action=import",
|
||||||
|
type : 'POST',
|
||||||
|
data : formData,
|
||||||
|
processData: false, // tell jQuery not to process the data
|
||||||
|
contentType: false, // tell jQuery not to set contentType
|
||||||
|
success : function(data) {
|
||||||
|
var json = JSON.parse(data);
|
||||||
|
parseStreams( json.Streams );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -97,7 +97,7 @@ function validateForm( form ) {
|
||||||
errors[errors.length] = "<?php echo translate('BadImageBufferCount') ?>";
|
errors[errors.length] = "<?php echo translate('BadImageBufferCount') ?>";
|
||||||
if ( !form.elements['newMonitor[WarmupCount]'].value || !(parseInt(form.elements['newMonitor[WarmupCount]'].value) >= 0 ) )
|
if ( !form.elements['newMonitor[WarmupCount]'].value || !(parseInt(form.elements['newMonitor[WarmupCount]'].value) >= 0 ) )
|
||||||
errors[errors.length] = "<?php echo translate('BadWarmupCount') ?>";
|
errors[errors.length] = "<?php echo translate('BadWarmupCount') ?>";
|
||||||
if ( !form.elements['newMonitor[PreEventCount]'].value || !(parseInt(form.elements['newMonitor[PreEventCount]'].value) > 0 ) || (parseInt(form.elements['newMonitor[PreEventCount]'].value) > parseInt(form.elements['newMonitor[ImageBufferCount]'].value)) )
|
if ( !form.elements['newMonitor[PreEventCount]'].value || !(parseInt(form.elements['newMonitor[PreEventCount]'].value) >= 0 ) || (parseInt(form.elements['newMonitor[PreEventCount]'].value) > parseInt(form.elements['newMonitor[ImageBufferCount]'].value)) )
|
||||||
errors[errors.length] = "<?php echo translate('BadPreEventCount') ?>";
|
errors[errors.length] = "<?php echo translate('BadPreEventCount') ?>";
|
||||||
if ( !form.elements['newMonitor[PostEventCount]'].value || !(parseInt(form.elements['newMonitor[PostEventCount]'].value) >= 0 ) )
|
if ( !form.elements['newMonitor[PostEventCount]'].value || !(parseInt(form.elements['newMonitor[PostEventCount]'].value) >= 0 ) )
|
||||||
errors[errors.length] = "<?php echo translate('BadPostEventCount') ?>";
|
errors[errors.length] = "<?php echo translate('BadPostEventCount') ?>";
|
||||||
|
|
|
@ -7,8 +7,8 @@ function Monitor( monitorData ) {
|
||||||
this.status = null;
|
this.status = null;
|
||||||
this.alarmState = STATE_IDLE;
|
this.alarmState = STATE_IDLE;
|
||||||
this.lastAlarmState = STATE_IDLE;
|
this.lastAlarmState = STATE_IDLE;
|
||||||
this.streamCmdParms = "view=request&request=stream&connkey="+this.connKey;
|
this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey;
|
||||||
this.onclick=monitorData.onclick;
|
this.onclick = monitorData.onclick;
|
||||||
if ( auth_hash )
|
if ( auth_hash )
|
||||||
this.streamCmdParms += '&auth='+auth_hash;
|
this.streamCmdParms += '&auth='+auth_hash;
|
||||||
this.streamCmdTimer = null;
|
this.streamCmdTimer = null;
|
||||||
|
@ -34,6 +34,7 @@ function Monitor( monitorData ) {
|
||||||
this.streamCmdTimer = clearTimeout( this.streamCmdTimer );
|
this.streamCmdTimer = clearTimeout( this.streamCmdTimer );
|
||||||
|
|
||||||
var stream = $j('#liveStream'+this.id)[0];
|
var stream = $j('#liveStream'+this.id)[0];
|
||||||
|
|
||||||
if ( respObj.result == 'Ok' ) {
|
if ( respObj.result == 'Ok' ) {
|
||||||
this.status = respObj.status;
|
this.status = respObj.status;
|
||||||
this.alarmState = this.status.state;
|
this.alarmState = this.status.state;
|
||||||
|
@ -90,27 +91,51 @@ function Monitor( monitorData ) {
|
||||||
console.error( respObj.message );
|
console.error( respObj.message );
|
||||||
// Try to reload the image stream.
|
// Try to reload the image stream.
|
||||||
if ( stream ) {
|
if ( stream ) {
|
||||||
|
if ( stream.src ) {
|
||||||
console.log('Reloading stream: ' + stream.src );
|
console.log('Reloading stream: ' + stream.src );
|
||||||
stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||||
|
} else {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log( 'No stream to reload?' );
|
console.log( 'No stream to reload?' );
|
||||||
}
|
}
|
||||||
} // end if Ok or not
|
} // end if Ok or not
|
||||||
var streamCmdTimeout = statusRefreshTimeout;
|
var streamCmdTimeout = statusRefreshTimeout;
|
||||||
if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT )
|
// The idea here is if we are alarmed, do updates faster. However, there is a timeout in the php side which isn't getting modified, so this may cause a problem. Also the server may only be able to update so fast.
|
||||||
streamCmdTimeout = streamCmdTimeout/5;
|
//if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ) {
|
||||||
|
//streamCmdTimeout = streamCmdTimeout/5;
|
||||||
|
//}
|
||||||
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
|
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
|
||||||
this.lastAlarmState = this.alarmState;
|
this.lastAlarmState = this.alarmState;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.streamCmdQuery = function( resent ) {
|
this.streamCmdQuery = function( resent ) {
|
||||||
//if ( resent )
|
if ( resent )
|
||||||
//console.log( this.connKey+": Resending" );
|
console.log( this.connKey+": Resending" );
|
||||||
//this.streamCmdReq.cancel();
|
//this.streamCmdReq.cancel();
|
||||||
this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY );
|
this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY );
|
||||||
};
|
};
|
||||||
|
this.onError = function( text, error ) {
|
||||||
|
console.log('onerror: ' + text + ' error:'+error);
|
||||||
|
};
|
||||||
|
this.onFailure = function( xhr ) {
|
||||||
|
console.log('onFailure: ' );
|
||||||
|
console.log(xhr );
|
||||||
|
// Requeue
|
||||||
|
var streamCmdTimeout = statusRefreshTimeout;
|
||||||
|
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
|
||||||
|
};
|
||||||
|
|
||||||
this.streamCmdReq = new Request.JSON( { url: this.server_url, method: 'get', timeout: 1000+AJAX_TIMEOUT, onSuccess: this.getStreamCmdResponse.bind( this ), onTimeout: this.streamCmdQuery.bind( this, true ), link: 'cancel' } );
|
this.streamCmdReq = new Request.JSON( {
|
||||||
|
url: this.server_url,
|
||||||
|
method: 'get',
|
||||||
|
timeout: 1000+AJAX_TIMEOUT,
|
||||||
|
onSuccess: this.getStreamCmdResponse.bind( this ),
|
||||||
|
onTimeout: this.streamCmdQuery.bind( this, true ),
|
||||||
|
onError: this.onError.bind(this),
|
||||||
|
onFailure: this.onFailure.bind(this),
|
||||||
|
link: 'cancel'
|
||||||
|
} );
|
||||||
|
|
||||||
requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq );
|
requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq );
|
||||||
}
|
}
|
||||||
|
@ -227,17 +252,37 @@ function changeSize() {
|
||||||
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
||||||
Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } );
|
Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } );
|
||||||
Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } );
|
Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } );
|
||||||
|
selectLayout('#zmMontageLayout');
|
||||||
} // end function changeSize()
|
} // end function changeSize()
|
||||||
|
|
||||||
function changeScale() {
|
function changeScale() {
|
||||||
var scale = $('scale').get('value');
|
var scale = $('scale').get('value');
|
||||||
|
$('width').set('value', '');
|
||||||
|
$('height').set('value', '');
|
||||||
|
Cookie.write( 'zmMontageScale', scale, { duration: 10*365 } );
|
||||||
|
Cookie.write( 'zmMontageWidth', '', { duration: 10*365 } );
|
||||||
|
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } );
|
||||||
|
if ( ! scale ) {
|
||||||
|
selectLayout('#zmMontageLayout');
|
||||||
|
return;
|
||||||
|
}
|
||||||
for ( var x = 0; x < monitors.length; x++ ) {
|
for ( var x = 0; x < monitors.length; x++ ) {
|
||||||
var monitor = monitors[x];
|
var monitor = monitors[x];
|
||||||
var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE;
|
var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE;
|
||||||
var newHeight = ( monitorData[x].height * scale ) / SCALE_BASE;
|
var newHeight = ( monitorData[x].height * scale ) / SCALE_BASE;
|
||||||
|
|
||||||
|
// Scale the frame
|
||||||
|
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||||
|
if ( ! monitor_frame ) {
|
||||||
|
console.log("Error finding frame for " + monitor.id );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( width )
|
||||||
|
monitor_frame.css('width',width+'px');
|
||||||
|
if ( height )
|
||||||
|
monitor_frame.css('height',height+'px');
|
||||||
/*Stream could be an applet so can't use moo tools*/
|
/*Stream could be an applet so can't use moo tools*/
|
||||||
var streamImg = document.getElementById( 'liveStream'+monitor.id );
|
var streamImg = $j('#liveStream'+monitor.id )[0];
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
if ( streamImg.nodeName == 'IMG' ) {
|
if ( streamImg.nodeName == 'IMG' ) {
|
||||||
var src = streamImg.src;
|
var src = streamImg.src;
|
||||||
|
@ -258,11 +303,6 @@ function changeScale() {
|
||||||
zonesSVG.style.height = newHeight + "px";
|
zonesSVG.style.height = newHeight + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('width').set('value', '');
|
|
||||||
$('height').set('value', '');
|
|
||||||
Cookie.write( 'zmMontageScale', scale, { duration: 10*365 } );
|
|
||||||
Cookie.write( 'zmMontageWidth', '', { duration: 10*365 } );
|
|
||||||
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toGrid(value) {
|
function toGrid(value) {
|
||||||
|
|
|
@ -827,7 +827,7 @@ switch ( $tab ) {
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
} else if ( $monitor->Type() == 'NVSocket' ) {
|
} else if ( $monitor->Type() == 'NVSocket' ) {
|
||||||
include('monitor_source_nvsocket.php');
|
include('_monitor_source_nvsocket.php');
|
||||||
} else if ( $monitor->Type() == 'Remote' ) {
|
} else if ( $monitor->Type() == 'Remote' ) {
|
||||||
?>
|
?>
|
||||||
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
|
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
|
||||||
|
|
|
@ -41,6 +41,10 @@ if ( ! empty($_REQUEST['eid'] ) ) {
|
||||||
$Event = new Event( $_REQUEST['eid'] );
|
$Event = new Event( $_REQUEST['eid'] );
|
||||||
$path = $Event->Path().'/'.$Event->DefaultVideo();
|
$path = $Event->Path().'/'.$Event->DefaultVideo();
|
||||||
Logger::Debug("Path: $path");
|
Logger::Debug("Path: $path");
|
||||||
|
} else if ( ! empty($_REQUEST['event_id'] ) ) {
|
||||||
|
$Event = new Event( $_REQUEST['event_id'] );
|
||||||
|
$path = $Event->Path().'/'.$Event->DefaultVideo();
|
||||||
|
Logger::Debug("Path: $path");
|
||||||
} else {
|
} else {
|
||||||
$errorText = 'No video path';
|
$errorText = 'No video path';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue