Merge remote-tracking branch 'upstream/master'

pull/2570/head
aktarus82 2019-04-09 16:14:34 +02:00
commit eba52023f9
25 changed files with 694 additions and 577 deletions

View File

@ -639,7 +639,7 @@ CREATE TABLE `Users` (
`Devices` enum('None','View','Edit') NOT NULL default 'None',
`System` enum('None','View','Edit') NOT NULL default 'None',
`MaxBandwidth` varchar(16),
`MonitorIds` tinytext,
`MonitorIds` text,
PRIMARY KEY (`Id`),
UNIQUE KEY `UC_Username` (`Username`)
) ENGINE=@ZM_MYSQL_ENGINE@;

1
db/zm_update-1.33.6.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE Users MODIFY MonitorIds text;

View File

@ -23,7 +23,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.33.4
Version: 1.33.6
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@ -410,11 +410,14 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%changelog
* Sun Apr 07 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.6-1
- Bump to 1.33.6 Development
* Sat Mar 30 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.4-1
- Bump tp 1.33.4 Development
- Bump to 1.33.4 Development
* Tue Dec 11 2018 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.0-1
- Bump tp 1.33.0 Development
- Bump to 1.33.0 Development
* Sat Dec 08 2018 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.32.3-1
- 1.32.3 Release

View File

