puppy居
puppy居士
posts - 41,comments - 27,trackbacks - 0
之所以要介绍S3C2410 DMA,因为它对性能太重要了!只有活用了DMA,CPU的性能才能上去!S3C2410有四个DMA,每个DMA支持工作方式基本相同,但支持的source Dest可能略有不同,具体见Datasheet。
  这里具体DMA CONTROL寄存器(DCON)的配置说明,进而引出DMA的各种工作方式。

  Atomic transfer:指的是DMA的单次原子操作,它可以是Unit模式(传输1个data size),也可以是burst模式(传输4个data size),具体对应DCON[28]。
  Data Size:指的是单次原子操作的数据位宽,8、16、32,具体对应DCON[21:20]。
  Request Source:DMA请求的来源有两种,软件&硬件模块,由DCON[23]控制;当为前者时,由软件对DMASKTRIG寄存器的位0置位触发一次DMA 操作。当为后者时,具体来源由DCON[26:24]控制,不同硬件模块的某时间触发一次DMA操作,具体要见不同的硬件模块。
  DMA service mode:DMA的工作模式有两种,单一服务模式&整体服务模式。前一模式下,一次DMA请求完成一项原子操作,并且transfer count的值减1。后一模式下,一次DMA请求完成一批原子操作,直到transfer count等于0表示完成一次整体服务。具体对应DCON[27]。
  RELOAD:在reload模式下,当transfer count的值变为零时,将自动加src、dst、TC的值加载到CURR_DST、CURR_SRC、CURR_TC,并开始一次新的DMA传输。该模式一般和整体服务模式一起使用,也就是说当一次整体服务开始后,src、dst、TC的值都已经被加载,因此可以更改为下一次服务的地址,2410说明文档中建议加入以下语句来判断当前的服务开始,src、dst、TC的值可以被更改了:while((rDSTATn & 0xfffff) == 0) ;
  Req&Ack:DMA请求和应答的协议有两种,Demard mode 和 Handshake mode。两者对Request和Ack的时序定义有所不同:在Demard模式下,如果DMA完成一次请求如果Request仍然有效,那么DMA就认为这是下一次DMA请求;在Handshake模式下,DMA完成一次请求后等待Request信号无效,然后把ACK也置无效,再等待下一次Request。这个设计外部DMA请求时可能要用到。
  传输总长度:DMA一次整体服务传输的总长度为:
Data Size × Atomic transfer size × TC(字节)。

S3C2410的DMA支持四类DMA传输:

系统总线到系统总线(ASB/AHB to ASB/AHB)
系统总线到外设总线(ASB/AHB to APB)
外设总线到系统总线(APB to ASB/AHB)
外设总线到外设总线(APB to APB)。
S3C2410共有四条DMA通道,每条通道5个请求源。

Ch0:nXDREQ0,UART0,SDI,Timer,USB EP1
Ch1: nXDREQ1,UART1,I2SSDI,SPI0,USB EP2
Ch2:I2SSDO,I2SSDI,SDI,Timer, USB EP3
Ch3:UART1,SDI,SPI1,Timer, USB EP4
S3C2410 DMA 三个比较重要的信号,引用2410官方文档:

DMA REQ: In the Single service mode, these three states of main FSM are performed and then stops, and waits for another DMA REQ. And if DMA REQ comes in, all three states are repeated.
DMA ACK: DMA ACK is asserted and then deasserted for each atomic transfer. In contrast, in the Whole service mode, main FSM waits at state-3 until CURR_TC becomes 0. Therefore, DMA ACK is asserted during all the transfers and then deasserted when TC reaches 0.
INT REQ: INT REQ is asserted only if CURR_TC becomes 0 regardless of the service mode (Single service mode or Whole service mode).
S3C2410 DMA状态机:
  S3C2410 的DMA使用一个具有三个状态的有限状态机进行DMA 传输的流程控制,引用2410官方文档:

State-1. As an initial state, the DMA waits for a DMA request. If it comes, it goes to state-2. At this state, DMA ACK and INT REQ are 0.
State-2. In this state, DMA ACK becomes 1 and the counter (CURR_TC) is loaded from DCON[19:0] register. Note that the DMA ACK remains 1 until it is cleared later.
State-3. In this state, sub-FSM handling the atomic operation of DMA is initiated. The sub-FSM reads the data from the source address and then writes it to destination address. In this operation, data size and transfer size(single or burst) are considered.
  每当一次DMA操作结束,不管是使用什么服务模式,DMA状态机都会自动地从状态三回到状态一,开始另一次操作。注意这里信号是DMA REQ 和 DMA ACK,而最终引脚信号是nXDREQ 和 nXDACK,所以最后实际输出的电平与这里的描述是相反的。

S3C2410 DMA 的服务模式:
  共有两种服务模式,一种是单一服务模式(single service),另外一种是整体服务模式(whole service)。
  在单一服务模式下,不使用传统的DMA计数器,三个DMA状态被顺序执行一次后停止,等待DMA 请求再一次来临后再重新开始另一次循环。
  在整体服务模式下,使用传统的DMA 计数器,状态机会停留在状态三,直到DMA计数器的值减为零,再回到状态一,等待下一次DMA请求。

S3C2410 DMA 数据传输模式:
共有两种数据传输模式:

单位数据传输模式:执行一次读操作和一次写操作。
并发数据传输模式:执行四次读操作和四次写操作。
S3C2410 DMA 的基本时序:
  nXDREQ请求生效并经过2CLK周期同步后,nXDACK响应并开始生效,但至少还要经过3CLK的周期延迟,DMA控制器才可获得总线的控制权,并开始数据传输。


S3C2410 DMA 的两种协议模式:


请求模式:If XnXDREQ remains asserted, the next transfer starts immediately. Otherwise it waits for XnXDREQ to be asserted.
握手模式:If XnXDREQ is deasserted, DMA deasserts XnXDACK in 2cycles. Otherwise it waits until XnXDREQ is deasserted.
S3C2410 DMA REQ与ACK 协议类型:
共有三种协议类型:

单一服务请求:

单一服务握手:

整体服务握手:

根据上面所说的服务模式和协议模式,很容易推知这三种协议的时序分别是什么。
posted @ 2008-10-09 08:39 puppy 阅读(965) | 评论 (0)编辑 收藏

在手持设备设计中,电源管理历来为重要的研究课题之一。我们日常所说的省电就属于电源管理的范畴,这也是我们最关心的一个部分。通过挂起不必要的设备、降低CPU的频率或者其它方法,可以减少能量的消耗,达到省电的目的。电源管理实际上是一个系统工程,从应用程序到内核框架,再到设备驱动和硬件设备,都要参与进来,才能达到电源管理的最优化。本文介绍一下动态电源管理(DPM)

 

所谓的动态电源管理(DPM)是一种电源管理机制,它允许在系统运行时动态的管理电源,这可能是相对于传统的电源管理方式而言的,传统的电源管理方式要求系统要么挂起(suspend)以节省能源,要么恢复(resume)运行让程序正常工作,这个过程通常要用户参与(如按键),而且这种状态切换非常缓慢。在动态电源管理(DPM)中,系统一方面可以关闭暂时不使用的设备,比如关闭硬盘和显示器。另外一方面也可以根据负载的重轻,动态调整CPU和总线的频率,以达到节省能源的目的。这都是动态完成的,不需要用户的干预,而且状态之间的切换非常快(每秒数百次)

 

动态电源管理(DPM)是很一个广泛的概念,很多系统实际上都采用了动态电源管理(DPM)方式,本文要谈的是Linux下的动态电源管理(DPM)Linux很早就采用了动态电源管理,在driver目录下有个cpufreq的驱动程序,它就是用来动态调整CPU频率以降低能源消耗的。

 

不过cpufreq似乎不能用于嵌入式环境,主要原因是:在嵌入式系统中,与LCD显示屏等外设相比,CPU已经不是能源消耗的大户了,光调整CPU的频率用处不大。而且cpufreq还依赖于像ACPIPC环境,而嵌入式设备一般都没有BIOS,电源管理功能只能完全由操作系统实现。cpufreq的实现目前还不太清楚,我们会在后续的文章中继续研究。

 

