-
Notifications
You must be signed in to change notification settings - Fork 246
feature: bt classic a2dp sink external codec api bindings #660
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
billylindeman
wants to merge
7
commits into
esp-rs:master
Choose a base branch
from
billylindeman:billy/a2dp-external-codec-api
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
aa37eb1
add external codec api integration from latest esp-idf
billylindeman 2f7e29c
parse aac params during negotiation
billylindeman 5f7bc70
cargo fmt
billylindeman 116af7f
cleanup
billylindeman 51ce358
add comment on how to run example
billylindeman 40fc5eb
Address pr comments
billylindeman 6a04344
wifi: drop Copy/Clone from DppCfgRecvdRef
billylindeman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Self-contained sdkconfig fragment for the bt_a2dp_sink_external_codec example. | ||
| # Can be used alone (`ESP_IDF_SDKCONFIG_DEFAULTS=this_file`) OR layered | ||
| # on top of .github/configs/sdkconfig.defaults. | ||
|
|
||
| # Stack sizes that Rust applications generally want bumped from defaults. | ||
| CONFIG_ESP_TIMER_TASK_STACK_SIZE=4096 | ||
| CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000 | ||
| CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=8192 | ||
| CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 | ||
| CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=4096 | ||
|
|
||
| # Bluetooth Classic + Bluedroid (A2DP sink prerequisites). | ||
| CONFIG_BT_ENABLED=y | ||
| CONFIG_BT_BLUEDROID_ENABLED=y | ||
| CONFIG_BT_CLASSIC_ENABLED=y | ||
| # Disable the BLE host stack entirely. We've added a cfg gate to | ||
| # esp-idf-svc's `bt::ble` module (src/bt.rs) so it only compiles when | ||
| # CONFIG_BT_BLE_ENABLED=y, which sidesteps the BLE GATT bindings that | ||
| # changed in esp-idf v6.1-dev. | ||
| CONFIG_BT_BLE_ENABLED=n | ||
| CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y | ||
| CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n | ||
| CONFIG_BTDM_CTRL_MODE_BTDM=n | ||
| CONFIG_BT_BTC_TASK_STACK_SIZE=15000 | ||
|
|
||
| # A2DP sink in external-codec mode with AAC + SBC SEPs. | ||
| CONFIG_BT_A2DP_ENABLE=y | ||
| CONFIG_BT_A2DP_USE_EXTERNAL_CODEC=y | ||
| CONFIG_BT_A2DP_CODEC_AAC_ENABLED=y | ||
| CONFIG_BT_A2DP_SEP_NUM_MAX=2 | ||
|
|
||
| # ESP32-WROVER (8 MB QSPI PSRAM). Bluedroid + A2DP wants more | ||
| # heap than the bare 320 KiB internal SRAM gives. | ||
| CONFIG_SPIRAM=y | ||
| CONFIG_SPIRAM_MODE_QUAD=y | ||
| CONFIG_SPIRAM_TYPE_AUTO=y | ||
| CONFIG_SPIRAM_SPEED_80M=y | ||
| # Flash and PSRAM share the SPI bus, so the two clock speeds must match. | ||
| CONFIG_ESPTOOLPY_FLASHFREQ_80M=y | ||
| CONFIG_SPIRAM_BOOT_INIT=y | ||
| CONFIG_SPIRAM_USE_MALLOC=y | ||
| CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y | ||
| CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 | ||
| CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| [idf_format_args] | ||
| partition_table = "partitions.csv" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| //! A2DP sink example using the external-codec API. | ||
| //! | ||
| //! Initialises Bluedroid classic, advertises the device as A2DP sink with | ||
| //! both AAC and SBC stream endpoints, and logs incoming events including | ||
| //! the encoded audio buffers delivered by the peer source (typically a | ||
| //! phone). Decoding of those buffers is intentionally left out — pair this | ||
| //! with Espressif's `esp_audio_codec` managed component (or any other | ||
| //! decoder) on top. | ||
| //! | ||
| //! Required sdkconfig settings: | ||
| //! | ||
| //! ```ignore | ||
| //! CONFIG_BT_ENABLED=y | ||
| //! CONFIG_BT_BLUEDROID_ENABLED=y | ||
| //! CONFIG_BT_CLASSIC_ENABLED=y | ||
| //! CONFIG_BT_A2DP_ENABLE=y | ||
| //! CONFIG_BT_A2DP_USE_EXTERNAL_CODEC=y | ||
| //! CONFIG_BT_A2DP_SEP_NUM_MAX=2 | ||
| //! CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y | ||
| //! CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n | ||
| //! CONFIG_BTDM_CTRL_MODE_BTDM=n | ||
| //! CONFIG_BT_BTC_TASK_STACK_SIZE=15000 | ||
| //! ``` | ||
| //! | ||
| //! To run this example: | ||
| //! MCU=esp32 ESP_IDF_SDKCONFIG_DEFAULTS=.github/configs/sdkconfig.a2dp_external_codec cargo +esp espflash flash --target xtensa-esp32-espidf --example bt_a2dp_sink_external_codec --monitor | ||
|
|
||
| #![allow(unknown_lints)] | ||
| #![allow(unexpected_cfgs)] | ||
|
|
||
| #[cfg(all(esp32, esp_idf_bt_a2dp_use_external_codec))] | ||
| fn main() -> anyhow::Result<()> { | ||
| example::main() | ||
| } | ||
|
|
||
| #[cfg(not(all(esp32, esp_idf_bt_a2dp_use_external_codec)))] | ||
| fn main() -> anyhow::Result<()> { | ||
| println!("FALLBACK MAIN: cfg gate did not match"); | ||
| panic!("This example requires ESP32 with CONFIG_BT_A2DP_USE_EXTERNAL_CODEC=y"); | ||
| } | ||
|
|
||
| #[cfg(all(esp32, esp_idf_bt_a2dp_use_external_codec))] | ||
| mod example { | ||
| use std::sync::Arc; | ||
|
|
||
| use esp_idf_svc::bt::a2dp::{A2dpEvent, Codec, EspA2dp, Sink}; | ||
| use esp_idf_svc::bt::gap::{DiscoveryMode, EspGap}; | ||
| use esp_idf_svc::bt::{reduce_bt_memory, BtClassic, BtDriver}; | ||
| use esp_idf_svc::hal::delay::FreeRtos; | ||
| use esp_idf_svc::hal::peripherals::Peripherals; | ||
| use esp_idf_svc::log::EspLogger; | ||
| use esp_idf_svc::nvs::EspDefaultNvsPartition; | ||
|
|
||
| use log::info; | ||
|
|
||
| pub fn main() -> anyhow::Result<()> { | ||
| esp_idf_svc::sys::link_patches(); | ||
| EspLogger::initialize_default(); | ||
| info!("step 1: logger up"); | ||
|
|
||
| let peripherals = Peripherals::take()?; | ||
| info!("step 2: peripherals taken"); | ||
| let nvs = EspDefaultNvsPartition::take()?; | ||
| info!("step 3: nvs taken"); | ||
|
|
||
| let mut modem = peripherals.modem; | ||
|
|
||
| reduce_bt_memory(unsafe { modem.reborrow() })?; | ||
| info!("step 4: reduce_bt_memory ok"); | ||
|
|
||
| let bt = Arc::new(BtDriver::<BtClassic>::new(modem, Some(nvs.clone()))?); | ||
| info!("step 5: BtDriver up"); | ||
|
|
||
| let gap = EspGap::new(bt.clone())?; | ||
| info!("step 6: gap created"); | ||
| gap.set_device_name("ESP32_A2DP_SINK")?; | ||
| gap.set_scan_mode(true, DiscoveryMode::Discoverable)?; | ||
| info!("step 7: gap configured"); | ||
|
|
||
| let a2dp = EspA2dp::<'_, _, _, Sink>::new_external_codec(bt.clone())?; | ||
| info!("step 8: a2dp external-codec sink up"); | ||
|
|
||
| a2dp.subscribe(|event| { | ||
| match &event { | ||
| A2dpEvent::SinkAudioData(buf) => { | ||
| info!( | ||
| "audio frame: {} frames, {} bytes, ts {}", | ||
| buf.frames(), | ||
| buf.data().len(), | ||
| buf.timestamp() | ||
| ); | ||
| } | ||
| A2dpEvent::SinkEndpointRegistered { seid, state } => { | ||
| info!("SEP {seid} register result: {state:?}"); | ||
| } | ||
| A2dpEvent::AudioCodecConfigured { bd_addr, codec } => { | ||
| info!("negotiated codec with {bd_addr:?}: {codec:?}"); | ||
| } | ||
| other => info!("a2dp event: {other:?}"), | ||
| } | ||
| 0 | ||
| })?; | ||
|
|
||
| info!("step 9: subscribed; registering SEPs"); | ||
| // AAC at seid 0 (preferred), SBC at seid 1 (mandatory fallback). | ||
| for (seid, codec) in [(0, Codec::aac_default()), (1, Codec::sbc_default())] { | ||
| info!("registering {} at seid {}", codec.name(), seid); | ||
| a2dp.register_sink_endpoint(seid, &codec)?; | ||
| } | ||
|
|
||
| info!("step 10: A2DP sink ready; pair with phone and play audio"); | ||
|
|
||
| loop { | ||
| FreeRtos::delay_ms(10_000); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.