AVIOContext是FFMPEG管理输入输出数据的结构体。
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源代码中翻出的定义如下所示:
1. typedef struct URLContext {
2. const AVClass *av_class; ///< information for av_log(). Set by url_open().
3. struct URLProtocol *prot;
4. int flags;
5. int is_streamed; /**< true if streamed (no seek possible), default = false */
6. int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
7. void *priv_data;
8. char *filename; /**< specified URL */
9. int is_connected;
10. AVIOInterruptCB interrupt_callback;
11. } URLContext;
URLContext结构体中还有一个结构体URLProtocol。注:每种协议(rtp,rtmp,file等)对应一个URLProtocol。这个结构体也不在FFMPEG提供的头文件中。从FFMPEG源代码中翻出其的定义:
1. typedef struct URLProtocol {
2. const char *name;
3. int (*url_open)(URLContext *h, const char *url, int flags);
4. int (*url_read)(URLContext *h, unsigned char *buf, int size);
5. int (*url_write)(URLContext *h, const unsigned char *buf, int size);
6. int whence);
7. int (*url_close)(URLContext *h);
8. struct URLProtocol *next;
9. int (*url_read_pause)(URLContext *h, int pause);
10. int stream_index,
11. int flags);
12. int (*url_get_file_handle)(URLContext *h);
13. int priv_data_size;
14. const AVClass *priv_data_class;
15. int flags;
16. int (*url_check)(URLContext *h, int mask);
17. } URLProtocol;
在这个结构体中,除了一些回调函数接口之外,有一个变量const char *name,该变量存储了协议的名称。每一种输入协议都对应这样一个结构体。
比如说,文件协议中代码如下(file.c):
1. URLProtocol ff_file_protocol = {
2. "file",
3. .url_open = file_open,
4. .url_read = file_read,
5. .url_write = file_write,
6. .url_seek = file_seek,
7. .url_close = file_close,
8. .url_get_file_handle = file_get_handle,
9. .url_check = file_check,
10. };
libRTMP中代码如下(libRTMP.c):
1. URLProtocol ff_rtmp_protocol = {
2. "rtmp",
3. .url_open = rtmp_open,
4. .url_read = rtmp_read,
5. .url_write = rtmp_write,
6. .url_close = rtmp_close,
7. .url_read_pause = rtmp_read_pause,
8. .url_read_seek = rtmp_read_seek,
9. .url_get_file_handle = rtmp_get_file_handle,
10. sizeof(RTMP),
11. .flags = URL_PROTOCOL_FLAG_NETWORK,
12. };
udp协议代码如下(udp.c):
1. URLProtocol ff_udp_protocol = {
2. "udp",
3. .url_open = udp_open,
4. .url_read = udp_read,
5. .url_write = udp_write,
6. .url_close = udp_close,
7. .url_get_file_handle = udp_get_file_handle,
8. sizeof(UDPContext),
9. .flags = URL_PROTOCOL_FLAG_NETWORK,
10. };
等号右边的函数是完成具体读写功能的函数。可以看一下file协议的几个函数(其实就是读文件,写文件这样的操作)(file.c):
1. /*
2. *雷霄骅
3. *leixiaohua1020@126.com
4. *中国传媒大学/数字电视技术
5. */
6. /* standard file protocol */
7.
8. static int file_read(URLContext *h, unsigned char *buf, int size)
9. {
10. int fd = (intptr_t) h->priv_data;
11. int r = read(fd, buf, size);
12. return (-1 == r)?AVERROR(errno):r;
13. }
14.
15. static int file_write(URLContext *h, const unsigned char *buf, int size)
16. {
17. int fd = (intptr_t) h->priv_data;
18. int r = write(fd, buf, size);
19. return (-1 == r)?AVERROR(errno):r;
20. }
21.
22. static int file_get_handle(URLContext *h)
23. {
24. return (intptr_t) h->priv_data;
25. }
26.
27. static int file_check(URLContext *h, int mask)
28. {
29. struct stat st;
30. int ret = stat(h->filename, &st);
31. if (ret < 0)
32. return AVERROR(errno);
33.
34. ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
35. ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
36.
37. return ret;
38. }
39.
40. #if CONFIG_FILE_PROTOCOL
41.
42. static int file_open(URLContext *h, const char *filename, int flags)
43. {
44. int access;
45. int fd;
46.
47. "file:", &filename);
48.
49. if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
50. access = O_CREAT | O_TRUNC | O_RDWR;
51. else if (flags & AVIO_FLAG_WRITE) {
52. access = O_CREAT | O_TRUNC | O_WRONLY;
53. else {
54. access = O_RDONLY;
55. }
56. #ifdef O_BINARY
57. access |= O_BINARY;
58. #endif
59. fd = open(filename, access, 0666);
60. if (fd == -1)
61. return AVERROR(errno);
62. void *) (intptr_t) fd;
63. return 0;
64. }
65.
66. /* XXX: use llseek */
67. static int64_t file_seek(URLContext *h, int64_t pos, int whence)
68. {
69. int fd = (intptr_t) h->priv_data;
70. if (whence == AVSEEK_SIZE) {
71. struct stat st;
72. int ret = fstat(fd, &st);
73. return ret < 0 ? AVERROR(errno) : st.st_size;
74. }
75. return lseek(fd, pos, whence);
76. }
77.
78. static int file_close(URLContext *h)
79. {
80. int fd = (intptr_t) h->priv_data;
81. return close(fd);
82. }