2013-03-17 07:45:21 +08:00
//
// ZoneMinder SDP Class Implementation, $Date: 2009-04-14 21:20:02 +0100 (Tue, 14 Apr 2009) $, $Revision: 2850 $
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
2016-12-26 23:23:16 +08:00
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2013-03-17 07:45:21 +08:00
//
# include "zm.h"
# if HAVE_LIBAVFORMAT
# include "zm_sdp.h"
2015-05-29 23:38:02 +08:00
# if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
2013-03-17 07:45:21 +08:00
SessionDescriptor : : StaticPayloadDesc SessionDescriptor : : smStaticPayloads [ ] = {
2016-04-04 22:11:48 +08:00
{ 0 , " PCMU " , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_PCM_MULAW , 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 } ,
{ 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 } ,
{ 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 } ,
{ 16 , " DVI4 " , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_NONE , 11025 , 1 } ,
{ 17 , " DVI4 " , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_NONE , 22050 , 1 } ,
{ 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 } ,
{ 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 }
2013-03-17 07:45:21 +08:00
} ;
SessionDescriptor : : DynamicPayloadDesc SessionDescriptor : : smDynamicPayloads [ ] = {
2016-04-04 22:11:48 +08:00
{ " 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 }
2013-03-17 07:45:21 +08:00
} ;
# else
SessionDescriptor : : StaticPayloadDesc SessionDescriptor : : smStaticPayloads [ ] = {
2016-04-04 22:11:48 +08:00
{ 0 , " PCMU " , CODEC_TYPE_AUDIO , CODEC_ID_PCM_MULAW , 8001 , 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 } ,
{ 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 } ,
{ 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 } ,
{ 16 , " DVI4 " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , 11025 , 1 } ,
{ 17 , " DVI4 " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , 22050 , 1 } ,
{ 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 } ,
{ 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 } ,
{ 33 , " MP2T " , CODEC_TYPE_DATA , CODEC_ID_MPEG2TS , 90000 , - 1 } ,
{ 34 , " H263 " , CODEC_TYPE_VIDEO , CODEC_ID_H263 , 90000 , - 1 } ,
{ - 1 , " " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 }
2013-03-17 07:45:21 +08:00
} ;
SessionDescriptor : : DynamicPayloadDesc SessionDescriptor : : smDynamicPayloads [ ] = {
2016-04-04 22:11:48 +08:00
{ " MP4V-ES " , CODEC_TYPE_VIDEO , CODEC_ID_MPEG4 } ,
{ " mpeg4-generic " , CODEC_TYPE_AUDIO , CODEC_ID_AAC } ,
{ " H264 " , CODEC_TYPE_VIDEO , CODEC_ID_H264 } ,
{ " AMR " , CODEC_TYPE_AUDIO , CODEC_ID_AMR_NB } ,
{ " vnd.onvif.metadata " , CODEC_TYPE_DATA , CODEC_ID_NONE }
2013-03-17 07:45:21 +08:00
} ;
# endif
SessionDescriptor : : ConnInfo : : ConnInfo ( const std : : string & connInfo ) :
2016-04-04 22:11:48 +08:00
mTtl ( 16 ) ,
mNoAddresses ( 0 )
2013-03-17 07:45:21 +08:00
{
2016-04-04 22:11:48 +08:00
StringVector tokens = split ( connInfo , " " ) ;
if ( tokens . size ( ) < 3 )
throw Exception ( " Unable to parse SDP connection info from ' " + connInfo + " ' " ) ;
mNetworkType = tokens [ 0 ] ;
if ( mNetworkType ! = " IN " )
throw Exception ( " Invalid SDP network type ' " + mNetworkType + " ' in connection info ' " + connInfo + " ' " ) ;
mAddressType = tokens [ 1 ] ;
2016-05-06 20:32:21 +08:00
if ( mAddressType ! = " IP4 " & & mAddressType ! = " IP6 " )
2016-04-04 22:11:48 +08:00
throw Exception ( " Invalid SDP address type ' " + mAddressType + " ' in connection info ' " + connInfo + " ' " ) ;
StringVector addressTokens = split ( tokens [ 2 ] , " / " ) ;
if ( addressTokens . size ( ) < 1 )
throw Exception ( " Invalid SDP address ' " + tokens [ 2 ] + " ' in connection info ' " + connInfo + " ' " ) ;
mAddress = addressTokens [ 0 ] ;
if ( addressTokens . size ( ) > = 2 )
mTtl = atoi ( addressTokens [ 1 ] . c_str ( ) ) ;
if ( addressTokens . size ( ) > = 3 )
mNoAddresses = atoi ( addressTokens [ 2 ] . c_str ( ) ) ;
2013-03-17 07:45:21 +08:00
}
SessionDescriptor : : BandInfo : : BandInfo ( const std : : string & bandInfo ) :
2016-04-04 22:11:48 +08:00
mValue ( 0 )
2013-03-17 07:45:21 +08:00
{
2016-04-04 22:11:48 +08:00
StringVector tokens = split ( bandInfo , " : " ) ;
if ( tokens . size ( ) < 2 )
throw Exception ( " Unable to parse SDP bandwidth info from ' " + bandInfo + " ' " ) ;
mType = tokens [ 0 ] ;
//if ( mNetworkType != "IN" )
//throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" );
mValue = atoi ( tokens [ 1 ] . c_str ( ) ) ;
2013-03-17 07:45:21 +08:00
}
SessionDescriptor : : MediaDescriptor : : MediaDescriptor ( const std : : string & type , int port , int numPorts , const std : : string & transport , int payloadType ) :
2016-04-04 22:11:48 +08:00
mType ( type ) ,
mPort ( port ) ,
mNumPorts ( numPorts ) ,
mTransport ( transport ) ,
mPayloadType ( payloadType ) ,
mFrameRate ( 0.0 ) ,
mClock ( 0 ) ,
mWidth ( 0 ) ,
mHeight ( 0 ) ,
mSprops ( " " ) ,
mConnInfo ( 0 )
2013-03-17 07:45:21 +08:00
{
}
SessionDescriptor : : SessionDescriptor ( const std : : string & url , const std : : string & sdp ) :
2016-04-04 22:11:48 +08:00
mUrl ( url ) ,
mConnInfo ( 0 ) ,
mBandInfo ( 0 )
2013-03-17 07:45:21 +08:00
{
2016-04-04 22:11:48 +08:00
MediaDescriptor * currMedia = 0 ;
2013-03-17 07:45:21 +08:00
2016-04-04 22:11:48 +08:00
StringVector lines = split ( sdp , " \r \n " ) ;
2017-11-19 05:00:10 +08:00
for ( StringVector : : const_iterator iter = lines . begin ( ) ; iter ! = lines . end ( ) ; + + iter ) {
2016-04-04 22:11:48 +08:00
std : : string line = * iter ;
if ( line . empty ( ) )
break ;
2013-03-17 07:45:21 +08:00
2016-04-04 22:11:48 +08:00
Debug ( 3 , " Processing SDP line '%s' " , line . c_str ( ) ) ;
const char sdpType = line [ 0 ] ;
if ( line [ 1 ] ! = ' = ' )
throw Exception ( " Invalid SDP format at ' " + line + " ' " ) ;
2013-03-17 07:45:21 +08:00
2016-04-04 22:11:48 +08:00
line . erase ( 0 , 2 ) ;
switch ( sdpType )
{
case ' v ' :
mVersion = line ;
break ;
case ' o ' :
mOwner = line ;
break ;
case ' s ' :
mName = line ;
break ;
case ' i ' :
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 ' :
mTimeInfo = line ;
break ;
case ' a ' :
{
mAttributes . push_back ( line ) ;
StringVector tokens = split ( line , " : " , 2 ) ;
std : : string attrName = tokens [ 0 ] ;
if ( currMedia )
2013-03-17 07:45:21 +08:00
{
2016-04-04 22:11:48 +08:00
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 " )
{
// a=rtpmap:96 MP4V-ES/90000
if ( tokens . size ( ) < 2 )
throw Exception ( " Unable to parse SDP rtpmap 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 ( ) ) ) ;
std : : string payloadDesc = attrTokens [ 1 ] ;
//currMedia->setPayloadType( payloadType );
if ( attrTokens . size ( ) > 1 )
2013-03-17 07:45:21 +08:00
{
2016-04-04 22:11:48 +08:00
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 " )
{
// 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 ] , " " ) ;
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 ( ) ) ) ;
//currMedia->setPayloadType( payloadType );
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 " )
{
// a=framerate:5.0
if ( tokens . size ( ) < 2 )
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 " )
{
// 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 ) ;
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 ( ) ) ) ;
//currMedia->setPayloadType( payloadType );
if ( attrTokens . size ( ) > 1 )
{
StringVector attr2Tokens = split ( attrTokens [ 1 ] , " ; " ) ;
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() );
2017-11-19 05:00:10 +08:00
if ( attr3Tokens [ 0 ] = = " profile-level-id " ) {
} else if ( attr3Tokens [ 0 ] = = " config " ) {
} else if ( attr3Tokens [ 0 ] = = " sprop-parameter-sets " ) {
2016-04-04 22:11:48 +08:00
size_t t = attr2Tokens [ i ] . find ( " = " ) ;
char * c = ( char * ) attr2Tokens [ i ] . c_str ( ) + t + 1 ;
Debug ( 4 , " sprop-parameter-sets value %s " , c ) ;
currMedia - > setSprops ( std : : string ( c ) ) ;
2017-11-19 05:00:10 +08:00
} else {
2016-04-04 22:11:48 +08:00
Debug ( 3 , " Ignoring SDP fmtp attribute '%s' for media '%s' " , attr3Tokens [ 0 ] . c_str ( ) , currMedia - > getType ( ) . c_str ( ) )
}
}
2013-03-17 07:45:21 +08:00
}
2017-11-19 05:00:10 +08:00
} else if ( attrName = = " mpeg4-iod " ) {
2016-04-04 22:11:48 +08:00
// a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA"
2017-11-19 05:00:10 +08:00
} else if ( attrName = = " mpeg4-esid " ) {
2016-04-04 22:11:48 +08:00
// a=mpeg4-esid:201
2017-11-19 05:00:10 +08:00
} else {
2016-04-04 22:11:48 +08:00
Debug ( 3 , " Ignoring SDP attribute '%s' for media '%s' " , line . c_str ( ) , currMedia - > getType ( ) . c_str ( ) )
}
2017-11-19 05:00:10 +08:00
} else {
2016-04-04 22:11:48 +08:00
Debug ( 3 , " Ignoring general SDP attribute '%s' " , line . c_str ( ) ) ;
}
break ;
}
case ' m ' :
{
StringVector tokens = split ( line , " " ) ;
if ( tokens . size ( ) < 4 )
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 ] , " / " ) ;
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 + " ' " ) ;
int payloadType = atoi ( tokens [ 3 ] . c_str ( ) ) ;
currMedia = new MediaDescriptor ( mediaType , mediaPort , mediaNumPorts , mediaTransport , payloadType ) ;
mMediaList . push_back ( currMedia ) ;
break ;
}
2013-03-17 07:45:21 +08:00
}
2016-04-04 22:11:48 +08:00
}
2013-03-17 07:45:21 +08:00
}
2014-11-15 05:31:03 +08:00
SessionDescriptor : : ~ SessionDescriptor ( )
{
2016-04-04 22:11:48 +08:00
if ( mConnInfo )
delete mConnInfo ;
if ( mBandInfo )
delete mBandInfo ;
for ( unsigned int i = 0 ; i < mMediaList . size ( ) ; i + + )
delete mMediaList [ i ] ;
2014-11-15 05:31:03 +08:00
}
2013-03-17 07:45:21 +08:00
AVFormatContext * SessionDescriptor : : generateFormatContext ( ) const
{
2016-04-04 22:11:48 +08:00
AVFormatContext * formatContext = avformat_alloc_context ( ) ;
2013-03-17 07:45:21 +08:00
2016-04-04 22:11:48 +08:00
strncpy ( formatContext - > filename , mUrl . c_str ( ) , sizeof ( formatContext - > filename ) ) ;
2013-09-27 20:51:33 +08:00
/*
2016-04-04 22:11:48 +08:00
if ( mName . length ( ) )
strncpy ( formatContext - > title , mName . c_str ( ) , sizeof ( formatContext - > title ) ) ;
if ( mInfo . length ( ) )
strncpy ( formatContext - > comment , mInfo . c_str ( ) , sizeof ( formatContext - > comment ) ) ;
2013-09-27 20:51:33 +08:00
*/
2016-04-04 22:11:48 +08:00
//formatContext->nb_streams = mMediaList.size();
2017-11-19 05:00:10 +08:00
for ( unsigned int i = 0 ; i < mMediaList . size ( ) ; i + + ) {
2016-04-04 22:11:48 +08:00
const MediaDescriptor * mediaDesc = mMediaList [ i ] ;
2015-05-29 23:38:02 +08:00
# if !LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0)
2016-04-04 22:11:48 +08:00
AVStream * stream = av_new_stream ( formatContext , i ) ;
2013-03-17 07:45:21 +08:00
# else
2016-04-04 22:11:48 +08:00
AVStream * stream = avformat_new_stream ( formatContext , NULL ) ;
stream - > id = i ;
2013-03-17 07:45:21 +08:00
# endif
2017-11-08 10:21:51 +08:00
# if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
2017-11-19 05:00:10 +08:00
AVCodecContext * codec_context = avcodec_alloc_context3 ( NULL ) ;
avcodec_parameters_to_context ( codec_context , stream - > codecpar ) ;
2017-11-08 10:21:51 +08:00
# else
2017-11-19 05:00:10 +08:00
AVCodecContext * codec_context = stream - > codec ;
2017-11-08 10:21:51 +08:00
# endif
2016-04-04 22:11:48 +08:00
Debug ( 1 , " Looking for codec for %s payload type %d / %s " , mediaDesc - > getType ( ) . c_str ( ) , mediaDesc - > getPayloadType ( ) , mediaDesc - > getPayloadDesc ( ) . c_str ( ) ) ;
2015-05-29 23:38:02 +08:00
# if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
2016-04-04 22:11:48 +08:00
if ( mediaDesc - > getType ( ) = = " video " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = AVMEDIA_TYPE_VIDEO ;
2016-04-04 22:11:48 +08:00
else if ( mediaDesc - > getType ( ) = = " audio " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = AVMEDIA_TYPE_AUDIO ;
2016-04-04 22:11:48 +08:00
else if ( mediaDesc - > getType ( ) = = " application " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = AVMEDIA_TYPE_DATA ;
2013-03-17 07:45:21 +08:00
# else
2016-04-04 22:11:48 +08:00
if ( mediaDesc - > getType ( ) = = " video " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = CODEC_TYPE_VIDEO ;
2016-04-04 22:11:48 +08:00
else if ( mediaDesc - > getType ( ) = = " audio " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = CODEC_TYPE_AUDIO ;
2016-04-04 22:11:48 +08:00
else if ( mediaDesc - > getType ( ) = = " application " )
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = CODEC_TYPE_DATA ;
2013-03-17 07:45:21 +08:00
# endif
2015-05-29 23:38:02 +08:00
# if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
2016-04-04 22:11:48 +08:00
std : : string codec_name ;
2015-05-29 23:38:02 +08:00
# endif
2017-11-19 05:00:10 +08:00
if ( mediaDesc - > getPayloadType ( ) < PAYLOAD_TYPE_DYNAMIC ) {
2016-04-04 22:11:48 +08:00
// Look in static table
2017-11-19 05:00:10 +08:00
for ( unsigned int i = 0 ; i < ( sizeof ( smStaticPayloads ) / sizeof ( * smStaticPayloads ) ) ; i + + ) {
if ( smStaticPayloads [ i ] . payloadType = = mediaDesc - > getPayloadType ( ) ) {
2016-04-04 22:11:48 +08:00
Debug ( 1 , " Got static payload type %d, %s " , smStaticPayloads [ i ] . payloadType , smStaticPayloads [ i ] . payloadName ) ;
2015-05-29 23:38:02 +08:00
# if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
2016-04-04 22:11:48 +08:00
codec_name = std : : string ( smStaticPayloads [ i ] . payloadName ) ;
2015-05-29 23:38:02 +08:00
# else
2017-11-08 10:21:51 +08:00
strncpy ( codec_context - > codec_name , smStaticPayloads [ i ] . payloadName , sizeof ( codec_context - > codec_name ) ) ; ;
2015-05-29 23:38:02 +08:00
# endif
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = smStaticPayloads [ i ] . codecType ;
codec_context - > codec_id = smStaticPayloads [ i ] . codecId ;
codec_context - > sample_rate = smStaticPayloads [ i ] . clockRate ;
2016-04-04 22:11:48 +08:00
break ;
2013-03-17 07:45:21 +08:00
}
2016-04-04 22:11:48 +08:00
}
2017-11-08 10:21:51 +08:00
} else {
2016-04-04 22:11:48 +08:00
// Look in dynamic table
2017-11-08 10:21:51 +08:00
for ( unsigned int i = 0 ; i < ( sizeof ( smDynamicPayloads ) / sizeof ( * smDynamicPayloads ) ) ; i + + ) {
if ( smDynamicPayloads [ i ] . payloadName = = mediaDesc - > getPayloadDesc ( ) ) {
2016-04-04 22:11:48 +08:00
Debug ( 1 , " Got dynamic payload type %d, %s " , mediaDesc - > getPayloadType ( ) , smDynamicPayloads [ i ] . payloadName ) ;
2015-05-29 23:38:02 +08:00
# if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
2016-04-04 22:11:48 +08:00
codec_name = std : : string ( smStaticPayloads [ i ] . payloadName ) ;
2015-05-29 23:38:02 +08:00
# else
2017-11-08 10:21:51 +08:00
strncpy ( codec_context - > codec_name , smDynamicPayloads [ i ] . payloadName , sizeof ( codec_context - > codec_name ) ) ; ;
2015-05-29 23:38:02 +08:00
# endif
2017-11-08 10:21:51 +08:00
codec_context - > codec_type = smDynamicPayloads [ i ] . codecType ;
codec_context - > codec_id = smDynamicPayloads [ i ] . codecId ;
codec_context - > sample_rate = mediaDesc - > getClock ( ) ;
2016-04-04 22:11:48 +08:00
break ;
2013-03-17 07:45:21 +08:00
}
2016-04-04 22:11:48 +08:00
}
}
2015-05-29 23:38:02 +08:00
# if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
2016-04-04 22:11:48 +08:00
if ( codec_name . empty ( ) )
2015-05-29 23:38:02 +08:00
# else
2016-04-04 22:11:48 +08:00
if ( ! stream - > codec - > codec_name [ 0 ] )
2015-05-29 23:38:02 +08:00
# endif
2016-04-04 22:11:48 +08:00
{
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 ( ) )
2017-11-08 10:21:51 +08:00
codec_context - > width = mediaDesc - > getWidth ( ) ;
2016-04-04 22:11:48 +08:00
if ( mediaDesc - > getHeight ( ) )
2017-11-08 10:21:51 +08:00
codec_context - > height = mediaDesc - > getHeight ( ) ;
if ( codec_context - > codec_id = = AV_CODEC_ID_H264 & & mediaDesc - > getSprops ( ) . size ( ) ) {
2016-04-04 22:11:48 +08:00
uint8_t start_sequence [ ] = { 0 , 0 , 1 } ;
2017-11-08 10:21:51 +08:00
codec_context - > extradata_size = 0 ;
codec_context - > extradata = NULL ;
2016-04-04 22:11:48 +08:00
char pvalue [ 1024 ] , * value = pvalue ;
strcpy ( pvalue , mediaDesc - > getSprops ( ) . c_str ( ) ) ;
while ( * value ) {
char base64packet [ 1024 ] ;
uint8_t decoded_packet [ 1024 ] ;
uint32_t packet_size ;
char * dst = base64packet ;
2013-09-27 19:08:11 +08:00
2016-04-04 22:11:48 +08:00
while ( * value & & * value ! = ' , '
& & ( dst - base64packet ) < ( long ) ( sizeof ( base64packet ) ) - 1 ) {
* dst + + = * value + + ;
}
* dst + + = ' \0 ' ;
2013-09-27 19:08:11 +08:00
2016-04-04 22:11:48 +08:00
if ( * value = = ' , ' )
value + + ;
2013-09-27 19:08:11 +08:00
2016-04-04 22:11:48 +08:00
packet_size = av_base64_decode ( decoded_packet , ( const char * ) base64packet , ( int ) sizeof ( decoded_packet ) ) ;
Hexdump ( 4 , ( char * ) decoded_packet , packet_size ) ;
if ( packet_size ) {
uint8_t * dest =
( uint8_t * ) av_malloc ( packet_size + sizeof ( start_sequence ) +
2017-11-08 10:21:51 +08:00
codec_context - > extradata_size +
# if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
AV_INPUT_BUFFER_PADDING_SIZE
# else
FF_INPUT_BUFFER_PADDING_SIZE
# endif
) ;
2016-04-04 22:11:48 +08:00
if ( dest ) {
2017-11-08 10:21:51 +08:00
if ( codec_context - > extradata_size ) {
2016-04-04 22:11:48 +08:00
// av_realloc?
2017-11-08 10:21:51 +08:00
memcpy ( dest , codec_context - > extradata , codec_context - > extradata_size ) ;
av_free ( codec_context - > extradata ) ;
2016-04-04 22:11:48 +08:00
}
2013-09-27 19:08:11 +08:00
2017-11-08 10:21:51 +08:00
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
# else
FF_INPUT_BUFFER_PADDING_SIZE
# endif
) ;
2013-09-27 19:08:11 +08:00
2017-11-08 10:21:51 +08:00
codec_context - > extradata = dest ;
codec_context - > extradata_size + = sizeof ( start_sequence ) + packet_size ;
2016-04-04 22:11:48 +08:00
// } else {
// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
// return AVERROR(ENOMEM);
}
2013-09-27 19:08:11 +08:00
}
2016-04-04 22:11:48 +08:00
}
2013-03-17 07:45:21 +08:00
}
2016-04-04 22:11:48 +08:00
}
2013-03-17 07:45:21 +08:00
2016-04-04 22:11:48 +08:00
return ( formatContext ) ;
2013-03-17 07:45:21 +08:00
}
# endif // HAVE_LIBAVFORMAT