maybe fix memleak, maybe fix crash

This commit is contained in:
Isaac Connor 2017-08-10 15:44:20 -04:00
parent cc28af8ed2
commit 536ccc0cec
6 changed files with 92 additions and 96 deletions

View File

@ -271,12 +271,15 @@ int FfmpegCamera::OpenFfmpeg() {
}
// Set transport method as specified by method field, rtpUni is default
if ( Method() == "rtpMulti" ) {
const std::string method = Method();
if ( method == "rtpMulti" ) {
ret = av_dict_set(&opts, "rtsp_transport", "udp_multicast", 0);
} else if ( Method() == "rtpRtsp" ) {
} else if ( method == "rtpRtsp" ) {
ret = av_dict_set(&opts, "rtsp_transport", "tcp", 0);
} else if ( Method() == "rtpRtspHttp" ) {
} else if ( method == "rtpRtspHttp" ) {
ret = av_dict_set(&opts, "rtsp_transport", "http", 0);
} else {
Warning("Unknown method (%s)", method);
}
if ( ret < 0 ) {
@ -834,7 +837,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
return 0;
}
} else {
Debug(3, "Not recording audio because we don't have a bvideo keyframe yet");
Debug(3, "Not recording audio yet because we don't have a video keyframe yet");
}
} else {
Debug(4, "Not doing recording of audio packet" );
@ -848,7 +851,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
#else
Debug( 3, "Some other stream index %d", packet.stream_index );
#endif
}
} // end if is video or audio or something else
// the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version.
zm_av_packet_unref( &packet );

View File

