AVFormatContext
AVFormatContext是一個描述編解碼格式上下文的數(shù)據(jù)結(jié)構(gòu)。
struct AVInputFormat *iformat;//輸入數(shù)據(jù)的封裝格式
AVIOContext *pb;//輸入數(shù)據(jù)的緩存
unsigned int nb_streams;//音頻流+視頻流的總數(shù)
AVStream **streams;//音視頻流
char filename[1024];//文件名
int64_t duration;//時長(單位:微秒us橘茉,轉(zhuǎn)換為秒需要除以1000000)
int bit_rate;//比特率(單位bps澈歉,轉(zhuǎn)換為kbps需要除以1000)
AVDictionary *metadata;//元數(shù)據(jù)
AVStream
AVStream是存儲每一個視頻/音頻流信息的結(jié)構(gòu)體展鸡。
結(jié)構(gòu)體參數(shù)來自:這里
int index; //在AVFormatContext中的索引,這個數(shù)字是自動生成的埃难,可以通過這個數(shù)字從AVFormatContext::streams表中索引到該流莹弊。
int id;//流的標(biāo)識,依賴于具體的容器格式涡尘。解碼:由libavformat設(shè)置忍弛。編碼:由用戶設(shè)置,如果未設(shè)置則由libavformat替換考抄。
AVCodecContext *codec;//指向該流對應(yīng)的AVCodecContext結(jié)構(gòu)细疚,調(diào)用avformat_open_input時生成。
AVRational time_base;//這是表示幀時間戳的基本時間單位(以秒為單位)座泳。該流中媒體數(shù)據(jù)的pts和dts都將以這個時間基準(zhǔn)為粒度惠昔。
int64_t start_time;//流的起始時間幕与,以流的時間基準(zhǔn)為單位挑势。如需設(shè)置,100%確保你設(shè)置它的值真的是第一幀的pts啦鸣。
int64_t duration;//解碼流的持續(xù)時間潮饱。如果源文件未指定持續(xù)時間,但指定了比特率诫给,則將根據(jù)比特率和文件大小估計該值香拉。
int64_t nb_frames; //此流中的幀數(shù)(如果已知)或0。
enum AVDiscard discard;//選擇哪些數(shù)據(jù)包可以隨意丟棄中狂,不需要去demux凫碌。
AVRational sample_aspect_ratio;//樣本長寬比(如果未知,則為0)胃榕。
AVDictionary *metadata;//元數(shù)據(jù)信息盛险。
AVRational avg_frame_rate;//平均幀速率。解封裝:可以在創(chuàng)建流時設(shè)置為libavformat勋又,也可以在avformat_find_stream_info()中設(shè)置苦掘。
//封裝:可以由調(diào)用者在avformat_write_header()之前設(shè)置。
AVPacket attached_pic;//附帶的圖片楔壤。比如說一些MP3鹤啡,AAC音頻文件附帶的專輯封面。
int probe_packets;//編解碼器用于probe的包的個數(shù)蹲嚣。
int codec_info_nb_frames;//在av_find_stream_info()期間已經(jīng)解封裝的幀數(shù)递瑰。
int request_probe;//流探測狀態(tài)祟牲,1表示探測完成,0表示沒有探測請求抖部,rest 執(zhí)行探測疲眷。
int skip_to_keyframe;//表示應(yīng)丟棄直到下一個關(guān)鍵幀的所有內(nèi)容。
int skip_samples;//在從下一個數(shù)據(jù)包解碼的幀開始時要跳過的采樣數(shù)您朽。
int64_t start_skip_samples;//如果不是0狂丝,則應(yīng)該從流的開始跳過的采樣的數(shù)目。
int64_t first_discard_sample;//如果不是0哗总,則應(yīng)該從流中丟棄第一個音頻樣本几颜。
int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];//內(nèi)部數(shù)據(jù),從pts生成dts讯屈。
int64_t last_dts_for_order_check;
uint8_t dts_ordered;
uint8_t dts_misordered;//內(nèi)部數(shù)據(jù)蛋哭,用于分析dts和檢測故障mpeg流。
AVRational display_aspect_ratio;//顯示寬高比涮母。
AVIOContext
AVIOContext是FFMPEG管理輸入輸出數(shù)據(jù)的結(jié)構(gòu)體谆趾。
unsigned char *buffer;//緩存開始位置
int buffer_size;//緩存大小(默認(rèn)32768)
unsigned char *buf_ptr;//當(dāng)前指針讀取到的位置
unsigned char *buf_end;//緩存結(jié)束的位置
void *opaque;//URLContext結(jié)構(gòu)體
AVCodecContext
AVCodecContext是一個描述編解碼器上下文的數(shù)據(jù)結(jié)構(gòu)叛本。
注釋來自這里
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:根據(jù)該參數(shù)跷叉,可以把PTS轉(zhuǎn)化為實際的時間(單位為秒s)
int width, height:如果是視頻的話,代表寬和高
int refs:運動估計參考幀的個數(shù)(H.264的話會有多幀营搅,MPEG2這類的一般就沒有了)
int sample_rate:采樣率(音頻)
int channels:聲道數(shù)(音頻)
enum AVSampleFormat sample_fmt:采樣格式
int profile:型(H.264里面就有云挟,其他編碼標(biāo)準(zhǔn)應(yīng)該也有)
int level:級(和profile差不太多)
AVCodec
解碼器。結(jié)構(gòu)來自:這里
/**
* AVCodec.
* H.264的解碼器對象: ff_h264_decoder
*/
typedef struct AVCodec
{
// 解碼器名字
const char *name;
// 解碼器完整名
const char *long_name;
// 媒體類型
// AVMEDIA_TYPE_VIDEO
// AVMEDIA_TYPE_AUDIO
// AVMEDIA_TYPE_DATA
enum AVMediaType type;
// 解碼器ID(AV_CODEC_ID_H264)
enum AVCodecID id;
// 能力集
// H264: CODEC_CAP_DR1|CODEC_CAP_DELAY|CODEC_CAP_SLICE_THREADS|CODEC_CAP_FRAME_THREADS
int capabilities;
// 支持的幀率(V)
const AVRational *supported_framerates;
// 支持的像素格式(V)
// AV_PIX_FMT_YUV420P
// AV_PIX_FMT_RGB24
const enum AVPixelFormat *pix_fmts;
// 支持的采樣率(A)
const int *supported_samplerates;
// 支持的采樣格式(A)
const enum AVSampleFormat *sample_fmts;
// 支持的聲道數(shù)(A)
const uint64_t *channel_layouts;
// (這里的3條感覺就是打補丁打出來的字段)
// 由解碼器支持低分辨率的最大值,不能直接訪問,使用av_codec_get_max_lowres()
uint8_t max_lowres;
// AVClass針對私有上下文
const AVClass *priv_class;
// 公認(rèn)的配置文件數(shù)組,如果未知則為NULL,數(shù)組由FF_PROFILE_UNKNOWN表示終止
const AVProfile *profiles;
// 私有數(shù)據(jù)總長度
int priv_data_size;
// 下一個鏈接對象
struct AVCodec *next;
// 假如被定義了, 那么當(dāng)他們被創(chuàng)建時則被線程上下文調(diào)用转质。
// 假如編解碼器在調(diào)用init()時分配了可寫表, 那么在這里重新分配.
// priv_data將被設(shè)置為原件的副本
int (*init_thread_copy)(AVCodecContext *);
/**
* 將必要的上下文變量從上一個線程復(fù)制到當(dāng)前線程的上下文,(跨線程拷貝)园欣。
* 假如沒有被定義, 下一個線程將自動啟動; 否則, 編解碼器必須調(diào)用call ff_thread_finish_setup().
*
* 目標(biāo)和源很少指向相同的上下文, 在這種情況下應(yīng)該跳過memcpy()的調(diào)用。
*/
int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src);
// 私有的指定的編解碼器默認(rèn)值.
const AVCodecDefault *defaults;
// 初始化編解碼器的靜態(tài)數(shù)據(jù), 由avcodec_register()來調(diào)用.
void (*init_static_data)(struct AVCodec *codec);
// 根據(jù)AVCodecContext來初始化
int (*init)(AVCodecContext *);
int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, const struct AVSubtitle *sub);
// 編碼數(shù)據(jù)到AVPacket.
// @參數(shù) avctx: 編解碼上下文
// @參數(shù) avpkt: 輸出的AVPacket,(可能包含上層調(diào)用者提供的緩沖區(qū))
// @參數(shù)[in] frame: AVFrame包含了未加工的數(shù)據(jù)來編碼
// @參數(shù)[out] got_packet_ptr: 設(shè)置為0或1來表示一個非空的AVPacket返回值avpkt
// @返回值 0表示成功,其他錯誤代碼表示錯誤
int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
// 執(zhí)行解碼,從數(shù)據(jù)包AVPacket中進行解碼轉(zhuǎn)為outdata和outdata_size,提供AVCodecContext來定義編解碼上下文信息
int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
// 關(guān)閉編解碼器對象
int (*close)(AVCodecContext *);
// 編碼+解碼的API函數(shù), 用來解耦packet/frame數(shù)據(jù)流(就是提供自己玩的接口休蟹,而不是打包操作).
// 這些API和avcodec_ prefixed的API差不多,除了下面這些:
// - 如果編解碼器關(guān)閉或者是錯誤類型,那么就不要使用沸枯。
// - 在調(diào)用AVCodec->send_packet()之前,改變了AVPacket參數(shù)數(shù)據(jù)
// - 假如AV_CODEC_CAP_DELAY沒有被設(shè)置、漏包或者幀壓根沒有被發(fā)送
// 發(fā)送幀
int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame);
// 發(fā)送包
int (*send_packet)(AVCodecContext *avctx, const AVPacket *avpkt);
// 接受幀
int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame);
// 接受包
int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt);
// 刷新緩沖區(qū)
void (*flush)(AVCodecContext *);
// 內(nèi)部的編解碼能力.
// 可以查看FF_CODEC_CAP_*系列宏鸡挠,在頭文件internal.h中
int caps_internal;
}
AVPacket
AVPacket是FFmpeg中很重要的一個數(shù)據(jù)結(jié)構(gòu)辉饱,它保存了解復(fù)用(demuxer)之后,解碼(decode)之前的數(shù)據(jù)(仍然是壓縮后的數(shù)據(jù))和關(guān)于這些數(shù)據(jù)的一些附加的信息拣展,如顯示時間戳(pts)彭沼,解碼時間戳(dts),數(shù)據(jù)時長(duration),所在流媒體的索引(stream_index)等等备埃。詳情看這里
pts: (int64_t)顯示時間姓惑,結(jié)合AVStream->time_base轉(zhuǎn)換成時間戳
dts: (int64_t)解碼時間褐奴,結(jié)合AVStream->time_base轉(zhuǎn)換成時間戳
size: (int)data的大小
stream_index: (int)packet在stream的index位置
flags: (int)標(biāo)示,結(jié)合AV_PKT_FLAG使用于毙,其中最低為1表示該數(shù)據(jù)是一個關(guān)鍵幀敦冬。
#define AV_PKT_FLAG_KEY 0x0001 //關(guān)鍵幀
#define AV_PKT_FLAG_CORRUPT 0x0002 //損壞的數(shù)據(jù)
#define AV_PKT_FLAG_DISCARD 0x0004 /丟棄的數(shù)據(jù)
side_data_elems: (int)邊緣數(shù)據(jù)元數(shù)個數(shù)
duration: (int64_t)數(shù)據(jù)的時長,以所屬媒體流的時間基準(zhǔn)為單位唯沮,未知則值為默認(rèn)值0
pos: (int64_t )數(shù)據(jù)在流媒體中的位置脖旱,未知則值為默認(rèn)值-1
convergence_duration:該字段已deprecated,不在使用
關(guān)于數(shù)據(jù)緩存,AVPacket本身只是個容器介蛉,不直接的包含數(shù)據(jù)萌庆,而是通過數(shù)據(jù)緩存的指針引用數(shù)據(jù)。
uint8_t *data:指向保存壓縮數(shù)據(jù)的指針币旧,這就是AVPacket的實際數(shù)據(jù)践险。
AVPacketSideData *side_data:容器提供的一些附加數(shù)據(jù)
AVBufferRef *buf:用來管理data指針引用的數(shù)據(jù)緩存,其使用在后面介紹吹菱。
AVFrame
AVFrame用來存儲解碼后的(或原始)音頻或視頻數(shù)據(jù)巍虫,位于avcodec.h文件中。
AVFrame必須由av_frame_alloc()分配內(nèi)存鳍刷,同時必須由av_frame_free()釋放占遥。
AVFrame分配內(nèi)存后能夠被多次用來存儲不同的數(shù)據(jù)(例如:decoder解碼后的幀)。av_frame_unref釋放任何持幀的引用倾剿,并結(jié)構(gòu)體還原到未被使用的狀態(tài)筷频。來自這里
一個AVPacket包含一個視頻幀(AVFrame),也可以包含多個音頻幀。
一幀音頻的數(shù)據(jù)量 = channel數(shù) * nb_samples樣本數(shù) * 每個樣本占用的字節(jié)數(shù)前痘。
uint8_t * data [AV_NUM_DATA_POINTERS];//解碼后原始數(shù)據(jù)(對視頻來說是YUV,RGB担忧,對音頻來說是PCM)芹缔。
int linesize[AV_NUM_DATA_POINTERS];//在視頻中,表示圖片一行數(shù)據(jù)的大小瓶盛。
uint8_t **extended_data;//指向數(shù)據(jù)平面/通道最欠。
int width, height;//一個視頻幀的寬度和高度。
int nb_samples;//這個AVFrame中的每個音頻聲道的樣本數(shù)惩猫。
int format;//表示解碼后的數(shù)據(jù)類型或格式芝硬,-1表示未被設(shè)置或不能識別的類型。
int key_frame;//是否為關(guān)鍵幀,1->關(guān)鍵幀轧房,0->非關(guān)鍵幀拌阴。
enum AVPictureType pict_type;//幀的類型。
AVRational sample_aspect_ratio;//視頻幀的寬高比奶镶,0表示未知迟赃。
int64_t pts;//顯示時間戳陪拘,表示該什么時候被顯示。
int64_t pkt_dts;//從AVPacket中拷貝的值纤壁。
int coded_picture_number;//編碼幀序號左刽。
int display_picture_number;//顯示幀需要。
void *opaque;//用戶私有信息酌媒。
int repeat_pict;//解碼時欠痴,每幀圖片延遲的時間,extra_delay = repeat_pict / (2*fps)秒咨。
int interlaced_frame;//是否是隔行掃描
int sample_rate;//音頻的采樣率斋否。
uint64_t channel_layout;//音頻的布局方式。
enum AVColorRange color_range;
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
enum AVColorSpace colorspace;
enum AVChromaLocation chroma_location;
int64_t best_effort_timestamp;//大多數(shù)情況下AVFrame的pts和best_effort_timestamp值是一樣的
int64_t pkt_pos;//記錄最后一個進入解碼器的packet在輸入文件中的位置偏移量拭荤。
int64_t pkt_duration;//對應(yīng)packet的時長茵臭,單位是AVStream->time_base。
AVDictionary *metadata;
int decode_error_flags;
int channels;//音頻通道個數(shù)
int pkt_size;//對應(yīng)packet的大小舅世。
int8_t *qscale_table;
int qstride;
int qscale_type;
AVBufferRef *qp_table_buf;
AVBufferRef *hw_frames_ctx;
AVBufferRef *opaque_ref;
AVSampleFormat
音頻數(shù)據(jù)格式旦委。名稱尾有p表示分片,如音頻有兩個聲道雏亚,分片左聲道存linesize[0],右聲道存linesize[1]缨硝,不分片都存linesize[0],左右左右...的順序依次存儲罢低。
enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};
AVPictureType
視頻幀類型查辩。
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};