当前位置: 首页 > article >正文

linux alsa-lib snd_pcm_open函数源码分析(一)

访问原版内容,可直接到博客linux alsa-lib snd_pcm_open函数源码分析(一)

系列文章其他部分:

 linux alsa-lib snd_pcm_open函数源码分析(二)

linux alsa-lib snd_pcm_open函数源码分析(三)

linux alsa-lib snd_pcm_open函数源码分析(四)

linux alsa-lib snd_pcm_open函数源码分析(五)

linux alsa-lib snd_pcm_open函数源码分析(六)

snd_pcm_open通常是接触alsa-lib的第一个api,也通常是使用alsa进行录音或播放的第一步。 正如名字中表示的一样,snd_pcm_open用来打开一个pcm音频设备,并得到这个音频设备的句柄, 即便用户使用了alsa的插件,使用时也同样是使用此接口,非常方便。但是这种使用上的方便是以snd_pcm_open及其复杂的实现为代价的。 这篇笔记的目的就是尽可能详细的分析这个函数到底做了什么工作,以及这些工作到底是怎么实现的。

1.版本信息

  • alsa-lib-1.1.5
  • alsa-plugins-1.1.5
  • linux-kernel-4.4.167

2.函数原型

snd_pcm_open实现位于alsa-lib/src/pcm/pcm.c中。 从函数实现上主要有两个功能,第一个是更新配置文件,第二个是打开设备。 这两个函数过程都很复杂,后面我们会继续详细解释。

/*
 * \brief Opens a PCM
 * \param pcmp 返回pcm句柄
 * \param name 要打开的pcm设备的名字
 * \param stream 想要的stream类型
 * \param mode 打开模式 (see #SND_PCM_NONBLOCK, #SND_PCM_ASYNC)
 * \return 0 表示成功,否则返回一个负的错误码
 */
int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
         snd_pcm_stream_t stream, int mode)
{
    snd_config_t *top;
    int err;

    assert(pcmp && name);
    err = snd_config_update_ref(&top);
    if (err < 0)
        return err;
    err = snd_pcm_open_noupdate(pcmp, top, name, stream, mode, 0);
    snd_config_unref(top);
    return err;
}

3.使用示例

下面是一段播放音频的代码,大部分来自于alsa-utils中的aplay.c文件,为了方便了解使用流程对其做了精简, 此示例仅仅为了说明snd_pcm_open的位置,无法直接编译运行。

4.代码分析

下面是对snd_pcm_open函数的分析过程,函数主要实现了两个工作:更新配置文件及打开pcm设备。 我们按照这两部分分别进行分析。

4.1 snd_config_update_ref

函数的目的是更新snd_config配置,与snd_config_update_r功能类似,主要区别是此函数会增加引用计数, 所以在引用计数为0前获取到配置树将永远不会被删除。同时由于函数使用了锁,所以函数是线程安全的。

注意这里的参数top,是个二级指针。在snd_pcm_open中传下来的是snd_config_t *top;中top的地址。

关键函数snd_config_update_r的详细分析参考inux alsa-lib snd_pcm_open函数详细分析(二)

/* top为出参 */
int snd_config_update_ref(snd_config_t **top)
{
    int err;

    if (top)
        *top = NULL;
    snd_config_lock();  /*加锁保证线程安全*/
    /* 主要功能实现在此,后续文章会继续分析 */
    err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
    if (err >= 0) {
        if (snd_config) {
            if (top) {
                snd_config->refcount++; /*增加引用计数*/
                *top = snd_config;      /*最终返回结果*/
            }
        } else {
            err = -ENODEV;
        }
    }
    snd_config_unlock();
    return err;
}
4.2 snd_pcm_open_noupdate

函数的目的是打开pcm设备,所要打开的具体设备需要依赖上面打开的设备树, 函数接受传入的设备名称,解析名称并在设备树中查找需要打开的设备, 如果配置中有使用插件,函数还需要解析插件,最终打开硬件设备。 注意snd_pcm_open函数最终返回的句柄pcmp其实就是此函数的返回的。

此函数会在后面文章继续分析。

static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
                 const char *name, snd_pcm_stream_t stream,
                 int mode, int hop)
{
    int err;
    snd_config_t *pcm_conf;
    const char *str;

    err = snd_config_search_definition(root, "pcm", name, &pcm_conf);
    if (err < 0) {
        SNDERR("Unknown PCM %s", name);
        return err;
    }
    if (snd_config_get_string(pcm_conf, &str) >= 0)
        err = snd_pcm_open_noupdate(pcmp, root, str, stream, mode,
                        hop + 1);
    else {
        snd_config_set_hop(pcm_conf, hop);
        err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);
    }
    snd_config_delete(pcm_conf);
    return err;
}

各子函数的详细介绍参考本系列其他文章


http://www.kler.cn/a/375582.html

相关文章:

  • 网络安全战略论文学习笔记day1
  • Java项目实战II基于Java+Spring Boot+MySQL的植物健康系统(开发文档+数据库+源码)
  • 系统安全架构的深度解析与实践:Java代码实现
  • Qt指定程序编译生成文件的位置
  • 安装fpm,解决*.deb=> *.rpm
  • uni-app实现app展示进度条在线更新以及定时更新提醒
  • 腾讯云数据库TDSQL:数据库界的“高架桥”
  • 【论文阅读】Associative Alignment for Few-shot Image Classification
  • ESP-IDF HTTP POST请求发送音频-启明云端乐鑫代理商
  • 【机器学习】21. Transformer: 最通俗易懂讲解
  • 优化低代码开发平台用户体验:功能树导航设计探讨
  • 穷举vs暴搜vs深搜vs回溯vs剪枝 算法专题
  • #渗透测试#SRC漏洞挖掘# 操作系统-windows系统
  • C++设计模式结构型模式———桥接模式
  • watch 和 computed 的区别 - 2024最新版前端秋招面试短期突击面试题【100道】
  • MySQL锁——针对实习面试
  • 【华为HCIP实战课程二十九】中间到中间系统协议IS-IS邻居关系建立和LSP详解,网络工程师
  • 关于武汉芯景科技有限公司的马达驱动芯片AT6237开发指南(兼容DRV8837)
  • BO-Transformer-LSTM多特征分类预测/故障诊断(Matlab实现)
  • Spring Boot 跨域解决方案
  • 星光校园之恋
  • leetcode day8 动态规划篇 3259+746+198
  • 高级java每日一道面试题-2024年10月25日-JVM篇-你是如何排查线上OOM问题的?
  • (python)如何进行加密
  • 输出特殊图案,请在c环境中运行
  • wpf设置全局字体大小,可以配置