diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index aeec18379..910b2ac42 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -91,7 +91,7 @@ RemoteCameraRtsp::~RemoteCameraRtsp() if ( mCodecContext ) { avcodec_close( mCodecContext ); - mCodecContext = NULL; // Freed by av_close_input_file + mCodecContext = NULL; // Freed by avformat_free_context in the destructor of RtspThread class } if ( capture ) diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index f157f4e4f..f6b773d9c 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -26,7 +26,6 @@ #include "zm_rtp_data.h" #include "zm_rtp_ctrl.h" #include "zm_db.h" -#include "zm_sdp.h" #include #include @@ -171,6 +170,7 @@ int RtspThread::requestPorts() nMonitors = 1; position = 0; } + mysql_free_result(result); int portRange = int(((config.max_rtp_port-config.min_rtp_port)+1)/nMonitors); smMinDataPort = config.min_rtp_port + (position * portRange); smMaxDataPort = smMinDataPort + portRange - 1; @@ -202,6 +202,7 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, mHost( host ), mPort( port ), mPath( path ), + mSessDesc( 0 ), mFormatContext( 0 ), mSeq( 0 ), mSession( 0 ), @@ -236,6 +237,17 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, RtspThread::~RtspThread() { + if ( mFormatContext ) + { + avformat_free_context( mFormatContext ); + mFormatContext = NULL; + } + if ( mSessDesc ) + { + delete mSessDesc; + mSessDesc = NULL; + } + delete mAuthenticator; } int RtspThread::run() @@ -387,11 +399,10 @@ int RtspThread::run() std::string sdp = response.substr( sdpStart ); Debug( 1, "Processing SDP '%s'", sdp.c_str() ); - SessionDescriptor *sessDesc = 0; try { - sessDesc = new SessionDescriptor( mUrl, sdp ); - mFormatContext = sessDesc->generateFormatContext(); + mSessDesc = new SessionDescriptor( mUrl, sdp ); + mFormatContext = mSessDesc->generateFormatContext(); } catch( const Exception &e ) { @@ -421,7 +432,7 @@ int RtspThread::run() { for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) { - SessionDescriptor::MediaDescriptor *mediaDesc = sessDesc->getStream( i ); + SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i ); #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) #else @@ -481,20 +492,26 @@ int RtspThread::run() return( -1 ); lines = split( response, "\r\n" ); - char *session = 0; + std::string session; int timeout = 0; char transport[256] = ""; for ( size_t i = 0; i < lines.size(); i++ ) { - sscanf( lines[i].c_str(), "Session: %a[0-9a-fA-F]; timeout=%d", &session, &timeout ); + 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 ) + sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout ); + } sscanf( lines[i].c_str(), "Transport: %s", transport ); } - if ( !session ) + if ( session.empty() ) Fatal( "Unable to get session identifier from response '%s'", response.c_str() ); - Debug( 2, "Got RTSP session %s, timeout %d secs", session, timeout ); + Debug( 2, "Got RTSP session %s, timeout %d secs", session.c_str(), timeout ); if ( !transport[0] ) Fatal( "Unable to get transport details from response '%s'", response.c_str() ); @@ -562,20 +579,21 @@ int RtspThread::run() return( -1 ); lines = split( response, "\r\n" ); - char *rtpInfo = 0; + std::string rtpInfo; for ( size_t i = 0; i < lines.size(); i++ ) { - sscanf( lines[i].c_str(), "RTP-Info: %as", &rtpInfo ); + if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) ) + rtpInfo = trimSpaces( lines[i].substr( 9 ) ); } - if ( !rtpInfo ) + if ( rtpInfo.empty() ) Fatal( "Unable to get RTP Info identifier from response '%s'", response.c_str() ); - Debug( 2, "Got RTP Info %s", rtpInfo ); + Debug( 2, "Got RTP Info %s", rtpInfo.c_str() ); int seq = 0; unsigned long rtpTime = 0; - parts = split( rtpInfo, ";" ); + parts = split( rtpInfo.c_str(), ";" ); for ( size_t i = 0; i < parts.size(); i++ ) { if ( startsWith( parts[i], "seq=" ) ) diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h index 4ecf99a92..937646b6d 100644 --- a/src/zm_rtsp.h +++ b/src/zm_rtsp.h @@ -26,6 +26,7 @@ #include "zm_thread.h" #include "zm_rtp_source.h" #include "zm_rtsp_auth.h" +#include "zm_sdp.h" #include #include @@ -73,6 +74,7 @@ private: SourceMap mSources; + SessionDescriptor *mSessDesc; AVFormatContext *mFormatContext; uint16_t mSeq; diff --git a/src/zm_sdp.cpp b/src/zm_sdp.cpp index 077be08b9..9c10d89f2 100644 --- a/src/zm_sdp.cpp +++ b/src/zm_sdp.cpp @@ -184,9 +184,15 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string mInfo = line; break; case 'c' : + // This prevent a memory leak if the field appears more than one time + if ( mConnInfo ) + delete mConnInfo; mConnInfo = new ConnInfo( line ); break; case 'b' : + // This prevent a memory leak if the field appears more than one time + if ( mBandInfo ) + delete mBandInfo; mBandInfo = new BandInfo( line ); break; case 't' : @@ -339,6 +345,16 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string } } +SessionDescriptor::~SessionDescriptor() +{ + if ( mConnInfo ) + delete mConnInfo; + if ( mBandInfo ) + delete mBandInfo; + for ( unsigned int i = 0; i < mMediaList.size(); i++ ) + delete mMediaList[i]; +} + AVFormatContext *SessionDescriptor::generateFormatContext() const { AVFormatContext *formatContext = avformat_alloc_context(); diff --git a/src/zm_sdp.h b/src/zm_sdp.h index 28d2d8c52..fb56a2886 100644 --- a/src/zm_sdp.h +++ b/src/zm_sdp.h @@ -213,6 +213,7 @@ protected: public: SessionDescriptor( const std::string &url, const std::string &sdp ); + ~SessionDescriptor(); const std::string &getUrl() const {