就目前掌握的资料来看,用嵌入式Linux系统的动态电源管理只有IBM奥斯汀实验室和MontaVista联合开发的动态电源管理(DPM)http://dynamicpower.sourceforge.net/)。我们将对它的架构做简要分析,下面提到动态电源管理(DPM)实际上是特指这个解决方案及其实现。

 

我们先介绍几个重要概念:

1.         operating point: 它实际上就是电源管理的一组配置数据,这组配置数据一旦确定,能源消耗率和系统性能也就确定了。比如:

 dpm_operating_point

上图有三个operating point,第一个operating point的名称为”33/33”,它的配置为:Core Voltage=1.0vPLL VCO = 800MHz等如表格第二列里的数据所示。

 

2.         operating state: 它实际上就是系统的运行状态,比如工作状态和空闲状态。不过在dynamicpower中,状态可以有很多种。同是工作状态,有高性能工作状态、中等性能工作状态和低性能工作状态等,甚至更多,根据具体的情况而定。

 

3.         policy: 它是电源管理的一个高级抽象。它负责把operating state映射到一个或者一组(class) operating point上。系统中可以有多个policy,但只一个policy处理激活状态。

 

4.         class: 代表一组operating point,在状态切换时,policy选取其中第一个满足约束条件的operating point作为有效operating point

 

5.         constraint:它指设备的约束条件,即只有在满足约束条件下,设备才能正常工作,比如LCD要一定总线频率才能正常更新屏幕。在状态切换时,如果下一状态对应的operating point不满足设备的约束条件,有两种选择:要么强制关闭设备,要么状态切换失败,根据设置而定。

 

dynamicpower可以认为是一种典型的按照机制与策略分开的模式设计的,它只实现了动态电源管理这种机制,而所有策略完全由用户空间的应用程序去做实现。总的来说它分为三个层次:

 

1.         API函数库。这一部分主要是对内核提供的sysfsproc文件进行封装,提供更好用的接口函数。它提供的函数如下:

int dpm_init(void);

int dpm_terminate(void);

int dpm_set_state(char *statename);

int dpm_create_op(char *name, char *params);

int dpm_set_op_param(char *op, char *param, int value);

int dpm_get_op_param(char *opname, char *param, char *buf, size_t bufsiz);

int dpm_create_class(char *name, char *params);

int dpm_create_policy(char *name, char *params);

int dpm_set_policy_state_map(char *policy, char *state, char *opclass);

int dpm_get_policy_state_map(char *policy, char *state, char *buf, size_t bufsiz);

int dpm_get_active_policy(char *name, size_t namemax);

int dpm_set_active_policy(char *policy);

 

 

如果明白了policyoperating stateoperating point等基本概念,上述函数不难理解:首先要创建一些operating point,即各种电源管理配置; 然后把这些operating point组合成class,接下来在operating stateclass/operating point之间建立映射关系,这是初始化过程要做的。在系统运行过程中,dpm会自动选择适当的模式,如果有多种policy,应用程序也可以激活适当的policy

 

2.         内核框架代码。它的主要功能包括对policy的管理,各种状态的切换等平台无关的操作,同时还提供了一些sysfsproc文件用来和用户空间的应用程序交互。它一部分的代码主要分布在下列文件中:

drivers/base/core.c

drivers/base/power/Makefile

drivers/base/power/power-dpm.c

drivers/base/power/resume.c

drivers/base/power/suspend.c

drivers/base/power/sysfs.c

drivers/dpm/Kconfig

drivers/dpm/Makefile

drivers/dpm/dpm-idle.c

drivers/dpm/dpm-ui.c

drivers/dpm/dpm.c

drivers/dpm/proc.c

fs/proc/base.c

include/linux/device.h

include/linux/dpm-trace.h

include/linux/dpm.h

include/linux/init_task.h

include/linux/pm.h

include/linux/sched.h

kernel/sched.c

kernel/softirq.c

kernel/workqueue.c

 

其中drivers/dpm/dpm.cdpm-idle.c是核心代码,dpm-ui.cproc.c主要是用于与用户空间应用程序交互的,其它代码则是用于与系统其它部分协调工作的。这一层代码不算太复杂,其中最重要的部分是状态切换,其主要过程如下:

dpm_set_os: 切换到新状态运行。

dpm_enter_state:把dpm_active_state置为新状态。

dpm_resync:让新状态生效。

dpm_choose_opt:找到适当的operating point

1.对于单个operating point:满足设备的约束(constraint)条件吗?满足则OK,否则再判断是否要强制切换。如果是则OK,否则切换失败。

2.对于一组operating point(class): 从列表中找到第一个满足约束条件的operating point,找到了则OK。否则切换失败。

dpm_set_opt: operating point生效。

dpm_md.set_opt: 调用依赖于具体平台的函数设置新的operating point

 

3.         平台相关代码。为了让operating point真正生效,通常要修改某些特定的寄存器,这是平台相关的。比如,在PXA27x上,要修改CCSRCCCRCLKCFG等寄存器。这一层要求实现下面几个接口函数:

struct dpm_md {

    int (*init_opt)(struct dpm_opt *opt);

    int (*set_opt)(struct dpm_opt *cur, struct dpm_opt *new);

    int (*get_opt)(struct dpm_opt *opt);

    int (*check_constraint)(struct constraint_param *param,

                    struct dpm_opt *opt);

    void    (*idle)(void);

    void    (*startup)(void);

    void    (*cleanup)(void);

};

 

       要了解这一层的代码,先要熟读平台datasheet相关的章节,这里不再多说。

posted @ 2008-09-10 12:37 puppy 阅读(1527) | 评论 (0)编辑 收藏
     摘要: MPlayer 名称概要说明一般注记播放选项 ( 仅用于 MPLAYER)分路器 / 媒体流选项OSD/ 字幕选项音频输出选项 ( 仅用于 MPLAYER)视频输出选项 ( 仅用于 MPLAYER)解码 / 滤镜选项编码选项 ( 仅用于 MENCODER)键盘控制SLAVE 模式协议文件示例BUGS作者标准声明 名称 ...  阅读全文
posted @ 2008-09-10 10:48 puppy 阅读(8719) | 评论 (0)编辑 收藏

        一个项目要求上音频、视频播放。项目环境为linux2.6 + s3c2440,google了一下,应该是mplayer无疑了。
        网上很多好人把mplayer的移植过程分享出来了,比较详细。自己交叉编译的过程中遇到的问题基本上都能搜索到解决办法。
        先到官方网站http://www.mplayerhq.hu下载一个最新的1.0-rc2版本,解压后就按照按照步骤来交叉编译了。
        MPlayer-1.0rc2.tar.bz2  + arm-linux-gcc-3.4.1.tar.bz2(就是网上流传的那个版本)

        1。./configure
         关键就是后面的配置参数了。rc2版本的配置参数相比pre版本而言有些微的改变,配置参数如下:

./configure --cc=arm-linux-gcc --target=arm-linux --enable-static \
     --prefix=/tmp/mplayer-rc2 --disable-win32dll --disable-dvdread \
     --enable-fbdev --disable-mencoder --disable-live --disable-mp3lib \
     --enable-mad --enable-libavcodec_a --language=zh_CN \
     --disable-armv5te --disable-armv6 \
     --with-extraincdir=/usr/local/arm/3.4.1/lib/include \
     --with-extralibdir=/usr/local/arm/3.4.1/lib/lib


         参数解释:
         --cc
         交叉编译工具,如果没添加到环境变量,就要指定完整路径

         --target
         在pre版本中,对于--target和这个配置参数是这样描述的:
