feng 的模块(框架)以及运作过程

来源:互联网 发布:淘宝客怎么推广到qq群 编辑:程序博客网 时间:2024/06/06 17:50
一、feng 的框架:
feng 的网络库
feng 使用是轻量级的事件库libev,
 
 
二、feng 是如何处理数据的
1、当处理PLAY请求时,feng 调用函数rtp_session_gslist_resume为每一个媒体(track)恢复播放,rtp_session_resume,在该函数,创建了一个线程池,线程数据为1个,(如果多个如何保存有序),线程池的回调是rtp_session_fill_cb,这个线程就是不停地从文件中读出数据,实际是调用钩子avf_read_packet从文件中读出数据,(暂停不知道读了多少数据),读出以后,调用ret = tr->parser->parse(tr, pkt.data, pkt.size);, 实际是调用h264.c注册的钩子,h264_parse, 分为avc格式和常规格式(avc格式起始码是一帧的长度,常规格式起始码是00000001), 我们先看常规格式,即起始码为00000001。
2、接着1,h264_parse其实就是分片,先找到一个nal(找到下一个起始码即可),判断nal的长度,如果小于一个MTU的大小,调用mparser_buffer_write,将数据写入feng 的bufferqueue,实际相当于一个生产者,(这个在PLAY请求后,创建线程池运行的),这么说,bufferqueue(用于数据的一生产多消费), 放入的是nal,即一个元素是nal,
这个小于MTU的nal直接就是rtp的数据了。
3、在PLAY中我们知道,在创建完线程池后,又创建了一个周期性读的rtp_write,这个函数周期性在rtp_write中,读出数据,这个周期性的写的函数可能是在SETUP,创建会话rtp_session_new创建的, 那么执行写的函数就是rtp_write_cb,在这里有足够的数据了,没有足够数据就等一个足够取到数据的时间,有了足够数据,就调用rtp_packet_send(session, buffer);将数据发出,
 
 
三、feng 程序运行过程:
1、在incoming.c中feng 调用feng_bind_port函数,生成主线程的监听fd(套接字),并注册回调rtsp_client_incoming_cb,这里使用的是半同步,半异步的reactor;
2、收到客户端的连接请求后,分别为连接返回的客户端fd, 注册可写,可读,异步断开连接,注册的回调为rtsp_write_cb, rtsp_read_cb, client_ev_disconnect_handler, 分别处理写,读,断开的事件;
3、当收到客户端RTSP请求后,回调rtsp_read_cb执行,通过rtsp_sock_read,将数据读出后,这时是rtsp消息(以两个/r/n/r/n结尾),调用RTSP_handler来处理相应的请求,这里面有这个处理方法的指针数据,比较有意思
enum RTSP_method_token {
  RTSP_ID_ERROR = ERR_GENERIC,
  RTSP_ID_DESCRIBE,
  RTSP_ID_ANNOUNCE,
  RTSP_ID_GET_PARAMETERS,
  RTSP_ID_OPTIONS,
  RTSP_ID_PAUSE,
  RTSP_ID_PLAY,
  RTSP_ID_RECORD,
  RTSP_ID_REDIRECT,
  RTSP_ID_SETUP,
  RTSP_ID_SET_PARAMETER,
  RTSP_ID_TEARDOWN
};
 
 static const rtsp_method_function methods[] = {
        [RTSP_ID_DESCRIBE] = RTSP_describe,
        [RTSP_ID_SETUP]    = RTSP_setup,
        [RTSP_ID_TEARDOWN] = RTSP_teardown,
        [RTSP_ID_OPTIONS]  = RTSP_options,
        [RTSP_ID_PLAY]     = RTSP_play,
        [RTSP_ID_PAUSE]    = RTSP_pause
    };
 
调用相应的消息的函数,进行处理methods[req->method_id](rtsp, req);
4、处理DESCRIBE 消息,先调用r_find_demuxer找到相应的文件的分离器(用于将包在一起的媒体分离出来),
在r_find_demuxer执行时,先注册钩子,用于不同的流类型的处理,
static const Demuxer *const demuxers[] = {
#ifdef LIVE_STREAMING
        &fnc_demuxer_sd,
#endif
        &fnc_demuxer_ds,
        &fnc_demuxer_avf,
        NULL
    };
然后来打开r_open_direct相应的文件,如果是avf类型(可能是文件类型),使用avf_init来初始化。
......
(未完待续)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

原创粉丝点击