GStreamer 插件开发指南

GStreamer 插件开发指南
GStreamer 插件开发指南

GStreamer 插件开发指南(0.10.9.1)

I. 介绍

GStreamer是一个用来创建流媒体应用程序的非常强大和通用的框架。GStreamer框架的许多优点来源于它的模块性:GStreamer可以无缝地接纳新的插件模块。但是由于模块性和强大的功能通常以极高的复杂性为代价(例如CORBA),编写一个新的插件并不总是一件简单的事。

本手册旨在帮助你了解GStreamer的框架0.10.9.1版)以便你能够开发新的插件来扩展当前的功能。本手册通过用C语言开发一个示例插件──一个音频过滤器──来定位大多数问题。然而,接下来的部分会通过编写其它类型的插件引入另一些问题,在本手册的结尾介绍了一些GStreamer的Python绑定。

目录

1. 前言

1.1. GStreamer是什么?

1.2. 谁应该读该指南?

1.3. 预备知识

1.4. 该指南的结构

2. 基本知识

2.1. 元件(Elements)和插件(Plugins)

2.2. 衬垫(Pads)

2.3. 数据(Data),缓冲区(Buffers)和事件(Events)

2.3.1. 缓冲区分配

2.4. MIME类型(Mimetypes)和属性

2.4.1. 基本类型

Chapter 1. 前言

1.1. GStreamer是什么?

GStreamer是一个创建流媒体应用程序的框架。其基本设计思想来自于俄勒冈(Oregon)研究生学院有关视频管道的创意, 同时也借鉴了DirectShow的设计思想。

GStreamer的开发框架使它有可能被用来编写任何类型的流媒体应用程序。基于GStreamer的程序开发框架使得编写任意类型的流媒体应用程序成为了可能。在编写处理音频、视频或者两者皆有的应用程序时, GStreamer可以让你的工作变得简单。GStreamer并不受限于音频和视频处理, 它能够处理任意类型的数据流。管道的设计对于一般应用的滤镜(filter)绰绰有余。这使得GStreamer成为一个优秀的框架,它甚至可以用来设计出对延时有很高要求的高端音频应用程序。

GStreamer最显著的用途是在构建一个播放器上。GStreamer已经支持很多格式的文件了, 包括:MP3, Ogg/Vorbis, MPEG-1/2, AVI, Quicktime, mod等等。从这个角度看,GStreamer更象是一个播放器。但是它主要的优点确是在于: 它的可插入组件能够很方便的接入到任意的管道当中。这个优点使得利用GStreamer编写一个万能的可编辑音视频应用程序成为可能。

GStreamer框架是基于插件的, 有些插件中提供了各种各样的多媒体数字信号编解码器,也有些提供了其他的功能。所有的插件都能够被链接到任意的已经定义了的数据流管道中。GStreamer的管道能够被GUI编辑器编辑, 能够以XML文件来保存。这样的设计使得管道程序库的消耗变得非常少。

GStreamer核心库函数是一个处理插件、数据流和媒体操作的框架。 GStreamer核心库还提供了一个API, 这个API是开放给程序员使用的---当程序员需要使用其他的插件来编写他所需要的应用程序的时候可以使用它。

1.2. 谁应该读该指南?

该指南叙述了如何为GStreamer编写新的模块。本指南针对以下几种人:

?那些想给 GStreamer增加新的数据处理方法的人。例如,可能有人想创建一个新的可见的工具---数据类型转换器,或者新的编码器或者解码器。

?那些想支持新的输入输出设备的人。例如:某人可能会想增加将数据输出到新的视频输出系统或从一个数码相机或耳机中读取数据的功能。

?那些想通过任何方法扩展GStreamer的人。你必须事先了解插件系统是如何工作的,这样你才能知道插件系统对其它代码有什么限制。读完了该手册,你也许会因为插件可以做如此多的事而感到惊讶。

如果你只是想使用GStreamer的已有功能,或者只想使用那些基于GStreamer程序,那么你可以不用再看下去了。如果你只关注与使用现有的插件去便写新的程序──现在有许多这样的插件──你也许想看的是《GStreamer应用程序开发手册》如果你只是想获得那些基于GStreamer的程序的帮助,那么你应该查看那些程序的用户手册。

1.3. 预备知识

该指南假定你已经稍微了解了GStreamer的基本工作原理。你也许希望首先阅读《GStreamer应用程序开发手册》,以便获得对GStreamer编程概念的了解。另外,不要忘了查看GStreamer网站上的已有文档。

为了理解这份手册,你必须对C语言有一个基本的了解。因为GStreamer是基于GObject编程模型,所以本指南假定你也已经对GObject编程有了一个基本的了解。你或许也想看一下Eric Harlow's的《Developing Linux Applications with GTK+ and GDK》一书。

1.4. 该指南的结构

为了帮助你驾驭这份指南,我们将其分为几个大的部分。每一部分致力于一个特定的GStreamer插件开发相关的广泛概念。该指南的所有部分按照以下顺序组织:

?编写一个插件── 介绍插件的结构,并用一个音频滤镜作为演示。

这一部分涵盖了编写一个插件的所有基本步骤,例如将element注册到GStreamer并进行一些初步设置以便能和相邻的element互传数据。讨论以一个示例程序开始,该程序创建一些基本的结构并在构建样板一节中注册一个element。接着,你将在Chapter 4, Chapter 5和Chapter 6中学会怎样通过一段代码得到一个基本的滤镜插件。

随后,在增加参数和Chapter 8中,我们将演示如何使用GObject使element在程序中可配置,以及怎样使你的程序和element交互。下一步,你将学习如何快速的创建一个测试程序来测试你在Chapter 9所学的所有知识。这里只涉及一些应用程序开发的基本知识,要想对此有一个全面的了解,请查看应用程序开发手册。

?高阶滤镜概念── GStreamer插件开发的高级特性信息。

通过对初步知识的学习,你应该能够创建一个有很好的特性的音频或视频过滤器插件了。然而,GStreamer为插件编写者提供了更多的东西。这一部分的章节包含了一些更高级的主题。例如调度,GStreamer的类型定义,时钟,接口和标签。因为这些特性是针对特定应用的

(purpose-specific),你可以按任何顺序阅读它们,它们大多不依赖于其他章节的知识。

在该部分的第一章不同的调度模式我们将解释一些element调度的基本知识。这部分不会很深入,只是一种介绍性的阐述为什么那些东西会那样工作。如果你对GStreamer的内部感兴趣,请阅读这一章。接下来,我们将这一知识运用于另一种类型的数据传输Chapter 5:不同的调度模式基于环路的(Loop-based)元件将让你能对其输入速率有更多的控制。这些在编写muxers或demuxers时是很有用的。

下一步,我们将在Chapter 12中讨论GStreamer媒体标识。你将学到怎样定义新的媒体类型及得到GStreamer内部的标准媒体类型列表。

在下一章,你将学习request-pads和sometimes-pads的概念,这些pad都是动态创建的,或者是因为应用程序的需要(request),或者是因为媒体类型的要求(sometimes),这些都将在Chapter 13中叙述。

接着,在Chapter 14,将解释GStreamer中的时钟概念。如果你的element中需要同步音视频,你必须知道这些信息。

接下来的几章,我们将讨论应用程序和element进行交互的高级方法。之前,我们在添加参数和Chapter 8中学会了如何通过GObject的方法来完成这一功能。我们将在Chapter 15中讨论动态参数,这是一种预先定义element行为的方法。下一步,我们会在Chapter 17中学习到接口的方方面面。接口是个非常特别的东西-应用级元件的特定方式,基于GObject的 GInterface之上。

最后,你将在Chapter 18中学到GStreamer是怎样处理元数据的。

在最后一章,Chapter 19中,将讨论GStreamer的事件机制。一方面,事件也是应用程序和element 间交互的方法,例如定位事件。另一方面,事件也是element间进行交互的一种方法,例如,element 可以通过事件传递媒体流断开的状况,在管道内转发标签等等。

?创建特殊类型的元件──编写其它类型的插件

由于前两部分以一个音频过滤器为例,所介绍的概念可以运用到过滤器插件的开发中。同时许多概念也可以运用到sources,sinks和autopluggers等其它类型的插件中。这一部分讨论编写其他特定类型的插件会碰到的问题。本章开始将焦点集中在可以使用基类(Pre-made base classes)编写的 element上。接下来,在写一个Demuxer或Parser, 写一个N-to-1元件或Muxer和写一个管理器中,讨论编写特殊的元件。

?附录── 关于插件开发的进一步信息

附录中包含一些不适合在手册的其它章节讲述的信息,这些大部分还没有完成。

手册的剩余部分总揽了GStreamer插件开发中的基本概念,涵盖的内容包括元件(Elements)和插件(Plugins), 衬垫, 数据(Data),缓冲区(Buffers)和事件(Events)和类型和属性。如果你已经熟悉了对这一部分,你可以将之当作一次回顾,或者直接跳到编写一个插件。

正如你所见,我们有许多的东西需要学习,让我们就此开始吧!

?通过扩展GstBin创建复杂的element,这样可以创建包含其它插件的插件。

?通过在类型侦测函数(typedetect functions)中加入新的mime类型,可以让你的插件处理全新的媒体类型。

Chapter 2. 基础概念介绍

本章介绍GStreamer的基本概念。掌握了这些基本概念将有助于你解决在扩展GStreamer时遇到的问题。关于这些概念的更详尽的解释请参考GStreamer应用程序开发指南;这些基本概念放在这儿主要是为了帮助你回顾一遍。

2.1. 元件和插件

元件是GStreamer的核心。在插件的开发中,一个元件就是继承于GstElement的一个对象。元件在与其他元件连接时提供了如下一些功能:例如,一个源元件为一个流提供数据,一个滤镜元件对流中的数据进行操作。没有了元件,GStreamer只是一堆概念性的管道,没有任何东西可供连接。GStreamer 已经自带了一大堆元件,但是我们仍然可以编写额外的元件。

然而,仅仅写一个新的元件并不够,为了使GStreamer能够使用它,你必须将元件封装到一个插件中。一个插件是一块可以加载的代码,通常被称为共享对象文件(shared object file)或动态链接库(dynamically linked library)。一个插件中可以包含一个或若干element。为简单起见,本手册主要涉及只包含一个element的插件。

滤镜是一类处理流数据的重要插件。数据的生产者和消费者分别被称为source和sink元件。箱柜(Bin)元件可以包含其它的元件。箱柜的主要职责是调度它包含的元件并使得数据流更平滑。热插拔(autoplugger)元件是另一种箱柜,它可以动态的加载其它元件,并将它们连接起了形成一个可以处理两个任意流的滤镜。

GStreamerr充斥着插件的概念,即使你只使用到一些标准的包。核心库中只有少量基本函数,其它所有的功能都由插件来实现。一个XML文件被用来保存所有注册的插件的详细信息。这样,使用GStreamer 的程序可以只在需要时加载插件,而不必事先全部加载。插件也只在需要它们的元件时才被加载。

查阅GStreamer库索引来获取GstElement和GstPlugin的当前实现细节。

2.2. 衬垫(Pads)

在GStreamer中,衬垫是用来在元件间协商连接和数据流的。衬垫可以看作元件间互相连接的“接口”,数据流通过这些接口流入流出元件。Pad具有特殊的数据处理能力:衬垫可以限制通过它的数据类型。只有当两个衬垫允许通过的数据类型兼容时才可以将它们连接起来。

也许打一个比方可以有助于理解这些概念。衬垫类似于物理设备上的a plug or jack。想象一个包含功放,DVD播放器和一个视频投影仪器的家庭影院系统。将投影仪和DVD播放器相连是允许的,因为这两个设备具有兼容的video jacks。而要将投影仪和功放连起来也许就行不通了,因为它们之间的jack不同。GStreamer中的衬垫具有和家庭影院系统中的jack相同的功能。

大部分情况下,所有在GStreamer中流经的数据都遵循一个原则。数据从element的一个或多个源衬垫流出,从一个或多个sink衬垫流入。源和sink元件分别只有源和sink衬垫。

查阅GStreamer库索引来获取GstPad的当前实现细节。

2.3. 数据,缓冲区和事件

GStreamer中的所有数据流被分割成一块一块的,并从一个元件的源衬垫传到另一个元件的sink衬垫。数据就是用来承载一块一块数据的数据结构。

数据包含以下的重要组成部分:

?一个类型域标识该数据的准确类型(control,content,...)。

?一个指示当前有多少元件引用缓冲区的引用计数器。当计数器的值为0时,缓冲区将被销毁,内存被释放(更详细的细节看下面)。

当前存在两种数据类型:事件(control)和缓冲区(content)。

缓冲区可以包含两个相连接的pad所能处理的任何数据。通常,一个缓冲区包含一块音频或视频数据块,该数据块从一个元件流向另一个元件。

缓冲区同样包含描述缓冲区内容的元数据(metadata)。一些重要的元数据类型有:?一个指向缓冲区数据的指针。

?一个标识缓冲区数据大小的整型变量。

?一个指示缓冲区的最佳显示时间的时间戳。

事件包含两个相连的衬垫间的流的状态的信息。只有事件被元件显式地支持时它们才会被发送,否则核心层将(尝试)自动处理事件。举例来说,事件会被用来表示一个时钟中断,媒体流的结束或高速缓冲区(cache)需要刷新。

事件结构可能会包含如下的成员:

?一个用来标明事件类型的子类型。

?事件类型相关的其他部分。

事件将在Chapter 19一章中广泛讨论。在那之前,只会涉及流结束(EOS)事件,该事件通常在文件结束时发出,标识流的结束。

查阅GStreamer库索引来获取GstMiniObject, GstBuffer和GstEvent的当前实现细节。

2.3.1. 缓冲区的分配

缓冲区是一块可以存放各种数据的内存。缓冲区的内存一般用malloc()函数分配。这样虽然很方便,但不总是最高效,因为数据经常需要被显式的拷入缓冲区。

有些特殊的元件创建指向特殊内存的缓冲区。例如,filesrc 元件通常会(使用 mmap())将一个文件映射到应用程序的地址空间,并创建指向那个地址范围的缓冲区。这些由filesrc创建的缓冲区具有和其它通用的缓冲区一样的行为,唯一的区别是它们是只读的。释放缓冲区的代码将自动检测内存类型并使用正确的方法释放内存。

另一种可能得到特殊缓冲区的途径是向下游同伙(downstream peer)发出请求。这样得到的缓冲区称为downstream-allocated缓冲区。元件可以请求一个连接到源衬垫的同伙创建一个指定大小的空缓冲区。如果下游元件可以创建一个正确大小的特殊缓冲区,它将会这样做。否则,GStreamer将会自动创

建一个通用缓冲区。接着,请求缓冲区的元件就可以将数据拷入缓冲区,并将缓冲区push给创建它的源衬垫。

许多sink元件的将数据拷到硬件的函数都经过了优化,或者可以直接操作硬件。这些元件为它们的上游伙伴创建downstream-allocated缓冲区是很平常的事。其中一例是ximagesink。它创建包含XImage 的缓冲区,因此当一个上游伙伴将数据拷入缓冲区时,数据被直接拷入XImage,这样ximagesink可以直接将图象画到屏幕上而不用先将数据拷到一个 XImage中。

滤镜元件通常有机会可以直接作用于缓冲区,或者在将数据从源缓冲区拷入目标缓冲区时发生作用。最佳方案是两种算法都予以实现,因为GStreamer框架会在可能的时候选择最快的算法。自然地,这只在元件的源和sink衬垫完全一致的情况下才有效果。

2.4. MIME类型(Mimetypes)和属性

GStreamer使用一个类型系统来保障流经元件的数据格式是可识别的。当连接元件中的衬垫时,类型系统对于确保特定的参数有着非常重要的作用,这些参数对正连接的元件间的衬垫的格式匹配有着特定作用。元件间的每一个连接有一个指定的类型和可选的属性集。

2.4.1. 基本类型

GStreamer已经支持许多基本的媒体类型。下表是GStreamer中的缓冲区所使用的一些基本类型。表中包含了类型的名字("mime type")和对类型的描述,类型相关的属性,以及每个属性的意义。已定义类型列表一节中列出了所有支持的类型。

Table 2-1. Table of Example Types

II. 构建插件

现在可以学习如何编写一个插件了。在这一部分,你将学习如何利用GStreamer 的基本编程概念来写一个简单的插件。也许前一部分没有涉及代码,导致事情变的有点抽象和难于理解。相比而言,这一部分将出现程序和代码,我们将开发一个名为"ExampleFilter".

示例过滤器元件的开发将以一个单一的输入衬垫和输出衬垫开始。起初,过滤器只是简单的将媒体和事件数据从它的sink pad传送到它的source pad而不作任何改动。但在这一部分的最后,你将学到如何给它添加一些包括属性和信号处理等有趣的功能。并且,读完下一部分,即Advanced Filter Concepts 后,你将可以给你的插件添加更多的功能。

你可以在GStreamer目录下的 examples/pwg/examplefilter/中找到着一部分所使用的示例代码。

目录

3. 构建样板(Boilerplate)

3.1. 获取GStreamer插件模板

3.2. 使用项目戳(Project Stamp)

3.3. 检查基本代码

3.4. GstElementDetails

3.5. GstStaticPadTemplate

3.6. 构造函数

3.7. Plugin_init函数