===============================================
--target=arm-armv4l-linux这个参数要注意的是一个分三部分,第一部分的arm是指arch,这里设定为arm;第二部分的armv4l是指具体的版本,这个要注意了,一定要跟libavcodec目录下的平台目录名一致,否则为这个平台的优化代码没办法编译进去(据我观察是这样的);第三部分是系统平台。
===============================================
         但是在rc2版本中,只需要--target=arm-linux这样指定就好了。

         --enable-static
         是设定静态连接,不需要一堆乱七八糟的动态库,尤其对我们这些新手来说省了很多的麻烦。如果设置了这个参数就不用设置--prefix了,另外也不用执行make install。

         --prefix=/tmp/mplayer-rc2
         make install后,可执行程序就安装在/tmp/mplayer-rc2目录下。

         --disable-win32dll
         禁用win32动态链接库支持。在pre版本中该参数为

        --disable-dvdread
        禁用libdvdread.

        --enable-fbdev
       支持fbdev,这个一定要选上。

        --disable-mp3lib 和 --enable-mad
        arm系列的cpu,一般都没浮点运算单元,而mplayer的mp3解码默认使用mp3lib,这个是浮点运算库,在arm上肯定跑不了,使用ffmp3或者libmad(需要外部库libmad支持)应该就没问题了。所以这里需要禁止掉mencoder和使能libmad。

        --disable-mencoder
        禁止编码功能。项目上不需要此功能,禁掉以缩小尺寸。而且听说在这里编译mencoder会有问题,听说而已,没试过。

        --disable-live
        禁止live 555流媒体。(不知道干啥用)

        --enable-libavcodec_a

        启用静态的libavcodec解码。在pre版本中该参数为--enable-libavcodec。

        --disable-armv5te --disable-armv6
        禁用armv5te、armv6指令扩展。

        --with-extraincdir和-with-extralibdir
        指定libmad和mad.h的路径。mad的路径被添加到编译参数-I和-L后面,替换libmad后需要指定。

        注:在pre版本中需要指定--host-cc=gcc配置参数。用来编译一些需要在host上执行的中间文件的,如codec-cfg,切记不能缺少。但在rc2版本中该参数可以省略掉。

        2。make
       ./configure 之后就开始make了。
       编译过程应该是很顺利的。宿主环境是Fedora 8,GCC版本为4.1.2。在FC8上编译pre版本会通不过gcc编译器检测,pre版本不支持4.x以上的版本。或许可以加上--disable-gcc-check禁用gcc版本检测,不过我没有试过,有闲的可以试一试。
       另外在redhat9宿主环境下也编译过rc2版本。不过make的时候好像弹出了个dvdcss的什么错误,在配置选项中--disable-libdvdcss-internal禁掉dvdcss就好了。
       因为需要mad库播放音频,所以还需要交叉编译libmad。
       libmad的版本为 libmad-0.15.1b.tar.bz2
       libmad也是configure make之类的步骤。configure的配置参数为:
       ./configure --enable-fpm=arm --host=arm-linux --disable-shared \
                        --disable-debugging --prefix=/usr/local/arm/3.4.1/lib \
                        CC=arm-linux-gcc

        
       之后make,就很顺利的编译出libmad了。注意--prefix配置选项表示libmad库和头文件在哪个目录生成,比如本例中make install后在/usr/local/arm/3.4.1/lib目录下就多了include和lib两个目录。这与mplayer的配置选项--with-extraincdir指定的目录是相符的。

       编译完成后就生成了mplayer,最开始下载到板子上运行的时候却崩溃了,打出错误信息:
       "MPlayer interrupted by signal 4 in module: decode_video"
       google了一下,发现是用了不支持的armv5、armv6的优化指令,s3c2440是armv4,运行到不认识的armv5、armv6的指令就崩溃了。加上禁用armv5、armv6的指令扩展配置选项--disable-armv5te --disable-armv6,再重新来一次,下载运行mplayer,就OK了。其实这些高版本的指令扩展应当是自动检测的,不知道为什么没有生效。需要手动的禁止掉。

 

       3。运行mplayer
       手上板子的LCD屏很怪,是240×320的,而不是常见的320×240。这样,用命令播放:

       mplayer test.avi

       开始播放avi的时候画面就被截短了,并打印出错信息:
     “Could not find matching colorspace - restrying with -vf scale...”。

       于是加上参数:

       mplayer test.avi -framedrop -quiet -vf rotate -flip -x 240 -y 320 

       画面是对了,但是速度非常慢,就像我们平时用“1/2倍速”来播放影片一样。CPU占有率90%以上。

       再瞎试,看到一组参数,试一下:

       mplayer test.avi -framedrop -quiet -vf rotate=1,scale=240:320 

       播放就比较流畅了。但是CPU占有率还是90%以上。test.avi是Xvid格式的MP4,505kbps。

       如果视频源文件的分辨率比240×320大,最好用工具转换一下,否则播放的速度会非常慢。

posted @ 2008-09-09 11:55 puppy 阅读(4889) | 评论 (12)编辑 收藏
   我们知道,wmv,wma,xvid,divx,很大一部分avi,他们都是所谓的mpeg4的文件,这种文件的压缩比极高,但是显示的质量并没 有太大的改变。mpeg2就是我们常见的dvd所采用的编码规范,MPEG(活动图像专家组)包括一组规范。其中5,6已经胎死腹中,mpeg7不是面向 消费的。第一个mpeg4规范的实现,是由MS作出来的,不过很快就被破解了,之后破解版本有了很多 的分支(如xvid,divx等),MS自己的文件也有版本更新,所以,mpeg4不是一种固定的格式,而是一组格式的统称,他们都可以上朔到MS的最初 版本.

DivX和XviD不能不说的故事, 好像很多人不知道他们的关系。 如今的电影是越来越好看,拍摄、制作的特技效果越来越精彩,人们期待的程度越来越高,盗版也越来越多;同时电影制作公司的防盗版技术做的越来越高明。但有句老话叫:"道高一尺,魔高一丈",无论你的电影多精彩、防盗技术多高明,总是有人偏偏能够把你"盗"出来,而且还"盗亦有盗",在保持"原版原味"的条件下,占用的空间变得越来越小,操作越来越灵活、简单,越来越方便传播。而且这种技术随着版本不断更新,画质越来越贴近原版、压缩速度越来越快、压缩/播放进程对计算机的需求越来越低。这就是DivX时代的新生力量──XviD。

  黑格尔说过"存在即合理"

  随着时代的进步,社会的发展,在计算机视频技术方面更是突飞猛进。如今视频的业界标准已经到了DVD时代。主流的DVD光驱的价格已经降到400元人民币以内。DVD播放机的价格最便宜的已经降到了700元。但是这些都是近期发生的事情,目前仍有一大群only CD-ROM群体,他们不愿意再投资去买DVD光驱,有的甚至由于机器无法再扩充而不能购买DVD光驱。这便促使另一个的解决方案的萌发。

  除此之外,互联网宽带的普及,Adsl宽带入户,P2P软件的泛滥,使得650MB的大文件轻松的实现异地传输。还有正版DVD大片的价格居高不下,也是正版DVD普及化的一大障碍。基于以上因素的存在,有一种新的视频压缩技术出现,那就是DivX,即"压缩电影"。压缩电影的技术有很多种,但是DivX最为普及,它广泛流传于互联网与盗版盘。

  随着时间的推移DivX再推出刚刚推出不久,就不断推陈出新,从DivX3.11到DivX4,目前最新版本为DivX5.02。本来版本越高,技术也就越高、播放的质量应该更好、更清晰。但是事实告诉我们随着版本的提升,压缩后的播放效果提升不明显,压缩所用的时间越来越长,压缩后的体积没有太大的进步,甚至有的使用DivX5.02压缩以后会出现跳帧的问题。这到底是为什么呢?难道视频压缩技术已经达到顶峰不能够再穿越了么?

  目前又出现一种新的压缩技术名为XviD,在视频业界初见端倪,就目前来看它的压缩时间就是一大卖点,它可以在保持DivX5的画质的基础上,大大提高压缩时间。

  光从名字上看就可以看出Xvid与Divx,他们之间肯定有着千丝万缕的联系,大家一定想知道。下面就为大家谈谈关于XviD的故事。

  Long long ago…

  故事的经过是这样的。

  早在1998年微软开发了第一个(也是唯一的)在PC上使用的MPEG-4(注)编码器,它包括MS MPEG4V1、MS MPEG4V2、MS MPEG4V3的系列编码内核。其中的V1和V2用来制作AVI文件,一直到现在它都是作为Windows的默认组件。不过V1和V2的编码质量不是很好,一直到MS MPEG4V3才开始有好转,画质有了显著的进步。但是不知微软出何居心,却将这个MS MPEG4V3 的视频编码内核封闭在仅仅应用于Windows Media流媒体技术上,也 就是说,我们经常看到的ASF流媒体文件中。ASF文件虽然有一些优势,但是由于过分的封闭,不能被编辑,未得到广泛的应用。这便惹怒了不怕天不怕地的视频黑客和置于钻研视频编码的高手。后来,这些小组不仅破解了微软的视频编码,而且经过他们的修改,一种新的视频编码诞生了。那就是广为流传的Mpeg4编码器──DivX3.11。

  随后一发不可收拾,DivX被传得红得发紫,很快就成了业界的标准。但是问题同样很快的出现了,DivX的基础技术是非法盗用微软的,只能在地下里流传,却上不了台面,正所谓"名不正,言不顺",无法进行广泛的发展,即产品化,更无法生产硬件播放机。

  "生产力要改变生产关系"

  在这种情况的迫使下,一些视频编码的高级程序员(包括原DivX 的开发者)组建了一家公司,名为DivXNetworks Inc。这家公司发起一个完全开放源码的项目,名为"ProjectMayo",目标是开发一套全新的、开放源码的MPEG4编码软件。由于它完全符合ISO MPEG4标准,又是完全开放源代码(就象linux操作系统),OpenDivX CODEC吸引了很多软件、视频高手参与。人力、物力大大投入,OpenDivX编码器和解码器原型很快便公布于众,之后又开发出具有更高性能的编码器Encore 2等等。这DivX的辉煌时期。

  虽然主要编码工作是DXN的人在做,但许多的技术难关的突破完全得力于来自开放源码社会的帮助。

  DivX的优势被人们所接受,高品质的DVD电影的容量一般为5GB,但经过DivX编码后的大小只有650MB,仅仅为原DVD容量的八分之一,图像品质却与DVD相当。它可以通过互联网相互传输,还可以报存在一张CD光盘(650MB)上。

  DXN的野心:

  DivXNetworks一直希望DivX能成为好莱坞巨头们选择的行业标准,并可以通过互联网进行传输的视频文件,就像唱片发行公司不得不接受MP3格式,并使用它在网上传输音乐文件一样。DXN希望并计划在网上出售视频内容的公司达成技术转让的协议。但是,到目前为止,它尚未和任何一家主要的、甚至具有影响力的电影制片公司达成这类协议。

  很可惜的是想DivX这么好的电影只能在电脑上播放,目前还没有一款播放机能够播放这样的光盘。日前,DXN已经来到了中国,这家公司的负责人表示,目前有许多美国人都希望能买到采用这一技术的DVD播放设备,但全球还没有人能生产,所以他希望能与中国的DVD制造商携手,在年内拿出产品,并且首先在美国推出。

  "天底下真的好人多么?那么小人算好人么?"

  就在DivX顺利发展时期,DivX的技术逐渐成熟,商机无限的时候,一台好戏上演了。由于DivX的技术不是依据GPL协议(通用公共许可证,一种开放源码项目中常用的保障自由使用和修改的软件或源码的协议),而是LGPL协议(注)。这是DXN公司为自己留的后门。

  2001年7月就在Encore2基本成型的时候,DXN公司突然封闭了DivX的原代码,并在此基础上发布了自有产品DivX4。DivX 4的基础就是开放源代码OpenDivX中的Encore 2,DXN利用了DivX的招牌。DNX公司这么做,可以说是出其不备的摆了所有人一刀。开放源码社会就这样被狠狠地涮了一回,他们是那么的无辜。

  DXN公司趁热打铁,很快推出了DivX5,但是DivX5没有比DivX4强到哪里去,甚至有bug,更可气的是这一版本还要收费。可怜阿,有那么多无偿为DivX技术付出的智慧与劳动的人,可悲阿,他们为一值都在无偿的为DNX公司赚钱。这种垄断和一直处于垄断地位的微软来说,DXN要更恨、更毒。

  人世间还是好人多!正义当头!

  首先是全球整个0dayz组织(注)永远的拒绝了DXN公司的DivX45。被人"涮"了一把的开源社团决定另起门户,逐渐重新聚拢开发力量,在OpenDivX版本的基础上,再次开发出一种新的MPEG-4编码、解码软件。这就是:XviD。从技术上来说XviD已经基本上与DivX5接近,或者还有所超越;

  春天来了:

  近一年来XviD继承并发展了曾经的OpenDIVX Encore 2,并且使其的性能、效率的到了极大的提升,被认为是目前最快的MPEG4编码。这是因为XviD重新改写了所有原代码,焕然一新。除此之外,Xvid还吸收了前车之鉴,依照GPL发布。(不再是以前DivX的LGPL,也就是说:谁要是想用它做成产品而不开放源码是非法的)而且在2002年,也就是今年,TDX2002(全球最著名的地下电影发行组织,每年在网上放出数千部最新而且高品质影片RIP)已经接纳XviD为官方标准。这样TDX2002就有了两个正式标准:DivX 3.11与XviD。而DivX 4、5像其它封闭的商业软件一样,被永远拒绝。

  报应来了!

  对开源软件下毒手的人远不止DXN一家,目前因为一家商业软件公司盗用XviD源代码,而被迫停止开发。具体的情况请参阅:
http://www.xvid.org

        DivX 4/5                    XviD
出品公司  DivXNetworks Inc              开放源代码(GPL授权)
推出时间   1998年                   2002年2月
创始人    罗达(Rota)及电脑黑客基尔(Gej)    被DXN"涮"的人
TDX2002认证 Yes                     Yes
oDay认证   No                      Yes
最新版本   5.02                     1.3+
费用     收费                     免费
压缩时间   长                          稍短
图像质量   高、接近DVD                高、接近DVD
压缩容量   较小                      较小
编码容量   3.4MB                     359K
优化设置   一般        强大的可调节性,使用这可设置很多选项,分别针对不同电影进行不同方式的压缩。

  XviD使用技巧:

  关于XviD压缩设置的文章很多,XviD可以调节的选项很细,由于篇幅限制,不再本文的讨论之内。在这里,我推荐大家使用"2-Pass"编码,因为它能给我们更精确的最终文件大小,并且生成最佳质量的编码 (在文件大小相同的情况下)。

  只安装DivX5的编解码器不能播放由Xvid压缩的电影。但是只安装XviD编码,可以顺利播放DivX5压缩的电影。但是在播放DivX5电影的时候,速度不能让人满意。加上ffdshow(注)之后效果明显改善。看来XviD在播放divX5的还不是很完善。

  虽然XviD到目前来讲与DivX5对战,仍有些身单力薄,优势不是很明显。但是笔者很看好XviD。首先,它是绝对开放源代码,这使得有更多的人投入到XviD的研发之中。还有,它完全重写DivX的原代码,让新的XivD去粗取精、焕然一新;目前XviD的开发人员有很多都是当初DivX的研发人员,对DivX的错误了解得很清楚,重写之后,XivD的地层优势可见一斑。另外,DivX4/5虽然版本不断更新,但是功能提升并不高,优势不明显。XviD是新生力量,而且充满了复仇的力量。祝XviD一路走好。

  XviD版本的历史:

  1.0 2002年2月17日 第一版 ,首次发布
  1.0 2002年2月28日 大量的修正和更准确地解释
  1.1 2002年3月2日 分析澄清了很多概念
  1.2 2002年3月4日 加入量化矩阵(quantization matrix), 移去量(removed quant). 柔和(smoothing) 技术
  1.3 2002年3月8日 关于 Nic's XviD Directshow Filter 的详释
  1.3+ 2002年7月23日 按照Nic's XVID Codec校正补充部分内容(目前最新版本)

  关于DivX起源的小知识:

  这种名为DivX 的技术,由一个27岁的法籍影音发烧友罗达(Rota)及电脑黑客基尔(Gej)创造出来得。

  原来DivX所采的技术并非这两位仁兄发明的,他们只不过是个盗版天才。随着Wind ows的大行其道,微软开发了MPEG-4技术,能够将视频影像文件容量压缩到很小。罗达与基尔将程式重写一遍,但将其改名为DivX,且放在网上随意任人下载。

  微软声称将对所有推动DivX发展的人、企业作出追究。可是罗达正全面申请将他们的DivX合法化。由于DivX虽然是从Windows的发明出来的,但却没有用过任何微软的技术。而且,他更与美国一些技术人士及财经人员开会,和组新公司 ProjectMayo.com全力推广DivX。

  其实,DivX是视频DVD的另一种保存方式,要靠DeCSS程序(注)才能做到。因为DV D本身有防复制的标记,让DVD不能随便复制到电脑里,但DeCSS能将它解码,令其可以复制,压缩成DivX电影。针对这一做法,各大电影商立即采取行动,防止DeCSS外流及散播,但为时已晚,DeCSS在Yahoo!、Google上都能找到。
 
  名词解释:

  DeCSS程序:乔.约翰森编写的小程序,仅有57K,不仅震撼了好莱坞,还引发了无数的法律纠纷。他创造出来的“小魔怪”,如今已经成了好莱坞制片商们最恨之入骨的冤家对头。DeCSS程序能够将正版加密的DVD影片复制到计算机硬盘上。它还可以将这些影片上传到互联网上。

  MPEG-4技术:是一种崭新的低码率、高压缩比的视频编码标准,传输速率为4.8~64kbit/s,使用时占用的存储空间比较小。目前的DivX(最新的XviD)电影都采用的此技术,现在被广泛采用。

  GPL协议:通用公共许可证,一种开放源码项目中常用的保障自由使用和修改的软件或源码的协议。

  LGPL协议:次级GPL(Lesser GPL),与GPL一样,是一种公共许可证。与GPL的最大不同是它允许私有。

  Ffdshow:一个支持 Xvid、MPEG4-V3 MPEG4-V2 以及 DivX 所有版本所制作的视频文件的播放软件,占CPU 资源比较少。
