mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
bluez5: add AAC-ELD codec
This commit is contained in:
parent
c3327742cc
commit
79ee1eaff0
6 changed files with 88 additions and 22 deletions
|
|
@ -21,6 +21,7 @@ enum spa_bluetooth_audio_codec {
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ,
|
SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
|
SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_AAC,
|
SPA_BLUETOOTH_AUDIO_CODEC_AAC,
|
||||||
|
SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_APTX,
|
SPA_BLUETOOTH_AUDIO_CODEC_APTX,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
|
SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_LDAC,
|
SPA_BLUETOOTH_AUDIO_CODEC_LDAC,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ static const struct spa_type_info spa_type_bluetooth_audio_codec[] = {
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "sbc_xq", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "sbc_xq", NULL },
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_MPEG, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "mpeg", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_MPEG, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "mpeg", NULL },
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_AAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aac", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_AAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aac", NULL },
|
||||||
|
{ SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aac_eld", NULL },
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_APTX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_APTX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx", NULL },
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx_hd", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx_hd", NULL },
|
||||||
{ SPA_BLUETOOTH_AUDIO_CODEC_LDAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "ldac", NULL },
|
{ SPA_BLUETOOTH_AUDIO_CODEC_LDAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "ldac", NULL },
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,13 @@ struct impl {
|
||||||
static int codec_fill_caps(const struct media_codec *codec, uint32_t flags,
|
static int codec_fill_caps(const struct media_codec *codec, uint32_t flags,
|
||||||
uint8_t caps[A2DP_MAX_CAPS_SIZE])
|
uint8_t caps[A2DP_MAX_CAPS_SIZE])
|
||||||
{
|
{
|
||||||
|
eld = spa_streq(codec->name, "aac_eld");
|
||||||
|
|
||||||
static const a2dp_aac_t a2dp_aac = {
|
static const a2dp_aac_t a2dp_aac = {
|
||||||
.object_type =
|
.object_type =
|
||||||
/* NOTE: AAC Long Term Prediction and AAC Scalable are
|
/* NOTE: AAC Long Term Prediction and AAC Scalable are
|
||||||
* not supported by the FDK-AAC library. */
|
* not supported by the FDK-AAC library. */
|
||||||
|
eld ? AAC_OBJECT_TYPE_MPEG4_AAC_ELD :
|
||||||
AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
||||||
AAC_OBJECT_TYPE_MPEG4_AAC_LC,
|
AAC_OBJECT_TYPE_MPEG4_AAC_LC,
|
||||||
AAC_INIT_FREQUENCY(
|
AAC_INIT_FREQUENCY(
|
||||||
|
|
@ -118,18 +121,27 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags,
|
||||||
if (caps_size < sizeof(conf))
|
if (caps_size < sizeof(conf))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
eld = spa_streq(codec->name, "aac_eld");
|
||||||
|
|
||||||
conf = *(a2dp_aac_t*)caps;
|
conf = *(a2dp_aac_t*)caps;
|
||||||
|
|
||||||
if (conf.object_type & AAC_OBJECT_TYPE_MPEG2_AAC_LC)
|
if (eld) {
|
||||||
conf.object_type = AAC_OBJECT_TYPE_MPEG2_AAC_LC;
|
if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_ELD)
|
||||||
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LC)
|
conf.object_type = AAC_OBJECT_TYPE_MPEG4_AAC_ELD;
|
||||||
conf.object_type = AAC_OBJECT_TYPE_MPEG4_AAC_LC;
|
else
|
||||||
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LTP)
|
return -ENOTSUP;
|
||||||
return -ENOTSUP; /* Not supported by FDK-AAC */
|
} else {
|
||||||
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_SCA)
|
if (conf.object_type & AAC_OBJECT_TYPE_MPEG2_AAC_LC)
|
||||||
return -ENOTSUP; /* Not supported by FDK-AAC */
|
conf.object_type = AAC_OBJECT_TYPE_MPEG2_AAC_LC;
|
||||||
else
|
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LC)
|
||||||
return -ENOTSUP;
|
conf.object_type = AAC_OBJECT_TYPE_MPEG4_AAC_LC;
|
||||||
|
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_LTP)
|
||||||
|
return -ENOTSUP; /* Not supported by FDK-AAC */
|
||||||
|
else if (conf.object_type & AAC_OBJECT_TYPE_MPEG4_AAC_SCA)
|
||||||
|
return -ENOTSUP; /* Not supported by FDK-AAC */
|
||||||
|
else
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if ((i = media_codec_select_config(aac_frequencies,
|
if ((i = media_codec_select_config(aac_frequencies,
|
||||||
SPA_N_ELEMENTS(aac_frequencies),
|
SPA_N_ELEMENTS(aac_frequencies),
|
||||||
|
|
@ -233,6 +245,8 @@ static int codec_validate_config(const struct media_codec *codec, uint32_t flags
|
||||||
if (caps == NULL || caps_size < sizeof(conf))
|
if (caps == NULL || caps_size < sizeof(conf))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
eld = spa_streq(codec->name, "aac_eld");
|
||||||
|
|
||||||
memcpy(&conf, caps, sizeof(conf));
|
memcpy(&conf, caps, sizeof(conf));
|
||||||
|
|
||||||
spa_zero(*info);
|
spa_zero(*info);
|
||||||
|
|
@ -246,9 +260,14 @@ static int codec_validate_config(const struct media_codec *codec, uint32_t flags
|
||||||
* bits for AAC object type. It's not clear if this was due to
|
* bits for AAC object type. It's not clear if this was due to
|
||||||
* a BlueZ bug, but we can be lax here and below in codec_init.
|
* a BlueZ bug, but we can be lax here and below in codec_init.
|
||||||
*/
|
*/
|
||||||
if (!(conf.object_type & (AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
if (eld) {
|
||||||
AAC_OBJECT_TYPE_MPEG4_AAC_LC)))
|
if (!(conf.object_type & AAC_OBJECT_TYPE_MPEG2_AAC_ELD))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
if (!(conf.object_type & (AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
||||||
|
AAC_OBJECT_TYPE_MPEG4_AAC_LC)))
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
SPA_FOR_EACH_ELEMENT_VAR(aac_frequencies, f) {
|
SPA_FOR_EACH_ELEMENT_VAR(aac_frequencies, f) {
|
||||||
if (AAC_GET_FREQUENCY(conf) & f->config) {
|
if (AAC_GET_FREQUENCY(conf) & f->config) {
|
||||||
|
|
@ -304,6 +323,8 @@ static void *codec_init(const struct media_codec *codec, uint32_t flags,
|
||||||
UINT bitratemode;
|
UINT bitratemode;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
eld = spa_streq(codec->name, "aac_eld");
|
||||||
|
|
||||||
this = calloc(1, sizeof(struct impl));
|
this = calloc(1, sizeof(struct impl));
|
||||||
if (this == NULL) {
|
if (this == NULL) {
|
||||||
res = -errno;
|
res = -errno;
|
||||||
|
|
@ -327,15 +348,30 @@ static void *codec_init(const struct media_codec *codec, uint32_t flags,
|
||||||
if (res != AACENC_OK)
|
if (res != AACENC_OK)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!(conf->object_type & (AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
if (eld) {
|
||||||
AAC_OBJECT_TYPE_MPEG4_AAC_LC))) {
|
if (!(conf->object_type & AAC_OBJECT_TYPE_MPEG4_AAC_ELD)) {
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = aacEncoder_SetParam(this->aacenc, AACENC_AOT, AOT_AAC_LC);
|
res = aacEncoder_SetParam(this->aacenc, AACENC_AOT, AOT_ER_AAC_ELD);
|
||||||
if (res != AACENC_OK)
|
if (res != AACENC_OK)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
res = aacEncoder_SetParam(this->aacenc, AACENC_SBR_MODE, 1);
|
||||||
|
if (res != AACENC_OK)
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
if (!(conf->object_type & (AAC_OBJECT_TYPE_MPEG2_AAC_LC |
|
||||||
|
AAC_OBJECT_TYPE_MPEG4_AAC_LC))) {
|
||||||
|
res = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = aacEncoder_SetParam(this->aacenc, AACENC_AOT, AOT_AAC_LC);
|
||||||
|
if (res != AACENC_OK)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
res = aacEncoder_SetParam(this->aacenc, AACENC_SAMPLERATE, this->rate);
|
res = aacEncoder_SetParam(this->aacenc, AACENC_SAMPLERATE, this->rate);
|
||||||
if (res != AACENC_OK)
|
if (res != AACENC_OK)
|
||||||
|
|
@ -632,7 +668,32 @@ const struct media_codec a2dp_codec_aac = {
|
||||||
.set_log = codec_set_log,
|
.set_log = codec_set_log,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct media_codec a2dp_codec_aac_eld = {
|
||||||
|
.id = SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD,
|
||||||
|
.codec_id = A2DP_CODEC_MPEG24,
|
||||||
|
.name = "aac_eld",
|
||||||
|
.description = "AAC-ELD",
|
||||||
|
.fill_caps = codec_fill_caps,
|
||||||
|
.select_config = codec_select_config,
|
||||||
|
.enum_config = codec_enum_config,
|
||||||
|
.validate_config = codec_validate_config,
|
||||||
|
.init_props = codec_init_props,
|
||||||
|
.clear_props = codec_clear_props,
|
||||||
|
.init = codec_init,
|
||||||
|
.deinit = codec_deinit,
|
||||||
|
.get_block_size = codec_get_block_size,
|
||||||
|
.start_encode = codec_start_encode,
|
||||||
|
.encode = codec_encode,
|
||||||
|
.start_decode = codec_start_decode,
|
||||||
|
.decode = codec_decode,
|
||||||
|
.abr_process = codec_abr_process,
|
||||||
|
.reduce_bitpool = codec_reduce_bitpool,
|
||||||
|
.increase_bitpool = codec_increase_bitpool,
|
||||||
|
.set_log = codec_set_log,
|
||||||
|
};
|
||||||
|
|
||||||
MEDIA_CODEC_EXPORT_DEF(
|
MEDIA_CODEC_EXPORT_DEF(
|
||||||
"aac",
|
"aac",
|
||||||
&a2dp_codec_aac
|
&a2dp_codec_aac,
|
||||||
|
&a2dp_codec_aac_eld
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@
|
||||||
#define AAC_OBJECT_TYPE_MPEG4_AAC_LC 0x40
|
#define AAC_OBJECT_TYPE_MPEG4_AAC_LC 0x40
|
||||||
#define AAC_OBJECT_TYPE_MPEG4_AAC_LTP 0x20
|
#define AAC_OBJECT_TYPE_MPEG4_AAC_LTP 0x20
|
||||||
#define AAC_OBJECT_TYPE_MPEG4_AAC_SCA 0x10
|
#define AAC_OBJECT_TYPE_MPEG4_AAC_SCA 0x10
|
||||||
|
#define AAC_OBJECT_TYPE_MPEG4_AAC_ELD 0x02
|
||||||
|
|
||||||
#define AAC_SAMPLING_FREQ_8000 0x0800
|
#define AAC_SAMPLING_FREQ_8000 0x0800
|
||||||
#define AAC_SAMPLING_FREQ_11025 0x0400
|
#define AAC_SAMPLING_FREQ_11025 0x0400
|
||||||
|
|
|
||||||
|
|
@ -3167,6 +3167,7 @@ int64_t spa_bt_transport_get_delay_nsec(struct spa_bt_transport *t)
|
||||||
return 150 * SPA_NSEC_PER_MSEC;
|
return 150 * SPA_NSEC_PER_MSEC;
|
||||||
case SPA_BLUETOOTH_AUDIO_CODEC_LDAC:
|
case SPA_BLUETOOTH_AUDIO_CODEC_LDAC:
|
||||||
return 175 * SPA_NSEC_PER_MSEC;
|
return 175 * SPA_NSEC_PER_MSEC;
|
||||||
|
case SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD:
|
||||||
case SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL:
|
case SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL:
|
||||||
case SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX:
|
case SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX:
|
||||||
case SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM:
|
case SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM:
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ static int codec_order(const struct media_codec *c)
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_LDAC,
|
SPA_BLUETOOTH_AUDIO_CODEC_LDAC,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
|
SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_APTX,
|
SPA_BLUETOOTH_AUDIO_CODEC_APTX,
|
||||||
|
SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_AAC,
|
SPA_BLUETOOTH_AUDIO_CODEC_AAC,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR,
|
SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR,
|
||||||
SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
|
SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue