decoder_api.c 9.2 KB
Newer Older
1 2 3
/*
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 * http://www.musicpd.org
4 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_internal.h"
22
#include "decoder_control.h"
23
#include "player_control.h"
24
#include "audio.h"
25
#include "song.h"
26
#include "buffer.h"
27

Max Kellermann's avatar
Max Kellermann committed
28
#include "normalize.h"
29
#include "pipe.h"
30
#include "chunk.h"
31

32
#include <glib.h>
33

34 35 36
#include <assert.h>
#include <stdlib.h>

37 38 39
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "decoder"

40 41 42 43
void
decoder_initialized(struct decoder *decoder,
		    const struct audio_format *audio_format,
		    bool seekable, float total_time)
44
{
45 46 47 48
	struct decoder_control *dc = decoder->dc;

	assert(dc->state == DECODE_STATE_START);
	assert(dc->pipe != NULL);
49
	assert(decoder != NULL);
50 51
	assert(decoder->stream_tag == NULL);
	assert(decoder->decoder_tag == NULL);
52
	assert(!decoder->seeking);
53
	assert(audio_format != NULL);
54
	assert(audio_format_defined(audio_format));
55
	assert(audio_format_valid(audio_format));
56

57 58
	dc->in_audio_format = *audio_format;
	getOutputAudioFormat(audio_format, &dc->out_audio_format);
59

60 61
	dc->seekable = seekable;
	dc->total_time = total_time;
62

63 64 65
	decoder_lock(dc);
	dc->state = DECODE_STATE_DECODE;
	decoder_unlock(dc);
66

67
	player_lock_signal();
68 69

	g_debug("audio_format=%u:%u:%u, seekable=%s",
70 71 72
		dc->in_audio_format.sample_rate,
		dc->in_audio_format.bits,
		dc->in_audio_format.channels,
73 74
		seekable ? "true" : "false");

75 76
	if (!audio_format_equals(&dc->in_audio_format,
				 &dc->out_audio_format))
77
		g_debug("converting to %u:%u:%u",
78 79 80
			dc->out_audio_format.sample_rate,
			dc->out_audio_format.bits,
			dc->out_audio_format.channels);
81
}
Max Kellermann's avatar
Max Kellermann committed
82

83
char *decoder_get_uri(G_GNUC_UNUSED struct decoder *decoder)
Max Kellermann's avatar
Max Kellermann committed
84
{
85 86 87
	const struct decoder_control *dc = decoder->dc;

	assert(dc->pipe != NULL);
88

89
	return song_get_uri(dc->song);
Max Kellermann's avatar
Max Kellermann committed
90 91
}

92
enum decoder_command decoder_get_command(G_GNUC_UNUSED struct decoder * decoder)
93
{
94 95 96
	const struct decoder_control *dc = decoder->dc;

	assert(dc->pipe != NULL);
97

98
	return dc->command;
99 100
}

101
void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder)
102
{
103
	struct decoder_control *dc = decoder->dc;
104

105
	decoder_lock(dc);
106

107 108 109 110 111 112
	assert(dc->command != DECODE_COMMAND_NONE);
	assert(dc->command != DECODE_COMMAND_SEEK ||
	       dc->seek_error || decoder->seeking);
	assert(dc->pipe != NULL);

	if (dc->command == DECODE_COMMAND_SEEK) {
113
		/* delete frames from the old song position */
114 115

		if (decoder->chunk != NULL) {
116
			music_buffer_return(dc->buffer, decoder->chunk);
117 118 119
			decoder->chunk = NULL;
		}

120
		music_pipe_clear(dc->pipe, dc->buffer);
121
	}
122

123 124
	dc->command = DECODE_COMMAND_NONE;
	decoder_unlock(dc);
125

126
	player_lock_signal();
127 128
}

129
double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
130
{
131 132 133 134
	const struct decoder_control *dc = decoder->dc;

	assert(dc->command == DECODE_COMMAND_SEEK);
	assert(dc->pipe != NULL);
135

136
	decoder->seeking = true;
137

138
	return dc->seek_where;
139 140 141 142
}

void decoder_seek_error(struct decoder * decoder)
{
143 144 145 146
	struct decoder_control *dc = decoder->dc;

	assert(dc->command == DECODE_COMMAND_SEEK);
	assert(dc->pipe != NULL);
147

148
	dc->seek_error = true;
149 150 151
	decoder_command_finished(decoder);
}

Max Kellermann's avatar
Max Kellermann committed
152
size_t decoder_read(struct decoder *decoder,
153
		    struct input_stream *is,
Max Kellermann's avatar
Max Kellermann committed
154 155
		    void *buffer, size_t length)
{
156 157
	const struct decoder_control *dc =
		decoder != NULL ? decoder->dc : NULL;
Max Kellermann's avatar
Max Kellermann committed
158 159
	size_t nbytes;

160
	assert(decoder == NULL ||
161 162
	       dc->state == DECODE_STATE_START ||
	       dc->state == DECODE_STATE_DECODE);
163
	assert(is != NULL);
Max Kellermann's avatar
Max Kellermann committed
164 165
	assert(buffer != NULL);

166 167 168
	if (length == 0)
		return 0;

169
	while (true) {
Max Kellermann's avatar
Max Kellermann committed
170
		/* XXX don't allow decoder==NULL */
171
		if (decoder != NULL &&
172 173 174
		    /* ignore the SEEK command during initialization,
		       the plugin should handle that after it has
		       initialized successfully */
175 176 177
		    (dc->command != DECODE_COMMAND_SEEK ||
		     (dc->state != DECODE_STATE_START && !decoder->seeking)) &&
		    dc->command != DECODE_COMMAND_NONE)
Max Kellermann's avatar
Max Kellermann committed
178 179
			return 0;

180 181
		nbytes = input_stream_read(is, buffer, length);
		if (nbytes > 0 || input_stream_eof(is))
Max Kellermann's avatar
Max Kellermann committed
182 183 184 185
			return nbytes;

		/* sleep for a fraction of a second! */
		/* XXX don't sleep, wait for an event instead */
186
		g_usleep(10000);
Max Kellermann's avatar
Max Kellermann committed
187 188 189
	}
}

Max Kellermann's avatar
Max Kellermann committed
190
/**
191 192
 * Sends a #tag as-is to the music pipe.  Flushes the current chunk
 * (decoder.chunk) if there is one.
Max Kellermann's avatar
Max Kellermann committed
193
 */
194
static enum decoder_command
195 196
do_send_tag(struct decoder *decoder, struct input_stream *is,
	    const struct tag *tag)
Max Kellermann's avatar
Max Kellermann committed
197
{
198
	struct music_chunk *chunk;
Max Kellermann's avatar
Max Kellermann committed
199

200 201 202
	if (decoder->chunk != NULL) {
		/* there is a partial chunk - flush it, we want the
		   tag in a new chunk */
203
		decoder_flush_chunk(decoder);
204
		player_lock_signal();
205 206
	}

207 208
	assert(decoder->chunk == NULL);

209 210
	chunk = decoder_get_chunk(decoder, is);
	if (chunk == NULL) {
211 212
		assert(decoder->dc->command != DECODE_COMMAND_NONE);
		return decoder->dc->command;
213 214
	}

215
	chunk->tag = tag_dup(tag);
216 217 218
	return DECODE_COMMAND_NONE;
}

219 220 221 222 223
static bool
update_stream_tag(struct decoder *decoder, struct input_stream *is)
{
	struct tag *tag;

224 225 226 227 228 229 230 231 232 233 234 235
	tag = is != NULL
		? input_stream_tag(is)
		: NULL;
	if (tag == NULL) {
		tag = decoder->song_tag;
		if (tag == NULL)
			return false;

		/* no stream tag present - submit the song tag
		   instead */
		decoder->song_tag = NULL;
	}
236 237 238 239 240 241 242 243

	if (decoder->stream_tag != NULL)
		tag_free(decoder->stream_tag);

	decoder->stream_tag = tag;
	return true;
}

244
enum decoder_command
245
decoder_data(struct decoder *decoder,
246
	     struct input_stream *is,
247
	     const void *_data, size_t length,
248
	     float data_time, uint16_t bitRate,
249
	     struct replay_gain_info *replay_gain_info)
Max Kellermann's avatar
Max Kellermann committed
250
{
251
	struct decoder_control *dc = decoder->dc;
252
	const char *data = _data;
253
	GError *error = NULL;
254
	enum decoder_command cmd;
Max Kellermann's avatar
Max Kellermann committed
255

256 257 258
	assert(dc->state == DECODE_STATE_DECODE);
	assert(dc->pipe != NULL);
	assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
259

260 261 262
	decoder_lock(dc);
	cmd = dc->command;
	decoder_unlock(dc);
263 264

	if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
265
	    length == 0)
