本文爲做者原創,轉載請註明出處:http://www.javashuo.com/article/p-nbtinpnl-cm.htmlhtml
ffplay是一個很簡單的播放器,可是初次接觸仍會感到概念和細節至關繁多,分析並不容易。深刻理解一項技術須要足夠的時間和大量的實踐,由淺入深逐步迭代,沒有時間就成了最大難題。本次分析過程斷斷續續持續了挺久,先是邊讀代碼邊加註釋,後面才整理了筆記,再加上理解淺薄很難精簡語言,所以行文比較囉嗦。筆記記錄倉促,錯誤不免,歡迎指正交流。後續如有時間繼續研究,將持續修正錯誤完善文檔。git
ffplay是FFmpeg工程自帶的簡單播放器,使用FFmpeg提供的解碼器和SDL庫進行視頻播放。本文基於FFmpeg工程4.1版本進行分析,其中ffplay源碼清單以下:
https://github.com/FFmpeg/FFmpeg/blob/n4.1/fftools/ffplay.cgithub
在嘗試分析源碼前,可先閱讀以下參考文章做爲鋪墊:
[1]. 雷霄驊,視音頻編解碼技術零基礎學習方法
[2]. 視頻編解碼基礎概念
[3]. 色彩空間與像素格式
[4]. 音頻參數解析
[5]. FFmpeg使用基礎
另外,本文最後的參考資料對理解源碼幫助很大,在此向各位分享者表示感謝。參考資料內容更精彩,建議閱讀。網絡
本筆記只放在一篇文檔裏的話篇幅過長,遂拆分紅下面一系列文章:
[1]. ffplay源碼分析1-概述
[2]. ffplay源碼分析2-數據結構
[3]. ffplay源碼分析3-代碼框架
[4]. ffplay源碼分析4-音視頻同步
[5]. ffplay源碼分析5-圖像格式轉換
[6]. ffplay源碼分析6-音頻重採樣
[7]. ffplay源碼分析7-播放控制數據結構
下圖引用自「雷霄驊,視音頻編解碼技術零基礎學習方法」,因原圖過小,看不太清楚,故從新制做了一張圖片。
以下內容引用自「雷霄驊,視音頻編解碼技術零基礎學習方法」:框架
解協議
將流媒體協議的數據,解析爲標準的相應的封裝格式數據。視音頻在網絡上傳播的時候,經常採用各類流媒體協議,例如HTTP,RTMP,或是MMS等等。這些協議在傳輸視音頻數據的同時,也會傳輸一些信令數據。這些信令數據包括對播放的控制(播放,暫停,中止),或者對網絡狀態的描述等。解協議的過程當中會去除掉信令數據而只保留視音頻數據。例如,採用RTMP協議傳輸的數據,通過解協議操做後,輸出FLV格式的數據。ide解封裝
將輸入的封裝格式的數據,分離成爲音頻流壓縮編碼數據和視頻流壓縮編碼數據。封裝格式種類不少,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的做用就是將已經壓縮編碼的視頻數據和音頻數據按照必定的格式放到一塊兒。例如,FLV格式的數據,通過解封裝操做後,輸出H.264編碼的視頻碼流和AAC編碼的音頻碼流。函數解碼
將視頻/音頻壓縮編碼數據,解碼成爲非壓縮的視頻/音頻原始數據。音頻的壓縮編碼標準包含AAC,MP3,AC-3等等,視頻的壓縮編碼標準則包含H.264,MPEG2,VC-1等等。解碼是整個系統中最重要也是最複雜的一個環節。經過解碼,壓縮編碼的視頻數據輸出成爲非壓縮的顏色數據,例如YUV420P,RGB等等;壓縮編碼的音頻數據輸出成爲非壓縮的音頻抽樣數據,例如PCM數據。源碼分析音視頻同步
根據解封裝模塊處理過程當中獲取到的參數信息,同步解碼出來的視頻和音頻數據,並將視頻音頻數據送至系統的顯卡和聲卡播放出來。學習
_______ ______________ | | | | | input | demuxer | encoded data | decoder | file | ---------> | packets | -----+ |_______| |______________| | v _________ | | | decoded | | frames | |_________| ________ ______________ | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder |________| |______________|
ffmpeg
調用libavformat庫(包含解複用器demuxer),從輸入文件中讀取到包含編碼數據的包(packet)。若是有多個輸入文件,ffmpeg
嘗試追蹤多個有效輸入流的最小時間戳(timestamp),用這種方式實現多個輸入文件的同步。
而後編碼包被傳遞到解碼器(decoder),解碼器解碼後生成原始幀(frame),原始幀能夠被濾鏡(filter)處理(圖中未畫濾鏡),經濾鏡處理後的幀送給編碼器,編碼器將之編碼後輸出編碼包。最終,由複用器(muxex)將編碼碼寫入特定封裝格式的輸出文件。
ffplay不須要編碼過程,是將上圖中的解碼後幀送往屏幕顯示。
本節內容引用自「雷霄驊,最簡單的視音頻播放示例7:SDL2播放RGB/YUV」
SDL(Simple DirectMedia Layer)是一套開放源代碼的跨平臺多媒體開發庫,使用C語言寫成。SDL提供了數種控制圖像、聲音、輸出入的函數,讓開發者只要用相同或是類似的代碼就能夠開發出跨多個平臺(Linux、Windows、Mac OS X等)的應用軟件。目前SDL多用於開發遊戲、模擬器、媒體播放器等多媒體應用領域。用下面這張圖能夠很明確地說明SDL的位置。
SDL實際上並不限於視音頻的播放,它將功能分紅下列數個子系統(subsystem):
Video(圖像):圖像控制以及線程(thread)和事件管理(event)
Audio(聲音):聲音控制
Joystick(搖桿):遊戲搖桿控制
CD-ROM(光盤驅動器):光盤媒體控制
Window Management(視窗管理):與視窗程序設計集成
Event(事件驅動):處理事件驅動
SDL播放視頻流程以下:
可參考示例程序:「FFmpeg簡易播放器的實現-最簡版」
[1] 雷霄驊,視音頻編解碼技術零基礎學習方法
[2] 視頻編解碼基礎概念, http://www.javashuo.com/article/p-kfylstit-o.html
[3] 色彩空間與像素格式, http://www.javashuo.com/article/p-kwxfzypa-bs.html
[4] 音頻參數解析, http://www.javashuo.com/article/p-qkmpwcem-bt.html
[5] FFmpeg基礎概念, http://www.javashuo.com/article/p-hkmuzuvf-cb.html
[6] 零基礎讀懂視頻播放器控制原理:ffplay播放器源代碼分析, https://cloud.tencent.com/developer/article/1004559
[7] An ffmpeg and SDL Tutorial, Tutorial 05: Synching Video
[8] 視頻同步音頻, https://zhuanlan.zhihu.com/p/44615401
[9] 即時通信音視頻開發(一):視頻編解碼之理論概述, http://www.52im.net/thread-228-1-1.html
[10] 音頻同步視頻, https://zhuanlan.zhihu.com/p/44680734
[11] 音視頻同步(播放)原理, http://www.javashuo.com/article/p-cohhhvtj-ea.html
[12] 對ffmpeg的時間戳的理解筆記, https://blog.csdn.net/topsluo/article/details/76239136
[13] ffmpeg音視頻同步---視頻同步到音頻時鐘, http://www.javashuo.com/article/p-kkvxtpch-bh.html
[14] FFmpeg音視頻同步原理與實現, https://www.jianshu.com/p/3578e794f6b5
[15] FFmpeg學習4:音頻格式轉換, http://www.javashuo.com/article/p-vnkeckad-gy.html
[16] ffmpeg關於音頻的總結(一), http://www.javashuo.com/article/p-dyxqgfmn-cg.html
[17] FFmpeg關於nb_smples,frame_size以及profile的解釋, https://blog.csdn.net/zhuweigangzwg/article/details/53335941
[18] ffplay frame queue分析, https://zhuanlan.zhihu.com/p/43564980
[19] 難點seek操做, https://github.com/rockcarry/ffplayer/wiki/%E9%9A%BE%E7%82%B9-seek-%E6%93%8D%E4%BD%9C
2018-12-28 V1.0 初稿 2019-01-15 V1.0 增長FrameQueue數據結構說明 2019-01-15 V1.0 增長圖像格式轉換說明,新增音頻重採樣章節 2019-01-18 V1.0 增長SEEK操做說明章節 2019-01-19 V1.0 整理章節排序