天天看點

RTSP丢包處理原理及doubango代碼改進

在做視訊時,發現有時丢包很嚴重。當然,頭目甲提拔的研發總監李某,根本就沒有解決難題的想法。是以,這個問題隻能是吾解決了。終端使用的是doubango,吾研究了代碼,先後設計了兩個方案,做了大量改動。如有興趣,可以詳細了解。

 首先是自己管理丢包功能。本來這個方案也是可行的,适用于P2P模式。而李某隻做了伺服器轉發,轉發時會更改RTSP封包的資訊,進而導緻伺服器拒絕發送封包。這個方案測試之後隻能放棄。

 後來吾在代碼中發現,已經有處理丢包的代碼。吾仔細研究之後,搞明白了,當然也是很簡單的處理辦法。經過深入分析,吾搞了一套完備的丢包處理。看看tdav_session_video.c中,吾修改的一個函數,說明如下:

// From jitter buffer to codec
static int _tdav_session_video_jb_cb(const tdav_video_jb_cb_data_xt* data)
{
    tdav_session_video_t* video = (tdav_session_video_t*)data->usr_data;
    tdav_session_av_t* base = (tdav_session_av_t*)data->usr_data;
    tmedia_session_t* session = (tmedia_session_t*)data->usr_data;
 
    switch (data->type) {
    default:
        break;
    case tdav_video_jb_cb_data_type_rtp: {
        return _tdav_session_video_decode(video, data->rtp.pkt);
    }
    case tdav_video_jb_cb_data_type_tmfr: {
        base->time_last_frame_loss_report = tsk_time_now();
        _tdav_session_video_local_request_idr(session, "TMFR", data->ssrc);
    }
    case tdav_video_jb_cb_data_type_fl: {
        base->time_last_frame_loss_report = tsk_time_now();
        if(data->fl.count > TDAV_SESSION_VIDEO_PKT_LOSS_MAX_COUNT_TO_REQUEST_FIR) {
            _tdav_session_video_local_request_idr(session, "TMFR", data->ssrc);
        }
        else if (base->avpf_mode_neg || base->is_fb_nack_neg)
        { // AVPF?
            if (data->lost_pkt_info_list)
            {
                //想了想,還是暫時不公開。等……再說。
            }
            /*else if (data->fl.count > 0)
            {
                // 這個代碼我看明白了。
                // 每16個為一組進行發送。
                // i 進行分組,
                // k 是分組中的變量,
                // j 是每組的數量。
                // Send RTCP-NACK
                tsk_size_t i, j, k;
                uint16_t seq_nums[16];
                for (i = 0; i < data->fl.count; i+=16) {
                    for(j = 0, k = i; j < 16 && k < data->fl.count; ++j, ++k) {
                        seq_nums[j] = (uint16_t)(data->fl.seq_num + i + j);
                        TSK_DEBUG_INFO("Request re-send(%u)", seq_nums[j]);
                    }
                    trtp_manager_signal_pkt_loss(base->rtp_manager, data->ssrc, seq_nums, j);
                }
            }*/
 
        }
 
        break;
    }
    case tdav_video_jb_cb_data_type_fps_changed: {
        if (base->congestion_ctrl_enabled) {
            video->fps_changed = tsk_true;
            if (video->decoder.codec) {
                TSK_DEBUG_INFO("Congestion control enabled and fps updated from %u to %u", data->fps.old, data->fps.new);
                TMEDIA_CODEC_VIDEO(video->decoder.codec)->in.fps = data->fps.new;
            }
            tsk_mutex_lock(video->h_mutex_qos);
            session->qos_metrics.video_in_avg_fps = (session->qos_metrics.video_in_avg_fps + data->fps.new) / (video->in_avg_fps_n++ ? 2 : 1);
            tsk_mutex_unlock(video->h_mutex_qos);
        }
        break;
    }
    }
 
    return 0;
}      

在tdav_video_jb.c中,吾重新設計了丢包的判斷、儲存,然後再通過這裡發送。

 那麼改進效果如何?效果極為明顯。丢包30%時畫面都可以接受。吾還專門進行了統計、顯示。在南昌進行投标示範的時候,在視訊畫面上顯示出來,這樣畫面變差時很令人信服。

 這個隻是丢包檢測完成後的重發請求。其實還有大量的修改。

繼續閱讀