ALSA Compress-Offload API

概述

從 ALSA API 的早期開始,它就被定義為支持 PCM,或考慮到了 IEC61937 等固定比特率的載荷。參數和返回值以幀計算是常態,這使得擴展已有的 API 以支持壓縮數據流充滿挑戰。

最近這些年,音頻數字信號處理器 (DSP) 常常被集成進片上系統 (SoC) 設計中,且 DSPs 也常被集成進音頻編解碼器 (這里的音頻編解碼器與 AAC 之類的音頻數據壓縮方案不同,它是指主要用于完成模擬信號和數字信號轉換的器件) 中。與基于主機的處理相比,在 DSP 這樣的處理器上處理壓縮數據可以顯著降低功耗。Linux 對這類硬件的支持不是很好,主要是因為主線內核中缺乏可用的通用 API。

不是要求更改 ALSA PCM 接口的 API 而破壞兼容性,而是引入了一個新的 “壓縮數據” API,為音頻 DSP 提供控制和數據流接口。

這個 API 的設計靈感來自于 Intel Moorestown SOC 的 2 年經驗,通過許多必須的更正把 API 上傳到主線內核而不是 staging 樹中,使其可供其他人使用。

需求

主要的需求包括如下這些:

  • 字節計數和時間之間的分離。壓縮的格式可能每個文件都有一個文件頭,或者完全沒有文件頭。幀和幀之間的載荷大小可能會變化。因此,當處理壓縮數據時,可靠地估計音頻緩沖區的時長是不可能的。需要專門的機制來實現可靠的音頻-視頻同步,這需要精確地報告給定時間點,已經渲染的采樣數。

  • 處理多種格式。PCM 數據只需要采樣率、通道數和位寬的規范。相反地,壓縮數據可能是各種各樣的格式。音頻 DSP 也可以在固件中嵌入對有限數量的音頻編碼器和解碼器的支持,或者可以通過庫的動態下載支持更多選擇。

  • 聚焦于主要的格式。這個 API 可以為用于音頻和視頻采集和播放的最流行的格式提供支持。它可能隨著音頻壓縮技術的進步,而添加新的格式。

  • 處理多種配置。即使對于像 AAC 這樣給定的格式,一些實現可能支持 AAC 多通道而不是 HE-AAC 立體聲。同樣,WMA10 M3 級別可能需要許多內存和 CPU 周期。新的 API 需要提供一個通用的方式來列出這些格式。

  • 僅渲染/獲取。這個 API 不提供任何硬件加速方法,其中 PCM 采樣被返回給用戶空間,以做更多處理。這個 API 聚焦于給 DSP 提供壓縮數據流,并假設解碼之后的數據被路由給一個物理輸出或邏輯后端。

  • 復雜性隱藏。對于每個壓縮格式,現有的用戶空間多媒體框架都具有現成的枚舉/結構體。這個新 API 假設有一個平臺特有的兼容性層,轉換并利用音頻 DSP 的能力,如 Android HAL 或 PulseAudio sinks。根據構造,常規的應用程序不應該使用此 API。

設計

新 API 在流控制方面與 PCM API 有許多相同的概念。無論內容是什么,啟動 (start),暫停 (pause),恢復 (resume),排空 (drain),和停止 (stop) 命令具有相同的語義。

內存環形緩沖區被分割為一系列片段的概念借鑒自 ALSA PCM API。然而,只能指定字節大小。

拖動/trick 模式假定由主機處理。

不支持快退/快進的概念。提交到環形緩沖區的數據不能失效,除非刪除所有緩沖區。

壓縮數據 API 對于數據如何被提交給音頻 DSP 不做任何假設。從主存儲器傳輸到嵌入式音頻集群或外部 DSP 的 SPI 接口的 DMA 傳輸都是可能的。與在 ALSA PCM 的情況中一樣,暴露了一組核心例程;每個驅動程序實現者都必須編寫對一組強制例程的支持,并可能使用可選例程。

主要補充內容是

get_caps

這個例程返回支持的音頻格式列表。在采集流上查詢 codecs 將返回編碼器,對播放流則將列出解碼器。

