faad_plugin.c 11.8 KB
Newer Older
1 2 3 4
/*
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 * http://www.musicpd.org
 *
5 6 7 8 9 10 11 12 13
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 19
 */

20
#include "../decoder_api.h"
21
#include "decoder_buffer.h"
22
#include "config.h"
23 24 25

#define AAC_MAX_CHANNELS	6

26
#include <assert.h>
27
#include <unistd.h>
28
#include <faad.h>
29 30 31
#include <glib.h>

#undef G_LOG_DOMAIN
32
#define G_LOG_DOMAIN "faad"
33

Max Kellermann's avatar
Max Kellermann committed
34
static const unsigned adts_sample_rates[] =
Avuton Olrich's avatar
Avuton Olrich committed
35 36 37
    { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
	16000, 12000, 11025, 8000, 7350, 0, 0, 0
};
38

39 40 41 42
/**
 * Check whether the buffer head is an AAC frame, and return the frame
 * length.  Returns 0 if it is not a frame.
 */
Max Kellermann's avatar
Max Kellermann committed
43
static size_t
44
adts_check_frame(const unsigned char *data)
45 46
{
	/* check syncword */
47
	if (!((data[0] == 0xFF) && ((data[1] & 0xF6) == 0xF0)))
48 49
		return 0;

50 51 52
	return (((unsigned int)data[3] & 0x3) << 11) |
		(((unsigned int)data[4]) << 3) |
		(data[5] >> 5);
53 54
}

Max Kellermann's avatar
Max Kellermann committed
55 56 57 58
/**
 * Find the next AAC frame in the buffer.  Returns 0 if no frame is
 * found or if not enough data is available.
 */
Max Kellermann's avatar
Max Kellermann committed
59
static size_t
60
adts_find_frame(struct decoder_buffer *buffer)
Max Kellermann's avatar
Max Kellermann committed
61
{
62 63 64
	const unsigned char *data, *p;
	size_t length, frame_length;
	bool ret;
Max Kellermann's avatar
Max Kellermann committed
65

66 67 68 69 70 71 72 73
	while (true) {
		data = decoder_buffer_read(buffer, &length);
		if (data == NULL || length < 8) {
			/* not enough data yet */
			ret = decoder_buffer_fill(buffer);
			if (!ret)
				/* failed */
				return 0;
74

75 76
			continue;
		}
Max Kellermann's avatar
Max Kellermann committed
77

78 79 80 81 82 83 84 85 86 87 88 89 90
		/* find the 0xff marker */
		p = memchr(data, 0xff, length);
		if (p == NULL) {
			/* no marker - discard the buffer */
			decoder_buffer_consume(buffer, length);
			continue;
		}

		if (p > data) {
			/* discard data before 0xff */
			decoder_buffer_consume(buffer, p - data);
			continue;
		}
Max Kellermann's avatar
Max Kellermann committed
91 92

		/* is it a frame? */
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
		frame_length = adts_check_frame(data);
		if (frame_length == 0) {
			/* it's just some random 0xff byte; discard it
			   and continue searching */
			decoder_buffer_consume(buffer, 1);
			continue;
		}

		if (length < frame_length) {
			/* available buffer size is smaller than the
			   frame will be - attempt to read more
			   data */
			ret = decoder_buffer_fill(buffer);
			if (!ret) {
				/* not enough data; discard this frame
				   to prevent a possible buffer
				   overflow */
				data = decoder_buffer_read(buffer, &length);
				if (data != NULL)
					decoder_buffer_consume(buffer, length);
			}

			continue;
		}
Max Kellermann's avatar
Max Kellermann committed
117

118 119 120
		/* found a full frame! */
		return frame_length;
	}
Max Kellermann's avatar
Max Kellermann committed
121 122
}

123
static float
124
adts_song_duration(struct decoder_buffer *buffer)
Avuton Olrich's avatar
Avuton Olrich committed
125
{
Max Kellermann's avatar
Max Kellermann committed
126
	unsigned int frames, frame_length;
127
	unsigned sample_rate = 0;
Max Kellermann's avatar
Max Kellermann committed
128
	float frames_per_second;
129 130

	/* Read all frames to ensure correct time and bitrate */
Avuton Olrich's avatar
Avuton Olrich committed
131
	for (frames = 0;; frames++) {
132 133 134
		frame_length = adts_find_frame(buffer);
		if (frame_length == 0)
			break;
135 136


137 138 139 140 141 142 143 144 145 146 147 148
		if (frames == 0) {
			const unsigned char *data;
			size_t buffer_length;

			data = decoder_buffer_read(buffer, &buffer_length);
			assert(data != NULL);
			assert(frame_length <= buffer_length);

			sample_rate = adts_sample_rates[(data[2] & 0x3c) >> 2];
		}

		decoder_buffer_consume(buffer, frame_length);
149 150
	}

Max Kellermann's avatar
Max Kellermann committed
151
	frames_per_second = (float)sample_rate / 1024.0;
152 153 154 155
	if (frames_per_second <= 0)
		return -1;

	return (float)frames / frames_per_second;
156 157
}

158
static float
159
faad_song_duration(struct decoder_buffer *buffer, struct input_stream *is)
160 161 162
{
	size_t fileread;
	size_t tagsize;
163 164
	const unsigned char *data;
	size_t length;
165

166
	fileread = is->size >= 0 ? is->size : 0;
167

168 169 170 171
	decoder_buffer_fill(buffer);
	data = decoder_buffer_read(buffer, &length);
	if (data == NULL)
		return -1;
172 173

	tagsize = 0;
174
	if (length >= 10 && !memcmp(data, "ID3", 3)) {
175 176
		/* skip the ID3 tag */

177 178
		tagsize = (data[6] << 21) | (data[7] << 14) |
		    (data[8] << 7) | (data[9] << 0);
179

Avuton Olrich's avatar
Avuton Olrich committed
180
		tagsize += 10;
181 182 183 184 185 186

		decoder_buffer_consume(buffer, tagsize);
		decoder_buffer_fill(buffer);
		data = decoder_buffer_read(buffer, &length);
		if (data == NULL)
			return -1;
187 188
	}

189 190
	if (is->seekable && length >= 2 &&
	    data[0] == 0xFF && ((data[1] & 0xF6) == 0xF0)) {
191
		/* obtain the duration from the ADTS header */
192
		float song_length = adts_song_duration(buffer);
193

194
		input_stream_seek(is, tagsize, SEEK_SET);
195

196 197 198 199
		data = decoder_buffer_read(buffer, &length);
		if (data != NULL)
			decoder_buffer_consume(buffer, length);
		decoder_buffer_fill(buffer);
200

201 202
		return song_length;
	} else if (length >= 5 && memcmp(data, "ADIF", 4) == 0) {
203
		/* obtain the duration from the ADIF header */
Max Kellermann's avatar
Max Kellermann committed
204
		unsigned bit_rate;
205
		size_t skip_size = (data[4] & 0x80) ? 9 : 0;
206

207
		if (8 + skip_size > length)
208 209
			/* not enough data yet; skip parsing this
			   header */
210
			return -1;
211

212 213 214 215
		bit_rate = ((data[4 + skip_size] & 0x0F) << 19) |
			(data[5 + skip_size] << 11) |
			(data[6 + skip_size] << 3) |
			(data[7 + skip_size] & 0xE0);
Max Kellermann's avatar
Max Kellermann committed
216 217

		if (fileread != 0 && bit_rate != 0)
218
			return fileread * 8.0 / bit_rate;
219
		else
220 221 222
			return fileread;
	} else
		return -1;
223 224
}

225 226 227 228 229
/**
 * Wrapper for faacDecInit() which works around some API
 * inconsistencies in libfaad.
 */
static bool
230
faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer,
231
		  struct audio_format *audio_format)
232
{
233 234 235 236 237 238
	union {
		/* deconst hack for libfaad */
		const void *in;
		void *out;
	} u;
	size_t length;
239
	int32_t nbytes;
240 241
	uint32_t sample_rate;
	uint8_t channels;
242 243 244 245
#ifdef HAVE_FAAD_LONG
	/* neaacdec.h declares all arguments as "unsigned long", but
	   internally expects uint32_t pointers.  To avoid gcc
	   warnings, use this workaround. */
246
	unsigned long *sample_rate_r = (unsigned long *)(void *)&sample_rate;
247
#else
248
	uint32_t *sample_rate_r = &sample_rate;
249 250
#endif

251 252 253 254 255
	u.in = decoder_buffer_read(buffer, &length);
	if (u.in == NULL)
		return false;

	nbytes = faacDecInit(decoder, u.out,
256
#ifdef HAVE_FAAD_BUFLEN_FUNCS
257
			     length,
258
#endif
259
			     sample_rate_r, &channels);
260 261 262
	if (nbytes < 0)
		return false;

263
	decoder_buffer_consume(buffer, nbytes);
264 265 266 267 268 269 270

	*audio_format = (struct audio_format){
		.bits = 16,
		.channels = channels,
		.sample_rate = sample_rate,
	};

271 272 273 274 275 276 277 278
	return true;
}

/**
 * Wrapper for faacDecDecode() which works around some API
 * inconsistencies in libfaad.
 */
static const void *
279
faad_decoder_decode(faacDecHandle decoder, struct decoder_buffer *buffer,
280
		    faacDecFrameInfo *frame_info)
281
{
282 283 284 285 286 287
	union {
		/* deconst hack for libfaad */
		const void *in;
		void *out;
	} u;
	size_t length;
288 289
	void *result;

290 291
	u.in = decoder_buffer_read(buffer, &length);
	if (u.in == NULL)
292
		return NULL;
293

294
	result = faacDecDecode(decoder, frame_info,
295
			       u.out
296
#ifdef HAVE_FAAD_BUFLEN_FUNCS
297
			       , length
298 299 300 301 302 303
#endif
			       );

	return result;
}

304 305 306 307 308
/**
 * Get a song file's total playing time in seconds, as a float.
 * Returns 0 if the duration is unknown, and a negative value if the
 * file is invalid.
 */
Max Kellermann's avatar
Max Kellermann committed
309 310
static float
faad_get_file_time_float(const char *file)
Avuton Olrich's avatar
Avuton Olrich committed
311
{
312
	struct decoder_buffer *buffer;
313
	float length;
314 315
	faacDecHandle decoder;
	faacDecConfigurationPtr config;
Max Kellermann's avatar
Max Kellermann committed
316
	struct input_stream is;
317

Max Kellermann's avatar
Max Kellermann committed
318
	if (!input_stream_open(&is, file))
Avuton Olrich's avatar
Avuton Olrich committed
319
		return -1;
320

321 322 323
	buffer = decoder_buffer_new(NULL, &is,
				    FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
	length = faad_song_duration(buffer, &is);
324

Avuton Olrich's avatar
Avuton Olrich committed
325
	if (length < 0) {
326
		bool ret;
327
		struct audio_format audio_format;
328

329 330 331 332
		decoder = faacDecOpen();

		config = faacDecGetCurrentConfiguration(decoder);
		config->outputFormat = FAAD_FMT_16BIT;
Avuton Olrich's avatar
Avuton Olrich committed
333
		faacDecSetConfiguration(decoder, config);
334

335
		decoder_buffer_fill(buffer);
336

337 338
		ret = faad_decoder_init(decoder, buffer, &audio_format);
		if (ret && audio_format_valid(&audio_format))
Avuton Olrich's avatar
Avuton Olrich committed
339
			length = 0;
340 341 342

		faacDecClose(decoder);
	}
343

344
	decoder_buffer_free(buffer);
Max Kellermann's avatar
Max Kellermann committed
345
	input_stream_close(&is);
346

347 348 349
	return length;
}

350 351 352 353 354
/**
 * Get a song file's total playing time in seconds, as an int.
 * Returns 0 if the duration is unknown, and a negative value if the
 * file is invalid.
 */
Max Kellermann's avatar
Max Kellermann committed
355 356
static int
faad_get_file_time(const char *file)
Avuton Olrich's avatar
Avuton Olrich committed
357
{
358
	int file_time = -1;
359 360
	float length;

Max Kellermann's avatar
Max Kellermann committed
361
	if ((length = faad_get_file_time_float(file)) >= 0)
362
		file_time = length + 0.5;
363

364
	return file_time;
365 366
}

367
static void
368
faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
369 370
{
	float file_time;
Max Kellermann's avatar
Max Kellermann committed
371
	float total_time = 0;
372
	faacDecHandle decoder;
373
	struct audio_format audio_format;
374
	faacDecConfigurationPtr config;
375
	bool ret;
Max Kellermann's avatar
Max Kellermann committed
376
	uint16_t bit_rate = 0;
377
	struct decoder_buffer *buffer;
378
	enum decoder_command cmd;
379

380 381 382
	buffer = decoder_buffer_new(mpd_decoder, is,
				    FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
	total_time = faad_song_duration(buffer, is);
383

384 385
	/* create the libfaad decoder */

386 387 388 389 390 391 392 393 394 395 396 397
	decoder = faacDecOpen();

	config = faacDecGetCurrentConfiguration(decoder);
	config->outputFormat = FAAD_FMT_16BIT;
#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX
	config->downMatrix = 1;
#endif
#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR
	config->dontUpSampleImplicitSBR = 0;
#endif
	faacDecSetConfiguration(decoder, config);

398 399
	while (!decoder_buffer_is_full(buffer) &&
	       !input_stream_eof(is) &&
400
	       decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) {
401 402
		adts_find_frame(buffer);
		decoder_buffer_fill(buffer);
403 404
	}

405 406
	/* initialize it */

407
	ret = faad_decoder_init(decoder, buffer, &audio_format);
408
	if (!ret) {
409
		g_warning("Error not a AAC stream.\n");
410
		faacDecClose(decoder);
411
		return;
412 413
	}

414 415 416 417 418 419
	if (!audio_format_valid(&audio_format)) {
		g_warning("invalid audio format\n");
		faacDecClose(decoder);
		return;
	}

420 421
	/* initialize the MPD core */

422 423
	decoder_initialized(mpd_decoder, &audio_format, false, total_time);

424 425
	/* the decoder loop */

426 427
	file_time = 0.0;

428
	do {
429
		size_t frame_size;
Max Kellermann's avatar
Max Kellermann committed
430 431
		const void *decoded;
		faacDecFrameInfo frame_info;
432 433 434 435

		/* find the next frame */

		frame_size = adts_find_frame(buffer);
436
		if (frame_size == 0)
437
			/* end of file */
438 439
			break;

440 441
		/* decode it */

442
		decoded = faad_decoder_decode(decoder, buffer, &frame_info);
443

Max Kellermann's avatar
Max Kellermann committed
444
		if (frame_info.error > 0) {
445
			g_warning("error decoding AAC stream: %s\n",
Max Kellermann's avatar
Max Kellermann committed
446
				  faacDecGetErrorMessage(frame_info.error));
447 448 449
			break;
		}

450
		if (frame_info.channels != audio_format.channels) {
451
			g_warning("channel count changed from %u to %u",
452
				  audio_format.channels, frame_info.channels);
453 454
			break;
		}
455

456
#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE
457
		if (frame_info.samplerate != audio_format.sample_rate) {
458
			g_warning("sample rate changed from %u to %lu",
459
				  audio_format.sample_rate,
460 461
				  (unsigned long)frame_info.samplerate);
			break;
462
		}
463
#endif
464

465
		decoder_buffer_consume(buffer, frame_info.bytesconsumed);
466

467 468
		/* update bit rate and position */

Max Kellermann's avatar
Max Kellermann committed
469
		if (frame_info.samples > 0) {
Max Kellermann's avatar
Max Kellermann committed
470
			bit_rate = frame_info.bytesconsumed * 8.0 *
471
			    frame_info.channels * audio_format.sample_rate /
Max Kellermann's avatar
Max Kellermann committed
472
			    frame_info.samples / 1000 + 0.5;
473
			file_time +=
Max Kellermann's avatar
Max Kellermann committed
474
			    (float)(frame_info.samples) / frame_info.channels /
475
			    audio_format.sample_rate;
476 477
		}

478 479
		/* send PCM samples to MPD */

Max Kellermann's avatar
Max Kellermann committed
480
		cmd = decoder_data(mpd_decoder, is, decoded,
Max Kellermann's avatar
Max Kellermann committed
481
				   (size_t)frame_info.samples * 2, file_time,
Max Kellermann's avatar
Max Kellermann committed
482
				   bit_rate, NULL);
483
	} while (cmd != DECODE_COMMAND_STOP);
484

485 486
	/* cleanup */

487 488 489
	faacDecClose(decoder);
}

Max Kellermann's avatar
Max Kellermann committed
490 491
static struct tag *
faad_tag_dup(const char *file)
Avuton Olrich's avatar
Avuton Olrich committed
492
{
Max Kellermann's avatar
Max Kellermann committed
493
	int file_time = faad_get_file_time(file);
494
	struct tag *tag;
Warren Dukes's avatar
Warren Dukes committed
495

496
	if (file_time < 0) {
Max Kellermann's avatar
Max Kellermann committed
497
		g_debug("Failed to get total song time from: %s", file);
498
		return NULL;
499
	}
Warren Dukes's avatar
Warren Dukes committed
500

501 502 503
	tag = tag_new();
	tag->time = file_time;
	return tag;
Warren Dukes's avatar
Warren Dukes committed
504 505
}

Max Kellermann's avatar
Max Kellermann committed
506 507 508 509
static const char *const faad_suffixes[] = { "aac", NULL };
static const char *const faad_mime_types[] = {
	"audio/aac", "audio/aacp", NULL
};
Warren Dukes's avatar
Warren Dukes committed
510

511 512
const struct decoder_plugin faad_decoder_plugin = {
	.name = "faad",
513
	.stream_decode = faad_stream_decode,
Max Kellermann's avatar
Max Kellermann committed
514 515 516
	.tag_dup = faad_tag_dup,
	.suffixes = faad_suffixes,
	.mime_types = faad_mime_types,
Warren Dukes's avatar
Warren Dukes committed
517
};