ffplay源碼分析1-概述


本文為作者原創,轉載請注明出處:https://www.cnblogs.com/leisure_chn/p/10301215.html

ffplay是一個很簡單的播放器,但是初次接觸仍會感到概念和細節相當繁多,分析並不容易。深入理解一項技術需要足夠的時間和大量的實踐,由淺入深逐步迭代,沒有時間就成了最大難題。本次分析過程斷斷續續持續了挺久,先是邊讀代碼邊加注釋,后面才整理了筆記,再加上理解淺薄很難精簡語言,因此行文比較啰嗦。筆記記錄倉促,錯誤難免,歡迎指正交流。后續若有時間繼續研究,將持續修正錯誤完善文檔。

ffplay是FFmpeg工程自帶的簡單播放器,使用FFmpeg提供的解碼器和SDL庫進行視頻播放。本文基於FFmpeg工程4.1版本進行分析,其中ffplay源碼清單如下:
https://github.com/FFmpeg/FFmpeg/blob/n4.1/fftools/ffplay.c

在嘗試分析源碼前,可先閱讀如下參考文章作為鋪墊:
[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-播放控制

1. 基本原理

1.1 播放器基本原理

下圖引用自“雷霄驊,視音頻編解碼技術零基礎學習方法”,因原圖太小,看不太清楚,故重新制作了一張圖片。
播放器基本原理示意圖
如下內容引用自“雷霄驊,視音頻編解碼技術零基礎學習方法”:

解協議
將流媒體協議的數據,解析為標准的相應的封裝格式數據。視音頻在網絡上傳播的時候,常常采用各種流媒體協議,例如HTTP,RTMP,或是MMS等等。這些協議在傳輸視音頻數據的同時,也會傳輸一些信令數據。這些信令數據包括對播放的控制(播放,暫停,停止),或者對網絡狀態的描述等。解協議的過程中會去除掉信令數據而只保留視音頻數據。例如,采用RTMP協議傳輸的數據,經過解協議操作后,輸出FLV格式的數據。

解封裝
將輸入的封裝格式的數據,分離成為音頻流壓縮編碼數據和視頻流壓縮編碼數據。封裝格式種類很多,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的作用就是將已經壓縮編碼的視頻數據和音頻數據按照一定的格式放到一起。例如,FLV格式的數據,經過解封裝操作后,輸出H.264編碼的視頻碼流和AAC編碼的音頻碼流。

解碼
將視頻/音頻壓縮編碼數據,解碼成為非壓縮的視頻/音頻原始數據。音頻的壓縮編碼標准包含AAC,MP3,AC-3等等,視頻的壓縮編碼標准則包含H.264,MPEG2,VC-1等等。解碼是整個系統中最重要也是最復雜的一個環節。通過解碼,壓縮編碼的視頻數據輸出成為非壓縮的顏色數據,例如YUV420P,RGB等等;壓縮編碼的音頻數據輸出成為非壓縮的音頻抽樣數據,例如PCM數據。

音視頻同步
根據解封裝模塊處理過程中獲取到的參數信息,同步解碼出來的視頻和音頻數據,並將視頻音頻數據送至系統的顯卡和聲卡播放出來。

1.2 FFmpeg轉碼流程

 _______              ______________
|       |            |              |
| 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不需要編碼過程,是將上圖中的解碼后幀送往屏幕顯示。

1.3 SDL播放過程簡介

本節內容引用自“雷霄驊,最簡單的視音頻播放示例7:SDL2播放RGB/YUV

SDL(Simple DirectMedia Layer)是一套開放源代碼的跨平台多媒體開發庫,使用C語言寫成。SDL提供了數種控制圖像、聲音、輸出入的函數,讓開發者只要用相同或是相似的代碼就可以開發出跨多個平台(Linux、Windows、Mac OS X等)的應用軟件。目前SDL多用於開發游戲、模擬器、媒體播放器等多媒體應用領域。用下面這張圖可以很明確地說明SDL的位置。

SDL示意圖

SDL實際上並不限於視音頻的播放,它將功能分成下列數個子系統(subsystem):
Video(圖像):圖像控制以及線程(thread)和事件管理(event)
Audio(聲音):聲音控制
Joystick(搖桿):游戲搖桿控制
CD-ROM(光盤驅動器):光盤媒體控制
Window Management(視窗管理):與視窗程序設計集成
Event(事件驅動):處理事件驅動

SDL播放視頻流程如下:

  1. 初始化
  1. 初始化SDL
  2. 創建窗口(Window)
  3. 基於窗口創建渲染器(Render)
  4. 創建紋理(Texture)
  1. 循環顯示畫面
  1. 設置紋理的數據
  2. 紋理復制給渲染目標
  3. 顯示

可參考示例程序:“FFmpeg簡易播放器的實現-最簡版

8. 參考資料

[1] 雷霄驊,視音頻編解碼技術零基礎學習方法
[2] 視頻編解碼基礎概念, https://www.cnblogs.com/leisure_chn/p/10285829.html
[3] 色彩空間與像素格式, https://www.cnblogs.com/leisure_chn/p/10290575.html
[4] 音頻參數解析, https://blog.csdn.net/caoshangpa/article/details/51218597
[5] FFmpeg基礎概念, https://www.cnblogs.com/leisure_chn/p/10297002.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] 音視頻同步(播放)原理, https://blog.csdn.net/zhuweigangzwg/article/details/25815851
[12] 對ffmpeg的時間戳的理解筆記, https://blog.csdn.net/topsluo/article/details/76239136
[13] ffmpeg音視頻同步---視頻同步到音頻時鍾, https://my.oschina.net/u/735973/blog/806117
[14] FFmpeg音視頻同步原理與實現, https://www.jianshu.com/p/3578e794f6b5
[15] FFmpeg學習4:音頻格式轉換, https://www.cnblogs.com/wangguchangqing/p/5851490.html
[16] ffmpeg關於音頻的總結(一), https://blog.csdn.net/zhuweigangzwg/article/details/51499123
[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/難點-seek-操作

9. 修改記錄

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 整理章節排序


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM