ffmpeg-結構體介紹

本篇博客在雷神的結構體介紹基礎上按自己的喜好整理的 后面根據自己工作中所需有所增改

AVStream


存儲每一個視頻/音頻流信息的結構體 AVStream重要的變量如下

int index:標識該視頻/音頻流
AVCodecContext *codec:指向該視頻/音頻流的AVCodecContext(它們是一一對應的關系)
AVRational time_base:時基。通過該值可以把PTS,DTS轉化為真正的時間。FFMPEG其他結構體中也有這個字段,但是根據我的經驗,只有AVStream中的time_base是可用的。PTS*time_base=真正的時間
AVDictionary *metadata:元數據信息
AVRational avg_frame_rate:幀率(注:對視頻來說,這個挺重要的)
AVPacket attached_pic:附帶的圖片。比如說一些MP3,AAC音頻文件附帶的專輯封面。
int64_t duration:該視頻/音頻流長度

AVIOContext


FFMPEG管理輸入輸出數據的結構體 里面中有以下幾個變量比較重要:

unsigned char *buffer:緩存開始位置
int buffer_size:緩存大?。J32768)
unsigned char *buf_ptr:當前指針讀取到的位置
unsigned char *buf_end:緩存結束的位置
void *opaque:URLContext結構體

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

其中opaque指向了URLContext。注意,這個結構體并不在FFMPEG提供的頭文件中,而是在FFMPEG的源代碼中。URLContext結構體中還有一個結構體URLProtocol。在這個結構體中,除了一些回調函數接口之外,有一個變量const char *name,該變量存儲了協議的名稱。每一種輸入協議都對應這樣一個結構體。

AVCodecContext


挑一些關鍵的變量來看看(這里只考慮解碼)。

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差不太多)

在這里需要注意:AVCodecContext中很多的參數是編碼的時候使用的,而不是解碼的時候使用的。

AVFormatContext:


在使用FFMPEG進行開發的時候,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:元數據

視頻的時長可以轉換成HH:MM:SS的形式,示例代碼如下:
<code>
AVFormatContext *pFormatCtx;
CString timelong;
//duration是以微秒為單位
//轉換成hh:mm:ss形式
int tns, thh, tmm, tss;
tns = (pFormatCtx->duration)/1000000;
thh = tns / 3600;
tmm = (tns % 3600) / 60;
tss = (tns % 60);
timelong.Format("%02d:%02d:%02d",thh,tmm,tss);
</code>

AVFrame


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的

AVPacket


存儲壓縮編碼數據相關信息的結構體 在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所屬的視頻/音頻流。

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:私有數據的大小

每一個編解碼器對應一個該結構體,查看一下ffmpeg的源代碼,我們可以看一下H.264解碼器的結構體如下所示(h264.c):

AVCodec ff_h264_decoder = {
.name           = "h264",
.type           = AVMEDIA_TYPE_VIDEO,
.id             = CODEC_ID_H264,
.priv_data_size = sizeof(H264Context),
.init           = ff_h264_decode_init,
.close          = ff_h264_decode_end,
.decode         = decode_frame,
.capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY |
CODEC_CAP_SLICE_THREADS | CODEC_CAP_FRAME_THREADS,
.flush          = flush_dpb,
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
.profiles = NULL_IF_CONFIG_SMALL(profiles),
.priv_class    = &h264_class,
};

AVPixelFormat定義如下


<code>
enum AVPixelFormat {
AV_PIX_FMT_NONE = -1,
AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
AV_PIX_FMT_GRAY8, ///< Y , 8bpp
AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black,
in each byte pixels are ordered from the msb to the lsb
AV_PIX_FMT_MONOBLACK, ///< Y ,1bpp, 0 is black, 1 is white,
in each byte pixels are ordered from the msb to the lsb
AV_PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG),
deprecated in favor of PIX_FMT_YUV420P and setting color_range
AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG),
deprecated in favor of PIX_FMT_YUV422P and setting color_range
AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG),
deprecated in favor of PIX_FMT_YUV444P and setting color_range
AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
AV_PIX_FMT_XVMC_MPEG2_IDCT,
...(代碼太長,略)
}
</code>

AVDictionary


#define AV_DICT_MATCH_CASE      1
#define AV_DICT_IGNORE_SUFFIX   2
#define AV_DICT_DONT_STRDUP_KEY 4    
#define AV_DICT_DONT_STRDUP_VAL 8   
#define AV_DICT_DONT_OVERWRITE 16    
#define AV_DICT_APPEND         32   


typedef struct {
    char *key;
    char *value;
} AVDictionaryEntry;


struct AVDictionary {
    int count;
    AVDictionaryEntry *elems;
};

從字面上看這是一個鍵值對, 更宏觀一些則為鍵值對數組, 嗯, 動態數組
這就能構建我們通常所說的字典?
這個數據結構有4個操作, 讀(查找)/寫(創建)/拷貝, 釋放

里面有幾個操作標志, 記錄下
AV_DICT_MATCH_CASE     查找時是否比較大小, 不比較大小則全部轉化為大寫來比較
AV_DICT_IGNORE_SUFFIX  查找時是否忽略后綴, 這里的后綴指字典里key 超過查找key 部分
                       如果設置了改參數則, 查找"abc", 可能會找到"abcde" 這樣的key
AV_DICT_DONT_STRDUP_KEY 設置key時, 是否把key 字符串復制一份
AV_DICT_DONT_STRDUP_VAL 設置value時, 是否把value 字符串復制一份
AV_DICT_DONT_OVERWRITE  寫入時不要覆蓋原來存在的key(存在key 則不設置), 否則把原來的key/value 釋放重建
AV_DICT_APPEND    如果已經存在key/value, 把將新的value 值連到舊的后面 

從這里copy的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 教程一:視頻截圖(Tutorial 01: Making Screencaps) 首先我們需要了解視頻文件的一些基...
    90后的思維閱讀 4,749評論 0 3
  • 原文地址:http://blog.csdn.net/yipie/article/details/7912291 摘...
    冬的天閱讀 7,215評論 1 6
  • 根據ffmpeg官方網站上的例子程序開始學習ffmpeg和SDL編程。 SDL是一個跨平臺的多媒體開發包。適用于游...
    762683ff5d3d閱讀 1,840評論 0 2
  • 清明節就要到了,天又下雨了。雨不大,淅淅瀝瀝,卻下個不停。每年的清明節似乎都是這樣,也不知今年,奶奶墳前的土被打濕...
    默言墨語閱讀 1,201評論 0 2
  • 13年的春天,跟研究生班的8個同學結伴去蘇揚玩了一圈。 當時去的8個人里面,我大概跟3個人是比較熟悉的,其余的幾個...
    蘸墨水的饅頭閱讀 182評論 0 0