Chinaunix首页 | 论坛 | 博客
  • 博客访问: 38525
  • 博文数量: 17
  • 博客积分: 1445
  • 博客等级: 上尉
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-30 18:15
文章分类

全部博文(17)

文章存档

2012年(1)

2010年(4)

2009年(8)

2008年(4)

我的朋友
最近访客

分类: LINUX

2009-06-24 19:40:22

:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://dugchin.blogbus.com/logs/41355229.html

q:mplayer有个stream目录,是干嘛的?
a:stream是mplayer为了统一文件操作封装的一个模块

q:文件操作不就是读写吗,还抽象个鸟?
a:哥哥,文件也有很多啊,有你的dvd,有你下载的小爱同学的高清avi,有网络视频,
甚至还有我们火星基地上ftp服务器的电影,这么多文件每个的操作方式必然会有
不同。比如本地的小爱片片,直接就可以读,网络视频那你显然需要建立个连接之
类的之后才能读,火星基地上的文件,那显然需要你先给基地发送个正弦波告诉他
我要看这个电影,然后他要是愿意就会用正弦波把电影发送给你看,波来波往的,
你就能看这个片了。

但无论如何,文件操作,无非就是打开关闭读写定位,这个你总同意吧。
接口封装的意义就不用废话了吧,所以mplayer的开发者为了能有简洁明了可扩展
高伸缩的文件操作,就抽象出了stream.h中的如下几个接口
typedef struct stream_st {
// Read
int (*fill_buffer)(struct stream_st *s, char* buffer, int max_len);
// Write
int (*write_buffer)(struct stream_st *s, char* buffer, int len);
// Seek
int (*seek)(struct stream_st *s,off_t pos);
// Control
// Will be later used to let streams like dvd and cdda report
// their structure (ie tracks, chapters, etc)
int (*control)(struct stream_st *s,int cmd,void* arg);
// Close
void (*close)(struct stream_st *s);

。。。。
} stream_t;

人家写的很清楚了这几个是干嘛的,地球人都能看明白吧。
于是对本地普通片,就有了open_f(stream_file.c),对ftp协议的网络视频,就有了
open_f(stream_ftp.c嘿丫也叫open_f),对于dvd,有dvb_open(stream_dvb.c),等等等等吧


q:哦看起来是挺方便的,要是我自己有个特殊的文件格式,只要我按照这几个接口,把
文件的操作实现了,那就能在mplayer里播放了是吧?
a:额,这只是第一步,当然是非常必要的一步,其他的你先别问,问了我也不回答

q:嘿,好吧。那比如我现在要播放一个文件,mplayer是怎么知道需要用哪个open来open呢?
不会是需要我告诉它吧?我自己都不知道
a:当然不用你告诉他。伟大的开源社区没有指望我们党和人名培养出来的用户能有那么高的智商。

因为文件类型过多,为了方便描述管理,mplayer又定义了stream_info_t结构,里边会记录
哎这个stream是谁写的啦(author),写得是不是够帅啦(comment)等等
typedef struct stream_info_st {
const char *info;
const char *name;
const char *author;
const char *comment;
/// mode isn't used atm (ie always READ) but it shouldn't be ignored
/// opts is at least in it's defaults settings and may have been
/// altered by url parsing if enabled and the options string parsing.
int (*open)(struct stream_st* st, int mode, void* opts, int* file_format);
const char* protocols[MAX_STREAM_PROTOCOLS];
const void* opts;
int opts_url; /* If this is 1 we will parse the url as an option string
* too. Otherwise options are only parsed from the
* options string given to open_stream_plugin */
} stream_info_t;

注意这里有一个int (*open)(。。。)
不得了啊,又是一个接口,而这个借口具体的实现,就是上边我们说过的dvb_open和open_f了。

而那个const char* protocols[MAX_STREAM_PROTOCOLS]记录的是本stream支持哪些协议。这是一个数组,
也就是说每个stream可以支持多个协议
比如ftp stream支持的是ftp协议,所以stream_ftp.c里边的stream_info_t关于protocols的描述就是
const stream_info_t stream_info_ftp = {
。。。。
{ "ftp", NULL },
。。。。
};

而普通本地文件,你可以写成file://localhost/c:/a.avi,也可以直接写成c:/a.avi,所以stream_file.c
里stream_info_t关于protocols的描述就是
const stream_info_t stream_info_file = {
。。。。
{ "file", "", NULL },
。。。。
};

mplayer会把这些个stream_info_t放到一个数组auto_open_streams里,当你要播放一个文件时,stream模
块会尝试打开它,它遍历auto_open_streams,先匹配文件采用的协议,比如你要打开一个c:/a.avi,你的
协议域是空,这样匹配stream_info_ftp,stream_info_dvd等等mplayer都会让你失败,然后在stream_info_file
时它会让你成功,协议匹配成功后,mplayer就会调用stream_info_t里的open方法,如果这个成功了,那么就说
明找到了正确的stream处理过程,如果失败了就失败了。。

q:挺智能的啊。嗯导演说不让我再问问题了,怕问多了你也不会,那我就下次在找你吧
a:谢谢谢谢,大家鼓掌

这里不得不说一下mplayer的插件机制。

程序写多了的人,干嘛都要先抽象一把。开发mplayer的这帮人显然是属于程序写的相当多的,于是他们为了面子问题,
把mplayer的几个关键模块都进行了抽象,每个模块定义了一组接口,具体的底层操作都实现了这些接口。

说得通俗一点就是带头大哥说我们要成就一番事业,就要遵循一些规则,于是下边的小弟们都要按照大哥定的帮规来行
事。说得民工一点,就是上层有接口,下层有实现,形成了看起来很美用起来很帅的插件机制。每个具体的处理方
法,都是一个插件。

这样其实对于看代码并没有传说中的那么麻烦。比如对于stream模块,你要找统一规划调用的操作,就直接看stream.h,
stream.c, 你要看具体操作,就去找stream_xxx.c,也算是一目了然了。

阅读(469) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~