2023-08-31

移動開發(fā)平臺視頻播放器探索

背景

APP開發(fā)中需要使用視頻播放器播放視頻雪隧,我們采用的是開源的第三方播放器IJK砰苍。雖然IJK功能強(qiáng)大吏祸,但是還是遇到不少問題揭糕。這里以iOS平臺為例子記錄下平時開發(fā)中學(xué)習(xí)到的知識和碰到的問題,以及如何解決屎即。

視頻播放基本流程

IJK是基于ffmpeg二次開發(fā)庙睡,其編解碼依賴于ffmpeg和videoToolBox,視頻顯示采用的是SDL(基于openGL實(shí)現(xiàn))技俐。整個視頻到畫面的流程我簡單用一張圖概括下乘陪。


視頻播放流程.jpg

流程看上去簡單,但是其中還涉及了多線程處理雕擂、圖形學(xué)知識啡邑、音視頻倍速播放等等知識,涉及的技術(shù)點(diǎn)很多井赌,想學(xué)透還是比較困難的谣拣。下面我將挑幾個基礎(chǔ)的簡單介紹募寨。

知識點(diǎn):視頻解碼I幀族展、B幀森缠、P幀以及視頻播放順序

視頻其實(shí)是一張張圖片按照時間點(diǎn)連續(xù)顯示到畫面上而形成的。如果視頻的清晰度很高仪缸,每張圖片都很大贵涵,那么在網(wǎng)絡(luò)上傳輸所付出代價就很大。所以視頻都不是原圖完完整整的保存的恰画,而是需要進(jìn)行"壓縮"宾茂,這個過程就是編碼,而按照什么規(guī)則"壓縮"就是編碼格式拴还,比如h265/h264跨晴。

在H.264壓縮標(biāo)準(zhǔn)中,編碼后,圖片會變成I幀片林,B幀端盆,P幀。


視頻組成.png

I幀

I幀其實(shí)就是完整的圖片费封,其沒有壓縮焕妙,可以直接用來顯示

P幀

P幀是基于前面的I幀進(jìn)行編碼的,所以要得到P幀原始的圖片需要前面I幀或者P幀的數(shù)據(jù)弓摘。


P幀.png

B幀

B幀是基于前面的幀和后面的幀一起編碼的焚鹊,要叨叨B真原始圖片需要前后2個幀。


B幀.png

視頻播放順序和視頻解碼順序

由于B幀的存在韧献,所以含有B幀視頻的解碼順序和播放順序是不一致的末患,比如


播放順序和解碼順序.jpg

所以有B幀的視頻播放順序不等于解碼順序。

實(shí)際遇到問題1

前段時間遇到一個視頻播放卡頓的問題锤窑,畫面播放不連續(xù)璧针。一開始以為是碼率不夠?qū)е碌奶鴰髞斫?jīng)過調(diào)試發(fā)現(xiàn)果复,音畫同步并沒有跳過幀陈莽,而是在排序隊(duì)列出口有大量的跳幀。這個問題比較奇怪虽抄,于是我對該過程進(jìn)行了模擬走搁。

由于B幀的存在,解碼的順序不等于播放順序迈窟,所以在解碼出幀后需要將現(xiàn)有幀根據(jù)播放順序排序击碗,IJK的設(shè)計是將幀放入排序隊(duì)列,并且保證隊(duì)列里有2幀以上才允許出隊(duì)列锄贼。那么上圖播放流程如下圖:


正常思路.jpg

目前按正常思路來看是正常的,2隊(duì)列深度不應(yīng)該出現(xiàn)跳幀情況索绪,但是事實(shí)調(diào)試確實(shí)出現(xiàn)了,這就比較奇怪了贫悄。后續(xù)查資料發(fā)現(xiàn) B幀是依賴P幀和I幀解碼瑞驱,那會不會B幀不是按照隊(duì)列先進(jìn)先出,而是先進(jìn)后出呢窄坦?圖調(diào)整如下唤反,不一樣的地方已經(jīng)標(biāo)紅:


