bluez5: support other ldac bit depth

Make the format_info const in codec_init, we just need to read the
final negotiated format in some cases.
Add some more ldac bit depths we support.
This commit is contained in:
Wim Taymans 2020-12-11 13:30:11 +01:00
parent bcf6c0986e
commit 8b52e44836
5 changed files with 50 additions and 116 deletions

View file

@ -140,7 +140,7 @@ static int codec_select_config(const struct a2dp_codec *codec, uint32_t flags,
} }
static void *codec_init(const struct a2dp_codec *codec, uint32_t flags, static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
void *config, size_t config_len, struct spa_audio_info *info, size_t mtu) void *config, size_t config_len, const struct spa_audio_info *info, size_t mtu)
{ {
struct impl *this; struct impl *this;
int res; int res;
@ -150,10 +150,6 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
res = -errno; res = -errno;
goto error; goto error;
} }
spa_zero(*info);
info->media_type = SPA_MEDIA_TYPE_audio;
info->media_subtype = SPA_MEDIA_SUBTYPE_aac;
this->mtu = mtu; this->mtu = mtu;
return this; return this;

View file

@ -202,10 +202,9 @@ static int codec_get_block_size(void *data)
} }
static void *codec_init(const struct a2dp_codec *codec, uint32_t flags, static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
void *config, size_t config_len, struct spa_audio_info *info, size_t mtu) void *config, size_t config_len, const struct spa_audio_info *info, size_t mtu)
{ {
struct impl *this; struct impl *this;
a2dp_aptx_t *conf = config;
int res, hd; int res, hd;
if ((this = calloc(1, sizeof(struct impl))) == NULL) if ((this = calloc(1, sizeof(struct impl))) == NULL)
@ -218,54 +217,12 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
this->mtu = mtu; this->mtu = mtu;
spa_zero(*info); if (info->media_type != SPA_MEDIA_TYPE_audio ||
info->media_type = SPA_MEDIA_TYPE_audio; info->media_subtype != SPA_MEDIA_SUBTYPE_raw ||
info->media_subtype = SPA_MEDIA_SUBTYPE_raw; info->info.raw.format != SPA_AUDIO_FORMAT_S16) {
info->info.raw.format = SPA_AUDIO_FORMAT_S16;
switch (conf->frequency) {
case APTX_SAMPLING_FREQ_16000:
info->info.raw.rate = 16000;
break;
case APTX_SAMPLING_FREQ_32000:
info->info.raw.rate = 32000;
break;
case APTX_SAMPLING_FREQ_44100:
info->info.raw.rate = 44100;
break;
case APTX_SAMPLING_FREQ_48000:
info->info.raw.rate = 48000;
break;
default:
res = -EINVAL; res = -EINVAL;
goto error; goto error;
}
switch (conf->channel_mode) {
case APTX_CHANNEL_MODE_MONO:
info->info.raw.channels = 1;
break;
case APTX_CHANNEL_MODE_STEREO:
info->info.raw.channels = 2;
break;
default:
res = -EINVAL;
goto error;
}
switch (info->info.raw.channels) {
case 1:
info->info.raw.position[0] = SPA_AUDIO_CHANNEL_MONO;
break;
case 2:
info->info.raw.position[0] = SPA_AUDIO_CHANNEL_FL;
info->info.raw.position[1] = SPA_AUDIO_CHANNEL_FR;
break;
default:
res = -EINVAL;
goto error;
} }
this->frame_length = hd ? 6 : 4; this->frame_length = hd ? 6 : 4;
this->codesize = 4 * 3 * 2; this->codesize = 4 * 3 * 2;
@ -275,6 +232,8 @@ error_errno:
res = -errno; res = -errno;
goto error; goto error;
error: error:
if (this->aptx)
aptx_finish(this->aptx);
free(this); free(this);
errno = -res; errno = -res;
return NULL; return NULL;

View file

@ -45,10 +45,8 @@ struct impl {
int mtu; int mtu;
int eqmid; int eqmid;
int channel_mode;
int frequency; int frequency;
int fmt; int fmt;
int lsu;
int codesize; int codesize;
int frame_length; int frame_length;
}; };
@ -130,7 +128,12 @@ static int codec_enum_config(const struct a2dp_codec *codec,
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_S16), SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(5,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_F32,
SPA_AUDIO_FORMAT_S32,
SPA_AUDIO_FORMAT_S24,
SPA_AUDIO_FORMAT_S16),
0); 0);
spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0); spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0);
@ -240,7 +243,7 @@ static int codec_get_block_size(void *data)
} }
static void *codec_init(const struct a2dp_codec *codec, uint32_t flags, static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
void *config, size_t config_len, struct spa_audio_info *info, size_t mtu) void *config, size_t config_len, const struct spa_audio_info *info, size_t mtu)
{ {
struct impl *this; struct impl *this;
a2dp_ldac_t *conf = config; a2dp_ldac_t *conf = config;
@ -255,64 +258,56 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
goto error_errno; goto error_errno;
this->eqmid = LDACBT_EQMID_SQ; this->eqmid = LDACBT_EQMID_SQ;
this->mtu = mtu;
this->frequency = info->info.raw.rate;
this->codesize = info->info.raw.channels;
spa_zero(*info); switch (info->info.raw.format) {
info->media_type = SPA_MEDIA_TYPE_audio; case SPA_AUDIO_FORMAT_F32:
info->media_subtype = SPA_MEDIA_SUBTYPE_raw; this->fmt = LDACBT_SMPL_FMT_F32;
info->info.raw.format = SPA_AUDIO_FORMAT_S16; this->codesize *= 4;
this->fmt = LDACBT_SMPL_FMT_S16; break;
this->mtu =mtu; case SPA_AUDIO_FORMAT_S32:
this->fmt = LDACBT_SMPL_FMT_S32;
this->codesize *= 4;
break;
case SPA_AUDIO_FORMAT_S24:
this->fmt = LDACBT_SMPL_FMT_S24;
this->codesize *= 3;
break;
case SPA_AUDIO_FORMAT_S16:
this->fmt = LDACBT_SMPL_FMT_S16;
this->codesize *= 2;
break;
default:
res = -EINVAL;
goto error;
}
switch(conf->frequency) { switch(conf->frequency) {
case LDACBT_SAMPLING_FREQ_044100: case LDACBT_SAMPLING_FREQ_044100:
info->info.raw.rate = 44100;
this->lsu = 128;
break;
case LDACBT_SAMPLING_FREQ_048000: case LDACBT_SAMPLING_FREQ_048000:
info->info.raw.rate = 48000; this->codesize *= 128;
this->lsu = 128;
break; break;
case LDACBT_SAMPLING_FREQ_088200: case LDACBT_SAMPLING_FREQ_088200:
info->info.raw.rate = 88200;
this->lsu = 256;
break;
case LDACBT_SAMPLING_FREQ_096000: case LDACBT_SAMPLING_FREQ_096000:
info->info.raw.rate = 96000; this->codesize *= 256;
this->lsu = 256;
break; break;
default: default:
res = -EINVAL; res = -EINVAL;
goto error; goto error;
} }
this->frequency = info->info.raw.rate;
switch(conf->channel_mode) {
case LDACBT_CHANNEL_MODE_STEREO:
info->info.raw.channels = 2;
break;
case LDACBT_CHANNEL_MODE_DUAL_CHANNEL:
info->info.raw.channels = 2;
break;
case LDACBT_CHANNEL_MODE_MONO:
info->info.raw.channels = 1;
break;
default:
res = -EINVAL;
goto error;
}
this->channel_mode = conf->channel_mode;
res = ldacBT_init_handle_encode(this->ldac, res = ldacBT_init_handle_encode(this->ldac,
this->mtu, this->mtu,
this->eqmid, this->eqmid,
this->channel_mode, conf->channel_mode,
this->fmt, this->fmt,
this->frequency); this->frequency);
if (res < 0) if (res < 0)
goto error; goto error;
this->frame_length = get_frame_length(this); this->frame_length = get_frame_length(this);
this->codesize = this->lsu * info->info.raw.channels * 2;
return this; return this;

View file

@ -303,7 +303,7 @@ static int codec_get_block_size(void *data)
} }
static void *codec_init(const struct a2dp_codec *codec, uint32_t flags, static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
void *config, size_t config_len, struct spa_audio_info *info, size_t mtu) void *config, size_t config_len, const struct spa_audio_info *info, size_t mtu)
{ {
struct impl *this; struct impl *this;
a2dp_sbc_t *conf = config; a2dp_sbc_t *conf = config;
@ -319,27 +319,25 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
this->sbc.endian = SBC_LE; this->sbc.endian = SBC_LE;
this->mtu = mtu; this->mtu = mtu;
spa_zero(*info); if (info->media_type != SPA_MEDIA_TYPE_audio ||
info->media_type = SPA_MEDIA_TYPE_audio; info->media_subtype != SPA_MEDIA_SUBTYPE_raw ||
info->media_subtype = SPA_MEDIA_SUBTYPE_raw; info->info.raw.format != SPA_AUDIO_FORMAT_S16) {
info->info.raw.format = SPA_AUDIO_FORMAT_S16; res = -EINVAL;
goto error;
}
switch (conf->frequency) { switch (conf->frequency) {
case SBC_SAMPLING_FREQ_16000: case SBC_SAMPLING_FREQ_16000:
this->sbc.frequency = SBC_FREQ_16000; this->sbc.frequency = SBC_FREQ_16000;
info->info.raw.rate = 16000;
break; break;
case SBC_SAMPLING_FREQ_32000: case SBC_SAMPLING_FREQ_32000:
this->sbc.frequency = SBC_FREQ_32000; this->sbc.frequency = SBC_FREQ_32000;
info->info.raw.rate = 32000;
break; break;
case SBC_SAMPLING_FREQ_44100: case SBC_SAMPLING_FREQ_44100:
this->sbc.frequency = SBC_FREQ_44100; this->sbc.frequency = SBC_FREQ_44100;
info->info.raw.rate = 44100;
break; break;
case SBC_SAMPLING_FREQ_48000: case SBC_SAMPLING_FREQ_48000:
this->sbc.frequency = SBC_FREQ_48000; this->sbc.frequency = SBC_FREQ_48000;
info->info.raw.rate = 48000;
break; break;
default: default:
res = -EINVAL; res = -EINVAL;
@ -349,35 +347,21 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
switch (conf->channel_mode) { switch (conf->channel_mode) {
case SBC_CHANNEL_MODE_MONO: case SBC_CHANNEL_MODE_MONO:
this->sbc.mode = SBC_MODE_MONO; this->sbc.mode = SBC_MODE_MONO;
info->info.raw.channels = 1;
break; break;
case SBC_CHANNEL_MODE_DUAL_CHANNEL: case SBC_CHANNEL_MODE_DUAL_CHANNEL:
this->sbc.mode = SBC_MODE_DUAL_CHANNEL; this->sbc.mode = SBC_MODE_DUAL_CHANNEL;
info->info.raw.channels = 2;
break; break;
case SBC_CHANNEL_MODE_STEREO: case SBC_CHANNEL_MODE_STEREO:
this->sbc.mode = SBC_MODE_STEREO; this->sbc.mode = SBC_MODE_STEREO;
info->info.raw.channels = 2;
break; break;
case SBC_CHANNEL_MODE_JOINT_STEREO: case SBC_CHANNEL_MODE_JOINT_STEREO:
this->sbc.mode = SBC_MODE_JOINT_STEREO; this->sbc.mode = SBC_MODE_JOINT_STEREO;
info->info.raw.channels = 2;
break; break;
default: default:
res = -EINVAL; res = -EINVAL;
goto error; goto error;
} }
switch (info->info.raw.channels) {
case 1:
info->info.raw.position[0] = SPA_AUDIO_CHANNEL_MONO;
break;
case 2:
info->info.raw.position[0] = SPA_AUDIO_CHANNEL_FL;
info->info.raw.position[1] = SPA_AUDIO_CHANNEL_FR;
break;
}
switch (conf->subbands) { switch (conf->subbands) {
case SBC_SUBBANDS_4: case SBC_SUBBANDS_4:
this->sbc.subbands = SBC_SB_4; this->sbc.subbands = SBC_SB_4;

View file

@ -336,7 +336,7 @@ struct a2dp_codec {
struct spa_pod_builder *builder, struct spa_pod **param); struct spa_pod_builder *builder, struct spa_pod **param);
void *(*init) (const struct a2dp_codec *codec, uint32_t flags, void *config, size_t config_size, void *(*init) (const struct a2dp_codec *codec, uint32_t flags, void *config, size_t config_size,
struct spa_audio_info *info, size_t mtu); const struct spa_audio_info *info, size_t mtu);
void (*deinit) (void *data); void (*deinit) (void *data);
int (*get_block_size) (void *data); int (*get_block_size) (void *data);