1. 程式人生 > >ffmpeg原始碼簡析(一)結構總覽

ffmpeg原始碼簡析(一)結構總覽

未畢業通過校招進入了某做機的公司從事camera方面的工作。比較悲劇的是做了將近一年的Camera之後,正要研究Camera上下層打通任督二脈的時候,公司架構調整加上OS版本大變動,被調到了多媒體組(不過也好,我對編碼解碼這塊也是嚮往已久)。以前大學的時候用vitamio寫過一個播放器專案,後來ijkplayer 出來之後也實踐過一兩個小專案,它們都是基於ffmpeg的框架。
懸窗播放視訊,讓你聊天看視訊兩不誤(上) :http://blog.csdn.net/king1425/article/details/59527229
懸窗播放視訊,讓你聊天看視訊兩不誤(下) :http://blog.csdn.net/king1425/article/details/59538663

學習ffmpeg也有段時間了,ffmpeg這個框架實在是大,原始碼看著註釋著忘著,很是凌亂。好記性不如爛筆頭,古人誠不欺我啊。以後就整理下學習過的東西,分享出來,方便了自己也幫助了他人,真是快樂。
感謝雷神,中國音視訊技術領域無私的拓荒者傳承者,您的博文治學態度令我敬佩,文章使我受益良多
本系列前辦部分應該是對雷神和其他資料的總結。
如果對ffmpeg不瞭解的客官進這裡
ffmpeg必知道的知識點http://blog.csdn.net/king1425/article/details/70348374

ffmpeg API變更

雷神記錄獲取媒體資訊使用的函式是av_find_stream_info()。但是較新的版本中,av_find_stream_info()函式已經無法使用了,取而代之的是avformat_find_stream_info()。再比如,早一些的程式中,開啟解碼器可以使用avcodec_open(),但是新版本的程式中必須使用avcodec_open2()。而早期版本的FFmpeg中開啟媒體的函式av_open_input_file()也已經被avformat_open_input()所取代。可以看出一些與libavformat相關的av_***()都變更為了avformat_***(),這一趨勢也說明FFmpeg的API正在慢慢朝著“名稱更加規範”的方向發展。
這裡也更了一篇

ffmpeg API變更 2009-03-01—— 2017-05-09變更
大家務必對著新的API學習

ffmpeg原始碼結構圖

編碼
引自雷神,圖片較大建議儲存為本地檔案,然後再檢視

函式背景色
函式在圖中以方框的形式表現出來。不同的背景色標誌了該函式不同的作用:

粉紅色背景函式:FFmpeg的API函式。
白色背景的函式:FFmpeg的內部函式。
黃色背景的函式:URLProtocol結構體中的函式,包含了讀寫各種協議的功能。
綠色背景的函式:AVOutputFormat結構體中的函式,包含了讀寫各種封裝格式的功能。
藍色背景的函式:AVCodec結構體中的函式,包含了編解碼的功能。

區域
整個關係圖可以分為以下幾個區域:

左邊區域——架構函式區域:這些函式並不針對某一特定的視訊格式。
右上方黃色區域——協議處理函式區域:不同的協議(RTP,RTMP,FILE)會呼叫不同的協議處理函式。
右邊中間綠色區域——封裝格式處理函式區域:不同的封裝格式(MKV,FLV,MPEG2TS,AVI)會呼叫不同的封裝格式處理函式。
右邊下方藍色區域——編解碼函式區域:不同的編碼標準(HEVC,H.264,MPEG2)會呼叫不同的編解碼函式。

箭頭線
為了把呼叫關係表示的更明顯,圖中的箭頭線也使用了不同的顏色:

紅色的箭頭線:標誌了編碼的流程。
其他顏色的箭頭線:標誌了函式之間的呼叫關係。其中:

    呼叫URLProtocol結構體中的函式用黃色箭頭線標識;

    呼叫AVOutputFormat結構體中的函式用綠色箭頭線標識;

    呼叫AVCodec結構體中的函式用藍色箭頭線標識。

