@ -18,6 +18,7 @@
*/
# include "avformat.h"
# include "mpegts.h"
# include "bitstream.h"
# include <unistd.h>
# include <sys/types.h>
@ -42,36 +43,146 @@
' url_open_dyn_packet_buf ' )
*/
# define RTP_VERSION 2
# define RTP_MAX_SDES 256 /* maximum text length for SDES */
/* RTCP paquets use 0.5 % of the bandwidth */
# define RTCP_TX_RATIO_NUM 5
# define RTCP_TX_RATIO_DEN 1000
typedef enum {
RTCP_SR = 200 ,
RTCP_RR = 201 ,
RTCP_SDES = 202 ,
RTCP_BYE = 203 ,
RTCP_APP = 204
} rtcp_type_t ;
typedef enum {
RTCP_SDES_END = 0 ,
RTCP_SDES_CNAME = 1 ,
RTCP_SDES_NAME = 2 ,
RTCP_SDES_EMAIL = 3 ,
RTCP_SDES_PHONE = 4 ,
RTCP_SDES_LOC = 5 ,
RTCP_SDES_TOOL = 6 ,
RTCP_SDES_NOTE = 7 ,
RTCP_SDES_PRIV = 8 ,
RTCP_SDES_IMG = 9 ,
RTCP_SDES_DOOR = 10 ,
RTCP_SDES_SOURCE = 11
} rtcp_sdes_type_t ;
/* from http://www.iana.org/assignments/rtp-parameters last updated 05 January 2005 */
AVRtpPayloadType_t AVRtpPayloadTypes [ ] =
{
{ 0 , " PCMU " , CODEC_TYPE_AUDIO , CODEC_ID_PCM_MULAW , 8000 , 1 } ,
{ 1 , " Reserved " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 2 , " Reserved " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 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_NONE , 8000 , 1 } ,
{ 13 , " CN " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , 8000 , 1 } ,
{ 14 , " MPA " , CODEC_TYPE_AUDIO , CODEC_ID_MP2 , 90000 , - 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 } ,
{ 19 , " reserved " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 20 , " unassigned " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 21 , " unassigned " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 22 , " unassigned " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 23 , " unassigned " , CODEC_TYPE_AUDIO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 24 , " unassigned " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 25 , " CelB " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , 90000 , - 1 } ,
{ 26 , " JPEG " , CODEC_TYPE_VIDEO , CODEC_ID_MJPEG , 90000 , - 1 } ,
{ 27 , " unassigned " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 28 , " nv " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , 90000 , - 1 } ,
{ 29 , " unassigned " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 30 , " unassigned " , CODEC_TYPE_VIDEO , CODEC_ID_NONE , - 1 , - 1 } ,
{ 31 , " H261 " , CODEC_TYPE_VIDEO , CODEC_ID_H261 , 90000 , - 1 } ,
{ 32 , " MPV " , CODEC_TYPE_VIDEO , CODEC_ID_MPEG1VIDEO , 90000 , - 1 } ,
{ 33 , " MP2T " , CODEC_TYPE_DATA , CODEC_ID_MPEG2TS , 90000 , - 1 } ,
{ 34 , " H263 " , CODEC_TYPE_VIDEO , CODEC_ID_H263 , 90000 , - 1 } ,
{ 35 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 36 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 37 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 38 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 39 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 40 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 41 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 42 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 43 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 44 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 45 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 46 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 47 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 48 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 49 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 50 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 51 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 52 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 53 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 54 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 55 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 56 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 57 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 58 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 59 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 60 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 61 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 62 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 63 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 64 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 65 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 66 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 67 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 68 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 69 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 70 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 71 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 72 , " reserved for RTCP conflict avoidance " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 73 , " reserved for RTCP conflict avoidance " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 74 , " reserved for RTCP conflict avoidance " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 75 , " reserved for RTCP conflict avoidance " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 76 , " reserved for RTCP conflict avoidance " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 77 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 78 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 79 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 80 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 81 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 82 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 83 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 84 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 85 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 86 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 87 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 88 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 89 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 90 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 91 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 92 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 93 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 94 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 95 , " unassigned " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 96 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 97 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 98 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 99 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 100 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 101 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 102 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 103 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 104 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 105 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 106 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 107 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 108 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 109 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 110 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 111 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 112 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 113 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 114 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 115 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 116 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 117 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 118 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 119 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 120 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 121 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 122 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 123 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 124 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 125 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 126 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ 127 , " dynamic " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 } ,
{ - 1 , " " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE , - 1 , - 1 }
} ;
AVRtpDynamicPayloadType_t AVRtpDynamicPayloadTypes [ ] =
{
{ " MP4V-ES " , CODEC_TYPE_VIDEO , CODEC_ID_MPEG4 } ,
{ " mpeg4-generic " , CODEC_TYPE_AUDIO , CODEC_ID_MPEG4AAC } ,
{ " " , CODEC_TYPE_UNKNOWN , CODEC_ID_NONE }
} ;
struct RTPDemuxContext {
AVFormatContext * ic ;
@ -83,7 +194,7 @@ struct RTPDemuxContext {
uint32_t base_timestamp ;
uint32_t cur_timestamp ;
int max_payload_size ;
MpegTSContext * ts ; /* only used for RTP_PT_ MPEG 2TS payloads */
MpegTSContext * ts ; /* only used for MP2T payloads */
int read_buf_index ;
int read_buf_size ;
@ -99,94 +210,37 @@ struct RTPDemuxContext {
/* buffer for output */
uint8_t buf [ RTP_MAX_PACKET_LENGTH ] ;
uint8_t * buf_ptr ;
/* special infos for au headers parsing */
rtp_payload_data_t * rtp_payload_data ;
} ;
int rtp_get_codec_info ( AVCodecContext * codec , int payload_type )
{
switch ( payload_type ) {
case RTP_PT_ULAW :
codec - > codec_type = CODEC_TYPE_AUDIO ;
codec - > codec_id = CODEC_ID_PCM_MULAW ;
codec - > channels = 1 ;
codec - > sample_rate = 8000 ;
break ;
case RTP_PT_ALAW :
codec - > codec_type = CODEC_TYPE_AUDIO ;
codec - > codec_id = CODEC_ID_PCM_ALAW ;
codec - > channels = 1 ;
codec - > sample_rate = 8000 ;
break ;
case RTP_PT_S16BE_STEREO :
codec - > codec_type = CODEC_TYPE_AUDIO ;
codec - > codec_id = CODEC_ID_PCM_S16BE ;
codec - > channels = 2 ;
codec - > sample_rate = 44100 ;
break ;
case RTP_PT_S16BE_MONO :
codec - > codec_type = CODEC_TYPE_AUDIO ;
codec - > codec_id = CODEC_ID_PCM_S16BE ;
codec - > channels = 1 ;
codec - > sample_rate = 44100 ;
break ;
case RTP_PT_MPEGAUDIO :
codec - > codec_type = CODEC_TYPE_AUDIO ;
codec - > codec_id = CODEC_ID_MP2 ;
break ;
case RTP_PT_JPEG :
codec - > codec_type = CODEC_TYPE_VIDEO ;
codec - > codec_id = CODEC_ID_MJPEG ;
break ;
case RTP_PT_MPEGVIDEO :
codec - > codec_type = CODEC_TYPE_VIDEO ;
codec - > codec_id = CODEC_ID_MPEG1VIDEO ;
break ;
case RTP_PT_MPEG2TS :
codec - > codec_type = CODEC_TYPE_DATA ;
codec - > codec_id = CODEC_ID_MPEG2TS ;
break ;
default :
return - 1 ;
if ( AVRtpPayloadTypes [ payload_type ] . codec_id ! = CODEC_ID_NONE ) {
codec - > codec_type = AVRtpPayloadTypes [ payload_type ] . codec_type ;
codec - > codec_id = AVRtpPayloadTypes [ payload_type ] . codec_type ;
if ( AVRtpPayloadTypes [ payload_type ] . audio_channels > 0 )
codec - > channels = AVRtpPayloadTypes [ payload_type ] . audio_channels ;
if ( AVRtpPayloadTypes [ payload_type ] . clock_rate > 0 )
codec - > sample_rate = AVRtpPayloadTypes [ payload_type ] . clock_rate ;
return 0 ;
}
return 0 ;
return - 1 ;
}
/* return < 0 if unknown payload type */
int rtp_get_payload_type ( AVCodecContext * codec )
{
int payload_type ;
int i , payload_type ;
/* compute the payload type */
payload_type = - 1 ;
switch ( codec - > codec_id ) {
case CODEC_ID_PCM_MULAW :
payload_type = RTP_PT_ULAW ;
break ;
case CODEC_ID_PCM_ALAW :
payload_type = RTP_PT_ALAW ;
break ;
case CODEC_ID_PCM_S16BE :
if ( codec - > channels = = 1 ) {
payload_type = RTP_PT_S16BE_MONO ;
} else if ( codec - > channels = = 2 ) {
payload_type = RTP_PT_S16BE_STEREO ;
for ( payload_type = - 1 , i = 0 ; AVRtpPayloadTypes [ i ] . pt > = 0 ; + + i )
if ( AVRtpPayloadTypes [ i ] . codec_id = = codec - > codec_id ) {
if ( codec - > codec_id = = CODEC_ID_PCM_S16BE )
if ( codec - > channels ! = AVRtpPayloadTypes [ i ] . audio_channels )
continue ;
payload_type = AVRtpPayloadTypes [ i ] . pt ;
}
break ;
case CODEC_ID_MP2 :
case CODEC_ID_MP3 :
payload_type = RTP_PT_MPEGAUDIO ;
break ;
case CODEC_ID_MJPEG :
payload_type = RTP_PT_JPEG ;
break ;
case CODEC_ID_MPEG1VIDEO :
payload_type = RTP_PT_MPEGVIDEO ;
break ;
case CODEC_ID_MPEG2TS :
payload_type = RTP_PT_MPEG2TS ;
break ;
default :
break ;
}
return payload_type ;
}
@ -216,7 +270,7 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int l
* MPEG2TS streams to indicate that they should be demuxed inside the
* rtp demux ( otherwise CODEC_ID_MPEG2TS packets are returned )
*/
RTPDemuxContext * rtp_parse_open ( AVFormatContext * s1 , AVStream * st , int payload_type )
RTPDemuxContext * rtp_parse_open ( AVFormatContext * s1 , AVStream * st , int payload_type , rtp_payload_data_t * rtp_payload_data )
{
RTPDemuxContext * s ;
@ -228,7 +282,8 @@ RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_t
s - > first_rtcp_ntp_time = AV_NOPTS_VALUE ;
s - > ic = s1 ;
s - > st = st ;
if ( payload_type = = RTP_PT_MPEG2TS ) {
s - > rtp_payload_data = rtp_payload_data ;
if ( ! strcmp ( AVRtpPayloadTypes [ payload_type ] . enc_name , " MP2T " ) ) {
s - > ts = mpegts_parse_open ( s - > ic ) ;
if ( s - > ts = = NULL ) {
av_free ( s ) ;
@ -250,6 +305,57 @@ RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_t
return s ;
}
static int rtp_parse_mp4_au ( RTPDemuxContext * s , const uint8_t * buf )
{
AVCodecContext codec ;
int au_headers_length , au_header_size , i ;
GetBitContext getbitcontext ;
rtp_payload_data_t * infos ;
infos = s - > rtp_payload_data ;
if ( infos = = NULL )
return - 1 ;
codec = s - > st - > codec ;
/* decode the first 2 bytes where are stored the AUHeader sections
length in bits */
au_headers_length = BE_16 ( buf ) ;
if ( au_headers_length > RTP_MAX_PACKET_LENGTH )
return - 1 ;
infos - > au_headers_length_bytes = ( au_headers_length + 7 ) / 8 ;
/* skip AU headers length section (2 bytes) */
buf + = 2 ;
init_get_bits ( & getbitcontext , buf , infos - > au_headers_length_bytes * 8 ) ;
/* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
au_header_size = infos - > sizelength + infos - > indexlength ;
if ( au_header_size < = 0 | | ( au_headers_length % au_header_size ! = 0 ) )
return - 1 ;
infos - > nb_au_headers = au_headers_length / au_header_size ;
infos - > au_headers = av_malloc ( sizeof ( struct AUHeaders ) * infos - > nb_au_headers ) ;
/* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
In my test , the faad decoder doesnt behave correctly when sending each AU one by one
but does when sending the whole as one big packet . . . */
infos - > au_headers [ 0 ] . size = 0 ;
infos - > au_headers [ 0 ] . index = 0 ;
for ( i = 0 ; i < infos - > nb_au_headers ; + + i ) {
infos - > au_headers [ 0 ] . size + = get_bits_long ( & getbitcontext , infos - > sizelength ) ;
infos - > au_headers [ 0 ] . index = get_bits_long ( & getbitcontext , infos - > indexlength ) ;
}
infos - > nb_au_headers = 1 ;
return 0 ;
}
/**
* Parse an RTP or RTCP packet directly sent as a buffer .
* @ param s RTP parse context .
@ -304,8 +410,8 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
av_log ( & s - > st - > codec , AV_LOG_ERROR , " RTP: PT=%02x: bad cseq %04x expected=%04x \n " ,
payload_type , seq , ( ( s - > seq + 1 ) & 0xffff ) ) ;
}
s - > seq = seq ;
# endif
s - > seq = seq ;
len - = 12 ;
buf + = 12 ;
@ -370,6 +476,28 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
pkt - > pts = addend + delta_timestamp ;
}
break ;
case CODEC_ID_MPEG4 :
pkt - > pts = timestamp ;
break ;
case CODEC_ID_MPEG4AAC :
if ( rtp_parse_mp4_au ( s , buf ) )
return - 1 ;
rtp_payload_data_t * infos = s - > rtp_payload_data ;
if ( infos = = NULL )
return - 1 ;
buf + = infos - > au_headers_length_bytes + 2 ;
len - = infos - > au_headers_length_bytes + 2 ;
/* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
one au_header */
av_new_packet ( pkt , infos - > au_headers [ 0 ] . size ) ;
memcpy ( pkt - > data , buf , infos - > au_headers [ 0 ] . size ) ;
buf + = infos - > au_headers [ 0 ] . size ;
len - = infos - > au_headers [ 0 ] . size ;
s - > read_buf_size = len ;
s - > buf_ptr = ( char * ) buf ;
pkt - > stream_index = s - > st - > index ;
return 0 ;
default :
/* no timestamp info yet */
break ;
@ -381,7 +509,7 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
void rtp_parse_close ( RTPDemuxContext * s )
{
if ( s - > payload_type = = RTP_PT_MPEG2TS ) {
if ( ! strcmp ( AVRtpPayloadTypes [ s - > payload_type ] . enc_name , " MP2T " ) ) {
mpegts_parse_close ( s - > ts ) ;
}
av_free ( s ) ;