注:写了一系列的结构体的分析的文章,在这里列一个列表:
FFMPEG结构体分析:AVFrame
FFMPEG结构体分析:AVFormatContext
FFMPEG结构体分析:AVCodecContext
FFMPEG结构体分析:AVIOContext
FFMPEG结构体分析:AVCodec
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket
FFMPEG有几个最重要的结构体,包含了解协议,解封装,解码操作,此前已经进行过分析:
FFMPEG中最关键的结构体之间的关系
在此不再详述,其中AVIOContext是FFMPEG管理输入输出数据的结构体。本文将会详细分析一下该结构体里每个变量的含义和作用。
首先看一下结构体的定义(位于avio.h):
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
typedef struct {
-
-
-
-
-
-
-
-
-
-
-
-
-
AVClass *av_class;
-
unsigned char *buffer;
-
int buffer_size;
-
unsigned char *buf_ptr;
-
unsigned char *buf_end;
-
-
-
-
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);
-
int64_t pos;
-
int must_flush;
-
int eof_reached;
-
int write_flag;
-
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;
-
-
-
-
int (*read_pause)(void *opaque, int pause);
-
-
-
-
-
-
int64_t (*read_seek)(void *opaque, int stream_index,
-
int64_t timestamp, int flags);
-
-
-
-
int seekable;
-
-
-
-
-
-
int64_t maxsize;
-
} AVIOContext;
AVIOContext中有以下几个变量比较重要:
unsigned char *buffer:缓存开始位置
int buffer_size:缓存大小(默认32768)
unsigned char *buf_ptr:当前指针读取到的位置
unsigned char *buf_end:缓存结束的位置
void *opaque:URLContext结构体
在解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。
其中opaque指向了URLContext。注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。从FFMPEG源代码中翻出的定义如下所示:
-
typedef struct URLContext {
-
const AVClass *av_class;
-
struct URLProtocol *prot;
-
int flags;
-
int is_streamed;
-
int max_packet_size;
-
void *priv_data;
-
char *filename;
-
int is_connected;
-
AVIOInterruptCB interrupt_callback;
-
} URLContext;
URLContext结构体中还有一个结构体URLProtocol。注:每种协议(rtp,rtmp,file等)对应一个URLProtocol。这个结构体也不在FFMPEG提供的头文件中。从FFMPEG源代码中翻出其的定义:
-
typedef struct URLProtocol {
-
const char *name;
-
int (*url_open)(URLContext *h, const char *url, int flags);
-
int (*url_read)(URLContext *h, unsigned char *buf, int size);
-
int (*url_write)(URLContext *h, const unsigned char *buf, int size);
-
int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
-
int (*url_close)(URLContext *h);
-
struct URLProtocol *next;
-
int (*url_read_pause)(URLContext *h, int pause);
-
int64_t (*url_read_seek)(URLContext *h, int stream_index,
-
int64_t timestamp, int flags);
-
int (*url_get_file_handle)(URLContext *h);
-
int priv_data_size;
-
const AVClass *priv_data_class;
-
int flags;
-
int (*url_check)(URLContext *h, int mask);
-
} URLProtocol;
在这个结构体中,除了一些回调函数接口之外,有一个变量const char *name,该变量存储了协议的名称。每一种输入协议都对应这样一个结构体。
比如说,文件协议中代码如下(file.c):
-
URLProtocol ff_file_protocol = {
-
.name = "file",
-
.url_open = file_open,
-
.url_read = file_read,
-
.url_write = file_write,
-
.url_seek = file_seek,
-
.url_close = file_close,
-
.url_get_file_handle = file_get_handle,
-
.url_check = file_check,
-
};
libRTMP中代码如下(libRTMP.c):
-
URLProtocol ff_rtmp_protocol = {
-
.name = "rtmp",
-
.url_open = rtmp_open,
-
.url_read = rtmp_read,
-
.url_write = rtmp_write,
-
.url_close = rtmp_close,
-
.url_read_pause = rtmp_read_pause,
-
.url_read_seek = rtmp_read_seek,
-
.url_get_file_handle = rtmp_get_file_handle,
-
.priv_data_size = sizeof(RTMP),
-
.flags = URL_PROTOCOL_FLAG_NETWORK,
-
};
udp协议代码如下(udp.c):
-
URLProtocol ff_udp_protocol = {
-
.name = "udp",
-
.url_open = udp_open,
-
.url_read = udp_read,
-
.url_write = udp_write,
-
.url_close = udp_close,
-
.url_get_file_handle = udp_get_file_handle,
-
.priv_data_size = sizeof(UDPContext),
-
.flags = URL_PROTOCOL_FLAG_NETWORK,
-
};
等号右边的函数是完成具体读写功能的函数。可以看一下file协议的几个函数(其实就是读文件,写文件这样的操作)(file.c):
-
-
-
-
-
-
-
-
static int file_read(URLContext *h, unsigned char *buf, int size)
-
{
-
int fd = (intptr_t) h->priv_data;
-
int r = read(fd, buf, size);
-
return (-1 == r)?AVERROR(errno):r;
-
}
-
-
static int file_write(URLContext *h, const unsigned char *buf, int size)
-
{
-
int fd = (intptr_t) h->priv_data;
-
int r = write(fd, buf, size);
-
return (-1 == r)?AVERROR(errno):r;
-
}
-
-
static int file_get_handle(URLContext *h)
-
{
-
return (intptr_t) h->priv_data;
-
}
-
-
static int file_check(URLContext *h, int mask)
-
{
-
struct stat st;
-
int ret = stat(h->filename, &st);
-
if (ret < 0)
-
return AVERROR(errno);
-
-
ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
-
ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
-
-
return ret;
-
}
-
-
#if CONFIG_FILE_PROTOCOL
-
-
static int file_open(URLContext *h, const char *filename, int flags)
-
{
-
int access;
-
int fd;
-
-
av_strstart(filename, "file:", &filename);
-
-
if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
-
access = O_CREAT | O_TRUNC | O_RDWR;
-
} else if (flags & AVIO_FLAG_WRITE) {
-
access = O_CREAT | O_TRUNC | O_WRONLY;
-
} else {
-
access = O_RDONLY;
-
}
-
#ifdef O_BINARY
-
access |= O_BINARY;
-
#endif
-
fd = open(filename, access, 0666);
-
if (fd == -1)
-
return AVERROR(errno);
-
h->priv_data = (void *) (intptr_t) fd;
-
return 0;
-
}
-
-
-
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
-
{
-
int fd = (intptr_t) h->priv_data;
-
if (whence == AVSEEK_SIZE) {
-
struct stat st;
-
int ret = fstat(fd, &st);
-
return ret < 0 ? AVERROR(errno) : st.st_size;
-
}
-
return lseek(fd, pos, whence);
-
}
-
-
static int file_close(URLContext *h)
-
{
-
int fd = (intptr_t) h->priv_data;
-
return close(fd);
-
}