calloc( audio_out_ctx->channels, sizeof(*converted_in_samples))) ) {
+ Error("Could not allocate converted in sample pointers\n");
return;
}
/**
* Allocate memory for the samples of all channels in one consecutive
* block for convenience.
*/
- if ((ret = av_samples_alloc( &converted_input_samples, NULL,
- audio_output_context->channels,
- audio_output_context->frame_size,
- audio_output_context->sample_fmt, 0)) < 0) {
- Error( "Could not allocate converted input samples (error '%s')\n",
- av_make_error_string(ret).c_str() );
+ if ( (ret = av_samples_alloc( &converted_in_samples, NULL,
+ audio_out_ctx->channels,
+ audio_out_ctx->frame_size,
+ audio_out_ctx->sample_fmt, 0)) < 0 ) {
+ Error("Could not allocate converted in samples (error '%s')\n",
+ av_make_error_string(ret).c_str());
- av_freep(converted_input_samples);
- free(converted_input_samples);
+ av_freep(converted_in_samples);
+ free(converted_in_samples);
return;
}
#endif
- output_frame->nb_samples = audio_output_context->frame_size;
- output_frame->format = audio_output_context->sample_fmt;
- output_frame->channel_layout = audio_output_context->channel_layout;
+ out_frame->nb_samples = audio_out_ctx->frame_size;
+ out_frame->format = audio_out_ctx->sample_fmt;
+ out_frame->channel_layout = audio_out_ctx->channel_layout;
- // The codec gives us the frame size, in samples, we calculate the size of the samples buffer in bytes
- unsigned int audioSampleBuffer_size = av_samples_get_buffer_size( NULL, audio_output_context->channels, audio_output_context->frame_size, audio_output_context->sample_fmt, 0 );
- converted_input_samples = (uint8_t*) av_malloc( audioSampleBuffer_size );
+ // The codec gives us the frame size, in samples, we calculate the size of the
+ // samples buffer in bytes
+ unsigned int audioSampleBuffer_size = av_samples_get_buffer_size(
+ NULL, audio_out_ctx->channels, audio_out_ctx->frame_size,
+ audio_out_ctx->sample_fmt, 0);
+ converted_in_samples = (uint8_t *)av_malloc(audioSampleBuffer_size);
- if ( !converted_input_samples ) {
- Error( "Could not allocate converted input sample pointers\n");
- return false;
- }
-
- // Setup the data pointers in the AVFrame
- if ( avcodec_fill_audio_frame(
- output_frame,
- audio_output_context->channels,
- audio_output_context->sample_fmt,
- (const uint8_t*) converted_input_samples,
- audioSampleBuffer_size, 0 ) < 0 ) {
- Error( "Could not allocate converted input sample pointers\n");
- return false;
- }
-
- return true;
-#else
- Error("Not built with libavresample library. Cannot do audio conversion to AAC");
+ if (!converted_in_samples) {
+ Error("Could not allocate converted in sample pointers\n");
return false;
+ }
+
+ // Setup the data pointers in the AVFrame
+ if (avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels,
+ audio_out_ctx->sample_fmt,
+ (const uint8_t *)converted_in_samples,
+ audioSampleBuffer_size, 0) < 0) {
+ Error("Could not allocate converted in sample pointers\n");
+ return false;
+ }
+
+ return true;
+#else
+ Error(
+ "Not built with libavresample library. Cannot do audio conversion to "
+ "AAC");
+ return false;
#endif
-}
+} // end bool VideoStore::setup_resampler()
-
-void VideoStore::dumpPacket( AVPacket *pkt ){
+void VideoStore::dumpPacket(AVPacket *pkt) {
char b[10240];
- snprintf(b, sizeof(b), " pts: %" PRId64 ", dts: %" PRId64 ", data: %p, size: %d, sindex: %d, dflags: %04x, s-pos: %" PRId64 ", c-duration: %" PRId64 "\n"
- , pkt->pts
- , pkt->dts
- , pkt->data
- , pkt->size
- , pkt->stream_index
- , pkt->flags
- , pkt->pos
- , pkt->duration
- );
+ snprintf(b, sizeof(b),
+ " pts: %" PRId64 ", dts: %" PRId64
+ ", data: %p, size: %d, sindex: %d, dflags: %04x, s-pos: %" PRId64
+ ", c-duration: %d\n",
+ pkt->pts, pkt->dts, pkt->data, pkt->size, pkt->stream_index,
+ pkt->flags, pkt->pos, pkt->duration);
Debug(1, "%s:%d:DEBUG: %s", __FILE__, __LINE__, b);
}
-int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
+int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
av_init_packet(&opkt);
- int duration;
+ opkt.pts = video_next_pts;
+ opkt.dts = video_next_dts;
+ opkt.duration = 0;
+ int duration;
+ if (!video_last_pts) {
+ duration = 0;
+ } else {
+ duration =
+ av_rescale_q(ipkt->pts - video_last_pts, video_in_stream->time_base,
+ video_out_stream->time_base);
+ Debug(1, "duration calc: pts(%d) - last_pts(%d) = (%d)", ipkt->pts,
+ video_last_pts, duration);
+ if (duration < 0) {
+ duration = ipkt->duration;
+ }
+ }
+
+ //#if ( 0 && video_last_pts && ( ipkt->duration == AV_NOPTS_VALUE || !
+ //ipkt->duration ) ) {
+ // Video packets don't really have a duration. Audio does.
+ // opkt.duration = av_rescale_q(duration, video_in_stream->time_base,
+ // video_out_stream->time_base);
+ // opkt.duration = 0;
+ //} else {
+ // duration = opkt.duration = av_rescale_q(ipkt->duration,
+ // video_in_stream->time_base, video_out_stream->time_base);
+ //}
+ video_last_pts = ipkt->pts;
+ video_last_dts = ipkt->dts;
+
+#if 0
//Scale the PTS of the outgoing packet to be the correct time base
if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( ! video_last_pts ) {
// This is the first packet.
opkt.pts = 0;
- Debug(2, "Starting video video_last_pts will become (%d)", ipkt->pts );
+ Debug(2, "Starting video video_last_pts will become (%d)", ipkt->pts);
} else {
if ( ipkt->pts < video_last_pts ) {
- Debug(1, "Resetting video_last_pts from (%d) to (%d)", video_last_pts, ipkt->pts );
+ Debug(1, "Resetting video_last_pts from (%d) to (%d)", video_last_pts, ipkt->pts);
// wrap around, need to figure out the distance FIXME having this wrong should cause a jump, but then play ok?
- opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts, video_input_stream->time_base, video_output_stream->time_base);
+ opkt.pts = video_next_pts + av_rescale_q( ipkt->pts, video_in_stream->time_base, video_out_stream->time_base);
} else {
- opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts - video_last_pts, video_input_stream->time_base, video_output_stream->time_base);
+ opkt.pts = video_next_pts + av_rescale_q( ipkt->pts - video_last_pts, video_in_stream->time_base, video_out_stream->time_base);
}
}
- Debug(3, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, video_last_pts );
- duration = ipkt->pts - video_last_pts;
+ Debug(3, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, video_last_pts);
video_last_pts = ipkt->pts;
} else {
Debug(3, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
}
-
- //Scale the DTS of the outgoing packet to be the correct time base
-
- // Just because the input stream wraps, doesn't mean the output needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the output. So need to handle input wrap, without causing output wrap.
- if ( ! video_last_dts ) {
+ // Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
+ if ( !video_last_dts ) {
// This is the first packet.
opkt.dts = 0;
- Debug(1, "Starting video video_last_dts will become (%d)", ipkt->dts );
+ Debug(1, "Starting video video_last_dts will become (%lu)", ipkt->dts);
video_last_dts = ipkt->dts;
} else {
+ // Scale the DTS of the outgoing packet to be the correct time base
+
if ( ipkt->dts == AV_NOPTS_VALUE ) {
- // why are we using cur_dts instead of packet.dts? I think cur_dts is in AV_TIME_BASE_Q, but ipkt.dts is in video_input_stream->time_base
- if ( video_input_stream->cur_dts < video_last_dts ) {
- Debug(1, "Resetting video_last_dts from (%d) to (%d) p.dts was (%d)", video_last_dts, video_input_stream->cur_dts, ipkt->dts );
- opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
+ // why are we using cur_dts instead of packet.dts? I think cur_dts is in AV_TIME_BASE_Q, but ipkt.dts is in video_in_stream->time_base
+ if ( video_in_stream->cur_dts < video_last_dts ) {
+ Debug(1, "Resetting video_last_dts from (%d) to (%d) p.dts was (%d)", video_last_dts, video_in_stream->cur_dts, ipkt->dts);
+ opkt.dts = video_next_dts + av_rescale_q(video_in_stream->cur_dts, AV_TIME_BASE_Q, video_out_stream->time_base);
} else {
- opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
+ opkt.dts = video_next_dts + av_rescale_q(video_in_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_out_stream->time_base);
}
- Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - previus_dts(%d)", opkt.dts, video_input_stream->cur_dts, video_last_dts );
- video_last_dts = video_input_stream->cur_dts;
+ Debug(3, "opkt.dts = %d from video_in_stream->cur_dts(%d) - previus_dts(%d)", opkt.dts, video_in_stream->cur_dts, video_last_dts);
+ video_last_dts = video_in_stream->cur_dts;
} else {
if ( ipkt->dts < video_last_dts ) {
- Debug(1, "Resetting video_last_dts from (%d) to (%d)", video_last_dts, ipkt->dts );
- opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts, video_input_stream->time_base, video_output_stream->time_base);
+ Debug(1, "Resetting video_last_dts from (%d) to (%d)", video_last_dts, ipkt->dts);
+ opkt.dts = video_next_dts + av_rescale_q( ipkt->dts, video_in_stream->time_base, video_out_stream->time_base);
} else {
- opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts - video_last_dts, video_input_stream->time_base, video_output_stream->time_base);
+ opkt.dts = video_next_dts + av_rescale_q( ipkt->dts - video_last_dts, video_in_stream->time_base, video_out_stream->time_base);
}
- Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)", opkt.dts, ipkt->dts, video_last_dts );
+ Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)", opkt.dts, ipkt->dts, video_last_dts);
video_last_dts = ipkt->dts;
}
}
- if ( opkt.dts > opkt.pts ) {
- Debug( 1, "opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
+#endif
+ if (opkt.dts > opkt.pts) {
+ Debug(1,
+ "opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen "
+ "before presentation.",
+ opkt.dts, opkt.pts);
opkt.dts = opkt.pts;
}
- if ( ipkt->duration == AV_NOPTS_VALUE ) {
- opkt.duration = av_rescale_q( duration, video_input_stream->time_base, video_output_stream->time_base);
- } else {
- opkt.duration = av_rescale_q(ipkt->duration, video_input_stream->time_base, video_output_stream->time_base);
- }
opkt.flags = ipkt->flags;
- opkt.pos=-1;
+ int keyframe = opkt.flags & AV_PKT_FLAG_KEY;
+ opkt.pos = -1;
opkt.data = ipkt->data;
opkt.size = ipkt->size;
- // Some camera have audio on stream 0 and video on stream 1. So when we remove the audio, video stream has to go on 0
- if ( ipkt->stream_index > 0 and ! audio_output_stream ) {
- Debug(1,"Setting stream index to 0 instead of %d", ipkt->stream_index );
- opkt.stream_index = 0;
- } else {
- opkt.stream_index = ipkt->stream_index;
- }
+ opkt.stream_index = video_out_stream->index;
AVPacket safepkt;
- memcpy( &safepkt, &opkt, sizeof(AVPacket) );
+ memcpy(&safepkt, &opkt, sizeof(AVPacket));
- Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts, opkt.duration );
- if ((opkt.data == NULL)||(opkt.size < 1)) {
- Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__ );
- dumpPacket( ipkt);
+ Debug(1,
+ "writing video packet keyframe(%d) pts(%d) dts(%d) duration(%d) "
+ "ipkt.duration(%d)",
+ keyframe, opkt.pts, opkt.dts, duration, ipkt->duration);
+ if ((opkt.data == NULL) || (opkt.size < 1)) {
+ Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__);
+ dumpPacket(ipkt);
dumpPacket(&opkt);
- } else if ((video_previous_dts > 0) && (video_previous_dts > opkt.dts)) {
- Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, video_previous_dts, opkt.dts);
- video_previous_dts = opkt.dts;
+ } else if ((video_next_dts > 0) && (video_next_dts > opkt.dts)) {
+ Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame",
+ __FILE__, __LINE__, video_next_dts, opkt.dts);
+ video_next_dts = opkt.dts;
dumpPacket(&opkt);
} else {
-
- video_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
- video_previous_pts = opkt.pts;
+ video_next_dts = opkt.dts + duration;
+ video_next_pts = opkt.pts + duration;
ret = av_interleaved_write_frame(oc, &opkt);
- if ( ret < 0 ) {
- // There's nothing we can really do if the frame is rejected, just drop it and get on with the next
- Warning("%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d) ", __FILE__, __LINE__, av_make_error_string(ret).c_str(), (ret));
+ if (ret < 0) {
+ // There's nothing we can really do if the frame is rejected, just drop it
+ // and get on with the next
+ Warning(
+ "%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d) "
+ " ",
+ __FILE__, __LINE__, av_make_error_string(ret).c_str(), (ret));
dumpPacket(&safepkt);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- zm_dump_codecpar( video_input_stream->codecpar );
- zm_dump_codecpar( video_output_stream->codecpar );
+ zm_dump_codecpar(video_in_stream->codecpar);
+ zm_dump_codecpar(video_out_stream->codecpar);
#endif
}
}
- zm_av_packet_unref(&opkt);
+ zm_av_packet_unref(&opkt);
return 0;
+} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
-} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
-
-int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
+int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
Debug(4, "writeAudioFrame");
- if ( ! audio_output_stream ) {
- Debug(1, "Called writeAudioFramePacket when no audio_output_stream");
- return 0;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
+ if (!audio_out_stream) {
+ Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
+ return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
+ // the moment
}
- if ( audio_output_codec ) {
+ if (audio_out_codec) {
+ Debug(3, "Have audio codec");
#ifdef HAVE_LIBAVRESAMPLE
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- ret = avcodec_send_packet( audio_input_context, ipkt );
- if ( ret < 0 ) {
+ ret = avcodec_send_packet(audio_in_ctx, ipkt);
+ if (ret < 0) {
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
return 0;
}
- ret = avcodec_receive_frame( audio_input_context, input_frame );
- if ( ret < 0 ) {
+ ret = avcodec_receive_frame(audio_in_ctx, in_frame);
+ if (ret < 0) {
Error("avcodec_receive_frame fail %s", av_make_error_string(ret).c_str());
return 0;
}
- Debug(2, "Frame: samples(%d), format(%d), sample_rate(%d), channel layout(%d) refd(%d)",
- input_frame->nb_samples,
- input_frame->format,
- input_frame->sample_rate,
- input_frame->channel_layout,
- audio_output_context->refcounted_frames
- );
+ Debug(2,
+ "Input Frame: samples(%d), format(%d), sample_rate(%d), channel "
+ "layout(%d)",
+ in_frame->nb_samples, in_frame->format,
+ in_frame->sample_rate, in_frame->channel_layout);
#else
/**
* Decode the audio frame stored in the packet.
- * The input audio stream decoder is used to do this.
+ * The in audio stream decoder is used to do this.
* If we are at the end of the file, pass an empty packet to the decoder
* to flush it.
*/
- if ((ret = avcodec_decode_audio4(audio_input_context, input_frame,
- &data_present, ipkt)) < 0) {
- Error( "Could not decode frame (error '%s')\n",
- av_make_error_string(ret).c_str());
- dumpPacket( ipkt );
- av_frame_free( &input_frame );
+ if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame,
+ &data_present, ipkt)) < 0) {
+ Error("Could not decode frame (error '%s')\n",
+ av_make_error_string(ret).c_str());
+ dumpPacket(ipkt);
+ av_frame_free(&in_frame);
return 0;
}
- if ( ! data_present ) {
+ if (!data_present) {
Debug(2, "Not ready to transcode a frame yet.");
return 0;
}
#endif
- int frame_size = input_frame->nb_samples;
- Debug(4, "Frame size: %d", frame_size );
+ int frame_size = out_frame->nb_samples;
- // Resample the input into the audioSampleBuffer until we proceed the whole decoded data
- if ( (ret = avresample_convert( resample_context,
- NULL,
- 0,
- 0,
- input_frame->data,
- 0,
- input_frame->nb_samples )) < 0 ) {
- Error( "Could not resample frame (error '%s')\n",
- av_make_error_string(ret).c_str());
- return 0;
- }
-
- if ( avresample_available( resample_context ) < output_frame->nb_samples ) {
- Debug(1, "No enough samples yet");
+ // Resample the in into the audioSampleBuffer until we proceed the whole
+ // decoded data
+ if ((ret =
+ avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
+ 0, in_frame->nb_samples)) < 0) {
+ Error("Could not resample frame (error '%s')\n",
+ av_make_error_string(ret).c_str());
+ av_frame_unref(in_frame);
+ return 0;
+ }
+ av_frame_unref(in_frame);
+
+ int samples_available = avresample_available(resample_ctx);
+
+ if (samples_available < frame_size) {
+ Debug(1, "Not enough samples yet (%d)", samples_available);
return 0;
}
+ Debug(3, "Output_frame samples (%d)", out_frame->nb_samples);
// Read a frame audio data from the resample fifo
- if ( avresample_read( resample_context, output_frame->data, output_frame->nb_samples ) != output_frame->nb_samples ) {
- Warning( "Error reading resampled audio: " );
+ if (avresample_read(resample_ctx, out_frame->data, frame_size) !=
+ frame_size) {
+ Warning("Error reading resampled audio: ");
return 0;
}
+ Debug(2,
+ "Frame: samples(%d), format(%d), sample_rate(%d), channel layout(%d)",
+ out_frame->nb_samples, out_frame->format,
+ out_frame->sample_rate, out_frame->channel_layout);
av_init_packet(&opkt);
- Debug(5, "after init packet" );
+ Debug(5, "after init packet");
- /** Set a timestamp based on the sample rate for the container. */
- //output_frame->pts = av_rescale_q( opkt.pts, audio_output_context->time_base, audio_output_stream->time_base );
-
- // convert the packet to the codec timebase from the stream timebase
- //Debug(3, "output_frame->pts(%d) best effort(%d)", output_frame->pts,
- //av_frame_get_best_effort_timestamp(output_frame)
- //);
- /**
- * Encode the audio frame and store it in the temporary packet.
- * The output audio stream encoder is used to do this.
- */
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- if (( ret = avcodec_send_frame( audio_output_context, output_frame ) ) < 0 ) {
- Error( "Could not send frame (error '%s')",
- av_make_error_string(ret).c_str());
+ 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);
return 0;
}
- if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) {
- Error( "Could not recieve packet (error '%s')",
- av_make_error_string(ret).c_str());
+ // av_frame_unref( out_frame );
+
+ 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(3, "Could not recieve packet (error '%s')",
+ av_make_error_string(ret).c_str());
+ } else {
+ Error("Could not recieve packet (error %d = '%s')", ret,
+ av_make_error_string(ret).c_str());
+ }
zm_av_packet_unref(&opkt);
+ av_frame_unref(in_frame);
+ // av_frame_unref( out_frame );
return 0;
}
#else
- if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
- Error( "Could not encode frame (error '%s')",
- av_make_error_string(ret).c_str());
+ 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 output a frame yet.");
+ if (!data_present) {
+ Debug(2, "Not ready to out a frame yet.");
zm_av_packet_unref(&opkt);
return 0;
}
@@ -853,86 +942,102 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
#endif
} else {
av_init_packet(&opkt);
- Debug(5, "after init packet" );
+ Debug(5, "after init packet");
opkt.data = ipkt->data;
opkt.size = ipkt->size;
}
- // PTS is difficult, because of the buffering of the audio packets in the resampler. So we have to do it once we actually have a packet...
+// PTS is difficult, because of the buffering of the audio packets in the
+// resampler. So we have to do it once we actually have a packet...
+// audio_last_pts is the pts of ipkt, audio_next_pts is the last pts of the
+// out
- //Scale the PTS of the outgoing packet to be the correct time base
+// Scale the PTS of the outgoing packet to be the correct time base
+#if 0
if ( ipkt->pts != AV_NOPTS_VALUE ) {
- if ( ! audio_last_pts ) {
+ if ( !audio_last_pts ) {
opkt.pts = 0;
Debug(1, "No audio_last_pts");
} else {
if ( audio_last_pts > ipkt->pts ) {
- Debug(1, "Resetting audeo_start_pts from (%d) to (%d)", audio_last_pts, ipkt->pts );
- opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts, audio_input_stream->time_base, audio_output_stream->time_base);
+ Debug(1, "Resetting audio_start_pts from (%d) to (%d)", audio_last_pts, ipkt->pts);
+ opkt.pts = audio_next_pts + av_rescale_q(ipkt->pts, audio_in_stream->time_base, audio_out_stream->time_base);
} else {
- opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_input_stream->time_base, audio_output_stream->time_base);
+ opkt.pts = audio_next_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_in_stream->time_base, audio_out_stream->time_base);
}
- Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts );
+ Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts);
}
audio_last_pts = ipkt->pts;
} else {
Debug(2, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
}
+#else
+ opkt.pts = audio_next_pts;
+ opkt.dts = audio_next_dts;
+#endif
- //Scale the DTS of the outgoing packet to be the correct time base
- if ( ! audio_last_dts ) {
- opkt.dts = 0;
-
- } else {
- if( ipkt->dts == AV_NOPTS_VALUE ) {
- // So if the input has no dts assigned... still need an output dts... so we use cur_dts?
+#if 0
+ 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 ( audio_last_dts > audio_input_stream->cur_dts ) {
- Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_input_stream->cur_dts );
- opkt.dts = audio_previous_dts + av_rescale_q( audio_input_stream->cur_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
+ 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_previous_dts + av_rescale_q( audio_input_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
+ 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);
}
- audio_last_dts = audio_input_stream->cur_dts;
- Debug(2, "opkt.dts = %d from video_input_stream->cur_dts(%d) - last_dts(%d)", opkt.dts, audio_input_stream->cur_dts, audio_last_dts );
+ audio_last_dts = audio_in_stream->cur_dts;
+ Debug(2, "opkt.dts = %d from video_in_stream->cur_dts(%d) - last_dts(%d)", opkt.dts, audio_in_stream->cur_dts, audio_last_dts);
} else {
- if ( audio_last_dts > ipkt->dts ) {
+ if ( audio_last_dts >= ipkt->dts ) {
Debug(1, "Resetting audio_last_dts from (%d) to (%d)", audio_last_dts, ipkt->dts );
- opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts, audio_input_stream->time_base, audio_output_stream->time_base);
+ opkt.dts = audio_next_dts + av_rescale_q(ipkt->dts, audio_in_stream->time_base, audio_out_stream->time_base);
} else {
- opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_input_stream->time_base, audio_output_stream->time_base);
+ opkt.dts = audio_next_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_in_stream->time_base, audio_out_stream->time_base);
+ Debug(2, "opkt.dts = %d from previous(%d) + ( ipkt->dts(%d) - last_dts(%d) )", opkt.dts, audio_next_dts, ipkt->dts, audio_last_dts );
}
- Debug(2, "opkt.dts = %d from ipkt->dts(%d) - last_dts(%d)", opkt.dts, ipkt->dts, audio_last_dts );
}
}
- audio_last_dts = ipkt->dts;
- if ( opkt.dts > opkt.pts ) {
- Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
+#endif
+ // audio_last_dts = ipkt->dts;
+ if (opkt.dts > opkt.pts) {
+ Debug(1,
+ "opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen "
+ "before presentation.",
+ opkt.dts, opkt.pts);
opkt.dts = opkt.pts;
}
- // I wonder if we could just use duration instead of all the hoop jumping above?
- opkt.duration = av_rescale_q(ipkt->duration, audio_input_stream->time_base, audio_output_stream->time_base);
- Debug( 2, "opkt.pts (%d), opkt.dts(%d) opkt.duration = (%d)", opkt.pts, opkt.dts, opkt.duration );
+ // I wonder if we could just use duration instead of all the hoop jumping
+ // above?
+ //
+ if (out_frame) {
+ opkt.duration = out_frame->nb_samples;
+ } else {
+ opkt.duration = ipkt->duration;
+ }
+ // opkt.duration = av_rescale_q(ipkt->duration, audio_in_stream->time_base,
+ // audio_out_stream->time_base);
+ Debug(2, "opkt.pts (%d), opkt.dts(%d) opkt.duration = (%d)", opkt.pts,
+ opkt.dts, opkt.duration);
- // pkt.pos: byte position in stream, -1 if unknown
+ // pkt.pos: byte position in stream, -1 if unknown
opkt.pos = -1;
- opkt.stream_index = ipkt->stream_index;
- Debug(2, "Stream index is %d", opkt.stream_index );
+ opkt.stream_index = audio_out_stream->index;
+ audio_next_dts = opkt.dts + opkt.duration;
+ audio_next_pts = opkt.pts + opkt.duration;
AVPacket safepkt;
memcpy(&safepkt, &opkt, sizeof(AVPacket));
- audio_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
- audio_previous_pts = opkt.pts;
ret = av_interleaved_write_frame(oc, &opkt);
- if(ret!=0){
- Error("Error writing audio frame packet: %s\n", av_make_error_string(ret).c_str());
+ if (ret != 0) {
+ Error("Error writing audio frame packet: %s\n",
+ av_make_error_string(ret).c_str());
dumpPacket(&safepkt);
} else {
- Debug(2,"Success writing audio frame" );
+ Debug(2, "Success writing audio frame");
}
zm_av_packet_unref(&opkt);
return 0;
-} // end int VideoStore::writeAudioFramePacket( AVPacket *ipkt )
-
+} // end int VideoStore::writeAudioFramePacket( AVPacket *ipkt )
diff --git a/src/zm_videostore.h b/src/zm_videostore.h
index 36ddd7bcf..014731f40 100644
--- a/src/zm_videostore.h
+++ b/src/zm_videostore.h
@@ -18,35 +18,35 @@ class VideoStore {
private:
unsigned int packets_written;
- AVOutputFormat *output_format;
+ AVOutputFormat *out_format;
AVFormatContext *oc;
- AVStream *video_output_stream;
- AVStream *audio_output_stream;
- AVCodecContext *video_output_context;
+ AVStream *video_out_stream;
+ AVStream *audio_out_stream;
+ AVCodecContext *video_out_ctx;
- AVStream *video_input_stream;
- AVStream *audio_input_stream;
+ AVStream *video_in_stream;
+ AVStream *audio_in_stream;
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
AVPacket opkt;
// we are transcoding
- AVFrame *input_frame;
- AVFrame *output_frame;
+ AVFrame *in_frame;
+ AVFrame *out_frame;
- AVCodecContext *video_input_context;
- AVCodecContext *audio_input_context;
+ AVCodecContext *video_in_ctx;
+ AVCodecContext *audio_in_ctx;
int ret;
// The following are used when encoding the audio stream to AAC
- AVCodec *audio_output_codec;
- AVCodecContext *audio_output_context;
+ AVCodec *audio_out_codec;
+ AVCodecContext *audio_out_ctx;
int data_present;
AVAudioFifo *fifo;
- int output_frame_size;
+ int out_frame_size;
#ifdef HAVE_LIBAVRESAMPLE
-AVAudioResampleContext* resample_context;
+AVAudioResampleContext* resample_ctx;
#endif
- uint8_t *converted_input_samples;
+ uint8_t *converted_in_samples;
const char *filename;
const char *format;
@@ -54,24 +54,30 @@ AVAudioResampleContext* resample_context;
bool keyframeMessage;
int keyframeSkipNumber;
- // These are for input
+ // These are for in
int64_t video_last_pts;
int64_t video_last_dts;
int64_t audio_last_pts;
int64_t audio_last_dts;
- // These are for output, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
- int64_t video_previous_pts;
- int64_t video_previous_dts;
- int64_t audio_previous_pts;
- int64_t audio_previous_dts;
+ // These are for out, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
+ int64_t video_next_pts;
+ int64_t video_next_dts;
+ int64_t audio_next_pts;
+ int64_t audio_next_dts;
int64_t filter_in_rescale_delta_last;
bool setup_resampler();
public:
- VideoStore(const char *filename_in, const char *format_in, AVStream *video_input_stream, AVStream *audio_input_stream, int64_t nStartTime, Monitor * p_monitor );
+ VideoStore(
+ const char *filename_in,
+ const char *format_in,
+ AVStream *video_in_stream,
+ AVStream *audio_in_stream,
+ int64_t nStartTime,
+ Monitor * p_monitor);
~VideoStore();
int writeVideoFramePacket( AVPacket *pkt );
diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp
index 7e4d151ff..1b4cb946f 100644
--- a/src/zm_zone.cpp
+++ b/src/zm_zone.cpp
@@ -68,7 +68,7 @@ void Zone::Setup(
overload_frames = p_overload_frames;
extend_alarm_frames = p_extend_alarm_frames;
- Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames );
+ //Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames );
alarmed = false;
was_alarmed = false;
diff --git a/src/zms.cpp b/src/zms.cpp
index 3b1a6dfd1..d8fc0a86c 100644
--- a/src/zms.cpp
+++ b/src/zms.cpp
@@ -52,7 +52,7 @@ int main( int argc, const char *argv[] ) {
srand( getpid() * time( 0 ) );
- enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
+ enum { ZMS_UNKNOWN, ZMS_MONITOR, ZMS_EVENT } source = ZMS_UNKNOWN;
enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG;
char format[32] = "";
int monitor_id = 0;
@@ -121,12 +121,16 @@ int main( int argc, const char *argv[] ) {
strncpy( format, value, sizeof(format) );
} else if ( !strcmp( name, "monitor" ) ) {
monitor_id = atoi( value );
+ if ( source == ZMS_UNKNOWN )
+ source = ZMS_MONITOR;
} else if ( !strcmp( name, "time" ) ) {
event_time = atoi( value );
} else if ( !strcmp( name, "event" ) ) {
event_id = strtoull( value, (char **)NULL, 10 );
+ source = ZMS_EVENT;
} else if ( !strcmp( name, "frame" ) ) {
frame_id = strtoull( value, (char **)NULL, 10 );
+ source = ZMS_EVENT;
} else if ( !strcmp( name, "scale" ) ) {
scale = atoi( value );
} else if ( !strcmp( name, "rate" ) ) {
@@ -264,6 +268,7 @@ int main( int argc, const char *argv[] ) {
if ( ! event_id ) {
Fatal( "Can't view an event without specifying an event_id." );
}
+ Debug(3,"Doing event stream scale(%d)", scale );
EventStream stream;
stream.setStreamScale( scale );
stream.setStreamReplayRate( rate );
@@ -273,6 +278,7 @@ int main( int argc, const char *argv[] ) {
if ( monitor_id && event_time ) {
stream.setStreamStart( monitor_id, event_time );
} else {
+ Debug(3, "Setting stream start to frame (%d)", frame_id);
stream.setStreamStart( event_id, frame_id );
}
if ( mode == ZMS_JPEG ) {
@@ -291,6 +297,8 @@ int main( int argc, const char *argv[] ) {
#endif // HAVE_LIBAVCODEC
} // end if jpeg or mpeg
stream.runStream();
+ } else {
+ Error("Neither a monitor or event was specified.");
} // end if monitor or event
logTerm();
diff --git a/utils/packpack/redhat_package.mk b/utils/packpack/redhat_package.mk
index c15e03528..34974e1b0 100644
--- a/utils/packpack/redhat_package.mk
+++ b/utils/packpack/redhat_package.mk
@@ -4,5 +4,5 @@
redhat_package: redhat_bootstrap package
redhat_bootstrap:
- sudo yum install -y --nogpgcheck build/zmrepo.noarch.rpm
+ sudo yum install -y --nogpgcheck build/external-repo.noarch.rpm
diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh
index 4e32671fd..4bf9e9ff6 100755
--- a/utils/packpack/startpackpack.sh
+++ b/utils/packpack/startpackpack.sh
@@ -9,7 +9,7 @@
# General sanity checks
checksanity () {
# Check to see if this script has access to all the commands it needs
- for CMD in set echo curl repoquery git ln mkdir rmdir cat patch; do
+ for CMD in set echo curl git ln mkdir rmdir cat patch; do
type $CMD 2>&1 > /dev/null
if [ $? -ne 0 ]; then
@@ -20,6 +20,19 @@ checksanity () {
fi
done
+ if [ "${OS}" == "el" ] && [ "${DIST}" == "6" ]; then
+ type repoquery 2>&1 > /dev/null
+
+ if [ $? -ne 0 ]; then
+ echo
+ echo "ERROR: The script cannot find the required command \"reqoquery\"."
+ echo "This command is required in order to build ZoneMinder on el6."
+ echo "Please install the \"yum-utils\" package then try again."
+ echo
+ exit 1
+ fi
+ fi
+
# Verify OS & DIST environment variables have been set before calling this script
if [ -z "${OS}" ] || [ -z "${DIST}" ]; then
echo "ERROR: both OS and DIST environment variables must be set"
@@ -211,6 +224,26 @@ zoneminder ($VERSION-${DIST}-1) unstable; urgency=low
EOF
}
+# start packpack, filter the output if we are running in travis
+execpackpack () {
+
+ if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
+ parms="-f utils/packpack/redhat_package.mk redhat_package"
+ else
+ parms=""
+ fi
+
+ if [ "${TRAVIS}" == "true" ]; then
+ utils/packpack/heartbeat.sh &
+ mypid=$!
+ packpack/packpack $parms > buildlog.txt 2>&1
+ kill $mypid
+ tail -n 3000 buildlog.txt | grep -v ONVIF
+ else
+ packpack/packpack $parms
+ fi
+}
+
################
# MAIN PROGRAM #
################
@@ -235,31 +268,31 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
rm -rf web/api/app/Plugin/Crud
mkdir web/api/app/Plugin/Crud
- if [ "${OS}" == "el" ]; then
- zmrepodistro=${OS}
+ # We use zmrepo to build el6 only. All other redhat distros use rpm fusion
+ if [ "${OS}" == "el" ] && [ "${DIST}" == "6" ]; then
+ baseurl="https://zmrepo.zoneminder.com/el/${DIST}/x86_64/"
+ reporpm="zmrepo"
+ # Let repoquery determine the full url and filename to the latest zmrepo package
+ dlurl=`repoquery --archlist=noarch --repofrompath=zmpackpack,${baseurl} --repoid=zmpackpack --qf="%{location}" ${reporpm} 2> /dev/null`
else
- zmrepodistro="f"
+ reporpm="rpmfusion-free-release"
+ dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
fi
- # Let repoquery determine the full url and filename of the zmrepo rpm we are interested in
- result=`repoquery --repofrompath=zmpackpack,https://zmrepo.zoneminder.com/${zmrepodistro}/"${DIST}"/x86_64/ --repoid=zmpackpack --qf="%{location}" zmrepo 2> /dev/null`
-
- if [ -n "$result" ] && [ $? -eq 0 ]; then
- echo "Retrieving ZMREPO rpm..."
- curl $result > build/zmrepo.noarch.rpm
+ # Give our downloaded repo rpm a common name so redhat_package.mk can find it
+ if [ -n "$dlurl" ] && [ $? -eq 0 ]; then
+ echo "Retrieving ${reporpm} repo rpm..."gd
+ curl $dlurl > build/external-repo.noarch.rpm
else
- echo "ERROR: Failed to retrieve zmrepo rpm..."
+ echo "ERROR: Failed to retrieve ${reporpm} repo rpm..."
+ echo "Download url was: $dlurl"
exit 1
fi
setrpmchangelog
echo "Starting packpack..."
- utils/packpack/heartbeat.sh &
- mypid=$!
- packpack/packpack -f utils/packpack/redhat_package.mk redhat_package > buildlog.txt 2>&1
- kill $mypid
- tail -n 3000 buildlog.txt | grep -v ONVIF
+ execpackpack
# Steps common to Debian based distros
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
@@ -279,11 +312,7 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
setdebchangelog
echo "Starting packpack..."
- utils/packpack/heartbeat.sh &
- mypid=$!
- packpack/packpack > buildlog.txt 2>&1
- kill $mypid
- tail -n 3000 buildlog.txt | grep -v ONVIF
+ execpackpack
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
installtrusty
@@ -303,11 +332,7 @@ elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86
setdebchangelog
echo "Starting packpack..."
- utils/packpack/heartbeat.sh &
- mypid=$!
- packpack/packpack > buildlog.txt 2>&1
- kill $mypid
- tail -n 3000 buildlog.txt | grep -v ONVIF
+ execpackpack
# If we are running inside Travis then attempt to install the deb we just built
if [ "${TRAVIS}" == "true" ]; then
diff --git a/web/api/app/Config/bootstrap.php.in b/web/api/app/Config/bootstrap.php.in
index a3213d150..cc096f233 100644
--- a/web/api/app/Config/bootstrap.php.in
+++ b/web/api/app/Config/bootstrap.php.in
@@ -138,15 +138,15 @@ if ( is_dir($configSubFolder) ) {
# Now that our array our finalized, define each key => value
# pair in the array as a constant
foreach( $configvals as $key => $value) {
- define( $key, $value );
- Configure::write( $matches[1], $matches[2] );
+ define( $key, $value );
+ Configure::write( $key, $value );
}
function process_configfile($configFile) {
if ( is_readable( $configFile ) ) {
$configvals = array();
- $cfg = fopen( $configFile, "r") or die("Could not open config file.");
+ $cfg = fopen( $configFile, 'r') or die('Could not open config file.');
while ( !feof($cfg) ) {
$str = fgets( $cfg, 256 );
if ( preg_match( '/^\s*$/', $str ))
diff --git a/web/api/app/Config/database.php.default b/web/api/app/Config/database.php.default
index 55f2bc958..c06953ec7 100644
--- a/web/api/app/Config/database.php.default
+++ b/web/api/app/Config/database.php.default
@@ -70,6 +70,9 @@ class DATABASE_CONFIG {
'login' => ZM_DB_USER,
'password' => ZM_DB_PASS,
'database' => ZM_DB_NAME,
+ 'ssl_ca' => ZM_DB_SSL_CA_CERT,
+ 'ssl_key' => ZM_DB_SSL_CLIENT_KEY,
+ 'ssl_cert' => ZM_DB_SSL_CLIENT_CERT,
'prefix' => '',
'encoding' => 'utf8',
);
diff --git a/web/includes/Event.php b/web/includes/Event.php
index 70668690b..a9102723f 100644
--- a/web/includes/Event.php
+++ b/web/includes/Event.php
@@ -131,7 +131,7 @@ class Event {
} # end Event->delete
public function getStreamSrc( $args=array(), $querySep='&' ) {
- if ( $this->{'DefaultVideo'} ) {
+ if ( $this->{'DefaultVideo'} and $args['mode'] != 'jpeg' ) {
return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'};
}
@@ -202,7 +202,7 @@ class Event {
// frame is an array representing the db row for a frame.
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
- $Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
+ $Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
$Event = $this;
$eventPath = $Event->Path();
@@ -217,28 +217,31 @@ class Event {
$captImage = 'snapshot.jpg';
Debug("Frame not specified, using snapshot");
} else {
- $captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
+ $captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyze.jpg', $frame['FrameId'] );
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
- # Generate the frame JPG
- if ( $Event->DefaultVideo() ) {
- $videoPath = $eventPath.'/'.$Event->DefaultVideo();
+ $captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
+ if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
+ # Generate the frame JPG
+ if ( $Event->DefaultVideo() ) {
+ $videoPath = $eventPath.'/'.$Event->DefaultVideo();
- if ( ! file_exists( $videoPath ) ) {
- Error("Event claims to have a video file, but it does not seem to exist at $videoPath" );
- return '';
- }
-
- #$command ='ffmpeg -v 0 -i '.$videoPath.' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
- $command ='ffmpeg -ss '. $frame['Delta'] .' -i '.$videoPath.' -frames:v 1 '.$eventPath.'/'.$captImage;
- Logger::Debug( "Running $command" );
- $output = array();
- $retval = 0;
- exec( $command, $output, $retval );
- Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
- } else {
- Error("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() );
- }
- }
+ if ( ! file_exists( $videoPath ) ) {
+ Error("Event claims to have a video file, but it does not seem to exist at $videoPath" );
+ return '';
+ }
+
+ #$command ='ffmpeg -v 0 -i '.$videoPath.' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
+ $command ='ffmpeg -ss '. $frame['Delta'] .' -i '.$videoPath.' -frames:v 1 '.$eventPath.'/'.$captImage;
+ Logger::Debug( "Running $command" );
+ $output = array();
+ $retval = 0;
+ exec( $command, $output, $retval );
+ Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
+ } else {
+ Error("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() );
+ }
+ } // end if capture file exists
+ } // end if analyze file exists
}
$captPath = $eventPath.'/'.$captImage;
diff --git a/web/includes/actions.php b/web/includes/actions.php
index 0516f0a38..374f852a2 100644
--- a/web/includes/actions.php
+++ b/web/includes/actions.php
@@ -435,11 +435,11 @@ Warning("Addterm");
# If we change anything that changes the shared mem size, zma can complain. So let's stop first.
zmaControl( $monitor, 'stop' );
zmcControl( $monitor, 'stop' );
- dbQuery( 'UPDATE Monitors SET '.implode( ", ", $changes ).' WHERE Id =?', array($mid) );
+ dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) );
if ( isset($changes['Name']) ) {
$saferOldName = basename( $monitor['Name'] );
$saferNewName = basename( $_REQUEST['newMonitor']['Name'] );
- rename( ZM_DIR_EVENTS."/".$saferOldName, ZM_DIR_EVENTS."/".$saferNewName);
+ rename( ZM_DIR_EVENTS.'/'.$saferOldName, ZM_DIR_EVENTS.'/'.$saferNewName);
}
if ( isset($changes['Width']) || isset($changes['Height']) ) {
$newW = $_REQUEST['newMonitor']['Width'];
@@ -493,7 +493,7 @@ Warning("Addterm");
Error("Users with Monitors restrictions cannot create new monitors.");
}
$restart = true;
- }
+ } # end if count(changes)
if ( ZM_OPT_X10 ) {
$x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] );
@@ -521,7 +521,7 @@ Warning("Addterm");
zmcControl( $new_monitor, 'start' );
zmaControl( $new_monitor, 'start' );
- if ( $monitor['Controllable'] ) {
+ if ( $new_monitor['Controllable'] ) {
require_once( 'control_functions.php' );
sendControlCommand( $mid, 'quit' );
}
@@ -530,8 +530,7 @@ Warning("Addterm");
$refreshParent = true;
} // end if restart
$view = 'none';
- }
- if ( $action == 'delete' ) {
+ } elseif ( $action == 'delete' ) {
if ( isset($_REQUEST['markMids']) && !$user['MonitorIds'] ) {
foreach( $_REQUEST['markMids'] as $markMid ) {
if ( canEdit( 'Monitors', $markMid ) ) {
@@ -541,6 +540,18 @@ Warning("Addterm");
zmcControl( $monitor, 'stop' );
}
+ // If fast deletes are on, then zmaudit will clean everything else up later
+ // If fast deletes are off and there are lots of events then this step may
+ // well time out before completing, in which case zmaudit will still tidy up
+ if ( !ZM_OPT_FAST_DELETE ) {
+ $markEids = dbFetchAll( 'SELECT Id FROM Events WHERE MonitorId=?', 'Id', array($markMid) );
+ foreach( $markEids as $markEid )
+ deleteEvent( $markEid );
+
+ deletePath( ZM_DIR_EVENTS.'/'.basename($monitor['Name']) );
+ deletePath( ZM_DIR_EVENTS.'/'.$monitor['Id'] ); // I'm trusting the Id.
+ } // end if ZM_OPT_FAST_DELETE
+
// This is the important stuff
dbQuery( 'DELETE FROM Monitors WHERE Id = ?', array($markMid) );
dbQuery( 'DELETE FROM Zones WHERE MonitorId = ?', array($markMid) );
@@ -549,18 +560,6 @@ Warning("Addterm");
fixSequences();
- // If fast deletes are on, then zmaudit will clean everything else up later
- // If fast deletes are off and there are lots of events then this step may
- // well time out before completing, in which case zmaudit will still tidy up
- if ( !ZM_OPT_FAST_DELETE ) {
- // Slight hack, we maybe should load *, but we happen to know that the deleteEvent function uses Id and StartTime.
- $markEids = dbFetchAll( 'SELECT Id,StartTime FROM Events WHERE MonitorId=?', NULL, array($markMid) );
- foreach( $markEids as $markEid )
- deleteEvent( $markEid, $markMid );
-
- deletePath( ZM_DIR_EVENTS.'/'.basename($monitor['Name']) );
- deletePath( ZM_DIR_EVENTS.'/'.$monitor['Id'] ); // I'm trusting the Id.
- } // end if ZM_OPT_FAST_DELETE
} // end if found the monitor in the db
} // end if canedit this monitor
} // end foreach monitor in MarkMid
diff --git a/web/includes/config.php.in b/web/includes/config.php.in
index 991414a56..6f34a5eb1 100644
--- a/web/includes/config.php.in
+++ b/web/includes/config.php.in
@@ -29,13 +29,12 @@ define( "ZM_DIR_TEMP", "@ZM_TMPDIR@" );
$configFile = ZM_CONFIG;
$localConfigFile = basename($configFile);
-if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 )
-{
- if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) )
- print( "Warning, overriding installed $localConfigFile file with local copy\n" );
- else
- error_log( "Warning, overriding installed $localConfigFile file with local copy" );
- $configFile = $localConfigFile;
+if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) {
+ if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) )
+ print( "Warning, overriding installed $localConfigFile file with local copy\n" );
+ else
+ error_log( "Warning, overriding installed $localConfigFile file with local copy" );
+ $configFile = $localConfigFile;
}
# Process name, value pairs from the main config file first
@@ -45,19 +44,19 @@ $configvals = process_configfile($configFile);
# update our config value array with those values
$configSubFolder = ZM_CONFIG_SUBDIR;
if ( is_dir($configSubFolder) ) {
- if ( is_readable($configSubFolder) ) {
- foreach ( glob("$configSubFolder/*.conf") as $filename ) {
- $configvals = array_replace($configvals, process_configfile($filename) );
- }
- } else {
- error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." );
+ if ( is_readable($configSubFolder) ) {
+ foreach ( glob("$configSubFolder/*.conf") as $filename ) {
+ $configvals = array_replace($configvals, process_configfile($filename) );
}
+ } else {
+ error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." );
+ }
}
# Now that our array our finalized, define each key => value
# pair in the array as a constant
foreach( $configvals as $key => $value) {
- define( $key, $value );
+ define( $key, $value );
}
//
@@ -135,91 +134,87 @@ require_once( 'database.php' );
loadConfig();
$GLOBALS['defaultUser'] = array(
- "Username" => "admin",
- "Password" => "",
- "Language" => "",
- "Enabled" => 1,
- "Stream" => 'View',
- "Events" => 'Edit',
- "Control" => 'Edit',
- "Monitors" => 'Edit',
- "Groups" => 'Edit',
- "Devices" => 'Edit',
- "System" => 'Edit',
- "MaxBandwidth" => "",
- "MonitorIds" => false
+ "Username" => "admin",
+ "Password" => "",
+ "Language" => "",
+ "Enabled" => 1,
+ "Stream" => 'View',
+ "Events" => 'Edit',
+ "Control" => 'Edit',
+ "Monitors" => 'Edit',
+ "Groups" => 'Edit',
+ "Devices" => 'Edit',
+ "System" => 'Edit',
+ "MaxBandwidth" => "",
+ "MonitorIds" => false
);
-function loadConfig( $defineConsts=true )
-{
- global $config;
- global $configCats;
- global $dbConn;
+function loadConfig( $defineConsts=true ) {
+ global $config;
+ global $configCats;
+ global $dbConn;
- $config = array();
- $configCat = array();
+ $config = array();
+ $configCat = array();
- $result = $dbConn->query( 'select * from Config order by Id asc' );
- if ( !$result )
- echo mysql_error();
- $monitors = array();
- while( $row = dbFetchNext( $result ) )
- {
- if ( $defineConsts )
- define( $row['Name'], $row['Value'] );
- $config[$row['Name']] = $row;
- if ( !($configCat = &$configCats[$row['Category']]) )
- {
- $configCats[$row['Category']] = array();
- $configCat = &$configCats[$row['Category']];
- }
- $configCat[$row['Name']] = $row;
+ $result = $dbConn->query( 'select * from Config order by Id asc' );
+ if ( !$result )
+ echo mysql_error();
+ $monitors = array();
+ while( $row = dbFetchNext( $result ) ) {
+ if ( $defineConsts )
+ define( $row['Name'], $row['Value'] );
+ $config[$row['Name']] = $row;
+ if ( !($configCat = &$configCats[$row['Category']]) ) {
+ $configCats[$row['Category']] = array();
+ $configCat = &$configCats[$row['Category']];
}
- //print_r( $config );
- //print_r( $configCats );
+ $configCat[$row['Name']] = $row;
+ }
+ //print_r( $config );
+ //print_r( $configCats );
}
require_once( 'logger.php' );
// For Human-readability, user ZM_SERVER in zm.conf, and convert it here to a ZM_SERVER_ID
if ( ! defined('ZM_SERVER_ID') ) {
- if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
- $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
- if ( ! $server_id ) {
- Error("Invalid Multi-Server configration detected. ZM_SERVER_NAME set to " . ZM_SERVER_NAME . " in zm.conf, but no corresponding entry found in Servers table.");
- } else {
- define( 'ZM_SERVER_ID', $server_id );
- }
- } else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
- $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST));
- if ( ! $server_id ) {
- Error("Invalid Multi-Server configration detected. ZM_SERVER_HOST set to " . ZM_SERVER_HOST . " in zm.conf, but no corresponding entry found in Servers table.");
- } else {
- define( 'ZM_SERVER_ID', $server_id );
- }
- }
+ if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
+ $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
+ if ( ! $server_id ) {
+ Error("Invalid Multi-Server configration detected. ZM_SERVER_NAME set to " . ZM_SERVER_NAME . " in zm.conf, but no corresponding entry found in Servers table.");
+ } else {
+ define( 'ZM_SERVER_ID', $server_id );
+ }
+ } else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
+ $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST));
+ if ( ! $server_id ) {
+ Error("Invalid Multi-Server configration detected. ZM_SERVER_HOST set to " . ZM_SERVER_HOST . " in zm.conf, but no corresponding entry found in Servers table.");
+ } else {
+ define( 'ZM_SERVER_ID', $server_id );
+ }
+ }
}
function process_configfile($configFile) {
- if ( is_readable( $configFile ) ) {
- $configvals = array();
+ if ( is_readable( $configFile ) ) {
+ $configvals = array();
- $cfg = fopen( $configFile, "r") or die("Could not open config file.");
- while ( !feof($cfg) )
- {
- $str = fgets( $cfg, 256 );
- if ( preg_match( '/^\s*$/', $str ))
- continue;
- elseif ( preg_match( '/^\s*#/', $str ))
- continue;
- elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
- $configvals[$matches[1]] = $matches[2];
- }
- fclose( $cfg );
- return( $configvals );
- } else {
- error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." );
- return( false );
+ $cfg = fopen( $configFile, 'r') or Error("Could not open config file: $configFile.");
+ while ( !feof($cfg) ) {
+ $str = fgets( $cfg, 256 );
+ if ( preg_match( '/^\s*$/', $str ))
+ continue;
+ elseif ( preg_match( '/^\s*#/', $str ))
+ continue;
+ elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
+ $configvals[$matches[1]] = $matches[2];
}
+ fclose( $cfg );
+ return( $configvals );
+ } else {
+ error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." );
+ return( false );
+ }
}
?>
diff --git a/web/includes/database.php b/web/includes/database.php
index dea9e4b8c..9a3a863d3 100644
--- a/web/includes/database.php
+++ b/web/includes/database.php
@@ -18,9 +18,9 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
-define( "DB_LOG_OFF", 0 );
-define( "DB_LOG_ONLY", 1 );
-define( "DB_LOG_DEBUG", 2 );
+define( 'DB_LOG_OFF', 0 );
+define( 'DB_LOG_ONLY', 1 );
+define( 'DB_LOG_DEBUG', 2 );
$GLOBALS['dbLogLevel'] = DB_LOG_OFF;
@@ -42,11 +42,23 @@ function dbConnect() {
}
try {
- $dbConn = new PDO( ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS );
+ $dbOptions = null;
+ if ( defined( 'ZM_DB_SSL_CA_CERT' ) and ZM_DB_SSL_CA_CERT ) {
+ $dbOptions = array(
+ PDO::MYSQL_ATTR_SSL_CA => ZM_DB_SSL_CA_CERT,
+ PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
+ PDO::MYSQL_ATTR_SSL_CERT => ZM_DB_SSL_CLIENT_CERT,
+ );
+ $dbConn = new PDO( ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions );
+ } else {
+ $dbConn = new PDO( ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS );
+ }
+
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $ex ) {
- echo "Unable to connect to ZM db." . $ex->getMessage();
+ echo 'Unable to connect to ZM db.' . $ex->getMessage();
+ error_log('Unable to connect to ZM DB ' . $ex->getMessage() );
$dbConn = null;
}
}
@@ -91,7 +103,7 @@ function dbError( $sql ) {
function dbEscape( $string ) {
global $dbConn;
- if ( version_compare( phpversion(), "4.3.0", "<") )
+ if ( version_compare( phpversion(), '4.3.0', '<') )
if ( get_magic_quotes_gpc() )
return( $dbConn->quote( stripslashes( $string ) ) );
else
@@ -217,7 +229,7 @@ function getTableColumns( $table, $asString=1 ) {
}
function getTableAutoInc( $table ) {
- $row = dbFetchOne( "show table status where Name=?", NULL, array($table) );
+ $row = dbFetchOne( 'show table status where Name=?', NULL, array($table) );
return( $row['Auto_increment'] );
}
@@ -329,11 +341,11 @@ function getTableDescription( $table, $asString=1 ) {
}
function dbFetchMonitor( $mid ) {
- return( dbFetchOne( "select * from Monitors where Id = ?", NULL, array($mid) ) );
+ return( dbFetchOne( 'select * from Monitors where Id = ?', NULL, array($mid) ) );
}
function dbFetchGroup( $gid ) {
- return( dbFetchOne( "select * from Groups where Id = ?", NULL, array($gid) ) );
+ return( dbFetchOne( 'select * from Groups where Id = ?', NULL, array($gid) ) );
}
?>
diff --git a/web/index.php b/web/index.php
index 6673b3079..69bea52ee 100644
--- a/web/index.php
+++ b/web/index.php
@@ -194,7 +194,7 @@ isset($view) || $view = NULL;
isset($request) || $request = NULL;
isset($action) || $action = NULL;
-if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $request != 'control' ) {
+if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' ) {
require_once( 'includes/csrf/csrf-magic.php' );
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check();
diff --git a/web/skins/classic/css/classic/views/zone.css b/web/skins/classic/css/classic/views/zone.css
index 897ee50ee..a637787d5 100644
--- a/web/skins/classic/css/classic/views/zone.css
+++ b/web/skins/classic/css/classic/views/zone.css
@@ -52,15 +52,15 @@
}
#imageFrame div {
- background-image: url(../../../graphics/point-g.gif);
+ background-image: url(../../../graphics/point-g.png);
}
#imageFrame div.highlight {
- background-image: url(../../../graphics/point-o.gif);
+ background-image: url(../../../graphics/point-o.png);
}
#imageFrame div.active {
- background-image: url(../../../graphics/point-r.gif);
+ background-image: url(../../../graphics/point-r.png);
}
#zonePoints {
diff --git a/web/skins/classic/css/dark/views/zone.css b/web/skins/classic/css/dark/views/zone.css
index 884c8dbe0..7d81d731b 100644
--- a/web/skins/classic/css/dark/views/zone.css
+++ b/web/skins/classic/css/dark/views/zone.css
@@ -52,15 +52,15 @@
}
#imageFrame div {
- background-image: url(../../../graphics/point-g.gif);
+ background-image: url(../../../graphics/point-g.png);
}
#imageFrame div.highlight {
- background-image: url(../../../graphics/point-o.gif);
+ background-image: url(../../../graphics/point-o.png);
}
#imageFrame div.active {
- background-image: url(../../../graphics/point-r.gif);
+ background-image: url(../../../graphics/point-r.png);
}
#zonePoints {
diff --git a/web/skins/classic/css/flat/views/zone.css b/web/skins/classic/css/flat/views/zone.css
index 023dd8d21..6b35ca287 100644
--- a/web/skins/classic/css/flat/views/zone.css
+++ b/web/skins/classic/css/flat/views/zone.css
@@ -52,15 +52,15 @@
}
#imageFrame div {
- background-image: url(../../../graphics/point-g.gif);
+ background-image: url(../../../graphics/point-g.png);
}
#imageFrame div.highlight {
- background-image: url(../../../graphics/point-o.gif);
+ background-image: url(../../../graphics/point-o.png);
}
#imageFrame div.active {
- background-image: url(../../../graphics/point-r.gif);
+ background-image: url(../../../graphics/point-r.png);
}
#zonePoints {
diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php
index 3f39029ed..440722b28 100644
--- a/web/skins/classic/views/console.php
+++ b/web/skins/classic/views/console.php
@@ -51,7 +51,7 @@ $eventCounts = array(
'filter' => array(
'Query' => array(
'terms' => array(
- array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 day' ),
+ array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 day' ),
)
)
),
@@ -62,7 +62,7 @@ $eventCounts = array(
'filter' => array(
'Query' => array(
'terms' => array(
- array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-7 day' ),
+ array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-7 day' ),
)
)
),
@@ -73,7 +73,7 @@ $eventCounts = array(
'filter' => array(
'Query' => array(
'terms' => array(
- array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 month' ),
+ array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 month' ),
)
)
),
@@ -84,7 +84,7 @@ $eventCounts = array(
'filter' => array(
'Query' => array(
'terms' => array(
- array( 'attr' => "Archived", 'op' => '=', 'val' => '1' ),
+ array( 'attr' => 'Archived', 'op' => '=', 'val' => '1' ),
)
)
),
@@ -107,7 +107,7 @@ for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
parseFilter( $filter );
- $counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j";
+ $counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) as EventCount$j";
$monitor['eventCounts'][$j]['filter'] = $filter;
}
$sql = 'select '.join($counts,', ').' from Events as E where MonitorId = ?';
@@ -203,45 +203,27 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
Name(); ?>
-
- '.$monitor['Device'].' ('.$monitor['Channel'].')', canEdit( 'Monitors' ) ) ?>
-
- '.preg_replace( '/^.*@/', '', $monitor['Host'] ).'', canEdit( 'Monitors' ) ) ?>
-
- '.preg_replace( '/^.*\//', '', $monitor['Path'] ).'', canEdit( 'Monitors' ) ) ?>
-
- '.$shortpath.'', canEdit( 'Monitors' ) ) ?>
-
- '.preg_replace( '/^.*\//', '', $monitor['Path'] ).'', canEdit( 'Monitors' ) ) ?>
-
-
-
-'. makePopupLink( '?view=monitor&mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', ''.$source.' ', canEdit( 'Monitors' ) ).'';
if ( $show_storage_areas ) {
?>
Name(); ?>
diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php
index 7aad2b36e..7c3ffbd4b 100644
--- a/web/skins/classic/views/events.php
+++ b/web/skins/classic/views/events.php
@@ -193,7 +193,9 @@ foreach ( $events as $event ) {
Id().$filterQuery.$sortQuery.'&page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->Id().($event->Archived()?'*':'') ) ?>
Id().$filterQuery.$sortQuery.'&page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), reScale( $event->Height(), $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ) ), validHtmlStr($event->Name()).($event->Archived()?'*':'' ) ) ?>
- MonitorName() ?>
+ MonitorId(), 'zmMonitor'.$event->Monitorid(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) )
+ ?>
Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
StartTime()) ) ?>
Length() ) ?>
diff --git a/web/skins/classic/views/image-ffmpeg.php b/web/skins/classic/views/image-ffmpeg.php
index 1030ddfde..496b4c695 100644
--- a/web/skins/classic/views/image-ffmpeg.php
+++ b/web/skins/classic/views/image-ffmpeg.php
@@ -15,7 +15,7 @@
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Events' ) )
diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js
index 5e8f147b1..91655aac5 100644
--- a/web/skins/classic/views/js/console.js
+++ b/web/skins/classic/views/js/console.js
@@ -88,7 +88,7 @@ $j( function() {
function applySort(event, ui) {
var monitor_ids = $j(this).sortable('toArray');
var ajax = new Request.JSON( {
- url: '/index.php?request=console',
+ url: '?request=console',
data: { monitor_ids: monitor_ids, action: 'sort' },
method: 'post',
timeout: AJAX_TIMEOUT
diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js
index 2909f0476..57ad9d86c 100644
--- a/web/skins/classic/views/js/watch.js
+++ b/web/skins/classic/views/js/watch.js
@@ -31,7 +31,7 @@ function changeScale() {
Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } );
/*Stream could be an applet so can't use moo tools*/
- var streamImg = $('#liveStream'+monitorId);
+ var streamImg = $('liveStream'+monitorId);
if ( streamImg ) {
streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px";
@@ -197,7 +197,7 @@ function getStreamCmdResponse( respObj, respText ) {
var streamImg = $('liveStream'+monitorId);
if ( streamImg ) {
streamImg.src = streamImg.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
- console.log("Changing lviestream src to " + streamImg.src);
+ console.log("Changing livestream src to " + streamImg.src);
} else {
console.log("Unable to find streamImg liveStream");
}
@@ -357,7 +357,14 @@ function statusCmdQuery() {
var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
if ( auth_hash )
alarmCmdParms += '&auth='+auth_hash;
-var alarmCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getAlarmCmdResponse, onTimeout: streamCmdQuery } );
+var alarmCmdReq = new Request.JSON( {
+ url: monitorUrl+thisUrl,
+ method: 'post',
+ timeout: AJAX_TIMEOUT,
+ link: 'cancel',
+ onSuccess: getAlarmCmdResponse,
+ onTimeout: streamCmdQuery
+} );
var alarmCmdFirst = true;
function getAlarmCmdResponse( respObj, respText ) {
@@ -378,11 +385,13 @@ function cmdForceAlarm() {
function cmdCancelForcedAlarm() {
alarmCmdReq.send( alarmCmdParms+"&command=cancelForcedAlarm" );
+ return false;
}
function getActResponse( respObj, respText ) {
if ( respObj.result == 'Ok' ) {
if ( respObj.refreshParent ) {
+ console.log('refreshing');
window.opener.location.reload();
}
}
diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php
index c5a76b420..1699d7186 100644
--- a/web/skins/classic/views/monitor.php
+++ b/web/skins/classic/views/monitor.php
@@ -155,14 +155,14 @@ function fourcc( $a, $b, $c, $d ) {
}
if ( isset( $_REQUEST['newMonitor'] ) ) {
- # Update the monitor object with whatever has been set so far.
+ # Update the monitor object with whatever has been set so far.
$monitor->set( $_REQUEST['newMonitor'] );
if ( ZM_OPT_X10 )
$newX10Monitor = $_REQUEST['newX10Monitor'];
} else {
- # FIXME: Triggers in the db is a comma separated string. Needs to be an array.
- #$monitor->Triggers()= explode( ',', isset($monitor->Triggers())?$monitor->Triggers:"" );
+ # FIXME: Triggers in the db is a comma separated string. Needs to be an array.
+ #$monitor->Triggers()= explode( ',', isset($monitor->Triggers())?$monitor->Triggers:"" );
if ( ZM_OPT_X10 )
$newX10Monitor = $x10Monitor;
}
@@ -178,9 +178,9 @@ if ( $monitor->AlarmMaxFPS() == '0.00' )
if ( !empty($_REQUEST['preset']) ) {
$preset = dbFetchOne( 'SELECT Type, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Palette, MaxFPS, Controllable, ControlId, ControlDevice, ControlAddress, DefaultRate, DefaultScale FROM MonitorPresets WHERE Id = ?', NULL, array($_REQUEST['preset']) );
foreach ( $preset as $name=>$value ) {
- # Does isset handle NULL's? I don't think this code is correct.
+ # Does isset handle NULL's? I don't think this code is correct.
if ( isset($value) ) {
- $monitor->$name = $value;
+ $monitor->$name = $value;
}
}
}
@@ -188,17 +188,17 @@ if ( !empty($_REQUEST['probe']) ) {
$probe = unserialize(base64_decode($_REQUEST['probe']));
foreach ( $probe as $name=>$value ) {
if ( isset($value) ) {
- # Does isset handle NULL's? I don't think this code is correct.
- $monitor->$name = $value;
+ # Does isset handle NULL's? I don't think this code is correct.
+ $monitor->$name = $value;
}
}
- if ( ZM_HAS_V4L && $monitor->Type() == 'Local' ) {
- $monitor->Palette( fourCC( substr($monitor->Palette,0,1), substr($monitor->Palette,1,1), substr($monitor->Palette,2,1), substr($monitor->Palette,3,1) ) );
- if ( $monitor->Format() == 'PAL' )
- $monitor->Format( 0x000000ff );
- elseif ( $monitor->Format() == 'NTSC' )
- $monitor->Format( 0x0000b000 );
- }
+ if ( ZM_HAS_V4L && $monitor->Type() == 'Local' ) {
+ $monitor->Palette( fourCC( substr($monitor->Palette,0,1), substr($monitor->Palette,1,1), substr($monitor->Palette,2,1), substr($monitor->Palette,3,1) ) );
+ if ( $monitor->Format() == 'PAL' )
+ $monitor->Format( 0x000000ff );
+ elseif ( $monitor->Format() == 'NTSC' )
+ $monitor->Format( 0x0000b000 );
+ }
}
$sourceTypes = array(
@@ -683,19 +683,19 @@ switch ( $tab ) {
'Default');
- $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
- $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
- foreach ( $results as $row => $storage_obj ) {
- $storage_areas[$storage_obj->Id] = $storage_obj->Name();
- }
- echo htmlSelect( 'newMonitor[StorageId]', $storage_areas, $monitor->StorageId() );
+ $storage_areas = array(0=>'Default');
+ $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
+ $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
+ foreach ( $results as $row => $storage_obj ) {
+ $storage_areas[$storage_obj->Id] = $storage_obj->Name();
+ }
+ echo htmlSelect( 'newMonitor[StorageId]', $storage_areas, $monitor->StorageId() );
?>
Type() ); ?>
Function()) { ?> selected="selected">
Enabled()) ) { ?> checked="checked"/>
-
-
-
+
+
+
LinkedMonitors()) )
- $monitorIds = array_flip( explode( ',', $monitor->LinkedMonitors()) );
- else
- $monitorIds = array();
- foreach ( $monitors as $linked_monitor ) {
- if ( (empty($monitor->Id()) || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor( $linked_monitor['Id'] ) ) {
+ $monitors = dbFetchAll( 'select Id,Name from Monitors order by Sequence asc' );
+ if ( !empty($monitor->LinkedMonitors()) )
+ $monitorIds = array_flip( explode( ',', $monitor->LinkedMonitors()) );
+ else
+ $monitorIds = array();
+ foreach ( $monitors as $linked_monitor ) {
+ if ( (empty($monitor->Id()) || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor( $linked_monitor['Id'] ) ) {
?>
- selected="selected">
+ selected="selected">
-
-
+
+
Method() == 'v4l1' ) {
?>
- $value ) { ?>Channel()) { ?> selected="selected">
- $value ) { ?>Format()) { ?> selected="selected">
- $value ) { ?>Palette()) { ?> selected="selected">
+ $value ) { ?>Channel()) { ?> selected="selected">
+ $value ) { ?>Format()) { ?> selected="selected">
+ $value ) { ?>Palette()) { ?> selected="selected">
- $value ) { ?>Channel()) { ?> selected="selected">
- $value ) { ?>Format()) { ?> selected="selected">
- $value ) { ?>Palette()) { ?> selected="selected">
+ $value ) { ?>Channel()) { ?> selected="selected">
+ $value ) { ?>Format()) { ?> selected="selected">
+ $value ) { ?>Palette()) { ?> selected="selected">
- V4LMultiBuffer() == 1 ? 'checked="checked"' : '' ) ?>/>
- Yes
- V4LMultiBuffer() == 0 ? 'checked="checked"' : '' ) ?>/>
- No
- V4LMultiBuffer()) ? 'checked="checked"' : '' ) ?>/>
- Use Config Value
+ V4LMultiBuffer() == 1 ? 'checked="checked"' : '' ) ?>/>
+ Yes
+ V4LMultiBuffer() == 0 ? 'checked="checked"' : '' ) ?>/>
+ No
+ V4LMultiBuffer()) ? 'checked="checked"' : '' ) ?>/>
+ Use Config Value
Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?>
Protocol()) || $monitor->Protocol() == 'http' ) {
+ if ( empty($monitor->Protocol()) || $monitor->Protocol() == 'http' ) {
?>
- Method() ); ?>
+ Method() ); ?>
@@ -870,7 +870,7 @@ switch ( $tab ) {
- $value ) { ?>Deinterlacing()) { ?> selected="selected">
+ $value ) { ?>Deinterlacing()) { ?> selected="selected">
@@ -954,41 +954,41 @@ switch ( $tab ) {
Controllable()) )
- continue;
+ foreach ( getEnumValues( 'Monitors', 'DefaultView' ) as $opt_view ) {
+ if ( $opt_view == 'Control' && ( !ZM_OPT_CONTROL || !$monitor->Controllable()) )
+ continue;
?>
- DefaultView()) { ?> selected="selected">
+ DefaultView()) { ?> selected="selected">
-
+
DefaultRate() ); ?>
DefaultScale() ); ?>
Type() == 'Local' ) {
+ if ( ZM_HAS_V4L && $monitor->Type() == 'Local' ) {
?>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
- ()
- Exif()) ) { ?> checked="checked"/>
-
+ ()
+ Exif()) ) { ?> checked="checked"/>
+
Path();
$videoFormats = array();
$ffmpegFormats = preg_split( '/\s+/', ZM_FFMPEG_FORMATS );
-foreach ( $ffmpegFormats as $ffmpegFormat )
-{
- if ( preg_match( '/^([^*]+)(\*\*?)$/', $ffmpegFormat, $matches ) )
- {
- $videoFormats[$matches[1]] = $matches[1];
- if ( !isset($videoFormat) && $matches[2] == "*" )
- {
- $videoFormat = $matches[1];
- }
- }
- else
- {
- $videoFormats[$ffmpegFormat] = $ffmpegFormat;
+foreach ( $ffmpegFormats as $ffmpegFormat ) {
+ if ( preg_match( '/^([^*]+)(\*\*?)$/', $ffmpegFormat, $matches ) ) {
+ $videoFormats[$matches[1]] = $matches[1];
+ if ( !isset($videoFormat) && $matches[2] == '*' ) {
+ $videoFormat = $matches[1];
}
+ } else {
+ $videoFormats[$ffmpegFormat] = $ffmpegFormat;
+ }
}
$videoFiles = array();
-if ( $dir = opendir( $eventPath ) )
-{
- while ( ($file = readdir( $dir )) !== false )
- {
- $file = $eventPath.'/'.$file;
- if ( is_file( $file ) )
- {
- if ( preg_match( '/\.(?:'.join( '|', $videoFormats ).')$/', $file ) )
- {
- $videoFiles[] = $file;
- }
- }
+if ( $dir = opendir( $eventPath ) ) {
+ while ( ($file = readdir( $dir )) !== false ) {
+ $file = $eventPath.'/'.$file;
+ if ( is_file( $file ) ) {
+ if ( preg_match( '/\.(?:'.join( '|', $videoFormats ).')$/', $file ) ) {
+ $videoFiles[] = $file;
+ }
}
- closedir( $dir );
+ }
+ closedir( $dir );
}
-if ( isset($_REQUEST['deleteIndex']) )
-{
- $deleteIndex = validInt($_REQUEST['deleteIndex']);
- unlink( $videoFiles[$deleteIndex] );
- unset( $videoFiles[$deleteIndex] );
+if ( isset($_REQUEST['deleteIndex']) ) {
+ $deleteIndex = validInt($_REQUEST['deleteIndex']);
+ unlink( $videoFiles[$deleteIndex] );
+ unset( $videoFiles[$deleteIndex] );
}
-if ( isset($_REQUEST['downloadIndex']) )
-{
- $downloadIndex = validInt($_REQUEST['downloadIndex']);
- header( "Pragma: public" );
- header( "Expires: 0" );
- header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
- header( "Cache-Control: private", false ); // required by certain browsers
- header( "Content-Description: File Transfer" );
- header( 'Content-disposition: attachment; filename="'.basename($videoFiles[$downloadIndex]).'"' ); // basename is required because the video index contains the path and firefox doesn't strip the path but simply replaces the slashes with an underscore.
- header( "Content-Transfer-Encoding: binary" );
- header( "Content-Type: application/force-download" );
- header( "Content-Length: ".filesize($videoFiles[$downloadIndex]) );
- readfile( $videoFiles[$downloadIndex] );
- exit;
+if ( isset($_REQUEST['downloadIndex']) ) {
+ $downloadIndex = validInt($_REQUEST['downloadIndex']);
+ header( 'Pragma: public' );
+ header( 'Expires: 0' );
+ header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
+ header( 'Cache-Control: private', false ); // required by certain browsers
+ header( 'Content-Description: File Transfer' );
+ header( 'Content-disposition: attachment; filename="'.basename($videoFiles[$downloadIndex]).'"' ); // basename is required because the video index contains the path and firefox doesn't strip the path but simply replaces the slashes with an underscore.
+ header( 'Content-Transfer-Encoding: binary' );
+ header( 'Content-Type: application/force-download' );
+ header( 'Content-Length: '.filesize($videoFiles[$downloadIndex]) );
+ readfile( $videoFiles[$downloadIndex] );
+ exit;
}
$focusWindow = true;
@@ -122,19 +110,16 @@ xhtmlHeaders(__FILE__, translate('Video') );
@@ -197,32 +176,24 @@ else
0 )
- {
- preg_match( '/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches );
- if ( preg_match( '/^r(.+)$/', $matches[2], $temp_matches ) )
- {
- $rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
- $rateText = isset($rates[$rate])?$rates[$rate]:($rate."x");
- }
- elseif ( preg_match( '/^F(.+)$/', $matches[2], $temp_matches ) )
- {
- $rateText = $temp_matches[1]."fps";
- }
- if ( preg_match( '/^s(.+)$/', $matches[3], $temp_matches ) )
- {
- $scale = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
- $scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x");
- }
- elseif ( preg_match( '/^S(.+)$/', $matches[3], $temp_matches ) )
- {
- $scaleText = $temp_matches[1];
- }
- $width = $scale?reScale( $event['Width'], $scale ):$event['Width'];
- $height = $scale?reScale( $event['Height'], $scale ):$event['Height'];
+ $index = 0;
+ foreach ( $videoFiles as $file ) {
+ if ( filesize( $file ) > 0 ) {
+ preg_match( '/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches );
+ if ( preg_match( '/^r(.+)$/', $matches[2], $temp_matches ) ) {
+ $rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
+ $rateText = isset($rates[$rate])?$rates[$rate]:($rate."x");
+ } elseif ( preg_match( '/^F(.+)$/', $matches[2], $temp_matches ) ) {
+ $rateText = $temp_matches[1]."fps";
+ }
+ if ( preg_match( '/^s(.+)$/', $matches[3], $temp_matches ) ) {
+ $scale = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
+ $scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x");
+ } elseif ( preg_match( '/^S(.+)$/', $matches[3], $temp_matches ) ) {
+ $scaleText = $temp_matches[1];
+ }
+ $width = $scale?reScale( $event['Width'], $scale ):$event['Width'];
+ $height = $scale?reScale( $event['Height'], $scale ):$event['Height'];
?>
@@ -232,14 +203,14 @@ else
/ /
diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php
index 8bbb6bda0..c64b66d1e 100644
--- a/web/skins/classic/views/watch.php
+++ b/web/skins/classic/views/watch.php
@@ -59,7 +59,11 @@ xhtmlHeaders( __FILE__, $monitor->Name()." - ".translate('Feed') );