get_codec_caps

對于每個 codec,這個例程返回能力 (capabilities) 的列表。這個例程的意圖是確保所有的能力都對應于有效的設置,并最小化配置失敗的風險。例如,對于諸如 AAC 之類的復雜編解碼器,支持的通道數可能取決于特定的配置 (profile)。如果通過單個描述符來暴露能力 (capabilities),可能發生配置 (profile)/通道數/格式的特定結合無法支持的情況。同樣,嵌入式 DSP 的內存和 CPU 周期有限,某些實現可能會使能力 (capabilities) 列表變得動態并依賴于現有工作負載。除了編解碼器設置之外,此例程還返回實現處理的最小緩沖區大小。該信息可以是 DMA 緩沖區大小、同步所需的字節數等的函數,并且可以由用戶空間使用來定義在開始播放之前需要在環形緩沖區中寫入多少內容。

set_params

這個例程設置為特定編解碼器選擇的配置。參數中最重要的字段是編解碼器類型;在大多數情況下解碼器將忽略其它參數,而編碼器將與設置保持嚴格一致。

get_params

這個例程返回 DSP 使用的實際設置。對設置的更改應該仍然是例外。

get_timestamp

時間戳變成多字段結構。它列出了傳輸的字節數、處理的采樣數以及渲染/采集的采樣數。所有這些值均可用于確定平均比特率、確定環形緩沖區是否需要重新填充或由于 DSP 上的解碼/編碼/IO 導致的延遲。

請注意,編解碼器/配置 (profile)/模式列表源自 OpenMAX AL 規范,而不是重新發明輪子。修改包括:

  • 添加 FLAC 和 IEC 格式
  • 編碼器/解碼器能力 (capabilities) 的合并
  • 配置 (profile)/模式列表為位掩碼,使描述符更加緊湊
  • 為解碼器添加 set_params (在 OpenMAX AL 中缺失)
  • 添加 AMR/AMR-WB 編碼模式 (在 OpenMAX AL 中缺失)
  • 為 WMA 添加格式信息
  • 需要時添加編碼選項 (源自 OpenMAX AL)
  • 添加 rateControlSupported (在 OpenMAX AL 中缺失)

狀態機

壓縮音頻流狀態機描述如下

                                      +----------+|          ||   OPEN   ||          |+----------+||| compr_set_params()|vcompr_free()                  +----------+
+------------------------------------|          |
|                                    |   SETUP  |
|          +-------------------------|          |<-------------------------+
|          |       compr_write()     +----------+                          |
|          |                              ^                                |
|          |                              | compr_drain_notify()           |
|          |                              |        or                      |
|          |                              |     compr_stop()               |
|          |                              |                                |
|          |                         +----------+                          |
|          |                         |          |                          |
|          |                         |   DRAIN  |                          |
|          |                         |          |                          |
|          |                         +----------+                          |
|          |                              ^                                |
|          |                              |                                |
|          |                              | compr_drain()                  |
|          |                              |                                |
|          v                              |                                |
|    +----------+                    +----------+                          |
|    |          |    compr_start()   |          |        compr_stop()      |
|    | PREPARE  |------------------->|  RUNNING |--------------------------+
|    |          |                    |          |                          |
|    +----------+                    +----------+                          |
|          |                            |    ^                             |
|          |compr_free()                |    |                             |
|          |              compr_pause() |    | compr_resume()              |
|          |                            |    |                             |
|          v                            v    |                             |
|    +----------+                   +----------+                           |
|    |          |                   |          |         compr_stop()      |
+--->|   FREE   |                   |  PAUSE   |---------------------------+|          |                   |          |+----------+                   +----------+

無縫播放

當播放唱片時,解碼器能夠跳過編碼器延遲和填充,并直接從一個曲目內容移動到另一個曲目內容。最終用戶可以將其視為無縫播放,因為我們在從一個曲目切換到另一個曲目時沒有靜音。