函式所在的檔案
每個函式標識了它所在的檔案路徑。

左邊區域(架構函式) 後續詳細分析~~~

右上區域(URLProtocol協議處理函式)
URLProtocol結構體包含如下協議處理函式指標:

url_open():開啟
url_read():讀取
url_write():寫入
url_seek():調整進度
url_close():關閉

【例子】不同的協議對應著上述介面有不同的實現函式,舉幾個例子:
File協議(即檔案)對應的URLProtocol結構體ff_file_protocol:
url_open() -> file_open() -> open()
url_read() -> file_read() -> read()
url_write() -> file_write() -> write()
url_seek() -> file_seek() -> lseek()

url_close() -> file_close() -> close()

RTMP協議(libRTMP)對應的URLProtocol結構體ff_librtmp_protocol:
url_open() -> rtmp_open() -> RTMP_Init(), RTMP_SetupURL(), RTMP_Connect(), RTMP_ConnectStream()
url_read() -> rtmp_read() -> RTMP_Read()
url_write() -> rtmp_write() -> RTMP_Write()
url_seek() -> rtmp_read_seek() -> RTMP_SendSeek()

url_close() -> rtmp_close() -> RTMP_Close()
UDP協議對應的URLProtocol結構體ff_udp_protocol:
url_open() -> udp_open()
url_read() -> udp_read()
url_write() -> udp_write()
url_seek() -> udp_close()
url_close() -> udp_close()

右中區域(AVOutputFormat封裝格式處理函式)
AVOutputFormat包含如下封裝格式處理函式指標:

write_header():寫檔案頭
write_packet():寫一幀資料
write_trailer():寫檔案尾

【例子】不同的封裝格式對應著上述介面有不同的實現函式,舉幾個例子:
FLV封裝格式對應的AVOutputFormat結構體ff_flv_muxer:
write_header() -> flv_write_header()
write_packet() –> flv_write_packet()

write_trailer() -> flv_write_trailer()
MKV封裝格式對應的AVOutputFormat結構體ff_matroska_muxer:
write_header() -> mkv_write_header()
write_packet() –> mkv_write_flush_packet()

write_trailer() -> mkv_write_trailer()
MPEG2TS封裝格式對應的AVOutputFormat結構體ff_mpegts_muxer:
write_header() -> mpegts_write_header()
write_packet() –> mpegts_write_packet()

write_trailer() -> mpegts_write_end()
AVI封裝格式對應的AVOutputFormat結構體ff_avi_muxer:
write_header() -> avi_write_header()
write_packet() –> avi_write_packet()
write_trailer() -> avi_write_trailer()

右下區域(AVCodec編解碼函式)
AVCodec包含如下編解碼函式指標:

init():初始化
encode2():編碼一幀資料
close():關閉

【例子】不同的編解碼器對應著上述介面有不同的實現函式,舉幾個例子:
HEVC編碼器對應的AVCodec結構體ff_libx265_encoder:
init() -> libx265_encode_init() -> x265_param_alloc(), x265_param_default_preset(), x265_encoder_open()
encode2() -> libx265_encode_frame() -> x265_encoder_encode()

close() -> libx265_encode_close() -> x265_param_free(), x265_encoder_close()
H.264編碼器對應的AVCodec結構體ff_libx264_encoder:
init() -> X264_init() -> x264_param_default(), x264_encoder_open(), x264_encoder_headers()
encode2() -> X264_frame() -> x264_encoder_encode()

close() -> X264_close() -> x264_encoder_close()
VP8編碼器(libVPX)對應的AVCodec結構體ff_libvpx_vp8_encoder:
init() -> vpx_init() -> vpx_codec_enc_config_default()
encode2() -> vp8_encode() -> vpx_codec_enc_init(), vpx_codec_encode()

close() -> vp8_free() -> vpx_codec_destroy()
MPEG2編碼器對應的AVCodec結構體ff_mpeg2video_encoder:
init() -> encode_init()
encode2() -> ff_mpv_encode_picture()
close() -> ff_mpv_encode_end()

