简介: CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉
🌻1.前言
本篇目的:理解
gst_audio_sink_get_type()如何注册并返回GstAudioSink的运行时类型,以及它与音频Sink实例、插件工厂之间的关系。
GStreamer使用GObject类型系统描述对象的继承关系。应用或子类代码遇到GstAudioSink时,通常先要取得它对应的GType,用于类型检查、继承判断和类信息查询。
gst_audio_sink_get_type()的职责是取得GstAudioSink的运行时类型标识。它不创建音频Sink实例,不打开音频设备,也不负责把某个具体Sink插件注册到元素工厂。
#mermaid-svg-AFfZIMpzkfHL5cuA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AFfZIMpzkfHL5cuA .error-icon{fill:#552222;}#mermaid-svg-AFfZIMpzkfHL5cuA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AFfZIMpzkfHL5cuA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AFfZIMpzkfHL5cuA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AFfZIMpzkfHL5cuA .marker.cross{stroke:#333333;}#mermaid-svg-AFfZIMpzkfHL5cuA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AFfZIMpzkfHL5cuA p{margin:0;}#mermaid-svg-AFfZIMpzkfHL5cuA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster-label text{fill:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster-label span{color:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster-label span p{background-color:transparent;}#mermaid-svg-AFfZIMpzkfHL5cuA .label text,#mermaid-svg-AFfZIMpzkfHL5cuA span{fill:#333;color:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA .node rect,#mermaid-svg-AFfZIMpzkfHL5cuA .node circle,#mermaid-svg-AFfZIMpzkfHL5cuA .node ellipse,#mermaid-svg-AFfZIMpzkfHL5cuA .node polygon,#mermaid-svg-AFfZIMpzkfHL5cuA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AFfZIMpzkfHL5cuA .rough-node .label text,#mermaid-svg-AFfZIMpzkfHL5cuA .node .label text,#mermaid-svg-AFfZIMpzkfHL5cuA .image-shape .label,#mermaid-svg-AFfZIMpzkfHL5cuA .icon-shape .label{text-anchor:middle;}#mermaid-svg-AFfZIMpzkfHL5cuA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AFfZIMpzkfHL5cuA .rough-node .label,#mermaid-svg-AFfZIMpzkfHL5cuA .node .label,#mermaid-svg-AFfZIMpzkfHL5cuA .image-shape .label,#mermaid-svg-AFfZIMpzkfHL5cuA .icon-shape .label{text-align:center;}#mermaid-svg-AFfZIMpzkfHL5cuA .node.clickable{cursor:pointer;}#mermaid-svg-AFfZIMpzkfHL5cuA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AFfZIMpzkfHL5cuA .arrowheadPath{fill:#333333;}#mermaid-svg-AFfZIMpzkfHL5cuA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AFfZIMpzkfHL5cuA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AFfZIMpzkfHL5cuA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AFfZIMpzkfHL5cuA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AFfZIMpzkfHL5cuA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AFfZIMpzkfHL5cuA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster text{fill:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA .cluster span{color:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AFfZIMpzkfHL5cuA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AFfZIMpzkfHL5cuA rect.text{fill:none;stroke-width:0;}#mermaid-svg-AFfZIMpzkfHL5cuA .icon-shape,#mermaid-svg-AFfZIMpzkfHL5cuA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AFfZIMpzkfHL5cuA .icon-shape p,#mermaid-svg-AFfZIMpzkfHL5cuA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AFfZIMpzkfHL5cuA .icon-shape .label rect,#mermaid-svg-AFfZIMpzkfHL5cuA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AFfZIMpzkfHL5cuA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AFfZIMpzkfHL5cuA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AFfZIMpzkfHL5cuA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 需要识别GstAudioSink类型
gst_audio_sink_get_type
取得GType类型标识
执行类型判断或查询
确认类型关系
🌻2.应用场景和用法
2.1查询类型和判断继承关系
gst_audio_sink_get_type()常用于以下场景:
| 场景 | 使用方式 | 得到的结果 |
|---|---|---|
| 类型检查 | 将返回值传给g_type_is_a() |
判断GstAudioSink是否属于某个父类型 |
| 注册子类 | 在G_DEFINE_TYPE()等宏中指定父类型 |
建立子类和GstAudioSink之间的继承关系 |
| 查询类型名称 | 将返回值传给g_type_name() |
得到运行时类型名称 |
| 配合类型宏 | 使用GST_TYPE_AUDIO_SINK |
取得相同的GType标识 |
函数返回的GType是类型系统中的标识,不是GstAudioSink*实例指针。拿到类型标识后,代码可以判断类型关系或取得类信息,但不能据此认为音频设备已经打开。
2.2函数原型与返回语义
函数原型如下:
c
GType
gst_audio_sink_get_type (void);
函数没有参数,返回GstAudioSink对应的GType。头文件中的类型宏:
c
#define GST_TYPE_AUDIO_SINK (gst_audio_sink_get_type ())
调用GST_TYPE_AUDIO_SINK与直接调用gst_audio_sink_get_type()作用相同。两者都用于取得类型标识。
最小调用方式如下:
c
GType type;
type = gst_audio_sink_get_type ();
if (!g_type_is_a (type, GST_TYPE_AUDIO_BASE_SINK)) {
g_printerr ("GstAudioSink parent type check failed\n");
return 1;
}
调用前只需要包含GStreamer音频头文件并初始化GStreamer。调用后得到类型标识,可将它用于运行时类型判断。
相邻接口的职责不同:
| 接口 | 主要职责 |
|---|---|
gst_audio_sink_get_type() |
取得GstAudioSink的运行时类型 |
g_type_is_a() |
判断一个GType是否属于另一个类型 |
g_type_name() |
查询GType对应的名称 |
g_object_new() |
根据类型创建GObject实例 |
gst_element_factory_make() |
根据元素工厂名称创建具体GStreamer元素 |
🌻3.调用流程剖析
3.1从类型宏进入GType注册
GstAudioSink的类型定义使用G_DEFINE_TYPE_WITH_CODE()。该宏生成gst_audio_sink_get_type()实现,并把GstAudioBaseSink指定为父类型。
首次取得该类型时,GType系统登记GstAudioSink类型信息。类型定义中的附加初始化代码还会初始化音频Sink调试类别,并为类扩展结构分配私有空间。函数最终返回注册后的类型标识。GstAudioSink实现
#mermaid-svg-MnTsWaQRRx8PJAnf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MnTsWaQRRx8PJAnf .error-icon{fill:#552222;}#mermaid-svg-MnTsWaQRRx8PJAnf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MnTsWaQRRx8PJAnf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MnTsWaQRRx8PJAnf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MnTsWaQRRx8PJAnf .marker.cross{stroke:#333333;}#mermaid-svg-MnTsWaQRRx8PJAnf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MnTsWaQRRx8PJAnf p{margin:0;}#mermaid-svg-MnTsWaQRRx8PJAnf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster-label text{fill:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster-label span{color:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster-label span p{background-color:transparent;}#mermaid-svg-MnTsWaQRRx8PJAnf .label text,#mermaid-svg-MnTsWaQRRx8PJAnf span{fill:#333;color:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf .node rect,#mermaid-svg-MnTsWaQRRx8PJAnf .node circle,#mermaid-svg-MnTsWaQRRx8PJAnf .node ellipse,#mermaid-svg-MnTsWaQRRx8PJAnf .node polygon,#mermaid-svg-MnTsWaQRRx8PJAnf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MnTsWaQRRx8PJAnf .rough-node .label text,#mermaid-svg-MnTsWaQRRx8PJAnf .node .label text,#mermaid-svg-MnTsWaQRRx8PJAnf .image-shape .label,#mermaid-svg-MnTsWaQRRx8PJAnf .icon-shape .label{text-anchor:middle;}#mermaid-svg-MnTsWaQRRx8PJAnf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MnTsWaQRRx8PJAnf .rough-node .label,#mermaid-svg-MnTsWaQRRx8PJAnf .node .label,#mermaid-svg-MnTsWaQRRx8PJAnf .image-shape .label,#mermaid-svg-MnTsWaQRRx8PJAnf .icon-shape .label{text-align:center;}#mermaid-svg-MnTsWaQRRx8PJAnf .node.clickable{cursor:pointer;}#mermaid-svg-MnTsWaQRRx8PJAnf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MnTsWaQRRx8PJAnf .arrowheadPath{fill:#333333;}#mermaid-svg-MnTsWaQRRx8PJAnf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MnTsWaQRRx8PJAnf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MnTsWaQRRx8PJAnf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MnTsWaQRRx8PJAnf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MnTsWaQRRx8PJAnf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MnTsWaQRRx8PJAnf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster text{fill:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf .cluster span{color:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MnTsWaQRRx8PJAnf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MnTsWaQRRx8PJAnf rect.text{fill:none;stroke-width:0;}#mermaid-svg-MnTsWaQRRx8PJAnf .icon-shape,#mermaid-svg-MnTsWaQRRx8PJAnf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MnTsWaQRRx8PJAnf .icon-shape p,#mermaid-svg-MnTsWaQRRx8PJAnf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MnTsWaQRRx8PJAnf .icon-shape .label rect,#mermaid-svg-MnTsWaQRRx8PJAnf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MnTsWaQRRx8PJAnf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MnTsWaQRRx8PJAnf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MnTsWaQRRx8PJAnf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调用类型宏或get_type
登记GstAudioSink类型
关联GstAudioBaseSink父类型
返回GType标识
GType登记的是类型信息。真正创建实例需要另外调用对象创建接口;取得类型标识不会触发音频设备的打开或配置。
3.2区分类型注册与音频设备操作
GstAudioSink继承自GstAudioBaseSink。它提供通用音频输出基类能力,并通过类虚函数连接设备操作,例如open、prepare、write、delay和close。GstAudioSink API说明
类型类初始化时,GstAudioSink会设置创建音频环形缓冲区的虚函数。后续实际运行时,基类再通过对应类方法处理环形缓冲区和设备操作。类型查询函数本身不执行这条播放流程。
还要区分GType和元素工厂。GType回答"对象属于什么类型",元素工厂回答"如何按名称创建一个具体元素"。例如alsasink等具体元素由插件注册到元素工厂;仅调用gst_audio_sink_get_type()不会让alsasink变得可用。
🌻4.实战案例
4.1初始化GStreamer并取得类型
程序调用gst_init()初始化GStreamer,再调用gst_audio_sink_get_type()取得类型标识。
4.2检查类型名称和父类型
使用g_type_name()读取类型名称,并使用g_type_is_a()确认该类型继承自GstAudioBaseSink。这两个检查可以验证返回值是类型系统中的GstAudioSink,而不是对象实例。
4.3完整代码
c
#include <gst/gst.h>
#include <gst/audio/audio.h>
int
main (int argc, char *argv[])
{
GType audio_sink_type;
const gchar *type_name;
gst_init (&argc, &argv);
/* 取得GstAudioSink在GType系统中的类型标识 */
audio_sink_type = gst_audio_sink_get_type ();
if (audio_sink_type == G_TYPE_INVALID) {
g_printerr ("Failed to get GstAudioSink type\n");
return 1;
}
/* 查询运行时类型名称 */
type_name = g_type_name (audio_sink_type);
if (type_name == NULL) {
g_printerr ("Failed to get type name\n");
return 1;
}
/* 验证GstAudioSink继承自GstAudioBaseSink */
if (!g_type_is_a (
audio_sink_type,
GST_TYPE_AUDIO_BASE_SINK)) {
g_printerr ("Unexpected GstAudioSink parent type\n");
return 1;
}
g_print ("type: %s\n", type_name);
g_print ("parent-check: TRUE\n");
return 0;
}
🌻5.总结
gst_audio_sink_get_type()负责取得GstAudioSink的GType标识,供GObject类型系统进行类型识别和继承关系查询。