此外,由于編碼可能會產生低強度噪聲。所有類型的壓縮數據都很難達到完美的無縫效果,但對于大多數音樂內容來說效果很好。解碼器需要知道編碼器延遲和編碼器填充。所以我們需要將其傳遞給 DSP。該元數據是從 ID3/MP4 頭中提取的,默認情況下不存在于比特流中,因此需要一個新的接口來將此信息傳遞給 DSP。此外,DSP 和用戶空間需要從一個曲目切換到另一個曲目,并開始使用第二個曲目的數據。

主要補充內容是:

set_metadata

該例程設置編碼器延遲和編碼器填充。解碼器可以使用它來去除靜音。這需要在寫入曲目中的數據之前進行設置。

set_next_track

該例程告訴 DSP,在此之后發送的元數據和寫入操作將對應于后續曲目。

partial_drain

當到達文件末尾時調用此函數。用戶空間可以通知 DSP 已達到 EOF,現在 DSP 可以開始跳過填充延遲。下一次寫入數據也將屬于下一個曲目。

無縫播放的順序流程為:

  • 打開
  • 獲得能力 (caps)/編解碼器能力 (caps)
  • 設置參數
  • 設置第一首曲目的元數據
  • 填充第一首曲目的數據
  • 觸發啟動
  • 用戶空間結束所有的發送,
  • 通過發送 set_next_track 指示下一首曲目的數據,
  • 設置下一首曲目的元數據
  • 然后調用 partial_drain 刷新 DSP 中緩沖區的大部分
  • 填充下一首曲目的數據
  • DSP 切換到第二首曲目

(注意:partial_drain 和寫入下一首曲目的數據的順序也可以反過來)

無縫播放狀態機

對于無縫播放,我們從運行狀態轉移到部分耗盡狀態并返回,同時設置元數據和下一首曲目的信號

                          +----------+compr_drain_notify()    |          |
+------------------------>|  RUNNING |
|                         |          |
|                         +----------+
|                              |
|                              |
|                              | compr_next_track()
|                              |
|                              V
|                         +----------+
|    compr_set_params()   |          |
|             +-----------|NEXT_TRACK|
|             |           |          |
|             |           +--+-------+
|             |              | |
|             +--------------+ |
|                              |
|                              | compr_partial_drain()
|                              |
|                              V
|                         +----------+
|                         |          |
+------------------------ | PARTIAL_ ||  DRAIN   |+----------+

不支持

  • 支持 VoIP/電路交換呼叫不是此 API 的目標。支持動態比特率變化需要 DSP 和主機堆棧之間的緊密耦合,從而限制了節能。

  • 不支持丟包隱藏。這將需要一個額外的接口,以便解碼器在傳輸過程中丟失幀時合成數據。將來可能會添加此功能。

  • 這個 API 不處理音量控制/路由。公開壓縮數據接口的設備將被視為常規 ALSA 設備;改變音量和路由信息將通過常規 ALSA kcontrol 提供。

  • 嵌入式音效。無論輸入是 PCM 還是壓縮的,都應以相同的方式啟用此類音效。

  • 多通道 IEC 編碼。不清楚是否需要這樣做。

  • 如上所述,不支持編碼/解碼加速。可以將解碼器的輸出路由到采集流,甚至實現轉碼功能。此路由將通過 ALSA kcontrol 啟用。

  • 音頻策略/資源管理。該 API 不提供任何掛鉤來查詢音頻 DSP 的利用率,也不提供任何搶占機制。

  • 沒有 underrun/overrun 的概念。由于寫入的字節本質上是壓縮的,并且寫入/讀取的數據不會及時直接轉換為渲染輸出,因此這不會處理 underrun/overrun 問題,可能會在用戶庫中處理

作者

  • Mark Brown 和 Liam Girdwood 討論了此 API 的需求
  • Harsha Priya 在 intel_sst 壓縮 API 方面的工作
  • Rakesh Ughreja 提供了寶貴的反饋
  • Sing Nallasellan、Sikkandar Madar 和 Prasanna Samaga 在真實平臺上演示并量化了音頻卸載的優勢。

原文

