FFMPEG 中的avio
1.avio接口
const char *avio_find_protocol_name(const char *url); int avio_check(const char *url, int flags); int avpriv_io_move(const char *url_src, const char *url_dst); int avpriv_io_delete(const char *url); int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options); int avio_read_dir(AVIODirContext *s, AVIODirEntry **next); int avio_close_dir(AVIODirContext **s); void avio_free_directory_entry(AVIODirEntry **entry); 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)); void avio_context_free(AVIOContext **s); void avio_w8(AVIOContext *s, int b); void avio_write(AVIOContext *s, const unsigned char *buf, int size); void avio_wl64(AVIOContext *s, uint64_t val); void avio_wb64(AVIOContext *s, uint64_t val); void avio_wl32(AVIOContext *s, unsigned int val); void avio_wb32(AVIOContext *s, unsigned int val); void avio_wl24(AVIOContext *s, unsigned int val); void avio_wb24(AVIOContext *s, unsigned int val); void avio_wl16(AVIOContext *s, unsigned int val); void avio_wb16(AVIOContext *s, unsigned int val); int avio_put_str(AVIOContext *s, const char *str); int avio_put_str16le(AVIOContext *s, const char *str); int avio_put_str16be(AVIOContext *s, const char *str); void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); int64_t avio_skip(AVIOContext *s, int64_t offset); static av_always_inline int64_t avio_tell(AVIOContext *s); int64_t avio_size(AVIOContext *s); int avio_feof(AVIOContext *s); void avio_flush(AVIOContext *s); int avio_read(AVIOContext *s, unsigned char *buf, int size); int avio_read_partial(AVIOContext *s, unsigned char *buf, int size); int avio_r8 (AVIOContext *s); unsigned int avio_rl16(AVIOContext *s); unsigned int avio_rl24(AVIOContext *s); unsigned int avio_rl32(AVIOContext *s); uint64_t avio_rl64(AVIOContext *s); unsigned int avio_rb16(AVIOContext *s); unsigned int avio_rb24(AVIOContext *s); unsigned int avio_rb32(AVIOContext *s); uint64_t avio_rb64(AVIOContext *s); int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); int avio_open(AVIOContext **s, const char *url, int flags); int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options); int avio_close(AVIOContext *s); int avio_closep(AVIOContext **s); int avio_open_dyn_buf(AVIOContext **s); int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); const char *avio_enum_protocols(void **opaque, int output); int avio_pause(AVIOContext *h, int pause); int64_t avio_seek_time(AVIOContext *h, int stream_index, int64_t timestamp, int flags); int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size); int avio_accept(AVIOContext *s, AVIOContext **c); int avio_handshake(AVIOContext *c);
2.avio结构
typedef struct AVIODirEntry { char *name; /**< Filename */ int type; /**< Type of the entry */ int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise. Name can be encoded with UTF-8 even though 0 is set. */ int64_t size; /**< File size in bytes, -1 if unknown. */ int64_t modification_timestamp; /**< Time of last modification in microseconds since unix epoch, -1 if unknown. */ int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch, -1 if unknown. */ int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix epoch, -1 if unknown. */ int64_t user_id; /**< User ID of owner, -1 if unknown. */ int64_t group_id; /**< Group ID of owner, -1 if unknown. */ int64_t filemode; /**< Unix file mode, -1 if unknown. */ } AVIODirEntry; typedef struct AVIODirContext { struct URLContext *url_context; } AVIODirContext; 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 than buffer+buffer_size if the read function returned less data than requested, e.g. for streams where no 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 eof reached */ 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;
3.测试demo
#include "libavformat/avio.h" //遍历支持的protocol int show_protocols() { void *opaque = NULL; const char *name; printf("Supported file protocols:\n" "Input:\n"); while ((name = avio_enum_protocols(&opaque, 0))) printf(" %s\n", name); printf("Output:\n"); while ((name = avio_enum_protocols(&opaque, 1))) printf(" %s\n", name); return 0; } int main() { char* srcName = "src1.mp4"; char* dstName = "test.mp4"; AVIOContext* pReadCtx = NULL; AVIOContext* pWriteCtx = NULL; unsigned char buf[1024]; int nRet = 0; show_protocols(); char* protocolName = avio_find_protocol_name(srcName); printf("protocol name: %s\n", protocolName); nRet = avio_open(&pReadCtx, srcName, AVIO_FLAG_READ); nRet = avio_open(&pWriteCtx, dstName, AVIO_FLAG_WRITE); int64_t srcSize = avio_size(pReadCtx); printf("srcSize: %lld\n", srcSize); nRet = avio_read(pReadCtx, buf, 1024); avio_write(pWriteCtx, buf, 1024); nRet = avio_close(pReadCtx); nRet = avio_close(pWriteCtx); AVIOContext* pWriteOnlyBufCtx = NULL; uint8_t* pWriteBuf = NULL; uint8_t* pWriteBuf1 = NULL; nRet = avio_open_dyn_buf(&pWriteOnlyBufCtx); avio_write(pWriteOnlyBufCtx, buf, 1024); //int nSize = avio_get_dyn_buf(pWriteOnlyBufCtx, &pWriteBuf); nRet = avio_close_dyn_buf(pWriteOnlyBufCtx, &pWriteBuf1); av_free(pWriteBuf1); printf("end\n"); return 0; }
4.找文件protocol类型
//libavformat/protocols.c const URLProtocol **ffurl_get_protocols(const char *whitelist, const char *blacklist) { const URLProtocol **ret; int i, ret_idx = 0; //url_protocols数组中保存了支持的Protocol类型 ret = av_mallocz_array(FF_ARRAY_ELEMS(url_protocols), sizeof(*ret)); if (!ret) return NULL; for (i = 0; url_protocols[i]; i++) { const URLProtocol *up = url_protocols[i]; if (whitelist && *whitelist && !av_match_name(up->name, whitelist)) continue; if (blacklist && *blacklist && av_match_name(up->name, blacklist)) continue; ret[ret_idx++] = up; } return ret; } static const struct URLProtocol *url_find_protocol(const char *filename) { const URLProtocol **protocols; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); int i; if (filename[proto_len] != ':' && (strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) || is_dos_path(filename)) strcpy(proto_str, "file"); else av_strlcpy(proto_str, filename, FFMIN(proto_len + 1, sizeof(proto_str))); av_strlcpy(proto_nested, proto_str, sizeof(proto_nested)); if ((ptr = strchr(proto_nested, '+'))) *ptr = '\0'; protocols = ffurl_get_protocols(NULL, NULL); if (!protocols) return NULL; for (i = 0; protocols[i]; i++) { const URLProtocol *up = protocols[i]; if (!strcmp(proto_str, up->name)) { av_freep(&protocols); return up; } if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && !strcmp(proto_nested, up->name)) { av_freep(&protocols); return up; } } av_freep(&protocols); return NULL; }
url_protocols数组定义在libavformat/protocol_list.c中
static const URLProtocol *url_protocols[] = { &ff_async_protocol, &ff_bluray_protocol, &ff_cache_protocol, &ff_concat_protocol, &ff_crypto_protocol, &ff_data_protocol, &ff_ffrtmpcrypt_protocol, &ff_ffrtmphttp_protocol, &ff_file_protocol, &ff_ftp_protocol, &ff_gopher_protocol, &ff_hls_protocol, &ff_http_protocol, &ff_httpproxy_protocol, &ff_https_protocol, &ff_icecast_protocol, &ff_mmsh_protocol, &ff_mmst_protocol, &ff_md5_protocol, &ff_pipe_protocol, &ff_prompeg_protocol, &ff_rtmp_protocol, &ff_rtmpe_protocol, &ff_rtmps_protocol, &ff_rtmpt_protocol, &ff_rtmpte_protocol, &ff_rtmpts_protocol, &ff_rtp_protocol, &ff_srtp_protocol, &ff_subfile_protocol, &ff_tee_protocol, &ff_tcp_protocol, &ff_tls_protocol, &ff_udp_protocol, &ff_udplite_protocol, &ff_libssh_protocol, NULL };