音視頻開發(fā)之旅(60) -調(diào)試分析FFmpeg (解封裝部分的)常用結(jié)構(gòu)體

目錄

  1. ffplay的斷點調(diào)試
  2. (解封裝部分)常用結(jié)構(gòu)體以及之間的關(guān)系分析
  3. 資料
  4. 收獲

工欲善其事笔呀,必先利其器埠帕,斷點調(diào)試媳瞪,對我們梳理流程排查問題十分重要抑片,可以ffmpeg的調(diào)試可以在XCode、VS code以及QT等ide上進行方便的調(diào)試分析硫惕。本篇我們以XCode為例來先介紹下ffplay的斷點調(diào)試茧痕,以ffmpeg4.4版本來進行分析。

一恼除、ffplay的斷點調(diào)試

首先下載和編譯ffmpeg踪旷,具體可以參考音視頻開發(fā)之旅(33) -交叉編譯android使用的FFmpeg(3.x和4.x)
區(qū)別在于,我們這次不是交叉編譯豁辉,而是在Mac上編譯安裝調(diào)試令野。

./configure --enable-static --disable-shared --enable-debug --disable-doc --disable-x86asm --enable-nonfree  --enable-libvpx --enable-gpl  --enable-opengl --enable-libx264  --enable-libx265 --enable-libvmaf
make -j8
sudo make install

編譯成功之后我們會看到幾個重要的可執(zhí)行文件ffmpeg_g、ffprobe_g以及ffplay_g,而接下來的運行和調(diào)試就會用到他們徽级。
如何在Xcode下配置調(diào)試ffmpeg源碼請參考:http://www.reibang.com/p/27a90b113413

我們在ffplay.c的main函數(shù)打斷點進行進行分析ffplay解封裝(read_thread)流程中用的的結(jié)構(gòu)體气破。

打開媒體流

VideoState *stream_open(const char *filename,const AVInputFormat *iformat)

涉及到結(jié)構(gòu)體:AVInputFormat

啟動readthread開始讀取

    is->read_tid     = SDL_CreateThread(read_thread, "read_thread", is);

分配AVFormatContext內(nèi)存

 AVFormatContext   ic = avformat_alloc_context();

打開流媒體文件

int avformat_open_input(AVFormatContext **ps, const char *filename,
                        const AVInputFormat *fmt, AVDictionary **options)

涉及到結(jié)構(gòu)體:AVFormatContext、AVInputFormat灰追、AVDictionary

獲取流信息

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)

涉及到結(jié)構(gòu)體:AVStream AVCodecParameters AVRational

循環(huán)讀取frame數(shù)據(jù)

 for (;;) {
     ...
     int av_read_frame(AVFormatContext *s, AVPacket *pkt)
     ...
}

涉及到結(jié)構(gòu)體:AVFormatContext堵幽、AVPacket等

解封裝的流程先到這里,可見如果想學(xué)習(xí)ffplay的源碼弹澎,首先要搞清楚主要流程以及過程中涉及的關(guān)鍵結(jié)構(gòu)體。
下一節(jié)我們來具體分析這些結(jié)構(gòu)體努咐。

三苦蒿、(解封裝部分)常用結(jié)構(gòu)體以及之間的關(guān)系分析常用結(jié)構(gòu)體以及之間的關(guān)系分析

3.1 常用結(jié)構(gòu)體以及之間的關(guān)系

FFMPEG中結(jié)構(gòu)體很多。最關(guān)鍵的結(jié)構(gòu)體可以分成以下幾類:
a)        解協(xié)議(http,rtsp,rtmp,mms)

AVIOContext渗稍,URLProtocol佩迟,URLContext主要存儲視音頻使用的協(xié)議的類型以及狀態(tài)。URLProtocol存儲輸入視音頻使用的封裝格式竿屹。每種協(xié)議都對應(yīng)一個URLProtocol結(jié)構(gòu)报强。(注意:FFMPEG中文件也被當做一種協(xié)議“file”)

