ffmpeg中为方便对资源进行访问,定义了两个结构体,URLContext中是对具体资源文件进行操作的上下文,URLProtocol则是在将资源进行分类的基础上,对某一类资源操作的函数集,熟悉Linux设备驱动程序的话,很容易联想到file_operations结构体

typedef struct URLContext
{
const AVClass *av_class; /**< information for av_log(). Set by url_open(). */
struct URLProtocol *prot;
void *priv_data;
char *filename; /**< specified URL */
int flags;
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
int is_streamed; /**< true if streamed (no seek possible), default = false */
int is_connected;
AVIOInterruptCB interrupt_callback;
int64_t rw_timeout; /**< maximum time to wait for (network) read/write operation completion, in mcs */
}
URLContext; typedef struct URLProtocol
{
const char *name;
int (*url_open)( URLContext *h, const char *url, int flags);
/**
* This callback is to be used by protocols which open further nested
* protocols. options are then to be passed to ffurl_open()/ffurl_connect()
* for those nested protocols.
*/
int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options); /**
* Read data from the protocol.
* If data is immediately available (even less than size), EOF is
* reached or an error occurs (including EINTR), return immediately.
* Otherwise:
* In non-blocking mode, return AVERROR(EAGAIN) immediately.
* In blocking mode, wait for data/EOF/error with a short timeout (0.1s),
* and return AVERROR(EAGAIN) on timeout.
* Checking interrupt_callback, looping on EINTR and EAGAIN and until
* enough data has been read is left to the calling function; see
* retry_transfer_wrapper in avio.c.
*/
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 (*url_get_multi_file_handle)(URLContext *h, int **handles,
int *numhandles);
int (*url_shutdown)(URLContext *h, int flags);
int priv_data_size;
const AVClass *priv_data_class;
int flags;
int (*url_check)(URLContext *h, int mask);
}
URLProtocol; 在代码中搜索url_open,很容易能够找到ffmpeg中支持的几个协议: URLProtocol ff_bluray_protocol =
{
.name = "bluray",
.url_close = bluray_close,
.url_open = bluray_open,
.url_read = bluray_read,
.url_seek = bluray_seek,
.priv_data_size = sizeof(BlurayContext),
.priv_data_class = &bluray_context_class,
}; URLProtocol ff_data_protocol =
{
.name = "data",
.url_open = data_open,
.url_close = data_close,
.url_read = data_read,
.priv_data_size = sizeof(DataContext),
}; 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,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &file_class,
}; URLProtocol ff_pipe_protocol =
{
.name = "pipe",
.url_open = pipe_open,
.url_read = file_read,
.url_write = file_write,
.url_get_file_handle = file_get_handle,
.url_check = file_check,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &pipe_class,
}; URLProtocol ff_ftp_protocol =
{
.name = "ftp",
.url_open = ftp_open,
.url_read = ftp_read,
.url_write = ftp_write,
.url_seek = ftp_seek,
.url_close = ftp_close,
.url_get_file_handle = ftp_get_file_handle,
.url_shutdown = ftp_shutdown,
.priv_data_size = sizeof(FTPContext),
.priv_data_class = &ftp_context_class,
.flags = URL_PROTOCOL_FLAG_NETWORK,
}; URLProtocol ff_hls_protocol =
{
.name = "hls",
.url_open = hls_open,
.url_read = hls_read,
.url_close = hls_close,
.flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,
.priv_data_size = sizeof(HLSContext),
}; URLProtocol ff_httpproxy_protocol =
{
.name = "httpproxy",
.url_open = http_proxy_open,
.url_read = http_buf_read,
.url_write = http_proxy_write,
.url_close = http_proxy_close,
.url_get_file_handle = http_get_file_handle,
.priv_data_size = sizeof(HTTPContext),
.flags = URL_PROTOCOL_FLAG_NETWORK,
}; ... 还有很多协议,不全部列出了,例如tcp, udp, ... 支持这些协议而定义的结构体在av_register_all()函数被调用时而注册,例如: REGISTER_PROTOCOL(FILE, file); #define REGISTER_PROTOCOL(X, x) \
{ \
extern URLProtocol ff_##x##_protocol; \
if (CONFIG_##X##_PROTOCOL) \
ffurl_register_protocol(&ff_##x##_protocol); \
} ffurl_register_protocol(&ff_file_protocol); int ffurl_register_protocol(URLProtocol *protocol)
{
URLProtocol **p;
p = &first_protocol;
while (*p != NULL)
p = &(*p)->next;
*p = protocol;
protocol->next = NULL;
return ;
} 注册到以static URLProtocol *first_protocol = NULL;为头的一个链表中,每一个协议结构体是链表中的一项; 以avio_open2为例: int avio_open2(AVIOContext **s, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options)
{
URLContext *h;
int err; err = ffurl_open(&h, filename, flags, int_cb, options);
if (err < )
return err; err = ffio_fdopen(s, h);
if (err < )
{
ffurl_close(h);
return err;
} return ;
} ffurl_open--->ffurl_alloc--->static struct URLProtocol *url_find_protocol(const char *filename) url_find_protocol函数会根据filename判断协议,这个函数的定义没太看懂,但是其作用,无非是先判断具体的协议,然后根据判读出来的协议,调用 URLProtocol *ffurl_protocol_next(URLProtocol *prev)
{
return prev ? prev->next : first_protocol;
} 函数,在之前注册的first_protocol链表上找到相应的协议结构体,然后返回给函数url_alloc_for_protocol,在这个函数中,则是根据判断的协议,生成URLContext结构体, uc = av_mallocz(sizeof(URLContext) + strlen(filename) + ); *puc = uc; 在ffurl_open函数中,ffurl_alloc函数返回之后,URLContext **puc结构体就已经被设置完毕,然后在ffurl_open函数中,再调用ret = ffurl_connect(*puc, options); int ffurl_connect(URLContext *uc, AVDictionary **options)
{
int err =
uc->prot->url_open2 ? uc->prot->url_open2(uc,
uc->filename,
uc->flags,
options) :
uc->prot->url_open(uc, uc->filename, uc->flags);
if (err)
return err;
uc->is_connected = ;
/* We must be careful here as ffurl_seek() could be slow,
* for example for http */
if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
if (!uc->is_streamed && ffurl_seek(uc, , SEEK_SET) < )
uc->is_streamed = ;
return ;
} prot是协议,在url_alloc_for_protocol函数中设置的:uc->prot = up; 然后url_open2, url_open都是在协议结构体中定义的函数指针,以"file"协议为例: 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,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &file_class,
}; url_open2是NULL,则调用url_open函数指针指向的函数file_open: static int file_open(URLContext *h, const char *filename, int flags)
{
FileContext *c = h->priv_data;
int access;
int fd;
struct stat st; av_strstart(filename, "file:", &filename); if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
access = O_CREAT | O_RDWR;
if (c->trunc)
access |= O_TRUNC;
} else if (flags & AVIO_FLAG_WRITE) {
access = O_CREAT | O_WRONLY;
if (c->trunc)
access |= O_TRUNC;
} else {
access = O_RDONLY;
}
#ifdef O_BINARY
access |= O_BINARY;
#endif
fd = avpriv_open(filename, access, );
if (fd == -)
return AVERROR(errno);
c->fd = fd; h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode); return ; }

