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

📄 rtp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
    vlc_object_detach( id );    vlc_object_release( id );    return VLC_SUCCESS;}static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,                 block_t *p_buffer ){    block_t *p_next;    assert( p_stream->p_sys->p_mux == NULL );    (void)p_stream;    while( p_buffer != NULL )    {        p_next = p_buffer->p_next;        if( id->pf_packetize( id, p_buffer ) )            break;        block_Release( p_buffer );        p_buffer = p_next;    }    return VLC_SUCCESS;}/**************************************************************************** * SAP: ****************************************************************************/static int SapSetup( sout_stream_t *p_stream ){    sout_stream_sys_t *p_sys = p_stream->p_sys;    sout_instance_t   *p_sout = p_stream->p_sout;    /* Remove the previous session */    if( p_sys->p_session != NULL)    {        sout_AnnounceUnRegister( p_sout, p_sys->p_session);        p_sys->p_session = NULL;    }    if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )    {        announce_method_t *p_method = sout_SAPMethod();        p_sys->p_session = sout_AnnounceRegisterSDP( p_sout,                                                     p_sys->psz_sdp,                                                     p_sys->psz_destination,                                                     p_method );        sout_MethodRelease( p_method );    }    return VLC_SUCCESS;}/***************************************************************************** File:****************************************************************************/static int FileSetup( sout_stream_t *p_stream ){    sout_stream_sys_t *p_sys = p_stream->p_sys;    FILE            *f;    if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )    {        msg_Err( p_stream, "cannot open file '%s' (%m)",                 p_sys->psz_sdp_file );        return VLC_EGENERIC;    }    fputs( p_sys->psz_sdp, f );    fclose( f );    return VLC_SUCCESS;}/**************************************************************************** * HTTP: ****************************************************************************/static int  HttpCallback( httpd_file_sys_t *p_args,                          httpd_file_t *, uint8_t *p_request,                          uint8_t **pp_data, int *pi_data );static int HttpSetup( sout_stream_t *p_stream, const vlc_url_t *url){    sout_stream_sys_t *p_sys = p_stream->p_sys;    p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,                                         url->i_port > 0 ? url->i_port : 80 );    if( p_sys->p_httpd_host )    {        p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,                                             url->psz_path ? url->psz_path : "/",                                             "application/sdp",                                             NULL, NULL, NULL,                                             HttpCallback, (void*)p_sys );    }    if( p_sys->p_httpd_file == NULL )    {        return VLC_EGENERIC;    }    return VLC_SUCCESS;}static int  HttpCallback( httpd_file_sys_t *p_args,                          httpd_file_t *f, uint8_t *p_request,                          uint8_t **pp_data, int *pi_data ){    VLC_UNUSED(f); VLC_UNUSED(p_request);    sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;    vlc_mutex_lock( &p_sys->lock_sdp );    if( p_sys->psz_sdp && *p_sys->psz_sdp )    {        *pi_data = strlen( p_sys->psz_sdp );        *pp_data = malloc( *pi_data );        memcpy( *pp_data, p_sys->psz_sdp, *pi_data );    }    else    {        *pp_data = NULL;        *pi_data = 0;    }    vlc_mutex_unlock( &p_sys->lock_sdp );    return VLC_SUCCESS;}/**************************************************************************** * RTP send ****************************************************************************/static void* ThreadSend( vlc_object_t *p_this ){    sout_stream_id_t *id = (sout_stream_id_t *)p_this;    unsigned i_caching = id->i_caching;    while( vlc_object_alive (id) )    {        block_t *out = block_FifoGet( id->p_fifo );        if( out == NULL )            continue; /* Forced wakeup */        if( id->srtp )        {   /* FIXME: this is awfully inefficient */            size_t len = out->i_buffer;            out = block_Realloc( out, 0, len + 10 );            out->i_buffer = len;            int val = srtp_send( id->srtp, out->p_buffer, &len, len + 10 );            if( val )            {                errno = val;                msg_Dbg( id, "SRTP sending error: %m" );                block_Release( out );                continue;            }            out->i_buffer = len;        }        mtime_t  i_date = out->i_dts + i_caching;        ssize_t  len = out->i_buffer;        mwait( i_date );        vlc_mutex_lock( &id->lock_sink );        unsigned deadc = 0; /* How many dead sockets? */        int deadv[id->sinkc]; /* Dead sockets list */        for( int i = 0; i < id->sinkc; i++ )        {            if( !id->srtp ) /* FIXME: SRTCP support */                SendRTCP( id->sinkv[i].rtcp, out );            if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )                continue;            /* Retry sending to root out soft-errors */            if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )                continue;            deadv[deadc++] = id->sinkv[i].rtp_fd;        }        vlc_mutex_unlock( &id->lock_sink );        block_Release( out );        for( unsigned i = 0; i < deadc; i++ )        {            msg_Dbg( id, "removing socket %d", deadv[i] );            rtp_del_sink( id, deadv[i] );        }        /* Hopefully we won't overflow the SO_MAXCONN accept queue */        while( id->listen_fd != NULL )        {            int fd = net_Accept( id, id->listen_fd, 0 );            if( fd == -1 )                break;            msg_Dbg( id, "adding socket %d", fd );            rtp_add_sink( id, fd, true );        }    }    return NULL;}int rtp_add_sink( sout_stream_id_t *id, int fd, bool rtcp_mux ){    rtp_sink_t sink = { fd, NULL };    sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,                          rtcp_mux );    if( sink.rtcp == NULL )        msg_Err( id, "RTCP failed!" );    vlc_mutex_lock( &id->lock_sink );    INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );    vlc_mutex_unlock( &id->lock_sink );    return VLC_SUCCESS;}void rtp_del_sink( sout_stream_id_t *id, int fd ){    rtp_sink_t sink = { fd, NULL };    /* NOTE: must be safe to use if fd is not included */    vlc_mutex_lock( &id->lock_sink );    for( int i = 0; i < id->sinkc; i++ )    {        if (id->sinkv[i].rtp_fd == fd)        {            sink = id->sinkv[i];            REMOVE_ELEM( id->sinkv, id->sinkc, i );            break;        }    }    vlc_mutex_unlock( &id->lock_sink );    CloseRTCP( sink.rtcp );    net_Close( sink.rtp_fd );}uint16_t rtp_get_seq( const sout_stream_id_t *id ){    /* This will return values for the next packet.     * Accounting for caching would not be totally trivial. */    return id->i_sequence;}/* FIXME: this is pretty bad - if we remove and then insert an ES * the number will get unsynched from inside RTSP */unsigned rtp_get_num( const sout_stream_id_t *id ){    sout_stream_sys_t *p_sys = id->p_stream->p_sys;    int i;    vlc_mutex_lock( &p_sys->lock_es );    for( i = 0; i < p_sys->i_es; i++ )    {        if( id == p_sys->es[i] )            break;    }    vlc_mutex_unlock( &p_sys->lock_es );    return i;}void rtp_packetize_common( sout_stream_id_t *id, block_t *out,                           int b_marker, int64_t i_pts ){    uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / INT64_C(1000000);    out->p_buffer[0] = 0x80;    out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;    out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;    out->p_buffer[3] = ( id->i_sequence     )&0xff;    out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;    out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;    out->p_buffer[6] = ( i_timestamp >>  8 )&0xff;    out->p_buffer[7] = ( i_timestamp       )&0xff;    memcpy( out->p_buffer + 8, id->ssrc, 4 );    out->i_buffer = 12;    id->i_sequence++;}void rtp_packetize_send( sout_stream_id_t *id, block_t *out ){    block_FifoPut( id->p_fifo, out );}/** * @return configured max RTP payload size (including payload type-specific * headers, excluding RTP and transport headers) */size_t rtp_mtu (const sout_stream_id_t *id){    return id->i_mtu - 12;}/***************************************************************************** * Non-RTP mux *****************************************************************************//** Add an ES to a non-RTP muxed stream */static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt ){    sout_input_t      *p_input;    sout_mux_t *p_mux = p_stream->p_sys->p_mux;    assert( p_mux != NULL );    p_input = sout_MuxAddStream( p_mux, p_fmt );    if( p_input == NULL )    {        msg_Err( p_stream, "cannot add this stream to the muxer" );        return NULL;    }    return (sout_stream_id_t *)p_input;}static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,                    block_t *p_buffer ){    sout_mux_t *p_mux = p_stream->p_sys->p_mux;    assert( p_mux != NULL );    sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );    return VLC_SUCCESS;}/** Remove an ES from a non-RTP muxed stream */static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id ){    sout_mux_t *p_mux = p_stream->p_sys->p_mux;    assert( p_mux != NULL );    sout_MuxDeleteStream( p_mux, (sout_input_t *)id );    return VLC_SUCCESS;}static ssize_t AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,                                            const block_t *p_buffer ){    sout_stream_sys_t *p_sys = p_stream->p_sys;    sout_stream_id_t *id = p_sys->es[0];    int64_t  i_dts = p_buffer->i_dts;    uint8_t         *p_data = p_buffer->p_buffer;    size_t          i_data  = p_buffer->i_buffer;    size_t          i_max   = id->i_mtu - 12;    size_t i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;    while( i_data > 0 )    {        size_t i_size;        /* output complete packet */        if( p_sys->packet &&            p_sys->packet->i_buffer + i_data > i_max )        {            rtp_packetize_send( id, p_sys->packet );            p_sys->packet = NULL;        }        if( p_sys->packet == NULL )        {            /* allocate a new packet */            p_sys->packet = block_New( p_stream, id->i_mtu );            rtp_packetize_common( id, p_sys->packet, 1, i_dts );            p_sys->packet->i_dts = i_dts;            p_sys->packet->i_length = p_buffer->i_length / i_packet;            i_dts += p_sys->packet->i_length;        }        i_size = __MIN( i_data,                        (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );        memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],                p_data, i_size );        p_sys->packet->i_buffer += i_size;        p_data += i_size;        i_data -= i_size;    }    return VLC_SUCCESS;}static ssize_t AccessOutGrabberWrite( sout_access_out_t *p_access,                                      block_t *p_buffer ){    sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;    while( p_buffer )    {        block_t *p_next;        AccessOutGrabberWriteBuffer( p_stream, p_buffer );        p_next = p_buffer->p_next;        block_Release( p_buffer );        p_buffer = p_next;    }    return VLC_SUCCESS;}static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream ){    sout_access_out_t *p_grab;    p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );    if( p_grab == NULL )        return NULL;    p_grab->p_module    = NULL;    p_grab->p_sout      = p_stream->p_sout;    p_grab->psz_access  = strdup( "grab" );    p_grab->p_cfg       = NULL;    p_grab->psz_path    = strdup( "" );    p_grab->p_sys       = (sout_access_out_sys_t *)p_stream;    p_grab->pf_seek     = NULL;    p_grab->pf_write    = AccessOutGrabberWrite;    vlc_object_attach( p_grab, p_stream );    return p_grab;}

⌨️ 快捷键说明

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