Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2019-07-23 10:14:34 -04:00
commit d3d0579454
22 changed files with 368 additions and 193 deletions

View File

@ -351,6 +351,7 @@ CREATE INDEX `Groups_Monitors_MonitorId_idx` ON `Groups_Monitors` (`MonitorId`);
DROP TABLE IF EXISTS `Logs`;
CREATE TABLE `Logs` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`TimeKey` decimal(16,6) NOT NULL,
`Component` varchar(32) NOT NULL,
`ServerId` int(10) unsigned,
@ -360,6 +361,7 @@ CREATE TABLE `Logs` (
`Message` text NOT NULL,
`File` varchar(255) DEFAULT NULL,
`Line` smallint(5) unsigned DEFAULT NULL,
PRIMARY KEY (`Id`),
KEY `TimeKey` (`TimeKey`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -589,6 +591,7 @@ CREATE INDEX `Servers_Name_idx` ON `Servers` (`Name`);
DROP TABLE IF EXISTS `Stats`;
CREATE TABLE `Stats` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`MonitorId` int(10) unsigned NOT NULL default '0',
`ZoneId` int(10) unsigned NOT NULL default '0',
`EventId` BIGINT UNSIGNED NOT NULL,
@ -605,6 +608,7 @@ CREATE TABLE `Stats` (
`MinY` smallint(5) unsigned NOT NULL default '0',
`MaxY` smallint(5) unsigned NOT NULL default '0',
`Score` smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (`Id`),
KEY `EventId` (`EventId`),
KEY `MonitorId` (`MonitorId`),
KEY `ZoneId` (`ZoneId`)
@ -745,7 +749,7 @@ insert into Storage VALUES (NULL, '@ZM_DIR_EVENTS@', 'Default', 'local', NULL, N
--
-- Create a default admin user.
--
insert into Users VALUES (NULL,'admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','Edit','Edit','','',0,1);
insert into Users VALUES (NULL,'admin','$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6','',1,'View','Edit','Edit','Edit','Edit','Edit','Edit','','',0,1);
--
-- Add a sample filter to purge the oldest 100 events when the disk is 95% full

27
db/zm_update-1.33.12.sql Normal file
View File

@ -0,0 +1,27 @@
--
-- Add primary keys for Logs and Stats tables
--
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Logs'
AND column_name = 'Id'
) > 0,
"SELECT 'Column Id already exists in Logs'",
"ALTER TABLE `Logs` ADD COLUMN `Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`Id`)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Stats'
AND column_name = 'Id'
) > 0,
"SELECT 'Column Id already exists in Stats'",
"ALTER TABLE `Stats` ADD COLUMN `Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`Id`)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -23,7 +23,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.33.9
Version: 1.33.12
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@ -411,6 +411,9 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%changelog
* Sun Jul 07 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.12-1
- Bump to 1.33.12 Development
* Sun Jun 23 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.9-1
- Bump to 1.33.9 Development

View File

@ -728,6 +728,7 @@ sub substituteTags {
}
if ( $text =~ s/%EIMOD%//g ) {
$text =~ s/%EIMOD%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=objdetect/g;
my $path = $Event->Path().'/objdetect.jpg';
if ( -e $path ) {
push @$attachments_ref, { type=>'image/jpeg', path=>$path };

View File

@ -21,6 +21,9 @@
#include "zm_ffmpeg.h"
#include "zm_image.h"
#include "zm_rgb.h"
extern "C" {
#include "libavutil/pixdesc.h"
}
#if HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
@ -70,14 +73,14 @@ static bool bInit = false;
void FFMPEGInit() {
if ( !bInit ) {
if ( logDebugging() )
if ( logDebugging() && config.log_ffmpeg ) {
av_log_set_level( AV_LOG_DEBUG );
else
av_log_set_callback(log_libav_callback);
Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options");
} else {
Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor not part of your debug targets");
av_log_set_level( AV_LOG_QUIET );
if ( config.log_ffmpeg )
av_log_set_callback(log_libav_callback);
else
Info("Not enabling ffmpeg logs, as LOG_FFMPEG is disabled in options");
}
#if LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)
#else
av_register_all();
@ -295,25 +298,6 @@ void zm_dump_video_frame(const AVFrame *frame, const char *text) {
frame->pts
);
}
void zm_dump_frame(const AVFrame *frame,const char *text) {
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),
frame->sample_rate,
frame->nb_samples,
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
frame->channels,
frame->pkt_duration,
#else
0, 0,
#endif
frame->channel_layout,
frame->pts
);
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar ( const AVCodecParameters *par ) {
@ -536,6 +520,45 @@ int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
return 0;
} // end int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet)
int zm_send_frame(AVCodecContext *ctx, AVFrame *frame, AVPacket &packet) {
int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ( (ret = avcodec_send_frame(ctx, frame)) < 0 ) {
Error("Could not send frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&packet);
return 0;
}
if ( (ret = avcodec_receive_packet(ctx, &packet)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) {
// The codec may need more samples than it has, perfectly valid
Debug(2, "Codec not ready to give us a packet");
} else {
Error("Could not recieve packet (error %d = '%s')", ret,
av_make_error_string(ret).c_str());
}
zm_av_packet_unref(&packet);
return 0;
}
#else
int data_present;
if ( (ret = avcodec_encode_audio2(
ctx, &packet, frame, &data_present)) < 0 ) {
Error("Could not encode frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&packet);
return 0;
}
if ( !data_present ) {
Debug(2, "Not ready to out a frame yet.");
zm_av_packet_unref(&packet);
return 0;
}
#endif
return 1;
} // wend zm_send_frame
void dumpPacket(AVStream *stream, AVPacket *pkt, const char *text) {
char b[10240];

View File

@ -299,7 +299,36 @@ void zm_dump_codec(const AVCodecContext *codec);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar(const AVCodecParameters *par);
#endif
void zm_dump_frame(const AVFrame *frame, const char *text="Frame");
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
#define zm_dump_frame(frame, text) Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d" \
" duration %" PRId64 \
" layout %d pts %" PRId64,\
text, \
frame->format, \
av_get_sample_fmt_name((AVSampleFormat)frame->format), \
frame->sample_rate, \
frame->nb_samples, \
frame->channels, \
frame->pkt_duration, \
frame->channel_layout, \
frame->pts \
);
#else
#define zm_dump_frame(frame, text) Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d" \
" duration %" PRId64 \
" layout %d pts %" PRId64, \
text, \
frame->format, \
av_get_sample_fmt_name((AVSampleFormat)frame->format), \
frame->sample_rate, \
frame->nb_samples, \
0, 0, \
frame->channel_layout, \
frame->pts \
);
#endif
void zm_dump_video_frame(const AVFrame *frame, const char *text="Frame");
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
@ -332,7 +361,9 @@ bool is_audio_stream(AVStream *);
bool is_video_context(AVCodec *);
bool is_audio_context(AVCodec *);
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet );
int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
int zm_send_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
void dumpPacket(AVStream *, AVPacket *,const char *text="");
void dumpPacket(AVPacket *,const char *text="");
#endif // ZM_FFMPEG_H

View File

@ -29,6 +29,7 @@ extern "C" {
#if HAVE_LIBAVUTIL_HWCONTEXT_H
#include "libavutil/hwcontext.h"
#endif
#include "libavutil/pixdesc.h"
}
#ifndef AV_ERROR_MAX_STRING_SIZE
#define AV_ERROR_MAX_STRING_SIZE 64
@ -135,7 +136,6 @@ FfmpegCamera::FfmpegCamera(
}
hwaccel = false;
hwFrame = NULL;
mFormatContext = NULL;
mVideoStreamId = -1;
@ -153,6 +153,8 @@ FfmpegCamera::FfmpegCamera(
packetqueue = NULL;
error_count = 0;
#if HAVE_LIBAVUTIL_HWCONTEXT_H
hwFrame = NULL;
hw_device_ctx = NULL;
hw_pix_fmt = AV_PIX_FMT_NONE;
#endif
@ -455,36 +457,46 @@ int FfmpegCamera::OpenFfmpeg() {
if ( !config ) {
Debug(1, "Decoder %s does not support device type %s.",
mVideoCodec->name, av_hwdevice_get_type_name(type));
return -1;
break;
}
if ( (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)
&& (config->device_type == type)
) {
hw_pix_fmt = config->pix_fmt;
break;
} else {
Debug(1, "decoder %s hwConfig doesn't match our type: %s, pix_fmt %s.",
mVideoCodec->name,
av_hwdevice_get_type_name(config->device_type),
av_get_pix_fmt_name(config->pix_fmt)
);
}
} // end foreach hwconfig
#else
hw_pix_fmt = find_fmt_by_hw_type(type);
#endif
Debug(1, "Selected gw_pix_fmt %d %s",
hw_pix_fmt,
av_get_pix_fmt_name(hw_pix_fmt));
if ( hw_pix_fmt != AV_PIX_FMT_NONE ) {
Debug(1, "Selected gw_pix_fmt %d %s",
hw_pix_fmt,
av_get_pix_fmt_name(hw_pix_fmt));
mVideoCodecContext->get_format = get_hw_format;
mVideoCodecContext->get_format = get_hw_format;
Debug(1, "Creating hwdevice for %s",
(hwaccel_device != "" ? hwaccel_device.c_str() : ""));
ret = av_hwdevice_ctx_create(&hw_device_ctx, type,
(hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0);
if ( ret < 0 ) {
Error("Failed to create specified HW device.");
return -1;
Debug(1, "Creating hwdevice for %s",
(hwaccel_device != "" ? hwaccel_device.c_str() : ""));
ret = av_hwdevice_ctx_create(&hw_device_ctx, type,
(hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0);
if ( ret < 0 ) {
Error("Failed to create specified HW device.");
return -1;
}
Debug(1, "Created hwdevice");
mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
hwaccel = true;
hwFrame = zm_av_frame_alloc();
} else {
Debug(1, "Failed to setup hwaccel.");
}
Debug(1, "Created hwdevice");
mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
hwaccel = true;
hwFrame = zm_av_frame_alloc();
#else
Warning("HWAccel support not compiled in.");
#endif
@ -637,6 +649,12 @@ int FfmpegCamera::Close() {
av_frame_free(&mRawFrame);
mRawFrame = NULL;
}
#if HAVE_LIBAVUTIL_HWCONTEXT_H
if ( hwFrame ) {
av_frame_free(&hwFrame);
hwFrame = NULL;
}
#endif
#if HAVE_LIBSWSCALE
if ( mConvertContext ) {
@ -665,6 +683,12 @@ int FfmpegCamera::Close() {
mAudioCodecContext = NULL; // Freed by av_close_input_file
}
#if HAVE_LIBAVUTIL_HWCONTEXT_H
if ( hw_device_ctx ) {
av_buffer_unref(&hw_device_ctx);
}
#endif
if ( mFormatContext ) {
#if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0)
av_close_input_file(mFormatContext);

View File

@ -7,8 +7,7 @@ FFmpeg_Input::FFmpeg_Input() {
input_format_context = NULL;
video_stream_id = -1;
audio_stream_id = -1;
av_register_all();
avcodec_register_all();
FFMPEGInit();
streams = NULL;
frame = NULL;
}

View File

@ -157,6 +157,7 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
std::pair<std::string, unsigned int> ans = verifyToken(jwt_token_str, key);
std::string username = ans.first;
unsigned int iat = ans.second;
Debug (1,"retrieved user '%s' from token", username.c_str());
if (username != "") {
char sql[ZM_SQL_MED_BUFSIZ] = "";
@ -178,7 +179,7 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
if ( n_users != 1 ) {
mysql_free_result(result);
Error("Unable to authenticate user %s", username.c_str());
Error("Unable to authenticate user '%s'", username.c_str());
return NULL;
}
@ -188,12 +189,12 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
if (stored_iat > iat ) { // admin revoked tokens
mysql_free_result(result);
Error("Token was revoked for %s", username.c_str());
Error("Token was revoked for '%s'", username.c_str());
return NULL;
}
Debug (1,"Got stored expiry time of %u",stored_iat);
Info ("Authenticated user '%s' via token", username.c_str());
Debug (1,"Authenticated user '%s' via token", username.c_str());
mysql_free_result(result);
return user;

View File

@ -308,7 +308,6 @@ VideoStore::VideoStore(
#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");
@ -476,7 +475,51 @@ VideoStore::~VideoStore() {
break;
}
#endif
// Need to adjust pts and dts and duration
pkt.stream_index = audio_out_stream->index;
pkt.duration = av_rescale_q(
pkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
// Scale the PTS of the outgoing packet to be the correct time base
if ( pkt.pts != AV_NOPTS_VALUE ) {
pkt.pts = av_rescale_q(
pkt.pts,
audio_out_ctx->time_base,
audio_in_stream->time_base);
// audio_first_pts is in audio_in_stream time base
pkt.pts -= audio_first_pts;
pkt.pts = av_rescale_q(
pkt.pts,
audio_in_stream->time_base,
audio_out_stream->time_base);
Debug(2, "audio pkt.pts = %" PRId64 " from first_pts(%" PRId64 ")",
pkt.pts, audio_first_pts);
} else {
Debug(2, "pkt.pts = undef");
pkt.pts = AV_NOPTS_VALUE;
}
if ( pkt.dts != AV_NOPTS_VALUE ) {
pkt.dts = av_rescale_q(
pkt.dts,
audio_out_ctx->time_base,
audio_in_stream->time_base);
pkt.dts -= audio_first_dts;
pkt.dts = av_rescale_q(
pkt.dts,
audio_in_ctx->time_base,
audio_out_stream->time_base);
Debug(2, "pkt.dts = %" PRId64 " - first_dts(%" PRId64 ")",
pkt.dts, audio_first_dts);
} else {
pkt.dts = AV_NOPTS_VALUE;
}
dumpPacket(audio_out_stream, &pkt, "writing flushed packet");
av_interleaved_write_frame(oc, &pkt);
zm_av_packet_unref(&pkt);
@ -1017,8 +1060,8 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
dumpPacket(audio_in_stream, ipkt, "input packet");
if ( audio_out_codec ) {
Debug(2, "Have output codec");
if ( ( ret = zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) < 0 ) {
Debug(3, "Not ready to receive frame");
return 0;
}
@ -1030,13 +1073,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
}
zm_dump_frame(out_frame, "Out frame after resample");
#if 0
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
if ( out_frame->pts != AV_NOPTS_VALUE ) {
if ( !audio_first_pts ) {
audio_first_pts = out_frame->pts;
Debug(1, "No video_first_pts setting to %" PRId64, audio_first_pts);
Debug(1, "No audio_first_pts setting to %" PRId64, audio_first_pts);
out_frame->pts = 0;
} else {
// out_frame_pts is in codec->timebase, audio_first_pts is in packet timebase.
out_frame->pts = out_frame->pts - audio_first_pts;
zm_dump_frame(out_frame, "Out frame after pts adjustment");
}
@ -1046,56 +1091,57 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
out_frame->pts = audio_next_pts;
}
audio_next_pts = out_frame->pts + out_frame->nb_samples;
#endif
av_init_packet(&opkt);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ( (ret = avcodec_send_frame(audio_out_ctx, out_frame)) < 0 ) {
Error("Could not send frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
if ( !zm_send_frame(audio_out_ctx, out_frame, opkt) ) {
return 0;
}
if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) {
// The codec may need more samples than it has, perfectly valid
Debug(2, "Codec not ready to give us a packet");
} else {
Error("Could not recieve packet (error %d = '%s')", ret,
av_make_error_string(ret).c_str());
}
zm_av_packet_unref(&opkt);
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')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
return 0;
}
if ( !data_present ) {
Debug(2, "Not ready to out a frame yet.");
zm_av_packet_unref(&opkt);
return 0;
}
#endif
#if 0
// These should be set by encoder. They may not directly relate to ipkt due to buffering in codec.
opkt.duration = av_rescale_q(opkt.duration,
audio_in_stream->time_base,
audio_out_stream->time_base);
opkt.pts = av_rescale_q(opkt.pts,
audio_in_stream->time_base,
audio_out_stream->time_base);
opkt.dts = av_rescale_q(opkt.dts,
audio_in_stream->time_base,
audio_out_stream->time_base);
#endif
dumpPacket(audio_out_stream, &opkt, "raw opkt");
opkt.duration = av_rescale_q(
opkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
// Scale the PTS of the outgoing packet to be the correct time base
if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( !audio_first_pts ) {
opkt.pts = 0;
audio_first_pts = ipkt->pts;
Debug(1, "No audio_first_pts");
} else {
opkt.pts = av_rescale_q(
opkt.pts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
opkt.pts -= audio_first_pts;
Debug(2, "audio opkt.pts = %" PRId64 " from first_pts %" PRId64,
opkt.pts, audio_first_pts);
}
} else {
Debug(2, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
}
if ( opkt.dts != AV_NOPTS_VALUE ) {
if ( !audio_first_dts ) {
opkt.dts = 0;
audio_first_dts = opkt.dts;
} else {
opkt.dts = av_rescale_q(
opkt.dts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
opkt.dts -= audio_first_dts;
Debug(2, "opkt.dts = %" PRId64 " from first_dts %" PRId64,
opkt.dts, audio_first_dts);
}
audio_last_dts = opkt.dts;
} else {
opkt.dts = AV_NOPTS_VALUE;
}
} else {
Debug(2,"copying");
av_init_packet(&opkt);
@ -1128,16 +1174,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
}
if ( ipkt->dts != AV_NOPTS_VALUE ) {
// So if the in has no dts assigned... still need an out dts... so we use cur_dts?
#if 0
if ( audio_last_dts >= audio_in_stream->cur_dts ) {
Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_in_stream->cur_dts);
opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts, AV_TIME_BASE_Q, audio_out_stream->time_base);
} else {
opkt.dts = audio_next_dts + av_rescale_q( audio_in_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_out_stream->time_base);
}
#endif
if ( !audio_first_dts ) {
opkt.dts = 0;
audio_first_dts = ipkt->dts;
@ -1204,28 +1240,9 @@ int VideoStore::resample_audio() {
av_make_error_string(ret).c_str());
return 0;
}
zm_dump_frame(out_frame, "Out frame after convert");
#if 0
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
if ( out_frame->pts != AV_NOPTS_VALUE ) {
if ( !video_first_pts ) {
video_first_pts = out_frame->pts;
Debug(1, "No video_first_pts setting to %" PRId64, video_first_pts);
out_frame->pts = 0;
} else {
out_frame->pts = out_frame->pts - video_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;
}
audio_next_pts = out_frame->pts + out_frame->nb_samples;
#endif
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples);
if ( ret < 0 ) {
Error("Could not reallocate FIFO");
return 0;
}
@ -1240,7 +1257,7 @@ int VideoStore::resample_audio() {
// 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.
// AAC requires 1024 samples per encode. Our input tends to be something else, so need to buffer them.
if ( frame_size > av_audio_fifo_size(fifo) ) {
return 0;
}
@ -1251,16 +1268,14 @@ int VideoStore::resample_audio() {
}
out_frame->nb_samples = frame_size;
// resampling changes the duration because the timebase is 1/samples
// I think we should be dealing in codec timebases not stream
if ( in_frame->pts != AV_NOPTS_VALUE ) {
out_frame->pkt_duration = av_rescale_q(
in_frame->pkt_duration,
audio_in_stream->time_base,
audio_out_stream->time_base);
out_frame->pts = av_rescale_q(
in_frame->pts,
audio_in_stream->time_base,
audio_out_stream->time_base);
audio_in_ctx->time_base,
audio_out_ctx->time_base);
}
zm_dump_frame(out_frame, "Out frame after timestamp conversion");
#else
#if defined(HAVE_LIBAVRESAMPLE)
ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,

View File

@ -43,9 +43,8 @@ bool ValidateAccess( User *user, int mon_id ) {
allowed = false;
}
if ( !allowed ) {
Error( "Error, insufficient privileges for requested action user %d %s for monitor %d",
user->Id(), user->getUsername(), mon_id );
exit( -1 );
Error("Error, insufficient privileges for requested action user %d %s for monitor %d",
user->Id(), user->getUsername(), mon_id);
}
return allowed;
}
@ -164,8 +163,7 @@ int main( int argc, const char *argv[] ) {
strncpy( auth, value, sizeof(auth)-1 );
} else if ( !strcmp( name, "token" ) ) {
jwt_token_str = value;
Debug(1,"ZMS: JWT token found: %s", jwt_token_str.c_str());
Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
} else if ( !strcmp( name, "user" ) ) {
username = UriDecode( value );
} else if ( !strcmp( name, "pass" ) ) {
@ -184,17 +182,15 @@ int main( int argc, const char *argv[] ) {
} else {
snprintf(log_id_string, sizeof(log_id_string), "zms_e%" PRIu64, event_id);
}
logInit( log_id_string );
logInit(log_id_string);
if ( config.opt_use_auth ) {
User *user = 0;
if (jwt_token_str != "") {
if ( jwt_token_str != "" ) {
//user = zmLoadTokenUser(jwt_token_str, config.auth_hash_ips);
user = zmLoadTokenUser(jwt_token_str, false);
}
else if ( strcmp(config.auth_relay, "none") == 0 ) {
} else if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( checkUser(username.c_str()) ) {
user = zmLoadUser(username.c_str());
} else {
@ -216,21 +212,27 @@ int main( int argc, const char *argv[] ) {
}
}
if ( !user ) {
fprintf(stdout, "HTTP/1.0 401 Unauthorized\r\n");
Error("Unable to authenticate user");
logTerm();
zmDbClose();
return -1;
}
ValidateAccess(user, monitor_id);
if ( !ValidateAccess(user, monitor_id) ) {
fprintf(stdout, "HTTP/1.0 403 Forbidden\r\n");
logTerm();
zmDbClose();
return -1;
}
} // end if config.opt_use_auth
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
setbuf( stdout, 0 );
setbuf(stdout, 0);
if ( nph ) {
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );
fprintf(stdout, "HTTP/1.0 200 OK\r\n");
}
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION );

View File

@ -333,7 +333,7 @@ EOF
fi;
else
echo "dputting to $PPA";
dput $PPA $SC
dput $PPA $SC
fi;
fi;
done; # foreach distro
@ -345,5 +345,3 @@ if [ "$INTERACTIVE" != "no" ]; then
else
rm -fr "$DIRECTORY.orig"; echo "The checked out copy has been deleted";
fi

View File

@ -1 +1 @@
1.33.11
1.33.12

View File

@ -254,6 +254,7 @@ class MonitorsController extends AppController {
throw new BadRequestException(__('Invalid command'));
}
$zm_path_bin = Configure::read('ZM_PATH_BIN');
$mToken = $this->request->query('token') ? $this->request->query('token') : null;
switch ($cmd) {
case 'on':
@ -281,8 +282,12 @@ class MonitorsController extends AppController {
$zmAuthRelay = $config['Config']['Value'];
$auth = '';
if ( $zmOptAuth ) {
if ( $zmAuthRelay == 'hashed' ) {
if ($mToken) {
$auth = ' -T '.$mToken;
}
elseif ( $zmAuthRelay == 'hashed' ) {
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_SECRET'));
$config = $this->Config->find('first', $options);
$zmAuthHashSecret = $config['Config']['Value'];

View File

@ -580,6 +580,9 @@ class Event {
if ( file_exists( $this->Path().'/'.$this->DefaultVideo() ) ) {
return true;
}
if ( !defined('ZM_SERVER_ID') ) {
return false;
}
$Storage= $this->Storage();
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
if ( $Server->Id() != ZM_SERVER_ID ) {
@ -624,6 +627,9 @@ class Event {
if ( file_exists($this->Path().'/'.$this->DefaultVideo()) ) {
return filesize($this->Path().'/'.$this->DefaultVideo());
}
if ( !defined('ZM_SERVER_ID') ) {
return false;
}
$Storage= $this->Storage();
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
if ( $Server->Id() != ZM_SERVER_ID ) {

View File

@ -105,6 +105,7 @@ private $defaults = array(
'DefaultCodec' => 'auto',
);
private $status_fields = array(
'Status' => null,
'AnalysisFPS' => null,
'CaptureFPS' => null,
'CaptureBandwidth' => null,
@ -271,17 +272,27 @@ private $control_fields = array(
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
} else {
if ( array_key_exists($fn, $this->control_fields) ) {
} else if ( array_key_exists($fn, $this->control_fields) ) {
return $this->control_fields{$fn};
} else if ( array_key_exists( $fn, $this->defaults ) ) {
} else if ( array_key_exists( $fn, $this->defaults ) ) {
return $this->defaults{$fn};
} else if ( array_key_exists( $fn, $this->status_fields) ) {
$sql = 'SELECT Status,CaptureFPS,AnalysisFPS,CaptureBandwidth
FROM Monitor_Status WHERE MonitorId=?';
$row = dbFetchOne($sql, NULL, array($this->{'Id'}));
if ( !$row ) {
Error("Unable to load Monitor record for Id=" . $this->{'Id'});
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call Monitor->$fn from $file:$line" );
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
}
return $this->{$fn};
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call Monitor->$fn from $file:$line" );
}
}

View File

@ -2459,11 +2459,13 @@ function do_post_request($url, $data, $optional_headers = null) {
$ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx);
if ( !$fp ) {
throw new Exception("Problem with $url, $php_errormsg");
throw new Exception("Problem with $url, "
.print_r(error_get_last(),true));
}
$response = @stream_get_contents($fp);
if ( $response === false ) {
throw new Exception("Problem reading data from $url, $php_errormsg");
throw new Exception("Problem reading data from $url, data: ".print_r($params,true)
.print_r(error_get_last(),true));
}
return $response;
}

View File

@ -51,51 +51,51 @@ function newWindow( url, name, width, height ) {
function getPopupSize( tag, width, height ) {
if ( typeof popupSizes == 'undefined' ) {
Error( "Can't find any window sizes" );
return ( {'width': 0, 'height': 0} );
Error("Can't find any window sizes");
return {'width': 0, 'height': 0};
}
var popupSize = Object.clone( popupSizes[tag] );
var popupSize = Object.clone(popupSizes[tag]);
if ( !popupSize ) {
Error( "Can't find window size for tag '"+tag+"'" );
return ( {'width': 0, 'height': 0} );
Error("Can't find window size for tag '"+tag+"'");
return {'width': 0, 'height': 0};
}
if ( popupSize.width && popupSize.height ) {
if ( width || height ) {
Warning( "Ignoring passed dimensions "+width+"x"+height+" when getting popup size for tag '"+tag+"'" );
Warning("Ignoring passed dimensions "+width+"x"+height+" when getting popup size for tag '"+tag+"'");
}
return ( popupSize );
return popupSize;
}
if ( popupSize.addWidth ) {
popupSize.width = popupSize.addWidth;
if ( !width ) {
Error( "Got addWidth but no passed width when getting popup size for tag '"+tag+"'" );
Error("Got addWidth but no passed width when getting popup size for tag '"+tag+"'");
} else {
popupSize.width += parseInt(width);
}
} else if ( width ) {
popupSize.width = width;
Error( "Got passed width but no addWidth when getting popup size for tag '"+tag+"'" );
Error("Got passed width but no addWidth when getting popup size for tag '"+tag+"'");
}
if ( popupSize.minWidth && popupSize.width < popupSize.minWidth ) {
Warning( "Adjusting to minimum width when getting popup size for tag '"+tag+"'" );
Warning("Adjusting to minimum width when getting popup size for tag '"+tag+"'");
popupSize.width = popupSize.minWidth;
}
if ( popupSize.addHeight ) {
popupSize.height = popupSize.addHeight;
if ( !height ) {
Error( "Got addHeight but no passed height when getting popup size for tag '"+tag+"'" );
Error("Got addHeight but no passed height when getting popup size for tag '"+tag+"'");
} else {
popupSize.height += parseInt(height);
}
} else if ( height ) {
popupSize.height = height;
Error( "Got passed height but no addHeight when getting popup size for tag '"+tag+"'" );
Error("Got passed height but no addHeight when getting popup size for tag '"+tag+"'");
}
if ( popupSize.minHeight && ( popupSize.height < popupSize.minHeight ) ) {
Warning( "Adjusting to minimum height ("+popupSize.minHeight+") when getting popup size for tag '"+tag+"' because calculated height is " + popupSize.height );
Warning("Adjusting to minimum height ("+popupSize.minHeight+") when getting popup size for tag '"+tag+"' because calculated height is " + popupSize.height);
popupSize.height = popupSize.minHeight;
}
return ( popupSize );
return popupSize;
}
function zmWindow() {
@ -144,7 +144,7 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
el.addEventListener("click", function onClick(evt) {
var el = this;
var url;
if (el.hasAttribute("href")) {
if ( el.hasAttribute("href") ) {
// <a>
url = el.getAttribute("href");
} else {
@ -167,12 +167,20 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
// 'data-on-click-this' calls the global function in the attribute value with the element when a click happens.
document.querySelectorAll("a[data-on-click-this], button[data-on-click-this], input[data-on-click-this]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click-this");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName);
return;
}
el.onclick = window[fnName].bind(el, el);
});
// 'data-on-click' calls the global function in the attribute value with no arguments when a click happens.
document.querySelectorAll("a[data-on-click], button[data-on-click], input[data-on-click]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName);
return;
}
el.onclick = function() {
window[fnName]();
};
@ -181,6 +189,10 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
// 'data-on-click-true' calls the global function in the attribute value with no arguments when a click happens.
document.querySelectorAll("a[data-on-click-true], button[data-on-click-true], input[data-on-click-true]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click-true");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName);
return;
}
el.onclick = function() {
window[fnName](true);
};
@ -189,12 +201,20 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
// 'data-on-change-this' calls the global function in the attribute value with the element when a change happens.
document.querySelectorAll("select[data-on-change-this], input[data-on-change-this]").forEach(function attachOnChangeThis(el) {
var fnName = el.getAttribute("data-on-change-this");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName);
return;
}
el.onchange = window[fnName].bind(el, el);
});
// 'data-on-change' adds an event listener for the global function in the attribute value when a change happens.
document.querySelectorAll("select[data-on-change], input[data-on-change]").forEach(function attachOnChange(el) {
var fnName = el.getAttribute("data-on-change");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName);
return;
}
el.onchange = window[fnName];
});
});

View File

@ -215,8 +215,12 @@ while ( $event_row = dbFetchNext($results) ) {
( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?>
</td>
<td class="colDuration"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
<td class="colFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames', 'frames', $event->Frames() ) ?></td>
<td class="colAlarmFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames', 'frames', $event->AlarmFrames() ) ?></td>
<td class="colFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->Frames() ) ?></td>
<td class="colAlarmFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->AlarmFrames() ) ?></td>
<td class="colTotScore"><?php echo $event->TotScore() ?></td>
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
<td class="colMaxScore"><?php echo makePopupLink(

View File

@ -24,11 +24,13 @@ if ( !canView('Events') ) {
}
require_once('includes/Frame.php');
$eid = validInt($_REQUEST['eid']);
$Event = new ZM\Event($eid);
$Monitor = $Event->Monitor();
$countSql = 'SELECT COUNT(*) AS FrameCount FROM Frames AS F WHERE 1 ';
$frameSql = 'SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames AS F WHERE 1 ';
$eid = $_REQUEST['eid'];
// override the sort_field handling in parseSort for frames
if ( empty($_REQUEST['sort_field']) )
@ -59,8 +61,6 @@ if ( $_REQUEST['filter']['sql'] ) {
$frameSql .= " ORDER BY $sortColumn $sortOrder,Id $sortOrder";
$Event = new ZM\Event($eid);
$Monitor = $Event->Monitor();
if ( isset( $_REQUEST['scale'] ) ) {
$scale = validNum($_REQUEST['scale']);
@ -75,22 +75,22 @@ if ( isset( $_REQUEST['scale'] ) ) {
$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 1;
$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : 0;
$nEvents = dbFetchOne($countSql, 'FrameCount' );
$nFrames = dbFetchOne($countSql, 'FrameCount' );
if ( !empty($limit) && $nEvents > $limit ) {
$nEvents = $limit;
if ( !empty($limit) && ($nFrames > $limit) ) {
$nFrames = $limit;
}
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
$pages = (int)ceil($nFrames/ZM_WEB_EVENTS_PER_PAGE);
if ( !empty($page) ) {
if ( $page < 0 )
if ( $page <= 0 )
$page = 1;
else if ( $pages and ( $page > $pages ) )
$page = $pages;
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
if ( empty( $limit ) ) {
if ( empty($limit) ) {
$limitAmount = ZM_WEB_EVENTS_PER_PAGE;
} else {
$limitLeft = $limit - $limitStart;
@ -104,7 +104,7 @@ if ( !empty($page) ) {
$maxShortcuts = 5;
$pagination = getPagination($pages, $page, $maxShortcuts, $sortQuery.'&eid='.$eid.$limitQuery.$filterQuery);
$frames = dbFetchAll( $frameSql );
$frames = dbFetchAll($frameSql);
$focusWindow = true;

View File

@ -192,9 +192,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
)
)
);
parseFilter($ZeroSize_filter);
}
?>
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
<td class="colId"><a href="<?php echo $montagereview_link ?>"><?php echo $monitor['Id'] ?></a></td>
@ -219,7 +218,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<?php echo count($FileMissing) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW .'&amp;page=1'.$FileMissing_filter['query'].'">'.count($FileMissing).'</a>' : '0' ?>
</td>
<td class="colZeroSize<?php echo count($ZeroSize) ? ' errorText' : ''?>">
<?php echo count($ZeroSize) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW .'&amp;page=1'.$ZeroSize_filter['query'].'">'.count($FileMissing).'</a>' : '0' ?>
<?php echo count($ZeroSize) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW .'&amp;page=1'.$ZeroSize_filter['query'].'">'.count($ZeroSize).'</a>' : '0' ?>
</td>
</tr>
<?php

View File

@ -78,7 +78,7 @@ if ( canView('Control') && $monitor->Type() == 'Local' ) {
<div id="closeControl"><a href="#" onclick="<?php echo $popup ? 'window.close()' : 'history.go(-1);return false;' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div>
</div>
<?php
if ( $monitor->Status() != 'Capturing' ) {
if ( $monitor->Status() != 'Connected' ) {
echo '<div class="warning">Monitor is not capturing. We will be unable to provide an image</div>';
}
?>