Lots accomplished!
1) Delta and blend SSE and standard alogirthms inside 2) Changed event streaming to use sendfile() syscall if available 3) Direct memory capture (Less memcpys required) 4) Added macros for BGR24 and RGB32(and its variants) formats 5) Modified Monitors database table to add a target colorspace option 6) Changed most image buffer allocations to be on 16 byte boundary, work still in progress 7) Added Target colorspace instead of the old colours selection. this one also visible to local cameras 8) Replacing Y deltas option with ZM_CPU_EXTENSIONS 9) Added SSE detection code 10) Changed some code to make linking success with inlining enabled. 11) Some other changes and work still in progress for some listed above
This commit is contained in:
parent
13e46d8595
commit
5c418133bf
|
@ -192,6 +192,9 @@
|
|||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#undef HAVE_SIGACTION
|
||||
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
#undef HAVE_SENDFILE
|
||||
|
||||
/* Define to 1 if the system has the type `siginfo_t'. */
|
||||
#undef HAVE_SIGINFO_T
|
||||
|
||||
|
@ -292,6 +295,9 @@
|
|||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||
#undef HAVE_SYS_SENDFILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ AC_FUNC_STAT
|
|||
AC_FUNC_STRFTIME
|
||||
AC_FUNC_STRTOD
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS([gethostbyname gethostname gettimeofday memmove memset mkdir munmap putenv select socket sqrt strcasecmp strchr strcspn strerror strncasecmp strrchr strsignal strspn strstr strtol strtoull])
|
||||
AC_CHECK_FUNCS([gethostbyname gethostname gettimeofday memmove memset mkdir munmap posix_memalign putenv select sendfile socket sqrt strcasecmp strchr strcspn strerror strncasecmp strrchr strsignal strspn strstr strtol strtoull])
|
||||
AC_CHECK_FUNCS([syscall sleep usleep ioctl ioctlsocket sigaction])
|
||||
|
||||
# Other programs
|
||||
|
@ -287,7 +287,7 @@ AC_CHECK_LIB(z,compress,,)
|
|||
AC_FUNC_ALLOCA
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h memory.h stddef.h stdlib.h string.h strings.h sys/param.h sys/time.h syslog.h unistd.h values.h])
|
||||
AC_CHECK_HEADERS([netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/socket.h sys/un.h glob.h])
|
||||
AC_CHECK_HEADERS([netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/socket.h sys/un.h glob.h sys/sendfile.h])
|
||||
AC_CHECK_HEADERS(execinfo.h,,,)
|
||||
AC_CHECK_HEADERS(syscall.h,,,)
|
||||
AC_CHECK_HEADERS(pthread.h,,,)
|
||||
|
|
|
@ -329,6 +329,7 @@ CREATE TABLE `Monitors` (
|
|||
`Path` varchar(255) NOT NULL default '',
|
||||
`Width` smallint(5) unsigned NOT NULL default '0',
|
||||
`Height` smallint(5) unsigned NOT NULL default '0',
|
||||
`Colours` tinyint(3) unsigned NOT NULL default '1',
|
||||
`Palette` int(10) unsigned NOT NULL default '0',
|
||||
`Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0',
|
||||
`Brightness` mediumint(7) NOT NULL default '-1',
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
-- This updates a 1.24.2 database to the next version
|
||||
--
|
||||
|
||||
--Add Colours colum. This is a harmless change for ZM 1.24.2 or ZM 1.24.3 without the patch, but is required to use the patch
|
||||
ALTER TABLE `Monitors` ADD `Colours` TINYINT UNSIGNED NOT NULL DEFAULT '1' AFTER `Height`;
|
||||
|
||||
--
|
||||
-- Add in remote ZoneMinder preset.
|
||||
--
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AUTOMAKE_OPTIONS = gnu
|
||||
|
||||
AM_CPPFLAGS = @MYSQL_CFLAGS@ @FFMPEG_CFLAGS@ -Wall -Wno-sign-compare -fno-inline
|
||||
AM_CPPFLAGS = @MYSQL_CFLAGS@ @FFMPEG_CFLAGS@ -Wall -Wno-sign-compare -finline-functions
|
||||
#AM_CXXFLAGS = -frepo
|
||||
|
||||
CLEANFILES = *.rpo
|
||||
|
|
|
@ -20,19 +20,22 @@
|
|||
#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_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 ) :
|
||||
id( p_id ),
|
||||
type( p_type ),
|
||||
width( p_width),
|
||||
height( p_height ),
|
||||
colours( p_colours ),
|
||||
subpixelorder( p_subpixelorder ),
|
||||
brightness( p_brightness ),
|
||||
hue( p_hue ),
|
||||
colour( p_colour ),
|
||||
contrast( p_contrast ),
|
||||
capture( p_capture )
|
||||
{
|
||||
pixels = width * height * colours;
|
||||
pixels = width * height;
|
||||
imagesize = pixels * colours;
|
||||
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
|
|
|
@ -39,7 +39,9 @@ protected:
|
|||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int colours;
|
||||
unsigned int subpixelorder;
|
||||
unsigned int pixels;
|
||||
unsigned int imagesize;
|
||||
int brightness;
|
||||
int hue;
|
||||
int colour;
|
||||
|
@ -47,7 +49,7 @@ protected:
|
|||
bool capture;
|
||||
|
||||
public:
|
||||
Camera( int p_id, SourceType p_type, 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( 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 );
|
||||
virtual ~Camera();
|
||||
|
||||
int getId() const { return( id ); }
|
||||
|
@ -59,7 +61,9 @@ public:
|
|||
unsigned int Width() const { return( width ); }
|
||||
unsigned int Height() const { return( height ); }
|
||||
unsigned int Colours() const { return( colours ); }
|
||||
unsigned int ImageSize() const { return( pixels ); }
|
||||
unsigned int SubpixelOrder const { return( subpixelorder ); }
|
||||
unsigned int Pixels() const { return( pixels ); }
|
||||
unsigned int ImageSize() const { return( imagesize ); }
|
||||
|
||||
virtual int Brightness( int/*p_brightness*/=-1 ) { return( -1 ); }
|
||||
virtual int Hue( int/*p_hue*/=-1 ) { return( -1 ); }
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define ZM_RELOAD_CAMBOZOLA 24
|
||||
#define ZM_TIMESTAMP_ON_CAPTURE 25
|
||||
#define ZM_LOCAL_BGR_INVERT 26
|
||||
#define ZM_Y_IMAGE_DELTAS 27
|
||||
#define ZM_CPU_EXTENSIONS 27
|
||||
#define ZM_FAST_IMAGE_BLENDS 28
|
||||
#define ZM_OPT_ADAPTIVE_SKIP 29
|
||||
#define ZM_BLEND_ALARMED_IMAGES 30
|
||||
|
@ -251,7 +251,7 @@
|
|||
int reload_cambozola;\
|
||||
bool timestamp_on_capture;\
|
||||
bool local_bgr_invert;\
|
||||
bool y_image_deltas;\
|
||||
bool cpu_extensions;\
|
||||
bool fast_image_blends;\
|
||||
bool opt_adaptive_skip;\
|
||||
bool blend_alarmed_images;\
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <glob.h>
|
||||
|
||||
#if defined(HAVE_SYS_SENDFILE_H) && defined(HAVE_SENDFILE)
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_time.h"
|
||||
|
@ -751,6 +755,9 @@ bool EventStream::loadEventData( int event_id )
|
|||
if ( config.use_deep_storage )
|
||||
{
|
||||
struct tm *event_time = localtime( &event_data->start_time );
|
||||
if ( config.dir_events[0] == '/' )
|
||||
snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
|
||||
else
|
||||
snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec );
|
||||
}
|
||||
else
|
||||
|
@ -1185,6 +1192,9 @@ bool EventStream::sendFrame( int delta_us )
|
|||
Debug( 2, "Sending frame %d", curr_frame_id );
|
||||
|
||||
static char filepath[PATH_MAX];
|
||||
static struct stat filestat;
|
||||
FILE *fdj = NULL;
|
||||
|
||||
snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id );
|
||||
|
||||
#if HAVE_LIBAVCODEC
|
||||
|
@ -1219,14 +1229,20 @@ bool EventStream::sendFrame( int delta_us )
|
|||
|
||||
if ( send_raw )
|
||||
{
|
||||
FILE *fdj = fopen( filepath, "r" );
|
||||
fdj = fopen( filepath, "rb" );
|
||||
if ( !fdj )
|
||||
{
|
||||
Error( "Can't open %s: %s", filepath, strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
#if HAVE_SENDFILE
|
||||
if( fstat(fileno(fdj),&filestat) < 0 ) {
|
||||
Error( "Failed getting information about file %s: %s", filepath, strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
#else
|
||||
img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj );
|
||||
fclose( fdj );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1269,12 +1285,31 @@ bool EventStream::sendFrame( int delta_us )
|
|||
Fatal( "Unexpected frame type %d", type );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(send_raw) {
|
||||
#if HAVE_SENDFILE
|
||||
fprintf( stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size );
|
||||
if(sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size) {
|
||||
Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno));
|
||||
return( false );
|
||||
}
|
||||
#else
|
||||
if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) {
|
||||
Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno));
|
||||
return( false );
|
||||
}
|
||||
#endif
|
||||
fclose(fdj); /* Close the file handle */
|
||||
} else {
|
||||
fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size );
|
||||
if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 )
|
||||
{
|
||||
Error( "Unable to send stream frame: %s", strerror(errno) );
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( stdout, "\r\n\r\n" );
|
||||
fflush( stdout );
|
||||
}
|
||||
|
@ -1413,3 +1448,4 @@ void EventStream::runStream()
|
|||
|
||||
closeComms();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "zm_ffmpeg_camera.h"
|
||||
|
||||
FfmpegCamera::FfmpegCamera( int p_id, 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, FFMPEG_SRC, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, 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 ),
|
||||
mPath( p_path )
|
||||
{
|
||||
if ( capture )
|
||||
|
|
|
@ -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_palette, 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_palette, 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 ) : 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 )
|
||||
{
|
||||
strncpy( path, p_path, sizeof(path) );
|
||||
if ( capture )
|
||||
|
@ -82,7 +82,7 @@ int FileCamera::PreCapture()
|
|||
|
||||
int FileCamera::Capture( Image &image )
|
||||
{
|
||||
return( image.ReadJpeg( path )?0:-1 );
|
||||
return( image.ReadJpeg( path, colours, subpixelorder )?0:-1 );
|
||||
}
|
||||
|
||||
int FileCamera::PostCapture()
|
||||
|
|
|
@ -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_palette, 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 );
|
||||
~FileCamera();
|
||||
|
||||
const char *Path() const { return( path ); }
|
||||
|
|
1688
src/zm_image.cpp
1688
src/zm_image.cpp
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,12 @@ extern "C"
|
|||
#include <zlib.h>
|
||||
#endif // HAVE_ZLIB_H
|
||||
|
||||
#define ZM_BUFTYPE_DONTFREE 0
|
||||
#define ZM_BUFTYPE_MALLOC 1
|
||||
#define ZM_BUFTYPE_NEW 2
|
||||
#define ZM_BUFTYPE_AVMALLOC 3
|
||||
#define ZM_BUFTYPE_ZM 4
|
||||
|
||||
//
|
||||
// This is image class, and represents a frame captured from a
|
||||
// camera in raw form.
|
||||
|
@ -41,8 +47,6 @@ extern "C"
|
|||
class Image
|
||||
{
|
||||
protected:
|
||||
typedef unsigned char BlendTable[256][256];
|
||||
typedef BlendTable *BlendTablePtr;
|
||||
|
||||
struct Edge
|
||||
{
|
||||
|
@ -66,6 +70,33 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
inline void DumpBuffer() {
|
||||
if (buffer && buffertype != ZM_BUFTYPE_DONTFREE) {
|
||||
if(buffertype == ZM_BUFTYPE_ZM)
|
||||
zm_freealigned(buffer);
|
||||
else if(buffertype == ZM_BUFTYPE_MALLOC)
|
||||
free(buffer);
|
||||
else if(buffertype == ZM_BUFTYPE_NEW)
|
||||
delete buffer;
|
||||
else if(buffertype == ZM_BUFTYPE_AVMALLOC)
|
||||
av_free(buffer);
|
||||
}
|
||||
buffer = NULL;
|
||||
allocation = 0;
|
||||
}
|
||||
|
||||
inline void AllocBuffer(size_t p_bufsize) {
|
||||
if(buffer)
|
||||
DumpBuffer();
|
||||
|
||||
buffer = (uint8_t*)zm_mallocaligned(16,p_bufsize);
|
||||
if(buffer == NULL)
|
||||
Panic("Memory allocation failed: %s",strerror(errno));
|
||||
|
||||
buffertype = ZM_BUFTYPE_ZM;
|
||||
allocation = p_bufsize;
|
||||
}
|
||||
|
||||
public:
|
||||
enum { CHAR_HEIGHT=11, CHAR_WIDTH=6 };
|
||||
enum { LINE_HEIGHT=CHAR_HEIGHT+0 };
|
||||
|
@ -76,7 +107,6 @@ protected:
|
|||
static unsigned char *y_r_table;
|
||||
static unsigned char *y_g_table;
|
||||
static unsigned char *y_b_table;
|
||||
static BlendTablePtr blend_tables[101];
|
||||
static jpeg_compress_struct *jpg_ccinfo[100];
|
||||
static jpeg_decompress_struct *jpg_dcinfo;
|
||||
static struct zm_error_mgr jpg_err;
|
||||
|
@ -87,22 +117,20 @@ protected:
|
|||
int pixels;
|
||||
int colours;
|
||||
int size;
|
||||
int allocation;
|
||||
int subpixelorder;
|
||||
unsigned long allocation;
|
||||
uint8_t *buffer;
|
||||
bool our_buffer;
|
||||
int buffertype; /* 0=not ours, no need to call free(), 1=malloc() buffer, 2=new buffer */
|
||||
int holdbuffer; /* Hold the buffer instead of replacing it with new one */
|
||||
char text[1024];
|
||||
|
||||
protected:
|
||||
mutable uint16_t *blend_buffer;
|
||||
|
||||
protected:
|
||||
static void Initialise();
|
||||
static BlendTablePtr GetBlendTable( int );
|
||||
|
||||
public:
|
||||
Image();
|
||||
Image( const char *filename );
|
||||
Image( int p_width, int p_height, int p_colours, uint8_t *p_buffer=0 );
|
||||
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
|
||||
Image( const Image &p_image );
|
||||
~Image();
|
||||
|
||||
|
@ -110,13 +138,33 @@ public:
|
|||
inline int Height() const { return( height ); }
|
||||
inline int Pixels() const { return( pixels ); }
|
||||
inline int Colours() const { return( colours ); }
|
||||
inline int SubpixelOrder const { return( subpixelorder ); }
|
||||
inline int Size() const { return( size ); }
|
||||
inline uint8_t *Buffer() const { return( buffer ); }
|
||||
inline uint8_t *Buffer( unsigned int x, unsigned int y= 0 ) const { return( &buffer[colours*((y*width)+x)] ); }
|
||||
|
||||
void Empty();
|
||||
void Assign( int p_width, int p_height, int p_colours, unsigned char *new_buffer );
|
||||
/* Internal buffer should not be modified from functions outside of this class */
|
||||
inline const uint8_t* Buffer() const { return( buffer ); }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return( &buffer[colours*((y*width)+x)] ); }
|
||||
/* Request writeable buffer */
|
||||
uint8_t* WriteBuffer(const int p_width, const int p_height, const int p_colours, const int p_subpixelorder);
|
||||
|
||||
inline int IsBufferHeld() const {
|
||||
return holdbuffer;
|
||||
}
|
||||
|
||||
inline void HoldBuffer(int tohold) {
|
||||
holdbuffer = tohold;
|
||||
}
|
||||
|
||||
inline void Empty() {
|
||||
if(!holdbuffer)
|
||||
DumpBuffer();
|
||||
|
||||
width = height = colours = size = pixels = subpixelorder = 0;
|
||||
}
|
||||
|
||||
void Assign( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t* new_buffer );
|
||||
void Assign( const Image &image );
|
||||
void AssignDirect( const int p_width, const int p_height, const int p_colours, const int p_subpixelorder, const uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype);
|
||||
|
||||
inline void CopyBuffer( const Image &image )
|
||||
{
|
||||
|
@ -124,20 +172,20 @@ public:
|
|||
{
|
||||
Panic( "Attempt to copy different size image buffers, expected %d, got %d", size, image.size );
|
||||
}
|
||||
memcpy( buffer, image.buffer, size );
|
||||
sse2_aligned_memcpy( buffer, image->Buffer(), size );
|
||||
}
|
||||
inline Image &operator=( const unsigned char *new_buffer )
|
||||
{
|
||||
memcpy( buffer, new_buffer, size );
|
||||
sse2_aligned_memcpy( buffer, new_buffer, size );
|
||||
return( *this );
|
||||
}
|
||||
|
||||
bool ReadRaw( const char *filename );
|
||||
bool WriteRaw( const char *filename ) const;
|
||||
|
||||
bool ReadJpeg( const char *filename );
|
||||
bool ReadJpeg( const char *filename, int p_colours, int p_subpixelorder);
|
||||
bool WriteJpeg( const char *filename, int quality_override=0 ) const;
|
||||
bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size );
|
||||
bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, int p_colours, int p_subpixelorder);
|
||||
bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const;
|
||||
|
||||
#if HAVE_ZLIB_H
|
||||
|
@ -154,9 +202,10 @@ public:
|
|||
static Image *Merge( int n_images, Image *images[] );
|
||||
static Image *Merge( int n_images, Image *images[], double weight );
|
||||
static Image *Highlight( int n_images, Image *images[], const Rgb threshold=RGB_BLACK, const Rgb ref_colour=RGB_RED );
|
||||
Image *Delta( const Image &image ) const;
|
||||
//Image *Delta( const Image &image ) const;
|
||||
void Image::Delta( const Image &image, Image* targetimage) const;
|
||||
|
||||
const Coord centreCoord( const char *text );
|
||||
const Coord centreCoord( const char *text ) const;
|
||||
void Annotate( const char *p_text, const Coord &coord, const Rgb fg_colour=RGB_WHITE, const Rgb bg_colour=RGB_BLACK );
|
||||
Image *HighlightEdges( Rgb colour, const Box *limits=0 );
|
||||
//Image *HighlightEdges( Rgb colour, const Polygon &polygon );
|
||||
|
@ -173,8 +222,12 @@ public:
|
|||
|
||||
void Rotate( int angle );
|
||||
void Flip( bool leftright );
|
||||
|
||||
void Scale( unsigned int factor );
|
||||
};
|
||||
|
||||
#endif // ZM_IMAGE_H
|
||||
|
||||
|
||||
typedef void (*blend_fptr_t)(uint8_t*, uint8_t*, uint8_t*, unsigned long, double);
|
||||
typedef void (*delta_fptr_t)(uint8_t*, uint8_t*, uint8_t*, unsigned long);
|
||||
|
||||
|
|
|
@ -46,6 +46,19 @@ static int vidioctl( int fd, int request, void *arg )
|
|||
static PixelFormat getFfPixFormatFromV4lPalette( int v4l_version, int palette )
|
||||
{
|
||||
PixelFormat pixFormat = PIX_FMT_NONE;
|
||||
|
||||
/* Check the endianness of the machine */
|
||||
uint32_t checkval = 0xAABBCCDD;
|
||||
int BigEndian;
|
||||
if(*(unsigned char*)&checkval == 0xDD)
|
||||
BigEndian = 0;
|
||||
else if(*(unsigned char*)&checkval == 0xAA)
|
||||
BigEndian = 1;
|
||||
else {
|
||||
Error("Unable to detect the processor's endianness. Assuming little-endian.");
|
||||
BigEndian = 0;
|
||||
}
|
||||
|
||||
#if ZM_HAS_V4L2
|
||||
if ( v4l_version == 2 )
|
||||
{
|
||||
|
@ -53,7 +66,7 @@ static PixelFormat getFfPixFormatFromV4lPalette( int v4l_version, int palette )
|
|||
{
|
||||
#ifdef V4L2_PIX_FMT_RGB444
|
||||
case V4L2_PIX_FMT_RGB444 :
|
||||
pixFormat = PIX_FMT_RGB32;
|
||||
pixFormat = PIX_FMT_RGB444;
|
||||
break;
|
||||
#endif // V4L2_PIX_FMT_RGB444
|
||||
case V4L2_PIX_FMT_RGB555 :
|
||||
|
@ -177,21 +190,27 @@ static PixelFormat getFfPixFormatFromV4lPalette( int v4l_version, int palette )
|
|||
{
|
||||
switch( palette )
|
||||
{
|
||||
case VIDEO_PALETTE_RGB32 :
|
||||
if(BigEndian)
|
||||
pixFormat = PIX_FMT_RGBA;
|
||||
else
|
||||
pixFormat = PIX_FMT_BGRA; // Or should it be ABGR?
|
||||
break;
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
if(BigEndian)
|
||||
pixFormat = PIX_FMT_RGB24;
|
||||
else
|
||||
pixFormat = PIX_FMT_BGR24;
|
||||
break;
|
||||
case VIDEO_PALETTE_GREY :
|
||||
pixFormat = PIX_FMT_GRAY8;
|
||||
break;
|
||||
case VIDEO_PALETTE_RGB555 :
|
||||
pixFormat = PIX_FMT_RGB555;
|
||||
break;
|
||||
case VIDEO_PALETTE_RGB565 :
|
||||
pixFormat = PIX_FMT_RGB565;
|
||||
break;
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
if ( config.local_bgr_invert )
|
||||
pixFormat = PIX_FMT_BGR24;
|
||||
else
|
||||
pixFormat = PIX_FMT_RGB24;
|
||||
break;
|
||||
case VIDEO_PALETTE_GREY :
|
||||
pixFormat = PIX_FMT_GRAY8;
|
||||
break;
|
||||
case VIDEO_PALETTE_YUYV :
|
||||
case VIDEO_PALETTE_YUV422 :
|
||||
pixFormat = PIX_FMT_YUYV422;
|
||||
|
@ -270,12 +289,8 @@ short *LocalCamera::b_u_table;
|
|||
|
||||
LocalCamera *LocalCamera::last_camera = NULL;
|
||||
|
||||
LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, const std::string &p_method, int p_width, int p_height, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
|
||||
#if ZM_HAS_V4L2
|
||||
Camera( p_id, LOCAL_SRC, p_width, p_height, (p_palette==V4L2_PIX_FMT_GREY?1:3), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
#elif ZM_HAS_V4L1
|
||||
Camera( p_id, LOCAL_SRC, p_width, p_height, (p_palette==VIDEO_PALETTE_GREY?1:3), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
|
||||
#endif // ZM_HAS_V4L2
|
||||
LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, 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 ) :
|
||||
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 ),
|
||||
device( p_device ),
|
||||
channel( p_channel ),
|
||||
standard( p_standard ),
|
||||
|
@ -322,8 +337,128 @@ LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel,
|
|||
if ( width != last_camera->width || height != last_camera->height )
|
||||
Warning( "Different capture sizes defined for monitors sharing same device, results may be unpredictable or completely wrong" );
|
||||
}
|
||||
|
||||
/* The V4L1 API doesn't care about endianness, which is why RGB32 and RGB24 in V4L1 are actually BGR32 and BGR24 on little endian machines. */
|
||||
/* Check the endianness of the machine */
|
||||
uint32_t checkval = 0xAABBCCDD;
|
||||
int BigEndian;
|
||||
if(*(unsigned char*)&checkval == 0xDD)
|
||||
BigEndian = 0;
|
||||
else if(*(unsigned char*)&checkval == 0xAA)
|
||||
BigEndian = 1;
|
||||
else {
|
||||
Error("Unable to detect the processor's endianness. Assuming little-endian.");
|
||||
BigEndian = 0;
|
||||
}
|
||||
|
||||
/* Set the correct colours, subpixel order and ffmpeg image format based on colours, palette and endianness */
|
||||
#if ZM_HAS_V4L2
|
||||
if ( v4l_version == 2 ) {
|
||||
switch( palette )
|
||||
{
|
||||
case V4L2_PIX_FMT_RGB32 :
|
||||
colours = 4;
|
||||
/* Not sure whats the correct format here, Some say ARGB, some say RGBA. */
|
||||
subpixelorder = ZM_SUBPIX_ORDER_ARGB;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_ARGB;
|
||||
#endif
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR32 :
|
||||
colours = 4;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_BGRA;
|
||||
#endif
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB24 :
|
||||
colours = 3;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_RGB24;
|
||||
#endif
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR24 :
|
||||
colours = 3;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_BGR24;
|
||||
#endif
|
||||
break;
|
||||
case V4L2_PIX_FMT_GREY :
|
||||
colours = 1;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE; /* Not needed but just in case */
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_GRAY8;
|
||||
#endif
|
||||
break;
|
||||
default :
|
||||
/* Use RGB24 for formas other than grayscale and RGB32\BGR32 and use RGB subpixel order */
|
||||
colours = 3;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_RGB24;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
if ( v4l_version == 1) {
|
||||
switch( palette )
|
||||
{
|
||||
case VIDEO_PALETTE_RGB32 :
|
||||
colours = 4;
|
||||
if(BigEndian) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_RGBA;
|
||||
#endif
|
||||
} else {
|
||||
/* TODO: Verify that RGB32 in V4L1 on little-endian is BGRA and not ABGR */
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_BGRA; // Or should it be ABGR?
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
colours = 3;
|
||||
if(BigEndian) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_RGB24;
|
||||
#endif
|
||||
} else {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_BGR24;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case VIDEO_PALETTE_GREY :
|
||||
colours = 3;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_GRAY8;
|
||||
#endif
|
||||
break;
|
||||
default :
|
||||
/* Use RGB24 for formas other than grayscale and RGB32\BGR32 and use RGB subpixel order */
|
||||
colours = 3;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = PIX_FMT_RGB24;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // ZM_HAS_V4L1
|
||||
|
||||
/* Fix the image size to be correct, based on the colours */
|
||||
imagesize = pixels * colours;
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
imagePixFormat = (colours==1)?PIX_FMT_GRAY8:PIX_FMT_RGB24;
|
||||
capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette );
|
||||
#endif // HAVE_LIBSWSCALE
|
||||
}
|
||||
|
@ -404,8 +539,6 @@ void LocalCamera::Initialise()
|
|||
{
|
||||
Warning( "Failed to set V4L2 field to %d, falling back to auto", config.v4l2_capture_fields );
|
||||
v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 )
|
||||
Fatal( "Failed to set video format: %s", strerror(errno) );
|
||||
}
|
||||
}
|
||||
if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 )
|
||||
|
@ -550,6 +683,16 @@ void LocalCamera::Initialise()
|
|||
|
||||
switch (vid_pic.palette = palette)
|
||||
{
|
||||
case VIDEO_PALETTE_RGB32 :
|
||||
{
|
||||
vid_pic.depth = 32;
|
||||
break;
|
||||
}
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
{
|
||||
vid_pic.depth = 24;
|
||||
break;
|
||||
}
|
||||
case VIDEO_PALETTE_GREY :
|
||||
{
|
||||
vid_pic.depth = 8;
|
||||
|
@ -560,15 +703,11 @@ void LocalCamera::Initialise()
|
|||
case VIDEO_PALETTE_YUV422 :
|
||||
case VIDEO_PALETTE_YUV420P :
|
||||
case VIDEO_PALETTE_YUV422P :
|
||||
default:
|
||||
{
|
||||
vid_pic.depth = 16;
|
||||
break;
|
||||
}
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
{
|
||||
vid_pic.depth = 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( brightness >= 0 ) vid_pic.brightness = brightness;
|
||||
|
@ -964,7 +1103,8 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
else
|
||||
sprintf( output, "error%d\n", errno );
|
||||
|
||||
return( false );
|
||||
/* Crop detection failure is not fatal and cropping is not used anyway, so no reason not to continue */
|
||||
/* return( false ); */
|
||||
}
|
||||
else if ( verbose )
|
||||
{
|
||||
|
@ -1081,6 +1221,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
if ( version == 1 )
|
||||
{
|
||||
struct video_capability vid_cap;
|
||||
memset( &vid_cap, 0, sizeof(video_capability) );
|
||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
|
||||
{
|
||||
Error( "Failed to get video capabilities: %s", strerror(errno) );
|
||||
|
@ -1130,6 +1271,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
|
||||
struct video_window vid_win;
|
||||
memset( &vid_win, 0, sizeof(video_window) );
|
||||
if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 )
|
||||
{
|
||||
Error( "Failed to get window attributes: %s", strerror(errno) );
|
||||
|
@ -1156,6 +1298,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_cap, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 )
|
||||
{
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
|
@ -1209,6 +1352,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
for ( int chan = 0; chan < vid_cap.channels; chan++ )
|
||||
{
|
||||
struct video_channel vid_src;
|
||||
memset( &vid_src, 0, sizeof(video_channel) );
|
||||
vid_src.channel = chan;
|
||||
if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 )
|
||||
{
|
||||
|
@ -1300,6 +1444,7 @@ int LocalCamera::Brightness( int p_brightness )
|
|||
if ( v4l_version == 1 )
|
||||
{
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_pic, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
||||
{
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
|
@ -1358,6 +1503,7 @@ int LocalCamera::Hue( int p_hue )
|
|||
if ( v4l_version == 1 )
|
||||
{
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_pic, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
||||
{
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
|
@ -1416,6 +1562,7 @@ int LocalCamera::Colour( int p_colour )
|
|||
if ( v4l_version == 1 )
|
||||
{
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_pic, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
||||
{
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
|
@ -1474,6 +1621,7 @@ int LocalCamera::Contrast( int p_contrast )
|
|||
if ( v4l_version == 1 )
|
||||
{
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_pic, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
||||
{
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
|
@ -1554,7 +1702,7 @@ int LocalCamera::Capture( Image &image )
|
|||
{
|
||||
Debug( 3, "Capturing" );
|
||||
|
||||
static unsigned char *buffer = 0;
|
||||
uint8_t* buffer = NULL;
|
||||
|
||||
int captures_per_frame = 1;
|
||||
if ( channel_count > 1 )
|
||||
|
@ -1641,31 +1789,45 @@ int LocalCamera::Capture( Image &image )
|
|||
#if HAVE_LIBSWSCALE
|
||||
Debug( 3, "Doing format conversion" );
|
||||
|
||||
static struct SwsContext *imgConversionContext = 0;
|
||||
static struct SwsContext *imgConversionContext = NULL;
|
||||
static AVFrame *tmpPicture = NULL;
|
||||
|
||||
static int pSize = ZM_MAX_IMAGE_SIZE;
|
||||
uint8_t* swscale_buffer = NULL;
|
||||
if ( imagePixFormat != capturePixFormat || captureWidth != width || captureHeight != height )
|
||||
{
|
||||
if ( !imgConversionContext )
|
||||
{
|
||||
#ifdef ZM_HAS_SSE2
|
||||
imgConversionContext = sws_getCachedContext( NULL, captureWidth, captureHeight, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL );
|
||||
#else
|
||||
imgConversionContext = sws_getCachedContext( NULL, captureWidth, captureHeight, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
|
||||
#endif
|
||||
if ( !imgConversionContext )
|
||||
Fatal( "Unable to initialise image scaling context" );
|
||||
|
||||
tmpPicture = avcodec_alloc_frame();
|
||||
if ( !tmpPicture )
|
||||
Fatal( "Could not allocate temporary picture" );
|
||||
int pictureSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
uint8_t *tmpPictureBuf = (uint8_t *)av_malloc(pictureSize);
|
||||
if (!tmpPictureBuf)
|
||||
Fatal( "Could not allocate temporary picture buffer" );
|
||||
avpicture_fill( (AVPicture *)tmpPicture, tmpPictureBuf, imagePixFormat, width, height );
|
||||
pSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
}
|
||||
/* Write the output image directly into the shared memory */
|
||||
swscale_buffer = image.WriteBuffer(width,height,colours,subpixelorder);
|
||||
if(swscale_buffer == NULL) {
|
||||
Error("Failed requesting writeable buffer for swscale conversion for the captured image.");
|
||||
return (-1);
|
||||
}
|
||||
avpicture_fill( (AVPicture *)tmpPicture, swscale_buffer, imagePixFormat, width, height );
|
||||
sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
|
||||
|
||||
buffer = tmpPicture->data[0];
|
||||
}
|
||||
#else // HAVE_LIBSWSCALE
|
||||
static unsigned char temp_buffer[ZM_MAX_IMAGE_SIZE];
|
||||
uint8_t* directbuffer = image.WriteBuffer(width,height,colours,subpixelorder);
|
||||
if(directbuffer == NULL) {
|
||||
Error("Failed requesting writeable buffer for the captured image.");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
switch( palette )
|
||||
{
|
||||
#if ZM_HAS_V4L1
|
||||
|
@ -1679,7 +1841,7 @@ int LocalCamera::Capture( Image &image )
|
|||
static char u_plane[ZM_MAX_IMAGE_DIM];
|
||||
static char v_plane[ZM_MAX_IMAGE_DIM];
|
||||
|
||||
unsigned char *rgb_ptr = temp_buffer;
|
||||
unsigned char *rgb_ptr = directbuffer;
|
||||
unsigned char *y_ptr = y_plane;
|
||||
char *u1_ptr = u_plane;
|
||||
char *u2_ptr = u_plane+width;
|
||||
|
@ -1742,7 +1904,7 @@ int LocalCamera::Capture( Image &image )
|
|||
*rgb_ptr++ = g<0?0:(g>255?255:g);
|
||||
*rgb_ptr++ = b<0?0:(b>255?255:b);
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
buffer = directbuffer;
|
||||
break;
|
||||
}
|
||||
#if ZM_HAS_V4L1
|
||||
|
@ -1756,7 +1918,7 @@ int LocalCamera::Capture( Image &image )
|
|||
static char u_plane[ZM_MAX_IMAGE_DIM];
|
||||
static char v_plane[ZM_MAX_IMAGE_DIM];
|
||||
|
||||
unsigned char *rgb_ptr = temp_buffer;
|
||||
unsigned char *rgb_ptr = directbuffer;
|
||||
unsigned char *y_ptr = y_plane;
|
||||
char *u1_ptr = u_plane;
|
||||
char *v1_ptr = v_plane;
|
||||
|
@ -1804,7 +1966,7 @@ int LocalCamera::Capture( Image &image )
|
|||
*rgb_ptr++ = g<0?0:(g>255?255:g);
|
||||
*rgb_ptr++ = b<0?0:(b>255?255:b);
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
buffer = directbuffer;
|
||||
break;
|
||||
}
|
||||
#if ZM_HAS_V4L1
|
||||
|
@ -1817,7 +1979,7 @@ int LocalCamera::Capture( Image &image )
|
|||
{
|
||||
int size = width*height*2;
|
||||
unsigned char *s_ptr = buffer;
|
||||
unsigned char *d_ptr = temp_buffer;
|
||||
unsigned char *d_ptr = directbuffer;
|
||||
|
||||
int y1,y2,u,v;
|
||||
int r,g,b;
|
||||
|
@ -1844,7 +2006,7 @@ int LocalCamera::Capture( Image &image )
|
|||
*d_ptr++ = g<0?0:(g>255?255:g);
|
||||
*d_ptr++ = b<0?0:(b>255?255:b);
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
buffer = directbuffer;
|
||||
break;
|
||||
}
|
||||
#if ZM_HAS_V4L1
|
||||
|
@ -1857,7 +2019,7 @@ int LocalCamera::Capture( Image &image )
|
|||
int size = width*height*2;
|
||||
unsigned char r,g,b;
|
||||
unsigned char *s_ptr = buffer;
|
||||
unsigned char *d_ptr = temp_buffer;
|
||||
unsigned char *d_ptr = directbuffer;
|
||||
for ( int i = 0; i < size; i += 2 )
|
||||
{
|
||||
b = ((*s_ptr)<<3)&0xf8;
|
||||
|
@ -1869,7 +2031,7 @@ int LocalCamera::Capture( Image &image )
|
|||
*d_ptr++ = b;
|
||||
s_ptr += 2;
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
buffer = directbuffer;
|
||||
break;
|
||||
}
|
||||
#if ZM_HAS_V4L1
|
||||
|
@ -1882,7 +2044,7 @@ int LocalCamera::Capture( Image &image )
|
|||
int size = width*height*2;
|
||||
unsigned char r,g,b;
|
||||
unsigned char *s_ptr = buffer;
|
||||
unsigned char *d_ptr = temp_buffer;
|
||||
unsigned char *d_ptr = directbuffer;
|
||||
for ( int i = 0; i < size; i += 2 )
|
||||
{
|
||||
b = ((*s_ptr)<<3)&0xf8;
|
||||
|
@ -1894,46 +2056,9 @@ int LocalCamera::Capture( Image &image )
|
|||
*d_ptr++ = b;
|
||||
s_ptr += 2;
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
buffer = directbuffer;
|
||||
break;
|
||||
}
|
||||
#if ZM_HAS_V4L1
|
||||
case VIDEO_PALETTE_RGB24 :
|
||||
{
|
||||
if ( config.local_bgr_invert )
|
||||
{
|
||||
int size = width*height*3;
|
||||
unsigned char *s_ptr = buffer;
|
||||
unsigned char *d_ptr = temp_buffer;
|
||||
for ( int i = 0; i < size; i += 3 )
|
||||
{
|
||||
*d_ptr++ = *(s_ptr+2);
|
||||
*d_ptr++ = *(s_ptr+1);
|
||||
*d_ptr++ = *s_ptr;
|
||||
s_ptr += 3;
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // ZM_HAS_V4L1
|
||||
#if ZM_HAS_V4L2
|
||||
case V4L2_PIX_FMT_BGR24 :
|
||||
{
|
||||
int size = width*height*3;
|
||||
unsigned char *s_ptr = buffer;
|
||||
unsigned char *d_ptr = temp_buffer;
|
||||
for ( int i = 0; i < size; i += 3 )
|
||||
{
|
||||
*d_ptr++ = *(s_ptr+2);
|
||||
*d_ptr++ = *(s_ptr+1);
|
||||
*d_ptr++ = *s_ptr;
|
||||
s_ptr += 3;
|
||||
}
|
||||
buffer = temp_buffer;
|
||||
break;
|
||||
}
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
case VIDEO_PALETTE_GREY :
|
||||
#endif // ZM_HAS_V4L1
|
||||
|
@ -1959,7 +2084,21 @@ int LocalCamera::Capture( Image &image )
|
|||
}
|
||||
|
||||
Debug( 3, "Assigning image" );
|
||||
image.Assign( width, height, colours, buffer );
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(swscale_buffer)
|
||||
/* A swsscale conversion was peformed with the output being stored directly into the shared memory */
|
||||
image.AssignDirect( width, height, colours, subpixelorder, buffer, imagesize, ZM_BUFTYPE_DONTFREE);
|
||||
else
|
||||
/* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
|
||||
#else
|
||||
if(directbuffer == buffer)
|
||||
/* A conversion was performed with the output being stored directly into the shared memory */
|
||||
image.AssignDirect( width, height, colours, subpixelorder, buffer, imagesize, ZM_BUFTYPE_DONTFREE);
|
||||
else
|
||||
/* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ protected:
|
|||
static LocalCamera *last_camera;
|
||||
|
||||
public:
|
||||
LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, const std::string &p_method, int p_width, int p_height, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture );
|
||||
LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, 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 );
|
||||
~LocalCamera();
|
||||
|
||||
void Initialise();
|
||||
|
|
|
@ -20,6 +20,37 @@
|
|||
#ifndef ZM_MEM_UTILS_H
|
||||
#define ZM_MEM_UTILS_H
|
||||
|
||||
|
||||
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
|
||||
uint8_t* alloc;
|
||||
uint8_t* retptr;
|
||||
#if HAVE_POSIX_MEMALIGN
|
||||
if(posix_memalign(&alloc,reqalignment,reqsize) != 0)
|
||||
return NULL;
|
||||
#else
|
||||
retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*));
|
||||
|
||||
if(retptr == NULL)
|
||||
return NULL;
|
||||
|
||||
if((retptr % reqalignment) != 0)
|
||||
alloc = retptr + (reqalignment - (retptr % reqalignment));
|
||||
|
||||
/* Store a pointer before to the start of the block, just before returned aligned memory */
|
||||
*(alloc - sizeof(void*)) = retptr;
|
||||
#endif
|
||||
return alloc;
|
||||
}
|
||||
|
||||
inline void zm_freealigned(void* ptr) {
|
||||
#if HAVE_POSIX_MEMALIGN
|
||||
free(ptr);
|
||||
#else
|
||||
/* Start of block is stored before the block if it was allocated by zm_mallocaligned */
|
||||
free((void*)*((uint8_t*)ptr - sizeof(void*)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline char *mempbrk( register const char *s, const char *accept, size_t limit )
|
||||
{
|
||||
if ( limit <= 0 || !s || !accept || !*accept )
|
||||
|
|
|
@ -285,8 +285,8 @@ Monitor::Monitor(
|
|||
ref_blend_perc( p_ref_blend_perc ),
|
||||
track_motion( p_track_motion ),
|
||||
signal_check_colour( p_signal_check_colour ),
|
||||
image( width, height, p_camera->Colours() ),
|
||||
ref_image( width, height, p_camera->Colours() ),
|
||||
delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ),
|
||||
ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ),
|
||||
purpose( p_purpose ),
|
||||
camera( p_camera ),
|
||||
n_zones( p_n_zones ),
|
||||
|
@ -342,7 +342,8 @@ Monitor::Monitor(
|
|||
mem_size = sizeof(SharedData)
|
||||
+ sizeof(TriggerData)
|
||||
+ (image_buffer_count*sizeof(struct timeval))
|
||||
+ (image_buffer_count*camera->ImageSize());
|
||||
+ (image_buffer_count*camera->ImageSize())
|
||||
+ 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */
|
||||
|
||||
Debug( 1, "mem.size=%d", mem_size );
|
||||
#if ZM_MEM_MAPPED
|
||||
|
@ -393,6 +394,11 @@ Monitor::Monitor(
|
|||
struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData));
|
||||
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
|
||||
|
||||
if((shared_images % 16) != 0) {
|
||||
/* Align images buffer to nearest 16 byte boundary */
|
||||
shared_images += (16 - (shared_images % 16));
|
||||
}
|
||||
|
||||
if ( purpose == CAPTURE )
|
||||
{
|
||||
memset( mem_ptr, 0, mem_size );
|
||||
|
@ -444,7 +450,8 @@ Monitor::Monitor(
|
|||
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(), &(shared_images[i*camera->ImageSize()]) );
|
||||
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 ( !n_zones )
|
||||
{
|
||||
|
@ -503,7 +510,7 @@ Monitor::Monitor(
|
|||
Warning( "Waiting for capture daemon" );
|
||||
sleep( 1 );
|
||||
}
|
||||
ref_image.Assign( width, height, camera->Colours(), image_buffer[shared_data->last_write_index].image->Buffer() );
|
||||
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer());
|
||||
|
||||
n_linked_monitors = 0;
|
||||
linked_monitors = 0;
|
||||
|
@ -997,10 +1004,14 @@ void Monitor::DumpImage( Image *dump_image ) const
|
|||
bool Monitor::CheckSignal( const Image *image )
|
||||
{
|
||||
static bool static_undef = true;
|
||||
/* RGB24 colors */
|
||||
static unsigned char red_val;
|
||||
static unsigned char green_val;
|
||||
static unsigned char blue_val;
|
||||
|
||||
static Rgb color_val; /* RGB32 color */
|
||||
static uint8_t grayscale_val; /* 8bit grayscale color */
|
||||
|
||||
if ( config.signal_check_points > 0 )
|
||||
{
|
||||
if ( static_undef )
|
||||
|
@ -1009,9 +1020,11 @@ bool Monitor::CheckSignal( const Image *image )
|
|||
red_val = RGB_RED_VAL(signal_check_colour);
|
||||
green_val = RGB_GREEN_VAL(signal_check_colour);
|
||||
blue_val = RGB_BLUE_VAL(signal_check_colour);
|
||||
color_val = RGB_ZEROALPHA(signal_check_colour); /* Clear alpha byte */
|
||||
grayscale_val = 0x000000ffu & signal_check_colour; /* Clear all bytes but lowest byte */
|
||||
}
|
||||
|
||||
const unsigned char *buffer = image->Buffer();
|
||||
const uint8_t *buffer = image->Buffer();
|
||||
int pixels = image->Pixels();
|
||||
int width = image->Width();
|
||||
int colours = image->Colours();
|
||||
|
@ -1028,11 +1041,21 @@ bool Monitor::CheckSignal( const Image *image )
|
|||
if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width )
|
||||
break;
|
||||
}
|
||||
const unsigned char *ptr = buffer+(index*colours);
|
||||
|
||||
if(colours == 1) {
|
||||
if ( *(buffer+index) != grayscale_val )
|
||||
return true;
|
||||
|
||||
} else if(colours == 3) {
|
||||
const uint8_t *ptr = buffer+(index*colours);
|
||||
if ( (RED(ptr) != red_val) || (GREEN(ptr) != green_val) || (BLUE(ptr) != blue_val) )
|
||||
{
|
||||
return( true );
|
||||
return true;
|
||||
|
||||
} else if(colours == 4) {
|
||||
if ( RGB_ZEROALPHA(*(((const Rgb*)buffer)+index)) != color_val )
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
|
@ -1733,11 +1756,11 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
|
|||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
if ( !device[0] )
|
||||
{
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) );
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
|
||||
}
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
|
@ -1772,6 +1795,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
|
|||
|
||||
int width = atoi(dbrow[col]); col++;
|
||||
int height = atoi(dbrow[col]); col++;
|
||||
int colours = atoi(dbrow[col]); col++;
|
||||
int palette = atoi(dbrow[col]); col++;
|
||||
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
|
@ -1816,6 +1840,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
|
|||
method,
|
||||
cam_width,
|
||||
cam_height,
|
||||
colours,
|
||||
palette,
|
||||
brightness,
|
||||
contrast,
|
||||
|
@ -1873,11 +1898,11 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
if ( !protocol )
|
||||
{
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) );
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path );
|
||||
}
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
|
@ -1913,6 +1938,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
|
||||
int width = atoi(dbrow[col]); col++;
|
||||
int height = atoi(dbrow[col]); col++;
|
||||
int colours = atoi(dbrow[col]); col++;
|
||||
int palette = atoi(dbrow[col]); col++;
|
||||
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
|
@ -1954,7 +1980,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
path, // Path
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -1973,7 +1999,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
path, // Path
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2035,11 +2061,11 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
if ( !file[0] )
|
||||
{
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) );
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file );
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file );
|
||||
}
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
|
@ -2071,6 +2097,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
|
||||
int width = atoi(dbrow[col]); col++;
|
||||
int height = atoi(dbrow[col]); col++;
|
||||
int colours = atoi(dbrow[col]); col++;
|
||||
int palette = atoi(dbrow[col]); col++;
|
||||
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
|
@ -2106,7 +2133,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
path, // File
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2163,11 +2190,11 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
if ( !file[0] )
|
||||
{
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
|
||||
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file );
|
||||
}
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
|
@ -2199,6 +2226,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
|
||||
int width = atoi(dbrow[col]); col++;
|
||||
int height = atoi(dbrow[col]); col++;
|
||||
int colours = atoi(dbrow[col]); col++;
|
||||
int palette = atoi(dbrow[col]); col++;
|
||||
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
|
@ -2234,7 +2262,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
path, // File
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2289,7 +2317,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
||||
{
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id );
|
||||
snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id );
|
||||
if ( mysql_query( &dbconn, sql ) )
|
||||
{
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
|
@ -2328,6 +2356,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
|
||||
int width = atoi(dbrow[col]); col++;
|
||||
int height = atoi(dbrow[col]); col++;
|
||||
int colours = atoi(dbrow[col]); col++;
|
||||
int palette = atoi(dbrow[col]); col++;
|
||||
Orientation orientation = (Orientation)atoi(dbrow[col]); col++;
|
||||
int brightness = atoi(dbrow[col]); col++;
|
||||
|
@ -2375,6 +2404,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
method,
|
||||
cam_width,
|
||||
cam_height,
|
||||
colours,
|
||||
palette,
|
||||
brightness,
|
||||
contrast,
|
||||
|
@ -2398,7 +2428,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
path.c_str(),
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2417,7 +2447,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
path.c_str(),
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2440,7 +2470,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
path.c_str(),
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2456,7 +2486,7 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
path.c_str(),
|
||||
cam_width,
|
||||
cam_height,
|
||||
palette,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
|
@ -2521,12 +2551,17 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose )
|
|||
|
||||
int Monitor::Capture()
|
||||
{
|
||||
int captureResult = camera->Capture( image );
|
||||
if ( captureResult == 1 )
|
||||
int index = image_count%image_buffer_count;
|
||||
Image* capture_image = image_buffer[index].image;
|
||||
|
||||
/* Capture directly into image buffer, avoiding the need to memcpy() */
|
||||
int captureResult = camera->Capture(*capture_image);
|
||||
|
||||
if ( captureResult != 0 )
|
||||
{
|
||||
// Unable to capture image for temporary reason
|
||||
// Fake a signal loss image
|
||||
image.Fill( signal_check_colour );
|
||||
capture_image->Fill( signal_check_colour );
|
||||
captureResult = 0;
|
||||
}
|
||||
if ( captureResult == 0 )
|
||||
|
@ -2544,25 +2579,25 @@ int Monitor::Capture()
|
|||
case ROTATE_180 :
|
||||
case ROTATE_270 :
|
||||
{
|
||||
image.Rotate( (orientation-1)*90 );
|
||||
capture_image->Rotate( (orientation-1)*90 );
|
||||
break;
|
||||
}
|
||||
case FLIP_HORI :
|
||||
case FLIP_VERT :
|
||||
{
|
||||
image.Flip( orientation==FLIP_HORI );
|
||||
capture_image->Flip( orientation==FLIP_HORI );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( image.Size() != camera->ImageSize() )
|
||||
if ( capture_image->Size() != camera->ImageSize() )
|
||||
{
|
||||
Error( "Captured image does not match expected size, check width, height and colour depth" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
int index = image_count%image_buffer_count;
|
||||
|
||||
if ( (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 );
|
||||
|
@ -2579,11 +2614,9 @@ int Monitor::Capture()
|
|||
gettimeofday( image_buffer[index].timestamp, NULL );
|
||||
if ( config.timestamp_on_capture )
|
||||
{
|
||||
TimestampImage( &image, image_buffer[index].timestamp );
|
||||
TimestampImage( capture_image, image_buffer[index].timestamp );
|
||||
}
|
||||
image_buffer[index].image->CopyBuffer( image );
|
||||
|
||||
shared_data->signal = CheckSignal( &image );
|
||||
shared_data->signal = CheckSignal(capture_image);
|
||||
shared_data->last_write_index = index;
|
||||
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
|
||||
|
||||
|
@ -2706,7 +2739,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
{
|
||||
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id );
|
||||
}
|
||||
delta_image->WriteJpeg( diag_path );
|
||||
delta_image.WriteJpeg( diag_path );
|
||||
}
|
||||
|
||||
// Blank out all exclusion zones
|
||||
|
@ -2719,7 +2752,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Blanking inactive zone %s", zone->Label() );
|
||||
delta_image->Fill( RGB_BLACK, zone->GetPolygon() );
|
||||
delta_image.Fill( RGB_BLACK, zone->GetPolygon() );
|
||||
}
|
||||
|
||||
// Check preclusive zones first
|
||||
|
@ -2731,7 +2764,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking preclusive zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( delta_image ) )
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
|
@ -2760,7 +2793,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking active zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( delta_image ) )
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
|
@ -2788,7 +2821,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking inclusive zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( delta_image ) )
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
|
@ -2817,7 +2850,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
continue;
|
||||
}
|
||||
Debug( 3, "Checking exclusive zone %s", zone->Label() );
|
||||
if ( zone->CheckAlarms( delta_image ) )
|
||||
if ( zone->CheckAlarms( &delta_image ) )
|
||||
{
|
||||
alarm = true;
|
||||
score += zone->Score();
|
||||
|
@ -2841,7 +2874,6 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
|
|||
shared_data->alarm_x = shared_data->alarm_y = -1;
|
||||
}
|
||||
|
||||
delete delta_image;
|
||||
// This is a small and innocent hack to prevent scores of 0 being returned in alarm state
|
||||
return( score?score:alarm );
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ protected:
|
|||
time_t last_write_time;
|
||||
time_t last_read_time;
|
||||
int last_event;
|
||||
int action;
|
||||
unsigned int action;
|
||||
int brightness;
|
||||
int hue;
|
||||
int colour;
|
||||
|
@ -210,7 +210,7 @@ protected:
|
|||
Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected
|
||||
|
||||
double fps;
|
||||
Image image;
|
||||
Image delta_image;
|
||||
Image ref_image;
|
||||
|
||||
Purpose purpose; // What this monitor has been created to do
|
||||
|
@ -301,6 +301,8 @@ public:
|
|||
unsigned int Width() const { return( width ); }
|
||||
unsigned int Height() const { return( height ); }
|
||||
unsigned int Colours() const { return( camera->Colours() ); }
|
||||
unsigned int SubpixelOrder const { return( camera->SubpixelOrder() ); }
|
||||
|
||||
|
||||
State GetState() const;
|
||||
int GetImage( int index=-1, int scale=100 ) const;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
#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_palette, 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_palette, 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 ) :
|
||||
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 ),
|
||||
protocol( p_protocol ),
|
||||
host( p_host ),
|
||||
port( p_port ),
|
||||
|
|
119
src/zm_rgb.h
119
src/zm_rgb.h
|
@ -20,11 +20,7 @@
|
|||
#ifndef ZM_RGB_H
|
||||
#define ZM_RGB_H
|
||||
|
||||
typedef unsigned int Rgb; // RGB colour type
|
||||
|
||||
#define RED(ptr) (*(ptr))
|
||||
#define GREEN(ptr) (*(ptr+1))
|
||||
#define BLUE(ptr) (*(ptr+2))
|
||||
typedef uint32_t Rgb; // RGB colour type
|
||||
|
||||
#define WHITE 0xff
|
||||
#define WHITE_R 0xff
|
||||
|
@ -46,8 +42,115 @@ typedef unsigned int Rgb; // RGB colour type
|
|||
#define RGB_TRANSPARENT (0x01000000)
|
||||
|
||||
#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff)
|
||||
#define RGB_RED_VAL(v) (((v)>>16)&0xff)
|
||||
#define RGB_GREEN_VAL(v) (((v)>>8)&0xff)
|
||||
#define RGB_BLUE_VAL(v) ((v)&0xff)
|
||||
|
||||
/* RGB or RGBA macros */
|
||||
#define BLUE_VAL_RGBA(v) (((v)>>16)&0xff)
|
||||
#define GREEN_VAL_RGBA(v) (((v)>>8)&0xff)
|
||||
#define RED_VAL_RGBA(v) ((v)&0xff)
|
||||
#define ALPHA_VAL_RGBA(v) ((v)>>24)&0xff)
|
||||
#define RED_PTR_RGBA(ptr) (*((uint8_t*)ptr))
|
||||
#define GREEN_PTR_RGBA(ptr) (*((uint8_t*)ptr+1))
|
||||
#define BLUE_PTR_RGBA(ptr) (*((uint8_t*)ptr+2))
|
||||
#define ALPHA_PTR_RGBA(ptr) (*((uint8_t*)ptr+3))
|
||||
|
||||
/* BGR or BGRA */
|
||||
#define RED_VAL_BGRA(v) (((v)>>16)&0xff)
|
||||
#define GREEN_VAL_BGRA(v) (((v)>>8)&0xff)
|
||||
#define BLUE_VAL_BGRA(v) ((v)&0xff)
|
||||
#define ALPHA_VAL_BGRA(v) ((v)>>24)&0xff)
|
||||
#define RED_PTR_BGRA(ptr) (*((uint8_t*)ptr+2))
|
||||
#define GREEN_PTR_BGRA(ptr) (*((uint8_t*)ptr+1))
|
||||
#define BLUE_PTR_BGRA(ptr) (*((uint8_t*)ptr))
|
||||
#define ALPHA_PTR_BGRA(ptr) (*((uint8_t*)ptr+3))
|
||||
|
||||
/* ARGB */
|
||||
#define BLUE_VAL_ARGB(v) (((v)>>24)&0xff)
|
||||
#define GREEN_VAL_ARGB(v) (((v)>>16)&0xff)
|
||||
#define RED_VAL_ARGB(v) (((v)>>8)&0xff)
|
||||
#define ALPHA_VAL_ARGB(v) ((v)&0xff)
|
||||
#define RED_PTR_ARGB(ptr) (*((uint8_t*)ptr+1))
|
||||
#define GREEN_PTR_ARGB(ptr) (*((uint8_t*)ptr+2))
|
||||
#define BLUE_PTR_ARGB(ptr) (*((uint8_t*)ptr+3))
|
||||
#define ALPHA_PTR_ARGB(ptr) (*((uint8_t*)ptr))
|
||||
|
||||
/* ABGR */
|
||||
#define BLUE_VAL_ABGR(v) (((v)>>8)&0xff)
|
||||
#define GREEN_VAL_ABGR(v) (((v)>>16)&0xff)
|
||||
#define RED_VAL_ABGR(v) (((v)>>24)&0xff)
|
||||
#define ALPHA_VAL_ABGR(v) ((v)&0xff)
|
||||
#define RED_PTR_ABGR(ptr) (*((uint8_t*)ptr+3))
|
||||
#define GREEN_PTR_ABGR(ptr) (*((uint8_t*)ptr+2))
|
||||
#define BLUE_PTR_ABGR(ptr) (*((uint8_t*)ptr+1))
|
||||
#define ALPHA_PTR_ABGR(ptr) (*((uint8_t*)ptr))
|
||||
|
||||
|
||||
#define RGBA_BGRA_ZEROALPHA(v) ((v)&0x00ffffff))
|
||||
#define ARGB_ABGR_ZEROALPHA(v) ((v)&0xffffff00))
|
||||
|
||||
/* ITU-R BT.709: Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B) */
|
||||
/* ITU-R BT.601: Y = (0.299 * R) + (0.587 * G) + (0.114 * B) */
|
||||
/* The formulas below produce an almost identical result to the weighted algorithms from the ITU-R BT.601 standard and the newer ITU-R BT.709 standard, but a lot faster */
|
||||
// #define RGB_FASTLUM_SINGLE_ITU709(v) ((RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3)
|
||||
// #define RGB_FASTLUM_VALUES_ITU709(ra,ga,ba) (((ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga)+(ga))>>3)
|
||||
// #define RGB_FASTLUM_SINGLE_ITU601(v) ((RED(v)+RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3)
|
||||
// #define RGB_FASTLUM_VALUES_ITU601(ra,ga,ba) (((ra)+(ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga))>>3)
|
||||
|
||||
/* ZM colours */
|
||||
#define ZM_COLOUR_RGB32 4
|
||||
#define ZM_COLOUR_RGB24 3
|
||||
#define ZM_COLOUR_GRAY8 1
|
||||
|
||||
/* Subpixel ordering */
|
||||
/* Based on byte order naming. For example, for ARGB (on both little endian or big endian) byte+0 should be alpha, byte+1 should be red, and so on. */
|
||||
#define ZM_SUBPIX_ORDER_NONE 2
|
||||
#define ZM_SUBPIX_ORDER_RGB 6
|
||||
#define ZM_SUBPIX_ORDER_BGR 5
|
||||
#define ZM_SUBPIX_ORDER_BGRA 7
|
||||
#define ZM_SUBPIX_ORDER_RGBA 8
|
||||
#define ZM_SUBPIX_ORDER_ABGR 9
|
||||
#define ZM_SUBPIX_ORDER_ARGB 10
|
||||
|
||||
/* A macro to use default subpixel order for a specified colour. */
|
||||
/* for grayscale it will use NONE, for 3 colours it will use R,G,B, for 4 colours it will use R,G,B,A */
|
||||
#define ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(c) ((c)<<1)
|
||||
|
||||
/* Convert RGB colour value into BGR\ARGB\ABGR */
|
||||
inline Rgb rgb_convert(Rgb p_col, int p_subpixorder) {
|
||||
Rgb result;
|
||||
|
||||
switch(p_subpixorder) {
|
||||
|
||||
case ZM_SUBPIX_ORDER_BGR:
|
||||
case ZM_SUBPIX_ORDER_BGRA:
|
||||
{
|
||||
BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col);
|
||||
GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col);
|
||||
RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col);
|
||||
return result;
|
||||
}
|
||||
case ZM_SUBPIX_ORDER_ARGB:
|
||||
{
|
||||
BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col);
|
||||
GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col);
|
||||
RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col);
|
||||
return result;
|
||||
}
|
||||
case ZM_SUBPIX_ORDER_ABGR:
|
||||
{
|
||||
BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col);
|
||||
GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col);
|
||||
RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col);
|
||||
return result;
|
||||
}
|
||||
/* Grayscale */
|
||||
case ZM_SUBPIX_ORDER_NONE:
|
||||
{
|
||||
result = p_col & 0xff;
|
||||
}
|
||||
default:
|
||||
return p_col;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ZM_RGB_H
|
||||
|
|
|
@ -146,38 +146,38 @@ private:
|
|||
mutable Condition mCondition;
|
||||
|
||||
public:
|
||||
ThreadData() : mCondition( mMutex )
|
||||
__attribute__((used)) ThreadData() : mCondition( mMutex )
|
||||
{
|
||||
}
|
||||
ThreadData( T value ) : mValue( value ), mCondition( mMutex )
|
||||
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex )
|
||||
{
|
||||
}
|
||||
//~ThreadData() {}
|
||||
|
||||
operator T() const
|
||||
__attribute__((used)) operator T() const
|
||||
{
|
||||
return( getValue() );
|
||||
}
|
||||
const T operator=( const T value )
|
||||
__attribute__((used)) const T operator=( const T value )
|
||||
{
|
||||
return( setValue( value ) );
|
||||
}
|
||||
|
||||
const T getValueImmediate() const
|
||||
__attribute__((used)) const T getValueImmediate() const
|
||||
{
|
||||
return( mValue );
|
||||
}
|
||||
T setValueImmediate( const T value )
|
||||
__attribute__((used)) T setValueImmediate( const T value )
|
||||
{
|
||||
return( mValue = value );
|
||||
}
|
||||
const T getValue() const;
|
||||
T setValue( const T value );
|
||||
const T getUpdatedValue() const;
|
||||
const T getUpdatedValue( double secs ) const;
|
||||
const T getUpdatedValue( int secs ) const;
|
||||
void updateValueSignal( const T value );
|
||||
void updateValueBroadcast( const T value );
|
||||
__attribute__((used)) const T getValue() const;
|
||||
__attribute__((used)) T setValue( const T value );
|
||||
__attribute__((used)) const T getUpdatedValue() const;
|
||||
__attribute__((used)) const T getUpdatedValue( double secs ) const;
|
||||
__attribute__((used)) const T getUpdatedValue( int secs ) const;
|
||||
__attribute__((used)) void updateValueSignal( const T value );
|
||||
__attribute__((used)) void updateValueBroadcast( const T value );
|
||||
};
|
||||
|
||||
class Thread
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
|
||||
const std::string stringtf( const char *format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -147,3 +149,48 @@ const std::string base64Encode( const std::string &inString )
|
|||
}
|
||||
return( outString );
|
||||
}
|
||||
|
||||
/* Sets sse_version */
|
||||
void ssedetect() {
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
/* x86 or x86-64 processor */
|
||||
uint32_t r_edx, r_ecx;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov $0x1,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
: "=d" (r_edx), "=c" (r_ecx)
|
||||
:
|
||||
: "%eax", "%ebx"
|
||||
);
|
||||
|
||||
if (r_ecx & 0x00000100) {
|
||||
sseversion = 35; /* SSSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3.");
|
||||
} else if (r_ecx & 0x00000001) {
|
||||
sseversion = 30; /* SSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE3.");
|
||||
} else if (r_edx & 0x04000000) {
|
||||
sseversion = 20; /* SSE2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE2.");
|
||||
} else if (r_edx & 0x02000000) {
|
||||
sseversion = 10; /* SSE */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE.");
|
||||
} else {
|
||||
sseversion = 0;
|
||||
Debug(1,"Detected a x86\\x86-64 processor.");
|
||||
}
|
||||
|
||||
#else
|
||||
/* Non x86 or x86-64 processor, SSE2 is not available */
|
||||
Debug(1,"Detected a non x86\\x86-64 processor.");
|
||||
sseversion = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Aligned SSE2 memory copy. Useful for copying big things like image buffers in ZM */
|
||||
/* This requires source and target memory to be aligned on 16byte boundary, or a general protection fault will occur, therefore we check for unaligned memory */
|
||||
void sse2memcpy(unsigned char* dest, const unsigned char* src, const size_t bytes) {
|
||||
memcpy(dest,src,bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,4 +43,9 @@ inline int min( int a, int b )
|
|||
return( a<=b?a:b );
|
||||
}
|
||||
|
||||
void ssedetect();
|
||||
void sse2memcpy(unsigned char* dest, const unsigned char* src, const size_t bytes);
|
||||
|
||||
extern unsigned int sseversion;
|
||||
|
||||
#endif // ZM_UTILS_H
|
||||
|
|
|
@ -62,7 +62,7 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
|
|||
|
||||
overload_count = 0;
|
||||
|
||||
pg_image = new Image( monitor->Width(), monitor->Height(), 1 );
|
||||
pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE);
|
||||
pg_image->Fill( 0xff, polygon );
|
||||
pg_image->Outline( 0xff, polygon );
|
||||
pg_image->Crop( polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() );
|
||||
|
@ -662,11 +662,11 @@ bool Zone::CheckAlarms( const Image *delta_image )
|
|||
|
||||
if ( type == INCLUSIVE )
|
||||
{
|
||||
score /= 2;
|
||||
score <<= 1;
|
||||
}
|
||||
else if ( type == EXCLUSIVE )
|
||||
{
|
||||
score *= 2;
|
||||
score >>= 1;
|
||||
}
|
||||
|
||||
Debug( 5, "Adjusted score is %d", score );
|
||||
|
|
Loading…
Reference in New Issue