4. 指定衬垫(pads)

4.1. Setcaps-函数

5. 链函数(The chain function)

6. 什么是状态?

6.1. 管理滤镜的状态

7. 添加参数

8. 信号

9. 编写测试程序

Chapter 3. 构建样板(Boilerplate)

本章你将学习如何用少量的代码创建一个新的插件。你将看到如何从零开始得到GStreamer的模板代码。随后你将学习怎样通过使用一些基本工具拷贝修改模板插件来生成一个新的插件。如果你照着示例做,到本章结束,你将得到一个可在GStreamer程序中编译使用的音频过滤插件。

3.1. 获取GStreamer插件模板

当前有两种方法可以用来开发一个新的GStreamer插件:你可以手写全部的代码,或者你可以拷贝一份现成的插件模板然后添加你需要的代码。迄今为止,第二种方法是比较简单的,因此,第一种方法将不再提及(这是留给读者的一个作业)。

第一步,从CVS模块中取出 gst-template的一份拷贝,其中包含了一个重要的工具以及GStreamer基

本插件的源代码模板。为了顺利得到 gst-template模块,确保你已经连到网络上,然后在终端中执行如下命令:

shell $ cvs -d:pserver:anoncvs@https://www.360docs.net/doc/7d14067645.html,/cvs/gstreamer login

Logging in to :pserver:anoncvs@https://www.360docs.net/doc/7d14067645.html,:/cvs/gstreamer

CVS password: [ENTER]

shell $ cvs -z3 -d:pserver:anoncvs@https://www.360docs.net/doc/7d14067645.html,:/cvs/gstreamer co gst-template

U gst-template/README

U gst-template/gst-app/AUTHORS

U gst-template/gst-app/ChangeLog

U gst-template/gst-app/Makefile.am

U gst-template/gst-app/NEWS

U gst-template/gst-app/README

U gst-template/gst-app/autogen.sh

U gst-template/gst-app/configure.ac

U gst-template/gst-app/src/Makefile.am

...

敲入第一个命令后,你必须按回车键登陆CVS服务器。(你或许必须登陆两次。)第二个命令将check out 出一系列文件,并放到./gst-template目录下。你要使用的模板将位于./gst-template/gst-plugin/

目录下。你应该先浏览一下该目录中的文件,并对插件的源码树结构有一个总体的了解。

3.2. 使用项目戳(Project Stamp)

编写一个新的元件所要做的第一件事为它指定一些基本信息:它的名字,作者,版本号等等。我们还必须定义一个对象来表示 element,并存放元件需要的数据。所有的这些统称为样板文件(boilerplate).

定义样板文件的标准方法是:写一些简单的代码,并填入一些结构。正如前一部分所说,实现这一目的的最简单方法拷贝一个模板然后根据你的需要增加一些功能。在./gst-plugins/tools/录下有个工具会对你有所帮助。这个名为make_element的程序是一个快速的命令行工具。

要使用make_element,首先开启一个终端窗口,进入gst-template/gst-plugin/src目录,然后运行make_element命令。make_element的参数为:

1.插件的名称。

2.本工具使用的源文件名,缺省使用gstplugin.{c,h}。

注意,插件名称的大小写很重要。在一些操作系统中,路径名的大小写同样很重要。例如:以下的基于插件模板创建一个ExampleFilter插件,并将所有输出文件放入gst-template/gst-plugin/src目录下:

shell $ cd gst-template/gst-plugin/src

shell $ ../tools/make_element ExampleFilter

最后一个命令创建了两个文件: gstexamplefilter.c和 gstexamplefilter.h。

3.3. 检查基本代码

首先我们将检查你要放入头文件中的代码(即使代码的所有接口都在插件系统中定义,不用太关心头文件里的内容,那不是很紧要的。)下面的代码可以在

examples/pwg/examplefilter/boiler/gstexamplefilter.h中找到。

Example 3-1. Example Plugin Header File

#include

/* Definition of structure storing data for this element. */

typedef struct _GstMyFilter {

GstElement element;

GstPad *sinkpad, *srcpad;

gboolean silent;

} GstMyFilter;

/* Standard definition defining a class for this element. */

typedef struct _GstMyFilterClass {

GstElementClass parent_class;

} GstMyFilterClass;

/* Standard macros for defining types for this element. */

#define GST_TYPE_MY_FILTER \

(gst_my_filter_get_type())

#define GST_MY_FILTER(obj) \

(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))

#define GST_MY_FILTER_CLASS(klass) \

(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass))

#define GST_IS_MY_FILTER(obj) \

(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER))

#define GST_IS_MY_FILTER_CLASS(obj) \

(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER))

/* Standard function returning type information. */

GType gst_my_filter_get_type (void);

使用这个头文件,你可以在你的代码中用下面的宏来生成GObject 基本信息,这样所有的函数都可以被恰当的调用:

#include "filter.h"

GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement, GST_TYPE_ELEMENT);

3.4. GstElementDetails

GstElementDetails结构给出了元件的一个层次类型,一个有可读性的描述,以及作者和版本信息。该结构的成员有:

?插件的一个长英文名。

?在一个层次树中的元件的类型。层次树定义为:指定一个顶层类型,后跟一个“/”,再跟下一层的类型,依次进行下去。类型的定义应该根据遍布在该文档中的指导方针进行。(FIXME:写下这些方针,并给出一个好的索引)

?对元件要实现目标的简短描述。

?元件作者的名字,可选的跟一个由尖括号括起来的email地址。

例如:

static GstElementDetails my_filter_details = {

"An example plugin",

"Example/FirstExample",

"Shows the basic structure of a plugin",

"your name "

};

元件细节在_base_init ()函数中被注册到插件中,作为GObject系统的一部分。你应该在用Glib注册类型的函数中来设置该GObject的_base_init ()函数。

static void

gst_my_filter_base_init (gpointer klass)

{

GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

static GstElementDetails my_filter_details = {

[..]

};

[..]

gst_element_class_set_details (element_class, &my_filter_details);

}

3.5. GstStaticPadTemplate

一个GstStaticPadTemplate是一个element将(也许)会创建并使用的pad的描述。它包含:?Pad的一个简短的名字。

?Pad的方向。

?现有属性。这表示pad是否总是存在(一个“always” pad),只在一些情况下存在(一个“sometimes” pad),或只在程序请求时存在(一个“request” pad)。

?该element支持的类型(capabilities)。

例如:

static GstStaticPadTemplate sink_factory =

GST_STATIC_PAD_TEMPLATE (

"sink",

GST_PAD_SINK,

GST_PAD_ALWAYS,

GST_STATIC_CAPS ("ANY")

);

那些pad模板在 _base_init ()函数中被注册。在_init ()函数中用 gst_pad_new_from_template ()根据模板来创建pad。该模板可以使用 gst_element_class_get_pad_template ()函数从element类中得到。更详细的信息见下面。要想用gst_pad_new_from_template (),函数从模板中创建一个新的pad,你必须将模板定义成全局变量。更多详情请参考第四章。

static GstStaticPadTemplate sink_factory = [..],

src_factory = [..];

static void

gst_my_filter_base_init (gpointer klass)

{

GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

[..]

gst_element_class_add_pad_template (element_class,

gst_static_pad_template_get (&src_factory));

gst_element_class_add_pad_template (element_class,

gst_static_pad_template_get (&sink_factory));

}

模板的最后一个参数是它的类型或所支持的类型列表。在这个例子中,我们使用了‘ANY’,意思是这个element接受所有输入格式。在一个实用的插件中,你会设置一个 MIME类型,以及一个可选的属性集合来保证只有支持的输入格式可以通过。参数的格式是一个以MIME类型开头,后跟一个以逗号分隔的所支持的属性集。一个支持16位整型原始音频,环绕或立体声的音频过滤器看起来会是这样:

static GstStaticPadTemplate sink_factory =

GST_STATIC_PAD_TEMPLATE (

"sink",

GST_PAD_SINK,

GST_PAD_ALWAYS,

GST_STATIC_CAPS (

"audio/x-raw-int, "

"width = (int) 16, "

"depth = (int) 16, "

"endianness = (int) BYTE_ORDER, "

"channels = (int) { 1, 2 }, "

"rate = (int) [ 8000, 96000 ]"

)

);

花括号里的值是一个列表,方括号里的值是一个范围。同时支持多个类型集,它们之间应该用分号隔开。以后在讲pad的一章里,我们将看到如何用类型来得到流的准确格式。

3.7. Plugin_init函数

一旦我们写完所有定义插件的代码,接下来就需要完成plugin_init()函数。这是一个特殊的函数,它在插件被加载时就立即被调用,而且它应该根据自己是否被加载并初始化,以及所有的依赖关系是否正确而返回TURE或FALSE。而且在这个函数中必须注册插件支持的所有element类型。

