FFmpeg筆記(六)-- 編解碼相關(guān)類咪笑、結(jié)構(gòu)體

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
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市网持,隨后出現(xiàn)的幾起案子宜岛,更是在濱河造成了極大的恐慌,老刑警劉巖功舀,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍倡,死亡現(xiàn)場離奇詭異,居然都是意外死亡辟汰,警方通過查閱死者的電腦和手機列敲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帖汞,“玉大人戴而,你說我怎么就攤上這事◆嬲海” “怎么了所意?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我扁眯,道長壮莹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任姻檀,我火速辦了婚禮命满,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绣版。我一直安慰自己胶台,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布杂抽。 她就那樣靜靜地躺著诈唬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缩麸。 梳的紋絲不亂的頭發(fā)上铸磅,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音杭朱,去河邊找鬼阅仔。 笑死,一個胖子當(dāng)著我的面吹牛弧械,可吹牛的內(nèi)容都是我干的八酒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刃唐,長吁一口氣:“原來是場噩夢啊……” “哼羞迷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起画饥,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衔瓮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后荒澡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體报辱,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年单山,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幅疼。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡米奸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爽篷,到底是詐尸還是另有隱情悴晰,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铡溪,受9級特大地震影響漂辐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棕硫,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一髓涯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哈扮,春花似錦纬纪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至靶庙,卻和暖如春问畅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背六荒。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工护姆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恬吕。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓签则,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铐料。 傳聞我的和親對象是個殘疾皇子渐裂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354