a2dp: delay codec init to after acquire

Some codecs need the MTU as a parameter so wait until we acquire
with creating the codec context.

Make some method to enumerate the parameters from the transport
config and use that for the EnumFormat param.
This commit is contained in:
Wim Taymans 2020-12-03 18:05:57 +01:00
parent 67694a1491
commit 8bf0b7b4db
5 changed files with 203 additions and 49 deletions

View file

@ -113,6 +113,86 @@ static int codec_select_config(uint32_t flags, const void *caps, size_t caps_siz
return sizeof(conf);
}
static int codec_enum_config(const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
struct spa_pod_builder *b, struct spa_pod **param)
{
a2dp_sbc_t conf;
struct spa_pod_frame f[2];
struct spa_pod_choice *choice;
uint32_t i = 0;
if (caps_size < sizeof(conf))
return -EINVAL;
memcpy(&conf, caps, sizeof(conf));
if (idx > 0)
return 0;
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_Format, id);
spa_pod_builder_add(b,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_S16),
0);
spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0);
spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_None, 0);
choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f[1]);
i = 0;
if (conf.frequency & LDACBT_SAMPLING_FREQ_048000) {
if (i++ == 0)
spa_pod_builder_int(b, 48000);
spa_pod_builder_int(b, 48000);
}
if (conf.frequency & LDACBT_SAMPLING_FREQ_044100) {
if (i++ == 0)
spa_pod_builder_int(b, 44100);
spa_pod_builder_int(b, 44100);
}
if (conf.frequency & LDACBT_SAMPLING_FREQ_088200) {
if (i++ == 0)
spa_pod_builder_int(b, 88200);
spa_pod_builder_int(b, 88200);
}
if (conf.frequency & LDACBT_SAMPLING_FREQ_096000) {
if (i++ == 0)
spa_pod_builder_int(b, 96000);
spa_pod_builder_int(b, 96000);
}
if (conf.frequency & LDACBT_SAMPLING_FREQ_176400) {
if (i++ == 0)
spa_pod_builder_int(b, 176400);
spa_pod_builder_int(b, 176400);
}
if (conf.frequency & LDACBT_SAMPLING_FREQ_192000) {
if (i++ == 0)
spa_pod_builder_int(b, 192000);
spa_pod_builder_int(b, 192000);
}
if (i > 1)
choice->body.type = SPA_CHOICE_Enum;
spa_pod_builder_pop(b, &f[1]);
if (conf.channel_mode & LDACBT_CHANNEL_MODE_MONO &&
conf.channel_mode & (LDACBT_CHANNEL_MODE_STEREO |
LDACBT_CHANNEL_MODE_DUAL_CHANNEL)) {
spa_pod_builder_add(b,
SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, 2),
0);
} else if (conf.channel_mode & LDACBT_CHANNEL_MODE_MONO) {
spa_pod_builder_add(b,
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1),
0);
} else {
spa_pod_builder_add(b,
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2),
0);
}
*param = spa_pod_builder_pop(b, &f[0]);
return 1;
}
static int codec_reduce_bitpool(void *data)
{
struct impl *this = data;
@ -125,13 +205,11 @@ static int codec_increase_bitpool(void *data)
return ldacBT_alter_eqmid_priority(this->ldac, LDACBT_EQMID_INC_QUALITY);
}
static int codec_get_num_blocks(void *data, size_t mtu)
static int codec_get_num_blocks(void *data)
{
struct impl *this = data;
size_t rtp_size = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
size_t frame_count = (mtu - rtp_size) / this->frame_length;
this->mtu = mtu;
size_t frame_count = (this->mtu - rtp_size) / this->frame_length;
/* frame_count is only 4 bit number */
if (frame_count > 15)
@ -145,7 +223,8 @@ static int codec_get_block_size(void *data)
return this->codesize;
}
static void *codec_init(uint32_t flags, void *config, size_t config_len, struct spa_audio_info *info)
static void *codec_init(uint32_t flags, void *config, size_t config_len, struct spa_audio_info *info,
size_t mtu)
{
struct impl *this;
a2dp_ldac_t *conf = config;
@ -166,6 +245,7 @@ static void *codec_init(uint32_t flags, void *config, size_t config_len, struct
info->media_subtype = SPA_MEDIA_SUBTYPE_raw;
info->info.raw.format = SPA_AUDIO_FORMAT_S16;
this->fmt = LDACBT_SMPL_FMT_S16;
this->mtu =mtu;
switch(conf->frequency) {
case LDACBT_SAMPLING_FREQ_044100:
@ -308,6 +388,7 @@ struct a2dp_codec a2dp_codec_ldac = {
.description = "LDAC",
.fill_caps = codec_fill_caps,
.select_config = codec_select_config,
.enum_config = codec_enum_config,
.init = codec_init,
.deinit = codec_deinit,
.get_block_size = codec_get_block_size,