posted @ 2008-09-09 09:57 puppy 阅读(310) | 评论 (0)编辑 收藏

MPlayer-1.0rc2和pre版本相比一些选项的名称变了

安装路径:
--prefix=DIR                       安装路径 [/usr/local]
--bindir=DIR                      执行程序安装路径 [PREFIX/bin]
--datadir=DIR                     相关文件安装路径 [PREFIX/share/mplayer]
--mandir=DIR                      使用手册安装路径 [PREFIX/share/man]
--confdir=DIR                     配置文件安装路径 [PREFIX/etc/mplayer]
--libdir=DIR                      对象代码库文件安装路径 [PREFIX/lib]
--codecsdir=DIR                   二进制解码器安装路径 [LIBDIR/codecs]
--win32codecsdir=DIR              Windows DLLs 文件安装路径[LIBDIR/codecs]
--xanimcodecsdir=DIR              XAnim 解码器安装路径 [LIBDIR/codecs]
--realcodecsdir=DIR                RealPlayer 解码器安装路径 [LIBDIR/codecs]

可选特性:
--disable-mencoder                不编译 mencoder(A/V 编码器) [有效]
--disable-mplayer                 不编译 mplayer [有效]
--enable-gui                      编译 gmplayer,使用GTK+ 可视界面 [无效]
--enable-gtk1                     强制使用 GTK 1.2 做为交互界面 [无效]
--enable-largefiles               支持大于 2GB 的文件[disable]
--enable-linux-devfs              默认设备设置到devfs中(设备文件系统)[无效]
--enable-termcap                  关键代码使用 termcap(terminal capabilities)数据库 [自动检测]
--enable-termios                   关键代码使用 termios (terminal I/O)[自动检测]
--disable-iconv                   不使用 iconv 进行编码转换 [自动检测]
--disable-langinfo                不使用 langinfo[自动检测]
--enable-lirc                     支持 LIRC (远程控制)[自动检测]
--enable-lircc                    支持 LIRCC 输入(LIRC 客户端守护进程)[自动检测]
--enable-joystick                 支持控制杆[无效]
--enable-apple-remote             使用 Apple 远程控制 (Mac OS X only) [自动检测]
--disable-vm                      不使用 X video 模式扩展[自动检测]
--disable-xf86keysym              不支持多媒体键[自动检测]
--enable-radio                     广播接口 [无效]
--enable-radio-capture             广播捕获(通过 PCI/line-in) [无效]
--disable-radio-v4l2               不使用 Video4Linux2 广播借口 [自动检测]
--disable-radio-bsdbt848           不使用 BSD BT848 广播借口 [自动检测]
--disable-tv                       不使用电视接口 (TV/DVB 采集卡) [有效]
--disable-tv-v4l1                  不使用 Video4Linux TV 接口 [自动检测]
--disable-tv-v4l2                  不使用 Video4Linux2 TV 接口 [自动检测]
--disable-tv-bsdbt848              不使用 BSD BT848 接口 [自动检测]
--disable-tv-teletext              不使用 图文电视(TV teletext) 接口 [自动检测]
--disable-pvr                      不使用 Video4Linux2 MPEG PVR [自动检测]
--disable-rtc                      不使用 Linux下的RTC (/dev/rtc)[自动检测]
--disable-network                  不使用网络 [有效]
--enable-winsock2                  允许 winsock2 [自动检测]
--enable-smb                       允许 Samba (SMB) 输入[自动检测]
--enable-live                      允许 LIVE555 流媒体[自动检测]
--enable-nemesi                    允许 Nemesi 流媒体 [自动检测]
--disable-dvdnav                   禁用 libdvdnav [自动检测]
--disable-dvdread                  禁用 libdvdread [自动检测]
--disable-dvdread-internal         禁用内部 libdvdread [自动检测]
--disable-libdvdcss-internal       禁用内部 libdvdcss [自动检测]
--disable-cdparanoia               禁用 cdparanoia [自动检测]
--disable-cddb                     禁用 cddb [自动检测]
--disable-bitmap-font              禁用点阵字体支持 [有效]
--disable-freetype                 禁用 Freetype2 字型呈现[自动检测]
--disable-fontconfig               禁用 fontconfig 的字体查找 [自动检测]
--disable-unrarlib                 禁用 Unique RAR 文件库 [有效]
--enable-menu                      使用 OSD 菜单 (非 DVD 菜单) [无效]
--disable-sortsub                  禁用字幕排序 [有效]
--enable-fribidi                   FriBiDi 库 [自动检测]
--disable-enca                     禁用 ENCA 字符集的 oracle 库[自动检测]
--disable-macosx                   禁用 Mac OS X 下制定特效 [自动检测]
--disable-maemo                    禁用 maemo 指定特效 [自动检测]
--enable-macosx-finder-support     Mac OS X Finder 引用参数解析 [无效]
--enable-macosx-bundle             Mac OS X 捆绑文件位置 [自动检测]
--disable-inet6                    禁用 IPv6 支持 [自动检测]
--disable-gethostbyname2           gethostbyname2 C 库的一部分[自动检测]
--disable-ftp                      禁用 FTP 支持 [有效]
--disable-vstream                  禁用 TiVo vstream 客户端支持[自动检测]
--disable-pthreads                 禁用 Posix 线程支持 [自动检测]
--disable-w32threads               禁用 Win32 线程支持 [自动检测]
--disable-ass                      禁用内部 SSA/ASS 字幕支持 [自动检测]
--enable-rpath                     运行时链接器路径到额外库 [无效]

