⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtcp.c

📁 uclinux 下的vlc播放器源代码
💻 C
字号:
/***************************************************************************** * rtcp.c: RTP/RTCP source file ***************************************************************************** * Copyright (C) 2005 M2X * * $Id: rtcp.c 14601 2006-03-03 21:43:48Z jpsaman $ * * Authors: Jean-Paul Saman <jpsaman #_at_# videolan dot org> * * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include <netinet/in.h>#include <sys/time.h>#include <sys/time.h>#include <vlc/vlc.h>#include <vlc_bits.h>#include <vlc_block.h>#include "rtp.h"#include "rtcp.h"static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_block );static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer );static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer );static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer );static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer );static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer );static block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp );static block_t *rtcp_encode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp );static block_t *rtcp_encode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp );static block_t *rtcp_encode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp );static int rtcp_decode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ){    unsigned int u_ssrc_count;    unsigned int i = 0;    if( !p_rtcp && !p_buffer )        return VLC_EGENERIC;    msg_Dbg( p_this, "decoding record: SR" );    p_rtcp->stats.u_SR_received++;    p_rtcp->stats.u_pkt_count   = p_buffer[20+RTCP_HEADER_LEN];    p_rtcp->stats.u_octet_count = p_buffer[24+RTCP_HEADER_LEN];    u_ssrc_count = p_buffer[RTCP_HEADER_LEN] & 0x1f;    msg_Dbg( p_this, "SR received %d, packet count %d, octect count %d, SSRC count %d",        p_rtcp->stats.u_SR_received,        p_rtcp->stats.u_pkt_count,        p_rtcp->stats.u_octet_count,        u_ssrc_count );    for( i=0; i < u_ssrc_count; i++ )    {        unsigned char count[4];        p_rtcp->stats.u_fract_lost = p_buffer[32+RTCP_HEADER_LEN];        count[0] = 0;        count[1] = p_buffer[33+RTCP_HEADER_LEN];        count[2] = p_buffer[34+RTCP_HEADER_LEN];        count[3] = p_buffer[35+RTCP_HEADER_LEN];        /* FIXME: I don't like the sight of this */        p_rtcp->stats.u_pkt_lost = ntohl((int)count);        p_rtcp->stats.u_highest_seq_no = ntohl( p_buffer[36+RTCP_HEADER_LEN] );        p_rtcp->stats.u_jitter  = ntohl( p_buffer[40+RTCP_HEADER_LEN] );        p_rtcp->stats.u_last_SR = ntohl( p_buffer[44+RTCP_HEADER_LEN] );        p_rtcp->stats.u_delay_since_last_SR = (mtime_t) ntohl( p_buffer[48+RTCP_HEADER_LEN] );        msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, jitter %d, last SR %d, delay %lld",            p_rtcp->stats.u_fract_lost,            p_rtcp->stats.u_pkt_lost,            p_rtcp->stats.u_highest_seq_no,            p_rtcp->stats.u_jitter,            p_rtcp->stats.u_last_SR,            p_rtcp->stats.u_delay_since_last_SR );    }    return VLC_SUCCESS;}static int rtcp_decode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ){    unsigned int u_ssrc_count;    unsigned int i = 0;    if( !p_rtcp && !p_buffer )        return VLC_EGENERIC;    msg_Dbg( p_this, "decoding record: RR" );    p_rtcp->stats.u_RR_received++;    u_ssrc_count = (p_buffer[RTCP_HEADER_LEN] & 0x1f);    msg_Dbg( p_this, "RR received %d, SSRC count %d", p_rtcp->stats.u_RR_received, u_ssrc_count );    for( i=0; i < u_ssrc_count; i++ )    {        unsigned char count[4];        p_rtcp->stats.u_fract_lost = p_buffer[12+RTCP_HEADER_LEN];        count[0] = 0;        count[1] = p_buffer[13+RTCP_HEADER_LEN];        count[2] = p_buffer[14+RTCP_HEADER_LEN];        count[3] = p_buffer[15+RTCP_HEADER_LEN];        /* FIXME: I don't like the sight of this */        p_rtcp->stats.u_pkt_lost = ntohl((int)count);        p_rtcp->stats.u_highest_seq_no = ntohl( p_buffer[16+RTCP_HEADER_LEN] );        p_rtcp->stats.u_jitter  = ntohl( p_buffer[20+RTCP_HEADER_LEN] );        p_rtcp->stats.u_last_RR = ntohl( p_buffer[24+RTCP_HEADER_LEN] );        p_rtcp->stats.u_delay_since_last_RR = (mtime_t) ntohl( p_buffer[28+RTCP_HEADER_LEN] );        msg_Dbg( p_this, "fract lost %d, packet lost %d, highest seqno %d, jitter %d, last RR %d, delay %lld",            p_rtcp->stats.u_fract_lost,            p_rtcp->stats.u_pkt_lost,            p_rtcp->stats.u_highest_seq_no,            p_rtcp->stats.u_jitter,            p_rtcp->stats.u_last_RR,            p_rtcp->stats.u_delay_since_last_RR );    }    return VLC_SUCCESS;}static int rtcp_decode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ){    if( !p_rtcp && !p_buffer )        return VLC_EGENERIC;    msg_Dbg( p_this, "decoding record: SDES" );    switch( p_buffer[8] )    {        case RTCP_INFO_CNAME:            p_rtcp->stats.l_dest_SSRC = ntohs( (int)(p_buffer[4+RTCP_HEADER_LEN]) );            break;        case RTCP_INFO_NAME:        case RTCP_INFO_EMAIL:        case RTCP_INFO_PHONE:        case RTCP_INFO_LOC:        case RTCP_INFO_TOOL:        case RTCP_INFO_NOTE:        case RTCP_INFO_PRIV: /* ignoring these */            break;        default:            return VLC_EGENERIC;    }    return VLC_SUCCESS;}static int rtcp_decode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ){    if( !p_rtcp && !p_buffer )        return VLC_EGENERIC;    msg_Dbg( p_this, "decoding record: BYE" );    return VLC_SUCCESS;}static int rtcp_decode_APP( vlc_object_t *p_this, rtcp_t *p_rtcp, uint8_t *p_buffer ){    if( !p_rtcp && !p_buffer )        return VLC_EGENERIC;    msg_Dbg( p_this, "decoding record: APP" );    /* Just ignore this packet */    return VLC_SUCCESS;}/* Decode RTCP packet * Decode incoming RTCP packet and inspect the records types. */int rtcp_decode( vlc_object_t *p_this, rtcp_t *p_rtcp, block_t *p_block ){    uint8_t *p_buffer = NULL;    unsigned int i_length = 0;    unsigned int i;    if( !p_rtcp && !p_block )        return VLC_EGENERIC;    i_length = p_block->i_buffer;    p_buffer = p_block->p_buffer;    for( i=0; i<i_length; ++i )    {        p_rtcp->u_count = p_buffer[i] & 0xF8;        p_rtcp->u_version = p_buffer[i] & 0x03;        p_rtcp->u_payload_type = p_buffer[i+1];        p_rtcp->u_length = (p_buffer[i+2]<<8) + p_buffer[i+3];        msg_Dbg( p_this, "New RTCP packet: count %d, version %d, type %d, lenght %d",            p_rtcp->u_count,            p_rtcp->u_version,            p_rtcp->u_payload_type,            p_rtcp->u_length );        switch( p_rtcp->u_payload_type )        {            case RTCP_SR:                rtcp_decode_SR( p_this, p_rtcp, p_buffer );                break;            case RTCP_RR:                rtcp_decode_RR( p_this, p_rtcp, p_buffer );                break;            case RTCP_SDES:                rtcp_decode_SDES( p_this, p_rtcp, p_buffer );                break;            case RTCP_BYE:                rtcp_decode_BYE( p_this, p_rtcp, p_buffer );                break;            case RTCP_APP:                rtcp_decode_APP( p_this, p_rtcp, p_buffer );                break;            default:                return VLC_EGENERIC;        }    }    return VLC_SUCCESS;}/* * Create RTCP records for reporting to server. */block_t *rtcp_encode( vlc_object_t *p_this, int type ){    rtcp_t  *p_rtcp = NULL;    block_t *p_block = NULL;    p_rtcp = (rtcp_t *) malloc( sizeof( rtcp_t ) );    if( !p_rtcp )        return NULL;    memset( p_rtcp, 0 , sizeof( rtcp_t ) );    p_rtcp->u_version = 2;    p_rtcp->u_payload_type = type;    p_rtcp->u_length = RTCP_HEADER_LEN;    switch( type )    {        case RTCP_SR: p_rtcp->u_length += sizeof(rtcp_SR); break;        case RTCP_RR: p_rtcp->u_length += sizeof(rtcp_RR); break;        case RTCP_SDES:            p_rtcp->u_length += sizeof(rtcp_SDES) + strlen(p_rtcp->report.sdes.p_data);            break;        case RTCP_BYE:  p_rtcp->u_length += sizeof(rtcp_BYE);  break;        case RTCP_APP:  /* ignore: p_rtcp->u_length += sizeof(rtcp_APP); */ break;    }    /* FIXME: Maybe this should be a buffer pool instead */    p_block = block_New( p_this, p_rtcp->u_length );    return p_block;}static block_t *rtcp_encode_SR( vlc_object_t *p_this, rtcp_t *p_rtcp ){    mtime_t ntp_time;    bs_t bits, *s = &bits;    block_t *p_block = NULL;    /* FIXME: Maybe this should be a buffer pool instead */    p_block = block_New( p_this, p_rtcp->u_length );    if( !p_block )        return NULL;    bs_init( s, p_block->p_buffer, p_block->i_buffer );    /* Fill in header */    bs_write( s, 5, p_rtcp->u_count );    bs_write( s, 1, 0 ); /* padding */    bs_write( s, 2, p_rtcp->u_version );    bs_write( s, 8, p_rtcp->u_payload_type );    bs_write( s, 16, p_rtcp->u_length );    /* fill in record */    bs_write( s, 32, htonl( p_rtcp->report.sr.u_ssrc ) );    ntp_time = mdate();    bs_write( s, 32, htonl( ((unsigned int)(ntp_time>>32)) ) ); /* ntp_timestampH */    bs_write( s, 32, htonl( ((unsigned int)ntp_time)) );/* ntp_timestampL */    /* FIXME: Make sure to generate a good RTP server timestamp.        p_rtcp->report.sr.rtp_timestamp = htonl(        (unsigned int) ((double)ntp_time.tv_sec +        (double)ntp_time.tv_usec/1000000.) * p_mux->rate        + session->start_rtptime ); */    bs_write( s, 32, htonl( p_rtcp->report.sr.rtp_timestamp ) );    bs_write( s, 32, htonl( p_rtcp->report.sr.u_pkt_count ) );    bs_write( s, 32, htonl( p_rtcp->report.sr.u_octet_count ) );    return p_block;}static block_t *rtcp_encode_RR( vlc_object_t *p_this, rtcp_t *p_rtcp ){    bs_t bits, *s = &bits;    block_t *p_block = NULL;    /* FIXME: Maybe this should be a buffer pool instead */    p_block = block_New( p_this, p_rtcp->u_length );    if( !p_block )        return NULL;    bs_init( s, p_block->p_buffer, p_block->i_buffer );    /* Fill in header */    bs_write( s, 5, p_rtcp->u_count );    bs_write( s, 1, 0 ); /* padding */    bs_write( s, 2, p_rtcp->u_version );    bs_write( s, 8, p_rtcp->u_payload_type );    bs_write( s, 16, (p_rtcp->u_length >> 2) -1 );    /* fill in record */    bs_write( s, 32, htonl( p_rtcp->report.rr.u_ssrc ) );    return p_block;}static block_t *rtcp_encode_SDES( vlc_object_t *p_this, rtcp_t *p_rtcp ){    bs_t bits, *s = &bits;    block_t *p_block = NULL;    char *p_hostname = strdup("hostname");    int i_length;    int i;    /* FIXME: Maybe this should be a buffer pool instead */    p_block = block_New( p_this, p_rtcp->u_length );    if( !p_block )        return NULL;    bs_init( s, p_block->p_buffer, p_block->i_buffer );    /* Fill in header */    bs_write( s, 5, p_rtcp->u_count );    bs_write( s, 1, 0 ); /* padding */    bs_write( s, 2, p_rtcp->u_version );    bs_write( s, 8, p_rtcp->u_payload_type );    bs_write( s, 16, (p_rtcp->u_length >> 2) -1 );    /* fill in record */    bs_write( s, 32,htonl( p_rtcp->report.sdes.u_ssrc ) );    bs_write( s, 8, htonl( p_rtcp->report.sdes.u_attr_name ) );    bs_write( s, 8, htonl( p_rtcp->report.sdes.u_length ) );    i_length = strlen(p_hostname);    bs_write( s, 8, i_length );    for( i=0; i<i_length; i++ )    {        bs_write( s, 8, p_hostname[i] );    }    free(p_hostname);    return p_block;}static block_t *rtcp_encode_BYE( vlc_object_t *p_this, rtcp_t *p_rtcp ){    bs_t bits, *s = &bits;    block_t *p_block = NULL;    char *p_reason = strdup( "Stream ended." );    int i_length;    int i;    /* FIXME: Maybe this should be a buffer pool instead */    p_block = block_New( p_this, p_rtcp->u_length );    if( !p_block )        return NULL;    bs_init( s, p_block->p_buffer, p_block->i_buffer );    /* Fill in header */    bs_write( s, 5, p_rtcp->u_count );    bs_write( s, 1, 0 ); /* padding */    bs_write( s, 2, p_rtcp->u_version );    bs_write( s, 8, p_rtcp->u_payload_type );    bs_write( s, 16, (p_rtcp->u_length >> 2) -1 );    /* fill in record */    bs_write( s, 32, htonl( p_rtcp->report.sdes.u_ssrc ) );    i_length = strlen(p_reason);    bs_write( s, 8, i_length );    for( i=0; i<i_length; i++ )    {        bs_write( s, 8, p_reason[i] );    }    free(p_reason);    return p_block;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -