模塊:
算法
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() : 註冊 濾鏡filteride
(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*, ...);
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方式能夠分紅如下幾個步驟:
sws_getContext()是初始化SwsContext的函數。sws_getContext()的聲明位於libswscale\swscale.h:
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等);