解码器:
--enable-gif                       GIF 支持 [自动检测]
--enable-png                       PNG 输入/输出支持 [自动检测]
--enable-jpeg                      JPEG 输入/输出支持 [自动检测]
--enable-libcdio                    外部 libcdio [自动检测]
--enable-liblzo                    外部 liblzo [自动检测]
--disable-win32dll                 禁用 Win32 DLL 支持 [有效]
--disable-qtx                      禁用 QuickTime 解码器支持 [有效]
--disable-xanim                    禁用 XAnim 解码器支持 [有效]
--disable-real                     禁用 RealPlayer 解码器支持 [有效]
--disable-xvid                     禁用 XviD [自动检测]
--disable-x264                     禁用 x264 [自动检测]
--disable-libnut                   禁用 libnut [自动检测]
--disable-libavutil_a              禁用静态 libavutil [自动检测]
--disable-libavcodec_a             禁用静态 libavcodec [自动检测]
--disable-libavformat_a            禁用静态 libavformat [自动检测]
--disable-libpostproc_a            禁用静态 libpostproc [自动检测]
--disable-libavutil_so             禁用共享 libavutil [自动检测]
--disable-libavcodec_so            禁用共享 libavcodec [自动检测]
--disable-libavformat_so           禁用共享 libavformat [自动检测]
--disable-libpostproc_so           禁用共享 libpostproc [自动检测]
--disable-libavcodec_mpegaudio_hp 禁用 libavcodec 中高精度音频解码 [有效]
--disable-tremor-internal          禁用外部 Tremor [有效]
--enable-tremor-low                低精度内部 Tremor [无效]
--enable-tremor-external           外部Tremor [自动检测]
--disable-libvorbis                禁用 libvorbis 支持 [自动检测]
--disable-speex                     禁用 Speex 支持 [自动检测]
--enable-theora                     OggTheora 库 [自动检测]
--enable-faad-external             外部 FAAD2 (AAC) [自动检测]
--disable-faad-internal            禁用内部 FAAD2 (AAC) [自动检测]
--enable-faad-fixed                内部 FAAD2 使用固定点模式 [无效]
--disable-faac                     禁用对 FAAC (AAC 编码器) 的支持 [自动检测]
--disable-ladspa                   禁用 LADSPA 插件支持 [自动检测]
--disable-libdv                    禁用 libdv 0.9.5 编码/解码 支持[自动检测]
--disable-mad                      禁用 libmad (MPEG 音频) 支持 [自动检测]
--disable-toolame                  禁用 Toolame (MPEG layer 2) 编码 [自动检测]
--disable-twolame                  禁用 Twolame (MPEG layer 2) 编码 [自动检测]
--enable-xmms                      XMMS 输入插件支持 [无效]
--enable-libdca                    libdca 支持 [自动检测]
--disable-mp3lib                   禁用内建 mp3lib [有效]
--disable-liba52                   禁用内建 liba52 [有效]
--disable-libmpeg2                 禁用内建 libmpeg2 [有效]
--disable-musepack                 禁用 musepack 支持 [自动检测]
--disable-libamr_nb                禁用 libamr 窄频 [自动检测]
--disable-libamr_wb                禁用 libamr 宽频 [自动检测]
--disable-decoder=DECODER          禁用指定 FFmpeg 解码器
--enable-decoder=DECODER           使用指定 FFmpeg 解码器
--disable-encoder=ENCODER          禁用指定 FFmpeg 编码器
--enable-encoder=ENCODER           使用指定 FFmpeg 编码器
--disable-parser=PARSER            禁用指定 FFmpeg 分析器
--enable-parser=PARSER             使用指定 FFmpeg 分析器

--disable-demuxer=DEMUXER           禁用指定 FFmpeg 分离器 (demuxer)
--enable-demuxer=DEMUXER            使用指定 FFmpeg 分离器
--disable-muxer=MUXER               禁用指定 FFmpeg 合并器 (muxer)

--enable-muxer=MUXER                使用指定 FFmpeg 合并器

视频输出:
--disable-vidix-internal            禁用内部 VIDIX [for x86 *nix]
--disable-vidix-external           禁用内部 VIDIX [for x86 *nix]
--with-vidix-drivers[=*]           VIDIX 驱动编译列表
                                   可用: cyberblade,ivtv,mach64,mga,mga_crtc2,
                                   nvidia,pm2,pm3,radeon,rage128,savage,sis,unichrome
--enable-gl                        OpenGL 视频输出[自动检测]
--enable-dga2                      DGA 2 支持 [自动检测]
--enable-dga1                      DGA 1 支持 [自动检测]
--enable-vesa                      VESA 视频输出 [自动检测]
--enable-svga                      SVGAlib 视频输出 [自动检测]
--enable-sdl                       SDL 视频输出 [自动检测]
--enable-aa                        AAlib 视频输出 [自动检测]
--enable-caca                      CACA 视频输出 [自动检测]
--enable-ggi                       GGI 视频输出 [自动检测]
--enable-ggiwmh                    GGI libggiwmh 扩展 [自动检测]
--enable-directx                   DirectX 视频输出 [自动检测]
--enable-dxr2                      DXR2 视频输出 [自动检测]
--enable-dxr3                      DXR3/H+ 视频输出 [自动检测]
--enable-ivtv                      IVTV TV-Out 视频输出 [自动检测]
--enable-v4l2                      V4L2 Decoder 音频/视频输出 [自动检测]
--enable-dvb                       DVB 视频输出 [自动检测]
--enable-dvbhead                   DVB 视频输出 (HEAD version) [自动检测]
--enable-mga                       mga_vid 视频输出 [自动检测]
--enable-xmga                      mga_vid X11 视频输出 [自动检测]
--enable-xv                        Xv 视频输出 [自动检测]
--enable-xvmc                      XvMC 加速 [无效]
--enable-vm                        XF86VidMode 支持 [自动检测]
--enable-xinerama                  Xinerama 支持 [自动检测]
--enable-x11                       X11 视频输出 [自动检测]
--enable-xshape                    XShape 支持 [自动检测]
--enable-fbdev                     FBDev 视频输出 [自动检测]
--enable-mlib                      mediaLib 视频输出 (Solaris) [无效]
--enable-3dfx                      obsolete /dev/3dfx 视频输出 [无效]
--enable-tdfxfb                    tdfxfb 视频输出 [无效]
--enable-s3fb                       s3fb (S3 ViRGE) 视频输出 [无效]
--enable-directfb                  DirectFB 视频输出 [自动检测]
--enable-zr                        ZR360[56]7/ZR36060 视频输出 [自动检测]
--enable-bl                        Blinkenlights 视频输出 [无效]
--enable-tdfxvid                   tdfx_vid 视频输出 [disable]
--enable-xvr100                    SUN XVR-100 视频输出 [自动检测]
--disable-tga                      禁用 Targa 视频输出 [有效]
--disable-pnm                      禁用 PNM 视频输出 [有效]
--disable-md5sum                   禁用 md5sum 视频输出 [有效]

音频输出:
--disable-alsa                     禁用 ALSA 音频输出 [自动检测]
--disable-ossaudio                 禁用 OSS 音频输出 [自动检测]
--disable-arts                     禁用 aRts 音频输出 [自动检测]
--disable-esd                       禁用 esd 音频输出 [自动检测]
--disable-polyp                    禁用 Polypaudio 音频输出 [自动检测]
--disable-jack                      禁用 JACK 音频输出 [自动检测]
--disable-openal                   禁用 OpenAL 音频输出 [自动检测]
--disable-nas                      禁用 NAS 音频输出 [自动检测]
--disable-sgiaudio                 禁用 SGI 音频输出 [自动检测]
--disable-sunaudio                 禁用 Sun 音频输出 [自动检测]
--disable-win32waveout             禁用 Windows waveout 音频输出 [自动检测]
--disable-select                   在音频设备中禁用 select() [有效]

杂项:
--enable-runtime-cpudetection      运行时 CPU 检测 [无效]
--enable-cross-compile             交叉编译 [自动检测]
--cc=COMPILER                      生成 MPlayer 的 C 编译器 [gcc]
--host-cc=COMPILER                 生成 Mplayer 时的必要工具的 C 编译器 [gcc]
--as=ASSEMBLER                      生成 MPlayer 的汇编 [as]
--ar=AR                             生成 MPlayer 的库集 [ar]
--ranlib=RANLIB                    生成 MPlayer 的 ranlib [ranlib]
--target=PLATFORM                  目标平台 (i386-linux, arm-linux, etc)
--enable-static                    生成静态的二进制链接
--charset=charset                  将控制台信息转化到字符集
--language=list                     空格或者逗号分隔在用户手册中使用的语言,第一个将会
在信息和GUI中使用(环境变量 $LINGUAS 也会加入) [en]
                                   (可用: bg cs de dk el en es fr hu it ja ko mk nb nl pl ro ru sk sv tr uk pt_BR zh_CN zh_TW all)
--with-install=PATH                已装程序路径
--enable-color-console              彩色控制台输出(不支持) [无效]

高级选项:
--enable-mmx                       MMX [自动检测]
--enable-mmxext                     MMX2 (Pentium III, Athlon) [自动检测]
--enable-3dnow                     3DNow! [自动检测]
--enable-3dnowext                  扩展 3DNow! [自动检测]
--enable-sse                       SSE [自动检测]
--enable-sse2                      SSE2 [自动检测]
--enable-ssse3                     SSSE3 [自动检测]
--enable-shm                       shm [自动检测]
--enable-altivec                   AltiVec (PowerPC) [自动检测]
--enable-armv5te                   DSP 扩展 (ARM) [自动检测]
--enable-armv6                     ARMv6 (ARM) [自动检测]
--enable-iwmmxt                     iWMMXt (ARM) [自动检测]
--disable-fastmemcpy                禁用 3DNow!/SSE/MMX 优化 memcpy [有效]
--enable-big-endian                强制将字节按照 Big-endian 规则排放 [自动检测]
--enable-debug[=1-3]               编译调试(debugging)信息 [无效]
--enable-profile                   编译记录(profiling)信息 [无效]
--disable-sighandler               禁用崩溃时 sighandler [有效]
--enable-crash-debug               自动链接 gdb 到崩溃位置 [无效]
--enable-dynamic-plugins           动态 A/V 插件 [无效]

