feng 的模塊(框架)以及運作過程

一、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來初始化。
......
(未完待續)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章