mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: Add AAC decoder
This commit is contained in:
		
							parent
							
								
									6d4d77802a
								
							
						
					
					
						commit
						76adcfaabe
					
				
					 1 changed files with 95 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -31,10 +31,16 @@
 | 
			
		|||
#include <spa/utils/dict.h>
 | 
			
		||||
 | 
			
		||||
#include <fdk-aac/aacenc_lib.h>
 | 
			
		||||
#include <fdk-aac/aacdecoder_lib.h>
 | 
			
		||||
 | 
			
		||||
#include "rtp.h"
 | 
			
		||||
#include "a2dp-codecs.h"
 | 
			
		||||
 | 
			
		||||
static struct spa_log *log;
 | 
			
		||||
static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.codecs.aac");
 | 
			
		||||
#undef SPA_LOG_TOPIC_DEFAULT
 | 
			
		||||
#define SPA_LOG_TOPIC_DEFAULT &log_topic
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_AAC_BITRATE	320000
 | 
			
		||||
#define MIN_AAC_BITRATE		64000
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +50,7 @@ struct props {
 | 
			
		|||
 | 
			
		||||
struct impl {
 | 
			
		||||
	HANDLE_AACENCODER aacenc;
 | 
			
		||||
	HANDLE_AACDECODER aacdec;
 | 
			
		||||
 | 
			
		||||
	struct rtp_header *header;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -412,11 +419,39 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
 | 
			
		|||
 | 
			
		||||
	this->codesize = enc_info.frameLength * this->channels * this->samplesize;
 | 
			
		||||
 | 
			
		||||
	this->aacdec = aacDecoder_Open(TT_MP4_LATM_MCP1, 1);
 | 
			
		||||
	if (!this->aacdec) {
 | 
			
		||||
		res = -EINVAL;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef AACDECODER_LIB_VL0
 | 
			
		||||
	res = aacDecoder_SetParam(this->aacdec, AAC_PCM_MIN_OUTPUT_CHANNELS, this->channels);
 | 
			
		||||
	if (res != AAC_DEC_OK) {
 | 
			
		||||
		spa_log_debug(log, "Couldn't set min output channels: 0x%04X", res);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res = aacDecoder_SetParam(this->aacdec, AAC_PCM_MAX_OUTPUT_CHANNELS, this->channels);
 | 
			
		||||
	if (res != AAC_DEC_OK) {
 | 
			
		||||
		spa_log_debug(log, "Couldn't set max output channels: 0x%04X", res);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	res = aacDecoder_SetParam(this->aacdec, AAC_PCM_OUTPUT_CHANNELS, this->channels);
 | 
			
		||||
	if (res != AAC_DEC_OK) {
 | 
			
		||||
		spa_log_debug(log, "Couldn't set output channels: 0x%04X", res);
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return this;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (this && this->aacenc)
 | 
			
		||||
		aacEncClose(&this->aacenc);
 | 
			
		||||
	if (this && this->aacdec)
 | 
			
		||||
		aacDecoder_Close(this->aacdec);
 | 
			
		||||
	free(this);
 | 
			
		||||
	errno = -res;
 | 
			
		||||
	return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +462,8 @@ static void codec_deinit(void *data)
 | 
			
		|||
	struct impl *this = data;
 | 
			
		||||
	if (this->aacenc)
 | 
			
		||||
		aacEncClose(&this->aacenc);
 | 
			
		||||
	if (this->aacdec)
 | 
			
		||||
		aacDecoder_Close(this->aacdec);
 | 
			
		||||
	free(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -502,6 +539,55 @@ static int codec_encode(void *data,
 | 
			
		|||
	return out_args.numInSamples * this->samplesize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int codec_start_decode (void *data,
 | 
			
		||||
		const void *src, size_t src_size, uint16_t *seqnum, uint32_t *timestamp)
 | 
			
		||||
{
 | 
			
		||||
	const struct rtp_header *header = src;
 | 
			
		||||
	size_t header_size = sizeof(struct rtp_header);
 | 
			
		||||
 | 
			
		||||
	spa_return_val_if_fail (src_size > header_size, -EINVAL);
 | 
			
		||||
 | 
			
		||||
	if (seqnum)
 | 
			
		||||
		*seqnum = ntohs(header->sequence_number);
 | 
			
		||||
	if (timestamp)
 | 
			
		||||
		*timestamp = ntohl(header->timestamp);
 | 
			
		||||
 | 
			
		||||
	return header_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int codec_decode(void *data,
 | 
			
		||||
		const void *src, size_t src_size,
 | 
			
		||||
		void *dst, size_t dst_size,
 | 
			
		||||
		size_t *dst_out)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *this = data;
 | 
			
		||||
	uint data_size = (uint)src_size;
 | 
			
		||||
	uint bytes_valid = data_size;
 | 
			
		||||
	CStreamInfo *aacinf;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	res = aacDecoder_Fill(this->aacdec, (UCHAR **)&src, &data_size, &bytes_valid);
 | 
			
		||||
	if (res != AAC_DEC_OK) {
 | 
			
		||||
		spa_log_debug(log, "AAC buffer fill error: 0x%04X", res);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res = aacDecoder_DecodeFrame(this->aacdec, dst, dst_size, 0);
 | 
			
		||||
	if (res != AAC_DEC_OK) {
 | 
			
		||||
		spa_log_debug(log, "AAC decode frame error: 0x%04X", res);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	aacinf = aacDecoder_GetStreamInfo(this->aacdec);
 | 
			
		||||
	if (!aacinf) {
 | 
			
		||||
		spa_log_debug(log, "AAC get stream info failed");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	*dst_out = aacinf->frameSize * aacinf->numChannels * this->samplesize;
 | 
			
		||||
 | 
			
		||||
	return src_size - bytes_valid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int codec_abr_process (void *data, size_t unsent)
 | 
			
		||||
{
 | 
			
		||||
	return -ENOTSUP;
 | 
			
		||||
| 
						 | 
				
			
			@ -538,6 +624,12 @@ static int codec_increase_bitpool(void *data)
 | 
			
		|||
	return codec_change_bitrate(this, (this->cur_bitrate * 4) / 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void codec_set_log(struct spa_log *global_log)
 | 
			
		||||
{
 | 
			
		||||
	log = global_log;
 | 
			
		||||
	spa_log_topic_init(log, &log_topic);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct a2dp_codec a2dp_codec_aac = {
 | 
			
		||||
	.id = SPA_BLUETOOTH_AUDIO_CODEC_AAC,
 | 
			
		||||
	.codec_id = A2DP_CODEC_MPEG24,
 | 
			
		||||
| 
						 | 
				
			
			@ -554,9 +646,12 @@ const struct a2dp_codec a2dp_codec_aac = {
 | 
			
		|||
	.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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
A2DP_CODEC_EXPORT_DEF(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue