vlc源码分析(3)-decoder.c 使用vlm rtsp方式输出流过程

从解复用,路过解码器,到输出 sout.

数据从 demux 解复用出来,放到解码器的fifo中,创建 解码器。

进入decoder.c的解码线程,从复用 demux出来的 mp4文件有两个 es流,video, audio,所以会创建两个 decoder,即两个decode线程分析decode线程中将数据 输出到 rtp的流程:

从 demux 解析出来的音频或视频es流,这里选择 rtsp输出(针对该demo的流程分析demo:https://blog.csdn.net/u012459903/article/details/88600045),没有涉及到播放显示。

下图中 部分函数 从rtp中来,关于跳转到rtp中的转折,在后续分析sout的初始化中

有两个单独的解码线程 video  audio , 对应有两个 sout 发送数据输出的线程。

rtps的相关部分:

上面图分心了数据从解复用,到解码器里面的一系列历程,最后调用到发送线程,发送线程:

static void* ThreadSend( void *data )
{
    sout_stream_id_sys_t *id = data;
    ...
    for (;;)
    {
        block_t *out = block_FifoGet( id->p_fifo );
    ...  
         for( int i = 0; i < id->sinkc; i++ )
         {
            SendRTCP( id->sinkv[i].rtcp, out )
            send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 )
         }
        
    }

    ...
}

看到这里的send, 用到 sout_stream_id_sys_t *id 中的 sinkv,进行数据 rtcp 和rtp的发送,这个 sinkv,即rtsp"过滤器"。逆向查找,可以找到他的创建过程:

stream_out/rtp.c 该模块的加载 ,在input线程启动时候调用 init()时,初始化InitSout( p_input )// 流输出   关于input线程已经在上一篇分析https://blog.csdn.net/u012459903/article/details/88896095 

补充一下 这个InitSout的分析

input.c 文件
static int InitSout( input_thread_t * p_input )
{
 input_thread_private_t *priv = input_priv(p_input);
 ...
//这里的 psz = "#rtp{sdp=rtsp://192.168.43.129:10086/stream}"
 priv->p_sout  = input_resource_RequestSout( priv->p_resource, NULL, psz );
==》 //经过几轮转换,调用到strem_output.c 中的 sout_StreamChainNew();创建一个流的链。 即上面的参数还可以增加,相当于添加多个 流的过滤器, 组成一个链条一样的一串过滤器, 我这里只有一个,所以这个链里面其实只有一个stream 过滤器。

sout_StreamChainNew 内部调用 sout_StreamNew来创建单个的 stream过滤器:
 sout_StreamNew( sout_instance_t *p_sout, char *psz_name,
 config_chain_t *p_cfg, sout_stream_t *p_next)
 {
    sout_stream_t *p_stream;
    p_stream = vlc_custom_create( p_sout, sizeof( *p_stream ), "stream out" );
    ...
    //重点,这里要加载模块了,此处的 p_stream->psz_name = "rtp"
    p_stream->p_module =
        module_need( p_stream, "sout stream", p_stream->psz_name, true );
    ...
 }
}

上面是从 input.c 到 rtp.c文件的跳转,和这个rtsp的关系,在rtp模块的 open中

static int Open( vlc_object_t *p_this )
{
...
    sout_stream_t       *p_stream = (sout_stream_t*)p_this;
...
    
     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
    if( psz != NULL )
    {
        // 参数 ps = "rtsp://192.168.43.129:10086/stream "
        SDPHandleUrl( p_stream, psz );
        //
          SDPHandleUrl()这个函数,在分析到上面的 rtsp后,调用 
           p_sys->rtsp = RtspSetup( VLC_OBJECT(p_stream), NULL, url.psz_path );
            激活rtsp。

           ==> RtspHandler()==>
            rtp_add_sink()
            {    ...
                 rtp_sink_t sink = { fd, NULL };
                 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
                          rtcp_mux );
                 TAB_APPEND(id->sinkc, id->sinkv, sink);
                 ...
            }
            
        ...
    }
...
}

rtp的 open 过程中,根据url,激活了rtsp, 然后再rtsp的控制中 调用 rtp_add_sink() 设置到 sout_stream_id_sys_t *id ->sinkv

这个就是ThreadSedn线程 用到的sinkv.  (rtsp 发送这部分需要有客户端连接才会触发)

猜你喜欢

转载自blog.csdn.net/u012459903/article/details/89000257
今日推荐