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

📄 rtp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
         * but we have to know it to build our SDP properly, which is why         * we ask the core. FIXME: broken when neither sout-rtp-ttl nor         * ttl are set. */        p_sys->i_ttl = config_GetInt( p_stream, "ttl" );    }    p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );    p_sys->i_payload_type = 96;    p_sys->i_es = 0;    p_sys->es   = NULL;    p_sys->rtsp = NULL;    p_sys->psz_sdp = NULL;    p_sys->b_export_sap = false;    p_sys->b_export_sdp_file = false;    p_sys->p_session = NULL;    p_sys->p_httpd_host = NULL;    p_sys->p_httpd_file = NULL;    p_stream->p_sys     = p_sys;    vlc_mutex_init( &p_sys->lock_sdp );    vlc_mutex_init( &p_sys->lock_es );    psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );    if( psz != NULL )    {        sout_stream_id_t *id;        /* Check muxer type */        if( strncasecmp( psz, "ps", 2 )         && strncasecmp( psz, "mpeg1", 5 )         && strncasecmp( psz, "ts", 2 ) )        {            msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );            free( psz );            vlc_mutex_destroy( &p_sys->lock_sdp );            vlc_mutex_destroy( &p_sys->lock_es );            free( p_sys );            return VLC_EGENERIC;        }        p_sys->p_grab = GrabberCreate( p_stream );        p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );        free( psz );        if( p_sys->p_mux == NULL )        {            msg_Err( p_stream, "cannot create muxer" );            sout_AccessOutDelete( p_sys->p_grab );            vlc_mutex_destroy( &p_sys->lock_sdp );            vlc_mutex_destroy( &p_sys->lock_es );            free( p_sys );            return VLC_EGENERIC;        }        id = Add( p_stream, NULL );        if( id == NULL )        {            sout_MuxDelete( p_sys->p_mux );            sout_AccessOutDelete( p_sys->p_grab );            vlc_mutex_destroy( &p_sys->lock_sdp );            vlc_mutex_destroy( &p_sys->lock_es );            free( p_sys );            return VLC_EGENERIC;        }        p_sys->packet = NULL;        p_stream->pf_add  = MuxAdd;        p_stream->pf_del  = MuxDel;        p_stream->pf_send = MuxSend;    }    else    {        p_sys->p_mux    = NULL;        p_sys->p_grab   = NULL;        p_stream->pf_add    = Add;        p_stream->pf_del    = Del;        p_stream->pf_send   = Send;    }    if( var_GetBool( p_stream, SOUT_CFG_PREFIX"sap" ) )        SDPHandleUrl( p_stream, "sap" );    psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );    if( psz != NULL )    {        config_chain_t *p_cfg;        SDPHandleUrl( p_stream, psz );        for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )        {            if( !strcmp( p_cfg->psz_name, "sdp" ) )            {                if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' )                    continue;                /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */                if( !strcmp( p_cfg->psz_value, psz ) )                    continue;                SDPHandleUrl( p_stream, p_cfg->psz_value );            }        }        free( psz );    }    /* update p_sout->i_out_pace_nocontrol */    p_stream->p_sout->i_out_pace_nocontrol++;    return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t * p_this ){    sout_stream_t     *p_stream = (sout_stream_t*)p_this;    sout_stream_sys_t *p_sys = p_stream->p_sys;    /* update p_sout->i_out_pace_nocontrol */    p_stream->p_sout->i_out_pace_nocontrol--;    if( p_sys->p_mux )    {        assert( p_sys->i_es == 1 );        Del( p_stream, p_sys->es[0] );        sout_MuxDelete( p_sys->p_mux );        sout_AccessOutDelete( p_sys->p_grab );        if( p_sys->packet )        {            block_Release( p_sys->packet );        }        if( p_sys->b_export_sap )        {            p_sys->p_mux = NULL;            SapSetup( p_stream );        }    }    if( p_sys->rtsp != NULL )        RtspUnsetup( p_sys->rtsp );    vlc_mutex_destroy( &p_sys->lock_sdp );    vlc_mutex_destroy( &p_sys->lock_es );    if( p_sys->p_httpd_file )        httpd_FileDelete( p_sys->p_httpd_file );    if( p_sys->p_httpd_host )        httpd_HostDelete( p_sys->p_httpd_host );    free( p_sys->psz_sdp );    if( p_sys->b_export_sdp_file )    {#ifdef HAVE_UNISTD_H        unlink( p_sys->psz_sdp_file );#endif        free( p_sys->psz_sdp_file );    }    free( p_sys->psz_destination );    free( p_sys );}/***************************************************************************** * SDPHandleUrl: *****************************************************************************/static void SDPHandleUrl( sout_stream_t *p_stream, const char *psz_url ){    sout_stream_sys_t *p_sys = p_stream->p_sys;    vlc_url_t url;    vlc_UrlParse( &url, psz_url, 0 );    if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )    {        if( p_sys->p_httpd_file )        {            msg_Err( p_stream, "you can use sdp=http:// only once" );            goto out;        }        if( HttpSetup( p_stream, &url ) )        {            msg_Err( p_stream, "cannot export SDP as HTTP" );        }    }    else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )    {        if( p_sys->rtsp != NULL )        {            msg_Err( p_stream, "you can use sdp=rtsp:// only once" );            goto out;        }        /* FIXME test if destination is multicast or no destination at all */        p_sys->rtsp = RtspSetup( p_stream, &url );        if( p_sys->rtsp == NULL )        {            msg_Err( p_stream, "cannot export SDP as RTSP" );        }        if( p_sys->p_mux != NULL )        {            sout_stream_id_t *id = p_sys->es[0];            id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0, GetDWBE( id->ssrc ),                                     p_sys->psz_destination, p_sys->i_ttl,                                     id->i_port, id->i_port + 1 );        }    }    else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||             ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )    {        p_sys->b_export_sap = true;        SapSetup( p_stream );    }    else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )    {        if( p_sys->b_export_sdp_file )        {            msg_Err( p_stream, "you can use sdp=file:// only once" );            goto out;        }        p_sys->b_export_sdp_file = true;        psz_url = &psz_url[5];        if( psz_url[0] == '/' && psz_url[1] == '/' )            psz_url += 2;        p_sys->psz_sdp_file = strdup( psz_url );    }    else    {        msg_Warn( p_stream, "unknown protocol for SDP (%s)",                  url.psz_protocol );    }out:    vlc_UrlClean( &url );}/***************************************************************************** * SDPGenerate *****************************************************************************//*static*/char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ){    const sout_stream_sys_t *p_sys = p_stream->p_sys;    char *psz_sdp;    struct sockaddr_storage dst;    socklen_t dstlen;    int i;    /*     * When we have a fixed destination (typically when we do multicast),     * we need to put the actual port numbers in the SDP.     * When there is no fixed destination, we only support RTSP unicast     * on-demand setup, so we should rather let the clients decide which ports     * to use.     * When there is both a fixed destination and RTSP unicast, we need to     * put port numbers used by the fixed destination, otherwise the SDP would     * become totally incorrect for multicast use. It should be noted that     * port numbers from SDP with RTSP are only "recommendation" from the     * server to the clients (per RFC2326), so only broken clients will fail     * to handle this properly. There is no solution but to use two differents     * output chain with two different RTSP URLs if you need to handle this     * scenario.     */    int inclport;    if( p_sys->psz_destination != NULL )    {        inclport = 1;        /* Oh boy, this is really ugly! (+ race condition on lock_es) */        dstlen = sizeof( dst );        if( p_sys->es[0]->listen_fd != NULL )            getsockname( p_sys->es[0]->listen_fd[0],                         (struct sockaddr *)&dst, &dstlen );        else            getpeername( p_sys->es[0]->sinkv[0].rtp_fd,                         (struct sockaddr *)&dst, &dstlen );    }    else    {        inclport = 0;        /* Dummy destination address for RTSP */        memset (&dst, 0, sizeof( struct sockaddr_in ) );        dst.ss_family = AF_INET;#ifdef HAVE_SA_LEN        dst.ss_len =#endif        dstlen = sizeof( struct sockaddr_in );    }    psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,                             NULL, 0, (struct sockaddr *)&dst, dstlen );    if( psz_sdp == NULL )        return NULL;    /* TODO: a=source-filter */    if( p_sys->rtcp_mux )        sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );    if( rtsp_url != NULL )        sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );    /* FIXME: locking?! */    for( i = 0; i < p_sys->i_es; i++ )    {        sout_stream_id_t *id = p_sys->es[i];        const char *mime_major; /* major MIME type */        const char *proto = "RTP/AVP"; /* protocol */        switch( id->i_cat )        {            case VIDEO_ES:                mime_major = "video";                break;            case AUDIO_ES:                mime_major = "audio";                break;            case SPU_ES:                mime_major = "text";                break;            default:                continue;        }        if( rtsp_url == NULL )        {            switch( p_sys->proto )            {                case IPPROTO_UDP:                    break;                case IPPROTO_TCP:                    proto = "TCP/RTP/AVP";                    break;                case IPPROTO_DCCP:                    proto = "DCCP/RTP/AVP";                    break;                case IPPROTO_UDPLITE:                    continue;            }        }        sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,                      id->i_payload_type, false, id->i_bitrate,                      id->psz_enc, id->i_clock_rate, id->i_channels,                      id->psz_fmtp);        if( rtsp_url != NULL )        {            assert( strlen( rtsp_url ) > 0 );            bool addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );            sdp_AddAttribute ( &psz_sdp, "control",                               addslash ? "%s/trackID=%u" : "%strackID=%u",                               rtsp_url, i );        }        else        {            if( id->listen_fd != NULL )                sdp_AddAttribute( &psz_sdp, "setup", "passive" );            if( p_sys->proto == IPPROTO_DCCP )                sdp_AddAttribute( &psz_sdp, "dccp-service-code",                                   "SC:RTP%c", toupper( mime_major[0] ) );        }    }    return psz_sdp;}/***************************************************************************** * RTP mux *****************************************************************************/static void sprintf_hexa( char *s, uint8_t *p_data, int i_data ){    static const char hex[16] = "0123456789abcdef";    int i;    for( i = 0; i < i_data; i++ )    {        s[2*i+0] = hex[(p_data[i]>>4)&0xf];        s[2*i+1] = hex[(p_data[i]   )&0xf];    }    s[2*i_data] = '\0';}/** * Shrink the MTU down to a fixed packetization time (for audio). */static voidrtp_set_ptime (sout_stream_id_t *id, unsigned ptime_ms, size_t bytes){    /* Samples per second */    size_t spl = (id->i_clock_rate - 1) * ptime_ms / 1000 + 1;    bytes *= id->i_channels;    spl *= bytes;    if (spl < rtp_mtu (id)) /* MTU is big enough for ptime */        id->i_mtu = 12 + spl;    else /* MTU is too small for ptime, align to a sample boundary */        id->i_mtu = 12 + (((id->i_mtu - 12) / bytes) * bytes);}/** Add an ES as a new RTP stream */static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ){    /* NOTE: As a special case, if we use a non-RTP     * mux (TS/PS), then p_fmt is NULL. */    sout_stream_sys_t *p_sys = p_stream->p_sys;    sout_stream_id_t  *id;    int               i_port, cscov = -1;    char              *psz_sdp;    id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );    if( id == NULL )        return NULL;    vlc_object_attach( id, p_stream );    /* Choose the port */    i_port = 0;    if( p_fmt == NULL )        ;    else    if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )    {        i_port = p_sys->i_port_audio;

⌨️ 快捷键说明

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