Linux Gstreamer深度解析之gst_audio_sink_get_type调用流程与实战(六十五)

简介: 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类型系统进行类型识别和继承关系查询。

相关推荐
xiaoqiMikko1 小时前
Linux 实战(一):CentOS 7、Rocky 9、Ubuntu 24.04 三台真机实测 —— 认清系统、换源、装包的版本坑
linux·centos
迷途之人不知返2 小时前
【基础IO】-1-预备知识与准备工作
linux
xiaoqiMikko2 小时前
Linux 实战(二):端口不通 —— CentOS 7、Rocky 9、Ubuntu 24.04 上防火墙和 SELinux 的实测差异
linux·centos
大鹏的NLP博客2 小时前
WSL Ubuntu 26.04 升级与环境整理记录
linux·ubuntu·wsl
程序猿追2 小时前
HarmonyOS 6 音视频实战:用 AVPlayer 做一个本地音乐播放器
华为·音视频·harmonyos
GeW3 小时前
如何打造真正的数字化工厂?需从Red Hat到数据库底层打捞基石
linux
沫璃染墨3 小时前
从零入门计算机网络系列(一):计算机网络初识——从网络发展史到TCP/IP协议》
linux·网络·网络协议·tcp/ip·计算机网络
云贝贝贝3 小时前
PostgreSQL 分区表:从设计到运维,大表不再卡
运维·数据库·postgresql
zyseo83 小时前
谷歌SEO 站内搜索优化实战:把站内搜索词变成关键词金矿
java·服务器·数据库