b)        解封裝(flv,avi,rmvb,mp4)

AVFormatContext主要存儲視音頻封裝格式中包含的信息;AVInputFormat存儲輸入視音頻使用的封裝格式拱燃。每種視音頻封裝格式都對應(yīng)一個AVInputFormat 結(jié)構(gòu)秉溉。

c)        解碼(h264,mpeg2,aac,mp3)

每個AVStream存儲一個視頻/音頻流的相關(guān)數(shù)據(jù);每個AVStream對應(yīng)一個AVCodecContext,存儲該視頻/音頻流使用解碼方式的相關(guān)數(shù)據(jù)召嘶;每個AVCodecContext中對應(yīng)一個AVCodec父晶,包含該視頻/音頻對應(yīng)的解碼器。每種解碼器都對應(yīng)一個AVCodec結(jié)構(gòu)弄跌。

d) 存數(shù)據(jù)

視頻的話甲喝,每個結(jié)構(gòu)一般是存一幀;音頻可能有好幾幀

解碼前數(shù)據(jù):AVPacket

解碼后數(shù)據(jù):AVFrame


引用自: https://blog.csdn.net/leixiaohua1020/article/details/11693997

他們之間的關(guān)系如下:


圖片來自:FFMPEG中最關(guān)鍵的結(jié)構(gòu)體之間的關(guān)系

3.2铛只。AVFormatContext
該結(jié)構(gòu)體定義在libavformat/Avformat.h中埠胖,它是一個貫穿始終的數(shù)據(jù)結(jié)構(gòu),很多函數(shù)都要用到它作為參數(shù)淳玩。幾個主要變量的作用如下:

struct AVInputFormat *iformat:輸入數(shù)據(jù)的封裝格式
struct AVOutputFormat *oformat:輸出數(shù)據(jù)的封裝格式

AVIOContext *pb:輸入數(shù)據(jù)的緩存

unsigned int nb_streams:視音頻流的個數(shù)

AVStream **streams:視音頻流

char filename[1024]:文件名

int64_t duration:時長(單位:微秒us押袍,轉(zhuǎn)換為秒需要除以1000000)

int bit_rate:比特率(單位bps,轉(zhuǎn)換為kbps需要除以1000)

AVDictionary *metadata:元數(shù)據(jù)

3.3 AVInputFormat
該結(jié)構(gòu)體定義也在libavformat/Avformat.h中凯肋,是解封裝器對象主要的變量的作用如下

const char *name: 格式的名稱
const char *mime_type: mime類型如 video/avc video/hevc audio/aac等

以及一系列函數(shù)指針
int (*read_probe)(const AVProbeData *);
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
int (*read_close)(struct AVFormatContext *);
int (*read_seek)(struct AVFormatContext *,
                     int stream_index, int64_t timestamp, int flags);
int (*read_play)(struct AVFormatContext *);

int (*read_pause)(struct AVFormatContext *);
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);

3.4 AVStream
每個AVStream存儲一個視頻/音頻流的相關(guān)數(shù)據(jù)谊惭;是解封裝器分離出來的流對象,即解封裝的產(chǎn)物侮东,它保存在AVFormatcontext中圈盔。

該結(jié)構(gòu)體定義也在libavformat/Avformat.h中, 主要變量如下:

int index;  流索引
int id; 流id
void *priv_data; 流數(shù)據(jù)
AVRational time_base; 時間基,通過該值可以把PTS悄雅,DTS轉(zhuǎn)化為真正的時間驱敲;PTS*time_base=真正的時間
int64_t duration:流長度
AVRational sample_aspect_ratio; 采樣率
AVRational avg_frame_rate:幀率
AVCodecContext *codec:指向該視頻/音頻流的AVCodecContext(它們是一一對應(yīng)的關(guān)系)

AVStream是解封裝環(huán)節(jié)的輸出宽闲,同時也是解碼環(huán)節(jié)的輸入众眨,每個AVStream對應(yīng)一個AVCodecContext,存儲該視頻/音頻流使用解碼方式的相關(guān)數(shù)據(jù)容诬;每個AVCodecContext中對應(yīng)一個AVCodec娩梨,包含該視頻/音頻對應(yīng)的解碼器。每種解碼器都對應(yīng)一個AVCodec結(jié)構(gòu)览徒。
解碼部分的數(shù)據(jù)結(jié)構(gòu)分析我們下一篇再來分析學(xué)習(xí)狈定。

3.5 AVPacket
存儲壓縮編碼數(shù)據(jù)相關(guān)信息的結(jié)構(gòu)體,保存了解封裝之后习蓬,解碼之前的數(shù)據(jù)以及PTS纽什、DTS、Duration以及streamId等信息
該結(jié)構(gòu)體定義位于libavcodec/Packet.h中躲叼,主要變量如下:

  uint8_t *data; 對于H.264來說芦缰。1個AVPacket的data通常對應(yīng)一個NAL。
int   size:data的大小
int64_t pts:顯示時間戳
int64_t dts:解碼時間戳
AVPacketSideData *side_data;附加信息

三枫慷、資料

《Android音視頻開發(fā)》-第八章
Xcode調(diào)試ffmpeg源碼(十五)
FFMPEG中最關(guān)鍵的結(jié)構(gòu)體之間的關(guān)系
FFMPEG結(jié)構(gòu)體分析:AVFormatContext
FFMPEG結(jié)構(gòu)體分析:AVStream
FFMPEG結(jié)構(gòu)體分析:AVPacket

四让蕾、收獲

通過本篇的學(xué)習(xí)實踐浪规,我們學(xué)習(xí)到了

  1. 如何在Xcode下斷點調(diào)試ffmpeg并進行ffplay解封裝流程的分析
  2. 了解常用結(jié)構(gòu)體之間的關(guān)系:解協(xié)議、解封裝涕俗、解碼對應(yīng)的結(jié)構(gòu)體以及之間的關(guān)系
  3. 了解解封裝相關(guān)的幾個關(guān)鍵結(jié)構(gòu)的的主要變量和函數(shù)罗丰。AVFormatContext、AVInputFormat再姑、AVStream

感謝你的閱讀
下一篇我們分析ffmpeg解碼部分的常用結(jié)構(gòu)體萌抵,歡迎關(guān)注公眾號“音視頻開發(fā)之旅”,一起學(xué)習(xí)成長元镀。
歡迎交流

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绍填,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子栖疑,更是在濱河造成了極大的恐慌讨永,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遇革,死亡現(xiàn)場離奇詭異卿闹,居然都是意外死亡,警方通過查閱死者的電腦和手機萝快,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門锻霎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揪漩,你說我怎么就攤上這事旋恼。” “怎么了奄容?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵冰更,是天一觀的道長。 經(jīng)常有香客問我昂勒,道長蜀细,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任叁怪,我火速辦了婚禮审葬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奕谭。我一直安慰自己,他們只是感情好痴荐,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布血柳。 她就那樣靜靜地躺著,像睡著了一般生兆。 火紅的嫁衣襯著肌膚如雪难捌。 梳的紋絲不亂的頭發(fā)上膝宁,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音根吁,去河邊找鬼员淫。 笑死,一個胖子當著我的面吹牛击敌,可吹牛的內(nèi)容都是我干的介返。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼沃斤,長吁一口氣:“原來是場噩夢啊……” “哼圣蝎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衡瓶,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤徘公,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哮针,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體关面,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年十厢,在試婚紗的時候發(fā)現(xiàn)自己被綠了等太。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡寿烟,死狀恐怖澈驼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筛武,我是刑警寧澤缝其,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站徘六,受9級特大地震影響内边,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜待锈,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一漠其、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竿音,春花似錦和屎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宽气,卻和暖如春随常,著一層夾襖步出監(jiān)牢的瞬間潜沦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工绪氛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唆鸡,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓枣察,卻偏偏與公主長得像争占,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子询件,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

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