并非真正使用了 WebRTC,但此處存在使用 WebRTC 技術(shù)性質(zhì)的相似之處。
Netflix的應(yīng)用程序可以在數(shù)百臺智能電視、電視棒和付費電視機頂盒上運行。Netflix的合作工程師的角色是幫助設(shè)備制造商在他們的設(shè)備上啟動Netflix應(yīng)用程序。在這篇文章中,我們將討論一個特別困難的問題,它影響了一款設(shè)備在歐洲的正常發(fā)布。
神秘的開始
2017年底,我參加一個電話會議,其中主要討論一個關(guān)于Netflix應(yīng)用程序在新機頂盒上啟動的問題。box是一款全新的Android電視設(shè)備,具有4k播放功能,基于Android開放源碼項目(AOSP) 5.0版本,又名“棒棒糖”。我在Netflix工作了幾年,過去發(fā)布過很多臺設(shè)備,但這是我推出的第一款A(yù)ndroid電視設(shè)備。
與該設(shè)備相關(guān)的四家公司都在此次電話會議中:推出該設(shè)備的大型歐洲付費電視公司(運營商)、集成機頂盒固件的承包商(集成商)、系統(tǒng)芯片供應(yīng)商(芯片供應(yīng)商)和我(Netflix)。
這家集成機頂盒固件的承包商(集成商)和Netflix已經(jīng)完成了嚴格的Netflix認證程序,但在這家電視運營商的內(nèi)部測試過程中,該公司的一名高管報告了一個嚴重問題:Netflix在他的設(shè)備上播放“結(jié)巴(卡頓)”。即視頻會播放很短的時間后暫停,接著重新開始,隨后又暫停。這種情況并不會一直發(fā)生,但肯定會在機頂盒通電后的幾天內(nèi)開始發(fā)生。他們提供了一段演示視頻,情況看起來很糟糕。
設(shè)備集成商找到了重現(xiàn)這個問題的方法:反復(fù)啟動Netflix,開始播放,然后回到設(shè)備的用戶界面。他們提供了一個腳本來自動化這個過程,有時這個過程會持續(xù)長達五分鐘的時間,但是腳本總是能夠穩(wěn)定地重現(xiàn)錯誤。
與此同時,芯片供應(yīng)商的一名現(xiàn)場工程師診斷出了根本原因:Netflix的Android電視應(yīng)用程序Ninja傳輸音頻數(shù)據(jù)的速度不夠快。卡頓是由于設(shè)備音頻管道緩沖不足引起的。當(dāng)解碼器等待Ninja傳送更多的音頻流時,播放停止,等待更多的數(shù)據(jù)到達后恢復(fù)播放。集成商、芯片供應(yīng)商和運營商都認為問題已經(jīng)確定,他們向我傳達的信息很明確:Netflix,你的應(yīng)用程序中有一個漏洞,你需要修復(fù)它。我從通話里聽出了壓力。他們設(shè)備的上線時間推遲了,而且超出了預(yù)算,他們期待我的解決方案。
調(diào)查
我持懷疑態(tài)度。同樣的Ninja應(yīng)用程序在數(shù)以百萬計的Android電視設(shè)備上運行,包括智能電視和其他機頂盒。如果Ninja存在漏洞,為什么它只出現(xiàn)在這款設(shè)備上?
我首先使用他們提供的腳本重現(xiàn)了問題,同時聯(lián)系了芯片供應(yīng)商的同事,詢問他以前是否見過類似的情況(他沒有見過)。接下來我開始檢查Ninja的源代碼,我想找到傳輸音頻數(shù)據(jù)的那行代碼。我認識很多,但我在播放代碼中開始不知所措,我需要幫助。
我上樓找到了Ninja編寫音頻和視頻傳輸代碼的工程師,他幫我梳理了代碼。我自己花了一些時間研究源代碼來理解它的工作部分,并添加了我自己的日志記錄來確認我的理解。Netflix應(yīng)用程序很復(fù)雜,簡單來說,它從Netflix服務(wù)器傳輸數(shù)據(jù),在設(shè)備上緩沖數(shù)秒的視頻和音頻數(shù)據(jù),然后一次一次地將視頻和音頻幀發(fā)送到設(shè)備的播放硬件。
圖1:設(shè)備播放管道(簡化)
讓我們花點時間來討論Netflix應(yīng)用程序中的音頻/視頻管道。在每個機頂盒和智能電視上,直到“解碼器緩沖區(qū)”都是相同的,但是將A/V數(shù)據(jù)傳輸?shù)皆O(shè)備的解碼器緩沖區(qū)是一個特定的程序,在它自己的線程中運行。它的例行工作是通過調(diào)用提供音頻或視頻數(shù)據(jù)下一幀的API(Netflix提供)來保持解碼器緩沖區(qū)滿狀態(tài)。在Ninja中,這一任務(wù)是由Android線程執(zhí)行的。有一個簡單的狀態(tài)機和一些邏輯來處理不同的播放狀態(tài),但在正常播放下,線程將一幀數(shù)據(jù)復(fù)制到Android播放API中,然后告訴線程調(diào)度程序等待15毫秒并再次調(diào)用處理程序。當(dāng)你創(chuàng)建一個Android線程時,可以請求線程重復(fù)運行,就像在一個循環(huán)中一樣,但是調(diào)用處理程序的是Android的線程調(diào)度程序,不是你自己的應(yīng)用程序。
60幀/秒是Netflix能播放視頻的最高幀率,設(shè)備必須每16.66毫秒渲染一個新幀,所以每15毫秒檢查一個新樣本的速度足以領(lǐng)先于Netflix提供的任何視頻流。因為集成商已經(jīng)確定音頻流是問題所在,所以我將注意力集中放在將音頻樣本傳遞給Android音頻服務(wù)的特定線程處理程序上。
我想回答這個問題:額外的時間在哪里?假設(shè)罪魁禍首是處理程序調(diào)用的某個函數(shù),所以我在處理程序中添加了日志消息,假設(shè)錯誤代碼是顯而易見的。很快就可以看出,處理程序中沒有任何不正常的行為,即使播放不流暢,處理器也能在幾毫秒內(nèi)運行正常。
啊哈,洞察力
最后,我關(guān)注了三個數(shù)字:數(shù)據(jù)傳輸速率,處理程序被調(diào)用的時間,以及處理程序?qū)⒖刂茩?quán)交還給Android的時間。我編寫了一個腳本來解析日志輸出,并制作了下面的圖表,它給出了答案。
圖2:可視化音頻吞吐量和線程處理器時間
橙色的線是數(shù)據(jù)從流媒體緩沖區(qū)移動到Android音頻系統(tǒng)的速率,單位是字節(jié)/毫秒。在這張圖表中,你可以看到三種不同的行為:
這兩個又高又尖的部分,數(shù)據(jù)速率達到500字節(jié)/毫秒。這是在播放開始之前的緩沖階段。處理程序正在盡可能快地復(fù)制數(shù)據(jù)。
中間的區(qū)域是正常播放階段。音頻數(shù)據(jù)以大約45字節(jié)/毫秒的速度傳輸。
當(dāng)音頻數(shù)據(jù)以接近10字節(jié)/毫秒的速度傳輸時,卡頓區(qū)域在右側(cè)。速度還不夠快,無法維持正常播放。
不可避免的結(jié)論是橙色線證實了芯片供應(yīng)商工程師的報告:Ninja傳輸音頻數(shù)據(jù)的速度不夠快。
為了理解這其中的原因,讓我們看看黃線和灰線又說明了哪些問題。
黃色的線顯示花費在處理程序本身的時間,根據(jù)處理程序頂部和底部記錄的時間戳計算。在正常播放和卡頓的區(qū)域,處理程序花費的時間是相同的:大約2毫秒。峰值顯示由于在設(shè)備上其他任務(wù)花費了時間而導(dǎo)致Ninja傳輸音頻數(shù)據(jù)的速度不夠快。
真正的原因
灰色的線是兩次調(diào)用處理程序之間的時間,它說明了不同的情況。在正常播放的情況下,你可以看到處理程序大約每15毫秒被調(diào)用一次。在播放卡頓的情況下,在右側(cè)大約每55毫秒調(diào)用一次處理程序。調(diào)用之間有額外的40毫秒,沒有辦法跟上播放的速度。但這是為什么呢?
我把我的發(fā)現(xiàn)告訴了集成商和芯片供應(yīng)商 (看,這是Android線程調(diào)度程序!),但他們對這一發(fā)現(xiàn)并不感冒。為什么不在每次調(diào)用處理程序時復(fù)制更多的數(shù)據(jù)呢?這是一個合理的質(zhì)疑,但改變這種行為涉及更深層次的變化,超出了我的準備,我繼續(xù)尋找根本原因。我深入研究了Android源代碼,了解到Android線程是一個用戶空間結(jié)構(gòu),線程調(diào)度程序使用epoll()系統(tǒng)調(diào)用進行計時。我知道epoll()的性能不能得到保證,所以我懷疑有什么東西以系統(tǒng)的方式影響epoll()。
就在這時,芯片供應(yīng)商的另一位工程師救了我,他發(fā)現(xiàn)了一個漏洞,這個漏洞在下一個名為“棉花糖”(Marshmallow)的Android版本中已經(jīng)修復(fù)了。Android線程調(diào)度程序根據(jù)應(yīng)用程序是在前臺運行還是在后臺運行來改變線程的行為。后臺線程被分配額外的40毫秒(4000萬ns)的等待時間。
Android系統(tǒng)本身的一個深層漏洞意味著當(dāng)線程移動到前臺時,這個額外的定時器值被保留。通常音頻處理線程是在應(yīng)用程序處于前臺時創(chuàng)建的,但有時線程是在Ninja仍然在后臺時創(chuàng)建的。當(dāng)這種情況發(fā)生時,播放就會卡頓。
經(jīng)驗教訓(xùn)
這并不是我們在這個平臺上修復(fù)的最后一個漏洞,但卻是最難追蹤的一個。它在Netflix應(yīng)用程序之外,在播放線程之外的系統(tǒng)部分,所有的初始數(shù)據(jù)都表明Netflix應(yīng)用程序本身存在缺陷。
這個故事確實體現(xiàn)了我熱愛這份工作的一個方面:我不能預(yù)知我們的合作伙伴會向我拋出的所有問題,要解決這些問題,我必須了解多個系統(tǒng),與優(yōu)秀的同事合作,并不斷督促自己學(xué)習(xí)更多知識。我所做的事直接影響著現(xiàn)實中的人們以及他們的用戶體驗。我知道,當(dāng)人們在客廳里享受Netflix時,我是Netflix團隊中不可或缺的一員,是我們讓這一切成為現(xiàn)實。
責(zé)任編輯:lq
-
應(yīng)用程序
+關(guān)注
關(guān)注
37文章
3267瀏覽量
57684 -
Netflix
+關(guān)注
關(guān)注
0文章
89瀏覽量
11212 -
WebRTC
+關(guān)注
關(guān)注
0文章
57瀏覽量
11240
原文標(biāo)題:Netflix 工程師的生活 —— 40毫秒的案例
文章出處:【微信號:livevideostack,微信公眾號:LiveVideoStack】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論