From 28269eccc34a0d49911dfa82fe9ccad903cf8e36 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 28 Apr 2019 12:05:32 -0400 Subject: [PATCH] Fix Remote RTSP Method on newer ffmpeg --- src/zm_remote_camera_rtsp.cpp | 27 ++++- src/zm_remote_camera_rtsp.h | 3 +- src/zm_rtp_ctrl.cpp | 156 ++++++++++--------------- src/zm_rtp_ctrl.h | 39 +++---- src/zm_rtp_source.cpp | 160 +++++++++---------------- src/zm_rtsp.cpp | 213 ++++++++++++++++------------------ src/zm_sdp.cpp | 197 +++++++++++++++---------------- 7 files changed, 350 insertions(+), 445 deletions(-) diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index 7e2143203..1f94f4849 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -28,7 +28,22 @@ #include #include -RemoteCameraRtsp::RemoteCameraRtsp( unsigned int p_monitor_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) : +RemoteCameraRtsp::RemoteCameraRtsp( + unsigned int p_monitor_id, + const std::string &p_method, + const std::string &p_host, + const std::string &p_port, + const std::string &p_path, + int p_width, + int p_height, + bool p_rtsp_describe, + int p_colours, + int p_brightness, + int p_contrast, + int p_hue, + int p_colour, + bool p_capture, + bool p_record_audio ) : RemoteCamera( p_monitor_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ), rtsp_describe( p_rtsp_describe ), rtspThread( 0 ) @@ -63,13 +78,13 @@ RemoteCameraRtsp::RemoteCameraRtsp( unsigned int p_monitor_id, const std::string mConvertContext = NULL; #endif /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ - if(colours == ZM_COLOUR_RGB32) { + if ( colours == ZM_COLOUR_RGB32 ) { subpixelorder = ZM_SUBPIX_ORDER_RGBA; imagePixFormat = AV_PIX_FMT_RGBA; - } else if(colours == ZM_COLOUR_RGB24) { + } else if ( colours == ZM_COLOUR_RGB24 ) { subpixelorder = ZM_SUBPIX_ORDER_RGB; imagePixFormat = AV_PIX_FMT_RGB24; - } else if(colours == ZM_COLOUR_GRAY8) { + } else if ( colours == ZM_COLOUR_GRAY8 ) { subpixelorder = ZM_SUBPIX_ORDER_NONE; imagePixFormat = AV_PIX_FMT_GRAY8; } else { @@ -169,7 +184,7 @@ int RemoteCameraRtsp::PrimeCapture() { } else { Debug(2, "Have another video stream." ); } - } + } else #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) #else @@ -181,6 +196,8 @@ int RemoteCameraRtsp::PrimeCapture() { } else { Debug(2, "Have another audio stream." ); } + } else { + Debug(1, "Have unknown codec type in stream %d : %d", i, mFormatContext->streams[i]->codec->codec_type); } } // end foreach stream diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h index b3e392a77..5fa5a0778 100644 --- a/src/zm_remote_camera_rtsp.h +++ b/src/zm_remote_camera_rtsp.h @@ -34,8 +34,7 @@ // accessed over a network connection using rtsp protocol // (Real Time Streaming Protocol) // -class RemoteCameraRtsp : public RemoteCamera -{ +class RemoteCameraRtsp : public RemoteCamera { protected: struct sockaddr_in rtsp_sa; struct sockaddr_in rtcp_sa; diff --git a/src/zm_rtp_ctrl.cpp b/src/zm_rtp_ctrl.cpp index b586c979f..bc6725c5d 100644 --- a/src/zm_rtp_ctrl.cpp +++ b/src/zm_rtp_ctrl.cpp @@ -28,12 +28,12 @@ #include -RtpCtrlThread::RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ) : mRtspThread( rtspThread ), mRtpSource( rtpSource ), mStop( false ) +RtpCtrlThread::RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ) + : mRtspThread( rtspThread ), mRtpSource( rtpSource ), mStop( false ) { } -int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) -{ +int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) { const RtcpPacket *rtcpPacket; rtcpPacket = (RtcpPacket *)packet; @@ -48,33 +48,24 @@ int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) int pt = rtcpPacket->header.pt; int len = ntohs(rtcpPacket->header.lenN); - Debug( 5, "RTCP Ver: %d", ver ); - Debug( 5, "RTCP Count: %d", count ); - Debug( 5, "RTCP Pt: %d", pt ); - Debug( 5, "RTCP len: %d", len ); + Debug( 5, "RTCP Ver: %d Count: %d Pt: %d len: %d", ver, count, pt, len); - switch( pt ) - { + switch( pt ) { case RTCP_SR : { uint32_t ssrc = ntohl(rtcpPacket->body.sr.ssrcN); Debug( 5, "RTCP Got SR (%x)", ssrc ); - if ( mRtpSource.getSsrc() ) - { - if ( ssrc != mRtpSource.getSsrc() ) - { + if ( mRtpSource.getSsrc() ) { + if ( ssrc != mRtpSource.getSsrc() ) { Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); return( -1 ); } - } - else if ( ssrc ) - { + } else if ( ssrc ) { mRtpSource.setSsrc( ssrc ); } - if ( len > 1 ) - { + if ( len > 1 ) { //printf( "NTPts:%d.%d, RTPts:%d\n", $ntptsmsb, $ntptslsb, $rtpts ); uint16_t ntptsmsb = ntohl(rtcpPacket->body.sr.ntpSecN); uint16_t ntptslsb = ntohl(rtcpPacket->body.sr.ntpFracN); @@ -89,25 +80,21 @@ int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) case RTCP_SDES : { ssize_t contentLen = packetLen - sizeof(rtcpPacket->header); - while ( contentLen ) - { + while ( contentLen ) { Debug( 5, "RTCP CL: %zd", contentLen ); uint32_t ssrc = ntohl(rtcpPacket->body.sdes.srcN); Debug( 5, "RTCP Got SDES (%x), %d items", ssrc, count ); - if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) - { + if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) { Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); return( -1 ); } unsigned char *sdesPtr = (unsigned char *)&rtcpPacket->body.sdes.item; - for ( int i = 0; i < count; i++ ) - { + for ( int i = 0; i < count; i++ ) { RtcpSdesItem *item = (RtcpSdesItem *)sdesPtr; Debug( 5, "RTCP Item length %d", item->len ); - switch( item->type ) - { + switch( item->type ) { case RTCP_SDES_CNAME : { std::string cname( item->data, item->len ); @@ -123,50 +110,39 @@ int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) case RTCP_SDES_NOTE : case RTCP_SDES_PRIV : default : - { Error( "Received unexpected SDES item type %d, ignoring", item->type ); - return( -1 ); - } + return -1; } int paddedLen = 4+2+item->len+1; // Add null byte paddedLen = (((paddedLen-1)/4)+1)*4; // Round to nearest multiple of 4 - Debug( 5, "RTCP PL:%d", paddedLen ); + Debug(5, "RTCP PL:%d", paddedLen); sdesPtr += paddedLen; contentLen = ( paddedLen <= contentLen ) ? ( contentLen - paddedLen ) : 0; } - } + } // end whiel contentLen break; } case RTCP_BYE : - { - Debug( 5, "RTCP Got BYE" ); + Debug(5, "RTCP Got BYE"); mStop = true; break; - } case RTCP_APP : - { // Ignoring as per RFC 3550 - Debug( 5, "Received RTCP_APP packet, ignoring."); + Debug(5, "Received RTCP_APP packet, ignoring."); break; - } case RTCP_RR : - { - Error( "Received RTCP_RR packet." ); - return( -1 ); - } + Error("Received RTCP_RR packet."); + return -1; default : - { // Ignore unknown packet types. Some cameras do this by design. - Debug( 5, "Received unexpected packet type %d, ignoring", pt ); + Debug(5, "Received unexpected packet type %d, ignoring", pt); break; - } } consumed = sizeof(uint32_t)*(len+1); - return( consumed ); + return consumed; } -int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) -{ +int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) { RtcpPacket *rtcpPacket = (RtcpPacket *)packet; int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.rr)+sizeof(rtcpPacket->body.rr.rr[0]); @@ -180,11 +156,13 @@ int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) mRtpSource.updateRtcpStats(); - Debug( 5, "Ssrc = %d", mRtspThread.getSsrc()+1 ); - Debug( 5, "Ssrc_1 = %d", mRtpSource.getSsrc() ); - Debug( 5, "Last Seq = %d", mRtpSource.getMaxSeq() ); - Debug( 5, "Jitter = %d", mRtpSource.getJitter() ); - Debug( 5, "Last SR = %d", mRtpSource.getLastSrTimestamp() ); + Debug(5, "Ssrc = %d Ssrc_1 = %d Last Seq = %d Jitter = %d Last SR = %d", + mRtspThread.getSsrc()+1, + mRtpSource.getSsrc(), + mRtpSource.getMaxSeq(), + mRtpSource.getJitter(), + mRtpSource.getLastSrTimestamp() + ); rtcpPacket->body.rr.ssrcN = htonl(mRtspThread.getSsrc()+1); rtcpPacket->body.rr.rr[0].ssrcN = htonl(mRtpSource.getSsrc()); @@ -195,11 +173,10 @@ int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) rtcpPacket->body.rr.rr[0].lsrN = htonl(mRtpSource.getLastSrTimestamp()); rtcpPacket->body.rr.rr[0].dlsrN = 0; - return( wordLen*sizeof(uint32_t) ); -} + return wordLen*sizeof(uint32_t); +} // end RtpCtrlThread::generateRr -int RtpCtrlThread::generateSdes( const unsigned char *packet, ssize_t packetLen ) -{ +int RtpCtrlThread::generateSdes( const unsigned char *packet, ssize_t packetLen ) { RtcpPacket *rtcpPacket = (RtcpPacket *)packet; const std::string &cname = mRtpSource.getCname(); @@ -218,11 +195,10 @@ int RtpCtrlThread::generateSdes( const unsigned char *packet, ssize_t packetLen rtcpPacket->body.sdes.item[0].len = cname.size(); memcpy( rtcpPacket->body.sdes.item[0].data, cname.data(), cname.size() ); - return( wordLen*sizeof(uint32_t) ); -} + return wordLen*sizeof(uint32_t); +} // end RtpCtrlThread::generateSdes -int RtpCtrlThread::generateBye( const unsigned char *packet, ssize_t packetLen ) -{ +int RtpCtrlThread::generateBye( const unsigned char *packet, ssize_t packetLen ) { RtcpPacket *rtcpPacket = (RtcpPacket *)packet; int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.bye)+sizeof(rtcpPacket->body.bye.srcN[0]); @@ -236,11 +212,10 @@ int RtpCtrlThread::generateBye( const unsigned char *packet, ssize_t packetLen ) rtcpPacket->body.bye.srcN[0] = htonl(mRtpSource.getSsrc()); - return( wordLen*sizeof(uint32_t) ); -} + return wordLen*sizeof(uint32_t); +} // end RtpCtrolThread::generateBye -int RtpCtrlThread::recvPackets( unsigned char *buffer, ssize_t nBytes ) -{ +int RtpCtrlThread::recvPackets( unsigned char *buffer, ssize_t nBytes ) { unsigned char *bufferPtr = buffer; // u_int32 len; /* length of compound RTCP packet in words */ @@ -259,33 +234,28 @@ int RtpCtrlThread::recvPackets( unsigned char *buffer, ssize_t nBytes ) // /* something wrong with packet format */ // } - while ( nBytes > 0 ) - { + while ( nBytes > 0 ) { int consumed = recvPacket( bufferPtr, nBytes ); if ( consumed <= 0 ) break; bufferPtr += consumed; nBytes -= consumed; } - return( nBytes ); + return nBytes; } -int RtpCtrlThread::run() -{ +int RtpCtrlThread::run() { Debug( 2, "Starting control thread %x on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); SockAddrInet localAddr, remoteAddr; bool sendReports; UdpInetSocket rtpCtrlServer; - if ( mRtpSource.getLocalHost() != "" ) - { + if ( mRtpSource.getLocalHost() != "" ) { if ( !rtpCtrlServer.bind( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ) ) Fatal( "Failed to bind RTCP server" ); sendReports = false; Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); - } - else - { + } else { if ( !rtpCtrlServer.bind( mRtspThread.getAddressFamily() == AF_INET6 ? "::" : "0.0.0.0", mRtpSource.getLocalCtrlPort() ) ) Fatal( "Failed to bind RTCP server" ); Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); @@ -309,17 +279,17 @@ int RtpCtrlThread::run() time_t now = time(NULL); Select::CommsList readable = select.getReadable(); - if ( readable.size() == 0 ) - { + if ( readable.size() == 0 ) { if ( ! timeout ) { // With this code here, we will send an SDES and RR packet every 10 seconds ssize_t nBytes; unsigned char *bufferPtr = buffer; bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - Debug( 3, "Preventing timeout by sending %zd bytes on sd %d. Time since last receive: %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc(), ( now-last_receive) ); - if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) - Error( "Unable to send: %s", strerror( errno ) ); + Debug( 3, "Preventing timeout by sending %zd bytes on sd %d. Time since last receive: %d", + bufferPtr-buffer, rtpCtrlServer.getWriteDesc(), ( now-last_receive) ); + if ( (nBytes = rtpCtrlServer.send(buffer, bufferPtr-buffer)) < 0 ) + Error("Unable to send: %s", strerror(errno)); timeout = true; continue; } else { @@ -332,25 +302,21 @@ int RtpCtrlThread::run() timeout = false; last_receive = time(NULL); } - for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter ) - { - if ( UdpInetSocket *socket = dynamic_cast(*iter) ) - { + for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); ++iter ) { + if ( UdpInetSocket *socket = dynamic_cast(*iter) ) { ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); Debug( 4, "Read %zd bytes on sd %d", nBytes, socket->getReadDesc() ); - if ( nBytes ) - { + if ( nBytes ) { recvPackets( buffer, nBytes ); - if ( sendReports ) - { + if ( sendReports ) { unsigned char *bufferPtr = buffer; bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - Debug( 3, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc() ); + Debug(3, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc()); if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) - Error( "Unable to send: %s", strerror( errno ) ); + Error("Unable to send: %s", strerror(errno)); //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); } } else { @@ -358,16 +324,14 @@ int RtpCtrlThread::run() mStop = true; break; } - } - else - { - Panic( "Barfed" ); - } - } + } else { + Panic("Barfed"); + } // end if socket + } // end foeach comms iterator } rtpCtrlServer.close(); mRtspThread.stop(); - return( 0 ); + return 0; } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtp_ctrl.h b/src/zm_rtp_ctrl.h index 6d8f3024c..9e5306f92 100644 --- a/src/zm_rtp_ctrl.h +++ b/src/zm_rtp_ctrl.h @@ -34,13 +34,11 @@ class RtspThread; class RtpSource; -class RtpCtrlThread : public Thread -{ +class RtpCtrlThread : public Thread { friend class RtspThread; private: - typedef enum - { + typedef enum { RTCP_SR = 200, RTCP_RR = 201, RTCP_SDES = 202, @@ -48,8 +46,7 @@ private: RTCP_APP = 204 } RtcpType; - typedef enum - { + typedef enum { RTCP_SDES_END = 0, RTCP_SDES_CNAME = 1, RTCP_SDES_NAME = 2, @@ -61,8 +58,7 @@ private: RTCP_SDES_PRIV = 8 } RtcpSdesType; - struct RtcpCommonHeader - { + struct RtcpCommonHeader { uint8_t count:5; // varies by packet type uint8_t p:1; // padding flag uint8_t version:2; // protocol version @@ -71,8 +67,7 @@ private: }; // Reception report block - struct RtcpRr - { + struct RtcpRr { uint32_t ssrcN; // data source being reported int32_t lost:24; // cumul. no. pkts lost (signed!) uint32_t fraction:8; // fraction lost since last SR/RR @@ -83,22 +78,18 @@ private: }; // SDES item - struct RtcpSdesItem - { + struct RtcpSdesItem { uint8_t type; // type of item (rtcp_sdes_type_t) uint8_t len; // length of item (in octets) char data[]; // text, not null-terminated }; // RTCP packet - struct RtcpPacket - { + struct RtcpPacket { RtcpCommonHeader header; // common header - union - { + union { // Sender Report (SR) - struct Sr - { + struct Sr { uint32_t ssrcN; // sender generating this report, network order uint32_t ntpSecN; // NTP timestamp, network order uint32_t ntpFracN; @@ -109,22 +100,19 @@ private: } sr; // Reception Report (RR) - struct Rr - { + struct Rr { uint32_t ssrcN; // receiver generating this report RtcpRr rr[]; // variable-length list } rr; // source description (SDES) - struct Sdes - { + struct Sdes { uint32_t srcN; // first SSRC/CSRC RtcpSdesItem item[]; // list of SDES items } sdes; // BYE - struct - { + struct { uint32_t srcN[]; // list of sources // can't express trailing text for reason (what does this mean? it's not even english!) } bye; @@ -148,8 +136,7 @@ private: public: RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ); - void stop() - { + void stop() { mStop = true; } }; diff --git a/src/zm_rtp_source.cpp b/src/zm_rtp_source.cpp index 0cd838902..02e8ed0c5 100644 --- a/src/zm_rtp_source.cpp +++ b/src/zm_rtp_source.cpp @@ -26,7 +26,17 @@ #if HAVE_LIBAVCODEC -RtpSource::RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime, _AVCODECID codecId ) : +RtpSource::RtpSource( + int id, + const std::string &localHost, + int localPortBase, + const std::string &remoteHost, + int remotePortBase, + uint32_t ssrc, + uint16_t seq, + uint32_t rtpClock, + uint32_t rtpTime, + _AVCODECID codecId ) : mId( id ), mSsrc( ssrc ), mLocalHost( localHost ), @@ -65,13 +75,12 @@ RtpSource::RtpSource( int id, const std::string &localHost, int localPortBase, c mLastSrTimeNtp = tvZero(); mLastSrTimeRtp = 0; - if(mCodecId != AV_CODEC_ID_H264 && mCodecId != AV_CODEC_ID_MPEG4) - Warning( "The device is using a codec that may not be supported. Do not be surprised if things don't work." ); + if ( mCodecId != AV_CODEC_ID_H264 && mCodecId != AV_CODEC_ID_MPEG4 ) + Warning("The device is using a codec (%d) that may not be supported. Do not be surprised if things don't work.", mCodecId); } -void RtpSource::init( uint16_t seq ) -{ - Debug( 3, "Initialising sequence" ); +void RtpSource::init( uint16_t seq ) { + Debug(3, "Initialising sequence"); mBaseSeq = seq; mMaxSeq = seq; mBadSeq = RTP_SEQ_MOD + 1; // so seq == mBadSeq is false @@ -84,77 +93,58 @@ void RtpSource::init( uint16_t seq ) mTransit = 0; } -bool RtpSource::updateSeq( uint16_t seq ) -{ +bool RtpSource::updateSeq( uint16_t seq ) { uint16_t uDelta = seq - mMaxSeq; // Source is not valid until MIN_SEQUENTIAL packets with // sequential sequence numbers have been received. Debug( 5, "Seq: %d", seq ); - if ( mProbation) - { + if ( mProbation) { // packet is in sequence - if ( seq == mMaxSeq + 1) - { + if ( seq == mMaxSeq + 1) { Debug( 3, "Sequence in probation %d, in sequence", mProbation ); mProbation--; mMaxSeq = seq; - if ( mProbation == 0 ) - { + if ( mProbation == 0 ) { init( seq ); mReceivedPackets++; return( true ); } - } - else - { + } else { Warning( "Sequence in probation %d, out of sequence", mProbation ); mProbation = MIN_SEQUENTIAL - 1; mMaxSeq = seq; return( false ); } return( true ); - } - else if ( uDelta < MAX_DROPOUT ) - { - if ( uDelta == 1 ) - { + } else if ( uDelta < MAX_DROPOUT ) { + if ( uDelta == 1 ) { Debug( 4, "Packet in sequence, gap %d", uDelta ); - } - else - { + } else { Warning( "Packet in sequence, gap %d", uDelta ); } // in order, with permissible gap - if ( seq < mMaxSeq ) - { + if ( seq < mMaxSeq ) { // Sequence number wrapped - count another 64K cycle. mCycles += RTP_SEQ_MOD; } mMaxSeq = seq; - } - else if ( uDelta <= RTP_SEQ_MOD - MAX_MISORDER ) - { + } else if ( uDelta <= RTP_SEQ_MOD - MAX_MISORDER ) { Warning( "Packet out of sequence, gap %d", uDelta ); // the sequence number made a very large jump - if ( seq == mBadSeq ) - { + if ( seq == mBadSeq ) { Debug( 3, "Restarting sequence" ); // Two sequential packets -- assume that the other side // restarted without telling us so just re-sync // (i.e., pretend this was the first packet). init( seq ); - } - else - { + } else { mBadSeq = (seq + 1) & (RTP_SEQ_MOD-1); return( false ); } - } - else - { + } else { Warning( "Packet duplicate or reordered, gap %d", uDelta ); // duplicate or reordered packet return( false ); @@ -163,10 +153,8 @@ bool RtpSource::updateSeq( uint16_t seq ) return( uDelta==1?true:false ); } -void RtpSource::updateJitter( const RtpDataHeader *header ) -{ - if ( mRtpFactor > 0 ) - { +void RtpSource::updateJitter( const RtpDataHeader *header ) { + if ( mRtpFactor > 0 ) { Debug( 5, "Delta rtp = %.6f", tvDiffSec( mBaseTimeReal ) ); uint32_t localTimeRtp = mBaseTimeRtp + uint32_t( tvDiffSec( mBaseTimeReal ) * mRtpFactor ); Debug( 5, "Local RTP time = %x", localTimeRtp ); @@ -174,8 +162,7 @@ void RtpSource::updateJitter( const RtpDataHeader *header ) uint32_t packetTransit = localTimeRtp - ntohl(header->timestampN); Debug( 5, "Packet transit RTP time = %x", packetTransit ); - if ( mTransit > 0 ) - { + if ( mTransit > 0 ) { // Jitter int d = packetTransit - mTransit; Debug( 5, "Jitter D = %d", d ); @@ -185,28 +172,22 @@ void RtpSource::updateJitter( const RtpDataHeader *header ) mJitter += d - ((mJitter + 8) >> 4); } mTransit = packetTransit; - } - else - { + } else { mJitter = 0; } Debug( 5, "RTP Jitter: %d", mJitter ); } -void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ) -{ +void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ) { struct timeval ntpTime = tvMake( ntpTimeSecs, suseconds_t((USEC_PER_SEC*(ntpTimeFrac>>16))/(1<<16)) ); Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); - if ( mBaseTimeNtp.tv_sec == 0 ) - { + if ( mBaseTimeNtp.tv_sec == 0 ) { mBaseTimeReal = tvNow(); mBaseTimeNtp = ntpTime; mBaseTimeRtp = rtpTime; - } - else if ( !mRtpClock ) - { + } else if ( !mRtpClock ) { Debug( 5, "lastSrNtpTime: %ld.%06ld, rtpTime: %x", mLastSrTimeNtp.tv_sec, mLastSrTimeNtp.tv_usec, rtpTime ); Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); @@ -227,8 +208,7 @@ void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint mLastSrTimeRtp = rtpTime; } -void RtpSource::updateRtcpStats() -{ +void RtpSource::updateRtcpStats() { uint32_t extendedMax = mCycles + mMaxSeq; mExpectedPackets = extendedMax - mBaseSeq + 1; @@ -255,8 +235,7 @@ void RtpSource::updateRtcpStats() Debug( 5, "Lost fraction = %d", mLostFraction ); } -bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) -{ +bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) { const RtpDataHeader *rtpHeader; rtpHeader = (RtpDataHeader *)packet; int rtpHeaderSize = 12 + rtpHeader->cc * 4; @@ -269,39 +248,29 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) // that there is no marker bit by changing the number of bits in the payload type field. bool thisM = rtpHeader->m || h264FragmentEnd; - if ( updateSeq( ntohs(rtpHeader->seqN) ) ) - { + if ( updateSeq( ntohs(rtpHeader->seqN) ) ) { Hexdump( 4, packet+rtpHeaderSize, 16 ); - if ( mFrameGood ) - { + if ( mFrameGood ) { int extraHeader = 0; - if( mCodecId == AV_CODEC_ID_H264 ) - { + if ( mCodecId == AV_CODEC_ID_H264 ) { int nalType = (packet[rtpHeaderSize] & 0x1f); Debug( 3, "Have H264 frame: nal type is %d", nalType ); - switch (nalType) - { + switch (nalType) { case 24: // STAP-A - { extraHeader = 2; break; - } case 25: // STAP-B case 26: // MTAP-16 case 27: // MTAP-24 - { extraHeader = 3; break; - } // FU-A and FU-B case 28: case 29: - { // Is this NAL the first NAL in fragmentation sequence - if ( packet[rtpHeaderSize+1] & 0x80 ) - { + if ( packet[rtpHeaderSize+1] & 0x80 ) { // Now we will form new header of frame mFrame.append( "\x0\x0\x1\x0", 4 ); // Reconstruct NAL header from FU headers @@ -311,17 +280,14 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) extraHeader = 2; break; - } default: - { Debug(3, "Unhandled nalType %d", nalType ); - } } // Append NAL frame start code if ( !mFrame.size() ) mFrame.append( "\x0\x0\x1", 3 ); - } + } // end if H264 mFrame.append( packet+rtpHeaderSize+extraHeader, packetLen-rtpHeaderSize-extraHeader ); } else { Debug( 3, "NOT H264 frame: type is %d", mCodecId ); @@ -329,16 +295,13 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) Hexdump( 4, mFrame.head(), 16 ); - if ( thisM ) - { - if ( mFrameGood ) - { + if ( thisM ) { + if ( mFrameGood ) { Debug( 3, "Got new frame %d, %d bytes", mFrameCount, mFrame.size() ); mFrameProcessed.setValueImmediate( false ); mFrameReady.updateValueSignal( true ); - if ( !mFrameProcessed.getValueImmediate() ) - { + if ( !mFrameProcessed.getValueImmediate() ) { // What is the point of this for loop? Is it just me, or will it call getUpdatedValue once or twice? Could it not be better written as // if ( ! mFrameProcessed.getUpdatedValue( 1 ) && mFrameProcessed.getUpdatedValue( 1 ) ) return false; @@ -347,45 +310,34 @@ bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) return( false ); } mFrameCount++; - } - else - { + } else { Warning( "Discarding incomplete frame %d, %d bytes", mFrameCount, mFrame.size() ); } mFrame.clear(); } - } - else - { - if ( mFrame.size() ) - { + } else { + if ( mFrame.size() ) { Warning( "Discarding partial frame %d, %d bytes", mFrameCount, mFrame.size() ); - } - else - { + } else { Warning( "Discarding frame %d", mFrameCount ); } mFrameGood = false; mFrame.clear(); } - if ( thisM ) - { + if ( thisM ) { mFrameGood = true; prevM = true; - } - else + } else prevM = false; updateJitter( rtpHeader ); - return( true ); + return true; } -bool RtpSource::getFrame( Buffer &buffer ) -{ +bool RtpSource::getFrame( Buffer &buffer ) { Debug( 3, "Getting frame" ); - if ( !mFrameReady.getValueImmediate() ) - { + if ( !mFrameReady.getValueImmediate() ) { // Allow for a couple of spurious returns for ( int count = 0; !mFrameReady.getUpdatedValue( 1 ); count++ ) if ( count > 1 ) @@ -395,7 +347,7 @@ bool RtpSource::getFrame( Buffer &buffer ) mFrameReady.setValueImmediate( false ); mFrameProcessed.updateValueSignal( true ); Debug( 4, "Copied %d bytes", buffer.size() ); - return( true ); + return true; } #endif // HAVE_LIBAVCODEC diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 703328e2e..5e2858e4f 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -46,53 +46,54 @@ bool RtspThread::sendCommand( std::string message ) { message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq ); Debug( 2, "Sending RTSP message: %s", message.c_str() ); 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() ) { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( false ); + message = base64Encode(message); + Debug(2, "Sending encoded RTSP message: %s", message.c_str()); + 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() ) { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( false ); + 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; } } - return( true ); + return true; } 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() ); + 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 ( 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() ); + Error("Response parse failure in '%s'", response.c_str()); } else { - Error( "Response parse failure, %zd bytes follow", response.size() ); + Error("Response parse failure, %zd bytes follow", response.size()); if ( response.size() ) Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); } - return( false ); + 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 ); + return false; } else if ( respCode != 200 ) { - Error( "Unexpected response code %d, text is '%s'", respCode, respText ); - return( false ); + Error("Unexpected response code %d, text is '%s'", respCode, respText); + return false; } - return( true ); -} + return true; +} // end RtspThread::recResponse int RtspThread::requestPorts() { if ( !smMinDataPort ) { char sql[ZM_SQL_SML_BUFSIZ]; + //FIXME Why not load specifically by Id? This will get ineffeicient with a lot of monitors 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 ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); @@ -107,7 +108,7 @@ int RtspThread::requestPorts() { int nMonitors = mysql_num_rows( result ); int position = 0; if ( nMonitors ) { - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) { + for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { int id = atoi(dbrow[0]); if ( mId == id ) { position = i; @@ -126,22 +127,30 @@ int RtspThread::requestPorts() { Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort ); } for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) { - PortSet::const_iterator iter = smAssignedPorts.find( i ); + PortSet::const_iterator iter = smAssignedPorts.find(i); if ( iter == smAssignedPorts.end() ) { - smAssignedPorts.insert( i ); - return( i ); + smAssignedPorts.insert(i); + return i; } } - Panic( "Can assign RTP port, no ports left in pool" ); - return( -1 ); + Panic("Can assign RTP port, no ports left in pool"); + return -1; } void RtspThread::releasePorts( int port ) { if ( port > 0 ) - smAssignedPorts.erase( port ); + smAssignedPorts.erase(port); } -RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe) : +RtspThread::RtspThread( + int id, + RtspMethod method, + const std::string &protocol, + const std::string &host, + const std::string &port, + const std::string &path, + const std::string &auth, + bool rtsp_describe) : mId( id ), mMethod( method ), mProtocol( protocol ), @@ -168,10 +177,10 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, mSsrc = rand(); - Debug( 2, "RTSP Local SSRC is %x", mSsrc ); + Debug(2, "RTSP Local SSRC is %x", mSsrc); if ( mMethod == RTP_RTSP_HTTP ) - mHttpSession = stringtf( "%d", rand() ); + mHttpSession = stringtf("%d", rand()); mNeedAuth = false; StringVector parts = split(auth,":"); @@ -216,8 +225,8 @@ int RtspThread::run() { bool authTried = false; if ( mMethod == RTP_RTSP_HTTP ) { - if ( !mRtspSocket2.connect( mHost.c_str(), mPort.c_str() ) ) - Fatal( "Unable to connect auxiliary RTSP/HTTP socket" ); + if ( !mRtspSocket2.connect(mHost.c_str(), mPort.c_str()) ) + Fatal("Unable to connect auxiliary RTSP/HTTP socket"); //Select select( 0.25 ); //select.addReader( &mRtspSocket2 ); //while ( select.wait() ) @@ -240,15 +249,15 @@ int RtspThread::run() { message += "\r\n"; Debug( 2, "Sending HTTP message: %s", message.c_str() ); 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 ); + Error("Unable to send message '%s': %s", message.c_str(), strerror(errno)); + return -1; } if ( mRtspSocket.recv( response ) < 0 ) { - Error( "Recv failed; %s", strerror(errno) ); - return( -1 ); + Error("Recv failed; %s", strerror(errno)); + return -1; } - Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() ); + 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 ) { @@ -259,25 +268,25 @@ int RtspThread::run() { if ( response.size() ) Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); } - return( -1 ); + return -1; } // If Server requests authentication, check WWW-Authenticate header and fill required fields // for requested authentication method - if (respCode == 401 && !authTried) { + if ( respCode == 401 && !authTried ) { mNeedAuth = true; mAuthenticator->checkAuthResponse(response); Debug(2, "Processed 401 response"); mRtspSocket.close(); - if ( !mRtspSocket.connect( mHost.c_str(), mPort.c_str() ) ) - Fatal( "Unable to reconnect RTSP socket" ); + if ( !mRtspSocket.connect(mHost.c_str(), mPort.c_str()) ) + Fatal("Unable to reconnect RTSP socket"); Debug(2, "connection should be reopened now"); } } while (respCode == 401 && !authTried); if ( respCode != 200 ) { - Error( "Unexpected response code %d, text is '%s'", respCode, respText ); - return( -1 ); + Error("Unexpected response code %d, text is '%s'", respCode, respText); + return -1; } message = "POST "+mPath+" HTTP/1.0\r\n"; @@ -300,25 +309,25 @@ int RtspThread::run() { // Request supported RTSP commands by the server message = "OPTIONS "+mUrl+" RTSP/1.0\r\n"; if ( !sendCommand( message ) ) - return( -1 ); + return -1; // A negative return here may indicate auth failure, but we will have setup the auth mechanisms so we need to retry. - if ( !recvResponse( response ) ) { + if ( !recvResponse(response) ) { if ( mNeedAuth ) { Debug( 2, "Resending OPTIONS due to possible auth requirement" ); - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); + if ( !sendCommand(message) ) + return -1; + if ( !recvResponse(response) ) + return -1; } else { - return( -1 ); + return -1; } } // end if failed response maybe due to auth char publicLine[256] = ""; - StringVector lines = split( response, "\r\n" ); + StringVector lines = split(response, "\r\n"); for ( size_t i = 0; i < lines.size(); i++ ) - sscanf( lines[i].c_str(), "Public: %[^\r\n]\r\n", publicLine ); + sscanf(lines[i].c_str(), "Public: %[^\r\n]\r\n", publicLine); // Check if the server supports the GET_PARAMETER command // If yes, it is likely that the server will request this command as a keepalive message @@ -331,44 +340,45 @@ int RtspThread::run() { do { if (mNeedAuth) authTried = true; - sendCommand( message ); - sleep( 1 ); - res = recvResponse( response ); - if (!res && respCode==401) + sendCommand(message); + // FIXME WHy sleep 1? + sleep(1); + res = recvResponse(response); + if ( !res && respCode==401 ) mNeedAuth = true; } while (!res && respCode==401 && !authTried); const std::string endOfHeaders = "\r\n\r\n"; - size_t sdpStart = response.find( endOfHeaders ); - if( sdpStart == std::string::npos ) - return( -1 ); + size_t sdpStart = response.find(endOfHeaders); + if ( sdpStart == std::string::npos ) + return -1; if ( mRtspDescribe ) { - std::string DescHeader = response.substr( 0,sdpStart ); - Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() ); + std::string DescHeader = response.substr(0, sdpStart); + Debug(1, "Processing DESCRIBE response header '%s'", DescHeader.c_str()); - lines = split( DescHeader, "\r\n" ); + lines = split(DescHeader, "\r\n"); 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:" ) ) { - mUrl = trimSpaces( lines[i].substr( 13 ) ); - Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); - break; - } + // 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:" ) ) { + mUrl = trimSpaces( lines[i].substr( 13 ) ); + Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); + break; } - } + } // end foreach line + } // end if mRtspDescribe sdpStart += endOfHeaders.length(); - std::string sdp = response.substr( sdpStart ); - Debug( 1, "Processing SDP '%s'", sdp.c_str() ); + std::string sdp = response.substr(sdpStart); + Debug(1, "Processing SDP '%s'", sdp.c_str()); try { mSessDesc = new SessionDescriptor( mUrl, sdp ); mFormatContext = mSessDesc->generateFormatContext(); } catch( const Exception &e ) { Error( e.getMessage().c_str() ); - return( -1 ); + return -1; } #if 0 @@ -672,51 +682,36 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali Hexdump( 4, (char *)buffer, 16 ); rtpDataThread.recvPacket( buffer+4, len ); Debug( 4, "Received" ); - } - else if ( channel == remoteChannels[1] ) - { + } else if ( channel == remoteChannels[1] ) { // len = ntohs( *((unsigned short *)(buffer+2)) ); // Debug( 4, "Got %d bytes on control channel %d", nBytes, channel ); Debug( 4, "Got %d bytes on control channel %d, packet length is %d", buffer.size(), channel, len ); Hexdump( 4, (char *)buffer, 16 ); rtpCtrlThread.recvPackets( buffer+4, len ); - } - else - { + } else { Error( "Unexpected channel selector %d in RTSP interleaved data", buffer[1] ); buffer.clear(); break; } buffer.consume( len+4 ); nBytes -= len+4; - } - else - { - if ( keepaliveResponse.compare( 0, keepaliveResponse.size(), (char *)buffer, keepaliveResponse.size() ) == 0 ) - { + } else { + if ( keepaliveResponse.compare( 0, keepaliveResponse.size(), (char *)buffer, keepaliveResponse.size() ) == 0 ) { Debug( 4, "Got keepalive response '%s'", (char *)buffer ); //buffer.consume( keepaliveResponse.size() ); - if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) - { + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) { int discardBytes = charPtr-(char *)buffer; buffer -= discardBytes; - } - else - { + } else { buffer.clear(); } - } - else - { - if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) - { + } else { + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) { int discardBytes = charPtr-(char *)buffer; Warning( "Unexpected format RTSP interleaved data, resyncing by %d bytes", discardBytes ); Hexdump( -1, (char *)buffer, discardBytes ); buffer -= discardBytes; - } - else - { + } else { Warning( "Unexpected format RTSP interleaved data, dumping %d bytes", buffer.size() ); Hexdump( -1, (char *)buffer, 32 ); buffer.clear(); @@ -764,16 +759,14 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali rtpDataThread.start(); rtpCtrlThread.start(); - while( !mStop ) - { + while ( !mStop ) { // Send a keepalive message if the server supports this feature and we are close to the timeout expiration - if ( sendKeepalive && (timeout > 0) && ((time(NULL)-lastKeepalive) > (timeout-5)) ) - { + if ( sendKeepalive && (timeout > 0) && ((time(NULL)-lastKeepalive) > (timeout-5)) ) { if ( !sendCommand( message ) ) - return( -1 ); + return -1; lastKeepalive = time(NULL); } - usleep( 100000 ); + usleep(100000); } #if 0 message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; @@ -783,10 +776,10 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali return( -1 ); #endif message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); + if ( !sendCommand(message) ) + return -1; + if ( !recvResponse(response) ) + return -1; rtpDataThread.stop(); rtpCtrlThread.stop(); @@ -801,13 +794,11 @@ Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepali break; } default: - { - Panic( "Got unexpected method %d", mMethod ); + Panic("Got unexpected method %d", mMethod); break; - } } - return( 0 ); + return 0; } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_sdp.cpp b/src/zm_sdp.cpp index af293d64a..c7bf1b578 100644 --- a/src/zm_sdp.cpp +++ b/src/zm_sdp.cpp @@ -26,17 +26,17 @@ #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { { 0, "PCMU", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_MULAW, 8000, 1 }, - { 3, "GSM", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 3, "GSM", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 4, "G723", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 5, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 6, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 16000, 1 }, - { 7, "LPC", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 7, "LPC", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 8, "PCMA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_ALAW, 8000, 1 }, { 9, "G722", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 10, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 2 }, { 11, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 1 }, { 12, "QCELP", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_QCELP, 8000, 1 }, - { 13, "CN", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 13, "CN", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP2, -1, -1 }, { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3, -1, -1 }, { 15, "G728", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, @@ -45,36 +45,36 @@ SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { { 18, "G729", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, { 25, "CelB", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, { 26, "JPEG", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MJPEG, 90000, -1 }, - { 28, "nv", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, + { 28, "nv", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, { 31, "H261", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H261, 90000, -1 }, { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG1VIDEO, 90000, -1 }, { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO, 90000, -1 }, { 33, "MP2T", AVMEDIA_TYPE_DATA, AV_CODEC_ID_MPEG2TS, 90000, -1 }, { 34, "H263", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H263, 90000, -1 }, - { -1, "", AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1 } + { -1, "", AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1 } }; SessionDescriptor::DynamicPayloadDesc SessionDescriptor::smDynamicPayloads[] = { - { "MP4V-ES", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, - { "mpeg4-generic", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, - { "H264", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, - { "AMR", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AMR_NB }, + { "MP4V-ES", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, + { "mpeg4-generic", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, + { "H264", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, + { "AMR", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AMR_NB }, { "vnd.onvif.metadata", AVMEDIA_TYPE_DATA, AV_CODEC_ID_NONE } }; #else SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { { 0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8001, 1 }, - { 3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1 }, - { 7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1 }, { 9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2 }, { 11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1 }, { 12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1 }, - { 13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, -1, -1 }, { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP3, -1, -1 }, { 15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, @@ -83,7 +83,7 @@ SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { { 18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, { 25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, { 26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1 }, - { 28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, { 31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1 }, { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1 }, { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1 }, @@ -105,7 +105,7 @@ SessionDescriptor::ConnInfo::ConnInfo( const std::string &connInfo ) : mTtl( 16 ), mNoAddresses( 0 ) { - StringVector tokens = split( connInfo, " " ); + StringVector tokens = split(connInfo, " "); if ( tokens.size() < 3 ) throw Exception( "Unable to parse SDP connection info from '"+connInfo+"'" ); mNetworkType = tokens[0]; @@ -136,7 +136,12 @@ SessionDescriptor::BandInfo::BandInfo( const std::string &bandInfo ) : mValue = atoi(tokens[1].c_str()); } -SessionDescriptor::MediaDescriptor::MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ) : +SessionDescriptor::MediaDescriptor::MediaDescriptor( + const std::string &type, + int port, + int numPorts, + const std::string &transport, + int payloadType ) : mType( type ), mPort( port ), mNumPorts( numPorts ), @@ -164,14 +169,13 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string if ( line.empty() ) break; - Debug( 3, "Processing SDP line '%s'", line.c_str() ); + Debug(3, "Processing SDP line '%s'", line.c_str()); const char sdpType = line[0]; if ( line[1] != '=' ) - throw Exception( "Invalid SDP format at '"+line+"'" ); + throw Exception("Invalid SDP format at '"+line+"'"); - line.erase( 0, 2 ); - switch( sdpType ) - { + line.erase(0, 2); + switch( sdpType ) { case 'v' : mVersion = line; break; @@ -204,19 +208,13 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string mAttributes.push_back( line ); StringVector tokens = split( line, ":", 2 ); std::string attrName = tokens[0]; - if ( currMedia ) - { - if ( attrName == "control" ) - { + if ( currMedia ) { + if ( attrName == "control" ) { if ( tokens.size() < 2 ) throw Exception( "Unable to parse SDP control attribute '"+line+"' for media '"+currMedia->getType()+"'" ); currMedia->setControlUrl( tokens[1] ); - } - else if ( attrName == "range" ) - { - } - else if ( attrName == "rtpmap" ) - { + } else if ( attrName == "range" ) { + } else if ( attrName == "rtpmap" ) { // a=rtpmap:96 MP4V-ES/90000 if ( tokens.size() < 2 ) throw Exception( "Unable to parse SDP rtpmap attribute '"+line+"' for media '"+currMedia->getType()+"'" ); @@ -226,53 +224,46 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); std::string payloadDesc = attrTokens[1]; //currMedia->setPayloadType( payloadType ); - if ( attrTokens.size() > 1 ) - { + if ( attrTokens.size() > 1 ) { StringVector payloadTokens = split( attrTokens[1], "/" ); std::string payloadDesc = payloadTokens[0]; int payloadClock = atoi(payloadTokens[1].c_str()); currMedia->setPayloadDesc( payloadDesc ); currMedia->setClock( payloadClock ); } - } - else if ( attrName == "framesize" ) - { + } else if ( attrName == "framesize" ) { // a=framesize:96 320-240 if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP framesize attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - StringVector attrTokens = split( tokens[1], " " ); + throw Exception("Unable to parse SDP framesize attribute '"+line+"' for media '"+currMedia->getType()+"'"); + StringVector attrTokens = split(tokens[1], " "); int payloadType = atoi(attrTokens[0].c_str()); if ( payloadType != currMedia->getPayloadType() ) - throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + throw Exception( stringtf("Payload type mismatch, expected %d, got %d in '%s'", + currMedia->getPayloadType(), payloadType, line.c_str())); //currMedia->setPayloadType( payloadType ); - StringVector sizeTokens = split( attrTokens[1], "-" ); + StringVector sizeTokens = split(attrTokens[1], "-"); int width = atoi(sizeTokens[0].c_str()); int height = atoi(sizeTokens[1].c_str()); - currMedia->setFrameSize( width, height ); - } - else if ( attrName == "framerate" ) - { + currMedia->setFrameSize(width, height); + } else if ( attrName == "framerate" ) { // a=framerate:5.0 if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP framerate attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + throw Exception("Unable to parse SDP framerate attribute '"+line+"' for media '"+currMedia->getType()+"'"); double frameRate = atof(tokens[1].c_str()); - currMedia->setFrameRate( frameRate ); - } - else if ( attrName == "fmtp" ) - { + currMedia->setFrameRate(frameRate); + } else if ( attrName == "fmtp" ) { // a=fmtp:96 profile-level-id=247; config=000001B0F7000001B509000001000000012008D48D8803250F042D14440F if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP fmtp attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - StringVector attrTokens = split( tokens[1], " ", 2 ); + throw Exception("Unable to parse SDP fmtp attribute '"+line+"' for media '"+currMedia->getType()+"'"); + StringVector attrTokens = split(tokens[1], " ", 2); int payloadType = atoi(attrTokens[0].c_str()); if ( payloadType != currMedia->getPayloadType() ) - throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + throw Exception(stringtf("Payload type mismatch, expected %d, got %d in '%s'", + currMedia->getPayloadType(), payloadType, line.c_str())); //currMedia->setPayloadType( payloadType ); - if ( attrTokens.size() > 1 ) - { + if ( attrTokens.size() > 1 ) { StringVector attr2Tokens = split( attrTokens[1], "; " ); - for ( unsigned int i = 0; i < attr2Tokens.size(); i++ ) - { + for ( unsigned int i = 0; i < attr2Tokens.size(); i++ ) { StringVector attr3Tokens = split( attr2Tokens[i], "=" ); //Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() ); if ( attr3Tokens[0] == "profile-level-id" ) { @@ -292,40 +283,39 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string } else if ( attrName == "mpeg4-esid" ) { // a=mpeg4-esid:201 } else { - Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() ) + Debug(3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str()); } } else { - Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() ); + Debug(3, "Ignoring general SDP attribute '%s'", line.c_str()); } break; } case 'm' : { - StringVector tokens = split( line, " " ); + StringVector tokens = split(line, " "); if ( tokens.size() < 4 ) - throw Exception( "Can't parse SDP media description '"+line+"'" ); + throw Exception("Can't parse SDP media description '"+line+"'"); std::string mediaType = tokens[0]; if ( mediaType != "audio" && mediaType != "video" && mediaType != "application" ) - throw Exception( "Unsupported media type '"+mediaType+"' in SDP media attribute '"+line+"'" ); - StringVector portTokens = split( tokens[1], "/" ); + throw Exception("Unsupported media type '"+mediaType+"' in SDP media attribute '"+line+"'"); + StringVector portTokens = split(tokens[1], "/"); int mediaPort = atoi(portTokens[0].c_str()); int mediaNumPorts = 1; if ( portTokens.size() > 1 ) mediaNumPorts = atoi(portTokens[1].c_str()); std::string mediaTransport = tokens[2]; if ( mediaTransport != "RTP/AVP" ) - throw Exception( "Unsupported media transport '"+mediaTransport+"' in SDP media attribute '"+line+"'" ); + throw Exception("Unsupported media transport '"+mediaTransport+"' in SDP media attribute '"+line+"'"); int payloadType = atoi(tokens[3].c_str()); - currMedia = new MediaDescriptor( mediaType, mediaPort, mediaNumPorts, mediaTransport, payloadType ); - mMediaList.push_back( currMedia ); + currMedia = new MediaDescriptor(mediaType, mediaPort, mediaNumPorts, mediaTransport, payloadType); + mMediaList.push_back(currMedia); break; } - } - } + } // end switch + } // end foreach line } -SessionDescriptor::~SessionDescriptor() -{ +SessionDescriptor::~SessionDescriptor() { if ( mConnInfo ) delete mConnInfo; if ( mBandInfo ) @@ -334,8 +324,7 @@ SessionDescriptor::~SessionDescriptor() delete mMediaList[i]; } -AVFormatContext *SessionDescriptor::generateFormatContext() const -{ +AVFormatContext *SessionDescriptor::generateFormatContext() const { AVFormatContext *formatContext = avformat_alloc_context(); #if (LIBAVFORMAT_VERSION_CHECK(58, 12, 0, 0, 100)) @@ -353,35 +342,40 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const for ( unsigned int i = 0; i < mMediaList.size(); i++ ) { const MediaDescriptor *mediaDesc = mMediaList[i]; #if !LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0) - AVStream *stream = av_new_stream( formatContext, i ); + AVStream *stream = av_new_stream(formatContext, i); #else - AVStream *stream = avformat_new_stream( formatContext, NULL ); + AVStream *stream = avformat_new_stream(formatContext, NULL); stream->id = i; #endif #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) AVCodecContext *codec_context = avcodec_alloc_context3(NULL); avcodec_parameters_to_context(codec_context, stream->codecpar); + stream->codec = codec_context; #else AVCodecContext *codec_context = stream->codec; #endif - Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); + std::string type = mediaDesc->getType(); + Debug(1, "Looking for codec for %s payload type %d / %s", + type.c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str()); #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - if ( mediaDesc->getType() == "video" ) + if ( type == "video" ) codec_context->codec_type = AVMEDIA_TYPE_VIDEO; - else if ( mediaDesc->getType() == "audio" ) + else if ( type == "audio" ) codec_context->codec_type = AVMEDIA_TYPE_AUDIO; - else if ( mediaDesc->getType() == "application" ) + else if ( type == "application" ) codec_context->codec_type = AVMEDIA_TYPE_DATA; #else - if ( mediaDesc->getType() == "video" ) + if ( type == "video" ) codec_context->codec_type = CODEC_TYPE_VIDEO; - else if ( mediaDesc->getType() == "audio" ) + else if ( type == "audio" ) codec_context->codec_type = CODEC_TYPE_AUDIO; - else if ( mediaDesc->getType() == "application" ) + else if ( type == "application" ) codec_context->codec_type = CODEC_TYPE_DATA; #endif + else + Warning("Unknown media_type %s", type.c_str()); #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) std::string codec_name; @@ -392,9 +386,9 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) { Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName ); #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - codec_name = std::string( smStaticPayloads[i].payloadName ); + codec_name = std::string(smStaticPayloads[i].payloadName); #else - strncpy( codec_context->codec_name, smStaticPayloads[i].payloadName, sizeof(codec_context->codec_name) );; + strncpy(codec_context->codec_name, smStaticPayloads[i].payloadName, sizeof(codec_context->codec_name)); #endif codec_context->codec_type = smStaticPayloads[i].codecType; codec_context->codec_id = smStaticPayloads[i].codecId; @@ -406,11 +400,11 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const // Look in dynamic table for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) { if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) { - Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName ); + Debug(1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName); #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - codec_name = std::string( smStaticPayloads[i].payloadName ); + codec_name = std::string(smStaticPayloads[i].payloadName); #else - strncpy( codec_context->codec_name, smDynamicPayloads[i].payloadName, sizeof(codec_context->codec_name) );; + strncpy(codec_context->codec_name, smDynamicPayloads[i].payloadName, sizeof(codec_context->codec_name)); #endif codec_context->codec_type = smDynamicPayloads[i].codecType; codec_context->codec_id = smDynamicPayloads[i].codecId; @@ -418,7 +412,7 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const break; } } - } + } /// end if static or dynamic #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) if ( codec_name.empty() ) @@ -426,7 +420,8 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const if ( !stream->codec->codec_name[0] ) #endif { - Warning( "Can't find payload details for %s payload type %d, name %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); + Warning( "Can't find payload details for %s payload type %d, name %s", + mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); //return( 0 ); } if ( mediaDesc->getWidth() ) @@ -449,11 +444,11 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const while (*value && *value != ',' && (dst - base64packet) < (long)(sizeof(base64packet)) - 1) { - *dst++ = *value++; + *dst++ = *value++; } *dst++ = '\0'; - if (*value == ',') + if ( *value == ',' ) value++; packet_size= av_base64_decode(decoded_packet, (const char *)base64packet, (int)sizeof(decoded_packet)); @@ -468,23 +463,23 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const FF_INPUT_BUFFER_PADDING_SIZE #endif ); - if(dest) { - if(codec_context->extradata_size) { - // av_realloc? + if ( dest ) { + if ( codec_context->extradata_size ) { + // av_realloc? memcpy(dest, codec_context->extradata, codec_context->extradata_size); - av_free(codec_context->extradata); - } + av_free(codec_context->extradata); + } - memcpy(dest+codec_context->extradata_size, start_sequence, sizeof(start_sequence)); - memcpy(dest+codec_context->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); - memset(dest+codec_context->extradata_size+sizeof(start_sequence)+ - packet_size, 0, + memcpy(dest+codec_context->extradata_size, start_sequence, sizeof(start_sequence)); + memcpy(dest+codec_context->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); + memset(dest+codec_context->extradata_size+sizeof(start_sequence)+ + packet_size, 0, #if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0) - AV_INPUT_BUFFER_PADDING_SIZE + AV_INPUT_BUFFER_PADDING_SIZE #else - FF_INPUT_BUFFER_PADDING_SIZE + FF_INPUT_BUFFER_PADDING_SIZE #endif -); + ); codec_context->extradata= dest; codec_context->extradata_size+= sizeof(start_sequence)+packet_size; @@ -497,7 +492,7 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const } } - return( formatContext ); + return formatContext; } #endif // HAVE_LIBAVFORMAT