AVFormatContext介紹(avformat.h)

不会笑的孩子發表於2024-03-09

typedef struct AVFormatContext結構體介紹

表示解複用(解碼)或複用(編碼)多媒體流的格式上下文。在使用FFMPEG進行開發的時候,AVFormatContext是一個貫穿時鐘的資料結構,很多函式都要用它作為引數。它是FFMPEG解封裝(flv,mp4,rmvb,avi)功能的結構體。

typedef struct AVFormatContext {
    const AVClass *av_class;//指向AVOptions和日誌記錄的AVClass結構的指標,用於AVOptions和日誌記錄
    struct AVInputFormat *iformat;//指向輸入格式的指標。
    struct AVOutputFormat *oformat;//指向輸出格式的指標。
    void *priv_data;//格式私有資料,一個AVOptions的結構。
    AVIOContext *pb;//格式的I/O上下文
    unsigned int nb_streams;//檔案中流的資訊
    AVStream **streams;//檔案中的資訊
    char filename[1024];//輸入或輸出檔名 
    int64_t start_time;//有關流的時間資訊
    int64_t duration;//有關流的時間資訊
    int bit_rate;//總流位元率
    unsigned int packet_size;//資料包大小
    int max_delay;//最大延遲
    int flags;//標誌位,指示各種格式相關的屬性,如是否生成pts、是否忽略索引等。
#define AVFMT_FLAG_GENPTS       0x0001 ///< Generate missing pts even if it requires parsing future frames.
#define AVFMT_FLAG_IGNIDX       0x0002 ///< Ignore index.
#define AVFMT_FLAG_NONBLOCK     0x0004 ///< Do not block when reading packets from input.
#define AVFMT_FLAG_IGNDTS       0x0008 ///< Ignore DTS on frames that contain both DTS & PTS
#define AVFMT_FLAG_NOFILLIN     0x0010 ///< Do not infer any values from other values, just return what is stored in the container
#define AVFMT_FLAG_NOPARSE      0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
#define AVFMT_FLAG_CUSTOM_IO    0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
#define AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted
#define AVFMT_FLAG_MP4A_LATM    0x8000 ///< Enable RTP MP4A-LATM payload
#define AVFMT_FLAG_SORT_DTS    0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
#define AVFMT_FLAG_PRIV_OPT    0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted)
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Dont merge side data but keep it separate
    unsigned int probesize;//資料探測大小
    int max_analyze_duration;//最大分析時長
    const uint8_t *key;//金鑰
    int keylen;//金鑰長度
    unsigned int nb_programs;//檔案中程式的數量
    AVProgram **programs;//指向AVProgram指標陣列的指標,表示檔案中的所有程式。
    enum CodecID video_codec_id;//影片編碼器ID
    enum CodecID audio_codec_id;//音訊編碼器ID
    enum CodecID subtitle_codec_id;//字幕編解碼器ID
    unsigned int max_index_size;//最大索引大小
    unsigned int max_picture_buffer;//最大影像緩衝區大小
    unsigned int nb_chapters;//檔案中章節的數量
    AVChapter **chapters;//指向AVChapter指標陣列的指標,表示檔案中的所有章節
    AVDictionary *metadata;//後設資料
    int64_t start_time_realtime;//實際開始時間
    int fps_probe_size;//fps探測大小
    int error_recognition;//錯誤識別
    AVIOInterruptCB interrupt_callback;//I/O中斷回撥函式
    int debug;//除錯標誌
#define FF_FDEBUG_TS        0x0001
    int ts_id;//傳輸流ID
    int audio_preload;//音訊預載入
    int max_chunk_duration;//最大塊時長
    int max_chunk_size;//最大塊大小
    struct AVPacketList *packet_buffer;//資料包緩衝區
    struct AVPacketList *packet_buffer_end;//資料包緩衝區末尾
    int64_t data_offset; //資料偏移量
    struct AVPacketList *raw_packet_buffer;//原始資料包緩衝區剩餘大小
    struct AVPacketList *raw_packet_buffer_end;
    struct AVPacketList *parse_queue;
    struct AVPacketList *parse_queue_end;
#define RAW_PACKET_BUFFER_SIZE 2500000
    int raw_packet_buffer_remaining_size;
} AVFormatContext;

其中最重要的結構是

AVIOContext *pb //輸入資料的緩衝
unsigned int nb_streams//視音訊的個數
AVStream **streams//視音訊流
char filename[1024]://檔名
int_64 duration:時長(單位:微秒us,轉換為秒需要除以100000)
int bit_rate:位元率(單位bps,轉換為kbps需要除以1000)
AVDictionary *metadata//元素據

影片的時長可以轉換HH::MM::SS的形式,示例程式碼如下:

AVFormatContext *pFormatCtx;
CString timelong;
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);

影片的原資料(metadata)資訊可以透過AVDictionary獲取。後設資料儲存在AVDictionaryEntry結構體中,如下所示

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

每一條後設資料分為key和value兩個屬性
在ffmpeg中透過av_dict_get()函式獲得影片的原資料。
.下列程式碼顯示獲取後設資料並存入meta字串變數的過程,注意每一條key和value之間有一個"\t",value之後有一個"\r\n"

//MetaData------------------------------------------------------------
//從AVDictionary獲得
//需要用到AVDictionaryEntry物件
//CString author,copyright,description;
CString meta=NULL,key,value;
AVDictionaryEntry *m = NULL;
//不用一個一個找出來
/*	m=av_dict_get(pFormatCtx->metadata,"author",m,0);
author.Format("作者:%s",m->value);
m=av_dict_get(pFormatCtx->metadata,"copyright",m,0);
copyright.Format("版權:%s",m->value);
m=av_dict_get(pFormatCtx->metadata,"description",m,0);
description.Format("描述:%s",m->value);
*/
//使用迴圈讀出
//(需要讀取的資料,欄位名稱,前一條欄位(迴圈時使用),引數)
while(m=av_dict_get(pFormatCtx->metadata,"",m,AV_DICT_IGNORE_SUFFIX)){
	key.Format(m->key);
	value.Format(m->value);
	meta+=key+"\t:"+value+"\r\n" ;
}