[原]零基礎學習視頻解碼之FFMpeg中比較重要的函數以及數據結構


在正式開始解碼練習前先了解下關於FFmpeg中比較重要的函數以及數據結構。

1. 數據結構: 

(1) AVFormatContext 

  AVFormatContext是一個貫穿始終的數據結構,很多函數都要用到它作為參數。FFmpeg代碼中對這個數據結構的注釋是:format I/O context 此結構包含了一個視頻流的格式內容。其中存有了AVInputFormator AVOutputFormat同一時間AVFormatContext內只能存在其中一個),和AVStreamAVPacket這幾個重要的數據結構以及一些其他的相關信息,比如title,author,copyright等。還有一些可能在編解碼中會用到的信息,諸如:duration, file_size, bit_rate等。

  初始化: 由於AVFormatConext結構包含許多信息因此初始化過程是分步完成,而且有些變量如果沒有值可用,也可不初始化。但是由於一般聲明都是用指針因此一個分配內存過程不可少:

  

AVFormatContext *pFormatCtx;

pFormatCtx = avformat_alloc_context();

 

 

(2) AVOutputFormat 

  編解碼器將要使用哪個codec指示。 

AVOutputFormat *fmt; 


fmt = guess_format(NULL, filename, NULL);

 

 

  根據filename來判斷文件格式,同時也初始化了用什么編碼器。當然,如果是用AVInputFormat *fmt的化,就是fix用什么解碼器。(指定輸出序列->fix編碼器,指定輸入序列->fix解碼器) 

 

(3) AVInputFormat 

  從AVFormatContext中獲取AVInputFormat

AVInputFormat *inputFormat;
inputFormat = pFormatCtx->iformat;

(4) AVCodecContext 

  此結構在Ffmpeg SDK中的注釋是:main external api structure其重要性可見一斑。而且在avcodec它的定義處,對其每個成員變量,都給出了十分詳細的介紹。應該說AVCodecContext的初始化是Codec使用中最重要的一環, 而且AVCodecContextAVStream的一個成員結構。

 

(5) AVCodec 

  結構AVCodec中成員變量和成員函數比較少,但是很重要。他包含了CodecID,也就是用哪個Codec、  像素格式信息。還有前面提到過的5個函數(initencodeclosedecoderflush)。AVCodec的初始化後的使用都是依附於AVCodecContex,前者是后者的成員。AVCodecContext初始化後 AVCodec也就能很好的初始化了。

 

 

(6) AVFrame 

  AVFrame是作為一個描述原始圖像(也就是YUV或是RGB…還有其他的嗎?)的結構,他的頭兩個成員數據,uint8_t 

*data[4]int linesize[4],第一個存放的是YCbCryuv格式),linesize是啥?由這兩個數據還能提取處另外一個數據結構:AVPicture。

  此外,AVFrame還含有其他一些成員數據,比如。是否key_frame、已編碼圖像書coded_picture_number、是否作為參考幀reference、宏塊類型 *mb_type等等。 

 

  AVFrame的初始化並沒有他結構上看上去的那么簡單。由於AVFrame還有一個承載圖像數據的任務(data[4])因此,對他分配內存應該要小心完成。

 

(7) AVPacket 

  AVPacket的存在是作為寫入文件的基本單元而存在的。我們可能會認為直接把編碼后的比特流寫入文件不就可以了,為什么還要麻煩設置一個AVPacket結構。在我看來這樣的編碼設置是十分有必要的,特別是在做視頻實時傳輸,同步、邊界問題可以通過AVPacket來解決。AVPacket的成員數據有兩個時間戳、數據data(通常是編碼后數據)、大小size等等(參見avformat.h 48行)。講AVPacket的用法就不得不提到編解碼函數,因為AVPacket的好些信息只有在編解碼后才能的知。

(8) AVPicture 

  AVPicture的存在有以下原因,AVPicturePicture的概念從Frame中提取出來,就只由Picture(圖片)本身的信息,亮度、色度和行大小。而Frame還有如是否是key frame之類的信息。這樣的類似分級是整個概念更加清晰。 AVPacket作為將編碼后數據寫入文件的基本數據單元,他的單元大小、數據都是由AVPacket來的

 

(9) AVStream

  AVStream作為繼AVFormatContext後第二個貫穿始終的結構是有其理由的。他的成員數據中有AVCodecContext這基本的上是對所使用的Video Codec的參數進行設定的(包括bit rate、分辨率等重要信息)。同時作為“Stream”,它包含了

  這個概念中的一些數據,比如:幀率(r_frame_rate)、基本時間計量單位(time_base)、(需要編解碼的)首幀位置(start_time)、持續時間(duration)、幀數(nb_frames)以及一些ip信息。當然后面的這些信息中有些不是必須要初始化的,但是AVCodecContex是一定要初始化的,而且就是作為初始化AVStream最重要的一個部分。

 

  以上是FFMpeg中比較重要的數據結構。下面的這個生成關系理一下思路:(->表示 派生出) 

  AVFormatContext->AVStream->AVCodecContext->AVCodec 

  | 

  AVOutputFormat or AVInputFormat 

  AVFrame->AVPicture….>AVPacket 

2.FFMpeg 中的函數:

  FFMpeg SDK提供了許多初始化函數和編碼函數。我們要做的就是對主要數據結構正確的初始化,以及正確使用相應的編解碼函數以及讀寫(I/O)操作函數。作為一個整體化的代碼SDKFFMpeg有一些他自己的標准化使用過程。比如函數av_register_all(); 就是一個最開始就該調用的注冊函數,他初始化了libavcodec注冊了所有的的codec和視頻文件格式(format)。

  (1). av_register_all (); 

     usage: initialize ibavcoded, and register all codecs and formats 

     每個使用FFMpeg SDK的工程都必須調用的函數。進行codecformat的注冊,然后才能使用。

      (2). AVFormatContext *avformat_alloc_context(void);

    usage: allocate the output media context.實際是初始化AVFormatContext的成員數據AVClass

  (3).void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output); 

    usage: 這一步會用有效的信息把 AVFormatContext 的流域(streams field)填滿。作為一個可調試的診斷,我們會將這些信息全盤輸出到標准錯誤輸出中,不過你在一個應用程序的產品中並不用這么做: 

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

    usage:打開一個視頻文件

  (5).int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

    usage:獲取視頻文件的流信息

  (6).AVCodec *avcodec_find_decoder(enum AVCodecID id);

    usage:獲取視頻編碼格式

  (7).int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

    usage:用一個編碼格式打開一個編碼文件

  (8).int av_read_frame(AVFormatContext *s, AVPacket *pkt);

    usage:從frame中讀取packet

  (9).int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, const AVPacket *avpkt);

    usage:解碼聲音

 

所以解碼流程如下:

  所以解碼流程為:注冊所有格式->初始化AVFormatContext->打開一個視頻文件->獲取視頻文件的流信息->獲取初始的視頻流->獲得視頻流編碼內容->獲得音頻流編碼內容->獲取視頻編碼格式->獲取音頻編碼格式->用一個編碼格式打開一個編碼文件->從frame中讀取packet->解碼視頻->解碼音頻->釋放packet->關閉解碼器->關閉AVFormatContext

 

  解碼流程函數:av_register_all()->avformat_alloc_context()->avformat_open_input()->avformat_find_stream_info()->avcodec_find_decoder()->avcodec_open2()->av_new_packet()->av_read_frame()->avcodec_decode_video2()-->avcodec_decode_audio4()->av_free_packet()->avcodec_close()->avformat_close_input()

    

 

 


免責聲明!

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



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