@ -67,7 +67,7 @@ sub AUTOLOAD {
if ( exists($self->{$name}) ) {
return $self->{$name};
}
Error("Can't access $name member of object of class $class");
Error("Can't access $name $AUTOLOAD member of object of class $class");
}
sub getKey {

View File

@ -84,7 +84,7 @@ sub open
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new(keep_alive => 1);
$self->{ua}->agent("ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION);
$self->{ua}->agent("ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'closed';
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);

View File

@ -40,7 +40,7 @@ sub open
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION );
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'closed';
Debug( "sendCmd credentials control address:'".$ADDRESS
."' realm:'" . $REALM

View File

@ -45,7 +45,7 @@ sub open {
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent('ZoneMinder Control Agent/'.$ZoneMinder::Base::ZM_VERSION);
$self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'closed';
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
Debug ( "sendCmd credentials control address:'".$ADDRESS
@ -120,6 +120,7 @@ sub sendCmd {
Debug('sendCmd command: ' . $url);
if ( $res->is_success ) {
Debug($res->content);
return !undef;
}
Error("Error check failed: '".$res->status_line()."' cmd:'".$cmd."'");
@ -155,6 +156,7 @@ sub sendCmdPost {
Debug("sendCmdPost credentials control to: $PROTOCOL$ADDRESS$url realm:'" . $REALM . "' username:'" . $USERNAME . "' password:'".$PASSWORD."'");
if ( $res->is_success ) {
Debug($res->content);
return !undef;
}
Error("sendCmdPost Error check failed: '".$res->status_line()."' cmd:");

View File

@ -30,7 +30,7 @@ use autouse 'Pod::Usage'=>qw(pod2usage);
use POSIX qw/strftime EPIPE/;
use Socket;
#use Data::Dumper;
use Module::Load::Conditional qw{can_load};;
use Module::Load::Conditional qw{can_load};
use constant MAX_CONNECT_DELAY => 15;
use constant MAX_COMMAND_WAIT => 1800;
@ -43,7 +43,7 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit();
my $arg_string = join( " ", @ARGV );
my $arg_string = join(' ', @ARGV);
my $id;
my %options;
@ -64,22 +64,46 @@ GetOptions(
) or pod2usage(-exitstatus => -1);
if ( !$id ) {
print( STDERR "Please give a valid monitor id\n" );
print(STDERR "Please give a valid monitor id\n");
pod2usage(-exitstatus => -1);
}
( $id ) = $id =~ /^(\w+)$/;
Debug("zmcontrol: arg string: $arg_string");
my $sock_file = $Config{ZM_PATH_SOCKS}.'/zmcontrol-'.$id.'.sock';
Debug("zmcontrol: arg string: $arg_string sock file $sock_file");
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
or Fatal("Can't open socket: $!");
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
my $saddr = sockaddr_un($sock_file);
my $server_up = connect(CLIENT, $saddr);
if ( !$server_up ) {
if ( $options{command} ) {
# Have a command, so we are the client, connect to the server and send it.
my $tries = 10;
my $server_up;
while ( $tries and ! ( $server_up = connect(CLIENT, $saddr) ) ) {
Debug("Failed to connect to $server_up at $sock_file");
runCommand("zmdc.pl start zmcontrol.pl --id=$id");
sleep 1;
$tries -= 1;
}
if ( $server_up ) {
# The server is there, connect to it
#print( "Writing commands\n" );
CLIENT->autoflush();
if ( $options{command} ) {
my $message = jsonEncode(\%options);
print(CLIENT $message);
}
shutdown(CLIENT, 1);
} else {
Error("Unable to connect to zmcontrol server at $sock_file");
}
} else {
# The server isn't there
my $monitor = zmDbGetMonitorAndControl($id);
if ( !$monitor ) {
@ -113,99 +137,72 @@ if ( !$server_up ) {
Fatal("Can't load ZoneMinder::Control::$protocol\n$Module::Load::Conditional::ERROR");
}
if ( my $cpid = fork() ) {
logReinit();
Info("Control server $id/$protocol starting at "
.strftime('%y/%m/%d %H:%M:%S', localtime())
);
# Parent process just sleep and fall through
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
or die("Can't open socket: $!");
my $attempts = 0;
while ( !connect(CLIENT, $saddr) ) {
$attempts++;
Fatal("Can't connect: $! after $attempts attempts to $sock_file") if $attempts > MAX_CONNECT_DELAY;
sleep(1);
}
} elsif ( defined($cpid) ) {
close(STDOUT);
close(STDERR);
$0 = $0." --id=$id";
setpgrp();
my $control = "ZoneMinder::Control::$protocol"->new($id);
my $control_key = $control->getKey();
$control->loadMonitor();
logReinit();
$control->open();
Info("Control server $id/$protocol starting at "
.strftime('%y/%m/%d %H:%M:%S', localtime())
);
$0 = $0." --id $id";
my $control = "ZoneMinder::Control::$protocol"->new($id);
my $control_key = $control->getKey();
$control->loadMonitor();
$control->open();
socket(SERVER, PF_UNIX, SOCK_STREAM, 0)
or Fatal("Can't open socket: $!");
unlink($sock_file);
bind(SERVER, $saddr) or Fatal("Can't bind: $!");
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
my $rin = '';
vec( $rin, fileno(SERVER), 1 ) = 1;
my $win = $rin;
my $ein = $win;
my $timeout = MAX_COMMAND_WAIT;
while( 1 ) {
my $nfound = select(my $rout = $rin, undef, undef, $timeout);
if ( $nfound > 0 ) {
if ( vec( $rout, fileno(SERVER), 1 ) ) {
my $paddr = accept(CLIENT, SERVER);
my $message = <CLIENT>;
next if !$message;
my $params = jsonDecode($message);
#Debug( Dumper( $params ) );
my $command = $params->{command};
close( CLIENT );
if ( $command eq 'quit' ) {
last;
}
$control->$command($params);
} else {
Fatal('Bogus descriptor');
}
} elsif ( $nfound < 0 ) {
if ( $! == EPIPE ) {
Error("Can't select: $!");
} else {
Fatal("Can't select: $!");
}
} else {
#print( "Select timed out\n" );
last;
}
} # end while forever
Info("Control server $id/$protocol exiting");
unlink($sock_file);
$control->close();
exit(0);
} else {
Fatal("Can't fork: $!");
# If we have a command when starting up, then do it.
if ( $options{command} ) {
my $command = $options{command};
$control->$command(\%options);
}
socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
unlink($sock_file);
bind(SERVER, $saddr) or Fatal("Can't bind: $!");
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
my $rin = '';
vec( $rin, fileno(SERVER), 1 ) = 1;
my $win = $rin;
my $ein = $win;
my $timeout = MAX_COMMAND_WAIT;
while( 1 ) {
my $nfound = select(my $rout = $rin, undef, undef, $timeout);
if ( $nfound > 0 ) {
if ( vec( $rout, fileno(SERVER), 1 ) ) {
my $paddr = accept(CLIENT, SERVER);
my $message = <CLIENT>;
next if !$message;
my $params = jsonDecode($message);
#Debug( Dumper( $params ) );
my $command = $params->{command};
close( CLIENT );
if ( $command eq 'quit' ) {
last;
}
$control->$command($params);
} else {
Fatal('Bogus descriptor');
}
} elsif ( $nfound < 0 ) {
if ( $! == EPIPE ) {
Error("Can't select: $!");
} else {
Fatal("Can't select: $!");
}
} else {
#print( "Select timed out\n" );
last;
}
} # end while forever
Info("Control server $id/$protocol exiting");
unlink($sock_file);
$control->close();
exit(0);
} # end if !server up
# The server is there, connect to it
#print( "Writing commands\n" );
CLIENT->autoflush();
if ( $options{command} ) {
my $message = jsonEncode(\%options);
print(CLIENT $message);
}
shutdown(CLIENT, 1);
exit(0);

View File

@ -193,6 +193,9 @@ Event::Event(
video_name[0] = 0;
snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
/* Save as video */
if ( monitor->GetOptVideoWriter() != 0 ) {
@ -251,7 +254,7 @@ Event::~Event() {
WriteDbFrames();
// Should not be static because we might be multi-threaded
char sql[ZM_SQL_MED_BUFSIZ];
char sql[ZM_SQL_LGE_BUFSIZ];
snprintf(sql, sizeof(sql),
"UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' WHERE Id = %" PRIu64,
monitor->EventPrefix(), id, end_time.tv_sec,
@ -453,9 +456,9 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
frames++;
static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
if ( monitor->GetOptSaveJPEGs() & 1 ) {
static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
Debug(1, "Writing pre-capture frame %d", frames);
WriteFrameImage(images[i], *(timestamps[i]), event_file);
} else {
@ -464,8 +467,6 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
// neccessarily be of the motion. But some events are less than 10 frames,
// so I am changing this to 1, but we should overwrite it later with a better snapshot.
if ( frames == 1 ) {
char snapshot_file[PATH_MAX];
snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
WriteFrameImage(images[i], *(timestamps[i]), snapshot_file);
}
}
@ -537,32 +538,29 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
}
frames++;
static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
bool write_to_db = false;
if ( monitor->GetOptSaveJPEGs() & 1 ) {
static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
Debug(1, "Writing capture frame %d to %s", frames, event_file);
if ( ! WriteFrameImage(image, timestamp, event_file) ) {
Error("Failed to write frame image");
}
} else {
//If this is the first frame, we should add a thumbnail to the event directory
if ( frames == 1 || score > (int)max_score ) {
char snapshot_file[PATH_MAX];
snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
if ( (frames == 1) || (score > (int)max_score) ) {
write_to_db = true; // web ui might show this as thumbnail, so db needs to know about it.
WriteFrameImage(image, timestamp, snapshot_file);
}
// The first frame with a score will be the frame that alarmed the event
if (!alarm_frame_written && score > 0) {
if ( (!alarm_frame_written) && (score > 0) ) {
write_to_db = true; // OD processing will need it, so the db needs to know about it
alarm_frame_written = true;
char alarm_file[PATH_MAX];
snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
WriteFrameImage(image, timestamp, alarm_file);
}
}
if ( videowriter != NULL ) {
Debug(3, "Writing video");
WriteFrameVideo(image, timestamp, videowriter);
}
@ -579,7 +577,7 @@ Debug(3, "Writing video");
static char sql[ZM_SQL_MED_BUFSIZ];
frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score));
if ( frame_data.size() > 20 ) {
if ( write_to_db || ( frame_data.size() > 20 ) ) {
WriteDbFrames();
Debug(1, "Adding 20 frames to DB");
last_db_frame = frames;
@ -621,6 +619,7 @@ Debug(3, "Writing video");
if ( alarm_image ) {
if ( monitor->GetOptSaveJPEGs() & 2 ) {
static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames);
Debug(1, "Writing analysis frame %d", frames);
if ( ! WriteFrameImage(alarm_image, timestamp, event_file, true) ) {
@ -628,7 +627,7 @@ Debug(3, "Writing video");
}
}
}
}
} // end if frame_type == ALARM
/* This makes viewing the diagnostic images impossible because it keeps deleting them
if ( config.record_diag_images ) {

View File

@ -90,6 +90,8 @@ class Event {
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
char snapshot_file[PATH_MAX];
char alarm_file[PATH_MAX];
VideoWriter* videowriter;
FILE* timecodes_fd;
char video_name[PATH_MAX];

View File

@ -65,8 +65,9 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs )
}
}
static bool bInit = false;
void FFMPEGInit() {
static bool bInit = false;
if ( !bInit ) {
if ( logDebugging() )
@ -77,7 +78,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback);
else
Info("Not enabling ffmpeg logs, as LOG_FFMPEG is disabled in options");
#if LIBAVCODEC_VERSION_CHECK(58, 18, 0, 64, 0)
#if LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)
#else
av_register_all();
#endif
@ -86,6 +87,11 @@ void FFMPEGInit() {
}
}
void FFMPEGDeInit() {
avformat_network_deinit();
bInit = false;
}
#if HAVE_LIBAVUTIL
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder) {
enum _AVPIXELFORMAT pf;
@ -279,7 +285,9 @@ static void zm_log_fps(double d, const char *postfix) {
}
void zm_dump_frame(const AVFrame *frame,const char *text) {
Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d layout %d pts %" PRId64,
Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d"
" duration %" PRId64
" layout %d pts %" PRId64,
text,
frame->format,
av_get_sample_fmt_name((AVSampleFormat)frame->format),
@ -287,8 +295,9 @@ void zm_dump_frame(const AVFrame *frame,const char *text) {
frame->nb_samples,
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
frame->channels,
frame->pkt_duration,
#else
0,
0, 0,
#endif
frame->channel_layout,
frame->pts
@ -311,7 +320,8 @@ void zm_dump_codecpar ( const AVCodecParameters *par ) {
#endif
void zm_dump_codec(const AVCodecContext *codec) {
Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)",
Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)\n"
"gop_size %d max_b_frames %d me_cmp %d me_range %d qmin %d qmax %d",
codec->codec_type,
codec->codec_id,
codec->width,
@ -319,11 +329,17 @@ void zm_dump_codec(const AVCodecContext *codec) {
codec->time_base.num,
codec->time_base.den,
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
(codec->pix_fmt == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(codec->pix_fmt))
(codec->pix_fmt == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(codec->pix_fmt)),
#else
"unsupported on avconv"
"unsupported on avconv",
#endif
);
codec->gop_size,
codec->max_b_frames,
codec->me_cmp,
codec->me_range,
codec->qmin,
codec->qmax
);
}
/* "user interface" functions */
@ -347,9 +363,9 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
Debug(1, "ids [0x%x]", st->id);
if (lang)
Debug(1, "language (%s)", lang->value);
Debug(1, "frames:%d, frame_size:%d stream timebase: %d/%d codec timebase: %d/%d",
st->codec_info_nb_frames, codec->frame_size, st->time_base.num, st->time_base.den,
st->codec->time_base.num, st->codec->time_base.den
Debug(1, "frames:%d, frame_size:%d stream timebase: %d/%d",
st->codec_info_nb_frames, codec->frame_size,
st->time_base.num, st->time_base.den
);
avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(1, "codec: %s", buf);
@ -368,17 +384,14 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
display_aspect_ratio.num, display_aspect_ratio.den);
}
if ( st->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
if ( codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
int tbn = st->time_base.den && st->time_base.num;
int tbc = st->codec->time_base.den && st->codec->time_base.num;
if (fps)
zm_log_fps(av_q2d(st->avg_frame_rate), "fps");
if (tbn)
zm_log_fps(1 / av_q2d(st->time_base), "stream tb numerator");
if (tbc)
zm_log_fps(1 / av_q2d(st->codec->time_base), "codec time base:");
}
if (st->disposition & AV_DISPOSITION_DEFAULT)
@ -425,6 +438,10 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
av_new_packet(dst,src->size);
memcpy(dst->data, src->data, src->size);
dst->flags = src->flags;
dst->pts = src->pts;
dst->dts = src->dts;
dst->duration = src->duration;
dst->stream_index = src->stream_index;
return 0;
}
#endif
@ -444,6 +461,14 @@ bool is_video_stream( AVStream * stream ) {
return false;
}
bool is_video_context( AVCodecContext *codec_context ) {
return
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
( codec_context->codec_type == AVMEDIA_TYPE_VIDEO );
#else
( codec_context->codec_type == CODEC_TYPE_VIDEO );
#endif
}
bool is_audio_stream( AVStream * stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -460,6 +485,15 @@ bool is_audio_stream( AVStream * stream ) {
return false;
}
bool is_audio_context( AVCodecContext *codec_context ) {
return
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
( codec_context->codec_type == AVMEDIA_TYPE_AUDIO );
#else
( codec_context->codec_type == CODEC_TYPE_AUDIO );
#endif
}
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet ) {
int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -494,15 +528,20 @@ int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet
# else
int frameComplete = 0;
while ( !frameComplete ) {
if ( (ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet )) < 0 ) {
Error( "Unable to decode frame at frame: %s, continuing",
av_make_error_string(ret).c_str() );
if ( is_video_context(context) ) {
ret = zm_avcodec_decode_video(context, frame, &frameComplete, &packet);
} else {
ret = avcodec_decode_audio4(context, frame, &frameComplete, &packet);
}
if ( ret < 0 ) {
Error("Unable to decode frame: %s", av_make_error_string(ret).c_str());
return 0;
}
}
} // end while !frameComplete
#endif
return 1;
} // end int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet )
void dumpPacket(AVStream *stream, AVPacket *pkt, const char *text) {
char b[10240];

View File

@ -199,6 +199,7 @@ extern "C" {
/* A single function to initialize ffmpeg, to avoid multiple initializations */
void FFMPEGInit();
void FFMPEGDeInit();
#if HAVE_LIBAVUTIL
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder);
@ -325,8 +326,11 @@ void zm_dump_frame(const AVFrame *frame, const char *text="Frame");
int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
bool is_video_stream( AVStream * stream );
bool is_audio_stream( AVStream * stream );
bool is_video_stream(AVStream *);
bool is_audio_stream(AVStream *);
bool is_video_context(AVCodec *);
bool is_audio_context(AVCodec *);
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet );
void dumpPacket(AVStream *, AVPacket *,const char *text="");
#endif // ZM_FFMPEG_H

View File

@ -168,7 +168,7 @@ FfmpegCamera::~FfmpegCamera() {
if ( capture ) {
Terminate();
}
avformat_network_deinit();
FFMPEGDeInit();
}
void FfmpegCamera::Initialise() {
@ -535,45 +535,45 @@ int FfmpegCamera::OpenFfmpeg() {
zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0);
// Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
Debug(1, "Calling avcodec_open");
if ( avcodec_open(mVideoCodecContext, mVideoCodec) < 0 )
ret = avcodec_open(mVideoCodecContext, mVideoCodec);
#else
Debug(1, "Calling avcodec_open2");
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 )
ret = avcodec_open2(mVideoCodecContext, mVideoCodec, &opts);
#endif
{
AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
Error( "Unable to open codec for video stream from %s", mPath.c_str() );
AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
if ( ret < 0 ) {
Error("Unable to open codec for video stream from %s", mPath.c_str());
av_dict_free(&opts);
return -1;
} else {
AVDictionaryEntry *e = NULL;
if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
av_dict_free(&opts);
}
zm_dump_codec(mVideoCodecContext);
}
if (mVideoCodecContext->hwaccel != NULL) {
if ( mVideoCodecContext->hwaccel != NULL ) {
Debug(1, "HWACCEL in use");
} else {
Debug(1, "HWACCEL not in use");
}
if ( mAudioStreamId >= 0 ) {
if ( (mAudioCodec = avcodec_find_decoder(
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
mAudioCodecContext = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( mAudioCodecContext, mFormatContext->streams[mAudioStreamId]->codecpar );
mFormatContext->streams[mAudioStreamId]->codecpar->codec_id
#else
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
mFormatContext->streams[mAudioStreamId]->codec->codec_id
#endif
if ( (mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL ) {
)) == NULL ) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
} else {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
mAudioCodecContext = avcodec_alloc_context3(mAudioCodec);
avcodec_parameters_to_context( mAudioCodecContext, mFormatContext->streams[mAudioStreamId]->codecpar );
#else
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
// = avcodec_alloc_context3(mAudioCodec);
#endif
Debug(1, "Audio Found decoder");
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
// Open the codec
@ -584,10 +584,10 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) {
#endif
Error( "Unable to open codec for video stream from %s", mPath.c_str() );
Error( "Unable to open codec for audio stream from %s", mPath.c_str() );
return -1;
}
Debug(2, "Opened audio codec");
zm_dump_codec(mAudioCodecContext);
} // end if find decoder
} // end if have audio_context
@ -675,6 +675,11 @@ int FfmpegCamera::Close() {
}
#endif
if ( videoStore ) {
delete videoStore;
videoStore = NULL;
}
if ( mVideoCodecContext ) {
avcodec_close(mVideoCodecContext);
Debug(1,"After codec close");
@ -700,10 +705,6 @@ int FfmpegCamera::Close() {
mFormatContext = NULL;
}
if ( videoStore ) {
delete videoStore;
videoStore = NULL;
}
if ( packetqueue ) {
delete packetqueue;
packetqueue = NULL;
@ -1034,7 +1035,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
//FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
Debug(4, "FfmpegInterruptCallback");
//Debug(4, "FfmpegInterruptCallback");
return zm_terminate;
}

View File

@ -81,7 +81,7 @@ VideoStore::VideoStore(
filename, format);
return;
} else {
Debug(4, "Success alocateing out ctx");
Debug(4, "Success allocating out ctx");
}
} // end if ! oc
@ -92,9 +92,9 @@ VideoStore::VideoStore(
oc->metadata = pmetadata;
out_format = oc->oformat;
out_format->flags |= AVFMT_TS_NONSTRICT; // allow non increasing dts
AVCodec *video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
if ( !video_out_codec ) {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Fatal("Could not find encoder for '%s'", avcodec_get_name(video_out_ctx->codec_id));
@ -103,7 +103,8 @@ VideoStore::VideoStore(
#endif
}
video_out_stream = avformat_new_stream(oc, video_out_codec);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
video_out_stream = avformat_new_stream(oc, NULL);
if ( !video_out_stream ) {
Error("Unable to create video out stream");
return;
@ -111,21 +112,31 @@ VideoStore::VideoStore(
Debug(2, "Success creating video out stream");
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
//video_out_stream->codec = avcodec_alloc_context3(video_out_codec);
// Since we are not re-encoding, all we have to do is copy the parameters
// by allocating our own copy, we don't run into the problems when we free the streams
video_out_ctx = avcodec_alloc_context3(video_out_codec);
// Since we are not re-encoding, all we have to do is copy the parameters
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(video_out_ctx, video_in_stream->codecpar);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
} else {
zm_dump_codec(video_out_ctx);
}
#else
video_out_stream = avformat_new_stream(oc, NULL);
if ( !video_out_stream ) {
Error("Unable to create video out stream");
return;
} else {
Debug(2, "Success creating video out stream");
}
video_out_ctx = video_out_stream->codec;
// This will wipe out the codec defaults
ret = avcodec_copy_context(video_out_ctx, video_in_ctx);
//video_out_ctx->width = video_in_ctx->width;
//video_out_ctx->height = video_in_ctx->height;
//video_out_ctx->pix_fmt = video_in_ctx->pix_fmt;
//video_out_ctx->max_b_frames = video_in_ctx->max_b_frames;
//video_out_ctx->has_b_frames = video_in_ctx->has_b_frames;
if ( ret < 0 ) {
Fatal("Unable to copy in video ctx to out video ctx %s",
av_make_error_string(ret).c_str());
@ -143,8 +154,7 @@ VideoStore::VideoStore(
zm_dump_codec(video_out_ctx);
//video_out_ctx->bit_rate = 400*1024;
//video_out_ctx->thread_count = 0;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
//// Fix deprecated formats
switch ( video_out_ctx->pix_fmt ) {
case AV_PIX_FMT_YUVJ422P :
@ -163,15 +173,6 @@ VideoStore::VideoStore(
break;
}
if ( video_out_ctx->codec_id == AV_CODEC_ID_H264 ) {
video_out_ctx->max_b_frames = 1;
if ( video_out_ctx->priv_data ) {
av_opt_set(video_out_ctx->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN);
//av_opt_set(video_out_ctx->priv_data, "preset", "ultrafast", 0);
} else {
Debug(2, "Not setting priv_data");
}
}
if ( !video_out_ctx->codec_tag ) {
Debug(2, "No codec_tag");
@ -186,6 +187,7 @@ VideoStore::VideoStore(
video_out_ctx->codec_tag = video_in_ctx->codec_tag;
}
}
#endif
video_out_stream->time_base = video_in_stream->time_base;
if ( video_in_stream->avg_frame_rate.num ) {
@ -196,13 +198,26 @@ VideoStore::VideoStore(
video_out_stream->avg_frame_rate = video_in_stream->avg_frame_rate;
}
if ( video_in_stream->r_frame_rate.num ) {
Debug(3,"Copying r_frame_rate (%d/%d)",
Debug(3,"Copying r_frame_rate (%d/%d) to out (%d/%d)",
video_in_stream->r_frame_rate.num,
video_in_stream->r_frame_rate.den
video_in_stream->r_frame_rate.den ,
video_out_stream->r_frame_rate.num,
video_out_stream->r_frame_rate.den
);
video_out_stream->r_frame_rate = video_in_stream->r_frame_rate;
}
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
if ( video_out_ctx->codec_id == AV_CODEC_ID_H264 ) {
//video_out_ctx->level = 32;I//
video_out_ctx->bit_rate = 400*1024;
video_out_ctx->max_b_frames = 1;
if ( video_out_ctx->priv_data ) {
av_opt_set(video_out_ctx->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN);
av_opt_set(video_out_ctx->priv_data, "preset", "ultrafast", 0);
} else {
Debug(2, "Not setting priv_data");
}
}
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
@ -230,7 +245,7 @@ VideoStore::VideoStore(
#endif
}
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
AVDictionary *opts = 0;
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
Warning("Can't open video codec (%s) %s",
@ -244,6 +259,7 @@ VideoStore::VideoStore(
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
}
#endif
Monitor::Orientation orientation = monitor->getOrientation();
if ( orientation ) {
@ -275,92 +291,6 @@ VideoStore::VideoStore(
fifo = NULL;
#endif
#endif
if ( audio_in_stream ) {
Debug(3, "Have audio stream");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_in_ctx = avcodec_alloc_context3(NULL);
ret = avcodec_parameters_to_context(audio_in_ctx,
audio_in_stream->codecpar);
audio_in_ctx->time_base = audio_in_stream->time_base;
#else
audio_in_ctx = audio_in_stream->codec;
#endif
if ( audio_in_ctx->codec_id != AV_CODEC_ID_AAC ) {
static char error_buffer[256];
avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0);
Debug(2, "Got something other than AAC (%s)", error_buffer);
if ( !setup_resampler() ) {
return;
}
} else {
Debug(2, "Got AAC");
audio_out_stream =
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec));
#else
avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec);
#endif
if ( !audio_out_stream ) {
Error("Unable to create audio out stream");
audio_out_stream = NULL;
} else {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(
audio_out_ctx, audio_in_stream->codecpar);
if ( ret < 0 ) {
Error("Unable to copy audio params to ctx %s",
av_make_error_string(ret).c_str());
}
ret = avcodec_parameters_from_context(
audio_out_stream->codecpar, audio_out_ctx);
if ( ret < 0 ) {
Error("Unable to copy audio params to stream %s",
av_make_error_string(ret).c_str());
}
if ( !audio_out_ctx->codec_tag ) {
audio_out_ctx->codec_tag = av_codec_get_tag(
oc->oformat->codec_tag, audio_in_ctx->codec_id);
Debug(2, "Setting audio codec tag to %d",
audio_out_ctx->codec_tag);
}
#else
audio_out_ctx = audio_out_stream->codec;
ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx);
audio_out_ctx->codec_tag = 0;
#endif
if ( ret < 0 ) {
Error("Unable to copy audio ctx %s",
av_make_error_string(ret).c_str());
audio_out_stream = NULL;
} else {
if ( audio_out_ctx->channels > 1 ) {
Warning("Audio isn't mono, changing it.");
audio_out_ctx->channels = 1;
} else {
Debug(3, "Audio is mono");
}
}
} // end if audio_out_stream
} // end if is AAC
if ( audio_out_stream ) {
if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
#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
video_first_pts = 0;
video_first_dts = 0;
video_last_pts = 0;
@ -368,11 +298,106 @@ VideoStore::VideoStore(
audio_first_pts = 0;
audio_first_dts = 0;
audio_last_pts = 0;
audio_last_dts = 0;
audio_next_pts = 0;
audio_next_dts = 0;
if ( audio_in_stream ) {
Debug(3, "Have audio stream");
if (
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_in_stream->codecpar->codec_id
#else
audio_in_stream->codec->codec_id
#endif
!= AV_CODEC_ID_AAC ) {
audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if ( !audio_out_codec ) {
Error("Could not find codec for AAC");
return;
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_out_stream = avformat_new_stream(oc, NULL);
audio_out_stream->time_base = audio_in_stream->time_base;
audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
if ( !audio_out_ctx ) {
Error("could not allocate codec ctx for AAC");
audio_out_stream = NULL;
return;
}
#else
audio_out_stream = avformat_new_stream(oc, audio_out_codec);
audio_out_ctx = audio_out_stream->codec;
#endif
audio_out_stream->time_base = audio_in_stream->time_base;
if ( !setup_resampler() ) {
return;
}
} else {
Debug(2, "Got AAC");
audio_out_stream = avformat_new_stream(oc, NULL);
if ( !audio_out_stream ) {
Error("Could not allocate new stream");
return;
}
audio_out_stream->time_base = audio_in_stream->time_base;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Just use the ctx to copy the parameters over
audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
if ( !audio_out_ctx ) {
Error("Could not allocate new output_context");
return;
}
// We don't actually care what the time_base is..
audio_out_ctx->time_base = audio_in_stream->time_base;
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(
audio_out_ctx, audio_in_stream->codecpar);
if ( ret < 0 ) {
Error("Unable to copy audio params to ctx %s",
av_make_error_string(ret).c_str());
}
ret = avcodec_parameters_from_context(
audio_out_stream->codecpar, audio_out_ctx);
if ( ret < 0 ) {
Error("Unable to copy audio params to stream %s",
av_make_error_string(ret).c_str());
}
#else
audio_out_ctx = audio_out_stream->codec;
ret = avcodec_copy_context(audio_out_ctx, audio_in_stream->codec);
if ( ret < 0 ) {
Error("Unable to copy audio ctx %s",
av_make_error_string(ret).c_str());
audio_out_stream = NULL;
return;
} // end if
audio_out_ctx->codec_tag = 0;
#endif
if ( audio_out_ctx->channels > 1 ) {
Warning("Audio isn't mono, changing it.");
audio_out_ctx->channels = 1;
} else {
Debug(3, "Audio is mono");
}
} // end if is AAC
if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
#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
} // VideoStore::VideoStore
bool VideoStore::open() {
@ -507,17 +532,21 @@ VideoStore::~VideoStore() {
#endif
video_in_ctx = NULL;
avcodec_close(video_out_ctx);
if ( video_out_codec ) {
avcodec_close(video_out_ctx);
Debug(4, "Success closing video_out_ctx");
video_out_codec = NULL;
} // end if video_out_codec
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
//avcodec_free_context(&video_out_ctx);
avcodec_free_context(&video_out_ctx);
#endif
video_out_ctx = NULL;
Debug(4, "Success freeing video_out_ctx");
} // end if video_out_stream
if ( audio_out_stream ) {
if ( audio_in_codec ) {
avcodec_close(audio_in_ctx);
Debug(4, "Success closing audio_in_ctx");
audio_in_codec = NULL;
} // end if audio_in_codec
@ -525,27 +554,32 @@ VideoStore::~VideoStore() {
// We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&audio_in_ctx);
#endif
Debug(4, "Success freeing audio_in_ctx");
audio_in_ctx = NULL;
avcodec_close(audio_out_ctx);
if ( audio_out_ctx ) {
avcodec_close(audio_out_ctx);
Debug(4, "Success closing audio_out_ctx");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&audio_out_ctx);
avcodec_free_context(&audio_out_ctx);
#endif
}
audio_out_ctx = NULL;
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
if ( resample_ctx ) {
#if defined(HAVE_LIBSWRESAMPLE)
#if defined(HAVE_LIBSWRESAMPLE)
if ( fifo ) {
av_audio_fifo_free(fifo);
fifo = NULL;
}
swr_free(&resample_ctx);
#else
#if defined(HAVE_LIBAVRESAMPLE)
#else
#if defined(HAVE_LIBAVRESAMPLE)
avresample_close(resample_ctx);
avresample_free(&resample_ctx);
#endif
#endif
#endif
#endif
}
if ( in_frame ) {
av_frame_free(&in_frame);
@ -562,7 +596,7 @@ VideoStore::~VideoStore() {
#endif
} // end if audio_out_stream
/* free the stream */
/* free the streams */
avformat_free_context(oc);
} // VideoStore::~VideoStore()
@ -579,34 +613,43 @@ bool VideoStore::setup_resampler() {
// decoder, can't reuse the one from the camera.
audio_in_codec =
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
#else
audio_in_codec = avcodec_find_decoder(audio_in_ctx->codec_id);
#endif
if ( (ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL)) < 0 ) {
Error("Can't open in codec!");
return false;
audio_in_ctx = avcodec_alloc_context3(audio_in_codec);
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(
audio_in_ctx, audio_in_stream->codecpar);
if ( ret < 0 ) {
Error("Unable to copy audio params to ctx %s",
av_make_error_string(ret).c_str());
}
audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if ( !audio_out_codec ) {
Error("Could not find codec for AAC");
return false;
}
#else
// codec is already open in ffmpeg_camera
audio_in_ctx = audio_in_stream->codec;
audio_in_codec = (AVCodec *)audio_in_ctx->codec;
//audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
#endif
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// audio_out_ctx = audio_out_stream->codec;
audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
if ( !audio_out_ctx ) {
Error("could not allocate codec ctx for AAC");
audio_out_stream = NULL;
#else
#if 0
ret = avcodec_copy_context(audio_in_ctx, audio_in_stream->codec);
if ( ret < 0 ) {
Fatal("Unable to copy in video ctx to out video ctx %s",
av_make_error_string(ret).c_str());
} else {
Debug(3, "Success copying ctx");
}
#endif
#endif
// if the codec is already open, nothing is done.
if ( (ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL)) < 0 ) {
Error("Can't open audio in codec!");
return false;
}
audio_out_stream = avformat_new_stream(oc, audio_out_codec);
#else
audio_out_stream = avformat_new_stream(oc, NULL);
audio_out_ctx = audio_out_stream->codec;
#endif
Debug(2, "Got something other than AAC (%s)", audio_in_codec->name);
// Some formats (i.e. WAV) do not produce the proper channel layout
if ( audio_in_ctx->channel_layout == 0 ) {
Debug(2, "Setting input channel layout to mono");
@ -620,10 +663,7 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->channels = audio_in_ctx->channels;
audio_out_ctx->channel_layout = audio_in_ctx->channel_layout;
audio_out_ctx->sample_fmt = audio_in_ctx->sample_fmt;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
#else
audio_out_ctx->refcounted_frames = 1;
#endif
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
if ( !audio_out_ctx->channel_layout ) {
Debug(3, "Correcting channel layout from (%d) to (%d)",
audio_out_ctx->channel_layout,
@ -631,7 +671,7 @@ bool VideoStore::setup_resampler() {
);
audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels);
}
#endif
if ( audio_out_codec->supported_samplerates ) {
int found = 0;
for ( unsigned int i = 0; audio_out_codec->supported_samplerates[i]; i++ ) {
@ -787,7 +827,9 @@ bool VideoStore::setup_resampler() {
out_frame->nb_samples = audio_out_ctx->frame_size;
out_frame->format = audio_out_ctx->sample_fmt;
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
out_frame->channels = audio_out_ctx->channels;
#endif
out_frame->channel_layout = audio_out_ctx->channel_layout;
out_frame->sample_rate = audio_out_ctx->sample_rate;
@ -826,7 +868,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
dumpPacket(video_in_stream, ipkt, "input packet");
int64_t duration;
if ( ipkt->duration ) {
if ( ipkt->duration != AV_NOPTS_VALUE ) {
duration = av_rescale_q(
ipkt->duration,
video_in_stream->time_base,
@ -880,29 +922,29 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
video_last_pts = ipkt->pts;
} else {
Debug(3, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
opkt.pts = 0;
//AV_NOPTS_VALUE;
}
// Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
// Just because the in stream wraps, doesn't mean the out needs to.
// Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out.
// So need to handle in wrap, without causing out wrap.
if ( ipkt->dts != AV_NOPTS_VALUE ) {
#if 0
if ( (!video_first_dts) && ( ipkt->dts >= 0 ) ) {
if ( !video_first_dts ) {
// && ( ipkt->dts >= 0 ) ) {
// This is the first packet.
opkt.dts = 0;
Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
video_first_dts = ipkt->dts;
} else {
#endif
opkt.dts = av_rescale_q(
ipkt->dts - video_first_pts,
ipkt->dts - video_first_dts,
video_in_stream->time_base,
video_out_stream->time_base
);
Debug(3, "opkt.dts = %" PRId64 " from ipkt->dts(%" PRId64 ") - first_pts(%" PRId64 ")",
opkt.dts, ipkt->dts, video_first_pts);
video_last_dts = ipkt->dts;
#if 0
opkt.dts, ipkt->dts, video_first_dts);
}
#endif
if ( opkt.dts > opkt.pts ) {
Debug(1,
"opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 "). Decompression must happen "
@ -915,6 +957,16 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.dts = 0;
}
# if 0
if ( opkt.dts <= video_out_stream->cur_dts ) {
Warning("Fixing non-monotonic dts/pts dts %" PRId64 " pts %" PRId64 " stream %" PRId64,
opkt.dts, opkt.pts, video_out_stream->cur_dts);
opkt.dts = video_out_stream->cur_dts + 1;
if ( opkt.dts > opkt.pts ) {
opkt.pts = opkt.dts;
}
}
#endif
opkt.flags = ipkt->flags;
opkt.pos = -1;
@ -954,46 +1006,21 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
// the moment
}
dumpPacket(audio_in_stream, ipkt, "input packet");
if ( audio_out_codec ) {
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ( (ret = avcodec_send_packet(audio_in_ctx, ipkt)) < 0 ) {
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
Debug(2, "Have output codec");
if ( ! zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) {
return 0;
}
if ( (ret = avcodec_receive_frame(audio_in_ctx, in_frame)) < 0 ) {
Error("avcodec_receive_frame fail %s", av_make_error_string(ret).c_str());
return 0;
}
#else
int data_present;
if ( (ret = avcodec_decode_audio4(
audio_in_ctx, in_frame, &data_present, ipkt)) < 0 ) {
Error("Could not decode frame (error '%s')",
av_make_error_string(ret).c_str());
dumpPacket(video_in_stream, ipkt);
// I'm not sure if we should be freeing the frame.
av_frame_free(&in_frame);
return 0;
}
if ( !data_present ) {
Debug(2, "Not ready to transcode a frame yet.");
return 0;
}
#endif
zm_dump_frame(in_frame, "In frame from decode");
int frame_size = in_frame->nb_samples;
// Resample the in into the audioSampleBuffer until we proceed the whole
// decoded data. Note: pts does not survive resampling or converting
#if defined(HAVE_LIBSWRESAMPLE)
Debug(2, "Converting %d to %d samples using swresample", in_frame->nb_samples, out_frame->nb_samples);
ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
zm_dump_frame(out_frame, "Out frame after convert");
if ( ! resample_audio() ) {
//av_frame_unref(in_frame);
return 0;
}
zm_dump_frame(out_frame, "Out frame after resample");
out_frame->pts = in_frame->pts;
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
@ -1005,64 +1032,12 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} else {
out_frame->pts = out_frame->pts - audio_first_pts;
}
//
} else {
// sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
out_frame->pts = audio_next_pts;
}
av_frame_unref(in_frame);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
Error("Could not reallocate FIFO");
return 0;
}
/** Store the new samples in the FIFO buffer. */
ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
if ( ret < frame_size ) {
Error("Could not write data to FIFO on %d written", ret);
return 0;
}
// Reset frame_size to output_frame_size
frame_size = audio_out_ctx->frame_size;
// AAC requires 1024 samples per encode. Our input tends to be 160, so need to buffer them.
if ( frame_size > av_audio_fifo_size(fifo) ) {
return 0;
}
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
Error("Could not read data from FIFO");
return 0;
}
out_frame->nb_samples = frame_size;
/// FIXME this is not the correct pts
#else
#if defined(HAVE_LIBAVRESAMPLE)
(ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
0, in_frame->nb_samples))
av_frame_unref(in_frame);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
int samples_available = avresample_available(resample_ctx);
if ( samples_available < frame_size ) {
Debug(1, "Not enough samples yet (%d)", samples_available);
return 0;
}
// Read a frame audio data from the resample fifo
if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
frame_size) {
Warning("Error reading resampled audio.");
return 0;
}
#endif
#endif
zm_dump_frame(out_frame, "Out frame after resample");
audio_next_pts = out_frame->pts + out_frame->nb_samples;
av_init_packet(&opkt);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -1087,6 +1062,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0;
}
#else
int data_present;
if ( (ret = avcodec_encode_audio2(
audio_out_ctx, &opkt, out_frame, &data_present)) < 0 ) {
Error("Could not encode frame (error '%s')",
@ -1100,11 +1076,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0;
}
#endif
#else
Error("Have audio codec but no resampler?!");
#endif
//if ( out_frame ) {
//opkt.duration = out_frame->nb_samples;
opkt.duration = av_rescale_q(opkt.duration,
audio_in_stream->time_base,
audio_out_stream->time_base);
@ -1114,12 +1085,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.dts = av_rescale_q(opkt.dts,
audio_in_stream->time_base,
audio_out_stream->time_base);
dumpPacket(audio_out_stream, &opkt, "raw opkt");
} else {
Debug(2,"copying");
av_init_packet(&opkt);
opkt.data = ipkt->data;
opkt.size = ipkt->size;
if ( ipkt->duration != AV_NOPTS_VALUE ) {
if ( ipkt->duration && (ipkt->duration != AV_NOPTS_VALUE) ) {
opkt.duration = av_rescale_q(
ipkt->duration,
audio_in_stream->time_base,
@ -1139,7 +1113,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
Debug(2, "audio opkt.pts = %" PRId64 " from ipkt->pts(%" PRId64 ") - first_pts(%" PRId64 ")",
opkt.pts, ipkt->pts, audio_first_pts);
}
audio_last_pts = ipkt->pts;
} else {
Debug(2, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
@ -1171,12 +1144,11 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} else {
opkt.dts = AV_NOPTS_VALUE;
}
}
} // end if encoding or copying
opkt.pos = -1;
opkt.stream_index = audio_out_stream->index;
dumpPacket(audio_out_stream, &opkt, "raw opkt");
opkt.flags = ipkt->flags;
if ( opkt.dts > opkt.pts ) {
Debug(1,
@ -1198,3 +1170,75 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
zm_av_packet_unref(&opkt);
return 0;
} // end int VideoStore::writeAudioFramePacket(AVPacket *ipkt)
int VideoStore::resample_audio() {
// Resample the in into the audioSampleBuffer until we process the whole
// decoded data. Note: pts does not survive resampling or converting
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
#if defined(HAVE_LIBSWRESAMPLE)
Debug(2, "Converting %d to %d samples using swresample",
in_frame->nb_samples, out_frame->nb_samples);
ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
zm_dump_frame(out_frame, "Out frame after convert");
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
Error("Could not reallocate FIFO");
return 0;
}
/** Store the new samples in the FIFO buffer. */
ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
if ( ret < in_frame->nb_samples ) {
Error("Could not write data to FIFO on %d written", ret);
return 0;
}
// Reset frame_size to output_frame_size
int frame_size = audio_out_ctx->frame_size;
// AAC requires 1024 samples per encode. Our input tends to be 160, so need to buffer them.
if ( frame_size > av_audio_fifo_size(fifo) ) {
return 0;
}
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
Error("Could not read data from FIFO");
return 0;
}
out_frame->nb_samples = frame_size;
#else
#if defined(HAVE_LIBAVRESAMPLE)
ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
0, in_frame->nb_samples);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
int frame_size = audio_out_ctx->frame_size;
int samples_available = avresample_available(resample_ctx);
if ( samples_available < frame_size ) {
Debug(1, "Not enough samples yet (%d)", samples_available);
return 0;
}
// Read a frame audio data from the resample fifo
if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
frame_size) {
Warning("Error reading resampled audio.");
return 0;
}
#endif
#endif
#else
Error("Have audio codec but no resampler?!");
return 0;
#endif
return 1;
} // end int VideoStore::resample_audio

View File

@ -20,14 +20,16 @@ extern "C" {
class VideoStore {
private:
AVOutputFormat *out_format;
AVFormatContext *oc;
AVStream *video_out_stream;
AVStream *audio_out_stream;
AVCodecContext *video_out_ctx;
AVOutputFormat *out_format;
AVFormatContext *oc;
AVStream *video_in_stream;
AVStream *audio_in_stream;
AVCodec *video_out_codec;
AVCodecContext *video_out_ctx;
AVStream *video_out_stream;
AVStream *video_in_stream;
AVStream *audio_in_stream;
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
AVPacket opkt;
@ -41,6 +43,7 @@ private:
int ret;
// The following are used when encoding the audio stream to AAC
AVStream *audio_out_stream;
AVCodec *audio_out_codec;
AVCodecContext *audio_out_ctx;
#ifdef HAVE_LIBSWRESAMPLE
@ -74,6 +77,7 @@ private:
int64_t audio_next_dts;
bool setup_resampler();
int resample_audio();
public:
VideoStore(

View File

@ -426,12 +426,12 @@ int main(int argc, char *argv[]) {
if ( config.opt_use_auth ) {
if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( !username ) {
fprintf(stderr, "Error, username must be supplied\n");
Error("Username must be supplied");
exit_zmu(-1);
}
if ( !checkUser(username)) {
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
Error("Username greater than allowed 32 characters");
exit_zmu(-1);
}
@ -439,7 +439,7 @@ int main(int argc, char *argv[]) {
} else {
if ( !(username && password) && !auth ) {
fprintf(stderr, "Error, username and password or auth string must be supplied\n");
Error("Username and password or auth string must be supplied");
exit_zmu(-1);
}
if ( auth ) {
@ -447,22 +447,22 @@ int main(int argc, char *argv[]) {
}
if ( username && password ) {
if ( !checkUser(username)) {
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
Error("username greater than allowed 32 characters");
exit_zmu(-1);
}
if ( !checkPass(password)) {
fprintf(stderr, "Error, password greater than allowed 64 characters\n");
Error("password greater than allowed 64 characters");
exit_zmu(-1);
}
user = zmLoadUser(username, password);
} // end if username && password
} // end if relay or not
if ( !user ) {
fprintf(stderr, "Error, unable to authenticate user\n");
return exit_zmu(-1);
Error("Unable to authenticate user");
exit_zmu(-1);
}
if ( !ValidateAccess(user, mon_id, function) ) {
fprintf(stderr, "Error, insufficient privileges for requested action\n");
Error("Insufficient privileges for requested action");
exit_zmu(-1);
}
} // end if auth
@ -497,201 +497,201 @@ int main(int argc, char *argv[]) {
if ( verbose ) {
char timestamp_str[64] = "None";
if ( timestamp.tv_sec )
strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( &timestamp.tv_sec ) );
strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime(&timestamp.tv_sec));
if ( image_idx == -1 )
printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 );
printf("Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000);
else
printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 );
printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000);
} else {
if ( have_output ) printf( "%c", separator );
printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 );
if ( have_output ) printf("%c", separator);
printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000);
have_output = true;
}
}
if ( function & ZMU_READ_IDX ) {
if ( verbose )
printf( "Last read index: %d\n", monitor->GetLastReadIndex() );
printf("Last read index: %d\n", monitor->GetLastReadIndex());
else {
if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastReadIndex() );
if ( have_output ) printf("%c", separator);
printf("%d", monitor->GetLastReadIndex());
have_output = true;
}
}
if ( function & ZMU_WRITE_IDX ) {
if ( verbose )
printf( "Last write index: %d\n", monitor->GetLastWriteIndex() );
else {
if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastWriteIndex() );
if ( verbose ) {
printf("Last write index: %d\n", monitor->GetLastWriteIndex());
} else {
if ( have_output ) printf("%c", separator);
printf("%d", monitor->GetLastWriteIndex());
have_output = true;
}
}
if ( function & ZMU_EVENT ) {
if ( verbose )
printf( "Last event id: %" PRIu64 "\n", monitor->GetLastEventId() );
else {
if ( have_output ) printf( "%c", separator );
printf( "%" PRIu64, monitor->GetLastEventId() );
if ( verbose ) {
printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId());
} else {
if ( have_output ) printf("%c", separator);
printf("%" PRIu64, monitor->GetLastEventId());
have_output = true;
}
}
if ( function & ZMU_FPS ) {
if ( verbose )
printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() );
printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS());
else {
if ( have_output ) printf( "%c", separator );
printf( "%.2f", monitor->GetFPS() );
if ( have_output ) printf("%c", separator);
printf("%.2f", monitor->GetFPS());
have_output = true;
}
}
if ( function & ZMU_IMAGE ) {
if ( verbose ) {
if ( image_idx == -1 )
printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() );
printf("Dumping last image captured to Monitor%d.jpg", monitor->Id());
else
printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() );
printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id());
if ( scale != -1 )
printf( ", scaling by %d%%", scale );
printf( "\n" );
printf(", scaling by %d%%", scale);
printf("\n");
}
monitor->GetImage( image_idx, scale>0?scale:100 );
monitor->GetImage(image_idx, scale>0?scale:100);
}
if ( function & ZMU_ZONES ) {
if ( verbose )
printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() );
monitor->DumpZoneImage( zoneString );
printf("Dumping zone image to Zones%d.jpg\n", monitor->Id());
monitor->DumpZoneImage(zoneString);
}
if ( function & ZMU_ALARM ) {
if ( verbose )
printf( "Forcing alarm on\n" );
monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" );
printf("Forcing alarm on\n");
monitor->ForceAlarmOn(config.forced_alarm_score, "Forced Web");
while ( monitor->GetState() != Monitor::ALARM ) {
// Wait for monitor to notice.
usleep(1000);
}
printf( "Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId() );
printf("Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId());
}
if ( function & ZMU_NOALARM ) {
if ( verbose )
printf( "Forcing alarm off\n" );
printf("Forcing alarm off\n");
monitor->ForceAlarmOff();
}
if ( function & ZMU_CANCEL ) {
if ( verbose )
printf( "Cancelling forced alarm on/off\n" );
printf("Cancelling forced alarm on/off\n");
monitor->CancelForced();
}
if ( function & ZMU_RELOAD ) {
if ( verbose )
printf( "Reloading monitor settings\n" );
printf("Reloading monitor settings\n");
monitor->actionReload();
}
if ( function & ZMU_ENABLE ) {
if ( verbose )
printf( "Enabling event generation\n" );
printf("Enabling event generation\n");
monitor->actionEnable();
}
if ( function & ZMU_DISABLE ) {
if ( verbose )
printf( "Disabling event generation\n" );
printf("Disabling event generation\n");
monitor->actionDisable();
}
if ( function & ZMU_SUSPEND ) {
if ( verbose )
printf( "Suspending event generation\n" );
printf("Suspending event generation\n");
monitor->actionSuspend();
}
if ( function & ZMU_RESUME ) {
if ( verbose )
printf( "Resuming event generation\n" );
printf("Resuming event generation\n");
monitor->actionResume();
}
if ( function & ZMU_QUERY ) {
char monString[16382] = "";
monitor->DumpSettings( monString, verbose );
printf( "%s\n", monString );
monitor->DumpSettings(monString, verbose);
printf("%s\n", monString);
}
if ( function & ZMU_BRIGHTNESS ) {
if ( verbose ) {
if ( brightness >= 0 )
printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) );
printf("New brightness: %d\n", monitor->actionBrightness(brightness));
else
printf( "Current brightness: %d\n", monitor->actionBrightness() );
printf("Current brightness: %d\n", monitor->actionBrightness());
} else {
if ( have_output ) printf( "%c", separator );
if ( have_output ) printf("%c", separator);
if ( brightness >= 0 )
printf( "%d", monitor->actionBrightness( brightness ) );
printf("%d", monitor->actionBrightness(brightness));
else
printf( "%d", monitor->actionBrightness() );
printf("%d", monitor->actionBrightness());
have_output = true;
}
}
if ( function & ZMU_CONTRAST ) {
if ( verbose ) {
if ( contrast >= 0 )
printf( "New brightness: %d\n", monitor->actionContrast( contrast ) );
printf("New brightness: %d\n", monitor->actionContrast(contrast));
else
printf( "Current contrast: %d\n", monitor->actionContrast() );
printf("Current contrast: %d\n", monitor->actionContrast());
} else {
if ( have_output ) printf( "%c", separator );
if ( have_output ) printf("%c", separator);
if ( contrast >= 0 )
printf( "%d", monitor->actionContrast( contrast ) );
printf("%d", monitor->actionContrast(contrast));
else
printf( "%d", monitor->actionContrast() );
printf("%d", monitor->actionContrast());
have_output = true;
}
}
if ( function & ZMU_HUE ) {
if ( verbose ) {
if ( hue >= 0 )
printf( "New hue: %d\n", monitor->actionHue( hue ) );
printf("New hue: %d\n", monitor->actionHue(hue));
else
printf( "Current hue: %d\n", monitor->actionHue() );
printf("Current hue: %d\n", monitor->actionHue());
} else {
if ( have_output ) printf( "%c", separator );
if ( have_output ) printf("%c", separator);
if ( hue >= 0 )
printf( "%d", monitor->actionHue( hue ) );
printf("%d", monitor->actionHue(hue));
else
printf( "%d", monitor->actionHue() );
printf("%d", monitor->actionHue());
have_output = true;
}
}
if ( function & ZMU_COLOUR ) {
if ( verbose ) {
if ( colour >= 0 )
printf( "New colour: %d\n", monitor->actionColour( colour ) );
printf("New colour: %d\n", monitor->actionColour(colour));
else
printf( "Current colour: %d\n", monitor->actionColour() );
printf("Current colour: %d\n", monitor->actionColour());
} else {
if ( have_output ) printf( "%c", separator );
if ( have_output ) printf("%c", separator);
if ( colour >= 0 )
printf( "%d", monitor->actionColour( colour ) );
printf("%d", monitor->actionColour(colour));
else
printf( "%d", monitor->actionColour() );
printf("%d", monitor->actionColour());
have_output = true;
}
}
if ( have_output ) {
printf( "\n" );
printf("\n");
}
if ( !function ) {
Usage();
}
delete monitor;
} else {
fprintf(stderr, "Error, invalid monitor id %d\n", mon_id);
Error("Invalid monitor id %d", mon_id);
exit_zmu(-1);
}
} else {
if ( function & ZMU_QUERY ) {
#if ZM_HAS_V4L
char vidString[0x10000] = "";
bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose );
printf( "%s", vidString );
exit_zmu( ok?0:-1 );
bool ok = LocalCamera::GetCurrentSettings(device, vidString, v4lVersion, verbose);
printf("%s", vidString);
exit_zmu(ok ? 0 : -1);
#else // ZM_HAS_V4L
fprintf( stderr, "Error, video4linux is required for device querying\n" );
exit_zmu( -1 );
Error("Video4linux is required for device querying");
exit_zmu(-1);
#endif // ZM_HAS_V4L
}
@ -702,25 +702,25 @@ int main(int argc, char *argv[]) {
}
sql += " order by Id asc";
if ( mysql_query( &dbconn, sql.c_str() ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit_zmu( mysql_errno( &dbconn ) );
if ( mysql_query(&dbconn, sql.c_str()) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
exit_zmu(mysql_errno(&dbconn));
}
MYSQL_RES *result = mysql_store_result( &dbconn );
MYSQL_RES *result = mysql_store_result(&dbconn);
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit_zmu( mysql_errno( &dbconn ) );
Error("Can't use query result: %s", mysql_error(&dbconn));
exit_zmu(mysql_errno(&dbconn));
}
Debug( 1, "Got %d monitors", mysql_num_rows( result ) );
Debug(1, "Got %d monitors", mysql_num_rows(result));
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
printf("%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate");
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
int mon_id = atoi(dbrow[0]);
int function = atoi(dbrow[1]);
if ( !user || user->canAccess( mon_id ) ) {
if ( !user || user->canAccess(mon_id) ) {
if ( function > 1 ) {
Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY );
Monitor *monitor = Monitor::Load(mon_id, false, Monitor::QUERY);
if ( monitor && monitor->connect() ) {
struct timeval tv = monitor->GetTimestamp();
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8" PRIu64 "%8.2f\n",
@ -738,7 +738,7 @@ int main(int argc, char *argv[]) {
}
} else {
struct timeval tv = { 0, 0 };
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
printf("%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
mon_id,
function,
0,
@ -749,11 +749,11 @@ int main(int argc, char *argv[]) {
0,
0.0
);
}
}
}
mysql_free_result( result );
}
} // end if function filter
} // endif !user || canAccess(mon_id)
} // end foreach row
mysql_free_result(result);
} // end if function && ZMU_LIST
}
delete user;

View File

@ -1 +1 @@
1.33.5
1.33.6

View File

@ -735,29 +735,29 @@ function buildControlCommand( $monitor ) {
return( $ctrlCommand );
}
function sendControlCommand($mid,$command) {
function sendControlCommand($mid, $command) {
// Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
$socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
if ( $socket < 0 ) {
Fatal( 'socket_create() failed: '.socket_strerror($socket) );
Fatal('socket_create() failed: '.socket_strerror($socket));
}
$sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$mid.'.sock';
if ( @socket_connect( $socket, $sockFile ) ) {
if ( @socket_connect($socket, $sockFile) ) {
$options = array();
foreach ( explode( ' ', $command ) as $option ) {
if ( preg_match( '/--([^=]+)(?:=(.+))?/', $option, $matches ) ) {
foreach ( explode(' ', $command) as $option ) {
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1;
}
}
$optionString = jsonEncode( $options );
if ( !socket_write( $socket, $optionString ) ) {
Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) );
$optionString = jsonEncode($options);
if ( !socket_write($socket, $optionString) ) {
Fatal("Can't write to control socket: ".socket_strerror(socket_last_error($socket)));
}
socket_close( $socket );
socket_close($socket);
} else if ( $command != 'quit' ) {
$command .= ' --id='.$mid;
// Can't connect so use script
$ctrlOutput = exec( escapeshellcmd( $command ) );
$ctrlOutput = exec(escapeshellcmd($command));
}
} // end function sendControlCommand( $mid, $command )
} // end function sendControlCommand($mid, $command)

View File

@ -157,7 +157,8 @@ function csrf_ob_handler($buffer, $flags) {
$input = "<input type='hidden' name='$name' value=\"$tokens\"$endslash>";
$buffer = preg_replace('#(<form[^>]*method\s*=\s*["\']post["\'][^>]*>)#i', '$1' . $input, $buffer);
if ($GLOBALS['csrf']['frame-breaker']) {
$buffer = str_ireplace('</head>', '<script nonce="'.$cspNonce.'">if (top != self) {top.location.href = self.location.href;}</script></head>', $buffer);
$buffer = str_ireplace('</head>', '<script nonce="'.$cspNonce.'">if (top != self) {top.location.href = self.location.href;}</script>
</head>', $buffer);
}
if ($js = $GLOBALS['csrf']['rewrite-js']) {
$buffer = str_ireplace(
@ -165,7 +166,8 @@ function csrf_ob_handler($buffer, $flags) {
'<script nonce="'.$cspNonce.'">'.
'var csrfMagicToken = "'.$tokens.'";'.
'var csrfMagicName = "'.$name.'";</script>'.
'<script src="'.$js.'"></script></head>',
'<script src="'.$js.'"></script>
</head>',
$buffer
);
$script = '<script nonce="'.$cspNonce.'">CsrfMagic.end();</script>';

View File

@ -782,6 +782,7 @@ $SLANG = array(
'VersionRemindNever' => 'Don\'t remind about new versions',
'VersionRemindWeek' => 'Remind again in 1 week',
'Version' => 'Version',
'ViewMatches' => 'View Matches',
'VideoFormat' => 'Video Format',
'VideoGenFailed' => 'Video Generation Failed!',
'VideoGenFiles' => 'Existing Video Files',

View File

@ -149,26 +149,18 @@ echo output_link_if_exists( array(
if ( $skinJsPhpFile ) {
?>
<script nonce="<?php echo $cspNonce; ?>">
//<![CDATA[
<!--
<?php
require_once( $skinJsPhpFile );
?>
//-->
//]]>
</script>
<?php
}
if ( $viewJsPhpFile ) {
?>
<script nonce="<?php echo $cspNonce; ?>">
//<![CDATA[
<!--
<?php
require_once( $viewJsPhpFile );
?>
//-->
//]]>
</script>
<?php
}
@ -186,12 +178,12 @@ echo output_link_if_exists( array(
if ($basename == 'watch' or $basename == 'log' ) {
// This is used in the log popup for the export function. Not sure if it's used anywhere else
?>
<script type="text/javascript" src="js/overlay.js"></script>
<script src="js/overlay.js"></script>
<?php } ?>
<?php
if ( $viewJsFile ) {
?>
<script type="text/javascript" src="<?php echo cache_bust($viewJsFile) ?>"></script>
<script src="<?php echo cache_bust($viewJsFile) ?>"></script>
<?php
}
?>

View File

@ -293,8 +293,8 @@ for ( $i=0; $i < count($terms); $i++ ) {
?>
<td><?php if ( count($terms) > 2 ) { echo htmlSelect("filter[Query][terms][$i][cbr]", $cbracketTypes, $term['cbr']); } else { ?>&nbsp;<?php } ?></td>
<td>
<input type="button" data-on-click-this="addTerm" value="+"/>
<input type="button" data-on-click-this="delTerm" value="-" <?php echo count($terms) == 1 ? 'disabled' : '' ?>/>
<button type="button" data-on-click-this="addTerm">+</button>
<button type="button" data-on-click-this="delTerm" <?php echo count($terms) == 1 ? 'disabled' : '' ?>>-</button>
</td>
</tr>
<?php
@ -392,8 +392,8 @@ if ( ZM_OPT_MESSAGE ) {
<input type="checkbox" name="filter[AutoDelete]" value="1"<?php if ( $filter->AutoDelete() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/>
</p>
<p><label><?php echo translate('FilterMoveEvents') ?></label>
<input type="checkbox" name="filter[AutoMove]" value="1"<?php if ( $filter->AutoMove() ) { ?> checked="checked"<?php } ?> onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/>
<?php echo htmlSelect('filter[AutoMoveTo]', $storageareas, $filter->AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' )); ?>
<input type="checkbox" name="filter[AutoMove]" value="1"<?php if ( $filter->AutoMove() ) { ?> checked="checked"<?php } ?> data-on-click-this="click_automove"/>
<?php echo htmlSelect('filter[AutoMoveTo]', $storageareas, $filter->AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;')); ?>
</p>
<p>
<label for="background"><?php echo translate('BackgroundFilter') ?></label>
@ -407,6 +407,7 @@ if ( ZM_OPT_MESSAGE ) {
<hr/>
<div id="contentButtons">
<button type="submit" data-on-click-this="submitToEvents"><?php echo translate('ListMatches') ?></button>
<!--<button type="submit" data-on-click-this="submitToMontageReview"><?php echo translate('ViewMatches') ?></button>-->
<button type="button" data-on-click-this="submitToExport"><?php echo translate('ExportMatches') ?></button>
<button type="button" name="executeButton" id="executeButton" data-on-click-this="executeFilter"><?php echo translate('Execute') ?></button>
<?php

View File

@ -63,6 +63,15 @@ function updateButtons(element) {
}
}
function click_automove(element) {
updateButtons(this);
if ( this.checked ) {
$j(this.form.elements['filter[AutoMoveTo]']).css('display', 'inline');
} else {
this.form.elements['filter[AutoMoveTo]'].hide();
}
}
function checkValue( element ) {
var rows = $j(element).closest('tbody').children();
parseRows(rows);
@ -83,6 +92,11 @@ function submitToEvents( element ) {
form.action = thisUrl + '?view=events';
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
}
function submitToMontageReview( element ) {
var form = element.form;
form.action = thisUrl + '?view=montagereview';
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
}
function submitToExport(element) {
var form = element.form;

View File

@ -59,8 +59,13 @@ include('_monitor_filters.php');
$filter_bar = ob_get_contents();
ob_end_clean();
if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
$filter = array(
$filter = array();
if ( isset($_REQUEST['filter']) ) {
$filter = $_REQUEST['filter'];
} else {
if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
$filter = array(
'Query' => array(
'terms' => array(
array('attr' => 'StartDateTime', 'op' => '>=', 'val' => $_REQUEST['minTime'], 'obr' => '1'),
@ -68,21 +73,22 @@ if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($display
)
),
);
if ( count($selected_monitor_ids) ) {
$filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => 'IN', 'val' => implode(',',$selected_monitor_ids), 'cnj' => 'and'));
} else if ( ( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) ) {
# this should be redundant
for ($i=0; $i < count($displayMonitors); $i++) {
if ($i == '0') {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
} else if ($i == (count($displayMonitors)-1)) {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
} else {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
if ( count($selected_monitor_ids) ) {
$filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => 'IN', 'val' => implode(',',$selected_monitor_ids), 'cnj' => 'and'));
} else if ( ( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) ) {
# this should be redundant
for ($i=0; $i < count($displayMonitors); $i++) {
if ($i == '0') {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
} else if ($i == (count($displayMonitors)-1)) {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
} else {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
}
}
}
}
parseFilter( $filter );
} # end if REQUEST[Filter]
parseFilter($filter);
# This is to enable the download button
session_start();
$_SESSION['montageReviewFilter'] = $filter;

View File

@ -87,8 +87,9 @@ if ( empty($_REQUEST['path']) ) {
$Frame->Id('objdetect');
} else if ( $_REQUEST['fid'] == 'alarm' ) {
# look for first alarmed frame
$Frame = ZM\Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
array('order'=>'FrameId ASC'));
$Frame = ZM\Frame::find_one(
array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
array('order'=>'FrameId ASC'));
if ( !$Frame ) { # no alarms, get first one I find
$Frame = ZM\Frame::find_one(array('EventId'=>$_REQUEST['eid']));
if ( !$Frame ) {
@ -101,7 +102,7 @@ if ( empty($_REQUEST['path']) ) {
$Monitor = $Event->Monitor();
if ( $Monitor->SaveJPEGs() & 1 ) {
# If we store Frames as jpgs, then we don't store an alarmed snapshot
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d', $Frame->FrameId()).'-'.$show.'.jpg';
} else {
$path = $Event->Path().'/alarm.jpg';
}
@ -113,12 +114,16 @@ if ( empty($_REQUEST['path']) ) {
ZM\Warning('No frame found for event ' . $_REQUEST['eid']);
$Frame = new ZM\Frame();
$Frame->Delta(1);
$Frame->FrameId('snapshot');
if ( $Monitor->SaveJPEGs() & 1 ) {
$Frame->FrameId(0);
} else {
$Frame->FrameId('snapshot');
}
}
$Monitor = $Event->Monitor();
if ( $Monitor->SaveJPEGs() & 1 ) {
# If we store Frames as jpgs, then we don't store a snapshot
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d', $Frame->FrameId()).'-'.$show.'.jpg';
} else {
$path = $Event->Path().'/snapshot.jpg';
}