ffmpga結構體和經常使用函數(總結)

  模塊:
算法

    libavcodec    - 編碼解碼器
        libavdevice   - 輸入輸出設備的支持
        libavfilter   - 視音頻濾鏡支持
        libavformat   - 視音頻等格式的解析
        libavutil     - 工具庫
        libpostproc   - 後期效果處理
        libswscale    - 圖像顏色、尺寸轉換
數組

1. ffmpga代碼簡析緩存

 

1.2 源碼——通用部分數據結構

(1). av_register_all (),     avcodec_register_all ()tcp

  avcodec_register_all() : 註冊 hwaccel,encoder,decoder,parser,bitstream
    av_register_all() : 註冊 muxer,demuxer,protocol,在全部基於ffmpeg的應用程序中幾乎第一個被調用的。只有調用了該函數,才能使用複用器,編碼器等
    avfilter_register_all() : 註冊 濾鏡filter
ide

(2).內存分配:av_malloc(),av_realloc(),av_mallocz(),av_calloc(),av_free(),av_freep()函數

  內存操做常見函數位於  libavutil\mem.中:工具

av_malloc()——簡單封裝了系統的malloc(),並作錯誤檢查工做;post

av_realloc()——簡單封裝了系統的realloc(),用於對申請的內存大小進行調整;字體

av_mallocz()——av_mallocz()中調用了av_malloc()以後,又調用memset()將分配的內存設置爲0

av_calloc()——簡單封裝了av_mallocz();

av_freep()——釋放申請的內存;

av_freep()——簡單封裝了av_free(),而且在釋放內存以後將目標指針設置爲null。

 

(3).ffmpeg結構體

a) 解協議(http,rtsp,rtmp,mms)

AVIOContext,URLProtocol,URLContext 主要存儲視音頻使用的協議的類型以及狀態。URLProtocol存儲輸入視音頻使用的封裝格式。每種協議都對應一個URLProtocol結構。(注 意:FFMPEG中文件也被當作一種協議「file」)

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

AVFormatContext主要存儲視音頻封裝格式中包含的信息;AVInputFormat存儲輸入視音頻使用的封裝格式。每種視音頻封裝格式都對應一個AVInputFormat 結構。

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

每一個AVStream存儲一個視頻/音頻流的相關數據;每一個AVStream對應一個AVCodecContext,存儲該視頻/音頻流使用解碼方式的相關數據;每一個AVCodecContext中對應一個AVCodec,包含該視頻/音頻對應的解碼器。每種解碼器都對應一個AVCodec結構。

d) 存數據

視頻的話,每一個結構通常是存一幀;音頻可能有好幾幀

解碼前數據:AVPacket

解碼後數據:AVFrame

 

AVFormatContext:統領全局的基本結構體。主要用於處理封裝格式(FLV/MKV/RMVB等)

AVIOContext:輸入輸出對應的結構體,用於輸入輸出(讀寫文件,RTMP協議等)。

AVStream,AVCodecContext:視音頻流對應的結構體,用於視音頻編解碼。

AVFrame:存儲非壓縮的數據(視頻對應RGB/YUV像素數據,音頻對應PCM採樣數據)

AVPacket:存儲壓縮數據(視頻對應H.264等碼流數據,音頻對應AAC/MP3等碼流數據)

 

<1>. AVFormatContext是一個貫穿始終的數據結構,不少函數都要用到它做爲參數。它是FFMPEG解封裝(flv,mp4,rmvb,avi)功能的結構體。下面看幾個主要變量的做用(在這裏考慮解碼的狀況):

struct AVInputFormat *iformat:輸入數據的封裝格式

AVIOContext *pb:輸入數據的緩存

unsigned int nb_streams:視音頻流的個數

AVStream **streams:視音頻流

char filename[1024]:文件名

int64_t duration:時長(單位:微秒ms,轉換爲秒須要除以1000000)

int bit_rate:比特率(單位bps,轉換爲kbps須要除以1000)

AVDictionary *metadata:元數據

 <2>. AVFrame結構體通常用於存儲原始數據(即非壓縮數據,例如對視頻來講是YUV,RGB,對音頻來講是PCM),此外還包含了一些相關的信息。好比 說,解碼的時候存儲了宏塊類型表,QP表,運動矢量表等數據。編碼的時候也存儲了相關的數據。所以在使用FFMPEG進行碼流分析的時候,AVFrame 是一個很重要的結構體。下面看幾個主要變量的做用(在這裏考慮解碼的狀況):

  uint8_t *data[AV_NUM_DATA_POINTERS]:解碼後原始數據(對視頻來講是YUV,RGB,對音頻來講是PCM)

  int linesize[AV_NUM_DATA_POINTERS]:data中「一行」數據的大小。注意:未必等於圖像的寬,通常大於圖像的寬。

  int width, height:視頻幀寬和高(1920x1080,1280x720...)

  int nb_samples:音頻的一個AVFrame中可能包含多個音頻幀,在此標記包含了幾個

  int format:解碼後原始數據類型(YUV420,YUV422,RGB24...)

  int key_frame:是不是關鍵幀

  enum AVPictureType pict_type:幀類型(I,B,P...)

  AVRational sample_aspect_ratio:寬高比(16:9,4:3...)

  int64_t pts:顯示時間戳

  int coded_picture_number:編碼幀序號

  int display_picture_number:顯示幀序號

  int8_t *qscale_table:QP表

  uint8_t *mbskip_table:跳過宏塊表

  int16_t (*motion_val[2])[2]:運動矢量表

  uint32_t *mb_type:宏塊類型表

  short *dct_coeff:DCT係數,這個沒有提取過

  int8_t *ref_index[2]:運動估計參考幀列表(貌似H.264這種比較新的標準纔會涉及到多參考幀)

  int interlaced_frame:是不是隔行掃描

  uint8_t motion_subsample_log2:一個宏塊中的運動矢量採樣個數,取log的

<3>.AVCodecContext,主要的外部API結構體,這個結構體主要用在編解碼過程當中,並且,編碼過程當中用到本結構體的參數比解碼用到的參數多

enum AVMediaType codec_type:編解碼器的類型(視頻,音頻...)

struct AVCodec  *codec:採用的解碼器AVCodec(H.264,MPEG2...)

int bit_rate:平均比特率

uint8_t *extradata; int extradata_size:針對特定編碼器包含的附加信息(例如對於H.264解碼器來講,存儲SPS,PPS等)

AVRational time_base:根據該參數,能夠把PTS轉化爲實際的時間(單位爲秒s)

int width, height:若是是視頻的話,表明寬和高

int refs:運動估計參考幀的個數(H.264的話會有多幀,MPEG2這類的通常就沒有了)

int sample_rate:採樣率(音頻)

int channels:聲道數(音頻)

enum AVSampleFormat sample_fmt:採樣格式

int profile:型(H.264裏面就有,其餘編碼標準應該也有)

int level:級(和profile差不太多)

<4>.AVIOContext,管理輸入輸出數據的結構體

unsigned char *buffer:緩存開始位置

int buffer_size:緩存大小(默認32768)

unsigned char *buf_ptr:當前指針讀取到的位置

unsigned char *buf_end:緩存結束的位置

void *opaque:URLContext結構體

在解碼的狀況下,buffer用於存儲ffmpeg讀入的數據。例如打開一個視頻文件的時候,先把數據從硬盤讀入buffer,而後在送給解碼器用於解碼。

其中opaque指向了URLContext。注意,這個結構體並不在FFMPEG提供的頭文件中,而是在FFMPEG的源代碼中。

<5>.AVCodec是存儲編解碼器信息的結構體

const char *name:編解碼器的名字,比較短

const char *long_name:編解碼器的名字,全稱,比較長

enum AVMediaType type:指明瞭類型,是視頻,音頻,仍是字幕

enum AVCodecID id:ID,不重複

const AVRational *supported_framerates:支持的幀率(僅視頻)

const enum AVPixelFormat *pix_fmts:支持的像素格式(僅視頻)

const int *supported_samplerates:支持的採樣率(僅音頻)

const enum AVSampleFormat *sample_fmts:支持的採樣格式(僅音頻)

const uint64_t *channel_layouts:支持的聲道數(僅音頻)

int priv_data_size:私有數據的大小

<6>.AVStream是存儲每個視頻/音頻流信息的結構體

  int index:標識該視頻/音頻流

  AVCodecContext *codec:指向該視頻/音頻流的AVCodecContext(它們是一一對應的關係)

  AVRational time_base:時基。經過該值能夠把PTS,DTS轉化爲真正的時間。FFMPEG其餘結構體中也有這個字段,可是根據個人經驗,  只有AVStream中的time_base是可用的。PTS*time_base=真正的時間

  int64_t duration:該視頻/音頻流長度

  AVDictionary *metadata:元數據信息

  AVRational avg_frame_rate:幀率(注:對視頻來講,這個挺重要的)

  AVPacket attached_pic:附帶的圖片。好比說一些MP3,AAC音頻文件附帶的專輯封面。

<7>. AVPacket存儲壓縮編碼數據相關信息的結構體,暫存解複用以後、解碼以前的媒體數據(一個音/視頻幀、一個字幕包等)及附加信息(解碼時間戳、顯示時間戳、時長等)

  uint8_t *data:壓縮編碼的數據。

  例如對於H.264來講。1個AVPacket的data一般對應一個NAL。

  注意:在這裏只是對應,而不是如出一轍。他們之間有微小的差異:使用FFMPEG類庫分離出多媒體文件中的H.264碼流

  所以在使用FFMPEG進行視音頻處理的時候,經常能夠將獲得的AVPacket的data數據直接寫成文件,從而獲得視音頻的碼流文件。

  int   size:data的大小

  int64_t pts:顯示時間戳

  int64_t dts:解碼時間戳

  int   stream_index:標識該AVPacket所屬的視頻/音頻流。

》》》結構體關係

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 1). 紅色字體的first_protocol first_iformat first_avcodec, 這三個不一樣的頭指針,分別爲ffmpeg支持 不一樣的數據源、不一樣格式以及不一樣編碼的音視頻數據提供了處理的可能。

 

 2). ffplay主要劃分爲四大部分: 數據源, 解複用, 解碼, 顯示播放. ffplay使用SDL庫進行視頻顯示和聲音播放,至於同步在ffplay中自個作的.

 

  首先, 談談數據源相應的數據結構: URLContext, ByteIOContext. 這兩個與音視頻數據相關, URLProtocol體如今功能函數上. 上圖中, URLContext的 void *priv_data 指向了FILE結構體, 其實這是做者的一點點失誤,ffmpeg使用的是c的底層io, 沒有使用stdio. c底層io是不帶緩存的, 因此加上了ByteIOContext爲無緩衝io提供緩存, 避免頻繁的進行i/o操做.

 

  其次, 解複用對應的數據結構: AVFormatContext中的void *priv_data字段, AVStream, AVStream中void *priv_data結合AVInputeFormat的使用, 從下一層的ByteIOContext的buffer中將音視頻數據分離.

 

  最後, 解碼對應的數據結構: AVCodecContext, AVCodec體如今功能函數上, 其中AVCodecContext的void *priv_data字段是特定的decodec.

 

  數據源 --> char *buffer --> 解複用 --> AVPacket(音頻包, 視頻包) --> 解碼 --> AVFrame(video) / audio_buffer(audio).

 

 3). first_protocol將file, tcp, udp, rtp...數據當成協議看待, 各自均提供URLProtocol結構體實例以功能函數的形式進行體現. first_iformat將ffmpeg所支持的全部格式串連到一塊兒, first_avcodec將ffmpeg支持的全部編碼器串連到一塊兒.

 

  三個指針鏈表是如何肯定相應實例的呢?

 

  a. (first_protocol, argv[1]參數) 參數例如: file://pathname/filename 協議: file, 默認也爲file; rtsp://ip_address/filename 協議:rtsp

 

  b. (first_iformat, is->iformat->read_probe())  

 

  c. (first_avcodec, is->iformat->read_head())

 

 

(4). avio_open2()

該函數用於打開FFmpeg的輸入輸出文件。avio_open2()的聲明位於libavformat\avio.h文件中 int avio_open2(AVIOContext **s, const char *url, int flags,  const AVIOInterruptCB *int_cb, AVDictionary **options) 

  s:函數調用成功以後建立的AVIOContext結構體。
  url:輸入輸出協議的地址(文件也是一種「廣義」的協議,對於文件來講就是文件的路徑)。
  flags:打開地址的方式。AVIO_FLAG_READ:只讀;AVIO_FLAG_WRITE:只寫;AVIO_FLAG_READ_WRITE:讀寫。                                                

(5). avcodec_find_encoder()和avcodec_find_decoder() 

查找編碼器 和解碼器,實質就是遍歷AVCodec鏈表而且得到符合條件的元素,聲明位於libavcodec\avcodec.h:

  AVCodec *avcodec_find_encoder(enum AVCodecID id);

  AVCodec *avcodec_find_decoder(enum AVCodecID id);

 

 

 

(6). avcodec_open2()

初始化一個視音頻編解碼器的AVCodecContext。avcodec_open2()的聲明位於libavcodec\avcodec.h

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

  avctx:須要初始化的AVCodecContext;
  codec:輸入的AVCodec;
  options:一些選項。例如使用libx264編碼的時候,「preset」,「tune」等均可以經過該參數設置

avcodec_open2() 函數的主要工做:

  1)爲各類結構體分配內存(經過各類av_malloc()實現)
  2)將輸入的AVDictionary形式的選項設置到AVCodecContext
  3)其餘一些零零碎碎的檢查,好比說檢查編解碼器是否處於「實驗」階段
  4)若是是編碼器,檢查輸入參數是否符合編碼器的要求
  5)調用AVCodec的init()初始化具體的解碼器。

 

(7). avcodec_close()

該函數用於關閉編碼器。avcodec_close()函數的聲明位於libavcodec\avcodec.h

int avcodec_close(AVCodecContext *avctx);

 

1.3 源碼——解碼部分

(1). avformat_open_input()

打開媒體的過程開始於avformat_open_input(),完成:

1).輸入輸出結構體AVIOContext的初始化;

2).輸入數據的協議(例如RTMP,或者file)的識別(經過一套評分機制):

  判斷文件名的後綴  + 讀取文件頭的數據進行比對

使用得到最高分的文件協議對應的URLProtocol,經過函數指針的方式,與

FFMPEG鏈接(非專業用詞);

3).剩下的就是調用該URLProtocol的函數進行open,read等操做了

 

(2). avformat_close_input()

用於打開一個AVFormatContext,通常狀況下是和avformat_open_input()成對使用的;

avformat_close_input()的聲明位於libavformat\avformat.h:        void avformat_close_input(AVFormatContext **s);

函數功能:

  1)調用AVInputFormat的read_close()方法關閉輸入流
  2)調用avformat_free_context()釋放AVFormatContext
  3)調用avio_close()關閉而且釋放AVIOContext

 

(3). avformat_find_stream_info()

 

該函數能夠讀取一部分視音頻數據而且得到一些相關的信息。avformat_find_stream_info()的聲明位於libavformat\avformat.h:

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);     函數正常執行後返回值大於等於0;

  c:輸入的AVFormatContext
  options:額外的選項

功能:

該函數主要用於給每一個媒體流(音頻/視頻)的AVStream結構體賦值。它其實已經實現瞭解碼器的查找,解碼器的打開,視音頻幀的讀取,視音頻幀的解碼等工做。換句話說,該函數實際上已經「走通」的解碼的整個流程。下面看一下除了成員變量賦值以外,該函數的幾個關鍵流程:

  1).查找解碼器:find_decoder()
  2).打開解碼器:avcodec_open2()
  3).讀取完整的一幀壓縮編碼的數據:read_frame_internal() 注:av_read_frame()內部實際上就是調用的read_frame_internal()。
  4).解碼一些壓縮編碼數據:try_decode_frame()

 

(4). av_read_frame()

讀取碼流中的音頻若干幀或者視頻一幀。例如,解碼視頻的時候,每解碼一個視頻幀,須要先調用 av_read_frame()得到一幀視頻的壓縮數據,而後才能對該數據進行解碼(例如H.264中一幀壓縮數據一般對應一個NAL)。

 先參考了其餘人對av_read_frame()的解釋,在此作一個參考:經過av_read_packet(***),讀取一個包,須要說明的是此函數必須是包含整數幀的,不存在半幀的狀況,以ts流爲例,是讀取一個完整的 PES包(一個完整pes包包含若干視頻或音頻es包),讀取完畢後,經過av_parser_parse2(***)分析出視頻一幀(或音頻若干幀), 返回,下次進入循環的時候,若是上次的數據沒有徹底取完,則st = s->cur_st;不會是NULL,即再此進入av_parser_parse2(***)流程,而不是下面的 av_read_packet(**)流程,這樣就保證了,若是讀取一次包含了N幀視頻數據(以視頻爲例),則調用 av_read_frame(***)N次都不會去讀數據,而是返回第一次讀取的數據,直到所有解析完畢。

 注意av_read_frame - 新版本的ffmpeg用的是av_read_frame,而老版本的是av_read_packet ,區別是av_read_packet讀出的是包,它多是半幀或多幀,不保證幀的完整性。av_read_frame對 av_read_packet進行了封裝,使讀出的數據老是完整的幀   

av_read_frame()的聲明位於libavformat\avformat.h:   int av_read_frame(AVFormatContext *s, AVPacket *pkt);

  s:輸入的AVFormatContext

  pkt:輸出的AVPacket/* 

 

(5). avcodec_decodec_video2()

解碼一幀視頻數據。輸入一個壓縮編碼的結構體AVPacket,輸出一個解碼後的結構體AVFrame。該函數的聲明位於libavcodec\avcodec.h,

int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt);

功能:

 1)對輸入的字段進行了一系列的檢查工做:例如寬高是否正確,輸入是否爲視頻等等。

 2)經過ret = avctx->codec->decode(avctx, picture, got_picture_ptr,&tmp)這句代碼,調用了相應AVCodec的decode()函數,完成了解碼操做。      AVCodec的decode()方法是一個函數指針,指向了具體解碼器的解碼函數

   3)對獲得的AVFrame的一些字段進行了賦值,例如寬高、像素格式等等。

 

(6). avformat_close_input()

關閉一個AVFormatContext,通常狀況下是和avformat_open_input()成對使用的。聲明位於libavformat\avformat.h

  void avformat_close_input(AVFormatContext   **s);

功能:

  1)調用AVInputFormat的read_close()方法關閉輸入流
  2)調用avformat_free_context()釋放AVFormatContext
  3)調用avio_close()關閉而且釋放AVIOContext

 

1.4 源碼——編碼部分

(1). avformat_alloc_output_context2()

在基於FFmpeg的視音頻編碼器程序中,該函數一般是第一個調用的函數(除了組件註冊函數av_register_all())。 avformat_alloc_output_context2()函數能夠初始化一個用於輸出的AVFormatContext結構體。它的聲明位於 libavformat\avformat.h

int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,  const char *format_name, const char *filename);
  ctx:函數調用成功以後建立的AVFormatContext結構體。
  oformat:指定AVFormatContext中的AVOutputFormat,用於肯定輸出格式。若是指定爲NULL,能夠設定後兩個參數(format_name或者filename)由              FFmpeg猜想輸出格式。
  PS:使用該參數須要本身手動獲取AVOutputFormat,相對於使用後兩個參數來講要麻煩一些。
  format_name:指定輸出格式的名稱。根據格式名稱,FFmpeg會推測輸出格式。輸出格式能夠是「flv」,「mkv」等等。
  filename:指定輸出文件的名稱。根據文件名稱,FFmpeg會推測輸出格式。文件名稱能夠是「xx.flv」,「yy.mkv」等等。

函數執行成功的話,其返回值大於等於0。

 

(2). avformat_write_header()

av_write_frame()用於寫視頻數據,avformat_write_header()用於寫視頻文件頭,而av_write_trailer()用於寫視頻文件尾。

avformat_write_header()的聲明位於libavformat\avformat.h ,int avformat_write_header(AVFormatContext *s, AVDictionary **options);

   s:用於輸出的AVFormatContext;

options:額外的選項;           函數正常執行後返回值等於0。                                            

功能:

   1)調用init_muxer()初始化複用器
   2)調用AVOutputFormat的write_header()

 

(3). avcodec_encode_video2()

編碼一幀視頻數據。avcodec_encode_video2()函數的聲明位於libavcodec\avcodec.h
int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); 

avctx:編碼器的AVCodecContext。
avpkt:編碼輸出的AVPacket。
frame:編碼輸入的AVFrame。
got_packet_ptr:成功編碼一個AVPacket的時候設置爲1。

函數返回0表明編碼成功

 

(4).av_write_frame()

輸出一幀視音頻數據,它的聲明位於libavformat\avformat.h:   int av_write_frame(AVFormatContext *s, AVPacket *pkt);

s:用於輸出的AVFormatContext。
pkt:等待輸出的AVPacket。

函數正常執行後返回值等於0。

 

(5). av_write_trailer()

av_write_trailer()用於輸出文件尾,它的聲明位於libavformat\avformat.h:  int av_write_trailer(AVFormatContext *s);

  它只須要指定一個參數,即用於輸出的AVFormatContext。
函數正常執行後返回值等於0。

 

1.5 源碼——其餘部分

(1). av_log()日誌輸出系統

av_log()是FFmpeg中輸出日誌的函數。通常狀況下FFmpeg類庫的源代碼中是不容許使用printf()這種的函數的,全部的輸出一概使用av_log()。

av_log()的聲明位於libavutil\log.h:  void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); 

  1)函數最後一個參數是「…」。
  在C語言中,在函數參數數量不肯定的狀況下使用「…」來表明參數。例如printf()的原型定義以下:  int printf (const char*, ...);  

  2)它的聲明後面有一個av_printf_format(3, 4)。有關這個地方的左右尚未深刻研究,網上資料中說它的做用是按照printf()的格式檢查av_log()的格式。

avcl:指定一個包含AVClass的結構體。
level:log的級別
fmt:和printf()同樣。

因而可知,av_log()和printf()的不一樣主要在於前面多了兩個參數。其中第一個參數指定該log所屬的結構體,例如 AVFormatContext、AVCodecContext等等。第二個參數指定log的級別,源代碼中定義了以下幾個級別 AV_LOG_PANIC ,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING,AV_LOG_INFO AV_LOG_VERBOSE,AV_LOG_DEBUG。 每一個級別定義的數值表明了嚴重程度,數值越小表明越嚴重。默認的級別是AV_LOG_INFO。此外,還有一個級別不輸出任何信息,即 AV_LOG_QUIET。當前系統存在着一個「Log級別」。全部嚴重程度高於該級別的Log信息都會輸出出來。例如當前的Log級別是 AV_LOG_WARNING,則會輸出AV_LOG_PANIC,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING 級別的信息,而不會輸出AV_LOG_INFO級別的信息。能夠經過av_log_get_level()得到當前Log的級別,經過另外一個函數 av_log_set_level()設置當前的Log級別。

 

(2). AVClass ,AVOption 結構體成員管理系統

AVOption ——描述結構體中的成員變量,它最主要的做用能夠歸納爲兩個字:「賦值」。一個AVOption結構體包含了變量名稱,簡短的幫助,取值等等信息。

AVClass——和AVOption有關的數據都存儲在AVClass結構體中, 一個結構體若要支持AVOption ,第一個成員變量是指向AVclass結構體的指針

該AVClass中的成員變量option必須指向一個AVOption類型的靜態數組。

 

AVOption:用來設置FFmpeg中變量的值的結構體AVOption的特色就在於它賦值時候的靈活性。AVOption可使用字符串爲任何類型的變量賦值。

統一使用字符串賦值。例如給int型變量qp設定值爲20,經過 AVOption須要傳遞進去一個內容爲「20」的字符串。
此外,AVOption中變量的名稱也使用字符串來表示。結合上面提到的使用字符串賦值的特性,咱們能夠發現使用AVOption以後,

傳遞兩個字符串(一個是變量的名稱,一個是變量的值)就能夠改變系統中變量的值。

AVClass:AVClass最主要的做用就是給結構體(例如AVFormatContext等)增長AVOption功能的支持。換句話說AVClass就是AVOption和目標結構體之間的「橋     梁」。AVClass要求必須聲明爲目標結構體的第一個量。 AVClass中有一個option數組用於存儲目標結構體的全部的AVOption。

舉個例子,AVFormatContext結構體,AVClass和AVOption之間

    圖中AVFormatContext結構體的第一個變量爲AVClass類型的指針av_class,它在AVFormatContext結構體初始化的時候,被賦值指向了全局靜態變量av_format_context_class結構體(定義位於libavformat\options.c)。而 AVClass類型的av_format_context_class結構體中的option變量指向了全局靜態數組 avformat_options(定義位於libavformat\options_table.h。

 

AVOption的幾個成員變量:

name:名稱。
help:簡短的幫助。
offset:選項相對結構體首部地址的偏移量(這個很重要)。
type:選項的類型。              ( AVOptionType類型的變量AVOptionType是一個枚舉類型
default_val:選項的默認值,(union類型的變量)
min:選項的最小值。
max:選項的最大值。
flags:一些標記。
unit:該選項所屬的邏輯單元,能夠爲空。

AVClass的幾個成員變量:

  class_name:AVClass名稱。
  item_name:函數,獲取與AVClass相關聯的結構體實例的名稱。
  option:AVOption類型的數組(最重要)。
  version:完成該AVClass的時候的LIBAVUTIL_VERSION。
  category:AVClass的類型,是一個類型爲AVClassCategory的枚舉型變量。

 

(3). sws_getContext() 初始化一個SwsContext

圖像處理(縮放,YUV/RGB格式轉換)類庫libswsscale:libswscale是一個主要用於處理圖片像素數據的類庫,能夠完成圖片像素格式的轉換,圖片的拉伸等工做

ibswscale經常使用的函數數量不多,通常狀況下就3個:

sws_getContext():初始化一個SwsContext。

sws_scale():處理圖像數據。

sws_freeContext():釋放一個SwsContext。

其中sws_getContext()也能夠用sws_getCachedContext()取代。

 


  libswscale處理數據有兩條最主要的方式:unscaled和scaled。unscaled用於處理不須要拉伸的像素數據(屬於比較特殊 的狀況),scaled用於處理須要拉伸的像素數據。Unscaled只須要對圖像像素格式進行轉換;而Scaled則除了對像素格式進行轉換以外,還需 要對圖像進行縮放。Scaled方式能夠分紅如下幾個步驟:

  • XXX to YUV Converter:首先將數據像素數據轉換爲8bitYUV格式;
  • Horizontal scaler:水平拉伸圖像,而且轉換爲15bitYUV;
  • Vertical scaler:垂直拉伸圖像;
  • Output converter:轉換爲輸出像素格式。

 

 

 

sws_getContext()是初始化SwsContext的函數。sws_getContext()的聲明位於libswscale\swscale.h:

    1. struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,  
    2.                                   int dstW, int dstH, enum AVPixelFormat dstFormat,  
    3.                                   int flags, SwsFilter *srcFilter,  
    4.                                   SwsFilter *dstFilter, const double *param);

srcH:源圖像的高
srcFormat:源圖像的像素格式
dstW:目標圖像的寬
dstH:目標圖像的高
dstFormat:目標圖像的像素格式
flags:設定圖像拉伸使用的算法   成功執行的話返回生成的SwsContext,不然返回NULL

 

(4). sws_scale()

用於轉換像素的函數,聲明位於:libswscale\swscale.

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],

          const int srcStride[], int srcSliceY, int srcSliceH,  uint8_t *const dst[], const int dstStride[]);

 

(5). avdevice_register_all() 註冊設備的函數

  在使用libavdevice以前,必須先運行avdevice_register_all()對設備進行註冊,不然就會出錯。 avdevice_register_all()的註冊方式和av_register_all()、avcodec_register_all()這幾個函數是相似的

  avdevice_register_all()調用3個函數進行設備組建的註冊:REGISTER_INDEV(),REGISTER_OUTDEV(),REGISTER_INOUTDEV()。上述3個函數其實是預約義的3個宏:
REGISTER_INDEV():註冊輸入設備。實際上調用了av_register_input_format()將輸入設備註冊成一個AVInputFormat。
REGISTER_OUTDEV():註冊輸出設備。實際上調用了av_register_output_format()將輸出設備註冊成一個AVOutputFormat。
REGISTER_INOUTDEV():註冊輸入設備和輸出設備。實際上將上述兩個宏定義合併了。

 

 

1.6  編譯

(1).  Makefile  文件

FFmpeg中與Makefile相關的文件主要有如下幾個:

  根目錄Makefile:最基本的Makefile;

  config.mak:由configure生成的Makefile,保存Configure的設置信息

  libavXXXX/Makefile:每一個類庫的Makefile(僅僅設置了幾個變量);

  library.mak:編譯類庫的Makefile(和libavXXXX/Makefile配合使用);
  common.mak:包含一些通用代碼的Makefile;

 

XXX.c:C語言文件;
XXX.h:C語言文件用到的頭文件;
XXX.o:C語言文件對應的目標文件;
XXX.d:C語言文件對應的依賴關係文件;

 

 

(2). Configure 腳本

Configure一方面用於檢測FFmpeg的編譯環境,另外一方面根據用戶配置的選項生成config.mak,config.h文件(可能還有config.asm),

Configure的總體流程能夠分紅如下幾步:

Set Default Value:設置各個變量默認值;

Parse Options:解析輸入的選項;

Check Compiler:檢查編譯器;

die_license_disabled():檢查GPL等協議的設置狀況;

Check:檢查編譯環境(數學函數,第三方類庫等);

Echo info:控制檯上打印配置信息;

Write basic info:向config.mak中寫入一些基本信息; 

print_config():向config.h、config.mak、config.asm中寫入全部配置信息;

print_enabled():向config.mak寫入全部enabled的組件信息;

pkgconfig_generate():向libavXXX/libavXXX.pc中寫入pkgconfig信息(XXX表明avcodec,avformat等);

相關文章
相關標籤/搜索