266
		return cmd;
267

268 269 270 271 272 273 274 275 276
	/* send stream tags */

	if (update_stream_tag(decoder, is)) {
		if (decoder->decoder_tag != NULL) {
			/* merge with tag from decoder plugin */
			struct tag *tag;

			tag = tag_merge(decoder->stream_tag,
					decoder->decoder_tag);
277
			cmd = do_send_tag(decoder, is, tag);
278 279 280
			tag_free(tag);
		} else
			/* send only the stream tag */
281
			cmd = do_send_tag(decoder, is, decoder->stream_tag);
282 283 284

		if (cmd != DECODE_COMMAND_NONE)
			return cmd;
285 286
	}

287
	if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
288
		data = pcm_convert(&decoder->conv_state,
289 290
				   &dc->in_audio_format, data, length,
				   &dc->out_audio_format, &length,
291 292 293 294 295 296 297 298
				   &error);
		if (data == NULL) {
			/* the PCM conversion has failed - stop
			   playback, since we have no better way to
			   bail out */
			g_warning("%s", error->message);
			return DECODE_COMMAND_STOP;
		}
Max Kellermann's avatar
Max Kellermann committed
299 300
	}

301
	while (length > 0) {
302 303
		struct music_chunk *chunk;
		char *dest;
304
		size_t nbytes;
305 306
		bool full;

307 308
		chunk = decoder_get_chunk(decoder, is);
		if (chunk == NULL) {
309 310
			assert(dc->command != DECODE_COMMAND_NONE);
			return dc->command;
311 312
		}

313
		dest = music_chunk_write(chunk, &dc->out_audio_format,
314
					 data_time, bitRate, &nbytes);
315
		if (dest == NULL) {
316
			/* the chunk is full, flush it */
317
			decoder_flush_chunk(decoder);
318
			player_lock_signal();
319
			continue;
Max Kellermann's avatar
Max Kellermann committed
320
		}
321 322 323 324 325 326 327 328 329 330 331 332

		assert(nbytes > 0);

		if (nbytes > length)
			nbytes = length;

		/* copy the buffer */

		memcpy(dest, data, nbytes);

		/* apply replay gain or normalization */

333
		if (replay_gain_mode != REPLAY_GAIN_OFF)
334
			replay_gain_apply(replay_gain_info, dest, nbytes,
335
					  &dc->out_audio_format);
336
		else if (normalizationEnabled)
337
			normalizeData(dest, nbytes, &dc->out_audio_format);
338 339 340

		/* expand the music pipe chunk */

341
		full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
342 343
		if (full) {
			/* the chunk is full, flush it */
344
			decoder_flush_chunk(decoder);
345
			player_lock_signal();
346
		}
347 348 349

		data += nbytes;
		length -= nbytes;
Max Kellermann's avatar
Max Kellermann committed
350 351
	}

352
	return DECODE_COMMAND_NONE;
Max Kellermann's avatar
Max Kellermann committed
353
}
354 355

enum decoder_command
356
decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
357 358
	    const struct tag *tag)
{
359
	const struct decoder_control *dc = decoder->dc;
360
	enum decoder_command cmd;
361

362 363
	assert(dc->state == DECODE_STATE_DECODE);
	assert(dc->pipe != NULL);
364 365 366 367 368 369 370 371 372
	assert(tag != NULL);

	/* save the tag */

	if (decoder->decoder_tag != NULL)
		tag_free(decoder->decoder_tag);
	decoder->decoder_tag = tag_dup(tag);

	/* check for a new stream tag */
373

374
	update_stream_tag(decoder, is);
375

376
	/* send tag to music pipe */
377

378 379 380
	if (decoder->stream_tag != NULL) {
		/* merge with tag from input stream */
		struct tag *merged;
381

382
		merged = tag_merge(decoder->stream_tag, decoder->decoder_tag);
383
		cmd = do_send_tag(decoder, is, merged);
384 385 386
		tag_free(merged);
	} else
		/* send only the decoder tag */
387
		cmd = do_send_tag(decoder, is, tag);
388

389
	return cmd;
390
}