mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-21 07:00:08 -05:00
bluez5: support packet loss concealment in codecs
LC3 and Opus have built-in support for packet loss concealment. Add codec interface for that, and implement for LC3. Extend media_codec interface so that packets not aligned with socket reads can be handled, as in HFP. This is required for correct sequence number counting, and for being able to run codec PLC *before* decoding the next correctly received packet.
This commit is contained in:
parent
a2ede93479
commit
d0680a2b3d
5 changed files with 76 additions and 5 deletions
|
|
@ -1310,6 +1310,24 @@ static SPA_UNUSED int codec_decode(void *data,
|
|||
return consumed;
|
||||
}
|
||||
|
||||
static int codec_produce_plc(void *data, void *dst, size_t dst_size)
|
||||
{
|
||||
struct impl *this = data;
|
||||
int ich, res;
|
||||
|
||||
if (dst_size < this->codesize)
|
||||
return -EINVAL;
|
||||
|
||||
for (ich = 0; ich < this->channels; ich++) {
|
||||
uint8_t *out = (uint8_t *)dst + (ich * 4);
|
||||
res = lc3_decode(this->dec[ich], NULL, 0, LC3_PCM_FORMAT_S24, out, this->channels);
|
||||
if (SPA_UNLIKELY(res < 0))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return this->codesize;
|
||||
}
|
||||
|
||||
static int codec_reduce_bitpool(void *data)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
|
|
@ -1424,6 +1442,7 @@ const struct media_codec bap_codec_lc3 = {
|
|||
.encode = codec_encode,
|
||||
.start_decode = codec_start_decode,
|
||||
.decode = codec_decode,
|
||||
.produce_plc = codec_produce_plc,
|
||||
.reduce_bitpool = codec_reduce_bitpool,
|
||||
.increase_bitpool = codec_increase_bitpool,
|
||||
.set_log = codec_set_log,
|
||||
|
|
|
|||
|
|
@ -213,6 +213,21 @@ static int codec_decode(void *data,
|
|||
return H2_PACKET_SIZE - 2;
|
||||
}
|
||||
|
||||
static int codec_produce_plc(void *data, void *dst, size_t dst_size)
|
||||
{
|
||||
struct impl *this = data;
|
||||
int res;
|
||||
|
||||
if (dst_size < LC3_A127_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
res = lc3_decode(this->dec, NULL, 0, LC3_PCM_FORMAT_FLOAT, dst, 1);
|
||||
if (res != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return LC3_A127_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static void codec_set_log(struct spa_log *global_log)
|
||||
{
|
||||
log = global_log;
|
||||
|
|
@ -233,6 +248,7 @@ static const struct media_codec hfp_codec_a127 = {
|
|||
.set_log = codec_set_log,
|
||||
.start_decode = codec_start_decode,
|
||||
.decode = codec_decode,
|
||||
.produce_plc = codec_produce_plc,
|
||||
.name = "lc3_a127",
|
||||
.description = "LC3-24kHz",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ static int codec_decode(void *data,
|
|||
int res;
|
||||
|
||||
*dst_out = 0;
|
||||
if (dst_size < LC3_SWB_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!this->data)
|
||||
this->data = h2_reader_read(&this->h2, src, src_size, &consumed, &this->avail);
|
||||
|
|
@ -205,14 +207,30 @@ static int codec_decode(void *data,
|
|||
this->data = NULL;
|
||||
|
||||
if (res) {
|
||||
h2_reader_init(&this->h2, true);
|
||||
return -EINVAL;
|
||||
/* fail decoding silently, so remainder of packet is processed */
|
||||
spa_log_debug(log, "decoding failed: %d", res);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
*dst_out = LC3_SWB_BLOCK_SIZE;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static int codec_produce_plc(void *data, void *dst, size_t dst_size)
|
||||
{
|
||||
struct impl *this = data;
|
||||
int res;
|
||||
|
||||
if (dst_size < LC3_SWB_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
res = lc3_decode(this->dec, NULL, 0, LC3_PCM_FORMAT_FLOAT, dst, 1);
|
||||
if (res != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return LC3_SWB_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static void codec_set_log(struct spa_log *global_log)
|
||||
{
|
||||
log = global_log;
|
||||
|
|
@ -233,8 +251,10 @@ 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 = "lc3_swb",
|
||||
.description = "LC3-SWB",
|
||||
.stream_pkt = true,
|
||||
};
|
||||
|
||||
MEDIA_CODEC_EXPORT_DEF(
|
||||
|
|
|
|||
|
|
@ -193,8 +193,9 @@ static int codec_decode(void *data,
|
|||
this->data = NULL;
|
||||
|
||||
if (res < 0) {
|
||||
h2_reader_init(&this->h2, true);
|
||||
return res;
|
||||
/* fail decoding silently, so remainder of packet is processed */
|
||||
spa_log_debug(log_, "decoding failed: %d", res);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
|
@ -222,6 +223,7 @@ const struct media_codec hfp_codec_msbc = {
|
|||
.decode = codec_decode,
|
||||
.name = "msbc",
|
||||
.description = "MSBC",
|
||||
.stream_pkt = true,
|
||||
};
|
||||
|
||||
MEDIA_CODEC_EXPORT_DEF(
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#define SPA_TYPE_INTERFACE_Bluez5CodecMedia SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private"
|
||||
|
||||
#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 14
|
||||
#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 15
|
||||
|
||||
struct spa_bluez5_codec_a2dp {
|
||||
struct spa_interface iface;
|
||||
|
|
@ -88,6 +88,10 @@ struct media_codec {
|
|||
|
||||
const struct media_codec *duplex_codec; /**< Codec for non-standard A2DP duplex channel */
|
||||
|
||||
const bool stream_pkt; /**< If true, socket data may contain multiple packets.
|
||||
* After successful decode, start_decode() should be
|
||||
* called again to parse the remaining data. */
|
||||
|
||||
int (*get_bis_config)(const struct media_codec *codec, uint8_t *caps,
|
||||
uint8_t *caps_size, struct spa_dict *settings,
|
||||
struct bap_codec_qos *qos);
|
||||
|
|
@ -202,6 +206,16 @@ struct media_codec {
|
|||
void *dst, size_t dst_size,
|
||||
size_t *dst_out);
|
||||
|
||||
/**
|
||||
* Generate audio data corresponding to one lost packet, using codec internal
|
||||
* packet loss concealment.
|
||||
*
|
||||
* NULL if not available.
|
||||
*
|
||||
* \return number of bytes produced, or < 0 for error
|
||||
*/
|
||||
int (*produce_plc) (void *data, void *dst, size_t dst_size);
|
||||
|
||||
int (*reduce_bitpool) (void *data);
|
||||
int (*increase_bitpool) (void *data);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue