- 所谓的自定义IO就是实现复用结构体
AVFormatContext
的pb
字段,这个字段的结果类型是AVIOContext
,可以通过avio_alloc_context
函数构造一个此结构体 - 如果是要读文件需要实现函数指针
read_packet
和seek
,如果是要写文件需要实现函数指针write_packet
和seek
buffer
和buffer_size
必须是有效的,如果是写文件,在写之前数据存储在此buffer中。如果是读文件,会预先读取到此buffer中。所以此buffer的大小应当大于我们一次性读写的大小。opaque
是用户自定义数据结构,read_packet
、write_packet
和seek
都会透传此数据结构给回用户。seek
函数指针中的whence
参数除了支持正常的SEEK_SET
、SEEK_CUR
、SEEK_END
还支持FFMpeg自定义的类型AVSEEK_SIZE
、AVSEEK_FORCE
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))
{
AVIOContext *s = av_malloc(sizeof(AVIOContext));
if (!s)
return NULL;
ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
read_packet, write_packet, seek);
return s;
}
/*
* 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: | | |
* +-------------+----------------------------------------------+
*
*/
bool InitAVFormatContext()
{
constexpr int32_t buffer_size = 16384;
uint8_t* buffer = new[buffer_size];
AVFormatContext* fmt = avformat_alloc_context();
fmt.pb = avio_alloc_context(buffer, buffer_size, 0, nullptr, [](void *opaque, uint8_t *buf, int buf_size){
return -1;
}, [](void *opaque, uint8_t *buf, int buf_size){
return -1;
}, [](void *opaque, int64_t offset, int whence){
return -1;
});
int32_t ret = avformat_open_input(&ctx->format_ctx, nullptr, nullptr, nullptr);
if (ret < 0) return false;
return true;
}