some fixes

This commit is contained in:
Isaac Connor
2017-11-17 14:30:38 -05:00
33 changed files with 321 additions and 395 deletions

View File

@@ -45,6 +45,7 @@ Camera::Camera( unsigned int p_monitor_id, SourceType p_type, unsigned int p_wid
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0)) {
Fatal("Image size is not multiples of 12 and 64");
}
monitor = NULL;
}
Camera::~Camera() {

View File

@@ -761,10 +761,10 @@ void Select::clearTimeout()
void Select::calcMaxFd()
{
mMaxFd = -1;
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
if ( (*iter)->getMaxDesc() > mMaxFd )
mMaxFd = (*iter)->getMaxDesc();
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
if ( (*iter)->getMaxDesc() > mMaxFd )
mMaxFd = (*iter)->getMaxDesc();
}
@@ -839,12 +839,12 @@ int Select::wait()
mReadable.clear();
FD_ZERO(&rfds);
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
FD_SET((*iter)->getReadDesc(),&rfds);
mWriteable.clear();
FD_ZERO(&wfds);
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
FD_SET((*iter)->getWriteDesc(),&wfds);
int nFound = select( mMaxFd+1, &rfds, &wfds, NULL, selectTimeout );
@@ -858,10 +858,10 @@ int Select::wait()
}
else
{
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ )
for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); ++iter )
if ( FD_ISSET((*iter)->getReadDesc(),&rfds) )
mReadable.push_back( *iter );
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ )
for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); ++iter )
if ( FD_ISSET((*iter)->getWriteDesc(),&rfds) )
mWriteable.push_back( *iter );
}

View File

@@ -478,32 +478,24 @@ public:
}
public:
virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const
{
virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const {
ssize_t nBytes = ::sendto( mSd, msg, len, 0, addr?addr->getAddr():NULL, addr?addr->getAddrSize():0 );
if ( nBytes < 0 )
Debug( 1, "Sendto of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const
{
virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const {
ssize_t nBytes = 0;
if ( addr )
{
if ( addr ) {
struct sockaddr sockAddr;
socklen_t sockLen;
nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen );
if ( nBytes < 0 )
{
if ( nBytes < 0 ) {
Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) );
}
else if ( sockLen )
{
} else if ( sockLen ) {
addr = SockAddr::newSockAddr( sockAddr, sockLen );
}
}
else
{
} else {
nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 );
if ( nBytes < 0 )
Debug( 1, "Recvfrom of %d bytes max on sd %d (no address) failed: %s", len, mSd, strerror(errno) );

View File

@@ -520,19 +520,19 @@ int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow,
/* These functions call the functions in the class for the correct object */
size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->data_callback(buffer,size,nmemb,userdata);
}
size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) {
return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata);
return reinterpret_cast<cURLCamera*>(userdata)->header_callback(buffer,size,nmemb,userdata);
}
int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) {
return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
return reinterpret_cast<cURLCamera*>(userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow);
}
void* thread_func_dispatcher(void* object) {
return ((cURLCamera*)object)->thread_func();
return reinterpret_cast<cURLCamera*>(object)->thread_func();
}
#endif // HAVE_LIBCURL

View File

@@ -228,11 +228,11 @@ Event::~Event() {
void Event::createNotes( std::string &notes ) {
notes.clear();
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) {
for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); ++mapIter ) {
notes += mapIter->first;
notes += ": ";
const StringSet &stringSet = mapIter->second;
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) {
for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); ++setIter ) {
if ( setIter != stringSet.begin() )
notes += ", ";
notes += *setIter;
@@ -310,7 +310,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
noteSetMap = newNoteSetMap;
update = true;
} else {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); ++newNoteSetMapIter ) {
const std::string &newNoteGroup = newNoteSetMapIter->first;
const StringSet &newNoteSet = newNoteSetMapIter->second;
//Info( "Got %d new strings", newNoteSet.size() );
@@ -323,7 +323,7 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
} else {
StringSet &noteSet = noteSetMapIter->second;
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() );
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) {
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); ++newNoteSetIter ) {
const std::string &newNote = *newNoteSetIter;
StringSet::iterator noteSetIter = noteSet.find( newNote );
if ( noteSetIter == noteSet.end() ) {
@@ -384,7 +384,6 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
}
strncpy( notesStr, notes.c_str(), sizeof(notesStr) );
notesLen = notes.length();
if ( mysql_stmt_execute( stmt ) ) {
Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) );

View File

