转载时请注明出处和作者
文章出处:http://www.nanbandao.com/bbs/
作者:Ella
为了播放器容易维护,应老大要求,INPUT模块和DEMUX模块必须分家。
INPUT模块是指通过各种方式(如读本地文件,http,udp,rtsp等等)将数据写到一段内存中,DEMUX模块只负责从相应的内存中取数据,也就是INPUT在一个线程,DEMUX在另外的线程里。
FFMPEG的架构是DEMUX需要数据时,先访问Buffer2,Buffer2如果有数据,则直接使用,如果没有,则调用INPUT模块的api,读 数据并将数据写入到Buffer1,然后将Buffer1的数据memcpy到Buffer2。Buffer1的初始化在 av_open_input_file函数的url_fopen的url_fdopen函数处理的,普通大小是1M;而Buffer2的大小是根据 DEMUX要求临时生成的buffer。向Buffer1写数据依赖于URLProtocol结构体,先看看该结构体的定义。
typedef struct URLProtocol
{
const char *name;
int (*url_open)(URLContext *h, const char *filename, int flags);
int (*url_read)(URLContext *h, unsigned char *buf, int size);
int (*url_write)(URLContext *h, 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);
} URLProtocol;
函数指针url_open是根据当前name进行open的,如果的本地文件,则直接open该文件,如果是http,则需要进行socket通信,并判 断socket是否成功建立;url_read,将数据读入buf所指向的内存中,url_write将数据写入buf,url_seek,seek到指 定的地方;url_close:realease open时相关的资源。
为了INPUT从FFMPEG分开,且符合FFMPEG架构,则构建了如下模型。
Buffer1和Buffer2的关系不变,变的是向Buffer1写数据模块,因此增加了一个新的URLProtocol类型,
URLProtocol mem_protocol =
{
"mem",
mem_data_open,
mem_data_read,
mem_data_write,
mem_data_seek,
mem_data_close,
};
而且需要在ffmpeg/libavformat/allformat.c 中注册REGISTER_PROTOCOL(MEM,mem);依次实现mem_data_open、mem_data_read、 mem_data_write、mem_data_seek、mem_data_close。
这样FFMPEG只需从Buffer3获取数据,而不用关心数据以何种方式得到