Audiosink的设计,需要满足下列一些需求:

  • 良好的chain_based 支持。绝大多数简单playback pipelines都是将音频数据从decoder直接push给audiosink;

  • 良好 getrange_based支持。大部分专业的应用都是audio sink从pipeline拉取数据。典型的作法是在一个回调函数中pull N Samples,回调函数一般在一个单独的线程或者是硬件设备来调度。

  • 提供准确的时钟。必须能够提供即使samples被丢弃或在流中发现不连续时也能提供采样准确的时钟。

  • 可能的话,提供DMA支持

Design

The design is based on a set of base classes and the concept of a ringbuffer of samples.

+-----------+   - provide preroll, rendering, timing
+ basesink + - caps nego
+-----+-----+
|
+-----V----------+    - manages ringbuffer
+ audiobasesink + - manages scheduling (push/pull)
+-----+----------+   - manages clock/query/seek
|      - manages scheduling of samples in the ringbuffer
|     - manages caps parsing
|
+-----V------+ - default ringbuffer implementation with a GThread
+ audiosink + - subclasses provide open/read/close methods
+------------+

The ringbuffer is a contiguous piece of memory divided into segtotal pieces of segments. Each segment has segsize bytes.

      play position
v
+---+---+---+-------------------------------------+----------+
+ 0 | 1 | 2 | .... | segtotal |
+---+---+---+-------------------------------------+----------+
<--->
segsize bytes = N samples * bytes_per_sample.

如上,环形缓冲器有一个play position,以segment表示。play position是设备正在从ringbuffer读取samples的位置。
ringbuffer可以进入PLAYING或STOPPED状态:
在STOPPED状态下,没有samples被put到设备,play pointer不前进。
在PLAYING状态下,samples被写入设备,并且在每个seg被写入设备之后,ringbuffer应该调用可配置的回调,
play pointer在每个段被写入之后前进。 对ringbuffer的写入操作将会把新的samples放入ringbuffer中。如果ringbuffer中没有足够的空间,
写操作将被阻塞。即使buffer为空,ringbuffer的播放也不会停止。当buffer为空时,设备会播放静音。
ringbuffer通过无锁原子操作实现,特别是在读取端,以便尽可能地降低低延迟。
每当一个new samples要put进ringbuffer,先获取read pointer,请求的write position和actural position作差值,
      /* get the currently processed segment */
segdone = g_atomic_int_get (&buf->segdone) - buf->segbase; /* see how far away it is from the write segment */
diff = writeseg - segdone;
   
.....       /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
      if (G_UNLIKELY (diff < 0)) {
        /* we need to drop one segment at a time, pretend we wrote a segment. */
        skip = TRUE;
        break;
      }       /* write segment is within writable range, we can break the loop and
       * start writing the data. */
      if (diff <= segtotal) {
        skip = FALSE;
        break;
      }       /* else we need to wait for the segment to become writable. */
      if (!wait_segment (buf))
        goto not_started;
    }

如果差值diff<0,则samples来太慢了,丢掉来太慢的数据。如果diff > segtotal,写入部分必须等待播放指针前进。

也就是需要设备先消耗掉ringbuffer中的数据,才能继续往ringbuffer中写入新的数据。

Audiosink design的更多相关文章

  1. 带你实现开发者头条APP(四)---首页优化(加入design包)

    title: 带你实现开发者头条APP(四)---首页优化(加入design包) tags: design,Toolbar,TabLayout,RecyclerView grammar_cjkRuby ...

  2. 【知识必备】一文让你搞懂design设计的CoordinatorLayout和AppbarLayout联动,让Design设计更简单~

    一.写在前面 其实博主在之前已经对design包的各个控件都做了博文说明,无奈个人觉得理解不够深入,所以有了这篇更加深入的介绍,希望各位看官拍砖~ 二.从是什么开始 1.首先我们得知道Coordina ...

  3. Android Material Design之 NavigationView侧滑界面自定义 随笔

    一.侧滑界面Menu自定义: 在menu文件夹下新建activity_main_drawer.xml文件,自定义标题和icon: <?xml version="1.0" en ...

  4. Material Design Reveal effect(揭示效果) 你可能见过但是叫不出名字的小效果

    Material Design Reveal effect(揭示效果) 你可能见过但是叫不出名字的小效果 前言: 每次写之前都会来一段(废)话.{心塞...} Google Play首页两个tab背景 ...

  5. 使用Design包实现QQ动画侧滑效果和滑动菜单导航

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个supp ...

  6. 安卓Design包下的TextInputLayout和FloatingActionButton的简单使用

    终于介绍到Design包的最后的东西了. 也很简单,一个是TextInputLayout. TextInputLayout作为一个父容器,包含一个新的EditText,可以给EditText添加意想不 ...

  7. 安卓Design包之AppBar和Toolbar的联用

    前面讲了Design包的的CoordinatorLayout和SnackBar的混用,现在继续理解Design包的AppBar; AppBarLayout跟它的名字一样,把容器类的组件全部作为AppB ...

  8. 安卓Design包之超强控件CoordinatorLayout与SnackBar的简单使用

    在前面的Design中,学习使用了TabLayout,NavigationView与DrawerLayout实现的神奇效果,今天就带来本次Design包中我认为最有意义的控件CoordinatorLa ...

  9. 安卓Design之NavigationView的使用

    前面讲解了Design包下的TabLayout的使用,下面将带来NavagationView和DrawLayout以及toolbar的联动. 项目已经同步至:https://github.com/na ...

随机推荐

  1. C#之Raw Socket网络封包监视源码

    大家可以建立一个Windows Form应用程序,在下面的各个文件中添加对应的源码: //RawSocket.csnamespace ReceiveAll{ using System; using S ...

  2. javascript快速入门26--XPath

    XPath 简介 XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML 文档中对元素和属性进行遍历.XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 ...

  3. requireJS简介和一个完整实例

    什么是 requireJS ? requireJS 是用JavaScript编写的JS框架,主要功能是可以按不同的先后依赖关系对 JavaScript 等文件的进行加载工作,可简单理解为JS文件的加载 ...

  4. [Android]Volley源代码分析(二)Cache

    Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源代码思路往下,来看下Volley对Cache的处理逻辑. 我们回忆一下昨天的简单代码,我们的入口是 ...

  5. Storm如何保证消息不丢失

    storm保证从spout发出的每个tuple都会被完全处理.这篇文章介绍storm是怎么做到这个保证的,以及我们使用者怎么做才能充分利用storm的可靠性特点. 一个tuple被"完全处理 ...

  6. 爪哇国新游记之二十九----访问URL获取输入流

    代码: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import ...

  7. web.xml文件中配置mime下载文件类型(转)

    转自:http://5aijava.iteye.com/blog/166600 TOMCAT在默认情况下下载.rar的文件是把文件当作text打开,以至于IE打开RAR文件为乱码,如果遇到这种情况时不 ...

  8. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-PLC支持哪些PLC语言类型

    PLC的标准化语言,统称为IEC 61131-3,该规范下有五种不同的语言可以创建PLC程序,TwinCAT都支持. IL(指令列表): 每条指令都从一个新行开始并包含一个操作和一个或多个操作数,一条 ...

  9. try....exception....finally

    class MyException(Exception): def __init__(self,msg): self.msg=msg def __str__(self): return self.ms ...

  10. HDU 4632 Palindrome subsequence(区间dp)

    Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/ ...