merge all the commits from the messed up iconnor_video branch
This commit is contained in:
parent
f73d8be765
commit
9a795432cf
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (zoneminder)
|
||||
set(zoneminder_VERSION "1.29.0")
|
||||
set(zoneminder_VERSION "1.30.0")
|
||||
# make API version a minor of ZM version
|
||||
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ ZoneMinder H264 Patch
|
|||
[![Build Status](https://travis-ci.org/ZoneMinder/ZoneMinder.png?branch=feature-h264-videostorage)](https://travis-ci.org/ZoneMinder/ZoneMinder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
|
||||
|
||||
##Feature-h264-videostorage Branch Details
|
||||
This branch supports direct recording of h264 cameras into MP4 format uisng the h264 Passthrough option, but only with FFMPEG Monitors currently. It also it provides h264 encoding from jpegs of any other monitor type and local or mpeg cameras. If you encounter any issues, please open an issue on GitHub and attach it to the h264 milestone. But do remember this is bleeding edge so it will have problems.
|
||||
This branch supports direct recording of h264 cameras into MP4 format uisng the h264 Passthrough option. As well it provides h264 encoding for local or mpeg cameras. If you encounter any issues, please open an issue on GitHub and attach it to the h264 milestone. But do remember this is bleeding edge so it will have problems.
|
||||
Thanks to @chriswiggins and @mastertheknife for their work, @SteveGilvarry is now maintaining this branch and welcomes any assistance.
|
||||
|
||||
**The following SQL changes are required, these will be merged to zmupdate once we are ready to merge this branch to master.**
|
||||
|
|
|
@ -193,6 +193,7 @@ CREATE TABLE `Events` (
|
|||
`Length` decimal(10,2) NOT NULL default '0.00',
|
||||
`Frames` int(10) unsigned default NULL,
|
||||
`AlarmFrames` int(10) unsigned default NULL,
|
||||
`DefaultVideo` VARCHAR( 64 ) NOT NULL,
|
||||
`TotScore` int(10) unsigned NOT NULL default '0',
|
||||
`AvgScore` smallint(5) unsigned default '0',
|
||||
`MaxScore` smallint(5) unsigned default '0',
|
||||
|
@ -344,6 +345,10 @@ CREATE TABLE `Monitors` (
|
|||
`Palette` int(10) unsigned NOT NULL default '0',
|
||||
`Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0',
|
||||
`Deinterlacing` int(10) unsigned NOT NULL default '0',
|
||||
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
|
||||
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
|
||||
`EncoderParameters` TEXT NOT NULL,
|
||||
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
|
||||
`RTSPDescribe` tinyint(1) unsigned NOT NULL default '0',
|
||||
`Brightness` mediumint(7) NOT NULL default '-1',
|
||||
`Contrast` mediumint(7) NOT NULL default '-1',
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
zoneminder (1.29.0+h264-wily-SNAPSHOT2016033101) wily; urgency=medium
|
||||
|
||||
*
|
||||
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Thu, 31 Mar 2016 10:29:41 -0400
|
||||
|
||||
zoneminder (1.28.1+1-vivid-SNAPSHOT2015081701) vivid; urgency=medium
|
||||
|
||||
* include api, switch to cmake build
|
||||
|
|
|
@ -21,6 +21,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
|
|||
,libphp-serialization-perl
|
||||
,libsys-mmap-perl [!hurd-any]
|
||||
,libwww-perl
|
||||
,libx264-dev, libmp4v2-dev
|
||||
# Unbundled (dh_linktree):
|
||||
,libjs-jquery
|
||||
,libjs-mootools
|
||||
|
@ -61,6 +62,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
,libmp4v2-2
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php5 | php5-fpm
|
||||
,mysql-server | virtual-mysql-server
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "zm.h"
|
||||
#include "zm_camera.h"
|
||||
|
||||
Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
id( p_id ),
|
||||
type( p_type ),
|
||||
width( p_width),
|
||||
|
@ -31,7 +31,8 @@ Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_co
|
|||
hue( p_hue ),
|
||||
colour( p_colour ),
|
||||
contrast( p_contrast ),
|
||||
capture( p_capture )
|
||||
capture( p_capture ),
|
||||
record_audio( p_record_audio )
|
||||
{
|
||||
pixels = width * height;
|
||||
imagesize = pixels * colours;
|
||||
|
|
|
@ -47,9 +47,10 @@ protected:
|
|||
int colour;
|
||||
int contrast;
|
||||
bool capture;
|
||||
bool record_audio;
|
||||
|
||||
public:
|
||||
Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
virtual ~Camera();
|
||||
|
||||
int getId() const { return( id ); }
|
||||
|
@ -74,7 +75,7 @@ public:
|
|||
|
||||
bool CanCapture() const { return( capture ); }
|
||||
|
||||
bool SupportsNativeVideo() const { return( type == FFMPEG_SRC ); }
|
||||
bool SupportsNativeVideo() const { return( (type == FFMPEG_SRC )||(type == REMOTE_SRC)); }
|
||||
|
||||
virtual int PrimeCapture() { return( 0 ); }
|
||||
virtual int PreCapture()=0;
|
||||
|
|
|
@ -30,8 +30,8 @@ const char* content_type_match = "Content-Type:";
|
|||
size_t content_length_match_len;
|
||||
size_t content_type_match_len;
|
||||
|
||||
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET )
|
||||
{
|
||||
|
||||
|
@ -313,6 +313,7 @@ int cURLCamera::PostCapture()
|
|||
|
||||
int cURLCamera::CaptureAndRecord( Image &image, bool recording, char* event_directory )
|
||||
{
|
||||
Error("Capture and Record not implemented for the cURL camera type");
|
||||
// Nothing to do here
|
||||
return( 0 );
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ protected:
|
|||
pthread_cond_t request_complete_cond;
|
||||
|
||||
public:
|
||||
cURLCamera( int p_id, const std::string &path, const std::string &username, const std::string &password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
cURLCamera( int p_id, const std::string &path, const std::string &username, const std::string &password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~cURLCamera();
|
||||
|
||||
const std::string &Path() const { return( mPath ); }
|
||||
|
|
|
@ -36,8 +36,8 @@ extern "C"{
|
|||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
mPath( p_path ),
|
||||
mMethod( p_method ),
|
||||
mOptions( p_options )
|
||||
|
@ -168,7 +168,7 @@ int FfmpegCamera::Capture( Image &image )
|
|||
(avResult == -110)
|
||||
)
|
||||
{
|
||||
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
|
||||
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf );
|
||||
ReopenFfmpeg();
|
||||
}
|
||||
|
||||
|
@ -176,6 +176,7 @@ int FfmpegCamera::Capture( Image &image )
|
|||
return( -1 );
|
||||
}
|
||||
Debug( 5, "Got packet from stream %d", packet.stream_index );
|
||||
// What about audio stream? Maybe someday we could do sound detection...
|
||||
if ( packet.stream_index == mVideoStreamId )
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
|
@ -187,8 +188,7 @@ int FfmpegCamera::Capture( Image &image )
|
|||
|
||||
Debug( 4, "Decoded video packet at frame %d", frameCount );
|
||||
|
||||
if ( frameComplete )
|
||||
{
|
||||
if ( frameComplete ) {
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||
|
@ -208,16 +208,18 @@ int FfmpegCamera::Capture( Image &image )
|
|||
#endif // HAVE_LIBSWSCALE
|
||||
|
||||
frameCount++;
|
||||
}
|
||||
}
|
||||
} // end if frameComplete
|
||||
} else {
|
||||
Debug( 4, "Different stream_index %d", packet.stream_index );
|
||||
} // end if packet.stream_index == mVideoStreamId
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||
av_packet_unref( &packet);
|
||||
#else
|
||||
av_free_packet( &packet );
|
||||
#endif
|
||||
}
|
||||
} // end while ! frameComplete
|
||||
return (0);
|
||||
}
|
||||
} // FfmpegCamera::Capture
|
||||
|
||||
int FfmpegCamera::PostCapture()
|
||||
{
|
||||
|
@ -312,6 +314,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
|
||||
// Find first video stream present
|
||||
mVideoStreamId = -1;
|
||||
mAudioStreamId = -1;
|
||||
for (unsigned int i=0; i < mFormatContext->nb_streams; i++ )
|
||||
{
|
||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||
|
@ -320,23 +323,32 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
|
||||
#endif
|
||||
{
|
||||
if ( mVideoStreamId == -1 ) {
|
||||
mVideoStreamId = i;
|
||||
break;
|
||||
// if we break, then we won't find the audio stream
|
||||
continue;
|
||||
} else {
|
||||
Debug(2, "Have another video stream." );
|
||||
}
|
||||
}
|
||||
if(mAudioStreamId == -1) //FIXME best way to copy all other streams?
|
||||
{
|
||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
|
||||
#else
|
||||
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO )
|
||||
#endif
|
||||
{
|
||||
if ( mAudioStreamId == -1 ) {
|
||||
mAudioStreamId = i;
|
||||
} else {
|
||||
Debug(2, "Have another audio stream." );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ( mVideoStreamId == -1 )
|
||||
Fatal( "Unable to locate video stream in %s", mPath.c_str() );
|
||||
if ( mAudioStreamId == -1 )
|
||||
Debug( 3, "Unable to locate audio stream in %s", mPath.c_str() );
|
||||
|
||||
Debug ( 1, "Found video stream" );
|
||||
|
||||
|
@ -521,17 +533,15 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
|
||||
/* Request a writeable buffer of the target image */
|
||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
if(directbuffer == NULL) {
|
||||
if( directbuffer == NULL ) {
|
||||
Error("Failed requesting writeable buffer for the captured image.");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int frameComplete = false;
|
||||
while ( !frameComplete )
|
||||
{
|
||||
while ( !frameComplete ) {
|
||||
int avResult = av_read_frame( mFormatContext, &packet );
|
||||
if ( avResult < 0 )
|
||||
{
|
||||
if ( avResult < 0 ) {
|
||||
char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
||||
av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||
if (
|
||||
|
@ -539,8 +549,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
(avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) ||
|
||||
// Check for Connection failure.
|
||||
(avResult == -110)
|
||||
)
|
||||
{
|
||||
) {
|
||||
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
|
||||
ReopenFfmpeg();
|
||||
}
|
||||
|
@ -549,8 +558,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
return( -1 );
|
||||
}
|
||||
Debug( 5, "Got packet from stream %d", packet.stream_index );
|
||||
if ( packet.stream_index == mVideoStreamId )
|
||||
{
|
||||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
if ( avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ) < 0 )
|
||||
#else
|
||||
|
@ -560,8 +568,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
|
||||
Debug( 4, "Decoded video packet at frame %d", frameCount );
|
||||
|
||||
if ( frameComplete )
|
||||
{
|
||||
if ( frameComplete ) {
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||
|
@ -572,21 +579,23 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
//TODO I think we need to store the key frame location for seeking as part of the event
|
||||
|
||||
//Video recording
|
||||
if(recording && !wasRecording){
|
||||
if ( recording && !wasRecording ) {
|
||||
//Instantiate the video storage module
|
||||
|
||||
videoStore = new VideoStore((const char *)event_file, "mp4", mFormatContext->streams[mVideoStreamId],mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId],startTime);
|
||||
wasRecording = true;
|
||||
strcpy(oldDirectory, event_file);
|
||||
|
||||
}else if(!recording && wasRecording && videoStore){
|
||||
} else if ( ( ! recording ) && wasRecording && videoStore ) {
|
||||
Info("Deleting videoStore instance");
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
}
|
||||
|
||||
//The directory we are recording to is no longer tied to the current event. Need to re-init the videostore with the correct directory and start recording again
|
||||
if(recording && wasRecording && (strcmp(oldDirectory, event_file)!=0) && (packet.flags & AV_PKT_FLAG_KEY) ){ //don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...if we store our key frame location with the event will that be enough?
|
||||
if ( recording && wasRecording && (strcmp(oldDirectory, event_file) != 0 ) && (packet.flags & AV_PKT_FLAG_KEY) ) {
|
||||
// don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...
|
||||
// if we store our key frame location with the event will that be enough?
|
||||
Info("Re-starting video storage module");
|
||||
if(videoStore){
|
||||
delete videoStore;
|
||||
|
@ -597,7 +606,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
strcpy(oldDirectory, event_file);
|
||||
}
|
||||
|
||||
if(videoStore && recording){
|
||||
if ( videoStore && recording ) {
|
||||
//Write the packet to our video store
|
||||
int ret = videoStore->writeVideoFramePacket(&packet, mFormatContext->streams[mVideoStreamId]);//, &lastKeyframePkt);
|
||||
if(ret<0){//Less than zero and we skipped a frame
|
||||
|
@ -607,9 +616,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
}
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(mConvertContext == NULL) {
|
||||
if ( mConvertContext == NULL ) {
|
||||
mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
|
||||
if(mConvertContext == NULL)
|
||||
if ( mConvertContext == NULL )
|
||||
Fatal( "Unable to create conversion context for %s", mPath.c_str() );
|
||||
}
|
||||
|
||||
|
@ -620,19 +629,24 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
|||
#endif // HAVE_LIBSWSCALE
|
||||
|
||||
frameCount++;
|
||||
}
|
||||
}else if(packet.stream_index == mAudioStreamId){//FIXME best way to copy all other streams
|
||||
if(videoStore && recording){
|
||||
} // end if frameComplete
|
||||
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
||||
if ( videoStore && recording ) {
|
||||
if ( record_audio ) {
|
||||
Debug(4, "Recording audio packet" );
|
||||
//Write the packet to our video store
|
||||
int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame
|
||||
if(ret<0){//Less than zero and we skipped a frame
|
||||
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
||||
av_free_packet( &packet );
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
Debug(4, "Not recording audio packet" );
|
||||
}
|
||||
}
|
||||
}
|
||||
av_free_packet( &packet );
|
||||
}
|
||||
} // end while ! frameComplete
|
||||
return (frameCount);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ protected:
|
|||
int64_t startTime;
|
||||
|
||||
public:
|
||||
FfmpegCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
FfmpegCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~FfmpegCamera();
|
||||
|
||||
const std::string &Path() const { return( mPath ); }
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "zm.h"
|
||||
#include "zm_file_camera.h"
|
||||
|
||||
FileCamera::FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : Camera( p_id, FILE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture )
|
||||
FileCamera::FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : Camera( p_id, FILE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio )
|
||||
{
|
||||
strncpy( path, p_path, sizeof(path) );
|
||||
if ( capture )
|
||||
|
|
|
@ -36,7 +36,7 @@ protected:
|
|||
char path[PATH_MAX];
|
||||
|
||||
public:
|
||||
FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~FileCamera();
|
||||
|
||||
const char *Path() const { return( path ); }
|
||||
|
|
|
@ -61,8 +61,8 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
|||
}
|
||||
}
|
||||
|
||||
LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
mPath( p_path ),
|
||||
mMethod( p_method ),
|
||||
mOptions( p_options )
|
||||
|
|
|
@ -57,7 +57,7 @@ protected:
|
|||
libvlc_media_player_t *mLibvlcMediaPlayer;
|
||||
|
||||
public:
|
||||
LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~LibvlcCamera();
|
||||
|
||||
const std::string &Path() const { return( mPath ); }
|
||||
|
|
|
@ -286,8 +286,26 @@ AVFrame **LocalCamera::capturePictures = 0;
|
|||
|
||||
LocalCamera *LocalCamera::last_camera = NULL;
|
||||
|
||||
LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, bool p_v4l_multi_buffer, unsigned int p_v4l_captures_per_frame, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras) :
|
||||
Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
LocalCamera::LocalCamera(
|
||||
int p_id,
|
||||
const std::string &p_device,
|
||||
int p_channel,
|
||||
int p_standard,
|
||||
bool p_v4l_multi_buffer,
|
||||
unsigned int p_v4l_captures_per_frame,
|
||||
const std::string &p_method,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_palette,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio,
|
||||
unsigned int p_extras) :
|
||||
Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
device( p_device ),
|
||||
channel( p_channel ),
|
||||
standard( p_standard ),
|
||||
|
|
|
@ -116,7 +116,25 @@ protected:
|
|||
static LocalCamera *last_camera;
|
||||
|
||||
public:
|
||||
LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, bool v4lmultibuffer, unsigned int v4lcapturesperframe, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras = 0);
|
||||
LocalCamera(
|
||||
int p_id,
|
||||
const std::string &device,
|
||||
int p_channel,
|
||||
int p_format,
|
||||
bool v4lmultibuffer,
|
||||
unsigned int v4lcapturesperframe,
|
||||
const std::string &p_method,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_palette,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio,
|
||||
unsigned int p_extras = 0);
|
||||
~LocalCamera();
|
||||
|
||||
void Initialise();
|
||||
|
|
|
@ -75,8 +75,7 @@ std::vector<std::string> split(const std::string &s, char delim) {
|
|||
|
||||
|
||||
|
||||
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id )
|
||||
{
|
||||
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
|
||||
strncpy( name, p_name, sizeof(name) );
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
|
@ -95,15 +94,12 @@ Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id )
|
|||
connected = false;
|
||||
}
|
||||
|
||||
Monitor::MonitorLink::~MonitorLink()
|
||||
{
|
||||
Monitor::MonitorLink::~MonitorLink() {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
bool Monitor::MonitorLink::connect()
|
||||
{
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 )
|
||||
{
|
||||
bool Monitor::MonitorLink::connect() {
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) {
|
||||
last_connect_time = time( 0 );
|
||||
|
||||
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
||||
|
@ -111,8 +107,7 @@ bool Monitor::MonitorLink::connect()
|
|||
Debug( 1, "link.mem.size=%d", mem_size );
|
||||
#if ZM_MEM_MAPPED
|
||||
map_fd = open( mem_file, O_RDWR, (mode_t)0600 );
|
||||
if ( map_fd < 0 )
|
||||
{
|
||||
if ( map_fd < 0 ) {
|
||||
Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) );
|
||||
disconnect();
|
||||
return( false );
|
||||
|
@ -125,44 +120,37 @@ bool Monitor::MonitorLink::connect()
|
|||
}
|
||||
|
||||
struct stat map_stat;
|
||||
if ( fstat( map_fd, &map_stat ) < 0 )
|
||||
{
|
||||
if ( fstat( map_fd, &map_stat ) < 0 ) {
|
||||
Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) );
|
||||
disconnect();
|
||||
return( false );
|
||||
}
|
||||
|
||||
if ( map_stat.st_size == 0 )
|
||||
{
|
||||
if ( map_stat.st_size == 0 ) {
|
||||
Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) );
|
||||
disconnect();
|
||||
return( false );
|
||||
}
|
||||
else if ( map_stat.st_size < mem_size )
|
||||
{
|
||||
} else if ( map_stat.st_size < mem_size ) {
|
||||
Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size );
|
||||
disconnect();
|
||||
return( false );
|
||||
}
|
||||
|
||||
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 );
|
||||
if ( mem_ptr == MAP_FAILED )
|
||||
{
|
||||
if ( mem_ptr == MAP_FAILED ) {
|
||||
Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) );
|
||||
disconnect();
|
||||
return( false );
|
||||
}
|
||||
#else // ZM_MEM_MAPPED
|
||||
shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 );
|
||||
if ( shm_id < 0 )
|
||||
{
|
||||
if ( shm_id < 0 ) {
|
||||
Debug( 3, "Can't shmget link memory: %s", strerror(errno) );
|
||||
connected = false;
|
||||
return( false );
|
||||
}
|
||||
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
|
||||
if ( mem_ptr < 0 )
|
||||
{
|
||||
if ( mem_ptr < 0 ) {
|
||||
Debug( 3, "Can't shmat link memory: %s", strerror(errno) );
|
||||
connected = false;
|
||||
return( false );
|
||||
|
@ -172,8 +160,7 @@ bool Monitor::MonitorLink::connect()
|
|||
shared_data = (SharedData *)mem_ptr;
|
||||
trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData));
|
||||
|
||||
if ( !shared_data->valid )
|
||||
{
|
||||
if ( !shared_data->valid ) {
|
||||
Debug( 3, "Linked memory not initialised by capture daemon" );
|
||||
disconnect();
|
||||
return( false );
|
||||
|
@ -188,15 +175,12 @@ bool Monitor::MonitorLink::connect()
|
|||
return( false );
|
||||
}
|
||||
|
||||
bool Monitor::MonitorLink::disconnect()
|
||||
{
|
||||
if ( connected )
|
||||
{
|
||||
bool Monitor::MonitorLink::disconnect() {
|
||||
if ( connected ) {
|
||||
connected = false;
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
if ( mem_ptr > 0 )
|
||||
{
|
||||
if ( mem_ptr > 0 ) {
|
||||
msync( mem_ptr, mem_size, MS_ASYNC );
|
||||
munmap( mem_ptr, mem_size );
|
||||
}
|
||||
|
@ -206,25 +190,21 @@ bool Monitor::MonitorLink::disconnect()
|
|||
map_fd = -1;
|
||||
#else // ZM_MEM_MAPPED
|
||||
struct shmid_ds shm_data;
|
||||
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 )
|
||||
{
|
||||
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) {
|
||||
Debug( 3, "Can't shmctl: %s", strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
|
||||
shm_id = 0;
|
||||
|
||||
if ( shm_data.shm_nattch <= 1 )
|
||||
{
|
||||
if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 )
|
||||
{
|
||||
if ( shm_data.shm_nattch <= 1 ) {
|
||||
if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) {
|
||||
Debug( 3, "Can't shmctl: %s", strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
||||
if ( shmdt( mem_ptr ) < 0 )
|
||||
{
|
||||
if ( shmdt( mem_ptr ) < 0 ) {
|
||||
Debug( 3, "Can't shmdt: %s", strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
|
@ -236,19 +216,15 @@ bool Monitor::MonitorLink::disconnect()
|
|||
return( true );
|
||||
}
|
||||
|
||||
bool Monitor::MonitorLink::isAlarmed()
|
||||
{
|
||||
if ( !connected )
|
||||
{
|
||||
bool Monitor::MonitorLink::isAlarmed() {
|
||||
if ( !connected ) {
|
||||
return( false );
|
||||
}
|
||||
return( shared_data->state == ALARM );
|
||||
}
|
||||
|
||||
bool Monitor::MonitorLink::inAlarm()
|
||||
{
|
||||
if ( !connected )
|
||||
{
|
||||
bool Monitor::MonitorLink::inAlarm() {
|
||||
if ( !connected ) {
|
||||
return( false );
|
||||
}
|
||||
return( shared_data->state == ALARM || shared_data->state == ALERT );
|
||||
|
@ -256,12 +232,9 @@ bool Monitor::MonitorLink::inAlarm()
|
|||
|
||||
bool Monitor::MonitorLink::hasAlarmed()
|
||||
{
|
||||
if ( shared_data->state == ALARM )
|
||||
{
|
||||
if ( shared_data->state == ALARM ) {
|
||||
return( true );
|
||||
}
|
||||
else if( shared_data->last_event != (unsigned int)last_event )
|
||||
{
|
||||
} else if ( shared_data->last_event != (unsigned int)last_event ) {
|
||||
last_event = shared_data->last_event;
|
||||
}
|
||||
return( false );
|
||||
|
@ -280,6 +253,7 @@ Monitor::Monitor(
|
|||
int p_savejpegs,
|
||||
int p_videowriter,
|
||||
std::string p_encoderparams,
|
||||
bool p_record_audio,
|
||||
const char *p_event_prefix,
|
||||
const char *p_label_format,
|
||||
const Coord &p_label_coord,
|
||||
|
@ -317,6 +291,7 @@ Monitor::Monitor(
|
|||
savejpegspref( p_savejpegs ),
|
||||
videowriterpref( p_videowriter ),
|
||||
encoderparams( p_encoderparams ),
|
||||
record_audio( p_record_audio ),
|
||||
label_coord( p_label_coord ),
|
||||
label_size( p_label_size ),
|
||||
image_buffer_count( p_image_buffer_count ),
|
||||
|
@ -450,16 +425,15 @@ Monitor::Monitor(
|
|||
shared_data->alarm_y = -1;
|
||||
}
|
||||
|
||||
if ( ( ! mem_ptr ) || ! shared_data->valid )
|
||||
{
|
||||
if ( purpose != QUERY )
|
||||
{
|
||||
if ( ( ! mem_ptr ) || ! shared_data->valid ) {
|
||||
if ( purpose != QUERY ) {
|
||||
Error( "Shared data not initialised by capture daemon for monitor %s", name );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after..
|
||||
// In my storage areas branch, I took this out.. and didn't notice any problems.
|
||||
if ( !n_zones ) {
|
||||
Debug( 1, "Monitor %s has no zones, adding one.", name );
|
||||
n_zones = 1;
|
||||
|
@ -475,8 +449,7 @@ Monitor::Monitor(
|
|||
Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d, LBS = %d", name, label_format, label_coord.X(), label_coord.Y(), label_size );
|
||||
Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, ARBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion );
|
||||
|
||||
if ( purpose == ANALYSIS )
|
||||
{
|
||||
if ( purpose == ANALYSIS ) {
|
||||
static char path[PATH_MAX];
|
||||
|
||||
strncpy( path, config.dir_events, sizeof(path) );
|
||||
|
@ -484,8 +457,7 @@ Monitor::Monitor(
|
|||
struct stat statbuf;
|
||||
errno = 0;
|
||||
stat( path, &statbuf );
|
||||
if ( errno == ENOENT || errno == ENOTDIR )
|
||||
{
|
||||
if ( errno == ENOENT || errno == ENOTDIR ) {
|
||||
if ( mkdir( path, 0755 ) )
|
||||
{
|
||||
Error( "Can't make %s: %s", path, strerror(errno));
|
||||
|
@ -496,10 +468,8 @@ Monitor::Monitor(
|
|||
|
||||
errno = 0;
|
||||
stat( path, &statbuf );
|
||||
if ( errno == ENOENT || errno == ENOTDIR )
|
||||
{
|
||||
if ( mkdir( path, 0755 ) )
|
||||
{
|
||||
if ( errno == ENOENT || errno == ENOTDIR ) {
|
||||
if ( mkdir( path, 0755 ) ) {
|
||||
Error( "Can't make %s: %s", path, strerror(errno));
|
||||
}
|
||||
char temp_path[PATH_MAX];
|
||||
|
@ -513,8 +483,7 @@ Monitor::Monitor(
|
|||
}
|
||||
|
||||
while( shared_data->last_write_index == (unsigned int)image_buffer_count
|
||||
&& shared_data->last_write_time == 0)
|
||||
{
|
||||
&& shared_data->last_write_time == 0) {
|
||||
Warning( "Waiting for capture daemon" );
|
||||
sleep( 1 );
|
||||
}
|
||||
|
@ -573,8 +542,7 @@ bool Monitor::connect() {
|
|||
exit( -1 );
|
||||
}
|
||||
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
|
||||
if ( mem_ptr < 0 )
|
||||
{
|
||||
if ( mem_ptr < 0 ) {
|
||||
Error( "Can't shmat: %s", strerror(errno));
|
||||
exit( -1 );
|
||||
}
|
||||
|
@ -591,29 +559,25 @@ bool Monitor::connect() {
|
|||
shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16)));
|
||||
}
|
||||
image_buffer = new Snapshot[image_buffer_count];
|
||||
for ( int i = 0; i < image_buffer_count; i++ )
|
||||
{
|
||||
for ( int i = 0; i < image_buffer_count; i++ ) {
|
||||
image_buffer[i].timestamp = &(shared_timestamps[i]);
|
||||
image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) );
|
||||
image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */
|
||||
}
|
||||
if ( (deinterlacing & 0xff) == 4)
|
||||
{
|
||||
if ( (deinterlacing & 0xff) == 4) {
|
||||
/* Four field motion adaptive deinterlacing in use */
|
||||
/* Allocate a buffer for the next image */
|
||||
next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
next_buffer.timestamp = new struct timeval;
|
||||
}
|
||||
|
||||
if ( ( purpose == ANALYSIS ) && analysis_fps )
|
||||
{
|
||||
if ( ( purpose == ANALYSIS ) && analysis_fps ) {
|
||||
// Size of pre event buffer must be greater than pre_event_count
|
||||
// if alarm_frame_count > 1, because in this case the buffer contains
|
||||
// alarmed images that must be discarded when event is created
|
||||
pre_event_buffer_count = pre_event_count + alarm_frame_count - 1;
|
||||
pre_event_buffer = new Snapshot[pre_event_buffer_count];
|
||||
for ( int i = 0; i < pre_event_buffer_count; i++ )
|
||||
{
|
||||
for ( int i = 0; i < pre_event_buffer_count; i++ ) {
|
||||
pre_event_buffer[i].timestamp = new struct timeval;
|
||||
pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
}
|
||||
|
@ -1892,6 +1856,7 @@ void Monitor::Reload()
|
|||
closeEvent();
|
||||
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
// This seems to have fallen out of date.
|
||||
snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id );
|
||||
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
|
@ -2084,7 +2049,7 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors )
|
|||
#if ZM_HAS_V4L
|
||||
int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'";
|
||||
if ( device[0] ) {
|
||||
sql += " AND Device='";
|
||||
sql += device;
|
||||
|
@ -2148,6 +2113,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
int savejpegs = atoi(dbrow[col]); col++;
|
||||
int videowriter = atoi(dbrow[col]); col++;
|
||||
std::string encoderparams = dbrow[col]; col++;
|
||||
bool record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
int contrast = atoi(dbrow[col]); col++;
|
||||
|
@ -2209,6 +2175,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE,
|
||||
record_audio,
|
||||
extras
|
||||
);
|
||||
|
||||
|
@ -2225,6 +2192,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
savejpegs,
|
||||
videowriter,
|
||||
encoderparams,
|
||||
record_audio,
|
||||
event_prefix,
|
||||
label_format,
|
||||
Coord( label_x, label_y ),
|
||||
|
@ -2272,7 +2240,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
|
||||
int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'";
|
||||
if ( staticConfig.SERVER_ID ) {
|
||||
sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID );
|
||||
}
|
||||
|
@ -2318,6 +2286,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
int savejpegs = atoi(dbrow[col]); col++;
|
||||
int videowriter = atoi(dbrow[col]); col++;
|
||||
std::string encoderparams = dbrow[col]; col++;
|
||||
bool record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
int contrast = atoi(dbrow[col]); col++;
|
||||
|
@ -2354,8 +2323,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height);
|
||||
|
||||
Camera *camera = 0;
|
||||
if ( protocol == "http" )
|
||||
{
|
||||
if ( protocol == "http" ) {
|
||||
camera = new RemoteCameraHttp(
|
||||
id,
|
||||
method,
|
||||
|
@ -2369,12 +2337,12 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
}
|
||||
#if HAVE_LIBAVFORMAT
|
||||
else if ( protocol == "rtsp" )
|
||||
{
|
||||
else if ( protocol == "rtsp" ) {
|
||||
camera = new RemoteCameraRtsp(
|
||||
id,
|
||||
method,
|
||||
|
@ -2389,12 +2357,12 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
}
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
else
|
||||
{
|
||||
else {
|
||||
Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() );
|
||||
}
|
||||
|
||||
|
@ -2411,6 +2379,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
savejpegs,
|
||||
videowriter,
|
||||
encoderparams,
|
||||
record_audio,
|
||||
event_prefix.c_str(),
|
||||
label_format.c_str(),
|
||||
Coord( label_x, label_y ),
|
||||
|
@ -2437,7 +2406,6 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
purpose,
|
||||
0,
|
||||
0
|
||||
|
||||
);
|
||||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
|
@ -2456,9 +2424,8 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
return( n_monitors );
|
||||
}
|
||||
|
||||
int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'";
|
||||
int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) {
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'";
|
||||
if ( file[0] ) {
|
||||
sql += " AND Path='";
|
||||
sql += file;
|
||||
|
@ -2501,6 +2468,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
int savejpegs = atoi(dbrow[col]); col++;
|
||||
int videowriter = atoi(dbrow[col]); col++;
|
||||
std::string encoderparams = dbrow[col]; col++;
|
||||
bool record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
int contrast = atoi(dbrow[col]); col++;
|
||||
|
@ -2546,7 +2514,8 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
|
||||
monitors[i] = new Monitor(
|
||||
|
@ -2562,6 +2531,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
savejpegs,
|
||||
videowriter,
|
||||
encoderparams,
|
||||
record_audio,
|
||||
event_prefix,
|
||||
label_format,
|
||||
Coord( label_x, label_y ),
|
||||
|
@ -2609,7 +2579,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
#if HAVE_LIBAVFORMAT
|
||||
int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose )
|
||||
{
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'";
|
||||
std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'";
|
||||
if ( file[0] ) {
|
||||
sql += " AND Path = '";
|
||||
sql += file;
|
||||
|
@ -2629,8 +2599,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
Debug( 1, "Got %d monitors", n_monitors );
|
||||
delete[] monitors;
|
||||
monitors = new Monitor *[n_monitors];
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
|
||||
{
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
|
||||
int col = 0;
|
||||
|
||||
int id = atoi(dbrow[col]); col++;
|
||||
|
@ -2654,6 +2623,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
int savejpegs = atoi(dbrow[col]); col++;
|
||||
int videowriter = atoi(dbrow[col]); col++;
|
||||
std::string encoderparams = dbrow[col]; col++;
|
||||
bool record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
int contrast = atoi(dbrow[col]); col++;
|
||||
|
@ -2701,7 +2671,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
|
||||
monitors[i] = new Monitor(
|
||||
|
@ -2717,6 +2688,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
savejpegs,
|
||||
videowriter,
|
||||
encoderparams,
|
||||
record_audio,
|
||||
event_prefix,
|
||||
label_format,
|
||||
Coord( label_x, label_y ),
|
||||
|
@ -2762,9 +2734,8 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
}
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
|
||||
Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose )
|
||||
{
|
||||
std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
|
||||
Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
|
||||
std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id );
|
||||
|
||||
MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() );
|
||||
if ( ! dbrow ) {
|
||||
|
@ -2802,7 +2773,7 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose )
|
|||
} else {
|
||||
v4l_captures_per_frame = config.captures_per_frame;
|
||||
}
|
||||
Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
||||
Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
||||
col++;
|
||||
|
||||
std::string protocol = dbrow[col]; col++;
|
||||
|
@ -2824,6 +2795,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
int savejpegs = atoi(dbrow[col]); col++;
|
||||
int videowriter = atoi(dbrow[col]); col++;
|
||||
std::string encoderparams = dbrow[col]; col++;
|
||||
bool record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
int contrast = atoi(dbrow[col]); col++;
|
||||
|
@ -2869,8 +2841,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
int extras = (deinterlacing>>24)&0xff;
|
||||
|
||||
Camera *camera = 0;
|
||||
if ( type == "Local" )
|
||||
{
|
||||
if ( type == "Local" ) {
|
||||
#if ZM_HAS_V4L
|
||||
camera = new LocalCamera(
|
||||
id,
|
||||
|
@ -2889,16 +2860,14 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE,
|
||||
record_audio,
|
||||
extras
|
||||
);
|
||||
#else // ZM_HAS_V4L
|
||||
Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id );
|
||||
#endif // ZM_HAS_V4L
|
||||
}
|
||||
else if ( type == "Remote" )
|
||||
{
|
||||
if ( protocol == "http" )
|
||||
{
|
||||
} else if ( type == "Remote" ) {
|
||||
if ( protocol == "http" ) {
|
||||
camera = new RemoteCameraHttp(
|
||||
id,
|
||||
method.c_str(),
|
||||
|
@ -2912,11 +2881,10 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
}
|
||||
else if ( protocol == "rtsp" )
|
||||
{
|
||||
} else if ( protocol == "rtsp" ) {
|
||||
#if HAVE_LIBAVFORMAT
|
||||
camera = new RemoteCameraRtsp(
|
||||
id,
|
||||
|
@ -2932,19 +2900,16 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
#else // HAVE_LIBAVFORMAT
|
||||
Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id );
|
||||
}
|
||||
}
|
||||
else if ( type == "File" )
|
||||
{
|
||||
} else if ( type == "File" ) {
|
||||
camera = new FileCamera(
|
||||
id,
|
||||
path.c_str(),
|
||||
|
@ -2955,11 +2920,10 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
}
|
||||
else if ( type == "Ffmpeg" )
|
||||
{
|
||||
} else if ( type == "Ffmpeg" ) {
|
||||
#if HAVE_LIBAVFORMAT
|
||||
camera = new FfmpegCamera(
|
||||
id,
|
||||
|
@ -2973,14 +2937,13 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
#else // HAVE_LIBAVFORMAT
|
||||
Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id );
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
}
|
||||
else if (type == "Libvlc")
|
||||
{
|
||||
} else if (type == "Libvlc") {
|
||||
#if HAVE_LIBVLC
|
||||
camera = new LibvlcCamera(
|
||||
id,
|
||||
|
@ -2994,14 +2957,13 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
#else // HAVE_LIBVLC
|
||||
Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id );
|
||||
#endif // HAVE_LIBVLC
|
||||
}
|
||||
else if ( type == "cURL" )
|
||||
{
|
||||
} else if ( type == "cURL" ) {
|
||||
#if HAVE_LIBCURL
|
||||
camera = new cURLCamera(
|
||||
id,
|
||||
|
@ -3015,14 +2977,13 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
#else // HAVE_LIBCURL
|
||||
Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id );
|
||||
#endif // HAVE_LIBCURL
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id );
|
||||
}
|
||||
monitor = new Monitor(
|
||||
|
@ -3038,6 +2999,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
savejpegs,
|
||||
videowriter,
|
||||
encoderparams,
|
||||
record_audio,
|
||||
event_prefix.c_str(),
|
||||
label_format.c_str(),
|
||||
Coord( label_x, label_y ),
|
||||
|
@ -3068,8 +3030,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
);
|
||||
|
||||
int n_zones = 0;
|
||||
if ( load_zones )
|
||||
{
|
||||
if ( load_zones ) {
|
||||
Zone **zones = 0;
|
||||
n_zones = Zone::Load( monitor, zones );
|
||||
monitor->AddZones( n_zones, zones );
|
||||
|
@ -3123,8 +3084,7 @@ int Monitor::Capture()
|
|||
captureResult = 0;
|
||||
}
|
||||
|
||||
if ( captureResult != 0 )
|
||||
{
|
||||
if ( captureResult != 0 ) {
|
||||
// Unable to capture image for temporary reason
|
||||
// Fake a signal loss image
|
||||
Rgb signalcolor;
|
||||
|
@ -3135,8 +3095,7 @@ int Monitor::Capture()
|
|||
captureResult = 1;
|
||||
}
|
||||
|
||||
if ( captureResult == 1 )
|
||||
{
|
||||
if ( captureResult == 1 ) {
|
||||
|
||||
/* Deinterlacing */
|
||||
if ( (deinterlacing & 0xff) == 1 ) {
|
||||
|
@ -3152,48 +3111,41 @@ int Monitor::Capture()
|
|||
}
|
||||
|
||||
|
||||
if ( orientation != ROTATE_0 )
|
||||
{
|
||||
switch ( orientation )
|
||||
{
|
||||
case ROTATE_0 :
|
||||
{
|
||||
if ( orientation != ROTATE_0 ) {
|
||||
switch ( orientation ) {
|
||||
case ROTATE_0 : {
|
||||
// No action required
|
||||
break;
|
||||
}
|
||||
case ROTATE_90 :
|
||||
case ROTATE_180 :
|
||||
case ROTATE_270 :
|
||||
{
|
||||
case ROTATE_270 : {
|
||||
capture_image->Rotate( (orientation-1)*90 );
|
||||
break;
|
||||
}
|
||||
case FLIP_HORI :
|
||||
case FLIP_VERT :
|
||||
{
|
||||
case FLIP_VERT : {
|
||||
capture_image->Flip( orientation==FLIP_HORI );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if captureResults == 1
|
||||
|
||||
}
|
||||
// if true? let's get rid of this.
|
||||
if ( true ) {
|
||||
|
||||
if ( capture_image->Size() > camera->ImageSize() )
|
||||
{
|
||||
if ( capture_image->Size() > camera->ImageSize() ) {
|
||||
Error( "Captured image %d does not match expected size %d check width, height and colour depth",capture_image->Size(),camera->ImageSize() );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( ((unsigned int)index == shared_data->last_read_index) && (function > MONITOR) )
|
||||
{
|
||||
if ( ((unsigned int)index == shared_data->last_read_index) && (function > MONITOR) ) {
|
||||
Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count );
|
||||
time_t now = time(0);
|
||||
double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec);
|
||||
time_t last_read_delta = now - shared_data->last_read_time;
|
||||
if ( last_read_delta > (image_buffer_count/approxFps) )
|
||||
{
|
||||
if ( last_read_delta > (image_buffer_count/approxFps) ) {
|
||||
Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta )
|
||||
shared_data->last_read_index = image_buffer_count;
|
||||
}
|
||||
|
@ -3203,8 +3155,7 @@ int Monitor::Capture()
|
|||
capture_image->MaskPrivacy( privacy_bitmask );
|
||||
|
||||
gettimeofday( image_buffer[index].timestamp, NULL );
|
||||
if ( config.timestamp_on_capture )
|
||||
{
|
||||
if ( config.timestamp_on_capture ) {
|
||||
TimestampImage( capture_image, image_buffer[index].timestamp );
|
||||
}
|
||||
shared_data->signal = CheckSignal(capture_image);
|
||||
|
@ -3213,8 +3164,7 @@ int Monitor::Capture()
|
|||
|
||||
image_count++;
|
||||
|
||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) )
|
||||
{
|
||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
||||
time_t now = image_buffer[index].timestamp->tv_sec;
|
||||
fps = double(fps_report_interval)/(now-last_fps_time);
|
||||
//Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
|
||||
|
@ -3223,16 +3173,14 @@ int Monitor::Capture()
|
|||
last_fps_time = now;
|
||||
}
|
||||
|
||||
if ( shared_data->action & GET_SETTINGS )
|
||||
{
|
||||
if ( shared_data->action & GET_SETTINGS ) {
|
||||
shared_data->brightness = camera->Brightness();
|
||||
shared_data->hue = camera->Hue();
|
||||
shared_data->colour = camera->Colour();
|
||||
shared_data->contrast = camera->Contrast();
|
||||
shared_data->action &= ~GET_SETTINGS;
|
||||
}
|
||||
if ( shared_data->action & SET_SETTINGS )
|
||||
{
|
||||
if ( shared_data->action & SET_SETTINGS ) {
|
||||
camera->Brightness( shared_data->brightness );
|
||||
camera->Hue( shared_data->hue );
|
||||
camera->Colour( shared_data->colour );
|
||||
|
@ -3292,10 +3240,8 @@ void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) c
|
|||
bool Monitor::closeEvent()
|
||||
{
|
||||
video_store_data->recording = false;
|
||||
if ( event )
|
||||
{
|
||||
if ( function == RECORD || function == MOCORD )
|
||||
{
|
||||
if ( event ) {
|
||||
if ( function == RECORD || function == MOCORD ) {
|
||||
gettimeofday( &(event->EndTime()), NULL );
|
||||
}
|
||||
delete event;
|
||||
|
@ -3747,7 +3693,7 @@ bool Monitor::DumpSettings( char *output, bool verbose )
|
|||
zones[i]->DumpSettings( output+strlen(output), verbose );
|
||||
}
|
||||
return( true );
|
||||
}
|
||||
} // bool Monitor::DumpSettings( char *output, bool verbose )
|
||||
|
||||
bool MonitorStream::checkSwapPath( const char *path, bool create_path )
|
||||
{
|
||||
|
|
118
src/zm_monitor.h
118
src/zm_monitor.h
|
@ -134,8 +134,7 @@ protected:
|
|||
typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState;
|
||||
|
||||
/* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
uint32_t trigger_state;
|
||||
uint32_t trigger_score;
|
||||
|
@ -146,8 +145,7 @@ protected:
|
|||
} TriggerData;
|
||||
|
||||
/* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */
|
||||
struct Snapshot
|
||||
{
|
||||
struct Snapshot {
|
||||
struct timeval *timestamp;
|
||||
Image *image;
|
||||
void* padding;
|
||||
|
@ -156,8 +154,7 @@ protected:
|
|||
//TODO: Technically we can't exclude this struct when people don't have avformat as the Memory.pm module doesn't know about avformat
|
||||
#if 1
|
||||
//sizeOf(VideoStoreData) expected to be 4104 bytes on 32bit and 64bit
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
char event_file[4096];
|
||||
uint32_t recording; //bool arch dependent so use uint32 instead
|
||||
|
@ -167,8 +164,7 @@ protected:
|
|||
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
|
||||
class MonitorLink
|
||||
{
|
||||
class MonitorLink {
|
||||
protected:
|
||||
unsigned int id;
|
||||
char name[64];
|
||||
|
@ -196,21 +192,17 @@ protected:
|
|||
MonitorLink( int p_id, const char *p_name );
|
||||
~MonitorLink();
|
||||
|
||||
inline int Id() const
|
||||
{
|
||||
inline int Id() const {
|
||||
return( id );
|
||||
}
|
||||
inline const char *Name() const
|
||||
{
|
||||
inline const char *Name() const {
|
||||
return( name );
|
||||
}
|
||||
|
||||
inline bool isConnected() const
|
||||
{
|
||||
inline bool isConnected() const {
|
||||
return( connected );
|
||||
}
|
||||
inline time_t getLastConnectTime() const
|
||||
{
|
||||
inline time_t getLastConnectTime() const {
|
||||
return( last_connect_time );
|
||||
}
|
||||
|
||||
|
@ -240,6 +232,7 @@ protected:
|
|||
int videowriterpref;
|
||||
std::string encoderparams;
|
||||
std::vector<EncoderParameter_t> encoderparamsvec;
|
||||
bool record_audio; // Whether to store the audio that we receive
|
||||
|
||||
int brightness; // The statically saved brightness of the camera
|
||||
int contrast; // The statically saved contrast of the camera
|
||||
|
@ -329,54 +322,85 @@ protected:
|
|||
public:
|
||||
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
|
||||
//bool OurCheckAlarms( Zone *zone, const Image *pImage );
|
||||
Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, int p_savejpegs, int p_videowriter, std::string p_encoderparams, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 );
|
||||
Monitor(
|
||||
int p_id,
|
||||
const char *p_name,
|
||||
unsigned int p_server_id,
|
||||
int p_function,
|
||||
bool p_enabled,
|
||||
const char *p_linked_monitors,
|
||||
Camera *p_camera,
|
||||
int p_orientation,
|
||||
unsigned int p_deinterlacing,
|
||||
int p_savejpegs,
|
||||
int p_videowriter,
|
||||
std::string p_encoderparams,
|
||||
bool p_record_audio,
|
||||
const char *p_event_prefix,
|
||||
const char *p_label_format,
|
||||
const Coord &p_label_coord,
|
||||
int label_size,
|
||||
int p_image_buffer_count,
|
||||
int p_warmup_count,
|
||||
int p_pre_event_count,
|
||||
int p_post_event_count,
|
||||
int p_stream_replay_buffer,
|
||||
int p_alarm_frame_count,
|
||||
int p_section_length,
|
||||
int p_frame_skip,
|
||||
int p_motion_frame_skip,
|
||||
double p_analysis_fps,
|
||||
unsigned int p_analysis_update_delay,
|
||||
int p_capture_delay,
|
||||
int p_alarm_capture_delay,
|
||||
int p_fps_report_interval,
|
||||
int p_ref_blend_perc,
|
||||
int p_alarm_ref_blend_perc,
|
||||
bool p_track_motion,
|
||||
Rgb p_signal_check_colour,
|
||||
bool p_embed_exif,
|
||||
Purpose p_purpose,
|
||||
int p_n_zones=0,
|
||||
Zone *p_zones[]=0
|
||||
);
|
||||
~Monitor();
|
||||
|
||||
void AddZones( int p_n_zones, Zone *p_zones[] );
|
||||
void AddPrivacyBitmask( Zone *p_zones[] );
|
||||
|
||||
bool connect();
|
||||
inline int ShmValid() const
|
||||
{
|
||||
inline int ShmValid() const {
|
||||
return( shared_data->valid );
|
||||
}
|
||||
|
||||
inline int Id() const
|
||||
{
|
||||
inline int Id() const {
|
||||
return( id );
|
||||
}
|
||||
inline const char *Name() const
|
||||
{
|
||||
inline const char *Name() const {
|
||||
return( name );
|
||||
}
|
||||
inline Function GetFunction() const
|
||||
{
|
||||
inline Function GetFunction() const {
|
||||
return( function );
|
||||
}
|
||||
inline bool Enabled()
|
||||
{
|
||||
inline bool Enabled() {
|
||||
if ( function <= MONITOR )
|
||||
return( false );
|
||||
return( enabled );
|
||||
}
|
||||
inline const char *EventPrefix() const
|
||||
{
|
||||
inline const char *EventPrefix() const {
|
||||
return( event_prefix );
|
||||
}
|
||||
inline bool Ready()
|
||||
{
|
||||
inline bool Ready() {
|
||||
if ( function <= MONITOR )
|
||||
return( false );
|
||||
return( image_count > ready_count );
|
||||
}
|
||||
inline bool Active()
|
||||
{
|
||||
inline bool Active() {
|
||||
if ( function <= MONITOR )
|
||||
return( false );
|
||||
return( enabled && shared_data->active );
|
||||
}
|
||||
inline bool Exif()
|
||||
{
|
||||
inline bool Exif() {
|
||||
return( embed_exif );
|
||||
}
|
||||
|
||||
|
@ -417,17 +441,14 @@ public:
|
|||
int actionColour( int p_colour=-1 );
|
||||
int actionContrast( int p_contrast=-1 );
|
||||
|
||||
inline int PrimeCapture()
|
||||
{
|
||||
inline int PrimeCapture() {
|
||||
return( camera->PrimeCapture() );
|
||||
}
|
||||
inline int PreCapture()
|
||||
{
|
||||
inline int PreCapture() {
|
||||
return( camera->PreCapture() );
|
||||
}
|
||||
int Capture();
|
||||
int PostCapture()
|
||||
{
|
||||
int PostCapture() {
|
||||
return( camera->PostCapture() );
|
||||
}
|
||||
|
||||
|
@ -470,8 +491,7 @@ public:
|
|||
|
||||
#define MOD_ADD( var, delta, limit ) (((var)+(limit)+(delta))%(limit))
|
||||
|
||||
class MonitorStream : public StreamBase
|
||||
{
|
||||
class MonitorStream : public StreamBase {
|
||||
protected:
|
||||
typedef struct SwapImage {
|
||||
bool valid;
|
||||
|
@ -502,19 +522,15 @@ protected:
|
|||
void processCommand( const CmdMsg *msg );
|
||||
|
||||
public:
|
||||
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 )
|
||||
{
|
||||
MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) {
|
||||
}
|
||||
void setStreamBuffer( int p_playback_buffer )
|
||||
{
|
||||
void setStreamBuffer( int p_playback_buffer ) {
|
||||
playback_buffer = p_playback_buffer;
|
||||
}
|
||||
void setStreamTTL( time_t p_ttl )
|
||||
{
|
||||
void setStreamTTL( time_t p_ttl ) {
|
||||
ttl = p_ttl;
|
||||
}
|
||||
bool setStreamStart( int monitor_id )
|
||||
{
|
||||
bool setStreamStart( int monitor_id ) {
|
||||
return loadMonitor( monitor_id );
|
||||
}
|
||||
void runStream();
|
||||
|
|
|
@ -21,8 +21,23 @@
|
|||
|
||||
#include "zm_utils.h"
|
||||
|
||||
RemoteCamera::RemoteCamera( int p_id, const std::string &p_protocol, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
RemoteCamera::RemoteCamera(
|
||||
int p_id,
|
||||
const std::string &p_protocol,
|
||||
const std::string &p_host,
|
||||
const std::string &p_port,
|
||||
const std::string &p_path,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio
|
||||
) :
|
||||
Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
protocol( p_protocol ),
|
||||
host( p_host ),
|
||||
port( p_port ),
|
||||
|
|
|
@ -55,7 +55,22 @@ protected:
|
|||
struct addrinfo *hp;
|
||||
|
||||
public:
|
||||
RemoteCamera( int p_id, const std::string &p_proto, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
RemoteCamera(
|
||||
int p_id,
|
||||
const std::string &p_proto,
|
||||
const std::string &p_host,
|
||||
const std::string &p_port,
|
||||
const std::string &p_path,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio
|
||||
);
|
||||
virtual ~RemoteCamera();
|
||||
|
||||
const std::string &Protocol() const { return( protocol ); }
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
#include <sys/filio.h> // FIONREAD and friends
|
||||
#endif
|
||||
|
||||
RemoteCameraHttp::RemoteCameraHttp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture )
|
||||
RemoteCameraHttp::RemoteCameraHttp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio )
|
||||
{
|
||||
sd = -1;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ protected:
|
|||
enum { SIMPLE, REGEXP } method;
|
||||
|
||||
public:
|
||||
RemoteCameraHttp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
RemoteCameraHttp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~RemoteCameraHttp();
|
||||
|
||||
void Initialise();
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
|
||||
RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
|
||||
rtsp_describe( p_rtsp_describe ),
|
||||
rtspThread( 0 )
|
||||
|
||||
|
@ -52,11 +52,14 @@ RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const
|
|||
|
||||
mFormatContext = NULL;
|
||||
mVideoStreamId = -1;
|
||||
mAudioStreamId = -1;
|
||||
mCodecContext = NULL;
|
||||
mCodec = NULL;
|
||||
mRawFrame = NULL;
|
||||
mFrame = NULL;
|
||||
frameCount = 0;
|
||||
wasRecording = false;
|
||||
startTime=0;
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
mConvertContext = NULL;
|
||||
|
@ -113,6 +116,8 @@ void RemoteCameraRtsp::Initialise()
|
|||
|
||||
int max_size = width*height*colours;
|
||||
|
||||
// This allocates a buffer able to hold a raw fframe, which is a little artbitrary. Might be nice to get some
|
||||
// decent data on how large a buffer is really needed.
|
||||
buffer.size( max_size );
|
||||
|
||||
if ( logDebugging() )
|
||||
|
@ -168,6 +173,7 @@ int RemoteCameraRtsp::PrimeCapture()
|
|||
// Find first video stream present
|
||||
mVideoStreamId = -1;
|
||||
|
||||
// Find the first video stream.
|
||||
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ )
|
||||
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
|
||||
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
|
||||
|
@ -236,8 +242,7 @@ int RemoteCameraRtsp::PrimeCapture()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraRtsp::PreCapture()
|
||||
{
|
||||
int RemoteCameraRtsp::PreCapture() {
|
||||
if ( !rtspThread->isRunning() )
|
||||
return( -1 );
|
||||
if ( !rtspThread->hasSources() )
|
||||
|
@ -248,8 +253,7 @@ int RemoteCameraRtsp::PreCapture()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraRtsp::Capture( Image &image )
|
||||
{
|
||||
int RemoteCameraRtsp::Capture( Image &image ) {
|
||||
AVPacket packet;
|
||||
uint8_t* directbuffer;
|
||||
int frameComplete = false;
|
||||
|
@ -261,14 +265,12 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
return (-1);
|
||||
}
|
||||
|
||||
while ( true )
|
||||
{
|
||||
while ( true ) {
|
||||
buffer.clear();
|
||||
if ( !rtspThread->isRunning() )
|
||||
return (-1);
|
||||
|
||||
if ( rtspThread->getFrame( buffer ) )
|
||||
{
|
||||
if ( rtspThread->getFrame( buffer ) ) {
|
||||
Debug( 3, "Read frame %d bytes", buffer.size() );
|
||||
Debug( 4, "Address %p", buffer.head() );
|
||||
Hexdump( 4, buffer.head(), 16 );
|
||||
|
@ -276,18 +278,17 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
if ( !buffer.size() )
|
||||
return( -1 );
|
||||
|
||||
if(mCodecContext->codec_id == AV_CODEC_ID_H264)
|
||||
{
|
||||
if(mCodecContext->codec_id == AV_CODEC_ID_H264) {
|
||||
// SPS and PPS frames should be saved and appended to IDR frames
|
||||
int nalType = (buffer.head()[3] & 0x1f);
|
||||
|
||||
// SPS
|
||||
// SPS The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures
|
||||
if(nalType == 7)
|
||||
{
|
||||
lastSps = buffer;
|
||||
continue;
|
||||
}
|
||||
// PPS
|
||||
// PPS The PPS NAL unit contains parameters that apply to the decoding of one or more individual pictures inside a coded video sequence
|
||||
else if(nalType == 8)
|
||||
{
|
||||
lastPps = buffer;
|
||||
|
@ -303,17 +304,17 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
|
||||
av_init_packet( &packet );
|
||||
|
||||
while ( !frameComplete && buffer.size() > 0 )
|
||||
{
|
||||
while ( !frameComplete && buffer.size() > 0 ) {
|
||||
packet.data = buffer.head();
|
||||
packet.size = buffer.size();
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
|
||||
// So I think this is the magic decode step. Result is a raw image?
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet );
|
||||
#else
|
||||
#else
|
||||
int len = avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size );
|
||||
#endif
|
||||
if ( len < 0 )
|
||||
{
|
||||
#endif
|
||||
if ( len < 0 ) {
|
||||
Error( "Error while decoding frame %d", frameCount );
|
||||
Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() );
|
||||
buffer.clear();
|
||||
|
@ -324,13 +325,165 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
//Hexdump( 0, buffer.head(), buffer.size() );
|
||||
|
||||
buffer -= len;
|
||||
|
||||
}
|
||||
// At this point, we either have a frame or ran out of buffer. What happens if we run out of buffer?
|
||||
if ( frameComplete ) {
|
||||
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height );
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(mConvertContext == NULL) {
|
||||
mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
|
||||
|
||||
if(mConvertContext == NULL)
|
||||
Fatal( "Unable to create conversion context");
|
||||
}
|
||||
|
||||
if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 )
|
||||
Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount );
|
||||
#else // HAVE_LIBSWSCALE
|
||||
Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" );
|
||||
#endif // HAVE_LIBSWSCALE
|
||||
|
||||
frameCount++;
|
||||
|
||||
} /* frame complete */
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||
av_packet_unref( &packet );
|
||||
#else
|
||||
av_free_packet( &packet );
|
||||
#endif
|
||||
} /* getFrame() */
|
||||
|
||||
if(frameComplete)
|
||||
return (0);
|
||||
|
||||
} // end while true
|
||||
|
||||
// can never get here.
|
||||
return (0) ;
|
||||
}
|
||||
|
||||
//Function to handle capture and store
|
||||
int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* event_file ) {
|
||||
AVPacket packet;
|
||||
uint8_t* directbuffer;
|
||||
int frameComplete = false;
|
||||
|
||||
/* Request a writeable buffer of the target image */
|
||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
if(directbuffer == NULL) {
|
||||
Error("Failed requesting writeable buffer for the captured image.");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while ( true ) {
|
||||
buffer.clear();
|
||||
if ( !rtspThread->isRunning() )
|
||||
return (-1);
|
||||
|
||||
if ( rtspThread->getFrame( buffer ) ) {
|
||||
Debug( 3, "Read frame %d bytes", buffer.size() );
|
||||
Debug( 4, "Address %p", buffer.head() );
|
||||
Hexdump( 4, buffer.head(), 16 );
|
||||
|
||||
if ( !buffer.size() )
|
||||
return( -1 );
|
||||
|
||||
if(mCodecContext->codec_id == AV_CODEC_ID_H264) {
|
||||
// SPS and PPS frames should be saved and appended to IDR frames
|
||||
int nalType = (buffer.head()[3] & 0x1f);
|
||||
|
||||
// SPS
|
||||
if(nalType == 7) {
|
||||
lastSps = buffer;
|
||||
continue;
|
||||
}
|
||||
// PPS
|
||||
else if(nalType == 8) {
|
||||
lastPps = buffer;
|
||||
continue;
|
||||
}
|
||||
// IDR
|
||||
else if(nalType == 5) {
|
||||
buffer += lastSps;
|
||||
buffer += lastPps;
|
||||
}
|
||||
} // end if H264, what about other codecs?
|
||||
|
||||
av_init_packet( &packet );
|
||||
|
||||
// Why are we checking for it being the video stream
|
||||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
|
||||
while ( !frameComplete && buffer.size() > 0 ) {
|
||||
packet.data = buffer.head();
|
||||
packet.size = buffer.size();
|
||||
|
||||
// So this does the decode
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet );
|
||||
#else
|
||||
int len = avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size );
|
||||
#endif
|
||||
if ( len < 0 ) {
|
||||
Error( "Error while decoding frame %d", frameCount );
|
||||
Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() );
|
||||
buffer.clear();
|
||||
continue;
|
||||
}
|
||||
Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() );
|
||||
//if ( buffer.size() < 400 )
|
||||
//Hexdump( 0, buffer.head(), buffer.size() );
|
||||
|
||||
buffer -= len;
|
||||
} // end while get & decode a frame
|
||||
|
||||
if ( frameComplete ) {
|
||||
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height );
|
||||
|
||||
//Video recording
|
||||
if ( recording && !wasRecording ) {
|
||||
//Instantiate the video storage module
|
||||
|
||||
videoStore = new VideoStore((const char *)event_file, "mp4", mFormatContext->streams[mVideoStreamId],mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId],startTime);
|
||||
wasRecording = true;
|
||||
strcpy(oldDirectory, event_file);
|
||||
|
||||
} else if ( !recording && wasRecording && videoStore ) {
|
||||
// Why are we deleting the videostore? Becase for soem reason we are no longer recording? How does that happen?
|
||||
Info("Deleting videoStore instance");
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
}
|
||||
|
||||
//The directory we are recording to is no longer tied to the current event. Need to re-init the videostore with the correct directory and start recording again
|
||||
if ( recording && wasRecording && (strcmp(oldDirectory, event_file)!=0) && (packet.flags & AV_PKT_FLAG_KEY) ) {
|
||||
//don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...if we store our key frame location with the event will that be enough?
|
||||
Info("Re-starting video storage module");
|
||||
if ( videoStore ) {
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
}
|
||||
|
||||
videoStore = new VideoStore((const char *)event_file, "mp4", mFormatContext->streams[mVideoStreamId],mAudioStreamId==-1?NULL:mFormatContext->streams[mAudioStreamId],startTime);
|
||||
strcpy( oldDirectory, event_file );
|
||||
}
|
||||
|
||||
if ( videoStore && recording ) {
|
||||
//Write the packet to our video store
|
||||
int ret = videoStore->writeVideoFramePacket(&packet, mFormatContext->streams[mVideoStreamId]);//, &lastKeyframePkt);
|
||||
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
||||
av_free_packet( &packet );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(mConvertContext == NULL) {
|
||||
|
@ -349,9 +502,29 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
frameCount++;
|
||||
|
||||
} /* frame complete */
|
||||
} else if ( packet.stream_index == mAudioStreamId ) {
|
||||
Debug( 4, "Got audio packet" );
|
||||
if ( videoStore && recording ) {
|
||||
if ( record_audio ) {
|
||||
Debug( 4, "Storing Audio packet" );
|
||||
//Write the packet to our video store
|
||||
int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame
|
||||
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||
av_packet_unref( &packet );
|
||||
#else
|
||||
av_free_packet( &packet );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
Debug( 4, "Not storing audio" );
|
||||
}
|
||||
}
|
||||
} // end if video or audio packet
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||
av_packet_unref( &packet);
|
||||
av_packet_unref( &packet );
|
||||
#else
|
||||
av_free_packet( &packet );
|
||||
#endif
|
||||
|
@ -359,10 +532,9 @@ int RemoteCameraRtsp::Capture( Image &image )
|
|||
|
||||
if(frameComplete)
|
||||
return (0);
|
||||
|
||||
}
|
||||
} // end while true
|
||||
return (0) ;
|
||||
}
|
||||
} // int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* event_file )
|
||||
|
||||
int RemoteCameraRtsp::PostCapture()
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "zm_utils.h"
|
||||
#include "zm_rtsp.h"
|
||||
#include "zm_ffmpeg.h"
|
||||
#include "zm_videostore.h"
|
||||
|
||||
//
|
||||
// Class representing 'rtsp' cameras, i.e. those which are
|
||||
|
@ -55,19 +56,24 @@ protected:
|
|||
#if HAVE_LIBAVFORMAT
|
||||
AVFormatContext *mFormatContext;
|
||||
int mVideoStreamId;
|
||||
int mAudioStreamId;
|
||||
AVCodecContext *mCodecContext;
|
||||
AVCodec *mCodec;
|
||||
AVFrame *mRawFrame;
|
||||
AVFrame *mFrame;
|
||||
_AVPIXELFORMAT imagePixFormat;
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
bool wasRecording;
|
||||
VideoStore *videoStore;
|
||||
char oldDirectory[4096];
|
||||
int64_t startTime;
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
struct SwsContext *mConvertContext;
|
||||
#endif
|
||||
|
||||
public:
|
||||
RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
|
||||
~RemoteCameraRtsp();
|
||||
|
||||
void Initialise();
|
||||
|
@ -79,7 +85,7 @@ public:
|
|||
int PreCapture();
|
||||
int Capture( Image &image );
|
||||
int PostCapture();
|
||||
int CaptureAndRecord( Image &image, bool recording, char* event_directory ) {return(0);};
|
||||
int CaptureAndRecord( Image &image, bool recording, char* event_directory );
|
||||
};
|
||||
|
||||
#endif // ZM_REMOTE_CAMERA_RTSP_H
|
||||
|
|
|
@ -262,6 +262,11 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen )
|
|||
int rtpHeaderSize = 12 + rtpHeader->cc * 4;
|
||||
// No need to check for nal type as non fragmented packets already have 001 start sequence appended
|
||||
bool h264FragmentEnd = (mCodecId == AV_CODEC_ID_H264) && (packet[rtpHeaderSize+1] & 0x40);
|
||||
// M stands for Market, it is the 8th bit
|
||||
// The interpretation of the marker is defined by a profile. It is intended
|
||||
// to allow significant events such as frame boundaries to be marked in the
|
||||
// packet stream. A profile may define additional marker bits or specify
|
||||
// that there is no marker bit by changing the number of bits in the payload type field.
|
||||
bool thisM = rtpHeader->m || h264FragmentEnd;
|
||||
|
||||
if ( updateSeq( ntohs(rtpHeader->seqN) ) )
|
||||
|
@ -275,15 +280,18 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen )
|
|||
if( mCodecId == AV_CODEC_ID_H264 )
|
||||
{
|
||||
int nalType = (packet[rtpHeaderSize] & 0x1f);
|
||||
Debug( 3, "Have H264 frame: nal type is %d", nalType );
|
||||
|
||||
switch (nalType)
|
||||
{
|
||||
case 24:
|
||||
case 24: // STAP-A
|
||||
{
|
||||
extraHeader = 2;
|
||||
break;
|
||||
}
|
||||
case 25: case 26: case 27:
|
||||
case 25: // STAP-B
|
||||
case 26: // MTAP-16
|
||||
case 27: // MTAP-24
|
||||
{
|
||||
extraHeader = 3;
|
||||
break;
|
||||
|
@ -304,6 +312,9 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen )
|
|||
extraHeader = 2;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Debug(3, "Unhandled nalType %d", nalType );
|
||||
}
|
||||
}
|
||||
|
||||
// Append NAL frame start code
|
||||
|
@ -311,6 +322,8 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen )
|
|||
mFrame.append( "\x0\x0\x1", 3 );
|
||||
}
|
||||
mFrame.append( packet+rtpHeaderSize+extraHeader, packetLen-rtpHeaderSize-extraHeader );
|
||||
} else {
|
||||
Debug( 3, "NOT H264 frame: type is %d", mCodecId );
|
||||
}
|
||||
|
||||
Hexdump( 4, mFrame.head(), 16 );
|
||||
|
|
|
@ -64,7 +64,7 @@ X264MP4Writer::X264MP4Writer(const char* p_path, const unsigned int p_width, con
|
|||
if(zm_pf == 0) {
|
||||
Error("Unable to match ffmpeg pixelformat");
|
||||
}
|
||||
codec_pf = AV_PIX_FMT_YUV420P;
|
||||
codec_pf = PIX_FMT_YUV420P;
|
||||
|
||||
swscaleobj.SetDefaults(zm_pf, codec_pf, width, height);
|
||||
|
||||
|
|
|
@ -120,8 +120,8 @@ protected:
|
|||
|
||||
/* SWScale */
|
||||
SWScale swscaleobj;
|
||||
enum _AVPIXELFORMAT zm_pf;
|
||||
enum _AVPIXELFORMAT codec_pf;
|
||||
enum PixelFormat zm_pf;
|
||||
enum PixelFormat codec_pf;
|
||||
size_t codec_imgsize;
|
||||
size_t zm_imgsize;
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# Define the line ending behavior of the different file extensions
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files we want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.php text
|
||||
*.default text
|
||||
*.ctp text
|
||||
*.sql text
|
||||
*.md text
|
||||
*.po text
|
||||
*.js text
|
||||
*.css text
|
||||
*.ini text
|
||||
*.properties text
|
||||
*.txt text
|
||||
*.xml text
|
||||
*.yml text
|
||||
.htaccess text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.bat eol=crlf
|
||||
|
||||
# Declare files that will always have LF line endings on checkout.
|
||||
*.pem eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mo binary
|
|
@ -1,21 +0,0 @@
|
|||
# User specific & automatically generated files #
|
||||
#################################################
|
||||
/app/Config/database.php
|
||||
/app/tmp
|
||||
/lib/Cake/Console/Templates/skel/tmp/
|
||||
/plugins
|
||||
/vendors
|
||||
/build
|
||||
/dist
|
||||
/tags
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
|
@ -1153,30 +1153,38 @@ function zmaCheck( $monitor )
|
|||
|
||||
function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false )
|
||||
{
|
||||
$eventPath = getEventPath( $event );
|
||||
$eventPath = ZM_DIR_EVENTS.'/'.getEventPath( $event );
|
||||
|
||||
if ( !is_array($frame) )
|
||||
$frame = array( 'FrameId'=>$frame, 'Type'=>'' );
|
||||
|
||||
//echo "S:$scale, CO:$captureOnly<br>";
|
||||
$currEvent = dbFetchOne( 'SELECT M.SaveJPEGs FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = '.$event['Id'] );
|
||||
if ( $currEvent['SaveJPEGs'] == "4" )
|
||||
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) {
|
||||
$captImage = "snapshot.jpg";
|
||||
else
|
||||
} else {
|
||||
$captImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] );
|
||||
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
|
||||
# Generate the frame JPG
|
||||
if ( $event['DefaultVideo'] ) {
|
||||
$command ='ffmpeg -v 0 -i '.$eventPath.'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
|
||||
system( $command, $output, $retval );
|
||||
} else {
|
||||
Error("Can't create frame images from video becuase there is no video file for this event " );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$captPath = $eventPath.'/'.$captImage;
|
||||
$thumbCaptPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$captImage;
|
||||
//echo "CI:$captImage, CP:$captPath, TCP:$thumbCaptPath<br>";
|
||||
|
||||
$analImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $frame['FrameId'] );
|
||||
$analPath = $eventPath.'/'.$analImage;
|
||||
$analFile = ZM_DIR_EVENTS."/".$analPath;
|
||||
$thumbAnalPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$analImage;
|
||||
//echo "AI:$analImage, AP:$analPath, TAP:$thumbAnalPath<br>";
|
||||
|
||||
$alarmFrame = $frame['Type']=='Alarm';
|
||||
|
||||
$hasAnalImage = $alarmFrame && file_exists( $analFile ) && filesize( $analFile );
|
||||
$hasAnalImage = $alarmFrame && file_exists( $analPath ) && filesize( $analPath );
|
||||
$isAnalImage = $hasAnalImage && !$captureOnly;
|
||||
|
||||
if ( !ZM_WEB_SCALE_THUMBS || $scale >= SCALE_BASE || !function_exists( 'imagecreatefromjpeg' ) )
|
||||
|
@ -1207,22 +1215,20 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
|
|||
$thumbPath = $thumbCaptPath;
|
||||
}
|
||||
|
||||
$imageFile = ZM_DIR_EVENTS."/".$imagePath;
|
||||
//$thumbFile = ZM_DIR_EVENTS."/".$thumbPath;
|
||||
$thumbFile = $thumbPath;
|
||||
if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) )
|
||||
{
|
||||
// Get new dimensions
|
||||
list( $imageWidth, $imageHeight ) = getimagesize( $imageFile );
|
||||
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
|
||||
$thumbWidth = $imageWidth * $fraction;
|
||||
$thumbHeight = $imageHeight * $fraction;
|
||||
|
||||
// Resample
|
||||
$thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight );
|
||||
$image = imagecreatefromjpeg( $imageFile );
|
||||
$image = imagecreatefromjpeg( $imagePath );
|
||||
imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight );
|
||||
|
||||
if ( !imagejpeg( $thumbImage, $thumbFile ) )
|
||||
if ( !imagejpeg( $thumbImage, $thumbPath ) )
|
||||
Error( "Can't create thumbnail '$thumbPath'" );
|
||||
}
|
||||
}
|
||||
|
@ -1231,15 +1237,13 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
|
|||
'eventPath' => $eventPath,
|
||||
'imagePath' => $imagePath,
|
||||
'thumbPath' => $thumbPath,
|
||||
'imageFile' => $imageFile,
|
||||
'imageFile' => $imagePath,
|
||||
'thumbFile' => $thumbFile,
|
||||
'imageClass' => $alarmFrame?"alarm":"normal",
|
||||
'isAnalImage' => $isAnalImage,
|
||||
'hasAnalImage' => $hasAnalImage,
|
||||
);
|
||||
|
||||
//echo "IP:$imagePath<br>";
|
||||
//echo "TP:$thumbPath<br>";
|
||||
return( $imageData );
|
||||
}
|
||||
|
||||
|
|
|
@ -584,6 +584,7 @@ $SLANG = array(
|
|||
'Protocol' => 'Protocol',
|
||||
'Rate' => 'Rate',
|
||||
'RecaptchaWarning' => 'Your reCaptcha secret key is invalid. Please correct it, or reCaptcha will not work', // added Sep 24 2015 - PP
|
||||
'RecordAudio' => 'Whether to store the audio stream when saving an event.',
|
||||
'Real' => 'Real',
|
||||
'Record' => 'Record',
|
||||
'RefImageBlendPct' => 'Reference Image Blend %ge',
|
||||
|
|
|
@ -55,7 +55,7 @@ $replayModes = array(
|
|||
if ( isset( $_REQUEST['streamMode'] ) )
|
||||
$streamMode = validHtmlStr($_REQUEST['streamMode']);
|
||||
else
|
||||
$streamMode = video;
|
||||
$streamMode = 'video';
|
||||
|
||||
if ( isset( $_REQUEST['replayMode'] ) )
|
||||
$replayMode = validHtmlStr($_REQUEST['replayMode']);
|
||||
|
|
|
@ -86,6 +86,7 @@ if ( ! empty($_REQUEST['mid']) ) {
|
|||
'SaveJPEGs' => "3",
|
||||
'VideoWriter' => "0",
|
||||
'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
|
||||
'RecordAudio' => "0",
|
||||
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
|
||||
'LabelX' => 0,
|
||||
'LabelY' => 0,
|
||||
|
@ -593,6 +594,7 @@ if ( $tab != 'storage' )
|
|||
<input type="hidden" name="newMonitor[SaveJPEGs]" value="<?php echo validHtmlStr($newMonitor['SaveJPEGs']) ?>"/>
|
||||
<input type="hidden" name="newMonitor[VideoWriter]" value="<?php echo validHtmlStr($newMonitor['VideoWriter']) ?>"/>
|
||||
<input type="hidden" name="newMonitor[EncoderParameters]" value="<?php echo validHtmlStr($newMonitor['EncoderParameters']) ?>"/>
|
||||
<input type="hidden" name="newMonitor[RecordAudio]" value="<?php echo validHtmlStr($newMonitor['RecordAudio']) ?>"/>
|
||||
<?php
|
||||
}
|
||||
if ( $tab != 'source' || ($newMonitor['Type'] != 'Remote' && $newMonitor['Protocol'] != 'RTSP'))
|
||||
|
@ -891,6 +893,7 @@ switch ( $tab )
|
|||
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['SaveJPEGs'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['VideoWriter'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($newMonitor['EncoderParameters']) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( !empty($newMonitor['RecordAudio']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
break;
|
||||
case 'timestamp' :
|
||||
|
|
Loading…
Reference in New Issue