1. 程式人生 > >FFmpeg:AVFormatContext結構體分析

FFmpeg:AVFormatContext結構體分析

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;