Merge branch 'master' into zma_to_thread
This commit is contained in:
commit
284b9f963f
|
@ -59,7 +59,7 @@ if(NOT HOST_OS)
|
|||
endif(NOT HOST_OS)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||
# Default CLFAGS and CXXFLAGS:
|
||||
set(CMAKE_C_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2")
|
||||
|
|
|
@ -482,7 +482,7 @@ CREATE TABLE `Monitors` (
|
|||
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
|
||||
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
|
||||
`OutputCodec` int(10) unsigned NOT NULL default 0,
|
||||
`Encoder` enum('auto','h264','h264_omx','mjpeg','mpeg1','mpeg2'),
|
||||
`Encoder` enum('auto','h264','libx264','h264_omx','h264_vaapi','mjpeg','mpeg1','mpeg2'),
|
||||
`OutputContainer` enum('auto','mp4','mkv'),
|
||||
`EncoderParameters` TEXT,
|
||||
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
|
||||
|
|
|
@ -239,7 +239,7 @@ use Sys::MemInfo qw(totalmem freemem totalswap freeswap);
|
|||
use ZoneMinder::Server qw(CpuLoad);
|
||||
#use Data::Dumper;
|
||||
|
||||
use constant KILL_DELAY => 60; # seconds to wait between sending TERM and sending KILL
|
||||
use constant KILL_DELAY => 10; # seconds to wait between sending TERM and sending KILL
|
||||
|
||||
our %cmd_hash;
|
||||
our %pid_hash;
|
||||
|
|
|
@ -156,7 +156,7 @@ while( 1 ) {
|
|||
Error("Error reading shared data for $$monitor{Id} $$monitor{Name}");
|
||||
} elsif ( !$image_time ) {
|
||||
# We can't get the last capture time so can't be sure it's died.
|
||||
$restart = 1;
|
||||
#$restart = 1;
|
||||
Error("Last analyse time for $$monitor{Id} $$monitor{Name} was zero.");
|
||||
} else {
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ public:
|
|||
inline unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||
inline unsigned int Size() const { return size; }
|
||||
|
||||
inline unsigned int AVPixFormat() {
|
||||
inline AVPixelFormat AVPixFormat() {
|
||||
if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
return AV_PIX_FMT_RGBA;
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
|
|
|
@ -999,6 +999,7 @@ bool Monitor::connect() {
|
|||
shared_data->format = camera->SubpixelOrder();
|
||||
shared_data->imagesize = camera->ImageSize();
|
||||
shared_data->alarm_cause[0] = 0;
|
||||
shared_data->last_frame_score = 0;
|
||||
trigger_data->size = sizeof(TriggerData);
|
||||
trigger_data->trigger_state = TRIGGER_CANCEL;
|
||||
trigger_data->trigger_score = 0;
|
||||
|
@ -1955,7 +1956,7 @@ bool Monitor::Analyse() {
|
|||
}
|
||||
}
|
||||
noteSet.insert(linked_monitors[i]->Name());
|
||||
score += 50;
|
||||
score += linked_monitors[i]->lastFrameScore(); // 50;
|
||||
} else {
|
||||
Debug(4, "Linked monitor %d %s is not alarmed",
|
||||
linked_monitors[i]->Id(), linked_monitors[i]->Name());
|
||||
|
@ -2195,6 +2196,7 @@ bool Monitor::Analyse() {
|
|||
snap->unlock();
|
||||
return false;
|
||||
}
|
||||
shared_data->last_frame_score = score;
|
||||
} else {
|
||||
Debug(3, "trigger == off");
|
||||
if ( event ) {
|
||||
|
@ -2512,7 +2514,7 @@ int Monitor::Capture() {
|
|||
Debug(1, "Not decoding");
|
||||
} else {
|
||||
Debug(2,"About to decode %p", packet);
|
||||
if ( ! packet->decode(camera->get_VideoCodecContext()) ) {
|
||||
if ( packet->decode(camera->get_VideoCodecContext()) < 0 ) {
|
||||
Error("decode failed");
|
||||
} // end if decode
|
||||
} // end if decoding
|
||||
|
|
|
@ -135,7 +135,8 @@ protected:
|
|||
uint8_t signal; /* +54 */
|
||||
uint8_t format; /* +55 */
|
||||
uint32_t imagesize; /* +56 */
|
||||
uint32_t epadding1; /* +60 */
|
||||
uint32_t last_frame_score; /* +60 */
|
||||
// uint32_t epadding1; /* +60 */
|
||||
/*
|
||||
** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038.
|
||||
** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16.
|
||||
|
@ -228,6 +229,10 @@ protected:
|
|||
inline bool isConnected() const { return connected && shared_data->valid; }
|
||||
inline time_t getLastConnectTime() const { return last_connect_time; }
|
||||
|
||||
inline uint32_t lastFrameScore() {
|
||||
return shared_data->last_frame_score;
|
||||
}
|
||||
|
||||
bool connect();
|
||||
bool disconnect();
|
||||
|
||||
|
|
|
@ -216,11 +216,12 @@ AVFrame *ZMPacket::get_out_frame( const AVCodecContext *ctx ) {
|
|||
Error("Unable to allocate a frame");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
codec_imgsize = av_image_get_buffer_size(
|
||||
ctx->pix_fmt,
|
||||
ctx->width,
|
||||
ctx->height, 1);
|
||||
ctx->height, 32);
|
||||
buffer = (uint8_t *)av_malloc(codec_imgsize);
|
||||
av_image_fill_arrays(
|
||||
out_frame->data,
|
||||
|
@ -229,7 +230,7 @@ AVFrame *ZMPacket::get_out_frame( const AVCodecContext *ctx ) {
|
|||
ctx->pix_fmt,
|
||||
ctx->width,
|
||||
ctx->height,
|
||||
1);
|
||||
32);
|
||||
#else
|
||||
codec_imgsize = avpicture_get_size(
|
||||
ctx->pix_fmt,
|
||||
|
|
|
@ -28,11 +28,10 @@ zm_packetqueue::zm_packetqueue(
|
|||
int p_video_stream_id,
|
||||
int p_audio_stream_id
|
||||
):
|
||||
video_stream_id(p_video_stream_id),
|
||||
video_stream_id(p_video_stream_id),
|
||||
max_video_packet_count(video_image_count),
|
||||
deleting(false)
|
||||
{
|
||||
video_stream_id = p_video_stream_id;
|
||||
max_video_packet_count = video_image_count-1;
|
||||
analysis_it = pktQueue.begin();
|
||||
|
||||
max_stream_id = p_video_stream_id > p_audio_stream_id ? p_video_stream_id : p_audio_stream_id;
|
||||
|
@ -43,7 +42,6 @@ video_stream_id(p_video_stream_id),
|
|||
|
||||
zm_packetqueue::~zm_packetqueue() {
|
||||
deleting = true;
|
||||
Debug(4, "In destructor");
|
||||
/* zma might be waiting. Must have exclusive access */
|
||||
while ( ! mutex.try_lock() ) {
|
||||
Debug(4, "Waiting for exclusive access");
|
||||
|
@ -51,12 +49,9 @@ zm_packetqueue::~zm_packetqueue() {
|
|||
}
|
||||
|
||||
while ( !pktQueue.empty() ) {
|
||||
Debug(4, "Fronting packet %d", pktQueue.empty());
|
||||
ZMPacket * packet = pktQueue.front();
|
||||
Debug(4, "poppng packet %d", packet->image_index);
|
||||
pktQueue.pop_front();
|
||||
if ( packet->image_index == -1 ) {
|
||||
Debug(4, "Deletng packet");
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +74,8 @@ bool zm_packetqueue::queuePacket(ZMPacket* zm_packet) {
|
|||
|
||||
pktQueue.push_back(zm_packet);
|
||||
packet_counts[zm_packet->packet.stream_index] += 1;
|
||||
Debug(1, "packet counts for %d is %d",
|
||||
zm_packet->packet.stream_index, packet_counts[zm_packet->packet.stream_index]);
|
||||
if ( analysis_it == pktQueue.end() ) {
|
||||
// Analsys_it should only point to end when queue is empty
|
||||
Debug(4, "pointing analysis_it to back");
|
||||
|
@ -95,8 +92,8 @@ bool zm_packetqueue::queuePacket(ZMPacket* zm_packet) {
|
|||
while ( packet_counts[video_stream_id] > max_video_packet_count ) {
|
||||
//clearQueue(max_video_packet_count, video_stream_id);
|
||||
//clearQueue is rather heavy. Since this is the only packet injection spot, we can just start at the beginning of the queue and remove packets until we get to the next video keyframe
|
||||
Debug(1, "Deleting a packet with stream index (%d) with keyframe(%d), Image_index(%d) video_frames_to_keep is (%d) max: %d",
|
||||
zm_packet->packet.stream_index, zm_packet->keyframe, zm_packet->image_index, packet_counts[video_stream_id] , max_video_packet_count);
|
||||
Debug(1, "Deleting a packet with stream index (%d) with keyframe(%d), video_frames_to_keep is (%d) max: %d",
|
||||
zm_packet->packet.stream_index, zm_packet->keyframe, packet_counts[video_stream_id], max_video_packet_count);
|
||||
ZMPacket *zm_packet = *pktQueue.begin();
|
||||
pktQueue.pop_front();
|
||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
|
||||
#if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
|
||||
SWScale::SWScale() : gotdefaults(false), swscale_ctx(nullptr), input_avframe(nullptr), output_avframe(nullptr) {
|
||||
Debug(4,"SWScale object created");
|
||||
|
||||
Debug(4, "SWScale object created");
|
||||
}
|
||||
|
||||
bool SWScale::init() {
|
||||
|
@ -68,10 +67,14 @@ SWScale::~SWScale() {
|
|||
swscale_ctx = nullptr;
|
||||
}
|
||||
|
||||
Debug(4,"SWScale object destroyed");
|
||||
Debug(4, "SWScale object destroyed");
|
||||
}
|
||||
|
||||
int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
int SWScale::SetDefaults(
|
||||
enum _AVPIXELFORMAT in_pf,
|
||||
enum _AVPIXELFORMAT out_pf,
|
||||
unsigned int width,
|
||||
unsigned int height) {
|
||||
|
||||
/* Assign the defaults */
|
||||
default_input_pf = in_pf;
|
||||
|
@ -109,16 +112,16 @@ int SWScale::Convert(
|
|||
break;
|
||||
}
|
||||
/* Get the context */
|
||||
swscale_ctx = sws_getCachedContext( swscale_ctx,
|
||||
swscale_ctx = sws_getCachedContext(swscale_ctx,
|
||||
in_frame->width, in_frame->height, format,
|
||||
out_frame->width, out_frame->height, (AVPixelFormat)out_frame->format,
|
||||
SWS_FAST_BILINEAR, NULL, NULL, NULL );
|
||||
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
||||
if ( swscale_ctx == NULL ) {
|
||||
Error("Failed getting swscale context");
|
||||
return -6;
|
||||
}
|
||||
/* Do the conversion */
|
||||
if(!sws_scale(swscale_ctx, in_frame->data, in_frame->linesize, 0, in_frame->height, out_frame->data, out_frame->linesize ) ) {
|
||||
if ( !sws_scale(swscale_ctx, in_frame->data, in_frame->linesize, 0, in_frame->height, out_frame->data, out_frame->linesize ) ) {
|
||||
Error("swscale conversion failed");
|
||||
return -10;
|
||||
}
|
||||
|
@ -138,6 +141,8 @@ int SWScale::Convert(
|
|||
unsigned int new_width,
|
||||
unsigned int new_height
|
||||
) {
|
||||
Debug(1, "Convert: in_buffer %p in_buffer_size %d out_buffer %p size %d width %d height %d width %d height %d",
|
||||
in_buffer, in_buffer_size, out_buffer, out_buffer_size, width, height, new_width, new_height);
|
||||
/* Parameter checking */
|
||||
if ( in_buffer == nullptr ) {
|
||||
Error("NULL Input buffer");
|
||||
|
@ -151,7 +156,7 @@ int SWScale::Convert(
|
|||
// Error("Invalid input or output pixel formats");
|
||||
// return -2;
|
||||
// }
|
||||
if (!width || !height || !new_height || !new_width) {
|
||||
if ( !width || !height || !new_height || !new_width ) {
|
||||
Error("Invalid width or height");
|
||||
return -3;
|
||||
}
|
||||
|
@ -188,7 +193,7 @@ int SWScale::Convert(
|
|||
|
||||
/* Check the buffer sizes */
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height, 1);
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height, 32);
|
||||
#else
|
||||
size_t insize = avpicture_get_size(in_pf, width, height);
|
||||
#endif
|
||||
|
@ -197,7 +202,7 @@ int SWScale::Convert(
|
|||
return -4;
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 1);
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 32);
|
||||
#else
|
||||
size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
|
||||
#endif
|
||||
|
@ -208,7 +213,9 @@ int SWScale::Convert(
|
|||
}
|
||||
|
||||
/* Get the context */
|
||||
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, new_width, new_height, out_pf, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr );
|
||||
swscale_ctx = sws_getCachedContext(
|
||||
swscale_ctx, width, height, in_pf, new_width, new_height,
|
||||
out_pf, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
|
||||
if ( swscale_ctx == nullptr ) {
|
||||
Error("Failed getting swscale context");
|
||||
return -6;
|
||||
|
@ -216,7 +223,7 @@ int SWScale::Convert(
|
|||
|
||||
/* Fill in the buffers */
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
if (av_image_fill_arrays(input_avframe->data, input_avframe->linesize,
|
||||
if ( av_image_fill_arrays(input_avframe->data, input_avframe->linesize,
|
||||
(uint8_t*) in_buffer, in_pf, width, height, 1) <= 0) {
|
||||
#else
|
||||
if (avpicture_fill((AVPicture*) input_avframe, (uint8_t*) in_buffer,
|
||||
|
@ -226,10 +233,10 @@ int SWScale::Convert(
|
|||
return -7;
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
|
||||
if ( av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
|
||||
out_buffer, out_pf, new_width, new_height, 1) <= 0) {
|
||||
#else
|
||||
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
|
||||
if ( avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
|
||||
new_height) <= 0) {
|
||||
#endif
|
||||
Error("Failed filling output frame with output buffer");
|
||||
|
@ -237,7 +244,9 @@ int SWScale::Convert(
|
|||
}
|
||||
|
||||
/* Do the conversion */
|
||||
if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) {
|
||||
if ( !sws_scale(swscale_ctx,
|
||||
input_avframe->data, input_avframe->linesize,
|
||||
0, height, output_avframe->data, output_avframe->linesize ) ) {
|
||||
Error("swscale conversion failed");
|
||||
return -10;
|
||||
}
|
||||
|
@ -245,18 +254,33 @@ int SWScale::Convert(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
int SWScale::Convert(
|
||||
const uint8_t* in_buffer,
|
||||
const size_t in_buffer_size,
|
||||
uint8_t* out_buffer,
|
||||
const size_t out_buffer_size,
|
||||
enum _AVPIXELFORMAT in_pf,
|
||||
enum _AVPIXELFORMAT out_pf,
|
||||
unsigned int width,
|
||||
unsigned int height) {
|
||||
return Convert(in_buffer, in_buffer_size, out_buffer, out_buffer_size, in_pf, out_pf, width, height, width, height);
|
||||
}
|
||||
|
||||
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
int SWScale::Convert(
|
||||
const Image* img,
|
||||
uint8_t* out_buffer,
|
||||
const size_t out_buffer_size,
|
||||
enum _AVPIXELFORMAT in_pf,
|
||||
enum _AVPIXELFORMAT out_pf,
|
||||
unsigned int width,
|
||||
unsigned int height) {
|
||||
if ( img->Width() != width ) {
|
||||
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
|
||||
Error("Source image width differs. Source: %d Output: %d", img->Width(), width);
|
||||
return -12;
|
||||
}
|
||||
|
||||
if ( img->Height() != height ) {
|
||||
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
|
||||
Error("Source image height differs. Source: %d Output: %d", img->Height(), height);
|
||||
return -13;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,10 +88,12 @@ VideoStore::VideoStore(
|
|||
audio_next_pts = 0;
|
||||
out_format = NULL;
|
||||
oc = NULL;
|
||||
|
||||
swscale.init();
|
||||
} // VideoStore::VideoStore
|
||||
|
||||
bool VideoStore::open() {
|
||||
Info("Opening video storage stream %s format: %s", filename, format);
|
||||
Debug(1, "Opening video storage stream %s format: %s", filename, format);
|
||||
|
||||
int ret = avformat_alloc_output_context2(&oc, nullptr, nullptr, filename);
|
||||
if ( ret < 0 ) {
|
||||
|
@ -132,6 +134,19 @@ bool VideoStore::open() {
|
|||
zm_dump_codecpar(video_in_stream->codecpar);
|
||||
}
|
||||
|
||||
int wanted_codec = monitor->OutputCodec();
|
||||
if ( !wanted_codec ) {
|
||||
// default to h264
|
||||
Debug(2, "Defaulting to H264");
|
||||
wanted_codec = AV_CODEC_ID_H264;
|
||||
// FIXME what is the optimal codec? Probably low latency h264 which is effectively mjpeg
|
||||
} else {
|
||||
Debug(2, "Codec is %d, wanted %d", video_in_ctx->codec_id, wanted_codec);
|
||||
}
|
||||
std::string wanted_encoder = monitor->Encoder();
|
||||
|
||||
// FIXME Should check that we are set to passthrough. Might be same codec, but want privacy overlays
|
||||
if ( (!wanted_codec) or (video_in_ctx->codec_id == wanted_codec) ) {
|
||||
video_out_ctx = avcodec_alloc_context3(NULL);
|
||||
if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
|
@ -140,23 +155,19 @@ bool VideoStore::open() {
|
|||
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( !video_out_ctx->codec_tag ) {
|
||||
video_out_ctx->codec_tag =
|
||||
av_codec_get_tag(oc->oformat->codec_tag, video_in_ctx->codec_id);
|
||||
av_codec_get_tag(oc->oformat->codec_tag, video_out_ctx->codec_id);
|
||||
Debug(2, "No codec_tag, setting to %d", video_out_ctx->codec_tag);
|
||||
}
|
||||
int wanted_codec = monitor->OutputCodec();
|
||||
if ( !wanted_codec ) {
|
||||
// default to h264
|
||||
//Debug(2, "Defaulting to H264");
|
||||
//wanted_codec = AV_CODEC_ID_H264;
|
||||
} else {
|
||||
Debug(2, "Codec is %d, wanted %d", video_in_ctx->codec_id, wanted_codec);
|
||||
}
|
||||
|
||||
// FIXME Should check that we are set to passthrough. Might be same codec, but want privacy overlays
|
||||
if ( (!wanted_codec) or (video_in_ctx->codec_id == wanted_codec) ) {
|
||||
// Copy params from instream to ctx
|
||||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
if ( ! (video_out_ctx->time_base.num && video_out_ctx->time_base.den) ) {
|
||||
Debug(2,"No timebase found in video in context, defaulting to Q");
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
}
|
||||
// Copy params from instream to ctx
|
||||
// There might not be a useful video_in_stream. v4l in might not populate this very
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
ret = avcodec_parameters_to_context(video_out_ctx, video_in_stream->codecpar);
|
||||
#else
|
||||
|
@ -167,7 +178,6 @@ bool VideoStore::open() {
|
|||
return false;
|
||||
}
|
||||
//video_out_ctx->time_base = (AVRational){1, 1000000}; // microseconds as base frame rate
|
||||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
// Fix deprecated formats
|
||||
switch ( video_out_ctx->pix_fmt ) {
|
||||
case AV_PIX_FMT_YUVJ422P :
|
||||
|
@ -187,18 +197,44 @@ bool VideoStore::open() {
|
|||
}
|
||||
} else { // Either no video in or not the desired codec
|
||||
for ( unsigned int i = 0; i < sizeof(codec_data) / sizeof(*codec_data); i++ ) {
|
||||
if ( wanted_encoder != "" ) {
|
||||
if ( wanted_encoder != codec_data[i].codec_name ) {
|
||||
Debug(1, "Not the right codec name %s != %s", codec_data[i].codec_name, wanted_encoder.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( codec_data[i].codec_id != wanted_codec ) {
|
||||
Debug(1, "Not the right codec %d != %d", codec_data[i].codec_id, wanted_codec);
|
||||
continue;
|
||||
}
|
||||
|
||||
video_out_codec = avcodec_find_encoder_by_name(codec_data[i].codec_name);
|
||||
if ( ! video_out_codec ) {
|
||||
if ( !video_out_codec ) {
|
||||
Debug(1, "Didn't find encoder for %s", codec_data[i].codec_name);
|
||||
continue;
|
||||
}
|
||||
Debug(1, "Found video codec for %s", codec_data[i].codec_name);
|
||||
video_out_ctx = avcodec_alloc_context3(video_out_codec);
|
||||
if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
#else
|
||||
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( !video_out_ctx->codec_tag ) {
|
||||
video_out_ctx->codec_tag =
|
||||
av_codec_get_tag(oc->oformat->codec_tag, video_out_ctx->codec_id);
|
||||
Debug(2, "No codec_tag, setting to %d", video_out_ctx->codec_tag);
|
||||
}
|
||||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
if ( ! (video_out_ctx->time_base.num && video_out_ctx->time_base.den) ) {
|
||||
Debug(2,"No timebase found in video in context, defaulting to Q");
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
}
|
||||
|
||||
video_out_ctx->codec_id = codec_data[i].codec_id;
|
||||
video_out_ctx->pix_fmt = codec_data[i].pix_fmt;
|
||||
video_out_ctx->level = 32;
|
||||
|
||||
|
@ -207,22 +243,22 @@ bool VideoStore::open() {
|
|||
video_out_ctx->height = monitor->Height();
|
||||
video_out_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
|
||||
// Just copy them from the in, no reason to choose different
|
||||
video_out_ctx->time_base = video_in_ctx->time_base;
|
||||
if ( ! (video_out_ctx->time_base.num && video_out_ctx->time_base.den) ) {
|
||||
Debug(2,"No timebase found in video in context, defaulting to Q");
|
||||
video_out_ctx->time_base = AV_TIME_BASE_Q;
|
||||
}
|
||||
video_out_stream->time_base = video_in_stream ? video_in_stream->time_base : AV_TIME_BASE_Q;
|
||||
|
||||
if ( video_out_ctx->codec_id == AV_CODEC_ID_H264 ) {
|
||||
/*
|
||||
video_out_ctx->bit_rate = 2000000;
|
||||
video_out_ctx->gop_size = 12;
|
||||
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);
|
||||
Debug(2, "setting priv_data crf");
|
||||
av_opt_set(video_out_ctx->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN);
|
||||
Debug(2, "setting priv_data preset");
|
||||
av_opt_set(video_out_ctx->priv_data, "preset", "ultrafast", 0);
|
||||
} else {
|
||||
Debug(2, "Not setting priv_data");
|
||||
av_opt_set(video_out_ctx->priv_data, "preset", "fast", 0);
|
||||
Debug(2, "Not setting priv_data");
|
||||
}
|
||||
*/
|
||||
} else if ( video_out_ctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ) {
|
||||
/* just for testing, we also add B frames */
|
||||
video_out_ctx->max_b_frames = 2;
|
||||
|
@ -235,13 +271,12 @@ bool VideoStore::open() {
|
|||
|
||||
AVDictionary *opts = 0;
|
||||
std::string Options = monitor->GetEncoderOptions();
|
||||
Debug(2, "Options?");
|
||||
Debug(2, "Options? %s", Options.c_str());
|
||||
ret = av_dict_parse_string(&opts, Options.c_str(), "=", ",#\n", 0);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not parse ffmpeg encoder options list '%s'\n", Options.c_str());
|
||||
} else {
|
||||
AVDictionaryEntry *e = NULL;
|
||||
AVDictionaryEntry *e = nullptr;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Debug(3, "Encoder Option %s=%s", e->key, e->value);
|
||||
}
|
||||
|
@ -252,16 +287,15 @@ bool VideoStore::open() {
|
|||
video_out_codec->name,
|
||||
av_make_error_string(ret).c_str()
|
||||
);
|
||||
video_out_codec = NULL;
|
||||
video_out_codec = nullptr;
|
||||
}
|
||||
|
||||
AVDictionaryEntry *e = NULL;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
AVDictionaryEntry *e = nullptr;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != nullptr ) {
|
||||
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
if ( video_out_codec ) break;
|
||||
|
||||
} // end foreach codec
|
||||
|
||||
if ( !video_out_codec ) {
|
||||
|
@ -270,12 +304,12 @@ bool VideoStore::open() {
|
|||
// We allocate and copy in newer ffmpeg, so need to free it
|
||||
avcodec_free_context(&video_out_ctx);
|
||||
#endif
|
||||
video_out_ctx = NULL;
|
||||
video_out_ctx = nullptr;
|
||||
|
||||
return false;
|
||||
} // end if can't open codec
|
||||
|
||||
Debug(2, "Sucess opening codec");
|
||||
Debug(2, "Success opening codec");
|
||||
|
||||
} // end if copying or transcoding
|
||||
} // end if video_in_stream
|
||||
|
@ -1026,11 +1060,11 @@ bool VideoStore::setup_resampler() {
|
|||
#endif
|
||||
} // end bool VideoStore::setup_resampler()
|
||||
|
||||
int VideoStore::writePacket( ZMPacket *ipkt ) {
|
||||
int VideoStore::writePacket(ZMPacket *ipkt) {
|
||||
if ( ipkt->packet.stream_index == video_in_stream_index ) {
|
||||
return writeVideoFramePacket( ipkt );
|
||||
return writeVideoFramePacket(ipkt);
|
||||
} else if ( ipkt->packet.stream_index == audio_in_stream_index ) {
|
||||
return writeAudioFramePacket( ipkt );
|
||||
return writeAudioFramePacket(ipkt);
|
||||
}
|
||||
Error("Unknown stream type in packet (%d) out input video stream is (%d) and audio is (%d)",
|
||||
ipkt->packet.stream_index, video_in_stream_index, ( audio_in_stream ? audio_in_stream_index : -1 )
|
||||
|
@ -1044,10 +1078,10 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) {
|
|||
|
||||
// if we have to transcode
|
||||
if ( video_out_ctx->codec_id != video_in_ctx->codec_id ) {
|
||||
//Debug(3, "Have encoding video frame count (%d)", frame_count);
|
||||
Debug(3, "Have encoding video frame count (%d)", frame_count);
|
||||
|
||||
if ( !zm_packet->out_frame ) {
|
||||
//Debug(3, "Have no out frame");
|
||||
Debug(3, "Have no out frame");
|
||||
AVFrame *out_frame = zm_packet->get_out_frame(video_out_ctx);
|
||||
if ( !out_frame ) {
|
||||
Error("Unable to allocate a frame");
|
||||
|
@ -1055,23 +1089,23 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) {
|
|||
}
|
||||
|
||||
if ( !zm_packet->in_frame ) {
|
||||
//Debug(2,"Have no in_frame");
|
||||
Debug(2, "Have no in_frame");
|
||||
if ( zm_packet->packet.size ) {
|
||||
//Debug(2,"Decoding");
|
||||
Debug(2, "Decoding");
|
||||
if ( !zm_packet->decode(video_in_ctx) ) {
|
||||
Debug(2, "unable to decode yet.");
|
||||
return 0;
|
||||
}
|
||||
//Go straight to out frame
|
||||
// Go straight to out frame
|
||||
swscale.Convert(zm_packet->in_frame, out_frame);
|
||||
} else if ( zm_packet->image ) {
|
||||
//Debug(2,"Have an image, convert it");
|
||||
Debug(2, "Have an image, convert it");
|
||||
//Go straight to out frame
|
||||
swscale.Convert(
|
||||
zm_packet->image,
|
||||
zm_packet->buffer,
|
||||
zm_packet->codec_imgsize,
|
||||
(AVPixelFormat)zm_packet->image->AVPixFormat(),
|
||||
zm_packet->image->AVPixFormat(),
|
||||
video_out_ctx->pix_fmt,
|
||||
video_out_ctx->width,
|
||||
video_out_ctx->height
|
||||
|
@ -1120,7 +1154,7 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) {
|
|||
}
|
||||
|
||||
av_init_packet(&opkt);
|
||||
opkt.data = NULL;
|
||||
opkt.data = nullptr;
|
||||
opkt.size = 0;
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// Do this to allow the encoder to choose whether to use I/P/B frame
|
||||
|
@ -1168,37 +1202,41 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) {
|
|||
opkt.dts = av_rescale_q(opkt.dts, video_out_ctx->time_base, video_out_stream->time_base);
|
||||
|
||||
int64_t duration;
|
||||
if ( zm_packet->in_frame->pkt_duration ) {
|
||||
duration = av_rescale_q(
|
||||
zm_packet->in_frame->pkt_duration,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base);
|
||||
Debug(1, "duration from ipkt: pts(%" PRId64 ") - last_pts(%" PRId64 ") = (%" PRId64 ") => (%" PRId64 ") (%d/%d) (%d/%d)",
|
||||
zm_packet->in_frame->pts,
|
||||
video_last_pts,
|
||||
zm_packet->in_frame->pkt_duration,
|
||||
duration,
|
||||
video_in_stream->time_base.num,
|
||||
video_in_stream->time_base.den,
|
||||
video_out_stream->time_base.num,
|
||||
video_out_stream->time_base.den
|
||||
);
|
||||
} else {
|
||||
duration =
|
||||
av_rescale_q(
|
||||
zm_packet->in_frame->pts - video_last_pts,
|
||||
if ( zm_packet->in_frame ) {
|
||||
if ( zm_packet->in_frame->pkt_duration ) {
|
||||
duration = av_rescale_q(
|
||||
zm_packet->in_frame->pkt_duration,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base);
|
||||
Debug(1, "duration calc: pts(%" PRId64 ") - last_pts(%" PRId64 ") = (%" PRId64 ") => (%" PRId64 ")",
|
||||
zm_packet->in_frame->pts,
|
||||
video_last_pts,
|
||||
zm_packet->in_frame->pts - video_last_pts,
|
||||
duration
|
||||
);
|
||||
if ( duration <= 0 ) {
|
||||
duration = zm_packet->in_frame->pkt_duration ? zm_packet->in_frame->pkt_duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base);
|
||||
}
|
||||
}
|
||||
Debug(1, "duration from ipkt: pts(%" PRId64 ") - last_pts(%" PRId64 ") = (%" PRId64 ") => (%" PRId64 ") (%d/%d) (%d/%d)",
|
||||
zm_packet->in_frame->pts,
|
||||
video_last_pts,
|
||||
zm_packet->in_frame->pkt_duration,
|
||||
duration,
|
||||
video_in_stream->time_base.num,
|
||||
video_in_stream->time_base.den,
|
||||
video_out_stream->time_base.num,
|
||||
video_out_stream->time_base.den
|
||||
);
|
||||
} else {
|
||||
duration =
|
||||
av_rescale_q(
|
||||
zm_packet->in_frame->pts - video_last_pts,
|
||||
video_in_stream->time_base,
|
||||
video_out_stream->time_base);
|
||||
Debug(1, "duration calc: pts(%" PRId64 ") - last_pts(%" PRId64 ") = (%" PRId64 ") => (%" PRId64 ")",
|
||||
zm_packet->in_frame->pts,
|
||||
video_last_pts,
|
||||
zm_packet->in_frame->pts - video_last_pts,
|
||||
duration
|
||||
);
|
||||
if ( duration <= 0 ) {
|
||||
duration = zm_packet->in_frame->pkt_duration ? zm_packet->in_frame->pkt_duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base);
|
||||
}
|
||||
} // end if in_frmae->pkt_duration
|
||||
} else {
|
||||
duration = av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base);
|
||||
} // end if in_frmae
|
||||
opkt.duration = duration;
|
||||
|
||||
} else { // codec matches, we are doing passthrough
|
||||
|
|
|
@ -24,7 +24,7 @@ class VideoStore {
|
|||
private:
|
||||
|
||||
struct CodecData {
|
||||
const int codec_id;
|
||||
const AVCodecID codec_id;
|
||||
const char *codec_codec;
|
||||
const char *codec_name;
|
||||
const enum AVPixelFormat pix_fmt;
|
||||
|
|
|
@ -156,32 +156,21 @@ class MonitorsController extends AppController {
|
|||
return;
|
||||
}
|
||||
|
||||
$monitor = $this->Monitor->find('first', array(
|
||||
'conditions' => array('Id' => $id)
|
||||
))['Monitor'];
|
||||
|
||||
$message = '';
|
||||
if ( $this->Monitor->save($this->request->data) ) {
|
||||
$message = 'Saved';
|
||||
$Monitor = $this->Monitor->find('first', array(
|
||||
'fields' => array('Function','ServerId'),
|
||||
|
||||
// Stop the monitor. Should happen before saving
|
||||
$this->Monitor->daemonControl($monitor, 'stop');
|
||||
$monitor = $this->Monitor->find('first', array(
|
||||
'conditions' => array('Id' => $id)
|
||||
))['Monitor'];
|
||||
|
||||
// - restart or stop this monitor after change
|
||||
$func = $Monitor['Function'];
|
||||
// We don't pass the request data as the monitor object because it may be a subset of the full monitor array
|
||||
$this->daemonControl($this->Monitor->id, 'stop');
|
||||
if (
|
||||
( $func != 'None' )
|
||||
and
|
||||
(
|
||||
(!defined('ZM_SERVER_ID'))
|
||||
or
|
||||
($Monitor['ServerId']==ZM_SERVER_ID)
|
||||
)
|
||||
) {
|
||||
if ( !defined('ZM_SERVER_ID')) {
|
||||
ZM\Debug("Not defined ZM_SERVER_ID");
|
||||
}
|
||||
$this->daemonControl($this->Monitor->id, 'start');
|
||||
}
|
||||
$this->Monitor->daemonControl($monitor, 'start');
|
||||
} else {
|
||||
$message = 'Error ' . print_r($this->Monitor->invalidFields(), true);
|
||||
}
|
||||
|
@ -353,7 +342,6 @@ class MonitorsController extends AppController {
|
|||
}
|
||||
|
||||
public function daemonControl($id, $command, $daemon=null) {
|
||||
|
||||
// Need to see if it is local or remote
|
||||
$monitor = $this->Monitor->find('first', array(
|
||||
'fields' => array('Type', 'Function', 'Device'),
|
||||
|
@ -361,35 +349,8 @@ class MonitorsController extends AppController {
|
|||
));
|
||||
$monitor = $monitor['Monitor'];
|
||||
|
||||
$daemons = array();
|
||||
if ( ! $daemon ) {
|
||||
if ( $monitor['Function'] == 'Monitor' ) {
|
||||
array_push($daemons, 'zmc');
|
||||
} else {
|
||||
array_push($daemons, 'zmc', 'zma');
|
||||
}
|
||||
} else {
|
||||
array_push($daemons, $daemon);
|
||||
}
|
||||
|
||||
$zm_path_bin = Configure::read('ZM_PATH_BIN');
|
||||
$status_text = $this->Monitor->daemonControl($monitor, $command, $daemon);
|
||||
|
||||
$status_text = '';
|
||||
foreach ( $daemons as $daemon ) {
|
||||
$args = '';
|
||||
if ( $daemon == 'zmc' and $monitor['Type'] == 'Local' ) {
|
||||
$args = '-d ' . $monitor['Device'];
|
||||
} else if ( $daemon == 'zmcontrol.pl' ) {
|
||||
$args = '--id '.$id;
|
||||
} else {
|
||||
$args = '-m ' . $id;
|
||||
}
|
||||
|
||||
$shellcmd = escapeshellcmd("$zm_path_bin/zmdc.pl $command $daemon $args");
|
||||
ZM\Debug("Command $shellcmd");
|
||||
$status = exec($shellcmd);
|
||||
$status_text .= $status."\n";
|
||||
}
|
||||
$this->set(array(
|
||||
'status' => 'ok',
|
||||
'statustext' => $status_text,
|
||||
|
|
|
@ -136,4 +136,44 @@ class Monitor extends AppModel {
|
|||
'joinTable' => 'Monitor_Status',
|
||||
)
|
||||
);
|
||||
|
||||
public function daemonControl($monitor, $command, $daemon=null) {
|
||||
if ( $monitor['Function'] == 'None' ) {
|
||||
ZM\Debug('Calling daemonControl when Function == None');
|
||||
return;
|
||||
}
|
||||
if ( defined('ZM_SERVER_ID') and ($monitor['ServerId']!=ZM_SERVER_ID) ) {
|
||||
ZM\Debug('Calling daemonControl for Monitor assigned to different server');
|
||||
return;
|
||||
}
|
||||
|
||||
$daemons = array();
|
||||
if ( ! $daemon ) {
|
||||
if ( $monitor['Function'] == 'Monitor' ) {
|
||||
array_push($daemons, 'zmc');
|
||||
} else {
|
||||
array_push($daemons, 'zmc', 'zma');
|
||||
}
|
||||
} else {
|
||||
array_push($daemons, $daemon);
|
||||
}
|
||||
|
||||
$status_text = '';
|
||||
foreach ( $daemons as $daemon ) {
|
||||
$args = '';
|
||||
if ( $daemon == 'zmc' and $monitor['Type'] == 'Local' ) {
|
||||
$args = '-d ' . $monitor['Device'];
|
||||
} else if ( $daemon == 'zmcontrol.pl' ) {
|
||||
$args = '--id '.$monitor['Id'];
|
||||
} else {
|
||||
$args = '-m ' . $monitor['Id'];
|
||||
}
|
||||
|
||||
$shellcmd = escapeshellcmd(ZM_PATH_BIN.'/zmdc.pl '.$command.' '.$daemon.' '.$args);
|
||||
ZM\Debug("Command $shellcmd");
|
||||
$status = exec($shellcmd);
|
||||
$status_text .= $status.PHP_EOL;
|
||||
} # end foreach daemon
|
||||
return $status_text;
|
||||
} # end function daemonControl
|
||||
}
|
||||
|
|
|
@ -202,6 +202,9 @@ if ( $action == 'save' ) {
|
|||
} // end foreach zone
|
||||
} // end if rotation or just size change
|
||||
} // end if changes in width or height
|
||||
} else {
|
||||
global $error_message;
|
||||
$error_message = dbError();
|
||||
} // end if successful save
|
||||
$restart = true;
|
||||
} else { // new monitor
|
||||
|
|
|
@ -112,10 +112,10 @@ function dbLog($sql, $update=false) {
|
|||
function dbError($sql) {
|
||||
global $dbConn;
|
||||
$error = $dbConn->errorInfo();
|
||||
if ( ! $error[0] )
|
||||
if ( !$error[0] )
|
||||
return '';
|
||||
|
||||
$message = "SQL-ERR '".implode("\n",$dbConn->errorInfo())."', statement was '".$sql."'";
|
||||
$message = "SQL-ERR '".implode("\n", $dbConn->errorInfo())."', statement was '".$sql."'";
|
||||
ZM\Error($message);
|
||||
return $message;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
$j.ajaxSetup({timeout: AJAX_TIMEOUT});
|
||||
var reportLogs = true;
|
||||
|
||||
if ( !window.console ) {
|
||||
window.console =
|
||||
|
@ -28,55 +30,63 @@ if ( !window.console ) {
|
|||
error: function() {}
|
||||
};
|
||||
}
|
||||
|
||||
if ( !console.debug ) {
|
||||
// IE8 has console but doesn't have console.debug so lets alias it.
|
||||
console.debug = console.log;
|
||||
}
|
||||
|
||||
var reportLogs = true;
|
||||
window.onerror = function(message, url, line) {
|
||||
logReport("ERR", message, url, line);
|
||||
};
|
||||
|
||||
var debugParms;
|
||||
var debugReq;
|
||||
window.addEventListener("securitypolicyviolation", function logCSP(evt) {
|
||||
var level = evt.disposition == "enforce" ? "ERR" : "DBG";
|
||||
var message = evt.blockedURI + " violated CSP " + evt.violatedDirective;
|
||||
|
||||
if ( evt.sample ) message += " (Sample: " + evt.sample + ")";
|
||||
logReport(level, message, evt.sourceFile, evt.lineNumber);
|
||||
});
|
||||
|
||||
function logReport( level, message, file, line ) {
|
||||
if ( !reportLogs ) {
|
||||
return;
|
||||
}
|
||||
if ( !reportLogs ) return;
|
||||
|
||||
if ( typeof(MooTools) == "undefined" ) {
|
||||
return;
|
||||
}
|
||||
/* eslint-disable no-caller */
|
||||
if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.name ) {
|
||||
message += ' - '+arguments.callee.caller.caller.name+'()';
|
||||
//console.log("arguments");
|
||||
} else {
|
||||
//message += new Error().stack;
|
||||
//console.log("stack");
|
||||
}
|
||||
/* eslint-enable no-caller */
|
||||
|
||||
if ( !debugReq ) {
|
||||
debugParms = "view=request&request=log&task=create";
|
||||
if ( Browser ) {
|
||||
debugParms += "&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown');
|
||||
} else {
|
||||
debugParms += "&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown";
|
||||
}
|
||||
debugReq = new Request.JSON({url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain'});
|
||||
var browser = {};
|
||||
if ( Browser ) {
|
||||
browser.name = Browser.name;
|
||||
browser.version = Browser.version;
|
||||
browser.platform = Browser.Platform ? Browser.Platform.name : 'unknown';
|
||||
} else {
|
||||
browser.name = 'unknown';
|
||||
browser.version = 'unknown';
|
||||
browser.platform = 'unknown';
|
||||
}
|
||||
var requestParms = debugParms;
|
||||
requestParms += "&level="+level+"&message="+encodeURIComponent(message);
|
||||
|
||||
var data = {
|
||||
view: 'request',
|
||||
request: 'log',
|
||||
task: 'create',
|
||||
level: level,
|
||||
message: encodeURIComponent(message),
|
||||
browser: browser
|
||||
};
|
||||
|
||||
if ( file ) {
|
||||
requestParms += "&file="+file;
|
||||
data.file = file;
|
||||
} else if ( location.search ) {
|
||||
//location.search is the querystring part, so ?blah=blah but there is almost never any value to this
|
||||
requestParms += "&file="+location.search;
|
||||
data.file = location.search;
|
||||
}
|
||||
if ( line ) {
|
||||
requestParms += "&line="+line;
|
||||
}
|
||||
debugReq.send(requestParms);
|
||||
|
||||
if ( line ) data.line = line;
|
||||
|
||||
$j.getJSON(thisUrl, data);
|
||||
}
|
||||
|
||||
function Panic(message) {
|
||||
|
@ -112,22 +122,6 @@ function Debug(message) {
|
|||
}
|
||||
|
||||
function Dump(value, label) {
|
||||
if ( label ) {
|
||||
console.debug(label+" => ");
|
||||
}
|
||||
if ( label ) console.debug(label+" => ");
|
||||
console.debug(value);
|
||||
}
|
||||
|
||||
window.onerror =
|
||||
function( message, url, line ) {
|
||||
logReport("ERR", message, url, line);
|
||||
};
|
||||
|
||||
window.addEventListener("securitypolicyviolation", function logCSP(evt) {
|
||||
var level = evt.disposition == "enforce" ? "ERR" : "DBG";
|
||||
var message = evt.blockedURI + " violated CSP " + evt.violatedDirective;
|
||||
if ( evt.sample ) {
|
||||
message += " (Sample: " + evt.sample + ")";
|
||||
}
|
||||
logReport(level, message, evt.sourceFile, evt.lineNumber);
|
||||
});
|
||||
|
|
|
@ -437,9 +437,9 @@ function secsToTime( seconds ) {
|
|||
|
||||
function submitTab(evt) {
|
||||
var tab = this.getAttribute("data-tab-name");
|
||||
var form = $('contentForm');
|
||||
form.action.value = "";
|
||||
form.tab.value = tab;
|
||||
var form = $j('#contentForm');
|
||||
form.attr('action', '');
|
||||
form.attr('tab', tab);
|
||||
form.submit();
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
@ -599,11 +599,11 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl) {
|
|||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
||||
function setButtonState(element_id, butClass) {
|
||||
var element = $(element_id);
|
||||
function setButtonState(element_id, btnClass) {
|
||||
var element = document.getElementById(element_id);
|
||||
if ( element ) {
|
||||
element.className = butClass;
|
||||
if (butClass == 'unavail' || (butClass == 'active' && (element.id == 'pauseBtn' || element.id == 'playBtn'))) {
|
||||
element.className = btnClass;
|
||||
if (btnClass == 'unavail' || (btnClass == 'active' && (element.id == 'pauseBtn' || element.id == 'playBtn'))) {
|
||||
element.disabled = true;
|
||||
} else {
|
||||
element.disabled = false;
|
||||
|
|
|
@ -156,6 +156,7 @@ if ( !$Event->Id() ) {
|
|||
}
|
||||
?>
|
||||
<button id="statsBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Stats') ?>" ><i class="fa fa-info"></i></button>
|
||||
<button id="framesBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Frames') ?>" ><i class="fa fa-picture-o"></i></button>
|
||||
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>"><i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ getBodyTopHTML();
|
|||
<th data-sortable="true" data-field="Archived"><?php echo translate('Archived') ?></th>
|
||||
<th data-sortable="true" data-field="Emailed"><?php echo translate('Emailed') ?></th>
|
||||
<th data-sortable="true" data-field="Monitor"><?php echo translate('Monitor') ?></th>
|
||||
<th data-sortable="true" data-field="Cause"><?php echo translate('Cause') ?></th>
|
||||
<th data-sortable="true" data-field="Cause" data-click-to-select="false"><?php echo translate('Cause') ?></th>
|
||||
<th data-sortable="true" data-field="StartDateTime"><?php echo translate('AttrStartTime') ?></th>
|
||||
<th data-sortable="true" data-field="EndDateTime"><?php echo translate('AttrEndTime') ?></th>
|
||||
<th data-sortable="true" data-field="Length"><?php echo translate('Duration') ?></th>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
var probeReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getProbeResponse} );
|
||||
var ProbeResults;
|
||||
|
||||
function probe( url_e ) {
|
||||
probeReq.send( "request=add_monitors&action=probe&url="+url_e.value );
|
||||
$j.getJSON(thisUrl + '?view=request&request=add_monitors&action=probe&url=' + url_e.value)
|
||||
.done(getProbeResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
var ProbeResults;
|
||||
|
||||
function getProbeResponse( respObj, respText ) {
|
||||
if ( checkStreamForErrors( "getProbeResponse", respObj ) ) {
|
||||
return;
|
||||
|
@ -82,7 +81,6 @@ function addMonitor(url) {
|
|||
function import_csv( form ) {
|
||||
var formData = new FormData( form );
|
||||
console.log(formData);
|
||||
//formData.append('file', $('#file')[0].files[0]);
|
||||
|
||||
$j.ajax({
|
||||
url: thisUrl+"?request=add_monitors&action=import",
|
||||
|
@ -90,16 +88,19 @@ function import_csv( form ) {
|
|||
data: formData,
|
||||
processData: false, // tell jQuery not to process the data
|
||||
contentType: false, // tell jQuery not to set contentType
|
||||
success: function(data) {
|
||||
done: function(data) {
|
||||
var json = JSON.parse(data);
|
||||
parseStreams( json.Streams );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
url = $j('#Url')[0];
|
||||
var url = $j('#Url')[0];
|
||||
|
||||
if ( url.value ) {
|
||||
probe(url);
|
||||
}
|
||||
}
|
||||
window.addEventListener( 'DOMContentLoaded', initPage );
|
||||
|
||||
$j(document).ready(initPage);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
||||
var table = $j('#eventStatsTable');
|
||||
var backBtn = $j('#backBtn');
|
||||
var renameBtn = $j('#renameBtn');
|
||||
|
@ -27,14 +26,20 @@ var streamCmdTimer = null;
|
|||
var streamStatus = null;
|
||||
var lastEventId = 0;
|
||||
var zmsBroke = false; //Use alternate navigation if zms has crashed
|
||||
var streamParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash ) streamParms += '&auth='+auth_hash;
|
||||
var frameBatch = 40;
|
||||
var currFrameId = null;
|
||||
var eventReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getEventResponse} );
|
||||
var actReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getActResponse} );
|
||||
var frameReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse} );
|
||||
var streamReq = new Request.JSON( {url: monitorUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getCmdResponse} );
|
||||
var auth_hash;
|
||||
|
||||
function streamReq(data) {
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.connkey = connKey;
|
||||
data.view = 'request';
|
||||
data.request = 'stream';
|
||||
|
||||
$j.getJSON(thisUrl, data)
|
||||
.done(getCmdResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
// Function called when video.js hits the end of the video
|
||||
function vjsReplay() {
|
||||
|
@ -208,7 +213,7 @@ function changeScale() {
|
|||
} // end function changeScale
|
||||
|
||||
function changeReplayMode() {
|
||||
var replayMode = $('replayMode').get('value');
|
||||
var replayMode = $j('#replayMode').val();
|
||||
|
||||
Cookie.write('replayMode', replayMode, {duration: 10*365, samesite: 'strict'});
|
||||
|
||||
|
@ -217,6 +222,7 @@ function changeReplayMode() {
|
|||
|
||||
function changeRate() {
|
||||
var rate = parseInt($j('select[name="rate"]').val());
|
||||
|
||||
if ( ! rate ) {
|
||||
pauseClicked();
|
||||
} else if ( rate < 0 ) {
|
||||
|
@ -233,13 +239,13 @@ function changeRate() {
|
|||
}
|
||||
}, 500); //500ms is a compromise between smooth reverse and realistic performance
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_VARPLAY+"&rate="+rate);
|
||||
streamReq({command: CMD_VARPLAY, rate: rate});
|
||||
} // end if vid
|
||||
} else { // Forward rate
|
||||
if ( vid ) {
|
||||
vid.playbackRate(rate/100);
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_VARPLAY+"&rate="+rate);
|
||||
streamReq({command: CMD_VARPLAY, rate: rate});
|
||||
}
|
||||
}
|
||||
Cookie.write('zmEventRate', rate, {duration: 10*365, samesite: 'strict'});
|
||||
|
@ -291,9 +297,9 @@ function getCmdResponse( respObj, respText ) {
|
|||
$j('#progressValue').html(secsToTime(parseInt(streamStatus.progress)));
|
||||
$j('#zoomValue').html(streamStatus.zoom);
|
||||
if ( streamStatus.zoom == "1.0" ) {
|
||||
setButtonState( $('zoomOutBtn'), 'unavail' );
|
||||
setButtonState( 'zoomOutBtn', 'unavail' );
|
||||
} else {
|
||||
setButtonState( $('zoomOutBtn'), 'inactive' );
|
||||
setButtonState( 'zoomOutBtn', 'inactive' );
|
||||
}
|
||||
|
||||
updateProgressBar();
|
||||
|
@ -316,23 +322,24 @@ function pauseClicked() {
|
|||
}
|
||||
vid.pause();
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_PAUSE);
|
||||
streamReq({command: CMD_PAUSE});
|
||||
}
|
||||
streamPause();
|
||||
}
|
||||
|
||||
function streamPause() {
|
||||
$j('#modeValue').html('Paused');
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||
setButtonState( 'pauseBtn', 'active' );
|
||||
setButtonState( 'playBtn', 'inactive' );
|
||||
setButtonState( 'fastFwdBtn', 'unavail' );
|
||||
setButtonState( 'slowFwdBtn', 'inactive' );
|
||||
setButtonState( 'slowRevBtn', 'inactive' );
|
||||
setButtonState( 'fastRevBtn', 'unavail' );
|
||||
}
|
||||
|
||||
function playClicked( ) {
|
||||
var rate_select = $j('select[name="rate"]');
|
||||
|
||||
if ( ! rate_select.val() ) {
|
||||
$j('select[name="rate"]').val(100);
|
||||
}
|
||||
|
@ -343,7 +350,7 @@ function playClicked( ) {
|
|||
vjsPlay(); //handles fast forward and rewind
|
||||
}
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_PLAY);
|
||||
streamReq({command: CMD_PLAY});
|
||||
}
|
||||
streamPlay();
|
||||
}
|
||||
|
@ -358,31 +365,31 @@ function vjsPlay() { //catches if we change mode programatically
|
|||
}
|
||||
|
||||
function streamPlay( ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'active' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState( 'pauseBtn', 'inactive' );
|
||||
setButtonState( 'playBtn', 'active' );
|
||||
setButtonState( 'fastFwdBtn', 'inactive' );
|
||||
setButtonState( 'slowFwdBtn', 'unavail' );
|
||||
setButtonState( 'slowRevBtn', 'unavail' );
|
||||
setButtonState( 'fastRevBtn', 'inactive' );
|
||||
}
|
||||
|
||||
function streamFastFwd( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'active' );
|
||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState( 'pauseBtn', 'inactive' );
|
||||
setButtonState( 'playBtn', 'inactive' );
|
||||
setButtonState( 'fastFwdBtn', 'active' );
|
||||
setButtonState( 'slowFwdBtn', 'unavail' );
|
||||
setButtonState( 'slowRevBtn', 'unavail' );
|
||||
setButtonState( 'fastRevBtn', 'inactive' );
|
||||
if ( vid ) {
|
||||
if ( revSpeed != .5 ) stopFastRev();
|
||||
vid.playbackRate(rates[rates.indexOf(vid.playbackRate()*100)-1]/100);
|
||||
if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) {
|
||||
setButtonState($('fastFwdBtn'), 'unavail');
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
}
|
||||
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365, samesite: 'strict'});
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_FASTFWD);
|
||||
streamReq({command: CMD_FASTFWD});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,7 +398,7 @@ function streamSlowFwd( action ) {
|
|||
if ( vid ) {
|
||||
vid.currentTime(vid.currentTime() + spf);
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_SLOWFWD);
|
||||
streamReq({command: CMD_SLOWFWD});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +406,7 @@ function streamSlowRev( action ) {
|
|||
if ( vid ) {
|
||||
vid.currentTime(vid.currentTime() - spf);
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_SLOWREV);
|
||||
streamReq({command: CMD_SLOWREV});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,16 +419,16 @@ function stopFastRev() {
|
|||
}
|
||||
|
||||
function streamFastRev( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
||||
setButtonState( $('fastRevBtn'), 'active' );
|
||||
setButtonState( 'pauseBtn', 'inactive' );
|
||||
setButtonState( 'playBtn', 'inactive' );
|
||||
setButtonState( 'fastFwdBtn', 'inactive' );
|
||||
setButtonState( 'slowFwdBtn', 'unavail' );
|
||||
setButtonState( 'slowRevBtn', 'unavail' );
|
||||
setButtonState( 'fastRevBtn', 'active' );
|
||||
if ( vid ) { //There is no reverse play with mp4. Set the speed to 0 and manually set the time back.
|
||||
revSpeed = rates[rates.indexOf(revSpeed*100)-1]/100;
|
||||
if ( rates.indexOf(revSpeed*100) == 0 ) {
|
||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||
setButtonState( 'fastRevBtn', 'unavail' );
|
||||
}
|
||||
clearInterval(intervalRewind);
|
||||
$j('select[name="rate"]').val(-revSpeed*100);
|
||||
|
@ -436,7 +443,7 @@ function streamFastRev( action ) {
|
|||
}
|
||||
}, 500); //500ms is a compromise between smooth reverse and realistic performance
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_FASTREV);
|
||||
streamReq({command: CMD_FASTREV});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,7 +459,7 @@ function streamPrev(action) {
|
|||
} else if (zmsBroke || (vid && PrevEventDefVideoPath.indexOf("view_video") < 0) || $j("#vjsMessage").length || PrevEventDefVideoPath.indexOf("view_video") > 0) {//zms broke, leaving videojs, last event, moving to videojs
|
||||
location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery);
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_PREV);
|
||||
streamReq({command: CMD_PREV});
|
||||
streamPlay();
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +487,7 @@ function streamNext(action) {
|
|||
} else if ( zmsBroke || (vid && NextEventDefVideoPath.indexOf("view_video") < 0) || NextEventDefVideoPath.indexOf("view_video") > 0) {//reload zms, leaving vjs, moving to vjs
|
||||
location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery);
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_NEXT);
|
||||
streamReq({command: CMD_NEXT});
|
||||
streamPlay();
|
||||
}
|
||||
}
|
||||
|
@ -531,7 +538,7 @@ function streamZoomIn( x, y ) {
|
|||
if (vid) {
|
||||
vjsPanZoom('zoom', x, y);
|
||||
} else {
|
||||
streamReq.send( streamParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y );
|
||||
streamReq({command: CMD_ZOOMIN, x: x, y: y});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,28 +546,28 @@ function streamZoomOut() {
|
|||
if (vid) {
|
||||
vjsPanZoom('zoomOut');
|
||||
} else {
|
||||
streamReq.send( streamParms+"&command="+CMD_ZOOMOUT );
|
||||
streamReq({command: CMD_ZOOMOUT});
|
||||
}
|
||||
}
|
||||
|
||||
function streamScale( scale ) {
|
||||
streamReq.send( streamParms+"&command="+CMD_SCALE+"&scale="+scale );
|
||||
streamReq({command: CMD_SCALE, scale: scale});
|
||||
}
|
||||
|
||||
function streamPan( x, y ) {
|
||||
if (vid) {
|
||||
vjsPanZoom('pan', x, y);
|
||||
} else {
|
||||
streamReq.send( streamParms+"&command="+CMD_PAN+"&x="+x+"&y="+y );
|
||||
streamReq({command: CMD_PAN, x: x, y: y});
|
||||
}
|
||||
}
|
||||
|
||||
function streamSeek( offset ) {
|
||||
streamReq.send( streamParms+"&command="+CMD_SEEK+"&offset="+offset );
|
||||
streamReq({command: CMD_SEEK, offset: offset});
|
||||
}
|
||||
|
||||
function streamQuery() {
|
||||
streamReq.send( streamParms+"&command="+CMD_QUERY );
|
||||
streamReq({command: CMD_QUERY});
|
||||
}
|
||||
|
||||
function getEventResponse(respObj, respText) {
|
||||
|
@ -570,9 +577,9 @@ function getEventResponse(respObj, respText) {
|
|||
}
|
||||
|
||||
eventData = respObj.event;
|
||||
var eventStills = $('eventStills');
|
||||
var eventStills = $j('#eventStills');
|
||||
|
||||
if ( eventStills && !$('eventStills').hasClass( 'hidden' ) && currEventId != eventData.Id ) {
|
||||
if ( eventStills && !eventStills.hasClass('hidden') && currEventId != eventData.Id ) {
|
||||
resetEventStills();
|
||||
}
|
||||
currEventId = eventData.Id;
|
||||
|
@ -602,9 +609,6 @@ function getEventResponse(respObj, respText) {
|
|||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||
|
||||
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery); //if popup removed, check if this allows forward
|
||||
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
|
||||
//var eventImg = $('eventImage');
|
||||
//eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } );
|
||||
if ( vid && CurEventDefVideoPath ) {
|
||||
vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use
|
||||
console.log('getEventResponse');
|
||||
|
@ -621,12 +625,14 @@ function getEventResponse(respObj, respText) {
|
|||
nearEventsQuery( eventData.Id );
|
||||
} // end function getEventResponse
|
||||
|
||||
function eventQuery( eventId ) {
|
||||
var eventParms = 'view=request&request=status&entity=event&id='+eventId;
|
||||
if ( auth_hash ) {
|
||||
eventParms += '&auth='+auth_hash;
|
||||
}
|
||||
eventReq.send( eventParms );
|
||||
function eventQuery(eventId) {
|
||||
var data = {};
|
||||
data.id = eventId;
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=event', data)
|
||||
.done(getEventResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function getNearEventsResponse( respObj, respText ) {
|
||||
|
@ -640,10 +646,8 @@ function getNearEventsResponse( respObj, respText ) {
|
|||
PrevEventDefVideoPath = respObj.nearevents.PrevEventDefVideoPath;
|
||||
NextEventDefVideoPath = respObj.nearevents.NextEventDefVideoPath;
|
||||
|
||||
var prevEventBtn = $('prevEventBtn');
|
||||
if ( prevEventBtn ) prevEventBtn.disabled = !prevEventId;
|
||||
var nextEventBtn = $('nextEventBtn');
|
||||
if ( nextEventBtn ) nextEventBtn.disabled = !nextEventId;
|
||||
$j('#prevEventBtn').prop('disabled', !prevEventId);
|
||||
$j('#nextEventBtn').prop('disabled', !nextEventId);
|
||||
$j('#prevBtn').prop('disabled', prevEventId == 0 ? true : false).attr('class', prevEventId == 0 ? 'unavail' : 'inactive');
|
||||
$j('#nextBtn').prop('disabled', nextEventId == 0 ? true : false).attr('class', nextEventId == 0 ? 'unavail' : 'inactive');
|
||||
}
|
||||
|
@ -656,7 +660,7 @@ function nearEventsQuery( eventId ) {
|
|||
}
|
||||
|
||||
function loadEventThumb( event, frame, loadImage ) {
|
||||
var thumbImg = $('eventThumb'+frame.FrameId);
|
||||
var thumbImg = $j('#eventThumb'+frame.FrameId);
|
||||
if ( !thumbImg ) {
|
||||
console.error('No holder found for frame '+frame.FrameId);
|
||||
return;
|
||||
|
@ -664,12 +668,12 @@ function loadEventThumb( event, frame, loadImage ) {
|
|||
var img = new Asset.image( imagePrefix+frame.EventId+"&fid="+frame.FrameId,
|
||||
{
|
||||
'onload': ( function( loadImage ) {
|
||||
thumbImg.setProperty( 'src', img.getProperty( 'src' ) );
|
||||
thumbImg.removeClass( 'placeholder' );
|
||||
thumbImg.setProperty( 'class', frame.Type=='Alarm'?'alarm':'normal' );
|
||||
thumbImg.setProperty( 'title', frame.FrameId+' / '+((frame.Type=='Alarm')?frame.Score:0) );
|
||||
thumbImg.removeEvents( 'click' );
|
||||
thumbImg.addEvent( 'click', function() {
|
||||
thumbImg.prop('src', img.prop('src'));
|
||||
thumbImg.prop('class', frame.Type=='Alarm'?'alarm':'normal');
|
||||
thumbImg.prop('title', frame.FrameId+' / '+((frame.Type=='Alarm')?frame.Score:0));
|
||||
thumbImg.removeClass('placeholder');
|
||||
thumbImg.off('click');
|
||||
thumbImg.click(function() {
|
||||
locateImage( frame.FrameId, true );
|
||||
} );
|
||||
if ( loadImage ) {
|
||||
|
@ -682,72 +686,73 @@ function loadEventThumb( event, frame, loadImage ) {
|
|||
|
||||
function loadEventImage(event, frame) {
|
||||
console.debug('Loading '+event.Id+'/'+frame.FrameId);
|
||||
var eventImg = $('eventImage');
|
||||
var thumbImg = $('eventThumb'+frame.FrameId);
|
||||
if ( eventImg.getProperty('src') != thumbImg.getProperty('src') ) {
|
||||
var eventImagePanel = $('eventImagePanel');
|
||||
var eventImg = $j('#eventImage');
|
||||
var thumbImg = $j('#eventThumb'+frame.FrameId);
|
||||
if ( eventImg.prop('src') != thumbImg.prop('src') ) {
|
||||
var eventImagePanel = $j('#eventImagePanel');
|
||||
|
||||
if ( eventImagePanel.getStyle('display') != 'none' ) {
|
||||
var lastThumbImg = $('eventThumb'+eventImg.getProperty('alt'));
|
||||
if ( eventImagePanel.css('display') != 'none' ) {
|
||||
var lastThumbImg = $j('#eventThumb' + eventImg.prop('alt'));
|
||||
lastThumbImg.removeClass('selected');
|
||||
lastThumbImg.setOpacity(1.0);
|
||||
lastThumbImg.css('opacity', '1.0');
|
||||
}
|
||||
|
||||
$('eventImageBar').setStyle('width', event.Width);
|
||||
$j('#eventImageBar').css('width', event.Width);
|
||||
if ( frame.Type == 'Alarm' ) {
|
||||
$('eventImageStats').removeClass('hidden');
|
||||
$j('#eventImageStats').removeClass('hidden');
|
||||
} else {
|
||||
$('eventImageStats').addClass('hidden');
|
||||
$j('#eventImageStats').addClass('hidden');
|
||||
}
|
||||
thumbImg.addClass('selected');
|
||||
thumbImg.setOpacity(0.5);
|
||||
thumbImg.css('opacity', '0.5');
|
||||
|
||||
if ( eventImagePanel.getStyle('display') == 'none' ) {
|
||||
eventImagePanel.setOpacity(0);
|
||||
eventImagePanel.setStyle('display', 'inline-block');
|
||||
if ( eventImagePanel.css('display') == 'none' ) {
|
||||
eventImagePanel.css('opacity', '0');
|
||||
eventImagePanel.css('display', 'inline-block');
|
||||
new Fx.Tween( eventImagePanel, {duration: 500, transition: Fx.Transitions.Sine} ).start( 'opacity', 0, 1 );
|
||||
}
|
||||
|
||||
eventImg.setProperties( {
|
||||
eventImg.prop( {
|
||||
'class': frame.Type=='Alarm'?'alarm':'normal',
|
||||
'src': thumbImg.getProperty( 'src' ),
|
||||
'title': thumbImg.getProperty( 'title' ),
|
||||
'alt': thumbImg.getProperty( 'alt' ),
|
||||
'src': thumbImg.prop('src'),
|
||||
'title': thumbImg.prop('title'),
|
||||
'alt': thumbImg.prop('alt'),
|
||||
'height': $j('#eventThumbs').height() - $j('#eventImageBar').outerHeight(true)-10
|
||||
} );
|
||||
|
||||
$('eventImageNo').set('text', frame.FrameId);
|
||||
$('prevImageBtn').disabled = (frame.FrameId==1);
|
||||
$('nextImageBtn').disabled = (frame.FrameId==event.Frames);
|
||||
$j('#eventImageNo').text(frame.FrameId);
|
||||
$j('#prevImageBtn').prop('disabled', !frame.FrameId == 1);
|
||||
$j('#nextImageBtn').prop('disabled', !frame.FrameId == event.Frames);
|
||||
}
|
||||
}
|
||||
|
||||
function hideEventImageComplete() {
|
||||
var thumbImg = $('eventThumb'+$('eventImage').getProperty('alt'));
|
||||
var thumbImg = $j('#eventThumb'+$j('#eventImage').prop('alt'));
|
||||
if ( thumbImg ) {
|
||||
thumbImg.removeClass('selected');
|
||||
thumbImg.setOpacity(1.0);
|
||||
thumbImg.css('opacity', '1.0');
|
||||
} else {
|
||||
console.log('Unable to find eventThumb at eventThumb'+$('eventImage').getProperty('alt'));
|
||||
console.log('Unable to find eventThumb at eventThumb'+$j('#eventImage').prop('alt'));
|
||||
}
|
||||
$('prevImageBtn').disabled = true;
|
||||
$('nextImageBtn').disabled = true;
|
||||
$('eventImagePanel').setStyle('display', 'none');
|
||||
$('eventImageStats').addClass('hidden');
|
||||
$j('#prevImageBtn').prop('disabled', true);
|
||||
$j('#nextImageBtn').prop('disabled', true);
|
||||
$j('#eventImagePanel').css('display', 'none');
|
||||
$j('#eventImageStats').addClass('hidden');
|
||||
}
|
||||
|
||||
function hideEventImage() {
|
||||
if ( $('eventImagePanel').getStyle('display') != 'none' ) {
|
||||
new Fx.Tween( $('eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start('opacity', 1, 0);
|
||||
if ( $j('#eventImagePanel').css('display') != 'none' ) {
|
||||
new Fx.Tween( $j('#eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start('opacity', 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function resetEventStills() {
|
||||
hideEventImage();
|
||||
$('eventThumbs').empty();
|
||||
$j('#eventThumbs').empty();
|
||||
if ( true || !slider ) {
|
||||
slider = new Slider( $('thumbsSlider'), $('thumbsKnob'), {
|
||||
slider = new Slider( '#thumbsSlider', '#thumbsKnob', {
|
||||
/*steps: eventData.Frames,*/
|
||||
value: 0,
|
||||
onChange: function( step ) {
|
||||
if ( !step ) {
|
||||
step = 0;
|
||||
|
@ -761,7 +766,7 @@ function resetEventStills() {
|
|||
checkFrames( eventData.Id, fid, ($j('#eventImagePanel').css('display')=='none'?'':'true'));
|
||||
scroll.toElement( 'eventThumb'+fid );
|
||||
}
|
||||
} ).set( 0 );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,8 +792,13 @@ function getFrameResponse(respObj, respText) {
|
|||
}
|
||||
|
||||
function frameQuery( eventId, frameId, loadImage ) {
|
||||
var parms = "view=request&request=status&entity=frameimage&id[0]="+eventId+"&id[1]="+frameId+"&loopback="+loadImage;
|
||||
frameReq.send(parms);
|
||||
var data = {};
|
||||
data.loopback = loadImage;
|
||||
data.id = {eventId, frameId};
|
||||
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=frameimage', data)
|
||||
.done(getFrameResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function checkFrames( eventId, frameId, loadImage ) {
|
||||
|
@ -813,23 +823,30 @@ function checkFrames( eventId, frameId, loadImage ) {
|
|||
}
|
||||
|
||||
for ( var fid = loFid; fid <= hiFid; fid++ ) {
|
||||
if ( !$('eventThumb'+fid) ) {
|
||||
var img = new Element('img', {'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder'});
|
||||
img.addEvent('click', function() {
|
||||
if ( !$j('#eventThumb'+fid) ) {
|
||||
var img = $j('<img>');
|
||||
img.attr({
|
||||
'id': 'eventThumb'+fid,
|
||||
'src': 'graphics/transparent.png',
|
||||
'alt': fid,
|
||||
'class': 'placeholder'
|
||||
});
|
||||
|
||||
img.click(function() {
|
||||
eventData['frames'][fid] = null;
|
||||
checkFrames(eventId, fid);
|
||||
});
|
||||
frameQuery(eventId, fid, loadImage && (fid == frameId));
|
||||
var imgs = $('eventThumbs').getElements('img');
|
||||
var imgs = $j('#eventThumbs img');
|
||||
var injected = false;
|
||||
if ( fid < imgs.length ) {
|
||||
img.inject(imgs[fid-1], 'before');
|
||||
imgs.before(img);
|
||||
injected = true;
|
||||
} else {
|
||||
injected = imgs.some(
|
||||
injected = imgs.toArray().some(
|
||||
function( thumbImg, index ) {
|
||||
if ( parseInt(img.getProperty('alt')) < parseInt(thumbImg.getProperty('alt')) ) {
|
||||
img.inject(thumbImg, 'before');
|
||||
if ( parseInt(img.prop('alt')) < parseInt(thumbImg.prop('alt')) ) {
|
||||
thumbImg.before(img);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -837,10 +854,10 @@ function checkFrames( eventId, frameId, loadImage ) {
|
|||
);
|
||||
}
|
||||
if ( !injected ) {
|
||||
img.inject($('eventThumbs'));
|
||||
$j('#eventThumbs').append(img);
|
||||
}
|
||||
var scale = parseInt(img.getStyle('height'));
|
||||
img.setStyles( {
|
||||
var scale = parseInt(img.css('height'));
|
||||
img.css( {
|
||||
'width': parseInt((eventData.Width*scale)/100),
|
||||
'height': parseInt((eventData.Height*scale)/100)
|
||||
} );
|
||||
|
@ -850,8 +867,8 @@ function checkFrames( eventId, frameId, loadImage ) {
|
|||
}
|
||||
}
|
||||
}
|
||||
$('prevThumbsBtn').disabled = (frameId==1);
|
||||
$('nextThumbsBtn').disabled = (frameId==eventData.Frames);
|
||||
$j('#prevThumbsBtn').prop('disabled', frameId == 1);
|
||||
$j('#nextThumbsBtn').prop('disabled', frameId == eventData.Frames);
|
||||
}
|
||||
|
||||
function locateImage( frameId, loadImage ) {
|
||||
|
@ -876,13 +893,13 @@ function nextImage() {
|
|||
|
||||
function prevThumbs() {
|
||||
if ( currFrameId > 1 ) {
|
||||
locateImage( parseInt(currFrameId)>10?(parseInt(currFrameId)-10):1, $('eventImagePanel').getStyle('display')!="none" );
|
||||
locateImage( parseInt(currFrameId)>10?(parseInt(currFrameId)-10):1, $j('#eventImagePanel').css('display')!="none" );
|
||||
}
|
||||
}
|
||||
|
||||
function nextThumbs() {
|
||||
if ( currFrameId < eventData.Frames ) {
|
||||
locateImage( parseInt(currFrameId)<(eventData.Frames-10)?(parseInt(currFrameId)+10):eventData.Frames, $('eventImagePanel').getStyle('display')!="none" );
|
||||
locateImage( parseInt(currFrameId)<(eventData.Frames-10)?(parseInt(currFrameId)+10):eventData.Frames, $j('#eventImagePanel').css('display')!="none" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,14 +928,15 @@ function getActResponse( respObj, respText ) {
|
|||
}
|
||||
|
||||
function actQuery(action, parms) {
|
||||
var actParms = "view=request&request=event&id="+eventData.Id+"&action="+action;
|
||||
if ( auth_hash ) {
|
||||
actParms += '&auth='+auth_hash;
|
||||
}
|
||||
if ( parms != null ) {
|
||||
actParms += "&"+Object.toQueryString(parms);
|
||||
}
|
||||
actReq.send(actParms);
|
||||
var data = {};
|
||||
if ( parms ) data = parms;
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.id = eventData.Id;
|
||||
data.action = action;
|
||||
|
||||
$j.getJSON(thisUrl + '?view=request&request=event', data)
|
||||
.done(getActResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function renameEvent() {
|
||||
|
@ -937,19 +955,19 @@ function showEventFrames() {
|
|||
}
|
||||
|
||||
function showStream() {
|
||||
$('eventStills').addClass('hidden');
|
||||
$('eventVideo').removeClass('hidden');
|
||||
$j('#eventStills').addClass('hidden');
|
||||
$j('#eventVideo').removeClass('hidden');
|
||||
|
||||
$('stillsEvent').removeClass('hidden');
|
||||
$('streamEvent').addClass('hidden');
|
||||
$j('#stillsEvent').removeClass('hidden');
|
||||
$j('#streamEvent').addClass('hidden');
|
||||
|
||||
streamMode = 'video';
|
||||
if (scale == 'auto') changeScale();
|
||||
}
|
||||
|
||||
function showStills() {
|
||||
$('eventStills').removeClass('hidden');
|
||||
$('eventVideo').addClass('hidden');
|
||||
$j('#eventStills').removeClass('hidden');
|
||||
$j('#eventVideo').addClass('hidden');
|
||||
|
||||
if (vid && ( vid.paused != true ) ) {
|
||||
// Pause the video
|
||||
|
@ -960,8 +978,8 @@ function showStills() {
|
|||
//playButton.innerHTML = "Play";
|
||||
}
|
||||
|
||||
$('stillsEvent').addClass('hidden');
|
||||
$('streamEvent').removeClass('hidden');
|
||||
$j('#stillsEvent').addClass('hidden');
|
||||
$j('#streamEvent').removeClass('hidden');
|
||||
|
||||
streamMode = 'stills';
|
||||
|
||||
|
@ -980,7 +998,7 @@ function showStills() {
|
|||
}
|
||||
|
||||
function showFrameStats() {
|
||||
var fid = $('eventImageNo').get('text');
|
||||
var fid = $j('#eventImageNo').text();
|
||||
window.location.assign('?view=stats&eid='+eventData.Id+'&fid='+fid);
|
||||
}
|
||||
|
||||
|
@ -1014,13 +1032,14 @@ function progressBarNav() {
|
|||
|
||||
function handleClick( event ) {
|
||||
var target = event.target;
|
||||
var rect = target.getBoundingClientRect();
|
||||
if ( vid ) {
|
||||
if (target.id != 'videoobj') return; // ignore clicks on control bar
|
||||
var x = event.offsetX;
|
||||
var y = event.offsetY;
|
||||
} else {
|
||||
var x = event.page.x - $(target).getLeft();
|
||||
var y = event.page.y - $(target).getTop();
|
||||
var x = event.page.x - rect.left;
|
||||
var y = event.page.y - rect.top;
|
||||
}
|
||||
|
||||
if ( event.shift || event.shiftKey ) { // handle both jquery and mootools
|
||||
|
@ -1069,8 +1088,26 @@ function getStat() {
|
|||
table.empty().append('<tbody>');
|
||||
$j.each( eventDataStrings, function( key ) {
|
||||
var th = $j('<th>').addClass('text-right').text(eventDataStrings[key]);
|
||||
var tdString = ( eventData[key].length ) ? eventData[key] : 'n/a';
|
||||
var td = $j('<td>').text(tdString);
|
||||
var tdString;
|
||||
|
||||
switch (eventData[key].length ? key : 'n/a') {
|
||||
case 'Frames':
|
||||
tdString = '<a href="?view=frames&eid=' + eventData.Id + '">' + eventData[key] + '</a>';
|
||||
break;
|
||||
case 'AlarmFrames':
|
||||
tdString = '<a href="?view=frames&eid=' + eventData.Id + '">' + eventData[key] + '</a>';
|
||||
break;
|
||||
case 'MaxScore':
|
||||
tdString = '<a href="?view=frame&eid=' + eventData.Id + '&fid=0">' + eventData[key] + '</a>';
|
||||
break;
|
||||
case 'n/a':
|
||||
tdString = 'n/a';
|
||||
break;
|
||||
default:
|
||||
tdString = eventData[key];
|
||||
}
|
||||
|
||||
var td = $j('<td>').html(tdString);
|
||||
var row = $j('<tr>').append(th, td);
|
||||
|
||||
$j('#eventStatsTable tbody').append(row);
|
||||
|
@ -1114,15 +1151,14 @@ function initPage() {
|
|||
progressBarNav();
|
||||
streamCmdTimer = streamQuery.delay(250);
|
||||
if ( canStreamNative ) {
|
||||
var imageFeed = $('imageFeed');
|
||||
if ( !imageFeed ) {
|
||||
if ( !$j('#imageFeed') ) {
|
||||
console.log('No element with id tag imageFeed found.');
|
||||
} else {
|
||||
var streamImg = imageFeed.getElement('img');
|
||||
var streamImg = $j('#imageFeed img');
|
||||
if ( !streamImg ) {
|
||||
streamImg = imageFeed.getElement('object');
|
||||
streamImg = $j('#imageFeed object');
|
||||
}
|
||||
$(streamImg).addEvent('click', function(event) {
|
||||
$j(streamImg).click(function(event) {
|
||||
handleClick(event);
|
||||
});
|
||||
}
|
||||
|
@ -1253,6 +1289,12 @@ function initPage() {
|
|||
}
|
||||
});
|
||||
|
||||
// Manage the FRAMES Button
|
||||
document.getElementById("framesBtn").addEventListener("click", function onFramesClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.assign('?view=frames&eid='+eventData.Id);
|
||||
});
|
||||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEdit.Events ) {
|
||||
|
|
|
@ -126,19 +126,24 @@ function previewEvent(slot) {
|
|||
}
|
||||
|
||||
function loadEventImage( imagePath, eid, fid ) {
|
||||
var eventData = $j('#eventData');
|
||||
var imageSrc = $j('#imageSrc');
|
||||
|
||||
imageSrc.show();
|
||||
imageSrc.attr('src', imagePath);
|
||||
imageSrc.attr('data-event-id', eid);
|
||||
imageSrc.attr('data-frame-id', fid);
|
||||
imageSrc.click(window['showEvent'].bind(imageSrc, imageSrc));
|
||||
imageSrc.off('click');
|
||||
imageSrc.click(function() {
|
||||
showEvent(this);
|
||||
});
|
||||
|
||||
var eventData = $j('#eventData');
|
||||
eventData.attr('data-event-id', eid);
|
||||
eventData.attr('data-frame-id', fid);
|
||||
eventData.off('click');
|
||||
eventData.click(showEvent.pass());
|
||||
|
||||
divDataOnClick();
|
||||
eventData.click(function() {
|
||||
showEvent(this);
|
||||
});
|
||||
}
|
||||
|
||||
function tlZoomBounds(event) {
|
||||
|
|
|
@ -974,6 +974,8 @@ echo htmlSelect('newMonitor[OutputCodec]', $videowriter_codecs, $monitor->Output
|
|||
$videowriter_encoders = array(
|
||||
'' => translate('Auto'),
|
||||
'h264_omx' => 'h264_omx',
|
||||
'libx264' => 'libx264',
|
||||
'h264_vaapi' => 'h264_vaapi',
|
||||
'h264' => 'h264',
|
||||
'mjpeg' => 'mjpeg',
|
||||
'mpeg1' => 'mpeg1',
|
||||
|
|
Loading…
Reference in New Issue