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