static gboolean

plugin_init (GstPlugin *plugin)

{

return gst_element_register (plugin, "my_filter",

GST_RANK_NONE,

GST_TYPE_MY_FILTER);

}

GST_PLUGIN_DEFINE (

GST_VERSION_MAJOR,

GST_VERSION_MINOR,

"my_filter",

"My filter plugin",

plugin_init,

VERSION,

"LGPL",

"GStreamer",

"https://www.360docs.net/doc/7d14067645.html,/"

)

注意,plugin_init()的返回信息将被缓存在一个中心注册表中。因此,务必保证该函数每次的返回信息是一致的:例如,不要根据运行时条件来决定element的工厂方法是否可用。如果一个element只能在特定条件下工作(例如,如果声卡没有被另一个进程使用),这必须处理为element不能进入READY 状态,而不是试图不让element出现。

Chapter 4. 指定pad

正如前文所说,pad是element间传输数据的通道,因此在创建element时它们显得非常重要。我们在样板文件代码中看到了静态pad模板如何在元件类中注册pad模板。在此,我们将看到怎样创建真实的element,用一个_setcaps ()函数配置一个特殊的类型以及怎样注册函数以便让数据流经element。

你在_base_init ()函数中将pad模板注册到element中,然后在_init ()函数中从pad模板中创建pad。创建完pad后,你必须设置_setcaps ()和 optionally a _getcaps ()函数指针,其中后者是可选的。另外,你还必须设置_chain ()函数指针。或者,pad也可以在一个循环模式中操作,也就是说它们能自己主动拉(pull)数据。这方面的话题以后会讲述的更多。此后,你必须将pad注册进element,就像这样:

static gboolean gst_my_filter_setcaps (GstPad *pad,

GstCaps *caps);

static GstFlowReturn gst_my_filter_chain (GstPad *pad,

GstBuffer *buf);

static void

gst_my_filter_init (GstMyFilter *filter, GstMyFilterClass *filter_klass)

{

GstElementClass *klass = GST_ELEMENT_CLASS (filter_klass);

/* pad through which data comes in to the element */

filter->sinkpad = gst_pad_new_from_template (

gst_element_class_get_pad_template (klass, "sink"), "sink");

gst_pad_set_setcaps_function (filter->sinkpad, gst_my_filter_setcaps);

gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain);

gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);

/* pad through which data goes out of the element */

filter->srcpad = gst_pad_new_from_template (

gst_element_class_get_pad_template (klass, "src"), "src");

gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);

/* properties initial value */

filter->silent = FALSE;

}

4.1. setcaps函数

_setcaps ()函数在cap协商时被调用,cap协商在cap协商中详细讨论。这是相连接的pad决定流经它们之间的流的类型的一个过程。第12章有完整的类型定义列表。一个_link ()函数接受一个指向定义了建议的流媒体类型的GstCaps结构的指针,并且可以返回"yes" (TRUE)或"no" (FALSE)。如果element 给出一个积极的响应,那种流类型将在pad上使用。示例如下:

static gboolean

gst_my_filter_setcaps (GstPad *pad,

GstCaps *caps)

{

GstStructure *structure = gst_caps_get_structure (caps, 0);

GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));

const gchar *mime;

/* Since we're an audio filter, we want to handle raw audio

* and from that audio type, we need to get the samplerate and

* number of channels. */

mime = gst_structure_get_name (structure);

if (strcmp (mime, "audio/x-raw-int") != 0) {

GST_WARNING ("Wrong mimetype %s provided, we only support %s",

mime, "audio/x-raw-int");

return FALSE;

}

/* we're a filter and don't touch the properties of the data.

* That means we can set the given caps unmodified on the next

* element, and use that negotiation return value as ours. */

if (!gst_pad_set_caps (filter->srcpad, caps))

return FALSE;

/* Capsnego succeeded, get the stream properties for internal

* usage and return success. */

gst_structure_get_int (structure, "rate", &filter->samplerate);

gst_structure_get_int (structure, "channels", &filter->channels);

g_print ("Caps negotiation succeeded with %d Hz @ %d channels\n",

filter->samplerate, filter->channels);

return TRUE;

在此,我们检查所给cap的mime类型。通常,你不需要在你自己的插件或element中这样做,因为核心库已经替你做了。我们只是简单的来示范如何得到一堆cap的mime类型。在内部,类型存储在GstStructure 结构中。一个GstCaps 仅仅是0个或多个结构或类型的封装而已。你还可以从这个结构中重新获取流的属性,就像上面代码中gst_structure_get_int ()函数的功能。

如果你的_link ()函数不需要做任何特殊的操作(例如,它只是转发cap),你可以将其设为

gst_pad_proxy_link ()。这是核心库提供的一个连接转发函数。它在诸如identity的element中是很有用的。

Chapter 5. 链函数(The chain function)

所有的数据处理在Chain函数中进行。在简单滤镜中,_chain ()函数多为线性函数── 因此每有一个输入缓冲区,便会有一个输出缓冲区。下面是chain函数的一个非常简单的实现:

static GstFlowReturn

gst_my_filter_chain (GstPad *pad,

GstBuffer *buf)

{

GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));

if (!filter->silent)

g_print ("Have data of size %u bytes!\n", GST_BUFFER_SIZE (buf));

return gst_pad_push (filter->srcpad, buf);

}

显然,上面的函数并没有做任何有用的事。你通常会在这儿处理数据而不是将这些数据打印出来。记住,缓冲区并不总是可写的。在更加高级的element中(那些进行事件处理的),你也许会要指定一个事件处理函数,当流事件发出时(例如流结束,连接中断,tags,等等)该函数会被调用。

static void

gst_my_filter_init (GstMyFilter * filter)

{

[..]

gst_pad_set_event_function (filter->sinkpad,

gst_my_filter_event);

[..]

}

static gboolean

gst_my_filter_event (GstPad *pad,

GstEvent *event)

{

GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));

switch (GST_EVENT_TYPE (event)) {

case GST_EVENT_EOS:

/* end-of-stream, we should close down all stream leftovers here */

gst_my_filter_stop_processing (filter);

break;

default:

break;

}

return gst_pad_event_default (pad, event);

}

static GstFlowReturn

gst_my_filter_chain (GstPad *pad,

GstBuffer *buf)

{

GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));

GstBuffer *outbuf;

outbuf = gst_my_filter_process_data (filter, buf);

gst_buffer_unref (buf);

if (!outbuf) {

/* something went wrong - signal an error */

GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL));

return GST_FLOW_ERROR;

}

return gst_pad_push (filter->srcpad, outbuf);

}

在某些情况下,也许element对数据输入的速率有控制权也是有好处的。在那种情况下,你也许要写一个所谓的基于循环(loop-based)的元件。Source elements(只含有source pads的elements)也可以是get-based elements。这些概念将在本指南的高阶部分以及专门讨论source pad的章节讲述。Chapter 6. 什么是状态(States)?

一个状态用来描述元件实例是否被初始化了,是否已经准备好要传输数据了,以及当前是否在处理数据。GStreamer中一共定义了四个状态:

?GST_STATE_NULL

?GST_STATE_READY

?GST_STATE_PAUSED

?GST_STATE_PLAYING

从现在开始,我们分别简单的用"NULL", "READY", "PAUSED"和"PLAYING"来指代这四个状态。

GST_STATE_NULL是element的缺省状态。这种状态下,没有分配任何运行时资源,也没有加载任何运行时库,显然此时不能处理数据。

GST_STATE_READY是下element的下一个状态。在READY状态下,一个element拥有所有的缺省资源(运行时库,运行时内存)。然而,所有流相关的东西还没有被分配或定义。当从NULL状态过渡到READY

状态时(GST_STATE_CHANGE_NULL_TO_READY),一个element应该分配所有的非流相关的资源以及加载所有运行时库(如果有的话)。反过来,(从READY到NULL状态GST_STATE_CHANGE_READY_TO_NULL),一个element应该卸载这些库并释放所有分配的资源。硬件设备就是这种资源的一个例子。注意,文件通常是流,应当被视为流相关的资源,因此不应该在该状态下分配。

GST_STATE_PAUSED下element已准备好接受并处理数据。对多数element来说,这个状态和PLAYING状态是一样的。唯一的例外是sink elements。sink elements只接受一个buffer然后阻塞。在这种情况下管道处于'prerolled'并且准备好可以立即将数据画出。

GST_STATE_PLAYING是element的最高状态。对多数element来说,该状态和PAUSED状态是完全一样的,它们接受并处理事件和缓冲区数据。只有sink elements需要区分PAUSED和PALAYING状态。在PLAYING 状态下,sink elemnts才真正将到达的数据输出(render),例如,将音频输出到声卡或将视频画面输出到image sink上。

6.1. 管理滤镜状态

