2009年2月18日星期三

gst看一下2

set_state能发送给管道中所有元件的change_state函数
每个元件的change_state函数中都会调用parent_class的change_state,
playbin--(parent)-->playbasebin
playbasebin--(parent)-->pipeline
pipeline--(parent)-->bin
最上一级是bin,看bin的change_state函数,

while (!done) {
gpointer data;

switch (gst_iterator_next (it, &data)) {
case GST_ITERATOR_OK:
{
GstElement *child;

child = GST_ELEMENT_CAST (data);

/* set state and base_time now */
ret = gst_bin_element_set_state (bin, child, base_time, current, next);
把bin里的元件一个个取出来发送set_state命令,这样所有元件都会改变状态了

gstclock获得时钟的3种方式
1 systemclock系统时钟
2 音频设备 基于采样率而知道的时钟
3 网络包中包含的时钟信息

我只看过systemclock, gstclock->gstsystemtclock->g_get_current_time->gettimeofday->(system call)

音视频时间同步到系统时间
并不是音频和视频谁同步谁,而是大家都跟系统时间同步
NS...B...B...EOS NS=new segment
C.running_time = absolute_time - base_time (系统)
B.running_time = (B.timestamp - NS.start)/NS.abs_rate + NS.accum (元件)
同步就是让B,C的running_time相等, B等待
base_time从NEW_SEGMENT事件发出为基准,比如seek后就是NEW SEGMENT

_class_init给klass挂函数指针

gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass;
把一个klass转换为3种数据结构,可以的原因是一级级都是数据结构的第一个成员,传进来的kclass是最大的数据结构,往小转当然可以

struct _GstBaseAudioSink {
GstBaseSink element;

struct _GstBaseSink {
GstElement element;

struct _GstElement
{
GstObject object;

状态变迁
NULL-->READY
1 probe device
2 open device

READY-->PAUSED
1 激活pad,返回ASYNC,然后起stream thread线程才把状态改变的事情做完,直到sink pad收到first buffer,阻塞住,这时才真正算状态改变完,用get_state可以查询到
2 管道running_time归零
3 如果是live source返回NO_PREROLL,不产生数据(live source是即使暂停也会产生数据的源,比如net和camera)

PAUSED-->PLAYING (大部分元件忽略这个状态)
1 管道选择时钟分发到每个子元件,也就是同步时钟只发生在PLAYING时
2 管道把clock running_time计算出来的base_time分发到每个子元件(change_state时)
3 sink衬垫不再阻塞buffer/event,开始render数据
4 live source开始产生数据

PLAYING-->PAUSED (大部分元件忽略这个状态)
1 如果sink此时无buffer在手一定要等收到buffer才能完成状态改变。看上面的READY->PAUSED也是sink在进入PAUSED前一定要有buffer,为了PLAYING时不至于让用户等待前面的一小撮时间
2 EOS事件无效,但到PLAYING时会repost
3 sink把preroll上的所有等待都解除阻塞
4 live source停止产生数据

PAUSED-->READY
1 sink解除阻塞preroll,元件解除阻塞设备
2 chain和get_range 返回WRONG_STATE,(buffer相关的函数)
3 pad使无效(deactivate),stream thread停止
4 sink忘记所有的协商格式(negotiation caps)

READY-->NULL
1 close device
2 删除所有动态建立的pads

2009年2月16日星期一

gst看一下1

1. 目录结构
gstreamer-0.10.21 目录
gst 核心文件,实现gst元件工厂等功能
plugins gstreamer-0.10.21提供的元件
lib 不可被应用调用的元件,但他是某些元件的parent class
pkgconfig install tools 都是make install需要拷贝的东西
po 各种语言的翻译文件
tests 测试gstreamer-0.10.21的元件

gst-plugins-base-0.10.21 目录
gst base提供的元件
gst-libs base提供的元件的parent class,应用不可用的元件
ext 需要额外源码库的元件
sys 系统相关的元件(x11,v4l)这2个window就没有

2.细数元件
看gst有哪些元件就看哪些文件调用了gst_element_register
grep -nr 'gst_element_register' --include=*.c ./

gstreamer的元件统一注册,别的元件基本都是单独注册
static struct _elements_entry _elements[] = {
{"capsfilter", GST_RANK_NONE, gst_capsfilter_get_type},
{"fakesrc", GST_RANK_NONE, gst_fake_src_get_type},
{"fakesink", GST_RANK_NONE, gst_fake_sink_get_type},
#ifdef HAVE_SYS_SOCKET_H
{"fdsrc", GST_RANK_NONE, gst_fd_src_get_type},
{"fdsink", GST_RANK_NONE, gst_fd_sink_get_type},
#endif
{"filesrc", GST_RANK_PRIMARY, gst_file_src_get_type},
{"identity", GST_RANK_NONE, gst_identity_get_type},
{"queue", GST_RANK_NONE, gst_queue_get_type},
{"filesink", GST_RANK_PRIMARY, gst_file_sink_get_type},
{"tee", GST_RANK_NONE, gst_tee_get_type},
{"typefind", GST_RANK_NONE, gst_type_find_element_get_type},
{"multiqueue", GST_RANK_NONE, gst_multi_queue_get_type},
{NULL, 0},
};

3.playbin(只说playbin播放视频的情况)
playbin元件算是整合的元件,内部建立工厂管道,用到很多元件。

3.1元件流程图
filesrc --> (typefind) -->decodebin -->|--> abin (audioconvert-->audioresample-->volume-->osssink)
··························································|--> vbin (identity-->ffmpegcolorspace-->videoscale-->fbdevsink)

3.2代码分析
应用程序建立playbin元件后就调用get_element_set_state将playbin设置为NULL,READY,PAUSED,PLAYING, 在READY-->PAUSED时候(GST_STATE_CHANGE_READY_TO_PAUSED),playbin就把管道建立起来了

gst_play_base_bin_change_state
|----setup_source
|----|----gen_source_element 建立source元件,也就是filesrc
|----|----|----if (play_base_bin->suburi) setup_subtitle 如果playbin的suburi属性被设置了就配置字幕元件
|----|----|----gst_element_make_from_uri
|----|----|----|----get_element_factories_from_uri_protocol根据字符串头uri协议search_by_entry确定工厂类型,比如file://则建立filesrc
|----|----|----gst_element_factory_create根据确定的工厂类型建立元件(filesrc)

|----|----analyse_source分析源是否是raw数据/有动态pad/有输出pad再做相应处理
|----|----|----几种情况都会走到group_commit
|----|----|----|----GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
setup_output_pads 也就是gstplaybin.c的setup_sinks

|----|----|----|----|----有音频需要可视化调用gen_vis_element
|----|----|----|----|----有音频不需要可视化调用gen_audio_element
|----|----|----|----|----有视频调用gen_video_element

|----|----make_decoder
|----|----|----gst_element_factory_make("decodebin", NULL)建立decodebin元件
|----|----gst_element_link (play_base_bin->source, decoder)把filesrc和decodebin链接起来

3.3 playbin目录
目录是gst-plugins-base-0.10.21/gst/playback/
原本看着文件挺多,不过是2套playbin,其中一套是非稳定版本playbin2,所以其实真正要看的文件不多 。
gstplayback.c注册playbin和playbin2
playbin用到的C文件有(主要是playbin, playbasebin, decodebin)
gstplaybin.c
gstplaybasebin.c
gstdecodebin.c
gststreaminfo.c
gststreamselector.c
gstplaymarshal.c

playbin2用到的C文件有(与playbin,playbasebin, decodebin等价的是playbin2,playsink, decodebin2)
gstplaybin2.c
gstplaysink.c
gstdecodebin2.c
及剩下的一些文件,gsturidecodebin.c和gstdecodebin2.c也是非稳定版本

3.4 playbin元件用到的parent class

filesrc的parent_class是basesrc,从下面可以看出来,
GST_BOILERPLATE_FULL (GstFileSrc, gst_file_src, GstBaseSrc, GST_TYPE_BASE_SRC,
_do_init);

当用户调用set_state时对应内部change_state, 会调用该元件的parent class的change_state。basesrc就像是filesrc的基类

osssink的parent_class是audiosink,从下面可以看出来,
osssink_type = g_type_register_static (GST_TYPE_AUDIO_SINK, "GstOssSink", &osssink_info, 0);

osssink只是做跟底层相关的工作,音频的逻辑层还是在audiosink和它的parent audiobasesink里面,他们再调用osssink的函数指针做具体读写声卡的操作

3.5 元件的parent class
因为change_state会分发到管道中的每个元件,元件的change_state里都会调用它parent_class的change_state,所以不免想看看playbin的parent_class
struct _GstPlayBin {
GstPlayBaseBin parent;

struct _GstPlayBaseBin {
GstPipeline pipeline;

playbin-->playbasebin-->pipeline已经到管道了

2009年1月16日星期五

在板子上使用交换分区

1. 内核勾上swap选项,
General setup --->[*] Support for paging of anonymous memory (swap) (y)
2.编译busybox时要有swapon命令
3.做交换分区文件8M
dd if=/dev/zero of=swapfile bs=1M count=8 //建立一个8M空文件
mkswap swapfile //格式化
sync //确保写进去了
4.把文件拷到板子上,添加到swap(如果文件在nfs上,执行swapon会出错)
swapon swapfile

添加以后可以在/proc/meminfo看到swap信息,

2009年1月7日星期三

(转){nfs:server is not responding,still trying} 解决办法

原文地址:http://hi.baidu.com/rjz78/blog/item/a3e6e7ee6276512e2cf53447.html

描述:我在arm上通过NFS共享文件时出现下面的错误提示
nfs:server is not responding,still trying

原因分析:NFS 的默认传输协议是 UDP,而PC机与嵌入式系统通过UPD交互时就会出现严重的网卡丢包现象。

解决方法:在客户端改用TCP协议,使用下面的命令,

#mount -t nfs -o nolock -o tcp 192.168.1.161:/opt /opt

(转)Fedora 启动过程

原文地址:http://blog.chinaunix.net/u/22418/showart_1356101.html

在 Intel i386 体系结构下,不同发行版本的 Linux 的启动过程有很多相似之处。

  • bios 读取位于第一个扇区(硬盘或光盘的主引导记录,简称 MBR)的 Linux 内核加载器。
  • 内核加载器加载内核。新的发行版本使用的大多是 2.6 系列的内核,不过 2.4 系列的内核仍然得到广泛的应用。
  • 运行 Init 进程并执行多个脚本。

如果从硬盘启动 Linux,内核加载器(Intel 兼容体系结构)主要使用的是 Lilo 或 Grub。如果从光盘引导 Linux,比如:Live CD 或安装盘,则常选择 Syslinux 作为内核加载器。

在配置文件 /etc/lilo.conf/boot/grub/grub.conf 中你可以设置:

  • 内核加载器安装在哪里(主引导记录还是单个分区的引导记录)。
  • 指定系统根文件系统(/)所在的分区。
  • 内核 image 和 initrd 的路径。

你可以配置启动不同的操作系统(Linux 或是其它的操作系统)和不同版本的内核。

每一个发行版本的 Linux 内核都源自 Linus Torvalds 内核,但是可能会具有不同的版本机制,或由版本的维护者加入的非 Linus 补丁。

你可以重新并编译安装官方的内核代码或不同发行版本的内核源码包。

Unix 系统启动的第一个进程总是 Init 进程,它的配置文件总是 /etc/inittab。分析 /etc/inittab 和所有被它 source 的脚本,你就可以完全地了解系统的启动过程。

Linux/Unix 的主要区别大多是 shell(初始化)脚本的不同。

很多的 Linux 发行版使用 Unix System V 的启动方法。基于 rc 脚本,根据不同的运行级别启动 /etc/init.d/ 下相应的脚本。

RedHat

/etc/rc.d/rc.sysinit

由 init 进程调用,它设置和执行所有的系统初始化函数,并 source /etc/sysconfig/* 目录下的配置文件。

/etc/rc.d/functions

被其它系统脚本使用的通用函数。

/etc/rc.d/*

所有系统服务的启动和关闭脚本。系统启动时根据用户指定的运行级别执行 /etc/rc#runlevel.d/(“#runlevel”为运行级别,一般为 1,3,5)目录下的脚本文件。
注意:/etc/rc#runlevel.d/ 目录下的脚本只是到 /etc/rc.d/ 目录下的脚本的一个链接。


Fedora - 启动过程


Fedora 采用 RedHat 的方式来启动系统。

Boot Loader

Fedora 使用 Grub 作为启动加载器,所有的配置文件和二进制文件都在 /boot/grub/ 目录下,grub.conf 包含所有的配置信息(/boot/grub/menu.lst 和 /etc/grub.conf 都是指向它的链接),/boot/grub/splash.xpm.gz 是 grub 启动时的默认背景图片。

Kernel

主要的二进制文件为 /boot/vmlinuz-version,系统符号(System Map)文件为 /boot/System.map-version,启动时初始化内存的文件为 /boot/initrd-version。当前内核的完整配置文件为 /boot/config-version。

内核模块位于 /lib/modules/version 目录下。

Init

/etc/inittab 有一个规定,mingetty 优先于运行级别 1 启动(所以单用户模式下不需要密码就可以直接使用 root shell)。不论什么运行级别,系统执行的第一个初始化脚本都是 /etc/rc.d/rc.sysinit,然后执行 /etc/rc#runlevel.d 目录下的脚本启动各种系统服务。

系统配置文件大多放在 /etc/sysconfig/ 下,在启动阶段被加载(sourced)。

/etc/rc.d/rc.sysinit 负责各种各样的启动工作,顺序如下

  • 根据 /etc/initlog.conf 和 /etc/syslog.conf 的设置,使用 initlog 来记录运行情况。
  • 如果使用 DEVFS,就启动 devfsd 服务。
  • 设置 hostname,hosttype 并加载(source) /etc/sysconfig/network
  • 挂载 procfs 和 sysfs 到 /proc 和 /sys 目录下
  • 检查 SeLinux 状态
  • 加 载(source) /etc/init.d/functions,该脚本包含被其它脚本用到的通用 shell 函数,包括:daemon(),killproc(),pidofproc(),status(),echo_success()(绿色的 OK),confirm()等等,并加载(source)其它重要的系统配置文件:/etc/sysconfig/i18n, /etc/sysconfig/init 等。
  • 设置系统默认字体。
  • 打印熟悉的 “Welcome to ...” 标志
  • 运行图形化的启动程序 rhgb,更改 /usr/share/rhgb 目录下的图片可以定制启动界面。
  • 根据 /etc/sysctl.conf 的设置来配置内核
  • 根据 /etc/sysconfig/clock 文件的参数来设置系统时钟
  • 根据 /etc/sysconfig/keyboard 的设置来配置键盘布局,改变 /etc/sysconfig/keyboard 文件的设置来定制文本模式下的键盘设定。
  • 初始化 ACPI 设定
  • 初始化 USB 控制器和 HID 设备
  • 查看 /fastboot,/fsckoptions,/forcefsck 和 /.autofsck 文件并加载(source) /etc/sysconfig/autofsck 来决定是否及如何进行文件系统检查。
  • 检查磁盘配额
  • 根据 /etc/isapnp.conf 初始化 ISA PNP 设备。
  • 以读写方式挂载根文件系统
  • 如果启用则启动逻辑卷管理(LVM)
  • 激活交换空间(swap)
  • 使用 /etc/modules.conf 中指定的参数来加载内核模块
  • 启动 raid(MD)设备
  • 如果存在 /.unconfigured 标志文件,则运行系统第一次启动必须的配置。
  • 删除 /,/var/lock,/var/run 目录下的标志文件,删除 rpm 数据库文件(/var/lib/rpm/__db*)和 /tmp 目录下的各种文件。
  • 初始化串口,SCSI 磁带,USB 存储器,Firewire
  • hdparm 程序根据 /etc/sysconfig/harddisks* 文件的配置开启硬盘优化。
  • 如果存在网络配置文件,则激活默认网络配置。

完成上述步骤后,系统进入默认的运行级别并激活 /etc/rc#runlevel.d/ 目录下的服务。

最后,系统将执行 /etc/rc.local 脚本。在这里,用户可以方便地添加希望在系统启动时运行的命令。