Skip to content
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

Add support for LHDC v2 A2DP source and sink #742

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Add support for LHDC v2 A2DP source and sink #742

wants to merge 1 commit into from

Conversation

arkq
Copy link
Owner

@arkq arkq commented Dec 8, 2024

This PR is a follow-up for #672

Copy link

codecov bot commented Dec 8, 2024

Codecov Report

Attention: Patch coverage is 41.66667% with 7 lines in your changes missing coverage. Please review.

Project coverage is 70.19%. Comparing base (0f322eb) to head (b842141).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/main.c 0.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #742      +/-   ##
==========================================
- Coverage   70.51%   70.19%   -0.32%     
==========================================
  Files          96       97       +1     
  Lines       16005    16067      +62     
  Branches     2509     2517       +8     
==========================================
- Hits        11286    11279       -7     
- Misses       4602     4670      +68     
- Partials      117      118       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@arkq
Copy link
Owner Author

arkq commented Dec 8, 2024

@anonymix007 I'm trying to add support for LHDC v2 using your library, but it seems that something is not right. As I've mentioned earlier, I have a retail device which is able to stream LHDC v2 codec (Huawei Mate 20 Pro). Unfortunately, the lhdcBT_dec_decode is not able to properly decode the stream. Captured RTP stream (from the phone) you can find here:
a2dp-sink-LHDC-v2-s32-48000-2c.zip. The *.rtp file is a hex dump of each A2DP packet, while the *.btd file is a dump which can be used with ./test/test-io to feed BT stream directly to the a2dp_lhdc_dec_thread function as follows (the --dump option will create decoded wav file):

./test/test-io lhdc-v2 --input-bt hw20-a2dp-sink-LHDC-v2-s32-48000-2c.btd --dump

It seems that the decoder is not able to decode most of the frames...

Used A2DP configuration:

$ a2dpconf lhdc-v2:3a050000324c140001
LHDC v2 <hex:3a050000324c140001> {
  vendor-id:32 = 0x0000053a [Savitech Corp.,]
  vendor-codec-id:16 = 0x4c32
  <reserved>:2
  bit-depth:2 = 24
  sample-rate:4 = 48000
  low-latency:1 = false
  max-bitrate:3 = 900
  version:4 = 0
  <reserved>:4
  ch-split-mode:4 = None
}

However, when stream is created with lhdcBT_encode (in order to create LHDC v2), the decoder is able to decode something. I'm not sure whether I've used the lhdcBT_encode in a right way (I've been trying to follow code from your lhdcenc_stereo.c), but the decoder is able to decode only the right channel. The left channel seems to be some garbage/noise. Also, the PCM format for lhdcBT_encode does not seem to be interleaved stereo s32le, but only a single channel.

Encoded and decoded sine with patch as follows:

diff --git a/src/a2dp-lhdc.c b/src/a2dp-lhdc.c
index f6d50e7..08fc4a2 100644
--- a/src/a2dp-lhdc.c
+++ b/src/a2dp-lhdc.c
@@ -303,7 +303,11 @@ void *a2dp_lhdc_enc_thread(struct ba_transport_pcm *t_pcm) {
if (codec_id == A2DP_CODEC_VENDOR_ID(LHDC_V2_VENDOR_ID, LHDC_V2_CODEC_ID)) {
-                               if ((rv = lhdcBT_encode(handle, input, bt.tail)) < 0) {
+                               int32_t xxx[2048] = { 0 };
+                               for (size_t i = 0; i < lhdc_ch_samples; i++)
+                                       xxx[i] = input[i*2];
+                               if ((rv = lhdcBT_encode(handle, xxx, bt.tail)) < 0) {
error("LHDC encoding error: %d", rv);
break;
}
./test/test-io lhdc-v2 --dump

test-io-lhdc-v2

Left channel is garbage, and the encoded channel is decoded as a right one.

Also, it seems that the lhdcBT_encode does not respect MTU. Even though the MTU is set to something like 900 bytes, the encoder writes ~2k of data. So, maybe the payload should be fragmented here on the RTP level?

Do you have any idea what might be wrong with v2 here?

In next few days I'll try to get some Android phone with LHDC v3 to test the v3 decoder.

@anonymix007
Copy link
Contributor

PCM data ends up in this function:

/**
 * LHDC encode function
 *  fb: LHDC control block.
 *  wav : The PCM data. please input non-planer and compact PCM data.
 *        (eg. The input stream format is 96KHz/24bits stereo and the LHDC request 512 samples for each frame.
 *         So the PCM data length should be 512 * 2 * (24/8) = 3072 bytes. The data order should be L/R, L/R, L/R....).
 *  ns  : The number of samples, not PCM data byte length. The LHDC encoder only supports 512.
 *  final   : Fixed to 0.
 *  out : Output buffer pointer.
 *  out_len : The output buffer size to protect overwrite.
 *
 *  Return value :
 *      The return value should be the encoded size, otherwise an error occurs (less than or equal to 0)
 *
 */
int LossyEncoderProcessWav(FFT_BLOCK *fb, unsigned char *wav, int ns, int final, unsigned char *out, int out_len);

I'll take a look at the dump a bit later.

Also, it seems that the lhdcBT_encode does not respect MTU. Even though the MTU is set to something like 900 bytes, the encoder writes ~2k of data.

This could be a bug in my implementation or normal behavior, I'm not sure. Is it happening for just a few first frames or is it consistent?

So, maybe the payload should be fragmented here on the RTP level?

AFAIU it won't work because sink devices do not do anything to defragment payloads afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants