直播問題分析總結(jié) -- 跳幀

跳幀策略

跳幀策略是指在播放累積延遲逐漸增大時采取的 " 丟棄非實時數(shù)據(jù) " 的策略约郁。

跳幀目的

為了保證實時性。

跳幀的原因分析

跳幀的原因匯總
非實時數(shù)據(jù)來不及處理

由于流媒體服務(wù)器本身的處理能力的問題但两,累計的非實時數(shù)據(jù)超過一定閾值(比如50幀)鬓梅,此時流媒體服務(wù)器可能會采取直接丟棄非實時幀序列的策略,然后直接處理實時幀谨湘,此時在客戶端看來就會出現(xiàn)跳幀的現(xiàn)象绽快。
除了直播,如果錄制的文件存在跳幀的現(xiàn)象(一般只會在大批量錄制的時候出現(xiàn))紧阔,非撤话眨可能是服務(wù)器的硬盤讀寫功能跟不上,來不及寫數(shù)據(jù)就被丟棄了擅耽,此時應(yīng)更換性能更好的硬盤活孩。

CPU占用過高

CPU占用過高,處理能力有限乖仇,導(dǎo)致收到的數(shù)據(jù)被丟棄憾儒,繼而處理最新的數(shù)據(jù),從而出現(xiàn)跳幀現(xiàn)象这敬。

播放器緩沖過小

播放器的緩存時間過小航夺,比如為0或著0.1,也會導(dǎo)致跳幀出現(xiàn)崔涂。
增加緩存時間可有效避免跳幀阳掐,但會影響實時性。

某次跳幀現(xiàn)象的分析和解決

現(xiàn)象描述

Windows 7下MFC開發(fā)的終端軟件(下文中簡稱終端)冷蚂,在內(nèi)嵌瀏覽器(Microsoft Web Browser控件)中打開網(wǎng)頁缭保。
網(wǎng)頁中通過Flash Player播放rtmp流,存在嚴(yán)重的跳幀的現(xiàn)象蝙茶。
基本上是艺骂,正常23秒,然后跳23秒隆夯,很是詭異钳恕。
處理步驟:

  • Step 1: 用IE直接網(wǎng)頁直播
    關(guān)閉終端,直接在IE中打開網(wǎng)頁查看直播蹄衷,發(fā)現(xiàn)不存在跳幀現(xiàn)象忧额,所以基本斷定應(yīng)該是終端本身處理的問題。
  • Step 2: 排除網(wǎng)絡(luò)原因愧口。
    分別通過以下ping的方式睦番,
ping 192.168.2.222 -t -l 4096

簡單分析了,視頻源到流媒體服務(wù)器,還有流媒體服務(wù)器到終端的網(wǎng)絡(luò)情況托嚣,發(fā)現(xiàn)時間基本上都在1~2ms左右巩检,說明網(wǎng)絡(luò)情況良好。

  • Step 3: 分析流本身的問題示启。
    獲取到rtmp流的實際地址兢哭,通過工具將rtmp流直接錄制能flv文件,將文件播放后發(fā)現(xiàn)丑搔,視頻連續(xù)厦瓢,也不存在跳幀的現(xiàn)象。說明流數(shù)據(jù)本身是好的啤月。
  • Step 4: 分析終端的邏輯煮仇。
    查看終端的任務(wù)瀏覽器時,發(fā)現(xiàn)了一個令人懷疑的現(xiàn)象谎仲,CPU的使用率本身并不高浙垫,一般在20%~50%左右,但CPU的頻率過高郑诺,一直在100%以上夹姥。
    CPU的頻率過高

    這時候,懷疑可能是終端程序中辙诞,對CPU的處理導(dǎo)致的辙售。
    忽然想起前一陣,在程序中加入了CPU的處理流程飞涂,每隔5秒中旦部,獲取當(dāng)前程序占用CPU和系統(tǒng)占用的CPU,返回給服務(wù)器较店。
    代碼如下:
#include <stdio.h>  
#include <Windows.h>

typedef long long           int64_t;
typedef unsigned long long  uint64_t;

/// 時間轉(zhuǎn)換
static uint64_t file_time_2_utc(const FILETIME* ftime)
{
    LARGE_INTEGER li;

    li.LowPart  = ftime->dwLowDateTime;
    li.HighPart = ftime->dwHighDateTime;

    return li.QuadPart;
}

/// 獲得CPU的核數(shù)
static int get_processor_number()
{
    SYSTEM_INFO info;
    GetSystemInfo(&info);
    return (int)info.dwNumberOfProcessors;
}

/// 獲取指定進程占用的CPU
int get_cpu_usage(int pid)
{  
    /// cpu數(shù)量
    static int processor_count_ = -1;

    // 上一次的時間
    static uint64_t last_time_ = 0;
    static uint64_t last_system_time_ = 0;

    FILETIME now;
    FILETIME creation_time;
    FILETIME exit_time;
    FILETIME kernel_time;
    FILETIME user_time;
    uint64_t system_time;
    uint64_t time;
    uint64_t system_time_delta;
    uint64_t time_delta;

    int cpu = -1;

    if(processor_count_ == -1)
    {
        processor_count_ = get_processor_number();
    }

    GetSystemTimeAsFileTime(&now);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
    if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
    {
        return 0;
    }

    system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time)) 
                  / processor_count_;  

    time = file_time_2_utc(&now);

    if ((last_system_time_ == 0) || (last_time_ == 0))
    {
        last_system_time_ = system_time;
        last_time_ = time;

        return 0;
    }

    system_time_delta = system_time - last_system_time_;
    time_delta = time - last_time_;

    if (time_delta == 0)
    {
        return 0;
    }

    cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);
    last_system_time_ = system_time;
    last_time_ = time;

    return cpu;
}

/// 獲取系統(tǒng)占用的CPU
int get_sys_cpu_usage()  
{  
    /// cpu數(shù)量  
    static int processor_count_ = -1;  

    /// 上一次的時間  
    static int64_t last_time_        = 0;  
    static int64_t last_system_time_ = 0;  

    FILETIME now;  
    FILETIME creation_time;  
    FILETIME exit_time;  
    FILETIME kernel_time;  
    FILETIME user_time;  
    int64_t system_time;  
    int64_t time;  
    int64_t system_time_delta;  
    int64_t time_delta;  

    int cpu = -1;  

    if(processor_count_ == -1)  
    {  
        processor_count_ = get_processor_number();  
    }  

    GetSystemTimeAsFileTime(&now);  

    if (!GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,  
        &kernel_time, &user_time))  
    {  
        // We don't assert here because in some cases (such as in the Task  Manager)  
        // we may call this function on a process that has just exited but we have  
        // not yet received the notification.  
        return -1;  
    }  

    system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time))   
                  / processor_count_;  
    time = file_time_2_utc(&now);  

    if ((last_system_time_ == 0) || (last_time_ == 0))  
    {  
        // First call, just set the last values.  
        last_system_time_ = system_time;  
        last_time_ = time;  

        return -1;  
    }  

    system_time_delta = system_time - last_system_time_;  
    time_delta = time - last_time_;  

    if (time_delta == 0)  
    {
        return -1;  
    }

    // We add time_delta / 2 so the result is rounded.  
    cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);  

    last_system_time_ = system_time;  
    last_time_ = time; 

    return cpu;  
}  

分析發(fā)現(xiàn)士八,禁用CPU操作相關(guān)的函數(shù)后,跳幀的現(xiàn)象消失梁呈。

References:

https://alwaysmavs.gitbooks.io/plplayerkit/content/4%20%E7%9B%B4%E6%92%AD%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/4.1%20%E8%B7%B3%E5%B8%A7%E7%AD%96%E7%95%A5.html
http://www.reibang.com/p/ecf51ee32589

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婚度,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子官卡,更是在濱河造成了極大的恐慌蝗茁,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寻咒,死亡現(xiàn)場離奇詭異评甜,居然都是意外死亡,警方通過查閱死者的電腦和手機仔涩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粘舟,“玉大人熔脂,你說我怎么就攤上這事佩研。” “怎么了霞揉?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵旬薯,是天一觀的道長衔憨。 經(jīng)常有香客問我梧乘,道長,這世上最難降的妖魔是什么夸盟? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任秽荞,我火速辦了婚禮骤公,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扬跋。我一直安慰自己阶捆,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布钦听。 她就那樣靜靜地躺著洒试,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朴上。 梳的紋絲不亂的頭發(fā)上垒棋,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音痪宰,去河邊找鬼叼架。 笑死,一個胖子當(dāng)著我的面吹牛酵镜,可吹牛的內(nèi)容都是我干的碉碉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼淮韭,長吁一口氣:“原來是場噩夢啊……” “哼垢粮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起靠粪,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜡吧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后占键,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昔善,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年畔乙,在試婚紗的時候發(fā)現(xiàn)自己被綠了君仆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖返咱,靈堂內(nèi)的尸體忽然破棺而出钥庇,到底是詐尸還是另有隱情,我是刑警寧澤咖摹,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布评姨,位于F島的核電站,受9級特大地震影響萤晴,放射性物質(zhì)發(fā)生泄漏吐句。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一店读、第九天 我趴在偏房一處隱蔽的房頂上張望嗦枢。 院中可真熱鬧,春花似錦两入、人聲如沸净宵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽择葡。三九已至,卻和暖如春剃氧,著一層夾襖步出監(jiān)牢的瞬間敏储,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工朋鞍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留已添,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓滥酥,卻偏偏與公主長得像更舞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坎吻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,986評論 6 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 在保證視頻圖像質(zhì)量的前提下缆蝉,HEVC通過增加一定的計算復(fù)雜度,可以實現(xiàn)碼流在H.264/AVC的基礎(chǔ)上降低50%瘦真。...
    加劉景長閱讀 7,878評論 0 6
  • 近幾天刊头,乘“澠池星美國際影城”開業(yè)的東風(fēng),贈優(yōu)惠票诸尽,我決定去感受一下這個國際影城的氛圍原杂。 吃過晚飯,揣著票您机,一路期...
    涼月西風(fēng)閱讀 246評論 0 1
  • 也許這樣的生活明天就會結(jié)束穿肄,也許會一直持續(xù)下去年局,會一次次的在不知名的角落哭泣,會一次又一次被生活折磨得左右為...
    清舞_d528閱讀 400評論 1 0