解碼

右上區域(URLProtocol協議處理函式)
URLProtocol結構體包含如下協議處理函式指標:

url_open():開啟
url_read():讀取
url_write():寫入
url_seek():調整進度
url_close():關閉

【例子】不同的協議對應著上述介面有不同的實現函式,舉幾個例子:
File協議(即檔案)對應的URLProtocol結構體ff_file_protocol:

url_open() -> file_open() -> open()
url_read() -> file_read() -> read()
url_write() -> file_write() -> write()
url_seek() -> file_seek() -> lseek()
url_close() -> file_close() -> close()

RTMP協議(libRTMP)對應的URLProtocol結構體ff_librtmp_protocol:

url_open() -> rtmp_open() -> RTMP_Init(), RTMP_SetupURL(), RTMP_Connect(), RTMP_ConnectStream()
url_read() -> rtmp_read() -> RTMP_Read()
url_write() -> rtmp_write() -> RTMP_Write()
url_seek() -> rtmp_read_seek() -> RTMP_SendSeek()
url_close() -> rtmp_close() -> RTMP_Close()

UDP協議對應的URLProtocol結構體ff_udp_protocol:

url_open() -> udp_open()
url_read() -> udp_read()
url_write() -> udp_write()
url_seek() -> udp_close()

url_close() -> udp_close()

右中區域(AVInputFormat封裝格式處理函式)
AVInputFormat包含如下封裝格式處理函式指標:

read_probe():檢查格式
read_header():讀取檔案頭
read_packet():讀取一幀資料
read_seek():調整進度
read_close():關閉

【例子】不同的封裝格式對應著上述介面有不同的實現函式,舉幾個例子:
FLV封裝格式對應的AVInputFormat結構體ff_flv_demuxer:

read_probe() -> flv_probe() –> probe()
read_header() -> flv_read_header() -> create_stream() -> avformat_new_stream()
read_packet() -> flv_read_packet()
read_seek() -> flv_read_seek()
read_close() -> flv_read_close()

MKV封裝格式對應的AVInputFormat結構體ff_matroska_demuxer:

read_probe() -> matroska_probe()
read_header() -> matroska_read_header()
read_packet() -> matroska_read_packet()
read_seek() -> matroska_read_seek()
read_close() -> matroska_read_close()

MPEG2TS封裝格式對應的AVInputFormat結構體ff_mpegts_demuxer:

read_probe() -> mpegts_probe()
read_header() -> mpegts_read_header()
read_packet() -> mpegts_read_packet() 
read_close() -> mpegts_read_close()

AVI封裝格式對應的AVInputFormat結構體ff_avi_demuxer:

read_probe() -> avi_probe()
read_header() -> avi_read_header()
read_packet() -> avi_read_packet()
read_seek() -> avi_read_seek()
read_close() -> avi_read_close()

右下區域(AVCodec編解碼函式)
AVCodec包含如下編解碼函式指標:

init():初始化
decode():解碼一幀資料
close():關閉

【例子】不同的編解碼器對應著上述介面有不同的實現函式,舉幾個例子:
HEVC解碼對應的AVCodec結構體ff_hevc_decoder:

init() -> hevc_decode_init()
decode() -> hevc_decode_frame() -> decode_nal_units()
close() -> hevc_decode_free()

H.264解碼對應的AVCodec結構體ff_h264_decoder:

init() -> ff_h264_decode_init()
decode() -> h264_decode_frame() -> decode_nal_units()
close() -> h264_decode_end()

VP8解碼(libVPX)對應的AVCodec結構體ff_libvpx_vp8_decoder:

init() -> vpx_init() -> vpx_codec_dec_init()
decode() -> vp8_decode() -> vpx_codec_decode(), vpx_codec_get_frame()
close() -> vp8_free() -> vpx_codec_destroy()

MPEG2解碼對應的AVCodec結構體ff_mpeg2video_decoder:

init() -> mpeg_decode_init()
decode() -> mpeg_decode_frame()

close() -> mpeg_decode_end()