云计算百科
云计算领域专业知识百科平台

06-Pipeline生命周期状态机与引用所有权

Pipeline 生命周期、状态机与 GStreamer 引用所有权

专栏:GStreamer C++ 从零到工程实战 · 第 7 篇 / 共 17 篇

系统掌握 Pipeline、Bin、NULL/READY/PAUSED/PLAYING、Preroll、Live Source,并用 RAII 理清 GstObject 与 GstMiniObject 的引用所有权。

第 6 课:Pipeline / Bin / State / Preroll

这一课非常重要,因为到现在为止,我们只是认识了“零件”:

Plugin

Factory

Element

Pad / Property

但真正运行起来时,还需要回答三个问题:

这些 Element 放在哪里?
谁统一管理它们?
整个媒体系统怎么启动、暂停、停止?

答案就是:

Bin
Pipeline
State


一、为什么不能只创建 Element?

假设你创建了三个 Element:

videotestsrc
videoconvert
autovideosink

它们现在只是三个独立对象:

Element A

Element B

Element C

即使你把 Pad 连起来:

A → B → C

还缺一个东西:

谁来统一管理这组 Element?

比如:

全部启动
全部暂停
全部停止
统一处理时钟
统一接收消息
统一管理生命周期

如果 Application 自己一个个管:

start(A);
start(B);
start(C);

pause(A);
pause(B);
pause(C);

stop(A);
stop(B);
stop(C);

很快就会乱。

所以 GStreamer 引入:

Bin


二、什么是 Bin?

可以把 Bin 理解为:

Element 的容器。

比如:

GstBin
┌──────────────────────────┐
│ │
│ Source → Convert → Sink │
│ │
└──────────────────────────┘

它里面可以装:

Element
Element
Element

可以类比普通对象树:

QObject
└── child QObject

或者 UI:

QWidget
├── QPushButton
├── QLabel
└── QLineEdit

但是不要完全等同。

这里最关键的是:

Bin 可以把一组 Element 当成一个整体管理。

比如:

VideoBin
┌──────────────────────────┐
│ Decoder → Convert → Scale│
└──────────────────────────┘

Application 不一定需要关心内部三个 Element。

对外可以把:

VideoBin

看成一个整体。


三、一个很漂亮的设计:Bin 本身也是 Element

这点特别重要。

GStreamer 的层次大致是:

在这里插入图片描述

图:GstObject、GstElement、GstBin 与 GstPipeline 的继承关系

也就是说:

GstBin IS-A GstElement

所以:

一个 Bin 里面可以装 Element,而 Bin 本身又可以作为更大 Bin 的一个 Element。

这样就可以无限组合。

比如:

Pipeline

├── Source

├── VideoBin
│ ├── Decoder
│ ├── Convert
│ └── Scale

└── Sink

甚至:

Pipeline

├── InputBin
├── DecodeBin
├── ProcessingBin
└── OutputBin

这是一种非常典型的层次化组合设计。


四、那 Pipeline 又是什么?

你可以先记一句:

Pipeline 是最顶层的 Bin。

也就是:

GstPipeline

GstBin

GstElement

普通 Bin:

一组 Element 的容器

Pipeline:

整个媒体处理系统的顶层容器

例如:

Pipeline
┌────────────────────────────────────────┐
│ │
│ videotestsrc → convert → videosink │
│ │
└────────────────────────────────────────┘

所以以后我们写:

GstElement *pipeline =
gst_pipeline_new(\”pipeline\”);

虽然变量类型经常写成:

GstElement*

但真实对象类型是:

GstPipeline

因为它也是 Element。


五、Pipeline 比普通 Bin 多做了什么?

Pipeline 不只是“最大的盒子”。

它还承担一些顶层职责,比如:

Clock
Bus
State synchronization
整体运行管理

所以可以粗略理解:

GstPipeline
┌───────────────────────────────────┐
│ │
│ Element → Element → Element │
│ │
│ 统一 State │
│ 统一 Clock │
│ 提供 Bus │
│ │
└───────────────────────────────────┘

你以后 Application 通常不会分别操作每个 Element。

而是主要操作:

Pipeline

例如:

gst_element_set_state(
pipeline,
GST_STATE_PLAYING
);

意思不是:

“只让 Pipeline 这个对象 PLAYING。”

而是:

让整个 Pipeline 及其内部 Element 进入对应运行状态。


六、为什么 Element 必须 add 到 Pipeline?

这是个非常重要的问题。

假设:

GstElement *source =
gst_element_factory_make(\”videotestsrc\”, \”source\”);

GstElement *sink =
gst_element_factory_make(\”autovideosink\”, \”sink\”);

此时:

source

sink

只是两个独立对象。

如果创建:

pipeline

但不 add:

pipeline

source

sink

三者依旧互不属于。

所以要:

gst_bin_add_many(
GST_BIN(pipeline),
source,
sink,
nullptr
);

变成:

Pipeline
┌──────────────────────────┐
│ │
│ source sink │
│ │
└──────────────────────────┘

这一步叫:

把 Element 加入 Bin

然后才去:

gst_element_link(source, sink);

形成:

Pipeline
┌──────────────────────────┐
│ │
│ source ───────

赞(0)
未经允许不得转载:网硕互联帮助中心 » 06-Pipeline生命周期状态机与引用所有权
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!