@@ -176,13 +176,13 @@ bool EventStream::loadEventData( int event_id ) {
event_data->n_frames = mysql_num_rows( result );
event_data->frames = new FrameData[event_data->frame_count];
int id, last_id = 0;
int last_id = 0;
time_t timestamp, last_timestamp = event_data->start_time;
double delta, last_delta = 0.0;
double last_delta = 0.0;
while ( ( dbrow = mysql_fetch_row( result ) ) ) {
id = atoi(dbrow[0]);
int id = atoi(dbrow[0]);
timestamp = atoi(dbrow[1]);
delta = atof(dbrow[2]);
double delta = atof(dbrow[2]);
int id_diff = id - last_id;
double frame_delta = (delta-last_delta)/id_diff;
if ( id_diff > 1 ) {
@@ -414,7 +414,6 @@ void EventStream::processCommand( const CmdMsg *msg ) {
}
send_frame = true;
break;
send_frame = true;
}
case CMD_PAN :
{

View File

@@ -75,7 +75,7 @@ class EventStream : public StreamBase {
int curr_frame_id;
double curr_stream_time;
bool send_frame;
bool send_frame;
EventData *event_data;
FFmpeg_Input *ffmpeg_input;
@@ -97,6 +97,7 @@ class EventStream : public StreamBase {
curr_frame_id = 0;
curr_stream_time = 0.0;
send_frame = false;
event_data = 0;

View File

@@ -109,8 +109,6 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags)
{
int ret;
if (!str)
return 0;
@@ -118,7 +116,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) {
if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
if ((int ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
return ret;
if (*str)

View File

@@ -107,7 +107,6 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mRawFrame = NULL;
mFrame = NULL;
frameCount = 0;
startTime = 0;
mIsOpening = false;
mCanCapture = false;
mOpenStart = 0;
@@ -275,8 +274,8 @@ int FfmpegCamera::OpenFfmpeg() {
return -1;
}
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
@@ -294,7 +293,6 @@ int FfmpegCamera::OpenFfmpeg() {
#endif
Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) );
startTime = av_gettime();//FIXME here or after find_Stream_info
Debug ( 1, "Got stream info" );
// Find first video stream present
@@ -416,21 +414,20 @@ int FfmpegCamera::OpenFfmpeg() {
if ( avcodec_open(mVideoCodecContext, mVideoCodec) < 0 ){
#else
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 ) {
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 ) {
#endif
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
} else {
AVDictionaryEntry *e = NULL;
if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
}
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
} else {
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
}
}
} // end if success opening codec
if (mVideoCodecContext->hwaccel != NULL) {
Debug(1, "HWACCEL in use");
@@ -451,17 +448,18 @@ int FfmpegCamera::OpenFfmpeg() {
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
// Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
Debug ( 1, "Calling avcodec_open" );
if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 )
Debug ( 1, "Calling avcodec_open" );
if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 )
#else
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 )
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 )
#endif
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
}
}
} // end if have audio stream
Debug ( 1, "Opened codec" );
# if 0
// Allocate space for the native video frame
mRawFrame = zm_av_frame_alloc();
@@ -508,6 +506,7 @@ int FfmpegCamera::OpenFfmpeg() {
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
#endif // HAVE_LIBSWSCALE
#endif
if ( (unsigned int)mVideoCodecContext->width != width || (unsigned int)mVideoCodecContext->height != height ) {
Warning( "Monitor dimensions are %dx%d but camera is sending %dx%d", width, height, mVideoCodecContext->width, mVideoCodecContext->height );
}

View File

@@ -46,8 +46,6 @@ class FfmpegCamera : public Camera {
#if HAVE_LIBAVFORMAT
AVFormatContext *mFormatContext;
int mVideoStreamId;
int mAudioStreamId;
AVCodec *mVideoCodec;
AVCodec *mAudioCodec;
AVFrame *mRawFrame;
@@ -82,7 +80,6 @@ class FfmpegCamera : public Camera {
pthread_t mReopenThread;
#endif // HAVE_LIBAVFORMAT
#if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext;
#endif

View File

@@ -146,7 +146,7 @@ Image::Image( const AVFrame *frame ) {
void Image::Assign( const AVFrame *frame ) {
/* Assume the dimensions etc are correct. FIXME */
AVPixelFormat format = (AVPixelFormat)AVPixFormat();
AVPixelFormat format = (AVPixelFormat)AVPixFormat();
AVFrame *dest_frame = zm_av_frame_alloc();
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
@@ -174,6 +174,8 @@ AVPixelFormat format = (AVPixelFormat)AVPixFormat();
Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras");
#endif // HAVE_LIBSWSCALE
av_frame_free( &dest_frame );
sws_freeContext(mConvertContext);
mConvertContext = NULL;
} // end Image::Image( const AVFrame *frame )
Image::Image( const Image &p_image ) {
@@ -464,7 +466,6 @@ void Image::Initialise() {
/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */
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 ) {
Error("WriteBuffer called with unexpected colours: %d",p_colours);
@@ -477,7 +478,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
}
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
newsize = (p_width * p_height) * p_colours;
unsigned int newsize = (p_width * p_height) * p_colours;
if ( buffer == NULL ) {
AllocImgBuffer(newsize);
@@ -2109,8 +2110,8 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size ) {
char time_text[64];
strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) );
char text[64];
if ( label ) {
char text[64];
snprintf( text, sizeof(text), "%s - %s", label, time_text );
Annotate( text, coord, size );
} else {
@@ -2632,8 +2633,7 @@ void Image::Rotate( int angle )
unsigned int new_width = width;
uint8_t* rotate_buffer = AllocBuffer(size);
switch( angle )
{
switch( angle ) {
case 90 :
{
new_height = width;
@@ -2642,41 +2642,27 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_rptr = *s_rptr++;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*d_ptr = *s_ptr++;
*(d_ptr+1) = *s_ptr++;
*(d_ptr+2) = *s_ptr++;
@@ -2691,28 +2677,20 @@ void Image::Rotate( int angle )
unsigned char *s_ptr = buffer+size;
unsigned char *d_ptr = rotate_buffer;
if ( colours == ZM_COLOUR_GRAY8 )
{
while( s_ptr > buffer )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
while( s_ptr > buffer ) {
s_ptr--;
*d_ptr++ = *s_ptr;
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr = (Rgb*)d_ptr;
while( s_rptr > (Rgb*)buffer )
{
while( s_rptr > (Rgb*)buffer ) {
s_rptr--;
*d_rptr++ = *s_rptr;
}
}
else /* Assume RGB24 */
{
while( s_ptr > buffer )
{
} else /* Assume RGB24 */ {
while( s_ptr > buffer ) {
s_ptr -= 3;
*d_ptr++ = *s_ptr;
*d_ptr++ = *(s_ptr+1);
@@ -2729,43 +2707,29 @@ void Image::Rotate( int angle )
unsigned int line_bytes = new_width*colours;
unsigned char *s_ptr = buffer+size;
if ( colours == ZM_COLOUR_GRAY8 )
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- )
{
if ( colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+(i-1);
for ( unsigned int j = new_height; j > 0; j-- ) {
s_ptr--;
*d_ptr = *s_ptr;
d_ptr += line_bytes;
}
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
} else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr;
Rgb* d_rptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- )
{
for ( unsigned int i = new_width; i > 0; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) {
s_rptr--;
*d_rptr = *s_rptr;
d_rptr += new_width;
}
}
}
else /* Assume RGB24 */
{
unsigned char *d_ptr;
for ( unsigned int i = new_width; i > 0; i-- )
{
d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- )
{
} else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) {
*(d_ptr+2) = *(--s_ptr);
*(d_ptr+1) = *(--s_ptr);
*d_ptr = *(--s_ptr);
@@ -2778,18 +2742,15 @@ void Image::Rotate( int angle )
}
AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
}
/* RGB32 compatible: complete */
void Image::Flip( bool leftright )
{
void Image::Flip( bool leftright ) {
uint8_t* flip_buffer = AllocBuffer(size);
unsigned int line_bytes = width*colours;
unsigned int line_bytes2 = 2*line_bytes;
if ( leftright )
{
if ( leftright ) {
// Horizontal flip, left to right
unsigned char *s_ptr = buffer+line_bytes;
unsigned char *d_ptr = flip_buffer;

View File

@@ -276,8 +276,7 @@ static boolean fill_input_buffer (j_decompress_ptr cinfo)
memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size );
nbytes = src->inbuffer_size;
if ( nbytes <= 0 )
{
if ( nbytes == 0 ) {
if ( src->start_of_data ) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);

View File

@@ -1501,20 +1501,20 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
sprintf( output+strlen(output), "Video Capabilities\n" );
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"",
vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"",
vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"",
vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"",
vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"",
vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"",
vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"",
vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"",
vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"",
vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"",
vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"",
vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":""
(vid_cap.type&VID_TYPE_CAPTURE)?" Can capture\n":"",
(vid_cap.type&VID_TYPE_TUNER)?" Can tune\n":"",
(vid_cap.type&VID_TYPE_TELETEXT)?" Does teletext\n":"",
(vid_cap.type&VID_TYPE_OVERLAY)?" Overlay onto frame buffer\n":"",
(vid_cap.type&VID_TYPE_CHROMAKEY)?" Overlay by chromakey\n":"",
(vid_cap.type&VID_TYPE_CLIPPING)?" Can clip\n":"",
(vid_cap.type&VID_TYPE_FRAMERAM)?" Uses the frame buffer memory\n":"",
(vid_cap.type&VID_TYPE_SCALES)?" Scalable\n":"",
(vid_cap.type&VID_TYPE_MONOCHROME)?" Monochrome only\n":"",
(vid_cap.type&VID_TYPE_SUBCAPTURE)?" Can capture subareas of the image\n":"",
(vid_cap.type&VID_TYPE_MPEG_DECODER)?" Can decode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MPEG_ENCODER)?" Can encode MPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_DECODER)?" Can decode MJPEG streams\n":"",
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":""
);
sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels );
sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios );

View File

@@ -344,6 +344,7 @@ Monitor::Monitor(
fps = 0.0;
event_count = 0;
image_count = 0;
analysis_image_count = 0;
ready_count = warmup_count;
first_alarm_count = 0;
last_alarm_count = 0;
@@ -758,6 +759,7 @@ double Monitor::GetFPS() const {
struct timeval time1 = snap1->timestamp;
int image_count = image_buffer_count;
int index2 = (index1+1)%image_buffer_count;
if ( index2 == image_buffer_count ) {
return 0.0;
@@ -774,7 +776,9 @@ double Monitor::GetFPS() const {
struct timeval time2 = snap2->timestamp;
double time_diff = tvDiffSec( time2, time1 );
if ( ! time_diff ) {
return 0.0;
}
double curr_fps = image_count/time_diff;
if ( curr_fps < 0.0 ) {
@@ -1193,6 +1197,15 @@ bool Monitor::Analyse() {
}
ZMPacket *snap = &image_buffer[index];
if ( snap->packet.stream_index != camera->get_VideoStreamId() ) {
if ( event ) {
//event->AddFrame( snap_image, *timestamp, score );
event->AddPacket( snap, 0 );
}
mutex.unlock();
return false;
}
struct timeval *timestamp = &snap->timestamp;
//Debug(2, "timestamp for index (%d) %s", index, timeval_to_string( *timestamp ) );
Image *snap_image = snap->image;
@@ -2852,6 +2865,7 @@ packet->reset();
if ( FirstCapture ) {
FirstCapture = 0;
mutex.unlock();
return 0;
}
} else {
@@ -2865,12 +2879,23 @@ packet->reset();
signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR);
capture_image->Fill(signalcolor);
shared_data->signal = false;
mutex.unlock();
return -1;
} else if ( captureResult > 0 ) {
if ( packet->packet.size && ! packet->frame ) {
packet->decode( camera->get_VideoCodecContext() );
packet->get_image();
if ( packet->packet.stream_index == camera->get_VideoStreamId() ) {
packet->decode( camera->get_VideoCodecContext() );
packet->get_image();
} else {
packet->decode( camera->get_AudioCodecContext() );
shared_data->last_write_index = index;
shared_data->last_write_time = image_buffer[index].timestamp.tv_sec;
mutex.unlock();
return 1;
}
} else {
Debug(2,"Not decoding");
}
/* Deinterlacing */
@@ -3339,7 +3364,7 @@ ZMPacket *Monitor::getSnapshot() {
// Wait for camera to get an image, and then assign it as the base reference image. So this should be done as the first task in the analysis thread startup.
void Monitor::get_ref_image() {
while (
while (
( shared_data->last_write_index == (unsigned int)image_buffer_count )
&&
( shared_data->last_write_time == 0 )

View File

@@ -330,7 +330,7 @@ protected:
MonitorLink **linked_monitors;
public:
Monitor( int p_id );
explicit Monitor( int p_id );
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
//bool OurCheckAlarms( Zone *zone, const Image *pImage );

View File

@@ -658,7 +658,10 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
replay_rate = ZM_RATE_BASE;
}
}
// Last read index is analysis... what do we care about analysis? I think we are using the same variable for two purposese
if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) {
// Is his % neccessary? is last_write_index not guaranteed to be < image_buffer_count?
int index = monitor->shared_data->last_write_index%monitor->image_buffer_count;
last_read_index = monitor->shared_data->last_write_index;
//Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer );

View File

@@ -88,7 +88,7 @@ void VideoStream::SetupFormat( ) {
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data) {
if ( !(s->priv_data) ) {
Fatal( "Could not allocate private data for output format." );
}
#if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0)
@@ -286,19 +286,19 @@ const char *VideoStream::MimeType( ) const {
}
void VideoStream::OpenStream( ) {
int avRet;
int ret;
/* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */
if ( ost ) {
/* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (avRet = avcodec_open( codec_context, codec )) < 0 )
if ( (ret = avcodec_open( codec_context, codec )) < 0 )
#else
if ( (avRet = avcodec_open2( codec_context, codec, 0 )) < 0 )
if ( (ret = avcodec_open2( codec_context, codec, 0 )) < 0 )
#endif
{
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
Fatal( "Could not open codec. Error code %d \"%s\"", ret, av_err2str(ret) );
}
Debug( 1, "Opened codec" );
@@ -364,7 +364,6 @@ void VideoStream::OpenStream( ) {
/* open the output file, if needed */
if ( !(of->flags & AVFMT_NOFILE) ) {
int ret;
#if LIBAVFORMAT_VERSION_CHECK(53, 15, 0, 21, 0)
ret = avio_open2( &ofc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL );
#elif LIBAVFORMAT_VERSION_CHECK(52, 102, 0, 102, 0)
@@ -405,9 +404,9 @@ void VideoStream::OpenStream( ) {
#endif
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
int ret = av_write_header( ofc );
ret = av_write_header( ofc );
#else
int ret = avformat_write_header( ofc, NULL );
ret = avformat_write_header( ofc, NULL );
#endif
if ( ret < 0 ) {

View File

@@ -46,6 +46,8 @@ ZMPacket::ZMPacket( Image *i ) {
}
ZMPacket::ZMPacket( AVPacket *p ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
set_packet( p );
keyframe = p->flags & AV_PKT_FLAG_KEY;
@@ -55,6 +57,8 @@ ZMPacket::ZMPacket( AVPacket *p ) {
}
ZMPacket::ZMPacket( AVPacket *p, struct timeval *t ) {
frame = NULL;
image = NULL;
av_init_packet( &packet );
set_packet( p );
timestamp = *t;
@@ -91,19 +95,19 @@ ZMPacket::~ZMPacket() {
}
void ZMPacket::reset() {
Debug(2,"reset");
//Debug(2,"reset");
zm_av_packet_unref( &packet );
packet.size = 0;
if ( in_frame ) {
Debug(4,"reset frame");
//Debug(4,"reset frame");
av_frame_free( &in_frame );
}
if ( frame ) {
Debug(4,"reset frame");
//Debug(4,"reset frame");
av_frame_free( &frame );
}
if ( buffer ) {
Debug(4,"freeing buffer");
//Debug(4,"freeing buffer");
av_freep( &buffer );
}
}

View File

@@ -51,9 +51,9 @@ class ZMPacket {
int decode( AVCodecContext *ctx );
void reset();
ZMPacket( AVPacket *packet, struct timeval *timestamp );
ZMPacket( AVPacket *packet );
explicit ZMPacket( AVPacket *packet );
ZMPacket( AVPacket *packet, AVFrame *frame, Image *image );
ZMPacket( Image *image );
explicit ZMPacket( Image *image );
ZMPacket();
~ZMPacket();

View File

@@ -42,7 +42,9 @@ RemoteCamera::RemoteCamera(
host( p_host ),
port( p_port ),
path( p_path ),
hp( 0 )
hp( 0 ),
mNeedAuth(false),
mAuthenticator(NULL)
{
if ( path[0] != '/' )
path = '/'+path;
@@ -97,14 +99,13 @@ void RemoteCamera::Initialise() {
int RemoteCamera::Read( int fd, char *buf, int size ) {
int ReceivedBytes = 0;
int bytes;
while ( ReceivedBytes < size ) {
// recv blocks until we get data, but it may be of ARBITRARY LENGTH and INCOMPLETE
int bytes_to_recv = size - ReceivedBytes;
if ( SOCKET_BUF_SIZE < bytes_to_recv )
bytes_to_recv = SOCKET_BUF_SIZE;
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
int bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
if ( bytes <= 0 ) {
Error("RemoteCamera::Read Recv error. Closing Socket\n");
return -1;

View File

@@ -531,9 +531,6 @@ int RemoteCameraHttp::GetResponse() {
} else
#endif // HAVE_LIBPCRE
{
if ( method == REGEXP ) {
Warning( "Unable to use netcam regexps as not compiled with libpcre" );
}
static const char *http_match = "HTTP/";
static const char *connection_match = "Connection:";
static const char *content_length_match = "Content-length:";

View File

@@ -332,7 +332,7 @@ int RtpCtrlThread::run()
timeout = false;
last_receive = time(NULL);
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetSocket *socket = dynamic_cast<UdpInetSocket *>(*iter) )
{

View File

@@ -94,7 +94,7 @@ int RtpDataThread::run()
mStop = true;
break;
}
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ )
for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter )
{
if ( UdpInetServer *socket = dynamic_cast<UdpInetServer *>(*iter) )
{

View File

@@ -36,8 +36,7 @@ int RtspThread::smMinDataPort = 0;
int RtspThread::smMaxDataPort = 0;
RtspThread::PortSet RtspThread::smAssignedPorts;
bool RtspThread::sendCommand( std::string message )
{
bool RtspThread::sendCommand( std::string message ) {
if ( mNeedAuth ) {
StringVector parts = split( message, " " );
if (parts.size() > 1)
@@ -46,20 +45,15 @@ bool RtspThread::sendCommand( std::string message )
message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION );
message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq );
Debug( 2, "Sending RTSP message: %s", message.c_str() );
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
message = base64Encode( message );
Debug( 2, "Sending encoded RTSP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
}
else
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
} else {
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( false );
}
@@ -67,77 +61,60 @@ bool RtspThread::sendCommand( std::string message )
return( true );
}
bool RtspThread::recvResponse( std::string &response )
{
bool RtspThread::recvResponse( std::string &response ) {
if ( mRtspSocket.recv( response ) < 0 )
Error( "Recv failed; %s", strerror(errno) );
Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
char respText[ZM_NETWORK_BUFSIZ];
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
}
return( false );
}
if ( respCode == 401)
{
if ( respCode == 401) {
Debug( 2, "Got 401 access denied response code, check WWW-Authenticate header and retry");
mAuthenticator->checkAuthResponse(response);
mNeedAuth = true;
return( false );
}
else if ( respCode != 200 )
{
} else if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( false );
}
return( true );
}
int RtspThread::requestPorts()
{
if ( !smMinDataPort )
{
int RtspThread::requestPorts() {
if ( !smMinDataPort ) {
char sql[ZM_SQL_SML_BUFSIZ];
strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) );
if ( mysql_query( &dbconn, sql ) )
{
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result )
{
if ( !result ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int nMonitors = mysql_num_rows( result );
int position = 0;
if ( nMonitors )
{
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
{
if ( nMonitors ) {
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
int id = atoi(dbrow[0]);
if ( mId == id )
{
if ( mId == id ) {
position = i;
break;
}
}
}
else
{
} else {
// Minor hack for testing when not strictly enabled
nMonitors = 1;
position = 0;
@@ -148,11 +125,9 @@ int RtspThread::requestPorts()
smMaxDataPort = smMinDataPort + portRange - 1;
Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort );
}
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ )
{
for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) {
PortSet::const_iterator iter = smAssignedPorts.find( i );
if ( iter == smAssignedPorts.end() )
{
if ( iter == smAssignedPorts.end() ) {
smAssignedPorts.insert( i );
return( i );
}
@@ -161,8 +136,7 @@ int RtspThread::requestPorts()
return( -1 );
}
void RtspThread::releasePorts( int port )
{
void RtspThread::releasePorts( int port ) {
if ( port > 0 )
smAssignedPorts.erase( port );
}
@@ -185,8 +159,7 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mStop( false )
{
mUrl = mProtocol+"://"+mHost+":"+mPort;
if ( !mPath.empty() )
{
if ( !mPath.empty() ) {
if ( mPath[0] == '/' )
mUrl += mPath;
else
@@ -208,10 +181,8 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mAuthenticator = new zm::Authenticator(parts[0], "");
}
RtspThread::~RtspThread()
{
if ( mFormatContext )
{
RtspThread::~RtspThread() {
if ( mFormatContext ) {
#if LIBAVFORMAT_VERSION_CHECK(52, 96, 0, 96, 0)
avformat_free_context( mFormatContext );
#else
@@ -219,16 +190,14 @@ RtspThread::~RtspThread()
#endif
mFormatContext = NULL;
}
if ( mSessDesc )
{
if ( mSessDesc ) {
delete mSessDesc;
mSessDesc = NULL;
}
delete mAuthenticator;
}
int RtspThread::run()
{
int RtspThread::run() {
std::string message;
std::string response;
@@ -246,8 +215,7 @@ int RtspThread::run()
bool authTried = false;
if ( mMethod == RTP_RTSP_HTTP )
{
if ( mMethod == RTP_RTSP_HTTP ) {
if ( !mRtspSocket2.connect( mHost.c_str(), mPort.c_str() ) )
Fatal( "Unable to connect auxiliary RTSP/HTTP socket" );
//Select select( 0.25 );
@@ -271,13 +239,11 @@ int RtspThread::run()
message += "Accept: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
if ( mRtspSocket.recv( response ) < 0 )
{
if ( mRtspSocket.recv( response ) < 0 ) {
Error( "Recv failed; %s", strerror(errno) );
return( -1 );
}
@@ -285,14 +251,10 @@ int RtspThread::run()
Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() );
float respVer = 0;
respCode = -1;
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 )
{
if ( isalnum(response[0]) )
{
if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) {
if ( isalnum(response[0]) ) {
Error( "Response parse failure in '%s'", response.c_str() );
}
else
{
} else {
Error( "Response parse failure, %zd bytes follow", response.size() );
if ( response.size() )
Hexdump( Logger::ERROR, response.data(), min(response.size(),16) );
@@ -313,8 +275,7 @@ int RtspThread::run()
} while (respCode == 401 && !authTried);
if ( respCode != 200 )
{
if ( respCode != 200 ) {
Error( "Unexpected response code %d, text is '%s'", respCode, respText );
return( -1 );
}
@@ -327,8 +288,7 @@ int RtspThread::run()
message += "Content-Type: application/x-rtsp-tunnelled\r\n";
message += "\r\n";
Debug( 2, "Sending HTTP message: %s", message.c_str() );
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() )
{
if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) {
Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) );
return( -1 );
}
@@ -383,17 +343,14 @@ int RtspThread::run()
if( sdpStart == std::string::npos )
return( -1 );
if ( mRtspDescribe )
{
if ( mRtspDescribe ) {
std::string DescHeader = response.substr( 0,sdpStart );
Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() );
lines = split( DescHeader, "\r\n" );
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
// If the device sends us a url value for Content-Base in the response header, we should use that instead
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) )
{
if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) {
mUrl = trimSpaces( lines[i].substr( 13 ) );
Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() );
break;
@@ -406,13 +363,10 @@ int RtspThread::run()
std::string sdp = response.substr( sdpStart );
Debug( 1, "Processing SDP '%s'", sdp.c_str() );
try
{
try {
mSessDesc = new SessionDescriptor( mUrl, sdp );
mFormatContext = mSessDesc->generateFormatContext();
}
catch( const Exception &e )
{
} catch( const Exception &e ) {
Error( e.getMessage().c_str() );
return( -1 );
}
@@ -436,10 +390,8 @@ int RtspThread::run()
_AVCODECID codecId;
if ( mFormatContext->nb_streams >= 1 )
{
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ )
{
if ( mFormatContext->nb_streams >= 1 ) {
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) {
SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
@@ -449,12 +401,9 @@ int RtspThread::run()
{
// Check if control Url is absolute or relative
controlUrl = mediaDesc->getControlUrl();
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin()))
{
if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin())) {
trackUrl = controlUrl;
}
else
{
} else {
if ( *trackUrl.rbegin() != '/') {
trackUrl += "/" + controlUrl;
} else {
@@ -470,8 +419,7 @@ int RtspThread::run()
}
}
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
localPorts[0] = requestPorts();
@@ -508,10 +456,8 @@ int RtspThread::run()
int timeout = 0;
char transport[256] = "";
for ( size_t i = 0; i < lines.size(); i++ )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
session = trimSpaces( sessionLine[0] );
if ( sessionLine.size() == 2 )
@@ -536,41 +482,31 @@ int RtspThread::run()
std::string distribution = "";
unsigned long ssrc = 0;
StringVector parts = split( transport, ";" );
for ( size_t i = 0; i < parts.size(); i++ )
{
for ( size_t i = 0; i < parts.size(); i++ ) {
if ( parts[i] == "unicast" || parts[i] == "multicast" )
distribution = parts[i];
else if ( startsWith( parts[i], "server_port=" ) )
{
else if ( startsWith( parts[i], "server_port=" ) ) {
method = "RTP/UNICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 );
remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "interleaved=" ) )
{
} else if ( startsWith( parts[i], "interleaved=" ) ) {
method = "RTP/RTSP";
StringVector subparts = split( parts[i], "=" );
StringVector channels = split( subparts[1], "-" );
remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 );
remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "port=" ) )
{
} else if ( startsWith( parts[i], "port=" ) ) {
method = "RTP/MULTICAST";
StringVector subparts = split( parts[i], "=" );
StringVector ports = split( subparts[1], "-" );
localPorts[0] = strtol( ports[0].c_str(), NULL, 10 );
localPorts[1] = strtol( ports[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[i], "destination=" ) )
{
} else if ( startsWith( parts[i], "destination=" ) ) {
StringVector subparts = split( parts[i], "=" );
localHost = subparts[1];
}
else if ( startsWith( parts[i], "ssrc=" ) )
{
} else if ( startsWith( parts[i], "ssrc=" ) ) {
StringVector subparts = split( parts[i], "=" );
ssrc = strtoll( subparts[1].c_str(), NULL, 16 );
}
@@ -592,13 +528,11 @@ int RtspThread::run()
lines = split( response, "\r\n" );
std::string rtpInfo;
for ( size_t i = 0; i < lines.size(); i++ )
{
for ( size_t i = 0; i < lines.size(); i++ ) {
if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) )
rtpInfo = trimSpaces( lines[i].substr( 9 ) );
// Check for a timeout again. Some rtsp devices don't send a timeout until after the PLAY command is sent
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) )
{
if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) ) {
StringVector sessionLine = split( lines[i].substr(9), ";" );
if ( sessionLine.size() == 2 )
sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout );
@@ -610,31 +544,22 @@ int RtspThread::run()
int seq = 0;
unsigned long rtpTime = 0;
StringVector streams;
if ( rtpInfo.empty() )
{
if ( rtpInfo.empty() ) {
Debug( 1, "RTP Info Empty. Starting values for Sequence and Rtptime shall be zero.");
}
else
{
} else {
Debug( 2, "Got RTP Info %s", rtpInfo.c_str() );
// More than one stream can be included in the RTP Info
streams = split( rtpInfo.c_str(), "," );
for ( size_t i = 0; i < streams.size(); i++ )
{
for ( size_t i = 0; i < streams.size(); i++ ) {
// We want the stream that matches the trackUrl we are using
if ( streams[i].find(controlUrl.c_str()) != std::string::npos )
{
if ( streams[i].find(controlUrl.c_str()) != std::string::npos ) {
// Parse the sequence and rtptime values
parts = split( streams[i].c_str(), ";" );
for ( size_t j = 0; j < parts.size(); j++ )
{
if ( startsWith( parts[j], "seq=" ) )
{
for ( size_t j = 0; j < parts.size(); j++ ) {
if ( startsWith( parts[j], "seq=" ) ) {
StringVector subparts = split( parts[j], "=" );
seq = strtol( subparts[1].c_str(), NULL, 10 );
}
else if ( startsWith( parts[j], "rtptime=" ) )
{
} else if ( startsWith( parts[j], "rtptime=" ) ) {
StringVector subparts = split( parts[j], "=" );
rtpTime = strtol( subparts[1].c_str(), NULL, 10 );
}
@@ -651,8 +576,7 @@ int RtspThread::run()
time_t now;
message = "GET_PARAMETER "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n";
switch( mMethod )
{
switch( mMethod ) {
case RTP_UNICAST :
{
RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId );
@@ -663,13 +587,11 @@ int RtspThread::run()
rtpDataThread.start();
rtpCtrlThread.start();
while( !mStop )
{
while( !mStop ) {
now = time(NULL);
// Send a keepalive message if the server supports this feature and we are close to the timeout expiration
Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) );
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) )
{
if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) {
if ( !sendCommand( message ) )
return( -1 );
lastKeepalive = now;
@@ -721,11 +643,9 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
Buffer buffer( ZM_NETWORK_BUFSIZ );
std::string keepaliveMessage = "OPTIONS "+mUrl+" RTSP/1.0\r\n";
std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n";
while ( !mStop && select.wait() >= 0 )
{
while ( !mStop && select.wait() >= 0 ) {
Select::CommsList readable = select.getReadable();
if ( readable.size() == 0 )
{
if ( readable.size() == 0 ) {
Error( "RTSP timed out" );
break;
}
@@ -735,23 +655,19 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali
buffer.append( tempBuffer, nBytes );
Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() );
while( buffer.size() > 0 )
{
if ( buffer[0] == '$' )
{
while( buffer.size() > 0 ) {
if ( buffer[0] == '$' ) {
if ( buffer.size() < 4 )
break;
unsigned char channel = buffer[1];
unsigned short len = ntohs( *((unsigned short *)(buffer+2)) );
Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel );
if ( (unsigned short)buffer.size() < (len+4) )
{
if ( (unsigned short)buffer.size() < (len+4) ) {
Debug( 4, "Missing %d bytes, rereading", (len+4)-buffer.size() );
break;
}
if ( channel == remoteChannels[0] )
{
if ( channel == remoteChannels[0] ) {
Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len );
Hexdump( 4, (char *)buffer, 16 );
rtpDataThread.recvPacket( buffer+4, len );

View File

@@ -31,8 +31,7 @@
#include <set>
#include <map>
class RtspThread : public Thread
{
class RtspThread : public Thread {
public:
typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod;
typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist;

View File

@@ -26,7 +26,11 @@
namespace zm {
Authenticator::Authenticator(std::string &username, std::string password) {
Authenticator::Authenticator( const std::string &username, const std::string &password) :
fCnonce( "0a4f113b" ),
fUsername(username),
fPassword(password)
{
#ifdef HAVE_GCRYPT_H
// Special initialisation for libgcrypt
if ( !gcry_check_version( GCRYPT_VERSION ) )
@@ -38,10 +42,7 @@ Authenticator::Authenticator(std::string &username, std::string password) {
#endif // HAVE_GCRYPT_H
fAuthMethod = AUTH_UNDEFINED;
fUsername = username;
fPassword = password;
nc = 1;
fCnonce = "0a4f113b";
}
Authenticator::~Authenticator() {
@@ -96,13 +97,11 @@ void Authenticator::authHandleHeader(std::string headerData)
}
}
std::string Authenticator::quote(std::string src)
{
std::string Authenticator::quote( const std::string &src ) {
return replaceAll(replaceAll(src, "\\", "\\\\"), "\"", "\\\"");
}
std::string Authenticator::getAuthHeader(std::string method, std::string uri)
{
std::string Authenticator::getAuthHeader(std::string method, std::string uri) {
std::string result = "Authorization: ";
if (fAuthMethod == AUTH_BASIC)
{

View File

@@ -37,7 +37,7 @@ namespace zm {
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
class Authenticator {
public:
Authenticator(std::string &username, std::string password);
Authenticator(const std::string &username, const std::string &password);
virtual ~Authenticator();
void reset();
@@ -60,7 +60,7 @@ private:
std::string fQop;
std::string fUsername;
std::string fPassword;
std::string quote( std::string src );
std::string quote( const std::string &src );
int nc;
};

View File

@@ -71,7 +71,7 @@ public:
int mNoAddresses;
public:
ConnInfo( const std::string &connInfo );
explicit ConnInfo( const std::string &connInfo );
};
class BandInfo {
@@ -80,7 +80,7 @@ public:
int mValue;
public:
BandInfo( const std::string &bandInfo );
explicit BandInfo( const std::string &bandInfo );
};
class MediaDescriptor {
@@ -138,48 +138,38 @@ public:
{
return( mControlUrl );
}
void setControlUrl( const std::string &controlUrl )
{
void setControlUrl( const std::string &controlUrl ) {
mControlUrl = controlUrl;
}
const int getClock() const
{
const int getClock() const {
return( mClock );
}
void setClock( int clock )
{
void setClock( int clock ) {
mClock = clock;
}
void setFrameSize( int width, int height )
{
void setFrameSize( int width, int height ) {
mWidth = width;
mHeight = height;
}
int getWidth() const
{
int getWidth() const {
return( mWidth );
}
int getHeight() const
{
int getHeight() const {
return( mHeight );
}
void setSprops(const std::string props)
{
void setSprops(const std::string &props) {
mSprops = props;
}
const std::string getSprops() const
{
const std::string getSprops() const {
return ( mSprops );
}
const double getFrameRate() const
{
const double getFrameRate() const {
return( mFrameRate );
}
void setFrameRate( double frameRate )
{
void setFrameRate( double frameRate ) {
mFrameRate = frameRate;
}
};

View File

@@ -32,8 +32,8 @@ protected:
public:
Storage();
Storage( MYSQL_ROW &dbrow );
Storage( unsigned int p_id );
explicit Storage( MYSQL_ROW &dbrow );
explicit Storage( unsigned int p_id );
~Storage();
unsigned int Id() const { return( id ); }

View File

@@ -82,9 +82,29 @@ int SWScale::Convert(
AVFrame *in_frame,
AVFrame *out_frame
) {
// THe J formats are deprecated, so we need to convert
AVPixelFormat format;
switch ( in_frame->format ) {
case AV_PIX_FMT_YUVJ420P :
format = AV_PIX_FMT_YUV420P;
break;
case AV_PIX_FMT_YUVJ422P :
format = AV_PIX_FMT_YUV422P;
break;
case AV_PIX_FMT_YUVJ444P :
format = AV_PIX_FMT_YUV444P;
break;
case AV_PIX_FMT_YUVJ440P :
format = AV_PIX_FMT_YUV440P;
break;
default:
format = (AVPixelFormat)in_frame->format;
break;
}
/* Get the context */
swscale_ctx = sws_getCachedContext( swscale_ctx,
in_frame->width, in_frame->height, (AVPixelFormat)in_frame->format,
in_frame->width, in_frame->height, format,
out_frame->width, out_frame->height, (AVPixelFormat)out_frame->format,
SWS_FAST_BILINEAR, NULL, NULL, NULL );
if ( swscale_ctx == NULL ) {
@@ -124,6 +144,24 @@ int SWScale::Convert(
return -3;
}
// THe J formats are deprecated, so we need to convert
switch ( in_pf ) {
case AV_PIX_FMT_YUVJ420P :
in_pf = AV_PIX_FMT_YUV420P;
break;
case AV_PIX_FMT_YUVJ422P :
in_pf = AV_PIX_FMT_YUV422P;
break;
case AV_PIX_FMT_YUVJ444P :
in_pf = AV_PIX_FMT_YUV444P;
break;
case AV_PIX_FMT_YUVJ440P :
in_pf = AV_PIX_FMT_YUV440P;
break;
default:
break;
}
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
/* Warn if the input or output pixelformat is not supported */
if(!sws_isSupportedInput(in_pf)) {

View File

@@ -80,7 +80,7 @@ const std::string stringtf( const char *format, ... )
return( tempString );
}
const std::string stringtf( const std::string format, ... )
const std::string stringtf( const std::string &format, ... )
{
va_list ap;
char tempBuffer[8192];

View File

@@ -33,7 +33,7 @@ std::string trimSet(std::string str, std::string trimset);
std::string replaceAll(std::string str, std::string from, std::string to);
const std::string stringtf( const char *format, ... );
const std::string stringtf( const std::string format, ... );
const std::string stringtf( const std::string &format, ... );
bool startsWith( const std::string &haystack, const std::string &needle );
StringVector split( const std::string &string, const std::string &chars, int limit=0 );

View File

@@ -118,6 +118,7 @@ Debug(2,"Copied video context from input stream");
#else
avcodec_copy_context( video_out_ctx, video_in_ctx );
#endif
video_out_ctx->time_base = (AVRational){1, 1000000}; // microseconds as base frame rate
// Same codec, just copy the packets, otherwise we have to decode/encode
video_out_codec = (AVCodec *)video_in_ctx->codec;
// Only set orientation if doing passthrough, otherwise the frame image will be rotated
@@ -281,10 +282,9 @@ Error("Codec not set");
);
} // end if copying or trasncoding
video_out_stream = avformat_new_stream(oc, video_out_codec);
if ( !video_out_stream ) {
Fatal("Unable to create video out stream\n");
if ( ! video_out_stream ) {
Fatal("Unable to create video out stream");
} else {
Debug(2, "Success creating video out stream");
}
@@ -303,7 +303,7 @@ Debug(2, "%dx%d", video_out_stream->codec->width, video_out_stream->codec->heigh
zm_dump_codec(video_out_ctx);
zm_dump_codec(video_out_stream->codec);
#endif
#if 0
#if 1
video_out_stream->time_base.num = video_out_ctx->time_base.num;
video_out_stream->time_base.den = video_out_ctx->time_base.den;
#endif
@@ -964,6 +964,7 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
return -1;
}
#else
av_init_packet(&opkt);
int data_present;
if ( (ret = avcodec_encode_video2(
video_out_ctx, &opkt, zm_packet->frame, &data_present)) < 0) {
@@ -983,9 +984,16 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
AVPacket *ipkt = &zm_packet->packet;
Debug(3, "Doing passthrough, just copy packet");
// Just copy it because the codec is the same
av_init_packet(&opkt);
opkt.data = ipkt->data;
opkt.size = ipkt->size;
opkt.flags = ipkt->flags;
if ( ! video_last_pts ) {
video_last_pts = zm_packet->timestamp.tv_sec*1000000 + zm_packet->timestamp.tv_usec;
opkt.dts = opkt.pts = 0;
} else {
opkt.dts = opkt.pts = ( zm_packet->timestamp.tv_sec*1000000 + zm_packet->timestamp.tv_usec ) - video_last_pts;
}
}
int keyframe = opkt.flags & AV_PKT_FLAG_KEY;
@@ -1014,7 +1022,7 @@ void VideoStore::write_video_packet( AVPacket &opkt ) {
//AVPacket safepkt;
//memcpy(&safepkt, &opkt, sizeof(AVPacket));
av_packet_rescale_ts( &opkt, video_out_ctx->time_base, video_out_stream->time_base );
//av_packet_rescale_ts( &opkt, video_out_ctx->time_base, video_out_stream->time_base );
Debug(1,
"writing video packet pts(%d) dts(%d) duration(%d) packet_count(%d)",
@@ -1102,11 +1110,12 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
}
#endif
int frame_size = out_frame->nb_samples;
in_frame->pts = audio_next_pts;
// Resample the in into the audioSampleBuffer until we proceed the whole
// decoded data
if ((ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
0, in_frame->nb_samples)) < 0) {
0, frame_size)) < 0) {
Error("Could not resample frame (error '%s')\n",
av_make_error_string(ret).c_str());
av_frame_unref(in_frame);
@@ -1115,16 +1124,14 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
av_frame_unref(in_frame);
int samples_available = avresample_available(resample_ctx);
if (samples_available < frame_size) {
if ( samples_available < frame_size ) {
Debug(1, "Not enough samples yet (%d)", samples_available);
return 0;
}
Debug(3, "Output_frame samples (%d)", out_frame->nb_samples);
// Read a frame audio data from the resample fifo
if (avresample_read(resample_ctx, out_frame->data, frame_size) !=
frame_size) {
if ( avresample_read(resample_ctx, out_frame->data, frame_size) != frame_size) {
Warning("Error reading resampled audio: ");
return 0;
}
@@ -1146,8 +1153,8 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
// av_frame_unref( out_frame );
if ((ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0) {
if (AVERROR(EAGAIN) == ret) {
if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) {
// THe codec may need more samples than it has, perfectly valid
Debug(3, "Could not recieve packet (error '%s')",
av_make_error_string(ret).c_str());
@@ -1155,20 +1162,20 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
Error("Could not recieve packet (error %d = '%s')", ret,
av_make_error_string(ret).c_str());
}
zm_av_packet_unref(&opkt);
//zm_av_packet_unref(&opkt);
av_frame_unref(in_frame);
// av_frame_unref( out_frame );
return 0;
}
#else
if ((ret = avcodec_encode_audio2(audio_out_ctx, &opkt, out_frame,
if ( (ret = avcodec_encode_audio2(audio_out_ctx, &opkt, out_frame,
&data_present)) < 0) {
Error("Could not encode frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
return 0;
}
if (!data_present) {
if ( !data_present ) {
Debug(2, "Not ready to out a frame yet.");
zm_av_packet_unref(&opkt);
return 0;
@@ -1176,11 +1183,13 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
#endif
#endif
opkt.duration = out_frame->nb_samples;
} else {
av_init_packet(&opkt);
Debug(5, "after init packet");
opkt.data = ipkt->data;
opkt.size = ipkt->size;
opkt.duration = ipkt->duration;
}
// PTS is difficult, because of the buffering of the audio packets in the
@@ -1245,7 +1254,7 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
opkt.dts = opkt.pts;
}
opkt.duration = out_frame ? out_frame->nb_samples : ipkt->duration;
//opkt.duration = out_frame ? out_frame->nb_samples : ipkt->duration;
// opkt.duration = av_rescale_q(ipkt->duration, audio_in_stream->time_base,
// audio_out_stream->time_base);
Debug(2, "opkt.pts (%d), opkt.dts(%d) opkt.duration = (%d)", opkt.pts,
@@ -1260,7 +1269,7 @@ int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) {
AVPacket safepkt;
memcpy(&safepkt, &opkt, sizeof(AVPacket));
ret = av_interleaved_write_frame(oc, &opkt);
if (ret != 0) {
if ( ret != 0 ) {
Error("Error writing audio frame packet: %s\n",
av_make_error_string(ret).c_str());
dumpPacket(&safepkt);