FFMPEG关键结构体——AVIOContext

一、:AVIOContext结构体

这个结构体,是FFmpeg中有关io操作的顶层结构体,是avio的核心。FFmpeg支持打开本地文件路径和流媒体协议的URL。

该结构体在libavformat/avio.h中定义

二、重要变量

①(*read_packet):读取音视频数据的函数。
②(*write_packet):写入音视频数据的函数。
③(*read_pause):暂停或恢复网络流媒体协议的播放 。

在这里插入图片描述

三、其他结构体成员解读

    unsigned char *buffer;  // buffer起始地址
    int buffer_size;        // 可以读取或者写入的最大的buffer size
    unsigned char *buf_ptr; // 当前正在读或写操作的buffer地址
    unsigned char *buf_end; // 数据结束的buffer地址,如果读取函数返回的数据小于请求数据,buf_end可能小于buffer + buffer_size
    void *opaque;  // 一个私有指针,传递给read / write / seek / 等函数
    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; // 当前buffer在文件中的位置
    int must_flush; // 如果下一个seek应该刷新,则为true
    int eof_reached; // 如果到达eof(end of file 文件尾),则为true
    int write_flag; // 如果开放写,则为true
    int (*read_pause)(void *opaque, int pause); // 暂停或恢复网络流媒体协议的播放
    int64_t (*read_seek)(void *opaque, int stream_index,
                         int64_t timestamp, int flags); // 快进到指定timestamp
    int seekable; // 如果为0,表示不可seek操作。其它值查看AVIO_SEEKABLE_XXX
    int64_t maxsize; // max filesize,用于限制分配空间大小
    int direct; // avio_seek是否直接调用底层的seek功能。
    int64_t bytes_read; // 字节读取统计数据
    int seek_count; // seek计数
    int writeout_count; // 写入次数统计
    int orig_buffer_size; // 原始buffer大小
    const char *protocol_whitelist; // 允许协议白名单,以','分隔
    const char *protocol_blacklist; // 不允许的协议黑名单,以','分隔
		// 用于替换write_packet的回调函数。
    int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
                           enum AVIODataMarkerType type, int64_t time);
} AVIOContext;

解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。

其中opaque指向了URLContext。注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。从FFMPEG源代码中翻出的定义如下所示:

四、相关函数

①avio_alloc_context()
AVIOContext的初始化函数是avio_alloc_context(),销毁的时候使用av_free()释放掉其中的缓存即可。
它的声明位于libavformat\avio.h中,如下所示。

typedef struct URLContext {
	const AVClass *av_class; ///< information for av_log(). Set by url_open().
	struct URLProtocol *prot;
	int flags;
	int is_streamed;  /**< true if streamed (no seek possible), default = false */
	int max_packet_size;  /**< if non zero, the stream is packetized with this max packet size */
	void *priv_data;
	char *filename; /**< specified URL */
	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):

/*
 *雷霄骅
 *leixiaohua1020@126.com
 *中国传媒大学/数字电视技术
 */
/* standard file protocol */
 
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;
}
 
/* XXX: use llseek */
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);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AVFilter是FFmpeg中的一个重要结构体,它代表着一个filter(过滤器),可以用于视频和音频处理。 AVFilter结构体定义在libavfilter/avfilter.h文件中,其主要成员变量包括: 1. char *name:过滤器名称,用于在命令行或脚本中标识该过滤器。 2. char *description:过滤器描述,用于在命令行或脚本中给出该过滤器的作用和功能。 3. AVFilterPad *inputs:输入端口,指向一个AVFilterPad结构体数组,代表着该过滤器的输入端口。 4. AVFilterPad *outputs:输出端口,指向一个AVFilterPad结构体数组,代表着该过滤器的输出端口。 5. AVFilterInitFunc *init:初始化函数,该函数会在过滤器被创建时调用,用于初始化过滤器的参数和状态。 6. AVFilterUninitFunc *uninit:反初始化函数,该函数会在过滤器被销毁时调用,用于清理过滤器的资源和状态。 7. AVFilterFilterFunc *filter:过滤函数,该函数会在过滤器被应用时调用,用于实现过滤器的具体功能。 8. AVFilterQueryFormatsFunc *query_formats:查询格式函数,该函数会在过滤器被创建时调用,用于查询输入输出格式,并将其保存在inputs和outputs中。 9. AVFilterFormats *formats:格式列表,代表着该过滤器支持的输入输出格式列表。 10. void *priv:私有数据,用于保存过滤器的内部状态和数据。 总之,AVFilter结构体FFmpeg中非常重要的一个结构体,它代表着一个filter(过滤器),可以用于视频和音频处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值