實(shí)際上.jpg

是否規(guī)定B幀一定要先進(jìn)先出這個沒法考證,硬解碼返回的順序完全依賴VideoToolBox的代碼實(shí)現(xiàn)鸭津,并且IJK有多年未維護(hù)彤侍,很可能是該問題導(dǎo)致。修改方案是將排序隊(duì)列擴(kuò)大逆趋,避免丟幀的情況出現(xiàn)盏阶。

知識點(diǎn):RGB和YUV

RGB和YUV都是圖像對顏色的編碼方式,簡單理解就是2中不同的方式來描述顏色闻书,視頻幀里面就是存儲這些顏色信息名斟。一個“屏幕”有許多像素點(diǎn),幀數(shù)據(jù)就是告知“屏幕”中每一個像素點(diǎn)要顯示什么顏色惠窄,然后所有像素點(diǎn)都顯示自己的顏色后就形成了圖片蒸眠。

RGB就比較簡單了,就是三原色杆融,每個像素點(diǎn)都有紅楞卡、綠、藍(lán)個“燈泡”,像素點(diǎn)根據(jù)幀傳進(jìn)來的3個值來調(diào)整3個燈泡的亮度脾歇,光顏色疊加就能顯示不同的顏色蒋腮。

YUV是被歐洲電視系統(tǒng)所采用的一種顏色編碼方法,之前都是黑白電視藕各,RGB對黑白電視兼容性不好池摧,YUV可以。Y”表示明亮度(Luminance或Luma)激况,也就是灰階值作彤;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度乌逐,用于指定像素的顏色竭讳。那現(xiàn)在顯示屏是怎么用YUV顯示的呢?其實(shí)很簡單浙踢,就是將YUV根據(jù)算法轉(zhuǎn)換成RGB绢慢,然后采用RGB的方式進(jìn)行顯示。

IJK播放器從幀轉(zhuǎn)換成圖像的過程簡化如下:


顯示.jpg

圖像顯示這塊講述比較簡單洛波,具體可以參考其他資料胰舆,這里不再贅述骚露。

實(shí)際問題2

近期在播放視頻的時候發(fā)現(xiàn)視頻播放畫面顯示異常,顯示如下:

問題視頻.PNG

起初以為是解碼問題缚窿,因?yàn)橹苯雍谄良摇5亲屑?xì)看,還有一些紅色的影像在動滨攻。那么就先定位是什么問題導(dǎo)致够话。先通過電腦端測試視頻,發(fā)現(xiàn)可以播放光绕,說明視頻本身沒有問題。通過調(diào)試畜份,發(fā)現(xiàn)可以正常解碼出幀诞帐,并且音畫同步和排序隊(duì)列出幀扣都沒有丟幀的情況。那么就可以初步定位問題出在幀->渲染這層爆雹。下面繼續(xù)判斷是解出的幀有問題還是渲染有問題停蕉。

videoToolBox解出的數(shù)據(jù)是CVImageBufferRef(可以參考IJKVideoToolBoxSync.m中VTDecoderCallback回調(diào)),我們可以通過代碼,將CVImageBufferRef轉(zhuǎn)換成UIimage再在頁面上顯示钙态,看看幀是否能正常顯示慧起。結(jié)果可以顯示,那么問題就出在渲染層了册倒。

IJK的渲染是靠SDL蚓挤,其核心還是openGL,又由于該視頻是硬解碼驻子,所以直接定位到其render文件renderer_yuv420sp_vtb.m灿意。下斷點(diǎn)后發(fā)現(xiàn),在openGL生成YUV Y層貼圖時報錯:


Y層錯誤.png
報錯.png

