FFmpeg解碼詳細流程


FFmpeg在解碼一個視頻的時候的函數調用流程。為了保證結構清晰,其中僅列出了最關鍵的函數,剔除了其它不是特別重要的函數。





下面解釋一下圖中關鍵標記的含義。



函數背景色

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

  • 粉紅色背景函數:FFmpeg的API函數。
  • 白色背景的函數:FFmpeg的內部函數。
  • 黃色背景的函數:URLProtocol結構體中的函數,包含處理協議(Protocol)的功能。
  • 綠色背景的函數:AVInputFormat結構體中的函數,包含處理封裝格式(Format)的功能。
  • 藍色背景的函數:AVCodec結構體中的函數,包含了編解碼器(Codec)的功能。
PS:URLProtocol,AVInputFormat,AVCodec在FFmpeg開始運行並且注冊完組件之后,都會分別被連接成一個個的鏈表。因此實際上是有很多的URLProtocol,AVInputFormat,AVCodec的。圖中畫出了解碼一個輸入協議是“文件”(其實就是打開一個文件。“文件”也被當做是一種廣義的協議),封裝格式為FLV,視頻編碼格式是H.264的數據的函數調用關系。



區域

整個架構圖可以分為以下幾個區域:

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



箭頭線

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

黑色箭頭線:標志了函數之間的調用關系。

紅色的箭頭線:標志了解碼的流程。

其他顏色的箭頭線:標志了函數之間的調用關系。其中:

調用URLProtocol結構體中的函數用黃色箭頭線標識;

調用AVInputFormat結構體中的函數用綠色箭頭線標識;

調用AVCodec結構體中的函數用藍色箭頭線標識。



函數所在的文件

每個函數旁邊標識了它所在的文件的路徑。


此外,還有一點需要注意的是,一些API函數內部也調用了另一些API函數。也就是說,API函數並不一定全部都調用FFmpeg的內部函數,他也有可能調用其他的API函數。例如從圖中可以看出來,avformat_close_input()調用了avformat_free_context()和avio_close()。這些在內部代碼中被調用的API函數也標記為粉紅色。



函數調用關系

下面簡單列出幾個區域中函數之間的調用關系(函數之間的調用關系使用縮進的方式表現出來)。



左邊區域(FFmpeg架構函數)



1.  av_register_all()

1)  avcodec_register_all()

(a) REGISTER_HWACCEL()

(b) REGISTER_ENCODER()

(c) REGISTER_DECODER()

(d) REGISTER_PARSER()

(e) REGISTER_BSF()

2)  REGISTER_MUXER()

3)  REGISTER_DEMUXER()

4)  REGISTER_PROTOCOL()

2.  avformat_alloc_context()

1) av_malloc(sizeof(AVFormatContext))

2) avformat_get_context_defaults()

(a) av_opt_set_defaults()

3.  avformat_open_input()

1) init_input()

(a) avio_open2()

a) ffurl_open()

i. ffurl_alloc()

l  url_find_protocol()

l  url_alloc_for_protocol()

ii. ffurl_connect()

URLProtocol->url_open()

b) ffio_fdopen()

i. av_malloc(buffer_size)

ii. avio_alloc_context()

l  av_mallocz(sizeof(AVIOContext))

l  ffio_init_context()

(b) av_probe_input_buffer2()

a) avio_read()

i.  AVInputFormat->read_packet()

b) av_probe_input_format2()

c) av_probe_input_format3()

i. av_iformat_next()

ii. av_match_name()

iii. av_match_ext()

iv. AVInputFormat->read_probe()

2) AVInputFormat->read_header()





4. avformat_find_stream_info()

1) find_decoder()

(a) avcodec_find_decoder()

2) avcodec_open2()

3) read_frame_internal()

4) try_decode_frame()

(a) avcodec_decode_video2()

5) avcodec_close()

6) estimate_timings()

(a)  estimate_timings_from_pts()

(b)  estimate_timings_from_bit_rate()

(c)  update_stream_timings()

5. avcodec_find_decoder()

1) find_encdec()

6. avcodec_open2()

1) AVCodec->init()

7. av_read_frame()

1) read_from_packet_buffer()

2) read_frame_internal()

(a) ff_read_packet()

a) AVInputFormat->read_packet()

(b) parse_packet()

a) av_parser_parse2()

8. avcodec_decode_video2()

1) av_packet_split_side_data()

2) AVCodec->decode()

3) av_frame_set_pkt_pos()

4) av_frame_set_best_effort_timestamp()

9. avcodec_close()

1) AVCodec->close()

10. avformat_close_input()

1) AVInputFormat->read_close()

2) avformat_free_context()

(a) ff_free_stream()

3) avio_close()

(a) avio_flush()

a) flush_buffer()

(b) ffurl_close()

a) ffurl_closep()

URLProtocol->url_close()



右上區域(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()


參考:







免責聲明!

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



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