如果可能,你的element应该从一个新的基类(Pre-made base classes)中继承。sources,sinks和滤镜/转换element都有已写好的通用基类。除此以外,存在一些音频,视频和其它element的专门的基类。

如果你使用一个基类,你基本不需要自己去处理状态的改变。你所要做的所有工作就是重载基类的

start()和stop()虚函数(也许会根据基类做不同的调用),基类将会为你做好所有的工作。

然而,如果你不继承已有的基类,但是继承GstElement或其它不是基于基类的类,你很可能要自己实现状态变迁函数以便在状态变化时得到通知。如果你的插件是解码器或编码器,这些是无可避免的,因为当前还没有解码器或编码器的基类。

一个element可以通过一个虚函数指针来得到状态变化的通知。在这个函数中,element可以初始化任何element所需的特定的数据,而且在从一个状态到另一个状态时可以出现转换失败。

不要在未处理的状态变化中使用g_assert;这由GstElement基类负责。

static GstStateChangeReturn

gst_my_filter_change_state (GstElement *element, GstStateChange transition);

static void

gst_my_filter_class_init (GstMyFilterClass *klass)

{

GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

element_class->change_state = gst_my_filter_change_state;

}

static GstStateChangeReturn

gst_my_filter_change_state (GstElement *element, GstStateChange transition)

{

GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

GstMyFilter *filter = GST_MY_FILTER (element);

switch (transition) {

case GST_STATE_CHANGE_NULL_TO_READY:

if (!gst_my_filter_allocate_memory (filter))

return GST_STATE_CHANGE_FAILURE;

break;

default:

break;

}

ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

if (ret == GST_STATE_CHANGE_FAILURE)

return ret;

switch (transition) {

case GST_STATE_CHANGE_READY_TO_NULL:

gst_my_filter_free_memory (filter);

break;

default:

break;

}

return ret;

}

注意,正向(NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING) 和反向(PLAYING=>PAUSED,

PAUSED=>READY, READY=>NULL)的状态变迁在两个分开的块中处理,而且反向的状态变化只在我们已经连接到(chained up to)父类的状态变迁函数时才被处理。为了保证多线程同时访问的安全性这样做是必须的。

这样做的原因是,例如反向状态变迁时当你的插件的chain函数仍然在其它线程中访问那些资源时你不必销毁所有已分配的资源。你的chain函数是否要运行取决于你的插件的pad的状态,而那些pad的状态是何element的状态紧密相连的。pad的状态是在GstElement函数的状态变迁函数中处理的,包括恰当的锁操作,这就是为什么在销毁分配的资源之前联锁(chain up)很重要的原因。

Chapter 7. 增加参数

最主要也是最重要的控制element行为的方法是通过设置GObject的属性。GObject的属性在

_class_init ()函数中定义。Element可以实现一个_get_property ()和一个 _set_property ()函数。如果一个应用程序改变或请求一个属性值,这些函数将会被调用,在这些函数中可以改变这些值或根据那些属性的要求在内部改变这些值。

/* properties */

enum {

ARG_0,

ARG_SILENT

/* FILL ME */

};

static void gst_my_filter_set_property (GObject *object,

guint prop_id,

const GValue *value,

GParamSpec *pspec); static void gst_my_filter_get_property (GObject *object,

guint prop_id,

GValue *value,

GParamSpec *pspec);

static void

gst_my_filter_class_init (GstMyFilterClass *klass)

{

GObjectClass *object_class = G_OBJECT_CLASS (klass);

/* define properties */

g_object_class_install_property (object_class, ARG_SILENT,

g_param_spec_boolean ("silent", "Silent",

"Whether to be very verbose or not",

FALSE, G_PARAM_READWRITE));

/* define virtual function pointers */

object_class->set_property = gst_my_filter_set_property;

object_class->get_property = gst_my_filter_get_property;

}

static void

gst_my_filter_set_property (GObject *object,

guint prop_id,

const GValue *value,

GParamSpec *pspec)

{

GstMyFilter *filter = GST_MY_FILTER (object);

switch (prop_id) {

case ARG_SILENT:

filter->silent = g_value_get_boolean (value);

g_print ("Silent argument was changed to %s\n",

filter->silent ? "true" : "false");

break;

default:

G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

break;

}

}

static void

gst_my_filter_get_property (GObject *object,

guint prop_id,

GValue *value,

GParamSpec *pspec)

{

GstMyFilter *filter = GST_MY_FILTER (object);

switch (prop_id) {

case ARG_SILENT:

g_value_set_boolean (value, filter->silent);

break;

default:

G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

break;

}

}

上面是一个演示如何使用参数的简单例子。图形程序,例如GStreamer编辑器,将使用这些属性并显示一个控件,用户可以通过该控件来改变这个属性。因为这些属性足够的用户友好,你应该精确的定义属性。不仅仅在于定义一个属性的有效范围,还在于你要选用具有描述性的字符串来定义这个属性,如果可能,尽量使用枚举或标志来代替整形数。GObject的文档对这些有完整的描述,但是下面我们将给出一个关于这个的简短的例子。注意,在这里使用整形数也许会使用户万全迷惑,因为它们在上下文中没有意义。这个例子是从videotestsrc中截取过来的。

typedef enum {

GST_VIDEOTESTSRC_SMPTE,

GST_VIDEOTESTSRC_SNOW,

GST_VIDEOTESTSRC_BLACK

} GstVideotestsrcPattern;

[..]

#define GST_TYPE_VIDEOTESTSRC_PATTERN (gst_videotestsrc_pattern_get_type ())

static GType

gst_videotestsrc_pattern_get_type (void)