Done.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/209336.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209336.shtml
英文地址,請注明出處:http://en.pswp.cn/news/209336.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git如何配置多個遠程倉庫,并且進行切換

一、配置多個遠程倉庫并進行切換&#xff0c;請按照以下步驟進行操作&#xff1a; 打開命令行終端&#xff0c;并進入您的 Git 倉庫所在的目錄。添加第一個遠程倉庫&#xff0c;使用以下命令&#xff1a;git remote add origin <第一個遠程倉庫的 URL>這里將遠程倉庫命名…

C# .NET平臺提取PDF表格數據,并轉換為txt、CSV和Excel表格文件

處理PDF文件中的內容是比較麻煩的事情&#xff0c;特別是以表格形式呈現的各種數據。為了充分利用這些寶貴的數據資源&#xff0c;我們可以通過程序提取PDF文件中的表格&#xff0c;并將其保存為更易于處理和分析的格式&#xff0c;如txt、csv、xlsx&#xff0c;從而更方便地對…

leetcode面試經典150題——35 螺旋矩陣

題目&#xff1a; 螺旋矩陣 描述&#xff1a; 給你一個 m 行 n 列的矩陣 matrix &#xff0c;請按照 順時針螺旋順序 &#xff0c;返回矩陣中的所有元素。 示例&#xff1a; 輸入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 輸出&#xff1a;[1,2,3,6,9,8,7,4,5] 提示&…

Redis Geo操作地理位置

Redis Geo 使用場景API列表名詞API列表Springboot使用mavenyamlTest 注意事項 Redis Geo 是Redis在3.2版本中新增的功能&#xff0c;用于存儲和操作地理位置信息 使用場景 滴滴打車&#xff1a;這是一個對地理位置精度要求較高的場景。通過使用Redis的GEO功能&#xff0c;滴滴…

12月8日作業

使用手動連接&#xff0c;將登錄框中的取消按鈕使用qt4版本的連接到自定義的槽函數中&#xff0c;在自定義的槽函數中調用關閉函數&#xff1b;將登錄按鈕使用qt5版本的連接到自定義的槽函數中&#xff0c;在槽函數中判斷u界面上輸入的賬號是否為"admin"&#xff0c;…

kafka學習筆記--安裝部署、簡單操作

本文內容來自尚硅谷B站公開教學視頻&#xff0c;僅做個人總結、學習、復習使用&#xff0c;任何對此文章的引用&#xff0c;應當說明源出處為尚硅谷&#xff0c;不得用于商業用途。 如有侵權、聯系速刪 視頻教程鏈接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;從入門到調優…

Day54力扣打卡

打卡記錄 出租車的最大盈利&#xff08;動態規劃&#xff09; 鏈接 class Solution:def maxTaxiEarnings(self, n: int, rides: List[List[int]]) -> int:d defaultdict(list)for start, end, w in rides:d[end].append((start, end - start w))f [0] * (n 1)for i in…

文章解讀與仿真程序復現思路——電力自動化設備EI\CSCD\北大核心《考慮源網荷效益的峰谷電價與峰谷時段雙層優化模型》

這個標題涉及到電力定價和能源效益的優化模型。讓我來分解一下&#xff1a; 峰谷電價&#xff1a;這是一種電力定價策略&#xff0c;即在一天內不同時間段設定不同的電價。通常&#xff0c;高峰時段&#xff08;需求高&#xff09;的電價相對較高&#xff0c;而低谷時段&#x…

人工智能學習9(LightGBM)

編譯工具&#xff1a;PyCharm 文章目錄 編譯工具&#xff1a;PyCharm lightGBM原理lightGBM的基礎使用案例1&#xff1a;鳶尾花案例2&#xff1a;絕對求生玩家排名預測一、數據處理部分1.數據獲取及分析2.缺失數據處理3.數據規范化4.規范化輸出部分數據5.異常數據處理5.1刪除開…

利用私域運營的四大策略實現企業營銷目標

私域運營指的是企業利用各種網絡技術和工具&#xff0c;以自己的平臺為基礎&#xff0c;建立、維護、更新和升級與用戶的私人關系。這種運營模式讓企業能更準確地了解客戶需求和喜好&#xff0c;通過定制化服務、優惠政策、個性化體驗等方式&#xff0c;獲取更多的客戶價值。相…

Child Mind Institute - Detect Sleep States(2023年第一次Kaggle拿到了銀牌總結)

感謝 感謝艾兄&#xff08;大佬帶隊&#xff09;、rich師弟&#xff08;師弟通過這次比賽機械轉碼成功、耐心學習&#xff09;、張同學&#xff08;也很有耐心的在學習&#xff09;&#xff0c;感謝開源方案&#xff08;開源就是銀牌&#xff09;&#xff0c;在此基礎上一個月…

基于Lucene的全文檢索系統的實現與應用

文章目錄 一、概念二、引入案例1、數據庫搜索2、數據分類3、非結構化數據查詢方法1&#xff09; 順序掃描法(Serial Scanning)2&#xff09;全文檢索(Full-text Search) 4、如何實現全文檢索 三、Lucene實現全文檢索的流程1、索引和搜索流程圖2、創建索引1&#xff09;獲取原始…

模板與泛型編程

函數模板 顯示實例化 區別定義與聲明 T是模板形參 int是模板實參 inpunt是函數形參 3是函數實參 顯示實例化 模板必須實例化可見 翻譯單元一處定義原則 與內聯函數異同 引入原因&#xff1a;函數模板是為了編譯器兩個階段的處理 內聯函數是為了能在編譯期展開 模板實參的類…

Android Kotlin語言下的文件存儲

目錄 將數據存儲到文件中 創建文件和保存數據 讀取文件 SharedPreferences存儲 存儲數據到SharedPreferences中 Context類中的getSharedPreferences()方法 Activity類中的getPreferences()方法 從SharedPreferences中讀取數據 SQLite數據庫存儲 創建數據庫 調用數據…

Java導出word

原文地址 傳入的值不能為null,否則會報錯&#xff0c;IXDocReport 有自己的判null規則&#xff0c;比較麻煩&#xff0c;建議代碼直接把null替換成"" public void exportWord1(WeeklyMeetDataDto dto, HttpServletResponse response) {ServletOutputStream downLoad…

Ignis - Interactive Fire System

Ignis - 點火、蔓延、熄滅、定制! 全方位火焰系統。 這個插件在21年的項目中使用過很好用值使用概述 想玩火嗎?如果想的話,那么Ignis就是你的最佳工具。有了Ignis,你可以把任何物體、植被或帶皮帶骨的網狀物轉換為可燃物體,它就會自動著火。然后,火焰可以蔓延,點燃其他物…

Java 一對多

前言 Internet 協議集支持一個無連接的傳輸協議&#xff0c;該協議稱為用戶數據報協議&#xff08;UDP&#xff0c;User Datagram Protocol&#xff09;。UDP 為應用程序提供了一種無需建立連接就可以發送封裝的 IP 數據包的方法。 此代碼就是基于UDP協議編寫。 通常把一對多的…

【docker 】centOS 安裝docker

官網 docker官網 github源碼 卸載舊版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安裝軟件包 yum install -y yum-utils \device-mapper-persistent-data…

【優選算法系列】【專題二滑動窗口】第四節.30. 串聯所有單詞的子串和76. 最小覆蓋子串

文章目錄 前言一、串聯所有單詞的子串 1.1 題目描述 1.2 題目解析 1.2.1 算法原理 1.2.2 代碼編寫 1.2.3 題目總結二、最小覆蓋子串 2.1 題目描述 2.2 題目解析 2.2.1 算法原理 2.2.2 代碼編寫 …

【Docker】進階之路:(四)操作容器

【Docker】進階之路&#xff1a;&#xff08;四&#xff09;Docker容器 容器的生命周期創建容器docker createdocker run 管理容器查看運行的容器&#xff1a;查看所有容器&#xff1a; 啟動與終止啟動容器終止容器 進入容器docker attachdocker exec 導出和導入導出導入 容器的…