這個目前階段用的不多,暫時不要花費太多精力。
url 的格式不同,使用的傳輸層協議也不同。這塊看代碼還沒看到自己想的這樣。
目前看的信息是:avformatContext 的 io_open 回調函數 在默認情況下叫?io_open_default,在解復用的?avformat_open_input 方法中一定會調用。那么我們如果不使用這個默認的?io_open_default,使用自己寫的回調函數,會怎么樣呢??
還看到的信息:avformatContext的pb (? ? AVIOContext *pb;)是通過 avio_alloc_context方法創建的,那么我們如果自己創建,也可以使用avio_alloc_context創建。
AVIOContext *avio_alloc_context(unsigned char *buffer,int buffer_size,int write_flag,void *opaque,int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),int64_t (*seek)(void *opaque, int64_t offset, int whence))
調用AVFormatContext* avformatContext = nullptr;const char* url_400 = "./120/400_300_25.mp4";const char* url_1080 = "./120/1920_1080_25.mp4";int ret = avformat_open_input(&avformatContext, url_400, nullptr, nullptr);1. avformat_open_input 方法內部會重新創建 avformat_alloc_context,創建 AVFormatContext *s = avformat_alloc_context() 1.1 avformat_alloc_context內部調用 avformat_get_context_defaults
static void avformat_get_context_defaults(AVFormatContext *s)
{memset(s, 0, sizeof(AVFormatContext));s->av_class = &av_format_context_class;s->io_open = io_open_default; //注意這里,設定了 AVFormatContext 的 io_open 回調函數s->io_close = io_close_default;av_opt_set_defaults(s);
}1.2 然后調用if ((ret = init_input(s, filename, &tmp)) < 0)------> if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)------> 也就是調用 io_open_default方法,傳遞參數為 AVFormatContext,AVFormatContext->pb的地址,后面在 -------> 調用 return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);---------> 和當前關系不大 err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);---------> err = ffio_fdopen(s, h);int ffio_fdopen(AVIOContext **s, URLContext *h)------> ffio_fdopen內部做了 avio_alloc_context,創建了AVIOContext *s,也就是 avformatContext的 pb,io_open --- A callback for opening new IO streams.從這里可以看出幾點:
0. 當avformat_open_input方法中傳遞的 avformatContext是nullptr, 則:AVFormatContext->io_open = io_open_default
1.即使我們使用 AVFormatContext *avformat_alloc_context(void)創建了avfromatContext,內部也會 AVFormatContext->io_open = io_open_default
1. io_open 回調函數,在avformat_open_input方法中會調用,也就是說,默認會調用 io_open_default 函數
2. 那么我們可以自己定義 AVFormatContext->io_open的回調函數嗎?那要看 io_open_default 函數的功能是啥?
avio_alloc_context 函數說明
AVIOContext *avio_alloc_context(unsigned char *buffer,int buffer_size,int write_flag,void *opaque,int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),int64_t (*seek)(void *opaque, int64_t offset, int whence));opaque是 read_packet / write_packet 的第?個參數,指向?戶數據。
buffer和buffer_size是 read_packet / write_packet 的第?個和第三個參數,是供FFmpeg使?
的數據區。
buffer ?作FFmpeg輸?時,由?戶負責向 buffer 中填充數據,FFmpeg取?數據。
buffer ?作FFmpeg輸出時,由FFmpeg負責向 buffer 中填充數據,?戶取?數據。
write_flag是緩沖區讀寫標志,讀寫的主語是指FFmpeg。
write_flag 為1時, buffer ?于寫,即作為FFmpeg輸出。
write_flag 為0時, buffer ?于讀,即作為FFmpeg輸?。
read_packet和write_packet是函數指針,指向?戶編寫的回調函數。
seek也是函數指針,需要?持seek時使?。 可以類?fseek的機制
需要和如下的結合起來學習,
AVFormatContext 再分析零-CSDN博客
AVIOContext? 是 avformatContext 結構體中一個成員變量
是傳輸層的
中文翻譯:
*-demuxing:
要么由用戶在avformat_open_input()之前設置(然后用戶必須手動關閉它),
要么由avformat_opend_input()設置。這里應該想要表達的是如果不設置,那么avformat_opend_input方法內部會自動查找。
*-muxing:由用戶在avformat_write_header()之前設置。調用者必須負責關閉/釋放IO上下文。
*如果在中設置了AVFMT_NOFILE標志,則不要設置此字段iform/oform.flags。在這種情況下,(解)復用器將以其他方式處理I/O,此字段將為NULL。
/*** I/O context.** - demuxing: either set by the user before avformat_open_input() (then* the user must close it manually) or set by avformat_open_input().* - muxing: set by the user before avformat_write_header(). The caller must* take care of closing / freeing the IO context.** Do NOT set this field if AVFMT_NOFILE flag is set in* iformat/oformat.flags. In such a case, the (de)muxer will handle* I/O in some other way and this field will be NULL.*/AVIOContext *pb;
AVIOContext 自己是一個結構體
/*** Bytestream IO Context.* New fields can be added to the end with minor version bumps.* Removal, reordering and changes to existing fields require a major* version bump.* sizeof(AVIOContext) must not be used outside libav*.** @note None of the function pointers in AVIOContext should be called* directly, they should only be set by the client application* when implementing custom I/O. Normally these are set to the* function pointers specified in avio_alloc_context()*/
typedef struct AVIOContext {/*** A class for private options.** If this AVIOContext is created by avio_open2(), av_class is set and* passes the options down to protocols.** If this AVIOContext is manually allocated, then av_class may be set by* the caller.** warning -- this field can be NULL, be sure to not pass this AVIOContext* to any av_opt_* functions in that case.*/const AVClass *av_class;/** The following shows the relationship between buffer, buf_ptr,* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing* (since AVIOContext is used for both):************************************************************************************ READING************************************************************************************ | buffer_size |* |---------------------------------------|* | |** buffer buf_ptr buf_end* +---------------+-----------------------+* |/ / / / / / / /|/ / / / / / /| |* read buffer: |/ / consumed / | to be read /| |* |/ / / / / / / /|/ / / / / / /| |* +---------------+-----------------------+** pos* +-------------------------------------------+-----------------+* input file: | | |* +-------------------------------------------+-----------------+************************************************************************************* WRITING************************************************************************************ | buffer_size |* |--------------------------------------|* | |** buf_ptr_max* buffer (buf_ptr) buf_end* +-----------------------+--------------+* |/ / / / / / / / / / / /| |* write buffer: | / / to be flushed / / | |* |/ / / / / / / / / / / /| |* +-----------------------+--------------+* buf_ptr can be in this* due to a backward seek** pos* +-------------+----------------------------------------------+* output file: | | |* +-------------+----------------------------------------------+**/unsigned char *buffer; /**< Start of the buffer. */int buffer_size; /**< Maximum buffer size */unsigned char *buf_ptr; /**< Current position in the buffer */unsigned char *buf_end; /**< End of the data, may be less thanbuffer+buffer_size if the read function returnedless data than requested, e.g. for streams whereno more data has been received yet. */void *opaque; /**< A private pointer, passed to the read/write/seek/...functions. */int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);int64_t (*seek)(void *opaque, int64_t offset, int whence);int64_t pos; /**< position in the file of the current buffer */int eof_reached; /**< true if was unable to read due to error or eof */int write_flag; /**< true if open for writing */int max_packet_size;unsigned long checksum;unsigned char *checksum_ptr;unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);int error; /**< contains the error code or 0 if no error happened *//*** Pause or resume playback for network streaming protocols - e.g. MMS.*/int (*read_pause)(void *opaque, int pause);/*** Seek to a given timestamp in stream with the specified stream_index.* Needed for some network streaming protocols which don't support seeking* to byte position.*/int64_t (*read_seek)(void *opaque, int stream_index,int64_t timestamp, int flags);/*** A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.*/int seekable;/*** max filesize, used to limit allocations* This field is internal to libavformat and access from outside is not allowed.*/int64_t maxsize;/*** avio_read and avio_write should if possible be satisfied directly* instead of going through a buffer, and avio_seek will always* call the underlying seek function directly.*/int direct;/*** Bytes read statistic* This field is internal to libavformat and access from outside is not allowed.*/int64_t bytes_read;/*** seek statistic* This field is internal to libavformat and access from outside is not allowed.*/int seek_count;/*** writeout statistic* This field is internal to libavformat and access from outside is not allowed.*/int writeout_count;/*** Original buffer size* used internally after probing and ensure seekback to reset the buffer size* This field is internal to libavformat and access from outside is not allowed.*/int orig_buffer_size;/*** Threshold to favor readahead over seek.* This is current internal only, do not use from outside.*/int short_seek_threshold;/*** ',' separated list of allowed protocols.*/const char *protocol_whitelist;/*** ',' separated list of disallowed protocols.*/const char *protocol_blacklist;/*** A callback that is used instead of write_packet.*/int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,enum AVIODataMarkerType type, int64_t time);/*** If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,* but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly* small chunks of data returned from the callback).*/int ignore_boundary_point;/*** Internal, not meant to be used from outside of AVIOContext.*/enum AVIODataMarkerType current_type;int64_t last_time;/*** A callback that is used instead of short_seek_threshold.* This is current internal only, do not use from outside.*/int (*short_seek_get)(void *opaque);int64_t written;/*** Maximum reached position before a backward seek in the write buffer,* used keeping track of already written data for a later flush.*/unsigned char *buf_ptr_max;/*** Try to buffer at least this amount of data before flushing it*/int min_packet_size;
} AVIOContext;
ffmpeg 是如何通過參數url 找到具體的 AVIOContext 的?
在解復用一個本地的mp4文件的時候,我們 是這樣調用的,傳遞的 url的值是?"./120/400_300_25.mp4"
? ? const char* url_400 = "./120/400_300_25.mp4";
? ? int ret = avformat_open_input(&avformatContext, url_400, nullptr, nullptr);