{

static GType videotestsrc_pattern_type = 0;

if (!videotestsrc_pattern_type) {

static GEnumValue pattern_types[] = {

{ GST_VIDEOTESTSRC_SMPTE, "smpte", "SMPTE 100% color bars" },

{ GST_VIDEOTESTSRC_SNOW, "snow", "Random (television snow)" },

{ GST_VIDEOTESTSRC_BLACK, "black", "0% Black" },

{ 0, NULL, NULL },

};

videotestsrc_pattern_type =

Origin 使用问题

Origin 使用问题集锦 1. 请教怎样反读出 origin 曲线上全部数据点? 如,我用 10个数据点画出了一条 origin 曲线,并存为 project的.OPJ 格式。但,现在我想利用 OPJ 文件从这条曲线上均匀的取出 100个数据点的数值,该如何做?注:要一切都使用 origin 软件完成,不用其他曲线识别软件。 Answer: ORIGIN 中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. 如何用origin 做出附件中的图: 其中标注的三角形、方块是怎么整上去的? Answer: 选中左侧竖工具条中的 draw tool(显示是几个点,第七个工具),移动到你要标注的位置双击,就产生了一个点,依次标注完方块。再标注三角的第一个点,标注完后改成三角,以后标注的就都是三角了。改动点的类型的方法和正常画曲线方式一样。 3. 如何用origin 做出附件图中的坐标轴(带刻度)?

Answer: 你把刻度改成那样不就行了。 8.0 的具体方法是双击坐标轴,title & format --> 选左边那个 bottom,然后在右边把 axis 改为 at position=。同理,然后选左边的 left,把axis也改为 at position=。 4. origin能否读取导入曲线的坐标? 一张 bmp 格式的图片,图片内容是坐标系和拟合曲线,但是不知道用什么软件绘制的。请问能否将该图片导入 origin,读出曲线上任意一点的数据? Answer: (1). 1.ORIGIN 有一个图形数字化插件可完成该任务。 2.有许多专门的图形数字化软件也可完成此任务。个人感觉专门的比插件也用、便捷。推荐 WINDIG25 (2). origin下的数字化插件是digitizer,下载地 址:https://www.360docs.net/doc/7d14067645.html,/fileexchange/details.aspx?fid=8拖入origin即可,但使用不是很方便。比较方便的是un-scan-it。 5. 如何在origin7.5 中标峰值? 用origin7.5 作的XRD图,怎样直接在峰上标数据? Answer: Tools/Pick peaks 设置一下点击 Find Peaks 就 OK了。Positive和Negative 是标正负峰值的意思,其他数值改变一下就知道干吗用的了。 6. 关于origin 拟合曲线延长的问题? 我想把拟合之后的直线向前或向后延长一段距离与坐标轴相交。但是不知道该怎么弄。是不是要改那个范围的最大值和最小值啊?可是怎么改?

origin8使用小技巧

人人网- 日志分享 1. 请教怎样反读出origin曲线上全部数据点? 如,我用10个数据点画出了一条origin曲线,并存为project的.OPJ格式。 但,现在我想利用OPJ文件从这条曲线上均匀的取出100个数据点的数值,该如何做? 注:要一切都使用origin软件完成,不用其他曲线识别软件。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1390313 [1] Answer: ORIGIN中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. origin中非线性拟合中logistic模型的疑问? origin 中非线性拟合中的logistic模型为 y = A2 + (A1-A2)/(1 + (x/x0)^p) 其初始参数设置为 sort(x_y_curve); //smooth(x_y_curve, 2); x0 = xaty50( x_y_curve ); p = 3.0;

A1 = max( y_data ); A2 = min( y_data ); A1 = min( y_data ); A2 = max( y_data ); 而据我看到的logistic的模型都是(自己origin中自定义的) y =A1/(1+(A1/A2-1)*exp(-k*x)) 也就是说 origin 中的logistic有4个数值需要确定,而自定义的有3个数值 从结果来看,没有太大区别,但为什么函数不一样呢? 不是学数学,高人能否详细说明下。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1391522 [2] Answer: 你可以看一下这个文档,里面有数种不同形式的 logistic 模型: https://www.360docs.net/doc/7d14067645.html,/web/packages/drc/drc.pdf [3] 当然,这是一个 R (https://www.360docs.net/doc/7d14067645.html,) 包的文档,但不妨碍你看其中的公式。 R 是开源的啊,以 GPL 发布,可以从 https://www.360docs.net/doc/7d14067645.html, [4]上了解更多。I 3. 如何用origin做出附件中的图:其中标注的三角形、方块是怎么整上去的?https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1393739 [5] Answer:

Origin 使用问题集锦

1. 请教怎样反读出origin曲线上全部数据点? 如,我用10个数据点画出了一条origin曲线,并存为project的.OPJ格式。 但,现在我想利用OPJ文件从这条曲线上均匀的取出100个数据点的数值,该如何做?注:要一切都使用origin软件完成,不用其他曲线识别软件。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1390313 Answer: ORIGIN中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. origin中非线性拟合中logistic模型的疑问? origin 中非线性拟合中的logistic模型为 y = A2 + (A1-A2)/(1 + (x/x0)^p) 其初始参数设置为 sort(x_y_curve); //smooth(x_y_curve, 2); x0 = xaty50( x_y_curve ); p = 3.0; if( yatxmin( x_y_curve ) > yatxmax( x_y_curve ) ) { A1 = max( y_data ); A2 = min( y_data ); } else { A1 = min( y_data ); A2 = max( y_data ); } 而据我看到的logistic的模型都是(自己origin中自定义的) y =A1/(1+(A1/A2-1)*exp(-k*x)) 也就是说origin 中的logistic有4个数值需要确定,而自定义的有3个数值 从结果来看,没有太大区别,但为什么函数不一样呢? 不是学数学,高人能否详细说明下。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1391522 Answer: 你可以看一下这个文档,里面有数种不同形式的logistic 模型: https://www.360docs.net/doc/7d14067645.html,/web/packages/drc/drc.pdf 当然,这是一个R (https://www.360docs.net/doc/7d14067645.html,) 包的文档,但不妨碍你看其中的公式。 R 是开源的啊,以GPL 发布,可以从https://www.360docs.net/doc/7d14067645.html,上了解更多。

origin使用常见问题

1. 请教怎样反读出origin 曲线上全部数据点? 如,我用10个数据点画出了一条origin 曲线,并存为project的.OPJ 格式。但,现在我想利用OPJ 文件从这条曲线上均匀的取出100个数据点的数值,该如何做?注:要一切都使用origin 软件完成,不用其他曲线识别软件。 Answer: ORIGIN 中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. 如何用origin 做出附件中的图: 其中标注的三角形、方块是怎么整上去的? Answer: 选中左侧竖工具条中的draw tool(显示是几个点,第七个工具),移动到你要标注的位置双击,就产生了一个点,依次标注完方块。再标注三角的第一个点,标注完后改成三角,以后标注的就都是三角了。改动点的类型的方法和正常画曲线方式一样。 3. 如何用origin 做出附件图中的坐标轴(带刻度)?

Answer: 你把刻度改成那样不就行了。 8.0 的具体方法是双击坐标轴,title & format --> 选左边那个bottom,然后在右边把axis 改为at position=。同理,然后选左边的left,把axis也改为at position=。 4. origin能否读取导入曲线的坐标? 一张bmp 格式的图片,图片内容是坐标系和拟合曲线,但是不知道用什么软件绘制的。请问能否将该图片导入origin,读出曲线上任意一点的数据? Answer: (1). 1.ORIGIN 有一个图形数字化插件可完成该任务。2.有许多专门的图形数字化软件也可完成此任务。个人感觉专门的比插件也用、便捷。推荐WINDIG25 (2). origin下的数字化插件是digitizer,下载地址:https://www.360docs.net/doc/7d14067645.html,/fileexchange/details.aspx?fid=8拖入origin即可,但使用不是很方便。比较方便的是un-scan-it。 5. 如何在origin7.5 中标峰值? 用origin7.5 作的XRD图,怎样直接在峰上标数据? Answer: Tools/Pick peaks 设置一下点击Find Peaks 就OK了。Positive和Negative 是标正负峰值的意思,其他数值改变一下就知道干吗用的了。 6. 关于origin 拟合曲线延长的问题? 我想把拟合之后的直线向前或向后延长一段距离与坐标轴相交。但是不知道该怎么弄。是不是要改那个范围的最大值和最小值啊?可是怎么改? Answer: (1). 有那个选项,你可以选择延长布满坐标轴,大概这么翻译吧,我也翻译不好。在analysis里呢,找找,我的卸载了。。。。 (2). 自己按照方程作图,就是先在一定范围内选一系列点`,然后求出对应的y,然后做曲线图把点连起来。 (3). 拟合之前在设定参数的时候就把坐标范围设定好,拟合出来的曲线就是你要的范围的。拟合好以后的曲线好像是不能修改参数的,只有重新拟合才行。 7. 我用origin 画的图,过了一段时间,不知道怎么的,就只有图,看不到数据窗口了,怎么能把数据窗口调出来呢? Answer: Veiw---project explorer;或者Alt+1。如果你是从拷贝的图进去,是看不到数据框的啊!所以建议要保存原始的图谱啊!

origin画切线教程

郑重声明:本人水平有限,不足之处望大家海涵,本教程 非专业人士编写,倘若用于商业用途出现任何损失后果自 负! 一.到origin官网上下载一个切线插件(该插件适用于很多版本7.5和8.0亲测) https://www.360docs.net/doc/7d14067645.html,/fileexchange/details.aspx?fid=106 二.打开origin8.0(7.5也可)双击该插件,自动安装。三.安装完后有提示 四.输入数据,这里我为了示范就随便输入几个

五.画线(不要告诉我你不会。。。。。。) 六.点击插件,在图上找到一个点,双击---奇迹就出现了

看,有切线了,图的上方还有斜率slope=210 有些同学可能觉得实验采集的点太少,很多地方画不了切线,而且切线的斜率不太可靠,不要紧,下面我就教你画曲线上任一点的切线 一.输入数据(我还用刚才的数据) 二.多项式拟合(你如果要拟合直线那肯定不存在画切线问题,废话了:) Analysis / Fitting / Fit Polynomial / Open Dialogue

我选择二项式拟合所以 要根据你具体的试验的数据,有的是指数拟合,有的是反 比例拟合,选择正确的你和方式最重要了

拟合完后在原图上出现了一条新的曲线,这时你再用切线工具发现做不了切线了,很多人在这里就放弃了,千万不要气馁,经过多次尝试我终于发现了问题所在,这条拟合的新曲线不是真正的曲线,他有很多不连续的点(具体有多少个点可以设置,这里不再熬述)组成,所以不能画出切线,那总得想个办法吧- _ - 其实很简单,只要把刚才拟合所生成的点再当做实验数据输入一遍就行了,哈哈,我真是太聪明了(不要喷,是真的^o^) 三.在book1里找到这些点的数据

ORIGIN使用中常见的问题

附录:有关ORIGIN使用中常见的问题 一、数据的输入 1、直接输入 打开ORIGIN默认的是出现一个包含2个数据列的名为DATA1的WORKSHEET表格,第一列为X,第二列为Y。可输入一组X、Y实验数据。 如果是同一X值下有多个对应的Y值,可按工具栏上的添加列按钮,根据需要添加相应的数据列; 如果是想把不同的数据画在同一个坐标系中,如将X、Y;X1、Y1;X2、Y2;X3、Y3对应的数据都画到同一个坐标系中,可以在现有的两列数据列后再添加6个数据列,分别将第三列、第五列第七列设为X列,然后将数据列全部选中,点击相应的曲线类型产生相应的曲线。 2、输入有规律的数据 曲线生成后,双击曲线,可打开对话框,从中修改曲线相应的属性,如曲线的颜色、线型、连接方式、数据点符号形状、大小、颜色等。 双击坐标轴,可在打开的对话框中设置坐标轴的属性,如坐标轴的起点与终点值,标记条间隔、样式,是否显示坐标轴等。 双击坐标轴标签,可以编辑坐标轴标题,其中有上下标、希腊字符等。 双击图例标签,可以编辑对应的曲线标记。 双击左上角的坐标系按钮(或叫层按钮,ORIGIN中,把一个坐标系称为一个层LAYER),可打开坐标系属性按钮。对坐标系中的数据曲线进行添加、去除等操作。 双击图形窗口中的空白处,可打开页面属性设置对话框,对页面的大小、颜色等进行设置。 2、从文件输入数据 ORIGIN7.0可输入各种格式的数据,在输入之前,必须有一个空的数据表格,即WORKSHEET,从文件菜单中选择输入(IMPORT),然后在出现的子菜单中选择相应的数据文件格式。7.0支持红外SPC格式文件,可以直接输入并作图; 1

Origin软件使用指导

科学绘图和数据处理软件Origin 高端图表和数据分析软件是科学家和工程师们必备的工具。Origin软件集绘制图表和数据分析为一体,是绘制图表和数据分析的理想工具,在科技领域享受很高的声誉。 Origin是美国Microcal公司推出的数据分析和绘图软件,自1991年问世以来,版本从4.0、5.0、6.0、7.0、7.5到2007年推出的最新版本8.0,软件不断推陈出新,逐步完善。在这十多年里,Origin为世界上数以万计需要科技绘图、数据分析和图表展示软件的科技工作者提供了一个全面解决方案。与Origin 7.5相比,Origin 8.0在菜单设计、具体操作等很多方面都有显著改进,特别是采用了新的X-Functions技术,可直接使用指令行模式,把“模块化”和“对象化”发挥到了淋漓尽致的程度,方便了其他软件的调用和协同处理,可以认为Origin 8.0从各方面来说都是一个很现代化、很完善的软件。 OriginPro是Origin专业版,它除具有Origin所有功能外,还提供了更强、更专业的3D拟合、图形处理、统计分析和信号处理分析及开发工具。OriginPro 8.0将以前版本中的峰拟合工具进一步完善,将其整合到“Peak and Baseline”菜单中。在异常复杂的峰值分析方面,Origin 8.0将以前版本中峰拟合模块插件也整合在“Peak and Baseline”菜单里的峰拟合向导(“Peak Analyzer)中。峰拟合向导功能强大,通过峰拟合向导界面,可以一步步完成如拉曼(Raman)光谱、红外光谱、X衍射谱线等多峰谱线高级分析,自动完成基线检测、多峰定位和多于100个峰的拟合,这对各种谱线的分析提供了便捷的工具,在材料学、工程学、光谱学、药理学及其他学科领域有着广泛的应用。 一.Origin 8专业版的安装破解激活方法及流程: 1、下载后直接解压缩至指定文件夹,在目录下点击Origin 8.exe;

origin 技巧

每年到修改论文的时候,发现很多同学不懂图形和数据处理,出来的图形惨不忍睹。有的人想学没处学,有的根本不想学,最后的结果是研究生给本科生干活,老师给学生干活。所以有空的时候,想以这种方式写一点数据处理技术,给自己的未来减负。 1 先从最简单的单X多Y图说起。 实验过程中经常遇到系列样品的表征数据,比如红外光谱、X-射线衍射等等,通常这些仪器测定的步长一致,也即X轴完全相同,这时候可以把系列数据绘制在一个图形中,图形的信息量丰富,也方便数据比较。例如这次本科论文中有一位同学的一组红外数据: 先从测试仪器上导出数据,一般都是txt文件,将txt文件直接或经过excel导入到Oringin 软件中,可以通过column/add new column或点击快捷工具来添加多栏数据。

点击作图工具(左下角红色圆圈标示的工具用于线状图),分别设置每一条曲线的X和Y数据,点击add添加数据。

得到以下的图形:

一般红外光谱图测试范围从4000~400cm-1,为了图形清晰美观,要处理以下几个问题:1)双击X轴数据,出现坐标轴编辑栏,在scale栏下分别编辑X和Y轴的范围和increment(间隔)。 2)点击edit/new layer/top X and right Y,增加一层图形,也就是着增加上X和右Y,这样图形比较方正,这时候还必须在坐标轴编辑栏里将上X和右Y的标尺和数据去掉。在Title&Format里去掉标尺,在Tick Lables里去掉数据。 得到以下的图形:

