ffmpeg-URL(转)
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
ffmpeg-URL(转)的更多相关文章
- MinGW下简单编译FFmpeg
2009.03.21补充:ffmpeg-0.5正式发布,地址为:[url]http://www.ffmpeg.org/releases/ffmpeg-0.5.tar.bz2[/url].修改了第7步, ...
- 2010_3_1最新 完整 FFMPEG 编译详解
在网上看了很多编译详解,都很零散.经过自己的编译,解决一些BUG,在此分享自己的一些经验... 话不多说了!直接上贴. 第一步:准备编译平台. 需要 一个 MinGW 和 一个 MSYS 安装包 以及 ...
- Android后台执行的定时器实现
Android后台运行定时器,方便我们运行定位跟踪等任务需求. 以下简要说明实现Android后台定时器的要点, 文章末尾能够下载到project代码,可直接编译运行. AndroidManifest ...
- ffmpeg 内存读写相关
需要的解码的视频数据在一段内存中.例如,通过其他系统送来的视频数据.同样,有的时候编码后的视频数据也未必要保存成一个文件.例如,要求将编码后的视频数据送给其他的系统进行下一步的处理.以上两种情况就要求 ...
- Linux下ffmpeg的完整安装
最近在做一个企业项目, 期间需要将用户上传的视频转成flv格式或mp4格式并用flash插件在前端播放, 我决定采用ffmpeg (http://www.ffmpeg.org/ )实现. 当然以前也用 ...
- ffmpeg 屏幕录制 so easy....
linux Linux下使用FFmpeg进行屏幕录制相对比较方便,可以使用x11grab,使用如下的命令: ffmpeg -f x11grab -s 1600x900 -r 50 -vcodec li ...
- FFmpeg中HLS文件解析源码
不少人都在找FFmpeg中是否有hls(m3u8)解析的源码,其实是有的.就是ffmpeg/libavformat/hlsproto.c,它依赖的文件也在那个目录中. 如果要是单纯想解析HLS的话,建 ...
- ffmpeg 转成MP3采样率8000
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Linux下ffmpeg的各种编解码器的安装
首先要安装各种解码器 1.lame tar -zxvf lame- cd lame- ./configure --enable-shared make make install 2.libogg ...
- ffmpeg处理RTMP流媒体的命令 发送流媒体的命令(UDP,RTP,RTMP)
将文件当做直播送至live ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName re限制输出速率,按照 ...
随机推荐
- ZOJ 3207 80ers' Memory(strcmp函数的用法)
80ers' Memory Time Limit: 1 Second Memory Limit: 32768 KB I guess most of us are so called 80er ...
- python基础之socket编程(TCP三次握手和四次挥手)
TCP协议中中的三次握手和四次挥手 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接 ...
- 伪变量foo foober是什么意思
原文: The terms foobar, foo, bar, baz and qux are sometimes used as placeholder names (also referred t ...
- 2017.10.31 Enginer+position+statement
一.The basic information Post name Engineering manager Department Engineering Post member A24645 imme ...
- main(int argc, char *argv[])详解
argc是命令行总的参数个数 argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数 命令行后面跟的用户输入的参数,比如: int main(int ar ...
- Linux SSH的命令详解[转]
http://www.linuxidc.com/Linux/2008-02/11055.htm前一阵远程维护Linux服务器,使用的是SSH,传说中的secure shell. 登陆:ssh [hos ...
- [QT] Tab键切换焦点顺序
在Qt Designer 中点击“编辑Tab顺序“按钮进入编辑Tab顺序模式,如下图: 之后界面会变成这样: 随处点击右键即可弹出菜单,选择 "制表符顺序列表..." 出现 剩下 ...
- windows 下后台启动 redis
1. 进入 DOS窗口 2. 在进入Redis的安装目录 3. 输入:redis-server --service-install redis.windows.conf --loglevel verb ...
- 【python】socket
UDP udp_server.py from datetime import datetime import socket server_address = ('localhost', 6789) m ...
- 使用阿里云Code进行版本控制并配置IDEA
1. 申请阿里code的账号,网址如下https://code.aliyun.com, 2. 申请完成之后,将账号信息发给项目负责人,由负责人加入项目中 3. 下载git,下载地址为 ...