危险的选项“不报告任何错误!”
--disable-gcc-check                禁用 gcc 版本检测 [有效]

自动检测失败时使用 (用(*)标记的选项之间用 ':' 分割
--extra-libs=FLAGS                  额外链接标志
--extra-libs-mplayer=FLAGS         MPlayer 额外链接标志
--extra-libs-mencoder=FLAGS        MEncoder 额外链接标志
--with-extraincdir=DIR             DIR 中额外头文件寻找路径 (*)
--with-extralibdir=DIR             DIR 中额外的链接器寻找路径 (*)
--with-xvmclib=NAME                 适配器指定的库名 (e.g. XvMCNVIDIA)

--with-freetype-config=PATH        freetype-config 路径
--with-fribidi-config=PATH          fribidi-config 路径
--with-glib-config=PATH            glib*-config 路径
--with-gtk-config=PATH             gtk*-config 路径
--with-sdl-config=PATH             sdl*-config 路径
--with-dvdnav-config=PATH          dvdnav-config 路径

posted @ 2008-09-05 16:41 puppy 阅读(1418) | 评论 (0)编辑 收藏

diff和patch是一对工具,在数学上来说,diff是对两个集合的差运算,patch是对两个集合的和运算。
diff比较两个文件或文件集合的差异,并记录下来,生成一个diff文件,这也是我们常说的patch文件,即补丁文件。
patch能将diff文件运用于 原来的两个集合之一,从而得到另一个集合。举个例子来说文件A和文件B,经过diff之后生成了补丁文件C,那么着个过程相当于 A -B = C ,那么patch的过程就是B+C = A 或A-C =B。
因此我们只要能得到A, B, C三个文件中的任何两个,就能用diff和patch这对工具生成另外一个文件。

这就是diff和patch的妙处。下面分别介绍一下两个工具的用法(待续)

1. diff的用法

diff后面可以接两个文件名或两个目录名。 如果是一个目录名加一个文件名,那么只作用在那么个目录下的同名文件。

如果是两个目录的话,作用于该目录下的所有文件,不递归。如果我们希望递归执行,需要使用-r参数。

命令diff A B > C ,一般A是原始文件,B是修改后的文件,C称为A的补丁文件。
不加任何参数生成的diff文件格式是一种简单的格式,这种格式只标出了不一样的行数和内容。我们需要一种更详细的格式,可以标识出不同之处的上下文环境,这样更有利于提高patch命令的识别能力。这个时候可以用-c开关。
2. patch的用法

patch用于根据原文件和补丁文件生成目标文件。还是拿上个例子来说

patch A C 就能得到B, 这一步叫做对A打上了B的名字为C的补丁。

之一步之后,你的文件A就变成了文件B。如果你打完补丁之后想恢复到A怎么办呢?

patch -R B C 就可以重新还原到A了。

所以不用担心会失去A的问题。

其实patch在具体使用的时候是不用指定原文件的,因为补丁文件中都已经记载了原文件的路径和名称。patch足够聪明可以认出来。但是有时候会 有点小问题。比如一般对两个目录diff的时候可能已经包含了原目录的名字,但是我们打补丁的时候会进入到目录中再使用patch,着个时候就需要你告诉 patch命令怎么处理补丁文件中的路径。可以利用-pn开关,告诉patch命令忽略的路径分隔符的个数。举例如下:

A文件在 DIR_A下,修改后的B文件在DIR_B下,一般DIR_A和DIR_B在同一级目录。我们为了对整个目录下的所有文件一次性diff,我们一般会到DIR_A和DIR_B的父目录下执行以下命令

diff -rc DIR_A DIR_B > C

着个时候补丁文件C中会记录了原始文件的路径为 DIR_A/A

现在另一个用户得到了A文件和C文件,其中A文件所在的目录也是DIR_A。 一般,他会比较喜欢在DIR_A目录下面进行patch操作,它会执行

patch < C

但是这个时候patch分析C文件中的记录,认为原始文件是./DIR_A/A,但实际上是./A,此时patch会找不到原始文件。为了避免这种情况我们可以使用-p1参数如下

patch -p1 < C

此时,patch会忽略掉第1个”/”之前的内容,认为原始文件是 ./A,这样就正确了。

最后有以下几点注意:

  1. 一次打多个patch的话,一般这些patch有先后顺序,得按次序打才行。
  2. 在patch之前不要对原文件进行任何修改
  3. 如果patch中记录的原始文件和你得到的原始文件版本不匹配(很容易出现),那么你可以尝试使用patch, 如果幸运的话,可以成功。大部分情况下,会有不匹配的情况,此时patch会生成rej文件,记录失败的地方,你可以手工修改。
posted @ 2008-08-29 18:07 puppy 阅读(263) | 评论 (0)编辑 收藏
      被阴了一把.
      做M2M终端协议的时候,报文封装都是按照little-endian来处理的。与服务器那边却总是连不上,后来把数据发过去核对,才发现服务器那边只认big-endian,即所谓的网络序。问题是协议里面并没有明确说明要这样做,没办法,只好再花时间加上htons、ntohs。
      在网络上发送数据之前,一般的做法的确是要转换成网络顺序发送。下次在做网络协议时一定要事先弄清楚,切记!

为了保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换 bsd socket提供了转换的函数 有下面四个:
 (s -- short    l -- long    h -- host   n -- network)
htons 
unsigned short类型从主机序转换到网络序
htonl 
unsigned long类型从主机序转换到网络序
ntohs 
unsigned short类型从网络序转换到主机序
ntohl 
unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换 
在使用big endian类型的系统中 这些函数会定义成空宏
同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.


不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器    操作系统    字节排序
Alpha    
全部    Little endian
HP-PA    NT    Little endian
HP-PA    UNIX    Big endian
Intelx86    
全部    Little endian <-----x86系统是小端字节序系统
Motorola680x()    
全部    Big endian
MIPS    NT    Little endian
MIPS    UNIX    Big endian
PowerPC    NT    Little endian
PowerPC    
NT    Big endian  <-----PPC系统是大端字节序系统
RS/6000    UNIX    Big endian
SPARC    UNIX    Big endian
ARM
    全部    Little endian 
posted @ 2008-08-27 15:07 puppy 阅读(590) | 评论 (0)编辑 收藏

 

Linux块设备层分析(2)

R.wen

三、块设备驱动层

块设备的关系图如图2,一个分区或一个硬盘都可能是block_device,它一个硬盘只有一个gendisk结构,且有可能有多个分区hd_struct


 

 

图2

我们来看一个IDE硬盘设备的驱动,在此我们不关心IDE总线的驱动,只是将其执行路线列出来。

static int ide_init_queue(ide_drive_t *drive)

{

       request_queue_t *q;

       ide_hwif_t *hwif = HWIF(drive);

       int max_sectors = 256;

       int max_sg_entries = PRD_ENTRIES;

       //分配一个请求队列,由IDE总线去帮助完成,简化了特定块设备的工作

       q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));

      

       //初始化队列中的一些参数

       q->queuedata = drive;

       blk_queue_segment_boundary(q, 0xffff);

……

       blk_queue_max_hw_segments(q, max_sg_entries);

       blk_queue_max_phys_segments(q, max_sg_entries);

       /* assign drive queue */

       drive->queue = q;

       return 0;

}

request_queue_t *

blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)

{

       request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);

      

       q->node = node_id;

       if (blk_init_free_list(q)) {

              kmem_cache_free(requestq_cachep, q);

              return NULL;

       }

       q->request_fn        = rfn; //由上可以看到,在ide-disk中,为do_ide_request

       q->prep_rq_fn              = NULL;

       q->unplug_fn         = generic_unplug_device;

       q->queue_flags             = (1 << QUEUE_FLAG_CLUSTER);

       q->queue_lock              = lock;

       blk_queue_segment_boundary(q, 0xffffffff);

       blk_queue_make_request(q, __make_request);

       blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);

       blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);

       blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);

       /*

       * all done

       */

       if (!elevator_init(q, NULL)) { //设置队列的IO调度算法

              blk_queue_congestion_threshold(q);

              return q;

       }

       blk_put_queue(q);

       return NULL;

}