接下来,要把粘在一起的数据分开,第一步将要移动的数据线激活,对着数据线,点击右键,set as active即可,然后可以采用两种方式移动数据: 1)Anlysis/Subtract/Reference data(减去某个估计的数值) 2)Anlysis/Translate/Vertical(垂直移动一个线段),Oringin自动启动“Screen Reader”

数字化(Digitize)插件介绍

数字化(Digitize)插件介绍 数宇化插件为origin网站提供的极为有用的免费插件之一,该插件可将普通曲线图直接在origin中数字化.例如,以通过扫描仪将曲线图扫入计算机, 或在网上获取的电子资料曲线图等。这些以图形格式保存的曲线线,能方便地通过数字化插件在origin软件中数字化。Digitize自带了帮助,以下简要介绍该插件的安装和使用。 1.下载数字化插件 在origin网页的文件交换目录中下载Digitize.opk 2.安装数字化插件 运行origin7.0,把Digitize.opk从所在文件夹拖到已打开的origin7.0工作界面中,此时完成安装,在origin7.0工作界面可以看到一个Digitize按钮。如图: 3.使用数字化插件 (1)点击Digitize按钮,打开数字化图形模版, (2)将要进行数字化的图形文件通过剪贴板粘贴到模版中, (3)在模版窗口中调整图形尺寸。 (4)右键单击模版中的图片,在弹出的快捷菜单中选择“Label Control” (5)在“Object Name”文本框中输入“image1”

(6)在“Attach to”栏选择“Page”单选按钮, (7)单击“OK”。 (8)为X、Y轴选择正确的坐标类型,Linear—线性坐标,Log 10—对数坐标, (9)单击模板中的Digitize按钮,注意不是origin7.0工作界面的那个。(10)要求你输入图上的两个x值做为x轴的参照,(最好取整数点) (11)在图上双击选取两个点对应你上面给出的两个x值(这是不需要理会Y值,注意图中画红圈的地方,是我选取的x轴的参照点。) (12)对Y坐标重复以上两步(10)、(11)。 (13)下面可以通过鼠标双击在图上读取数据点。比如我想要最上面一条曲线的数据点,大致我会选取紫色圆圈所标的那些数据点。

利用Origin程序及Digitizer插件从图形中读取数据

利用 Origin 程序及 Digitizer 插件从图中读取数据
制作:Dfggc (C)2006,小木虫版权所有,转载请注明 2006 年 5 月 18 日
利用 Origin 程序及 Digitizer 插件从图中读取数据
By Dfggc, (C)2006,https://www.360docs.net/doc/7d14067645.html,

一、背景 当你想把自己的数据和文献中的数据对比时, 文献上只有图形而 没有原始数据,怎么办?在论坛上有 steincat 等老牛提出一些解决方 法, 在这里讲述一下我利用 origin 实现图形数字化的过程, 多谢指正。
二、你所需要的东西 电脑、windows 操作系统(不用说了) ,origin 6.0(网上搂一下, 到处都是,注意是 6.0,新版本没有试过,不能保证成功) ,Digitizer 插件(已上传) 。
三、Origin 6.0 主程序和 Digitizer 插件的安装 1、安装 Origin6.0 很简单,不用细说了吧。如图。
利用 Origin 程序及 Digitizer 插件从图中读取数据
By Dfggc, (C)2006,https://www.360docs.net/doc/7d14067645.html,

2、安装插件 如图:选择从开始菜单中选择 origin 程序组下的 addon setup。
利用 Origin 程序及 Digitizer 插件从图中读取数据
By Dfggc, (C)2006,https://www.360docs.net/doc/7d14067645.html,

选择安装插件所在的文件夹的位置:你电脑里存放 Digitizer6 的 路径:如\\C:\Documents and Settings\new\桌面\Digitizer6,点击 ok,安 装,finish ok
安装完成后,打开 Origin,会出现小窗口 addon,如图。
利用 Origin 程序及 Digitizer 插件从图中读取数据
By Dfggc, (C)2006,https://www.360docs.net/doc/7d14067645.html,

origin小技巧