@ -107,8 +107,7 @@ Image::Image( const char *filename ) {
text[0] = '\0';
}
Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer )
{
Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer ) {
if ( !initialised )
Initialise();
width = p_width;
@ -119,21 +118,17 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin
size = pixels*colours;
buffer = 0;
holdbuffer = 0;
if ( p_buffer )
{
if ( p_buffer ) {
allocation = size;
buffertype = ZM_BUFTYPE_DONTFREE;
buffer = p_buffer;
}
else
{
} else {
AllocImgBuffer(size);
}
text[0] = '\0';
}
Image::Image( const Image &p_image )
{
Image::Image( const Image &p_image ) {
if ( !initialised )
Initialise();
width = p_image.width;
@ -170,8 +165,7 @@ void Image::Deinitialise() {
delete readjpg_dcinfo;
readjpg_dcinfo = 0;
}
if ( decodejpg_dcinfo )
{
if ( decodejpg_dcinfo ) {
jpeg_destroy_decompress( decodejpg_dcinfo );
delete decodejpg_dcinfo;
decodejpg_dcinfo = 0;
@ -186,14 +180,13 @@ void Image::Deinitialise() {
}
}
void Image::Initialise()
{
void Image::Initialise() {
/* Assign the blend pointer to function */
if(config.fast_image_blends) {
if(config.cpu_extensions && sseversion >= 20) {
if ( config.fast_image_blends ) {
if ( config.cpu_extensions && sseversion >= 20 ) {
fptr_blend = &sse2_fastblend; /* SSE2 fast blend */
Debug(4,"Blend: Using SSE2 fast blend function");
} else if(config.cpu_extensions && neonversion >= 1) {
} else if ( config.cpu_extensions && neonversion >= 1 ) {
#if defined(__aarch64__)
fptr_blend = &neon64_armv8_fastblend; /* ARM Neon (AArch64) fast blend */
Debug(4,"Blend: Using ARM Neon (AArch64) fast blend function");
@ -236,8 +229,8 @@ void Image::Initialise()
(*fptr_blend)(blend1,blend2,blendres,128,12.0);
/* Compare results with expected results */
for(int i=0;i<128;i++) {
if(abs(blendexp[i] - blendres[i]) > 3) {
for ( int i=0; i < 128; i ++ ) {
if ( abs(blendexp[i] - blendres[i]) > 3 ) {
Panic("Blend function failed self-test: Results differ from the expected results. Column %u Expected %u Got %u",i,blendexp[i],blendres[i]);
}
}
@ -246,8 +239,8 @@ void Image::Initialise()
fptr_delta8_bgr = &std_delta8_bgr;
/* Assign the delta functions */
if(config.cpu_extensions) {
if(sseversion >= 35) {
if ( config.cpu_extensions ) {
if ( sseversion >= 35 ) {
/* SSSE3 available */
fptr_delta8_rgba = &ssse3_delta8_rgba;
fptr_delta8_bgra = &ssse3_delta8_bgra;
@ -255,7 +248,7 @@ void Image::Initialise()
fptr_delta8_abgr = &ssse3_delta8_abgr;
fptr_delta8_gray8 = &sse2_delta8_gray8;
Debug(4,"Delta: Using SSSE3 delta functions");
} else if(sseversion >= 20) {
} else if ( sseversion >= 20 ) {
/* SSE2 available */
fptr_delta8_rgba = &sse2_delta8_rgba;
fptr_delta8_bgra = &sse2_delta8_bgra;
@ -263,7 +256,7 @@ void Image::Initialise()
fptr_delta8_abgr = &sse2_delta8_abgr;
fptr_delta8_gray8 = &sse2_delta8_gray8;
Debug(4,"Delta: Using SSE2 delta functions");
} else if(neonversion >= 1) {
} else if ( neonversion >= 1 ) {
/* ARM Neon available */
#if defined(__aarch64__)
fptr_delta8_rgba = &neon64_armv8_delta8_rgba;
@ -329,8 +322,8 @@ void Image::Initialise()
(*fptr_delta8_gray8)(delta8_1,delta8_2,delta8_gray8_res,128);
/* Compare results with expected results */
for(int i=0;i<128;i++) {
if(abs(delta8_gray8_exp[i] - delta8_gray8_res[i]) > 7) {
for ( int i=0; i < 128; i++ ) {
if ( abs(delta8_gray8_exp[i] - delta8_gray8_res[i]) > 7 ) {
Panic("Delta grayscale function failed self-test: Results differ from the expected results. Column %u Expected %u Got %u",i,delta8_gray8_exp[i],delta8_gray8_res[i]);
}
}
@ -339,8 +332,8 @@ void Image::Initialise()
(*fptr_delta8_rgba)(delta8_1,delta8_2,delta8_rgba_res,32);
/* Compare results with expected results */
for(int i=0;i<32;i++) {
if(abs(delta8_rgba_exp[i] - delta8_rgba_res[i]) > 7) {
for ( int i=0; i < 32; i++ ) {
if ( abs(delta8_rgba_exp[i] - delta8_rgba_res[i]) > 7 ) {
Panic("Delta RGBA function failed self-test: Results differ from the expected results. Column %u Expected %u Got %u",i,delta8_rgba_exp[i],delta8_rgba_res[i]);
}
}
@ -359,7 +352,7 @@ void Image::Initialise()
#if defined(__i386__) && !defined(__x86_64__)
/* Use SSE2 aligned memory copy? */
if(config.cpu_extensions && sseversion >= 20) {
if ( config.cpu_extensions && sseversion >= 20 ) {
fptr_imgbufcpy = &sse2_aligned_memcpy;
Debug(4,"Image buffer copy: Using SSE2 aligned memcpy");
} else {
@ -425,24 +418,24 @@ void Image::Initialise()
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) {
unsigned int newsize;
if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) {
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("WriteBuffer called with unexpected colours: %d",p_colours);
return NULL;
}
if(!p_height || !p_width) {
if ( !p_height || !p_width ) {
Error("WriteBuffer called with invalid width or height: %d %d",p_width,p_height);
return NULL;
}
if(p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) {
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
newsize = (p_width * p_height) * p_colours;
if(buffer == NULL) {
if ( buffer == NULL ) {
AllocImgBuffer(newsize);
} else {
if(allocation < newsize) {
if(holdbuffer) {
if ( allocation < newsize ) {
if ( holdbuffer ) {
Error("Held buffer is undersized for requested buffer");
return NULL;
} else {
@ -467,30 +460,30 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
/* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */
void Image::AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype) {
if(new_buffer == NULL) {
if ( new_buffer == NULL ) {
Error("Attempt to directly assign buffer from a NULL pointer");
return;
}
if(!p_height || !p_width) {
if ( !p_height || !p_width ) {
Error("Attempt to directly assign buffer with invalid width or height: %d %d",p_width,p_height);
return;
}
if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) {
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to directly assign buffer with unexpected colours per pixel: %d",p_colours);
return;
}
unsigned int new_buffer_size = ((p_width*p_height)*p_colours);
if(buffer_size < new_buffer_size) {
if ( buffer_size < new_buffer_size ) {
Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",buffer_size, p_width, p_height, p_colours, new_buffer_size );
return;
}
if(holdbuffer && buffer) {
if(new_buffer_size > allocation) {
if ( holdbuffer && buffer ) {
if ( new_buffer_size > allocation ) {
Error("Held buffer is undersized for assigned buffer");
return;
} else {
@ -502,7 +495,7 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
/* Copy into the held buffer */
if(new_buffer != buffer)
if ( new_buffer != buffer )
(*fptr_imgbufcpy)(buffer, new_buffer, size);
/* Free the new buffer */
@ -529,35 +522,35 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
void Image::Assign(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) {
unsigned int new_size = (p_width * p_height) * p_colours;
if(new_buffer == NULL) {
if ( new_buffer == NULL ) {
Error("Attempt to assign buffer from a NULL pointer");
return;
}
if(buffer_size < new_size) {
if ( buffer_size < new_size ) {
Error("Attempt to assign buffer from an undersized buffer of size: %zu",buffer_size);
return;
}
if(!p_height || !p_width) {
if ( !p_height || !p_width ) {
Error("Attempt to assign buffer with invalid width or height: %d %d",p_width,p_height);
return;
}
if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) {
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to assign buffer with unexpected colours per pixel: %d",p_colours);
return;
}
if ( !buffer || p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) {
if ( !buffer || p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
if (holdbuffer && buffer) {
if (new_size > allocation) {
if ( holdbuffer && buffer ) {
if ( new_size > allocation ) {
Error("Held buffer is undersized for assigned buffer");
return;
}
} else {
if(new_size > allocation || !buffer) {
if ( new_size > allocation || !buffer ) {
DumpImgBuffer();
AllocImgBuffer(new_size);
}

View File

@ -55,23 +55,26 @@ extern imgbufcpy_fptr_t fptr_imgbufcpy;
/* Should be called from Image class functions */
inline static uint8_t* AllocBuffer(size_t p_bufsize) {
uint8_t* buffer = (uint8_t*)zm_mallocaligned(64,p_bufsize);
if(buffer == NULL)
if ( buffer == NULL )
Fatal("Memory allocation failed: %s",strerror(errno));
return buffer;
}
inline static void DumpBuffer(uint8_t* buffer, int buffertype) {
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;
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);
*/
} else {
Error( "Unknown buffer type in DumpBuffer(%d)", buffertype );
}
}
}
@ -80,27 +83,23 @@ inline static void DumpBuffer(uint8_t* buffer, int buffertype) {
// This is image class, and represents a frame captured from a
// camera in raw form.
//
class Image
{
class Image {
protected:
struct Edge
{
struct Edge {
int min_y;
int max_y;
double min_x;
double _1_m;
static int CompareYX( const void *p1, const void *p2 )
{
static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) );
else
return( int(e1->min_y - e2->min_y) );
}
static int CompareX( const void *p1, const void *p2 )
{
static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
return( int(e1->min_x - e2->min_x) );
}
@ -113,7 +112,7 @@ protected:
}
inline void AllocImgBuffer(size_t p_bufsize) {
if(buffer)
if ( buffer )
DumpImgBuffer();
buffer = AllocBuffer(p_bufsize);
@ -176,27 +175,24 @@ public:
inline void HoldBuffer(int tohold) { holdbuffer = tohold; }
inline void Empty() {
if(!holdbuffer)
DumpImgBuffer();
width = height = colours = size = pixels = subpixelorder = 0;
if ( !holdbuffer )
DumpImgBuffer();
width = height = colours = size = pixels = subpixelorder = 0;
}
void Assign( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size);
void Assign( const Image &image );
void AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype);
inline void CopyBuffer( const Image &image )
{
inline void CopyBuffer( const Image &image ) {
Assign(image);
}
inline Image &operator=( const Image &image )
{
inline Image &operator=( const Image &image ) {
Assign(image);
return *this;
}
inline Image &operator=( const unsigned char *new_buffer )
{
inline Image &operator=( const unsigned char *new_buffer ) {
(*fptr_imgbufcpy)(buffer, new_buffer, size);
return( *this );
}
@ -207,9 +203,9 @@ public:
bool ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder);
bool WriteJpeg ( const char *filename) const;
bool WriteJpeg ( const char *filename, int quality_override ) const;
bool WriteJpeg ( const char *filename, struct timeval timestamp ) const;
bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const;
bool WriteJpeg ( const char *filename, int quality_override ) const;
bool WriteJpeg ( const char *filename, struct timeval timestamp ) const;
bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const;
bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder);
bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const;
@ -232,7 +228,7 @@ public:
void Delta( const Image &image, Image* targetimage) const;
const Coord centreCoord( const char *text ) const;
void MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour=0x00222222 );
void MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour=0x00222222 );
void Annotate( const char *p_text, const Coord &coord, const unsigned int size=1, const Rgb fg_colour=RGB_WHITE, const Rgb bg_colour=RGB_BLACK );
Image *HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits=0 );
//Image *HighlightEdges( Rgb colour, const Polygon &polygon );

View File

@ -112,6 +112,9 @@ Logger::Logger() :
Logger::~Logger() {
terminate();
for ( StringMap::iterator itr = smCodes.begin(); itr != smCodes.end(); itr ++ ) {
smCodes.erase( itr );
}
}
void Logger::initialise( const std::string &id, const Options &options ) {

View File

@ -30,8 +30,7 @@
#endif // HAVE_SYS_SYSCALL_H
#include <mysql/mysql.h>
class Logger
{
class Logger {
public:
enum {
NOOPT=-6,

View File

@ -63,24 +63,24 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
av_make_error_string(ret).c_str()
);
} else {
Debug(2, "Success allocating output context");
Debug(4, "Success allocating output format context");
}
//Couldn't deduce format from filename, trying from format name
if ( ! oc ) {
if ( !oc ) {
avformat_alloc_output_context2(&oc, NULL, format, filename);
if (!oc) {
if ( !oc ) {
Fatal("Could not create video storage stream %s as no output context"
" could not be assigned based on filename or format %s",
filename, format);
} else {
Debug(4, "Success alocateing output context");
}
} else {
Debug(2, "Success alocateing output context");
}
} // end if ! oc
AVDictionary *pmetadata = NULL;
int dsr = av_dict_set(&pmetadata, "title", "Zoneminder Security Recording", 0);
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
if ( dsr < 0 ) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
oc->metadata = pmetadata;
output_format = oc->oformat;
@ -348,7 +348,7 @@ VideoStore::~VideoStore(){
#endif
Debug(2, "writing flushed packet pts(%d) dts(%d) duration(%d)", pkt.pts, pkt.dts, pkt.duration);
pkt.pts = audio_next_pts;
pkt.dts = audio_next_dts;
pkt.dts = audio_next_dts;
if ( pkt.duration > 0 )
pkt.duration = av_rescale_q(pkt.duration, audio_output_context->time_base, audio_output_stream->time_base);
@ -377,12 +377,12 @@ VideoStore::~VideoStore(){
// What if we were only doing audio recording?
if ( video_output_stream ) {
avcodec_close(video_output_context);
av_free(video_output_context);
//av_free(video_output_context);
video_output_context = NULL;
}
if (audio_output_stream) {
avcodec_close(audio_output_context);
av_free(audio_output_context);
//av_free(audio_output_context);
audio_output_context = NULL;
#ifdef HAVE_LIBAVRESAMPLE
if ( resample_context ) {
@ -871,6 +871,8 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
zm_av_packet_unref(&opkt);
return 0;
}
av_frame_unref( input_frame );
av_frame_unref( output_frame );
#else
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
Error( "Could not encode frame (error '%s')",