bluez-alsa
bluez-alsa copied to clipboard
Add support for LHDC V3 A2DP source and sink
Closes #588
~~Source does not work, only some buzzing noise is produced instead of music. I've tried saving pcm.data as raw pcm and it seems to be incorrect already. Library expects interleaved 24 or 16 bit data depending on selected bit depth, so probably related to the use of BA_TRANSPORT_PCM_FORMAT_S24_4LE.~~ It seems to be somewhat working now, but not yet perfect.
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 63.97%. Comparing base (
b7bb861
) to head (004360a
).
Additional details and impacted files
@@ Coverage Diff @@
## master #672 +/- ##
==========================================
+ Coverage 63.93% 63.97% +0.04%
==========================================
Files 93 93
Lines 14809 14809
Branches 2374 2375 +1
==========================================
+ Hits 9468 9474 +6
+ Misses 5235 5229 -6
Partials 106 106
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
I still have no idea why this happens even with BA_TRANSPORT_PCM_FORMAT_S32_4LE. Apparently, some variables in a2dp_lhdc_enc_thread
aren't what I thought. liblhdcBT_enc.so built from same sources works fine in Android. PCM dump appears to have same issues as sound in headphones. liblhdcBT_enc.so built from same sources works fine in Android, so I can't see what's wrong.
I'd like to test it locally. From where I can get the ldhcBT-dec/enc libraries? If this PR were to go to master I need to have a possibility to test the code for potential regressions.
UPDATED Apr 5, 2024 libs.zip headers.zip
Source code for libraries will be available later.
LHDC_INCLUDE_DIR=/path/to/headers
export LHDC_DEC_CFLAGS="-I$LHDC_INCLUDE_DIR/liblhdcdec/include -I$LHDC_INCLUDE_DIR/liblhdcdec/inc -L$LHDC_INCLUDE_DIR"
export LHDC_DEC_LIBS="-llhdcBT_dec"
export LHDC_ENC_CFLAGS="-I$LHDC_INCLUDE_DIR/liblhdc/include -I$LHDC_INCLUDE_DIR/liblhdc/inc -L$LHDC_INCLUDE_DIR"
export LHDC_ENC_LIBS="-llhdcBT_enc"
autoreconf --install
mkdir build && cd build
../configure --enable-aac --enable-lhdc --enable-debug
make
sudo make install
In the last few days I've done long overdue refactoring around A2DP codecs. Now, the logic is kept mostly in one file, which should simplify maintenance and addition of new codecs. Due to extensive changes, I've rebased your work on top of current master. The code seems to compile, but I've got no time yet to test whether it works :D
Also, I've left some commented code (I'm not sure whether it will be required or not). In the A2DP configuration for LHDC you've added #define LHDC_CHANNEL_MODE_STEREO 0x03
which suggests that the channel mode can be selected, is that true? If yes, the channel mode selection will need to be done right in a2dp_lhdc_configuration_select()
and a2dp_lhdc_configuration_check()
functions, otherwise, maybe the define should be removed?
Most constants were directly copied from AOSP patches. This must be a remnant of that. Seems to be unused, so might be removed probably.
The commented out code seems to be for channel mode, so could be removed as well.
Another issue would be to implement LLAC/V3/V4 selection logic, which is basically the following:
- If LLAC is supported and LLAC-friendly bitrate is selected (ABR or < 500 kbps) then default to 48 kHz and enable LLAC (V4 flag needs to be set to 0).
- If LLAC is not supported then enable V4 if it's supported, otherwise go for V3.
At least sink seems to still work.
I've tried to run it once again, but now it doesn't seem to work (even AAC doesn't work).
$ bluealsa-aplay
bluealsa-aplay: [8934] W: ../../../utils/aplay/aplay.c:1278: Couldn't get BlueALSA PCM list: Sender is not authorized to send message
or from root:
bluealsa-aplay: [9413] D: ../../../utils/aplay/aplay.c:876: Creating IO worker XX:XX:XX:XX:XX:XX
bluealsa-aplay: [9413] D: ../../../utils/aplay/aplay.c:1287: Starting main loop
bluealsa-aplay: [9414] D: ../../../utils/aplay/aplay.c:542: Opening BlueALSA source PCM: /org/bluealsa/hci0/dev_XX_XX_XX_XX_XX_XX/a2dpsnk/source
bluealsa-aplay: [9414] D: ../../../utils/aplay/aplay.c:568: Starting IO loop
bluealsa-aplay: [9414] D: ../../../utils/aplay/aplay.c:692: Opening ALSA playback PCM: name=default channels=2 rate=44100
bluealsa-aplay: [9414] W: ../../../utils/aplay/aplay.c:696: Couldn't open ALSA playback PCM: Open PCM: Host is down
Probably related to #681, though I haven't recompiled PipeWire, just renamed /usr/lib/spa-0.2/bluez5. My phone also says "Problem connecting. Turn device off & back on", but I definitely can see audio packets in WireShark.
UPD This works for AAC:
sudo bluealsa-cli open /org/bluealsa/hci0/dev_XX_XX_XX_XX_XX_XX/a2dpsnk/source | play -e signed-integer -b 16 -c 2 -r 44100 -t raw -
But it segfaults with LHDC:
#0 0x00007ffff768632c in ??? () at /usr/lib/libc.so.6
#1 0x00007ffff76356c8 in raise () at /usr/lib/libc.so.6
#2 0x00007ffff761d4b8 in abort () at /usr/lib/libc.so.6
#3 0x00007ffff761e395 in ??? () at /usr/lib/libc.so.6
#4 0x00007ffff76902a7 in ??? () at /usr/lib/libc.so.6
#5 0x00007ffff7690de4 in ??? () at /usr/lib/libc.so.6
#6 0x00007ffff7690f2b in ??? () at /usr/lib/libc.so.6
#7 0x00007ffff7691fdd in ??? () at /usr/lib/libc.so.6
#8 0x00007ffff7692669 in ??? () at /usr/lib/libc.so.6
#9 0x00007ffff7694e93 in free () at /usr/lib/libc.so.6
#10 0x000055555555ff81 in ffb_free (ffb=0x7ffff4bffc70) at ../../src/shared/ffb.c:46
#11 0x000055555557b1d7 in a2dp_lhdc_dec_thread (t_pcm=0x5555555c08f0) at ../../src/a2dp-lhdc.c:347
#12 0x00007ffff768455a in ??? () at /usr/lib/libc.so.6
#13 0x00007ffff7701a3c in ??? () at /usr/lib/libc.so.6
But it segfaults with LHDC
It seems that the problem is somewhere within encoder code. The reason of abort is heap corruption due to memmove()
beyond allocated memory in ffb_t bt
buffer. I've tested with new library and the old one, but the result is all the same:
==1263640== Invalid write of size 2
==1263640== at 0x48529E3: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1263640== by 0x4F1C7E4: ??? (in /mnt/storage1t/Downloads/balsa/build/lhdc/liblhdcBT_enc.new.so)
==1263640== by 0x125B5E: a2dp_lhdc_enc_thread (a2dp-lhdc.c:179)
==1263640== by 0x5309AC2: start_thread (pthread_create.c:442)
==1263640== by 0x539AA03: clone (clone.S:100)
==1263640== Address 0x5af146a is 1,002 bytes inside a block of size 1,003 alloc'd
==1263640== at 0x48487A9: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1263640== by 0x111C9C: ffb_init (ffb.c:26)
==1263640== by 0x125801: a2dp_lhdc_enc_thread (a2dp-lhdc.c:125)
==1263640== by 0x5309AC2: start_thread (pthread_create.c:442)
==1263640== by 0x539AA03: clone (clone.S:100)
==1263640==
==1263640== Invalid write of size 1
==1263640== at 0x4852A13: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1263640== by 0x4F1C7E4: ??? (in /mnt/storage1t/Downloads/balsa/build/lhdc/liblhdcBT_enc.new.so)
==1263640== by 0x125B5E: a2dp_lhdc_enc_thread (a2dp-lhdc.c:179)
==1263640== by 0x5309AC2: start_thread (pthread_create.c:442)
==1263640== by 0x539AA03: clone (clone.S:100)
==1263640== Address 0x5af1478 is 13 bytes after a block of size 1,003 alloc'd
==1263640== at 0x48487A9: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1263640== by 0x111C9C: ffb_init (ffb.c:26)
==1263640== by 0x125801: a2dp_lhdc_enc_thread (a2dp-lhdc.c:125)
==1263640== by 0x5309AC2: start_thread (pthread_create.c:442)
==1263640== by 0x539AA03: clone (clone.S:100)
I was testing the decoder, but encoder having the same issue is really strange. None of them should call memmove
directly (except third-party submodules). I'll look into that.
Do you have any suggestions for coexisting with pipewire?
I was testing the decoder, but encoder having the same issue is really strange.
I've added a test code which encodes PCM and then decodes it, so due to encoder failure I was not able to check decoder, not yet :D
Do you have any suggestions for coexisting with pipewire?
What do you mean "coexisting"? If you have BlueALSA and PipeWire running on the same host at the same time, then you should disable (somehow) Bluetooth support in PipeWire (I'm not sure whether renaming BlueZ plugin is sufficient, it might be though). Then, remove paired device and pair it again, so BlueZ will not reuse cached SDP information.
EDIT: In order to test encoder/decoder with IO test you can run it with valgrind like this:
make check TESTS=
CK_FORK=no valgrind ./test/test-io lhdc-v3
What do you mean "coexisting"?
bluealsa-aplay
doesn't play any sound: Couldn't open ALSA playback PCM: Open PCM: Host is down
Though, I guess, for debugging this issue I might just run that test.
bluealsa-aplay doesn't play any sound: Couldn't open ALSA playback PCM: Open PCM: Host is down
I guess that you have to use PCM playback which is not grabbed by PipeWire or use some playback PCM exposed by PipeWire itself (if there is any). However, I'm not PipeWire user (not yet), so I've got zero knowledge about PipeWire configuration. Anyway, the error code "Host is down" is kinda strange...
Apparently, it doesn't like the following line:
memcpy(out_put, enc, handle->host_mtu_size);
And this is exactly what original library does.
So this, per say, is not a library error. Should be fixed now.
So this, per say, is not a library error. Should be fixed now.
OK, now the test passes but only with the old version of the library. With the new one (UPDATED Mar 1, 2024) encoder produces only 78 bytes per packet, where the old one produces 270 bytes. It looks like the output is truncated because these 78 bytes matches with the first 78 bytes in the packet from the old encoder.
You're right, there was a stupid bug. I've updated the libraries.
UPDATED Apr 5, 2024 libs.zip headers.zip
Source code for libraries will be available later.
LHDC_INCLUDE_DIR=/path/to/headers export LHDC_DEC_CFLAGS="-I$LHDC_INCLUDE_DIR/liblhdcdec/include -I$LHDC_INCLUDE_DIR/liblhdcdec/inc -L$LHDC_INCLUDE_DIR" export LHDC_DEC_LIBS="-llhdcBT_dec" export LHDC_ENC_CFLAGS="-I$LHDC_INCLUDE_DIR/liblhdc/include -I$LHDC_INCLUDE_DIR/liblhdc/inc -L$LHDC_INCLUDE_DIR" export LHDC_ENC_LIBS="-llhdcBT_enc" autoreconf --install mkdir build && cd build ../configure --enable-aac --enable-lhdc --enable-debug make sudo make install
Where did you get the library liblhdcBT_dec.so from?
Where did you get the library liblhdcBT_dec.so from?
From the same place as liblhdcBT_enc.so. I compiled it from sources.