由上可见,当unplug一个块设备时,它将执行do_ide_request()

void do_ide_request(request_queue_t *q)

{

       ide_drive_t *drive = q->queuedata;

       ide_do_request(HWGROUP(drive), IDE_NO_IRQ);

}

static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)

{

       ide_drive_t      *drive;

       ide_hwif_t      *hwif;

       struct request *rq;

       ide_startstop_t       startstop;

       int             loops = 0;

       /* for atari only: POSSIBLY BROKEN HERE(?) */

       ide_get_lock(ide_intr, hwgroup);

       /* caller must own ide_lock */

       BUG_ON(!irqs_disabled());

       while (!hwgroup->busy) {

              hwgroup->busy = 1;

              drive = choose_drive(hwgroup); //选择硬盘

              ……

       again:

              hwif = HWIF(drive);

              if (hwgroup->hwif->sharing_irq &&

                  hwif != hwgroup->hwif &&

                  hwif->io_ports[IDE_CONTROL_OFFSET]) {

                     /* set nIEN for previous hwif */

                     SELECT_INTERRUPT(drive);

              }

              hwgroup->hwif = hwif;

              hwgroup->drive = drive;

              drive->sleeping = 0;

      

              /*

              * we know that the queue isn't empty, but this can happen

              * if the q->prep_rq_fn() decides to kill a request

              */

              rq = elv_next_request(drive->queue); //取下一个请求

              if (!rq) {

                     hwgroup->busy = 0;

                     break;

              }

              hwgroup->rq = rq;

              local_irq_enable_in_hardirq();

                     /* allow other IRQs while we start this request */

              startstop = start_request(drive, rq); //开始向磁盘写入该请求

              spin_lock_irq(&ide_lock);

              if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)

                     enable_irq(hwif->irq);

              if (startstop == ide_stopped)

                     hwgroup->busy = 0;

       }

}

static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)

{

       ide_startstop_t startstop;

       sector_t block;

       block    = rq->sector;

       if (blk_fs_request(rq) &&

           (drive->media == ide_disk || drive->media == ide_floppy)) {

              block += drive->sect0;

       }

       SELECT_DRIVE(drive);

       if (!drive->special.all) {

              ide_driver_t *drv;

       ……

              if (rq->cmd_type == REQ_TYPE_ATA_CMD ||

                  rq->cmd_type == REQ_TYPE_ATA_TASK ||

                  rq->cmd_type == REQ_TYPE_ATA_TASKFILE)

                     return execute_drive_cmd(drive, rq);

              else if (blk_pm_request(rq)) {

                     ……

                     return startstop;

              }

              drv = *(ide_driver_t **)rq->rq_disk->private_data;

              return drv->do_request(drive, rq, block);

       }

}

posted @ 2008-08-22 15:19 puppy 阅读(440) | 评论 (0)编辑 收藏

Linux块设备层分析(3)

R.wen


以上均是IDE总线上设备的通用接口,直到do_request开始才执行特定设备的驱动,如CDHD, floppyIDE设备。我们来看一下ide-disk

1、 首先是设备的初始化操作。

IDE设备接口

static ide_driver_t idedisk_driver = {

       .gen_driver = {

              .owner           = THIS_MODULE,

              .name             = "ide-disk",

              .bus        = &ide_bus_type,

       },

       .probe                   = ide_disk_probe,

       .remove                 = ide_disk_remove,

       .shutdown             = ide_device_shutdown,

       .version          = IDEDISK_VERSION,

       .media                   = ide_disk,

       .supports_dsc_overlap   = 0,

       .do_request            = ide_do_rw_disk,

       .end_request          = ide_end_request,

       .error                    = __ide_error,

       .abort                    = __ide_abort,

       .proc                     = idedisk_proc,

};

static struct block_device_operations idedisk_ops = {

       .owner           = THIS_MODULE,

       .open             = idedisk_open,

       .release    = idedisk_release,

       .ioctl              = idedisk_ioctl,

       .getgeo           = idedisk_getgeo,

       .media_changed     = idedisk_media_changed,

       .revalidate_disk= idedisk_revalidate_disk

};

//设备注册

static int __init idedisk_init(void)

{

       return driver_register(&idedisk_driver.gen_driver);

}

//这个probe函数是在设备注册时由驱动模型去执行

static int ide_disk_probe(ide_drive_t *drive)

{

       struct ide_disk_obj *idkp;

       struct gendisk *g;

       idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);

      

//分配一个gendisk结构

g = alloc_disk_node(1 << PARTN_BITS,

                     hwif_to_node(drive->hwif));

       ide_init_disk(g, drive);

       //用上面的结构注册设备

       ide_register_subdriver(drive, &idedisk_driver);

       kref_init(&idkp->kref);

       //一些初始化操作

       idkp->drive = drive;

       idkp->driver = &idedisk_driver;

       idkp->disk = g;

       g->private_data = &idkp->driver;

       drive->driver_data = idkp;

       idedisk_setup(drive);

       g->minors = 1 << PARTN_BITS;

       g->driverfs_dev = &drive->gendev;

       g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;

       set_capacity(g, idedisk_capacity(drive));

       g->fops = &idedisk_ops;

       add_disk(g); //插入设备,至此,该设备可用

       return 0;

}

2、 处理IDE总线发来的请求

由上可以看到,IDE总线驱动调用设备的do_request()去处理这个请求,我们在上面的注册中可以看到。在ide-disk里,它是ide_do_rw_disk()

/*

* 268435455 == 137439 MB or 28bit limit

* 320173056 == 163929 MB or 48bit addressing

* 1073741822 == 549756 MB or 48bit addressing fake drive

*/

static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)

{

       ide_hwif_t *hwif = HWIF(drive);

……

       if (hwif->rw_disk)

       hwif->rw_disk(drive, rq);

       return __ide_do_rw_disk(drive, rq, block);

}

//以下就是特定硬盘设备的驱动了,因为我们只关心块设备驱动编程的框架,所以就不深入进去了。

/*

* __ide_do_rw_disk() issues READ and WRITE commands to a disk,

* using LBA if supported, or CHS otherwise, to address sectors.

*/

static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)

{

       ide_hwif_t *hwif    = HWIF(drive);

       unsigned int dma    = drive->using_dma;

       u8 lba48         = (drive->addressing == 1) ? 1 : 0;

       task_ioreg_t command   = WIN_NOP;

       ata_nsector_t         nsectors;

       nsectors.all            = (u16) rq->nr_sectors;

       if (hwif->no_lba48_dma && lba48 && dma) {

              if (block + rq->nr_sectors > 1ULL << 28)

                     dma = 0;

              else

                     lba48 = 0;

       }

       if (drive->select.b.lba) {

              if (lba48) {

                     ……

              } else {

              ……

              }

       } else {

              ……

       }

       if (dma) {

              ……

              /* fallback to PIO */

              ide_init_sg_cmd(drive, rq);

       }

       if (rq_data_dir(rq) == READ) {

              if (drive->mult_count) {

                     hwif->data_phase = TASKFILE_MULTI_IN;

                     command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;

              } else {

                     hwif->data_phase = TASKFILE_IN;

                     command = lba48 ? WIN_READ_EXT : WIN_READ;

              }

              ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);

              return ide_started;

       } else {

       ……

              return pre_task_out_intr(drive, rq);

       }

}

3、 块设备驱动小结

我们由上看到, 块设备驱动编程的主要工作包括分配并初始化一个gendisk结构,分配并初始化一个请求队列,请求处理函数的编写(request_fn),还有中断的处理等等。但具体到不同的设备,实现又有一些出入,我们在上面看到的IDE设备,它大部分工作都是在IDE总线级上实现了,它做了许多繁琐但必要的工作,并向下层特定设备提供统一的接口,这样就大大简化了块设备驱动的编写过程。

       有兴趣可以参考一下内核ramdisk的实现。

posted @ 2008-08-22 15:19 puppy 阅读(479) | 评论 (0)编辑 收藏
仅列出标题
共5页: 1 2 3 4 5