[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] bluetooth: mSBC: Decode packets larger than mSBC frame

PulseAudio Marge Bot (@pulseaudio-merge-bot) gitlab at gitlab.freedesktop.org
Fri May 27 17:45:08 UTC 2022



PulseAudio Marge Bot pushed to branch master at PulseAudio / pulseaudio


Commits:
9916f0ea by Igor V. Kovalenko at 2022-05-27T17:42:38+00:00
bluetooth: mSBC: Decode packets larger than mSBC frame

Bluetooth transport layer already allows for packets larger than mSBC frame, and
there are up to 1 + MTU / (mSBC packet size) complete frames to be decoded from
each incoming SCO packet.

Now decoder fails when there is more than one complete frame available, which
could happen if MTU size is larger than 1.5 * (mSBC packet size) = 90

Fix this by adding a loop over avialable frames, and adjust decoded buffer size
to allow decoding up to 1 + MTU / (mSBC packet size) frames at once.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/706>

- - - - -


1 changed file:

- src/modules/bluetooth/bt-codec-msbc.c


Changes:

=====================================
src/modules/bluetooth/bt-codec-msbc.c
=====================================
@@ -112,7 +112,15 @@ static size_t get_read_block_size(void *codec_info, size_t link_mtu) {
         block_size = pa_frame_align(block_size, &info->sample_spec);
     }
 
-    return block_size;
+    /* If MTU exceeds mSBC frame size there could be up to 1 + MTU / (mSBC frame size)
+     * frames decoded for single incoming packet.
+     * See also pa_bluetooth_transport::last_read_size handling
+     * and comment about MTU size in bt_prepare_encoder_buffer()
+     */
+    if (link_mtu <= MSBC_PACKET_SIZE)
+        return block_size;
+
+    return block_size * (1 + link_mtu / MSBC_PACKET_SIZE);
 }
 
 static size_t get_write_block_size(void *codec_info, size_t link_mtu) {
@@ -204,10 +212,10 @@ static inline bool is_all_zero(const uint8_t *ptr, size_t len) {
 /*
  * We build a msbc frame up in the sbc_info buffer until we have a whole one
  */
-static struct msbc_frame *msbc_find_frame(struct sbc_info *si, ssize_t *len,
+static struct msbc_frame *msbc_find_frame(struct sbc_info *si, size_t *len,
                                           const uint8_t *buf, int *pseq)
 {
-    int i;
+    size_t i;
     uint8_t *p = si->input_buffer;
 
     /* skip input if it has all zero bytes
@@ -241,7 +249,7 @@ static struct msbc_frame *msbc_find_frame(struct sbc_info *si, ssize_t *len,
             id1.b = p[1];
             *pseq = (id1.s.sn0 & 0x1) | (id1.s.sn1 & 0x2);
             si->msbc_push_offset = 0;
-            *len = *len - i;
+            *len -= i + 1;
             return (struct msbc_frame *)p;
         }
         continue;
@@ -255,49 +263,55 @@ static struct msbc_frame *msbc_find_frame(struct sbc_info *si, ssize_t *len,
 
 static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
     struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
-    ssize_t remaining;
+    size_t save_input_size;
     ssize_t decoded;
     size_t written = 0;
+    size_t total_written = 0;
+    size_t total_processed = 0;
     struct msbc_frame *frame;
     int seq;
 
-    remaining = input_size;
-    frame = msbc_find_frame(sbc_info, &remaining, input_buffer, &seq);
+    while (input_size > 0) {
 
-    /* only process when we have a full frame */
-    if (!frame) {
-        *processed = input_size - remaining;
-        return 0;
-    }
+        save_input_size = input_size;
+        frame = msbc_find_frame(sbc_info, &input_size, input_buffer + total_processed, &seq);
 
-    uint8_t lost_packets = (4 + seq - sbc_info->msbc_seq++) % 4;
+        total_processed += save_input_size - input_size;
 
-    if (lost_packets) {
-        pa_log_debug("Lost %d input audio packet(s)", lost_packets);
-        sbc_info->msbc_seq = seq + 1;
-    }
+        /* Only full mSBC frame should be decoded */
+        if (!frame)
+            break;
+
+        uint8_t lost_packets = (4 + seq - sbc_info->msbc_seq++) % 4;
 
-    decoded = sbc_decode(&sbc_info->sbc, frame->payload, MSBC_FRAME_SIZE, output_buffer, output_size, &written);
+        if (lost_packets) {
+            pa_log_debug("Lost %d input audio packet(s)", lost_packets);
+            sbc_info->msbc_seq = seq + 1;
+        }
 
-    /* now we've consumed the sbc_info buffer, start a new one with
-     * the partial frame we have */
-    if (remaining > 0)
-        msbc_find_frame(sbc_info, &remaining, input_buffer + input_size - remaining, &seq);
+        /* pa_bt_codec::get_read_block_size must provide space for all decoded frames */
+        pa_assert_fp(output_size >= sbc_info->codesize);
 
-    pa_assert_fp(remaining == 0);
+        decoded = sbc_decode(&sbc_info->sbc, frame->payload, MSBC_FRAME_SIZE, output_buffer, output_size, &written);
 
-    if (PA_UNLIKELY(decoded <= 0)) {
-        pa_log_error("mSBC decoding error (%li)", (long) decoded);
-        pa_silence_memory(output_buffer, sbc_info->codesize, &sbc_info->sample_spec);
-        decoded = sbc_info->frame_length;
-        written = sbc_info->codesize;
-    }
+        if (PA_UNLIKELY(decoded <= 0)) {
+            pa_log_error("mSBC decoding error (%li)", (long) decoded);
+            pa_silence_memory(output_buffer, sbc_info->codesize, &sbc_info->sample_spec);
+            decoded = sbc_info->frame_length;
+            written = sbc_info->codesize;
+        }
 
-    pa_assert_fp((size_t)decoded == sbc_info->frame_length);
-    pa_assert_fp((size_t)written == sbc_info->codesize);
+        pa_assert_fp((size_t)decoded == sbc_info->frame_length);
+        pa_assert_fp((size_t)written == sbc_info->codesize);
+
+        output_buffer += written;
+        output_size -= written;
+
+        total_written += written;
+    }
 
-    *processed = input_size - remaining;
-    return written;
+    *processed = total_processed;
+    return total_written;
 }
 
 /* Modified SBC codec for HFP Wideband Speech*/



View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/9916f0eace6ab1825af74a5f9b166918a06ce50e

-- 
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/9916f0eace6ab1825af74a5f9b166918a06ce50e
You're receiving this email because of your account on gitlab.freedesktop.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20220527/92e58562/attachment-0001.htm>


More information about the pulseaudio-commits mailing list