UbuntuBluetooth A2DP receiver實現分析



https://blog.csdn.net/wendell_gong/article/details/20557707

 

A2DP相關部分的簡介

    A2DP——Advanced Audio Distribution Profile,是藍牙音訊資料傳輸的profileA2DP中定義了兩種role: Source and Sink。發送音訊流的設備是source,接收音訊流的設備是sink,比如手機是source,藍牙耳機是sinkA2DP依賴與傳輸層協議AVDTP——Audio/Video Distribution Transport ProtocolA2DP還規定了音訊的編碼格式,其中SBC是必須支援的,可選的格式有MPEG-1, MPEG-2, MPEG-4, AAC and ATRC, 另外也支援廠商擴展的格式,比如高品質的音訊編碼格式apt-X

BlueZ相關部分簡介

    BlueZLinux的官方標準藍牙協議層,目前的最新版本是5.x。在4.46上,BlueZ實現了對A2DP Sink的支持,而之前的版本只支持A2DP Source。以下的討論是基於BlueZ 4.46之後的4.x版本。5.x因為在D-Bus介面方面有較大改動,會影響A2DP Sink和上層Audio server的介面,不在本討論覆蓋範圍之內。

PulseAudio相關部分的簡介

    PulseAudio是一個開源的、跨平臺的、支援網路的sound server。它可以支援從一個或多個source(進程或音訊採集設備)輸入聲音並重定向它到一個或多個sink(音效卡,遠端網路PulseAudio server或其他進程)。PulseAudio的目的之一就是通過它來reroute所有的音訊流,如下圖

 

為了支援Bluetooth audio sourcePulseAuido還實現了動態檢測藍牙音訊設備的功能。這個功能和BlueZ A2DP Sink都是由João Paulo實現的,可以在它的blogBlueZ now has A2DP Sink support》中找到相關資訊(需要翻牆,責任自負)。

系統架構

 

開啟A2DP Receiver功能

    按照這篇《Can I use my computer as an A2DP receiver?》的說明,即可在Ubuntu系統上開啟A2DP receiver的功能。有一點需要解釋的是為什麼要打開的是A2DP Sink,而/etc/bluetooth/audio.conf中增加的卻是Enable=Source。這個‘source’是針對PulseAudio的來說的,而不是指A2DP中的source role。一個Bluetooth A2DP sink device,在PulseAudio看來就是一個音訊輸入的source。另,在某些Ubuntu版本上有PulseAudio不能reroute A2DP audio stream的情況。我的PC系統資訊如下:Ubuntu 12.04, BlueZ 4.98, pulseAudio 1.1

    bluez.orgpulseaudio.org可下載到源碼,然後進行分析。

BlueZA2DP Sink的實現

    在閱讀代碼之前,最好先熟悉以下這兩份spec: A2DP and AVDTP,這將有助於理解代碼。從bluetooth.org上可以下載到這兩份spec

    bluez/audio目錄集中了audio相關的protocolprofile(但是並未給每個audio相關的profile建立子目錄,BlueZ 5.x對此上做了改進,在bluez/profiles目錄下給每個profile建立了子目錄)。audio相關的模組以BlueZ plugin的形式載入,其plugin介面實現在bluez/audio/main.c中。audio_init()載入了audio.conf文件,並調用bluez/audio/manager.c中的audio_manager_init()對這個檔的內容進行解析。前面提到的‘Enable=Source’就是被這個函數解析的,並設置了‘enabled.source = TRUE’。在manager.c中,audio的一系列server都被註冊了,包括headset server, gateway server, a2dp server, avrcp server, media server。如果想瞭解每個server的註冊,初始化過程,可以從manager.c入手。

    A2DP Sink實現的原始檔案是source.c(注意:source.c實現了A2DP Sink而不是sink.c)。a2dp.c也做了一些支持A2DP sink的相應改進,比如增加了對AVDTP_SEP_TYPE_SOURCE的判斷,然後調用相應的sourcesink函數。結合文檔和protocol analyzer tool可以比較容易追蹤音訊資料流程的處理過程。

PulseAudio如何從BlueZ得到音訊資料

    雖然BlueZ內部對A2DP Sink的實現較為複雜,但是暴露給外部的資料介面確非常簡單。在bluez/audio/ipc.c中實現了三個bt_audio_service函數。PulseAudio使用bt_audio_service_open()打開一個socket,然後調用bt_audio_service_get_data_fd()得到音訊資料檔案描述符fd。這個fd是通過那個socketBlueZ的進程傳遞到PulseAudio的進程的。最後,使用完畢,調用bt_audio_service_close()來關閉socketPulseAudio通過D-busBlueZ進行通信,進行參數的讀取和設置,決定合適的讀取時機,發送讀取的狀態。

     PulseAudiofd讀出的音訊資料流程是經過SBC壓縮編碼的(對於採用其他編碼,如MPEG-1,的情況,本文不做討論),PulseAudio還需要對這些音訊資料流程進行解碼。在BlueZ中已經實現了SBC編解碼,原始檔案位於bluez/sbcPluseAudio直接使用了這些原始程式碼,把它們放在pulseadio/src/modules/bluetooth/sbc中。

創作者介紹
創作者 立你斯 的頭像
立你斯

立你斯學習記錄

立你斯 發表在 痞客邦 留言(0) 人氣()