bluez5: add PLC for MSBC using spandsp

Use spandsp as optional dependency for MSBC codec, for providing PLC.
This commit is contained in:
Pauli Virtanen 2025-06-14 18:52:55 +03:00 committed by Wim Taymans
parent 90a1b35017
commit 87843366ce
5 changed files with 66 additions and 4 deletions

View file

@ -153,6 +153,10 @@ option('bluez5-codec-g722',
description: 'Enable G722 open source codec implementation',
type: 'feature',
value: 'auto')
option('bluez5-plc-spandsp',
description: 'Enable SpanDSP for packet loss concealment',
type: 'feature',
value: 'auto')
option('control',
description: 'Enable control spa plugin integration',
type: 'feature',

View file

@ -111,6 +111,9 @@ if get_option('spa-plugins').allowed()
endif
g722_codec_option = get_option('bluez5-codec-g722')
summary({'G722': g722_codec_option.allowed()}, bool_yn: true, section: 'Bluetooth audio codecs')
spandsp_dep = dependency('spandsp', required : get_option('bluez5-plc-spandsp'))
cdata.set('HAVE_SPANDSP', spandsp_dep.found())
endif
have_vulkan = false

View file

@ -3,6 +3,8 @@
/* SPDX-FileCopyrightText: Copyright © 2025 Pauli Virtanen */
/* SPDX-License-Identifier: MIT */
#include "config.h"
#include <unistd.h>
#include <string.h>
#include <stddef.h>
@ -24,10 +26,12 @@
#include "media-codecs.h"
#include "hfp-h2.h"
#include "plc.h"
#define MSBC_BLOCK_SIZE 240
static struct spa_log *log;
static struct spa_log *log_;
struct impl {
sbc_t msbc;
@ -36,6 +40,8 @@ struct impl {
void *data;
size_t avail;
plc_state_t *plc;
};
static int codec_enum_config(const struct media_codec *codec, uint32_t flags,
@ -104,6 +110,10 @@ static void *codec_init(const struct media_codec *codec, uint32_t flags,
h2_reader_init(&this->h2, true);
this->plc = plc_init(NULL);
if (!this->plc)
return NULL;
return spa_steal_ptr(this);
}
@ -112,6 +122,7 @@ static void codec_deinit(void *data)
struct impl *this = data;
sbc_finish(&this->msbc);
plc_free(this->plc);
free(this);
}
@ -198,13 +209,30 @@ static int codec_decode(void *data,
return consumed;
}
plc_rx(this->plc, dst, *dst_out / sizeof(int16_t));
return consumed;
}
static int codec_produce_plc(void *data, void *dst, size_t dst_size)
{
struct impl *this = data;
int res;
if (dst_size < MSBC_BLOCK_SIZE)
return -EINVAL;
res = plc_fillin(this->plc, dst, MSBC_BLOCK_SIZE / sizeof(int16_t));
if (res < 0)
return res;
return MSBC_BLOCK_SIZE;
}
static void codec_set_log(struct spa_log *global_log)
{
log = global_log;
spa_log_topic_init(log, &codec_plugin_log_topic);
log_ = global_log;
spa_log_topic_init(log_, &codec_plugin_log_topic);
}
const struct media_codec hfp_codec_msbc = {
@ -221,6 +249,7 @@ const struct media_codec hfp_codec_msbc = {
.set_log = codec_set_log,
.start_decode = codec_start_decode,
.decode = codec_decode,
.produce_plc = codec_produce_plc,
.name = "msbc",
.description = "MSBC",
.stream_pkt = true,

View file

@ -110,7 +110,7 @@ bluez_codec_hfp_msbc = shared_library('spa-codec-bluez5-hfp-msbc',
[ 'hfp-codec-msbc.c', 'media-codecs.c' ],
include_directories : [ configinc ],
c_args : codec_args,
dependencies : [ spa_dep, sbc_dep ],
dependencies : [ spa_dep, sbc_dep, spandsp_dep ],
install : true,
install_dir : spa_plugindir / 'bluez5')

26
spa/plugins/bluez5/plc.h Normal file
View file

@ -0,0 +1,26 @@
/* Spa PLC */
/* SPDX-FileCopyrightText: Copyright © 2025 Pauli Virtanen */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_BLUEZ5_PLC_H
#define SPA_BLUEZ5_PLC_H
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#ifdef HAVE_SPANDSP
#include <spandsp.h>
#else
typedef struct { char dummy; } plc_state_t;
static inline int plc_rx(plc_state_t *s, int16_t *data, int len) { return -ENOTSUP; }
static inline int plc_fillin(plc_state_t *s, int16_t *data, int len) { return -ENOTSUP; }
static inline plc_state_t *plc_init(plc_state_t *s)
{
static plc_state_t state;
return &state;
}
static inline int plc_free(plc_state_t *s) { return 0; }
#endif
#endif