FFmpeg:AVFormatContext結構體分析
阿新 • • 發佈:2019-01-29
FFmpeg: AVFormatContext結構體解析
AVFormatContext
AVFormatContext
是API中直接接觸到的結構體,位於avformat.h中,是音視訊資料,也就是音視訊檔案(通常接觸到的mp3/mp4等檔案)的一種抽象和封裝,該檔案中包含了多路流,包括音訊流、視訊流、字幕流等。該結構體的使用,貫穿了ffmpeg使用的整個流程,現在資料為王,不是沒有道理的。
術語
- 流(stream),一種用於形容音視訊資料的名詞。音視訊播放中,資料都是通過迴圈,不斷處理直到結束,跟水流及其相似。
結構定義及成員解讀
typedef struct AVFormatContext {
/**
* A class for logging and @ref avoptions. Set by avformat_alloc_context().
* Exports (de)muxer private options if they exist.
*/
const AVClass *av_class;
/**
* 輸入容器格式.
* 用於分流,通過avformat_open_input()設定.
*/
struct AVInputFormat *iformat;
/**
* 輸出容器格式。
*
* 用於混流,必須在avformat_write_header()呼叫前設定.
*/
struct AVOutputFormat *oformat;
/**
* Format private data. This is an AVOptions-enabled struct
* if and only if iformat/oformat.priv_class is not NULL.
*
* - muxing: set by avformat_write_header()
* - demuxing: set by avformat_open_input()
*/
void *priv_data;
/**
* I/O 上下文.
*
* - 分流: 在avformat_open_input() 之前設定(使用者必須手動釋放)或者通過avformat_open_input()
* 自動設定.
* - 混流: 在avformat_write_header()之前設定.使用者必須注意及時關閉/釋放IO上下文。
*
* 不要設定AVFMT_NOFILE標誌給iformat/oformat.flags。因為這種情況下,該值為NULL,混/分流器會通
* 過其它方式處理I/O。
*/
AVIOContext *pb;
/* 後面都是流資訊 */
/**
* 訊號流屬性標誌,AVFMTCTX_*的組合.
* 通過libavformat設定.
*/
int ctx_flags;
/**
* AVFormatContext.streams中的元素數量,其實就是流的總數.
*
* 通過avformat_new_stream()設定, 禁止其它程式碼修改。
*/
unsigned int nb_streams;
/**
* 媒體中減重,所有流的列表,新的流由avformat_new_stream()建立。
*
* - 分流: 流在avformat_open_input()函式中由libavformat建立。如果AVFMTCTX_NOHEANDER被設定
* 帶ctx_flags中,新的流可能出現在av_read_frame()中。
* - 混流: 流在avformat_write_header()函式之前被使用者建立
*
* 在avformat_free_context()函式中,通過libavformat釋放。
*/
AVStream **streams;
/**
* 輸入輸出檔名
*
* - 分流: 通過avformat_open_input()設定。
* - 混流: 在avformat_write_header()呼叫前,可以被使用者設定。
*/
char filename[1024];
/**
* 元件第一幀的位置,用AV_TIME_BASE分數秒錶示。禁止直接設定,由AVStream的值推導而來。
*
* - 分流:通過libavformat設定.
*/
int64_t start_time;
/**
* 留的時長,以AV_TIME_BASE分數秒為單位。如果您不知道任何單個流的持續時間,也不設定其中的任何一
* 個,請僅設定此值。 如果沒有設定,該值可以被AVStream推匯出來
*
* 只用於分流操作,通過libavformat設定。
*/
int64_t duration;
/**
* 總流的位元率以bit/s為單位,如果流不可用,該值為0。如果流檔案大小和時長已知,不要直接設定它,
* FFmpeg會自動計算。
*/
int64_t bit_rate;
unsigned int packet_size;
int max_delay;
/**
* 修改分/混流器操作的標誌,一個AVFMT_FLAG_*的組合。
* 在avformat_open_input() / avformat_write_header()呼叫之前使用者自行設定.
*/
int flags;
#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_NOBUFFER 0x0040 ///< Do not buffer frames when possible
#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_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet.
/**
* 混流時,儘量避免將隨機/不可控的資料寫入輸出中,包括隨機IDs,實時時間戳/日期,混流器版本等等。
*
* 該標記主要用於測試
*/
#define AVFMT_FLAG_BITEXACT 0x0400
#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)
#if FF_API_LAVF_KEEPSIDE_FLAG
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Don't merge side data but keep it separate. Deprecated, will be the default.
#endif
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Wait for packet data before writing a header, and add bitstream filters as requested by the muxer
/**
* 從指定容器格式的輸入中讀取最大資料的大小。
* 僅用於分流操作,使用者可以在avformat_open_input()函式前設定。
*/
int64_t probesize;
/**
* 從指定容器格式的輸入中讀取的最大資料時長(以AV_TIME_BASE為單位)。
* 僅用於分流操作,在avformat_find_stream_info()呼叫前設定。為0時,讓avformat自動選擇。
*/
int64_t max_analyze_duration;
const uint8_t *key;
int keylen;
unsigned int nb_programs;
AVProgram **programs;
/**
* 強制視訊codec_id.
* 分流操作: 使用者設定。
*/
enum AVCodecID video_codec_id;
/**
* 強制音訊codec_id.
* 分流操作: 使用者設定。
*/
enum AVCodecID audio_codec_id;
/**
* 強制字幕codec_id.
* 分流操作: 使用者設定。
*/
enum AVCodecID subtitle_codec_id;
/**
* 每個索引使用的記憶體最大值(以位元組為單位)。
* 如果索引超出記憶體限制,專案會被丟棄以保持較小的記憶體佔用。這回導致seeking較慢和不準確(取決於分流
* 器)
* 完全記憶體索引是強制性的分解器將忽略這一點。
* - 混流操作: 不實用
* - 分流操作: 由使用者設定
*/
unsigned int max_index_size;
/**
* 從裝置獲取的實時幀緩衝的最大記憶體大小(以位元組為單位)
*/
unsigned int max_picture_buffer;
/**
* AVChapter陣列中的章節數量。
* 混流時,章節資訊通暢會寫在檔案頭中,所以nb_chapters應該在寫檔案頭之前被初始化。一些混流器(例如
* mov、mkv)可以將章節寫在預告中。為了在預告中撰寫章節,在write_header呼叫時nb_chapters必須為
* 並且在write_trailer被呼叫時為非0數。
* - 混流操作: 使用者設定
* - 分流操作: libavformat設定
*/
unsigned int nb_chapters;
AVChapter **chapters;
/**
* 適用於整個檔案的元資料。
*
* - 分流操作: libavformat在avformat_open_input()函式中設定。
* - 混流操作: 呼叫者可以在avformat_write_header()函式呼叫前設定。
*
* 通過libavformat在函式avformat_free_context()中釋放。
*/
AVDictionary *metadata;
/**
* 從Unix紀元(1970年1月1日00:00)開始,以真實世界時間開始流的開始時間,以微秒為單位。 即,流在現
* 實世界被使用的pts=0時間。
* - 混流操作: 在avformat_write_header()呼叫前被呼叫者設定。如果設定為0或AV_NOPTS_VALUE,則
* 將使用當前時間(wall-time)。
* - 分流操作: 由libavformat設定. 如果AV_NOPTS_VALUE未知,注意,一定數量的幀被獲取後,該值可能
* 變得已知。
*/
int64_t start_time_realtime;
/**
* 用於確定avformat_find_stream_info()中幀率的幀數。
* 僅用於分流,在avformat_find_stream_info()呼叫前由呼叫者設定
*/
int fps_probe_size;
/**
* 錯誤識別; 較高的值將檢測到更多的錯誤,但可能會錯誤檢測一些或多或少有效的部分作為錯誤。 在
* avformat_open_input()之前由呼叫方設定的僅用於解分流。
*/
int error_recognition;
/**
* I/O層自定義中斷回撥函式。
*
* 分流操作: avformat_open_input()呼叫前由使用者設定.
* 混流操作: avformat_write_header()呼叫前由使用者設定(主要用於AVFMT_NOFILE 格式)。如果用它來
* 開啟檔案,該回調也會傳遞給avio_open2().
*/
AVIOInterruptCB interrupt_callback;
/**
* 啟用debug標誌。
*/
int debug;
#define FF_FDEBUG_TS 0x0001
/**
* Maximum buffering duration for interleaving.
*
* To ensure all the streams are interleaved correctly,
* av_interleaved_write_frame() will wait until it has at least one packet
* for each stream before actually writing any packets to the output file.
* When some streams are "sparse" (i.e. there are large gaps between
* successive packets), this can result in excessive buffering.
*
* This field specifies the maximum difference between the timestamps of the
* first and the last packet in the muxing queue, above which libavformat
* will output a packet regardless of whether it has queued a packet for all
* the streams.
*
* Muxing only, set by the caller before avformat_write_header().
*/
int64_t max_interleave_delta;
/**
* 允許非標準和實驗性擴充套件
* @see AVCodecContext.strict_std_compliance
*/
int strict_std_compliance;
/**
* 供使用者檢測檔案上發生事件的標誌。事件處理後,使用者必須清除標誌。AVFMT_EVENT_FLAG_ *的組合。
*/
int event_flags;
#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
/**
* 在等待第一個時間戳時要讀取的最大資料包數。僅用於解碼。
*/
int max_ts_probe;
/**
* 避免混流過程中的負面時間戳。 AVFMT_AVOID_NEG_TS_ *常量中的任何值。 請注意,這隻適用於使用
* av_interleaved_write_frame。 (interleave_packet_per_dts正在使用中)
* - 混流: 使用者設定
* - 分流: 不使用
*/
int avoid_negative_ts;
#define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format
#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0
/**
* 傳輸流id。
* 這將被移入分流器的私有選項。 因此沒有API / ABI相容性
*/
int ts_id;
/**
* 音訊預載入以微秒為單位。 請注意,並非所有格式都支援此功能,如果在不支援的情況下使用它,則可能會發
* 生不可預知的情況。
* - 編碼: 使用者設定
* - 解碼: 不使用
*/
int audio_preload;
/**
* 最大塊時間(以微秒為單位)。 請注意,並非所有格式都支援此功能,如果在不支援的情況下使用它,則可能
* 會發生不可預知的情況。
* - 編碼: 使用者設定
* - 解碼: 不使用
*/
int max_chunk_duration;
/**
* 最大塊大小(以位元組為單位)。注意,並非所有格式都支援此功能,如果在不支援的情況下使用它,可能會發
* 生不可預知的情況。
* - 編碼: 使用者設定
* - 解碼: 不使用
*/
int max_chunk_size;
/**
* 強制使用wallclock時間戳作為pts / dts資料包在B幀存在的情況下存在未定義的結果。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int use_wallclock_as_timestamps;
/**
* avio標誌,用於強制使用AVIO_FLAG_DIRECT。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int avio_flags;
/**
* 時長欄位可以通過各種方式進行計算,並且可以使用此欄位瞭解時長是如何計算的。
* - 編碼: 不使用
* - 解碼: 使用者讀取
*/
enum AVDurationEstimationMethod duration_estimation_method;
/**
* 開啟流時跳過初始位元組
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int64_t skip_initial_bytes;
/**
* 正確的單個時間戳溢位
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
unsigned int correct_ts_overflow;
/**
* 強制seeking到任意幀(即使沒有關鍵幀)
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int seek2any;
/**
* 在每個資料包之後重新整理I / O上下文。
* - 編碼: 使用者設定
* - 解碼: 不使用
*/
int flush_packets;
/**
* 格式探測分數。 最高分是AVPROBE_SCORE_MAX,當分流器探測格式時設定它。
* - 編碼: 不使用
* - 解碼: avformat設定,使用者讀取
*/
int probe_score;
/**
* 要最大限度地讀取以識別格式的位元組數。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int format_probesize;
/**
* ',' 分割的支援的解碼器劉表,如果值為NULL,表示支援所有解碼器。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
char *codec_whitelist;
/**
* ',' 分割的支援的分流器列表,如果值為NULL,所有分流器都支援。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
char *format_whitelist;
/**
* libavformat內部使用的不透明欄位。 不得以任何方式訪問。
*/
AVFormatInternal *internal;
/**
* IO重定位標誌。
* 當基礎IO上下文讀指標重新定位時,例如在執行基於位元組的查詢時,這由avformat設定。 分流器可以使用
* 標誌來檢測這種變化。
*/
int io_repositioned;
/**
* 強制視訊解碼器。強制資料解碼器。這允許使用強制指定的解碼器,即使有多個相同的codec_id.
* 分流: 使用者設定
*/
AVCodec *video_codec;
/**
* 強制音訊解碼器。強制資料解碼器。這允許使用強制指定的解碼器,即使有多個相同的codec_id.
* 分流: 使用者設定
*/
AVCodec *audio_codec;
/**
* 強制資料解碼器。這允許使用強制指定的解碼器,即使有多個相同的codec_id.
* 分流: 使用者設定
*/
AVCodec *subtitle_codec;
/**
* 強制資料解碼器。這允許使用強制指定的解碼器,即使有多個相同的codec_id.
* 分流: 使用者設定
*/
AVCodec *data_codec;
/**
* 在原資料頭中,充當填充(分割)的位元組數
* 分流: 不使用
* 混流: 使用者可以通過av_format_set_metadata_header_padding設定.
*/
int metadata_header_padding;
/**
* 使用者資料,這是使用者的私有資料空間。
*/
void *opaque;
/**
* 裝置用應用通訊的回撥。
*/
av_format_control_message control_message_cb;
/**
* 輸出時移,以微妙為單位。
* 混流: 使用者設定
*/
int64_t output_ts_offset;
/**
* 轉儲格式分隔符。可以是", " 或者 "\n" 等
* - 混流: 使用者設定
* - 分流: 使用者設定
*/
uint8_t *dump_separator;
/**
* 強制資料codec_id.
* 分流操作: 使用者設定
*/
enum AVCodecID data_codec_id;
#if FF_API_OLD_OPEN_CALLBACKS
/**
* Called to open further IO contexts when needed for demuxing.
*
* This can be set by the user application to perform security checks on
* the URLs before opening them.
* The function should behave like avio_open2(), AVFormatContext is provided
* as contextual information and to reach AVFormatContext.opaque.
*
* If NULL then some simple checks are used together with avio_open2().
*
* Must not be accessed directly from outside avformat.
* @See av_format_set_open_cb()
*
* Demuxing: Set by user.
*
* @deprecated Use io_open and io_close.
*/
attribute_deprecated
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
#endif
/**
* ',' 符號分割的支援協議列表separated list of allowed protocols.
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
char *protocol_whitelist;
/*
* A callback for opening new IO streams.
*
* Whenever a muxer or a demuxer needs to open an IO stream (typically from
* avformat_open_input() for demuxers, but for certain formats can happen at
* other times as well), it will call this callback to obtain an IO context.
*
* @param s the format context
* @param pb on success, the newly opened IO context should be returned here
* @param url the url to open
* @param flags a combination of AVIO_FLAG_*
* @param options a dictionary of additional options, with the same
* semantics as in avio_open2()
* @return 0 on success, a negative AVERROR code on failure
*
* @note Certain muxers and demuxers do nesting, i.e. they open one or more
* additional internal format contexts. Thus the AVFormatContext pointer
* passed to this callback may be different from the one facing the caller.
* It will, however, have the same 'opaque' field.
*/
int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
int flags, AVDictionary **options);
/**
* 將AVFormateContext.io_open()開啟流關閉的回撥。
*/
void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
/**
* ',' 符分割的不支援協議列表。
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
char *protocol_blacklist;
/**
* 最大streams數量
* - 編碼: 不使用
* - 解碼: 使用者設定
*/
int max_streams;
} AVFormatContext;