http://blog.csdn.net/xiruanliuwei/article/details/24928237

最新文章

  1. HBase设计与开发性能优化(转)
  2. angularjs封装bootstrap官网的时间插件datetimepicker
  3. Android Programming: Pushing the Limits -- Chapter 6: Services and Background Tasks
  4. Leetcode 20 Valid Parentheses stack的应用
  5. VNC的安装与配置
  6. Linux软件
  7. cocos2d-x 几何绘制: DrawingPrimitives 和 CCDrawNode
  8. C++ list用法
  9. 在VS中如何用C++连接Mysql
  10. JavaScript引用类型之Array类型一
  11. lesson - 7 课程笔记 vim
  12. Linux解决MySQL-python安装失败问题
  13. Windows 记事本的 ANSI、Unicode、UTF-8 这三种编码模式有什么区别?
  14. tensorflow学习笔记2:c++程序静态链接tensorflow库加载模型文件
  15. java实现文件监控
  16. Java并发之volatile二
  17. 17中介者模式Mediator
  18. 001.hadoop及hbase部署
  19. 安装调试Installing Odoo
  20. python-property、__get__、__set__

热门文章

  1. GDB和Core Dump使用笔记
  2. js不执行的问题
  3. LeetCode OJ:Permutations(排列)
  4. Android(Lollipop/5.0) Material Design(一) 简介
  5. zoj-3963 Heap Partition(贪心+二分+树状数组)
  6. Leetcode 1013. Partition Array Into Three Parts With Equal Sum
  7. 使用iptables nat进行端口转发
  8. [Luogu4169][Violet]天使玩偶/SJY摆棋子
  9. java多线程:线程体往外抛出异常的处理机制实践
  10. Yii 一些小的问题