@ -258,13 +258,78 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int l
return 0 ;
}
/**
* some rtp servers assume client is dead if they don ' t hear from them . . .
* so we send a Receiver Report to the provided ByteIO context
* ( we don ' t have access to the rtcp handle from here )
*/
int rtp_check_and_send_back_rr ( RTPDemuxContext * s , int count )
{
ByteIOContext pb ;
uint8_t * buf ;
int len ;
int rtcp_bytes ;
if ( ! s - > rtp_ctx | | ( count < 1 ) )
return - 1 ;
/* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
s - > octet_count + = count ;
rtcp_bytes = ( ( s - > octet_count - s - > last_octet_count ) * RTCP_TX_RATIO_NUM ) /
RTCP_TX_RATIO_DEN ;
rtcp_bytes / = 50 ; // mmu_man: that's enough for me... VLC sends much less btw !?
if ( rtcp_bytes < 28 )
return - 1 ;
s - > last_octet_count = s - > octet_count ;
if ( url_open_dyn_buf ( & pb ) < 0 )
return - 1 ;
// Receiver Report
put_byte ( & pb , ( RTP_VERSION < < 6 ) + 1 ) ; /* 1 report block */
put_byte ( & pb , 201 ) ;
put_be16 ( & pb , 7 ) ; /* length in words - 1 */
put_be32 ( & pb , s - > ssrc ) ; // our own SSRC
put_be32 ( & pb , s - > ssrc ) ; // XXX: should be the server's here!
// some placeholders we should really fill...
put_be32 ( & pb , ( ( 0 < < 24 ) | ( 0 & 0x0ffffff ) ) ) ; /* 0% lost, total 0 lost */
put_be32 ( & pb , ( 0 < < 16 ) | s - > seq ) ;
put_be32 ( & pb , 0x68 ) ; /* jitter */
put_be32 ( & pb , - 1 ) ; /* last SR timestamp */
put_be32 ( & pb , 1 ) ; /* delay since last SR */
// CNAME
put_byte ( & pb , ( RTP_VERSION < < 6 ) + 1 ) ; /* 1 report block */
put_byte ( & pb , 202 ) ;
len = strlen ( s - > hostname ) ;
put_be16 ( & pb , ( 6 + len + 3 ) / 4 ) ; /* length in words - 1 */
put_be32 ( & pb , s - > ssrc ) ;
put_byte ( & pb , 0x01 ) ;
put_byte ( & pb , len ) ;
put_buffer ( & pb , s - > hostname , len ) ;
// padding
for ( len = ( 6 + len ) % 4 ; len % 4 ; len + + ) {
put_byte ( & pb , 0 ) ;
}
put_flush_packet ( & pb ) ;
len = url_close_dyn_buf ( & pb , & buf ) ;
if ( ( len > 0 ) & & buf ) {
# if defined(DEBUG)
printf ( " sending %d bytes of RR \n " , len ) ;
# endif
url_write ( s - > rtp_ctx , buf , len ) ;
av_free ( buf ) ;
}
return 0 ;
}
/**
* open a new RTP parse context for stream ' st ' . ' st ' can be NULL for
* MPEG2TS streams to indicate that they should be demuxed inside the
* rtp demux ( otherwise CODEC_ID_MPEG2TS packets are returned )
* TODO : change this to not take rtp_payload data , and use the new dynamic payload system .
*/
RTPDemuxContext * rtp_parse_open ( AVFormatContext * s1 , AVStream * st , int payload_type , rtp_payload_data_t * rtp_payload_data )
RTPDemuxContext * rtp_parse_open ( AVFormatContext * s1 , AVStream * st , URLContext * rtpc , int payload_type , rtp_payload_data_t * rtp_payload_data )
{
RTPDemuxContext * s ;
@ -299,6 +364,9 @@ RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, int payload_t
break ;
}
}
// needed to send back RTCP RR in RTSP sessions
s - > rtp_ctx = rtpc ;
gethostname ( s - > hostname , sizeof ( s - > hostname ) ) ;
return s ;
}
@ -399,6 +467,8 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
seq = ( buf [ 2 ] < < 8 ) | buf [ 3 ] ;
timestamp = decode_be32 ( buf + 4 ) ;
ssrc = decode_be32 ( buf + 8 ) ;
/* store the ssrc in the RTPDemuxContext */
s - > ssrc = ssrc ;
/* NOTE: we can handle only one payload type */
if ( s - > payload_type ! = payload_type )