嗯崇呵,Y層貼圖報錯缤剧,是剩UV層,Y層是表示亮度域慷,出錯后顯示黑色合情合理荒辕。但是該怎么修改呢,前面已經(jīng)證明幀數(shù)據(jù)沒有問題犹褒,那為什么Y層貼圖會報錯呢抵窒?并且這個錯誤也沒有具體回調(diào),線索就此斷了化漆,只知道是這里出問題估脆,但是無法修改,嘗試調(diào)整SDL幾個參數(shù)無果座云,陷入僵局疙赠。

后來點(diǎn)擊該方法付材,發(fā)現(xiàn)OPENGLES_DEPRECATED(ios(3.0, 12.0) 這么一句話,openGL在iOS12就被廢棄了圃阳?通過查資料厌衔,原來openGL在iOS12之后就不建議使用,蘋果采用替代方案Metal全面替代openGL捍岳,并且性能據(jù)說比之前高10倍富寿。開發(fā)文檔:開發(fā)文檔 IJK渲染層只是將幀轉(zhuǎn)化成圖像,只要幀已經(jīng)正確解出來并且格式固定锣夹,那么是采用OPENGL渲染還是采用Metal渲染對整個視頻播放流程無影響页徐。因此我們決定嘗試采用Metal全面替換openGL。

經(jīng)過幾天嘗試Metal银萍,發(fā)現(xiàn)Metal的寫法與OpenGL十分相似变勇,而且采用OC編寫面向?qū)ο螅梢灾苯佑肁RC管理內(nèi)存贴唇,省去了釋放內(nèi)存的煩惱搀绣。果然還是蘋果自家的東西好用。戳气。簡單的思路是在IJK播放器蓋一個MTKView瓶您,當(dāng)使用Metal渲染時將MTKView解除隱藏芯肤,將解析出來的CVPixelBufferRef一層層傳出來,遞給MTKView顯示击蹲。

優(yōu)勢:

1、CVPixelBufferRef-> MTKView都是蘋果的類类咧,兼容性好区宇,不會像openGL出現(xiàn)異常報錯

2、MTKView的性能更高

3卧晓、面向?qū)ο缶幊虄?nèi)存釋放有保障

劣勢:

1螟炫、有一定門檻昼钻,有openGL開發(fā)經(jīng)驗(yàn)更容易理解狈究。

調(diào)整后的視頻如下:

結(jié)果.PNG
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末磅废,一起剝皮案震驚了整個濱河市竟趾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖贾费,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箱玷,死亡現(xiàn)場離奇詭異波丰,居然都是意外死亡沐批,警方通過查閱死者的電腦和手機(jī)先馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門仿野,熙熙樓的掌柜王于貴愁眉苦臉地迎上來犁河,“玉大人,你說我怎么就攤上這事辣苏『灏” “怎么了稀蟋?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呐赡。 經(jīng)常有香客問我退客,道長,這世上最難降的妖魔是什么链嘀? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任萌狂,我火速辦了婚禮,結(jié)果婚禮上怀泊,老公的妹妹穿的比我還像新娘茫藏。我一直安慰自己,他們只是感情好霹琼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布务傲。 她就那樣靜靜地躺著,像睡著了一般枣申。 火紅的嫁衣襯著肌膚如雪售葡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天忠藤,我揣著相機(jī)與錄音天通,去河邊找鬼。 笑死熄驼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烘豹。 我是一名探鬼主播瓜贾,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼携悯!你這毒婦竟也來了祭芦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤憔鬼,失蹤者是張志新(化名)和其女友劉穎龟劲,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轴或,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昌跌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了照雁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕愤。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出萍诱,到底是詐尸還是另有隱情悬嗓,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布裕坊,位于F島的核電站包竹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏籍凝。R本人自食惡果不足惜周瞎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望静浴。 院中可真熱鬧堰氓,春花似錦、人聲如沸苹享。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽得问。三九已至囤攀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宫纬,已是汗流浹背焚挠。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漓骚,地道東北人蝌衔。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蝌蹂,于是被迫代替她去往敵國和親噩斟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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