1. 请教怎样反读出 origin 曲线上全部数据点? 如,我用 10个数据点画出了一条 origin 曲线,并存为 project的.OPJ 格式。但,现在我想利用 OPJ 文件从这条曲线上均匀的取出 100个数据点的数值,该如何做?注:要一切都使用 origin 软件完成,不用其他曲线识别软件。 Answer: ORIGIN 中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. 如何用origin 做出附件中的图: 其中标注的三角形、方块是怎么整上去的? Answer: 选中左侧竖工具条中的 draw tool(显示是几个点,第七个工具),移动到你要标注的位置双击,就产生了一个点,依次标注完方块。再标注三角的第一个点,标注完后改成三角,以后标注的就都是三角了。改动点的类型的方法和正常画曲线方式一样。 3. 如何用origin 做出附件图中的坐标轴(带刻度)?

Answer: 你把刻度改成那样不就行了。 8.0 的具体方法是双击坐标轴,title & format --> 选左边那个 bottom,然后在右边把 axis 改为 at position=。同理,然后选左边的 left,把 axis也改为 at position=。 4. origin能否读取导入曲线的坐标? 一张 bmp 格式的图片,图片内容是坐标系和拟合曲线,但是不知道用什么软件绘制的。请问能否将该图片导入 origin,读出曲线上任意一点的数据? Answer: (1). 1.ORIGIN 有一个图形数字化插件可完成该任务。 2.有许多专门的图形数字化软件也可完成此任务。个人感觉专门的比插件也用、便捷。推荐 WINDIG25 (2). origin下的数字化插件是digitizer,下载地 址:https://www.360docs.net/doc/7d14067645.html,/fileexchange/details.aspx?fid=8拖入origin即可,但使用不是很方便。比较方便的是un-scan-it。 5. 如何在origin7.5 中标峰值? 用origin7.5 作的XRD图,怎样直接在峰上标数据? Answer: Tools/Pick peaks 设置一下点击 Find Peaks 就 OK了。Positive和Negative 是标正负峰值的意思,其他数值改变一下就知道干吗用的了。 6. 关于origin 拟合曲线延长的问题? 我想把拟合之后的直线向前或向后延长一段距离与坐标轴相交。但是不知道该怎么弄。是不是要改那个范围的最大值和最小值啊?可是怎么改?

origin 使用技巧

1.请教怎样反读出origin曲线上全部数据点? 如,我用10个数据点画出了一条origin曲线,并存为project的.OPJ格式。但,现在我想利用OPJ文件从这条曲线上均匀的取出100个数据点的数值,该如何做? 注:要一切都使用origin软件完成,不用其他曲线识别软件。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1390313 Answer: ORIGIN中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. origin中非线性拟合中logistic模型的疑问? origin 中非线性拟合中的logistic模型为 y = A2 + (A1-A2)/(1 + (x/x0)^p) 其初始参数设置为 sort(x_y_curve); //smooth(x_y_curve, 2); x0 = xaty50( x_y_curve ); p = 3.0; if( yatxmin( x_y_curve ) > yatxmax( x_y_curve ) ) { A1 = max( y_data ); A2 = min( y_data ); } else { A1 = min( y_data ); A2 = max( y_data ); } 而据我看到的logistic的模型都是(自己origin中自定义的) y =A1/(1+(A1/A2-1)*exp(-k*x))

也就是说origin 中的logistic有4个数值需要确定,而自定义的有3个数值 从结果来看,没有太大区别,但为什么函数不一样呢? 不是学数学,高人能否详细说明下。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1391522 Answer: 你可以看一下这个文档,里面有数种不同形式的logistic 模型: https://www.360docs.net/doc/7d14067645.html,/web/packages/drc/drc.pdf 当然,这是一个R (https://www.360docs.net/doc/7d14067645.html,) 包的文档,但不妨碍你看其中的公式。 R 是开源的啊,以GPL 发布,可以从https://www.360docs.net/doc/7d14067645.html,上了解更多。3.如何用origin做出附件中的图:其中标注的三角形、方块是怎么整上去的?https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1393739 Answer: 选中左侧竖工具条中的 draw tool(显示是几个点,第七个工具),移动到你要标注的位置双击,就产生了一个点,依次标注完方块。再标注三角的第一个点,标注完后改成三角,以后标注的就都是三角了。改动点的类型的方法和正常画曲线方式一样。 4.如何用origin做出附件图中的坐标轴(带刻度)? https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1397419 Answer: 你把刻度改成那样不就行了。8.0的具体方法是双击坐标轴,title & format --> 选左边那个bottom,然后在右边把axis改为at position=。同理,然后选左边的left,把axis也改为at position=。 5. origin能否读取导入曲线的坐标? 一张bmp格式的图片,图片内容是坐标系和拟合曲线,但是不知道用什么软件绘制的。请问能否将该图片导入origin,读出曲线上任意一点的数据? https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1398227 Answer: (1). 1.ORIGIN有一个图形数字化插件可完成该任务。2.有许多专门的图形数字化软件也可完成此任务。个人感觉专门的比插件也用、便捷。推荐WINDIG25

origin知识

在origin中,先在菜单栏中选择绘图菜单,单击里面的散点图的绘制,之后在菜单栏中选择分析菜单,里面有线性拟合和多项式拟合等,单击你要的拟合方式,在弹出的子窗口中将“show formula on graph”勾选一下,就可以显示公式了。 以下为本人自己使用Origin的一些经验,有一些虽然都是小问题,但书上没有。现拿出来给大家参考,欢迎批评指正。 1.怎么求非自然数为底的幂函数 Origin中的自然数的幂函数很容易,用EXP函数就可以了,但是其它幂函数没有,例如:将一列数据转变为以10为底,数列为幂指数,用10^col(A)就可以了。 2.如何输入σ,±这样的符号 添加文本,然后点击Ctrl+M,选择你所需的字符,插入就行了。 3.自定义公式拟和技巧 origin7.0中虽然提供了强大的拟合曲线库外,但在实际使用中,你可能会发觉在所提供的曲线库中没有你想要拟合的公式。这时你就可以使用用户自定义公式进行拟合。过程如下: (1)打开主工具栏中analysis的non-linear curve fit....,这时会出来一个选择公式界面。 (2)选择编辑公式,需要你提供公式名称以供系统保存;还要提供参数的个数及主变量及因变量符号。 (3)按你需要的公式写在编辑框内,注意千万别写错了。写完后按save进行保存。 (4)现在开始拟合:在action中选dataset,提供主变量和因变量的一些相关参数。 (5)在action中选simulate,在参数中填上你根据数据及其它一些条件确定的粗略的初始参数以及拟合起始点的位置及拟合点数,然后按下create curve就会在图上出现一条拟合曲线,但这往往与期望值差距较大,因此接下来需要进行参数优化。 (6)参数优化采用试错法,根据曲线形状逐渐改变参数,注意,多参数时改变任何一个参数都会改变曲线形状,因此可以一次变一个参数,直到达到满意的形状。 (7)在action中选fit,按下Chi-sqr和10-lit。 (8)在action中选results,按下param worksheet生成拟合曲线及数据。此时可以关闭拟合界面。 (9)在图左上角右键点1,选add/remove plot,将多余的曲线删除,将nlsf系列曲线留下。拟合数据可在param worksheet中看到。 这样就完成了一次自定义曲线拟合。

origin使用方法

转:小木虫Origin 使用问题集锦,和大家分享了来源:孙明道的日志 1. 请教怎样反读出origin曲线上全部数据点? 如,我用10个数据点画出了一条origin曲线,并存为project的.OPJ格式。 但,现在我想利用OPJ文件从这条曲线上均匀的取出100个数据点的数值,该如何做?注:要一切都使用origin软件完成,不用其他曲线识别软件。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1390313 Answer: ORIGIN中,在分析菜单(或统计菜单)中有插值命令,打开设置对话框,输入数据的起点和终点以及插值点的个数,OK!生成新的插值曲线和对应的数据表格。 2. origin中非线性拟合中logistic模型的疑问? origin 中非线性拟合中的logistic模型为 y = A2 + (A1-A2)/(1 + (x/x0)^p) 其初始参数设置为 sort(x_y_curve); //smooth(x_y_curve, 2); x0 = xaty50( x_y_curve ); p = 3.0; if( yatxmin( x_y_curve ) > yatxmax( x_y_curve ) ) { A1 = max( y_data ); A2 = min( y_data ); } else { A1 = min( y_data ); A2 = max( y_data ); } 而据我看到的logistic的模型都是(自己origin中自定义的) y =A1/(1+(A1/A2-1)*exp(-k*x)) 也就是说origin 中的logistic有4个数值需要确定,而自定义的有3个数值 从结果来看,没有太大区别,但为什么函数不一样呢? 不是学数学,高人能否详细说明下。 https://www.360docs.net/doc/7d14067645.html,/bbs/viewthread.php?tid=1391522 Answer: 你可以看一下这个文档,里面有数种不同形式的logistic 模型: https://www.360docs.net/doc/7d14067645.html,/web/packages/drc/drc.pdf

相关主题
相关文档
最新文档