DecoderThread.cxx 13.5 KB
Newer Older
1
/*
2
 * Copyright 2003-2016 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
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.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

20
#include "config.h"
21
#include "DecoderThread.hxx"
22
#include "DecoderControl.hxx"
23
#include "Bridge.hxx"
24 25
#include "DecoderError.hxx"
#include "DecoderPlugin.hxx"
26
#include "DetachedSong.hxx"
27
#include "MusicPipe.hxx"
28
#include "fs/Traits.hxx"
29
#include "fs/AllocatedPath.hxx"
30
#include "DecoderAPI.hxx"
Max Kellermann's avatar
Max Kellermann committed
31
#include "input/InputStream.hxx"
32
#include "input/LocalOpen.hxx"
33
#include "DecoderList.hxx"
34
#include "system/Error.hxx"
35
#include "util/MimeType.hxx"
Max Kellermann's avatar
Max Kellermann committed
36
#include "util/UriUtil.hxx"
37
#include "util/RuntimeError.hxx"
38
#include "util/Domain.hxx"
39
#include "util/ScopeExit.hxx"
40
#include "thread/Name.hxx"
41
#include "tag/ApeReplayGain.hxx"
42
#include "Log.hxx"
Warren Dukes's avatar
Warren Dukes committed
43

44
#include <stdexcept>
45
#include <functional>
46
#include <memory>
47

48
static constexpr Domain decoder_thread_domain("decoder_thread");
49

50
/**
51
 * Opens the input stream with InputStream::Open(), and waits until
52
 * the stream gets ready.
53 54 55
 *
 * Unlock the decoder before calling this function.
 */
56
static InputStreamPtr
57
decoder_input_stream_open(DecoderControl &dc, const char *uri)
58
{
59
	auto is = InputStream::Open(uri, dc.mutex, dc.cond);
60 61 62 63

	/* wait for the input stream to become ready; its metadata
	   will be available then */

64
	const ScopeLock protect(dc.mutex);
65

66
	is->Update();
67 68
	while (!is->IsReady()) {
		if (dc.command == DecoderCommand::STOP)
69
			throw StopDecoder();
70

71
		dc.Wait();
72

73
		is->Update();
74 75
	}

76
	is->Check();
77

78
	return is;
79 80
}

81
static InputStreamPtr
82
decoder_input_stream_open(DecoderControl &dc, Path path)
83
{
84
	auto is = OpenLocalInputStream(path, dc.mutex, dc.cond);
85 86 87 88 89 90

	assert(is->IsReady());

	return is;
}

91 92 93 94 95
/**
 * Decode a stream with the given decoder plugin.
 *
 * Caller holds DecoderControl::mutex.
 */
96
static bool
97
decoder_stream_decode(const DecoderPlugin &plugin,
98
		      DecoderBridge &bridge,
99
		      InputStream &input_stream)
100
{
101
	assert(plugin.stream_decode != nullptr);
102 103
	assert(bridge.stream_tag == nullptr);
	assert(bridge.decoder_tag == nullptr);
104
	assert(input_stream.IsReady());
105
	assert(bridge.dc.state == DecoderState::START);
106

107
	FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name);
108

109
	if (bridge.dc.command == DecoderCommand::STOP)
110
		throw StopDecoder();
111

112
	/* rewind the stream, so each plugin gets a fresh start */
113 114 115 116
	try {
		input_stream.Rewind();
	} catch (const std::runtime_error &) {
	}
117

118
	{
119
		const ScopeUnlock unlock(bridge.dc.mutex);
120

121
		FormatThreadName("decoder:%s", plugin.name);
122

123
		plugin.StreamDecode(bridge, input_stream);
124

125 126
		SetThreadName("decoder");
	}
127

128 129
	assert(bridge.dc.state == DecoderState::START ||
	       bridge.dc.state == DecoderState::DECODE);
130

131
	return bridge.dc.state != DecoderState::START;
132 133
}

134 135 136 137 138
/**
 * Decode a file with the given decoder plugin.
 *
 * Caller holds DecoderControl::mutex.
 */
139
static bool
140
decoder_file_decode(const DecoderPlugin &plugin,
141
		    DecoderBridge &bridge, Path path)
142
{
143
	assert(plugin.file_decode != nullptr);
144 145
	assert(bridge.stream_tag == nullptr);
	assert(bridge.decoder_tag == nullptr);
146 147
	assert(!path.IsNull());
	assert(path.IsAbsolute());
148
	assert(bridge.dc.state == DecoderState::START);
149

150
	FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name);
151

152
	if (bridge.dc.command == DecoderCommand::STOP)
153
		throw StopDecoder();
154

155
	{
156
		const ScopeUnlock unlock(bridge.dc.mutex);
157

158
		FormatThreadName("decoder:%s", plugin.name);
159

160
		plugin.FileDecode(bridge, path);
161

162 163
		SetThreadName("decoder");
	}
164

165 166
	assert(bridge.dc.state == DecoderState::START ||
	       bridge.dc.state == DecoderState::DECODE);
167

168
	return bridge.dc.state != DecoderState::START;
169 170
}

171
gcc_pure
172
static bool
173
decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is)
174
{
175
	assert(plugin.stream_decode != nullptr);
176

177
	const char *mime_type = is.GetMimeType();
178 179
	return mime_type != nullptr &&
		plugin.SupportsMimeType(GetMimeTypeBase(mime_type).c_str());
180
}
181

182 183 184 185 186
gcc_pure
static bool
decoder_check_plugin_suffix(const DecoderPlugin &plugin, const char *suffix)
{
	assert(plugin.stream_decode != nullptr);
187

188
	return suffix != nullptr && plugin.SupportsSuffix(suffix);
189 190
}

191
gcc_pure
192
static bool
193
decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
194
		     const char *suffix)
195
{
196 197 198 199
	return plugin.stream_decode != nullptr &&
		(decoder_check_plugin_mime(plugin, is) ||
		 decoder_check_plugin_suffix(plugin, suffix));
}
200

201
static bool
202
decoder_run_stream_plugin(DecoderBridge &bridge, InputStream &is,
203 204 205 206 207
			  const char *suffix,
			  const DecoderPlugin &plugin,
			  bool &tried_r)
{
	if (!decoder_check_plugin(plugin, is, suffix))
208 209
		return false;

210
	bridge.error = std::exception_ptr();
211

212
	tried_r = true;
213
	return decoder_stream_decode(plugin, bridge, is);
214
}
215

216
static bool
217
decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is,
218 219
			  const char *uri, bool &tried_r)
{
220 221
	UriSuffixBuffer suffix_buffer;
	const char *const suffix = uri_get_suffix(uri, suffix_buffer);
222

223 224
	using namespace std::placeholders;
	const auto f = std::bind(decoder_run_stream_plugin,
225
				 std::ref(bridge), std::ref(is), suffix,
226 227
				 _1, std::ref(tried_r));
	return decoder_plugins_try(f);
228 229 230 231 232 233
}

/**
 * Try decoding a stream, using the fallback plugin.
 */
static bool
234
decoder_run_stream_fallback(DecoderBridge &bridge, InputStream &is)
235
{
236
	const struct DecoderPlugin *plugin;
237

238 239 240
#ifdef HAVE_FFMPEG
	plugin = decoder_plugin_from_name("ffmpeg");
#else
241
	plugin = decoder_plugin_from_name("mad");
242
#endif
243
	return plugin != nullptr && plugin->stream_decode != nullptr &&
244
		decoder_stream_decode(*plugin, bridge, is);
245 246
}

247 248
/**
 * Attempt to load replay gain data, and pass it to
249
 * DecoderClient::SubmitReplayGain().
250 251
 */
static void
252
LoadReplayGain(DecoderClient &client, InputStream &is)
253 254 255
{
	ReplayGainInfo info;
	if (replay_gain_ape_read(is, info))
256
		client.SubmitReplayGain(&info);
257 258
}

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
/**
 * Call LoadReplayGain() unless ReplayGain is disabled.  This saves
 * the I/O overhead when the user is not interested in the feature.
 */
static void
MaybeLoadReplayGain(DecoderBridge &bridge, InputStream &is)
{
	{
		const ScopeLock protect(bridge.dc.mutex);
		if (bridge.dc.replay_gain_mode == ReplayGainMode::OFF)
			/* ReplayGain is disabled */
			return;
	}

	LoadReplayGain(bridge, is);
}

276 277
/**
 * Try decoding a stream.
278
 *
279
 * DecoderControl::mutex is not locked by caller.
280 281
 */
static bool
282
decoder_run_stream(DecoderBridge &bridge, const char *uri)
283
{
284
	DecoderControl &dc = bridge.dc;
285

286 287
	auto input_stream = decoder_input_stream_open(dc, uri);
	assert(input_stream);
288

289
	MaybeLoadReplayGain(bridge, *input_stream);
290

291
	const ScopeLock protect(dc.mutex);
292

293
	bool tried = false;
294
	return dc.command == DecoderCommand::STOP ||
295
		decoder_run_stream_locked(bridge, *input_stream, uri,
296
					  tried) ||
297 298
		/* fallback to mp3: this is needed for bastard streams
		   that don't have a suffix or set the mimeType */
299
		(!tried &&
300
		 decoder_run_stream_fallback(bridge, *input_stream));
301 302
}

303 304 305
/**
 * Decode a file with the given decoder plugin.
 *
306
 * DecoderControl::mutex is not locked by caller.
307
 */
308
static bool
309
TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix,
310
	       InputStream &input_stream,
311
	       const DecoderPlugin &plugin)
312
{
313 314 315
	if (!plugin.SupportsSuffix(suffix))
		return false;

316
	bridge.error = std::exception_ptr();
317

318
	DecoderControl &dc = bridge.dc;
319

320
	if (plugin.file_decode != nullptr) {
321
		const ScopeLock protect(dc.mutex);
322
		return decoder_file_decode(plugin, bridge, path_fs);
323
	} else if (plugin.stream_decode != nullptr) {
324
		const ScopeLock protect(dc.mutex);
325
		return decoder_stream_decode(plugin, bridge, input_stream);
326 327
	} else
		return false;
328 329
}

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
/**
 * Decode a container file with the given decoder plugin.
 *
 * DecoderControl::mutex is not locked by caller.
 */
static bool
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix,
		    const DecoderPlugin &plugin)
{
	if (plugin.container_scan == nullptr ||
	    plugin.file_decode == nullptr ||
	    !plugin.SupportsSuffix(suffix))
		return false;

	bridge.error = nullptr;

	DecoderControl &dc = bridge.dc;
	const ScopeLock protect(dc.mutex);
	return decoder_file_decode(plugin, bridge, path_fs);
}

/**
 * Decode a container file.
 *
 * DecoderControl::mutex is not locked by caller.
 */
static bool
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix)
{
	return decoder_plugins_try([&bridge, path_fs,
				    suffix](const DecoderPlugin &plugin){
					   return TryContainerDecoder(bridge,
								      path_fs,
								      suffix,
								      plugin);
				   });
}

368 369
/**
 * Try decoding a file.
370
 *
371
 * DecoderControl::mutex is not locked by caller.
372 373
 */
static bool
374
decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs)
375
{
376
	const char *suffix = uri_get_suffix(uri_utf8);
377 378
	if (suffix == nullptr)
		return false;
379

380 381 382 383 384 385 386 387 388 389 390 391 392 393
	InputStreamPtr input_stream;

	try {
		input_stream = decoder_input_stream_open(bridge.dc, path_fs);
	} catch (const std::system_error &e) {
		if (IsPathNotFound(e) &&
		    /* ENOTDIR means this may be a path inside a
		       "container" file */
		    TryContainerDecoder(bridge, path_fs, suffix))
			return true;

		throw;
	}

394
	assert(input_stream);
395

396
	MaybeLoadReplayGain(bridge, *input_stream);
397

398
	auto &is = *input_stream;
399
	return decoder_plugins_try([&bridge, path_fs, suffix,
400
				    &is](const DecoderPlugin &plugin){
401
					   return TryDecoderFile(bridge,
402 403
								 path_fs,
								 suffix,
404
								 is,
405 406
								 plugin);
				   });
407 408
}

409 410 411 412 413 414
/**
 * Decode a song.
 *
 * DecoderControl::mutex is not locked.
 */
static bool
415 416
DecoderUnlockedRunUri(DecoderBridge &bridge,
		      const char *real_uri, Path path_fs)
417
try {
418
	return !path_fs.IsNull()
419 420
		? decoder_run_file(bridge, real_uri, path_fs)
		: decoder_run_stream(bridge, real_uri);
421 422
} catch (StopDecoder) {
	return true;
423
} catch (...) {
424 425 426 427 428
	const char *error_uri = real_uri;
	const std::string allocated = uri_remove_auth(error_uri);
	if (!allocated.empty())
		error_uri = allocated.c_str();

429 430
	std::throw_with_nested(FormatRuntimeError("Failed to decode %s",
						  error_uri));
431 432
}

433 434 435 436 437
/**
 * Decode a song addressed by a #DetachedSong.
 *
 * Caller holds DecoderControl::mutex.
 */
438
static void
439
decoder_run_song(DecoderControl &dc,
440
		 const DetachedSong &song, const char *uri, Path path_fs)
Avuton Olrich's avatar
Avuton Olrich committed
441
{
442 443 444 445 446 447 448
	DecoderBridge bridge(dc, dc.start_time.IsPositive(),
			     /* pass the song tag only if it's
				authoritative, i.e. if it's a local
				file - tags on "stream" songs are just
				remembered from the last time we
				played it*/
			     song.IsFile() ? new Tag(song.GetTag()) : nullptr);
449

450
	dc.state = DecoderState::START;
451
	dc.CommandFinishedLocked();
452

453
	bool success;
454 455
	{
		const ScopeUnlock unlock(dc.mutex);
Warren Dukes's avatar
Warren Dukes committed
456

457
		AtScopeExit(&bridge) {
458
			/* flush the last chunk */
459 460
			if (bridge.current_chunk != nullptr)
				bridge.FlushChunk();
461
		};
462

463
		success = DecoderUnlockedRunUri(bridge, uri, path_fs);
464

465
	}
466

467
	if (bridge.error) {
468
		/* copy the Error from struct Decoder to
469
		   DecoderControl */
470
		std::rethrow_exception(bridge.error);
471
	} else if (success)
472
		dc.state = DecoderState::STOP;
473
	else {
474
		const char *error_uri = song.GetURI();
475 476 477
		const std::string allocated = uri_remove_auth(error_uri);
		if (!allocated.empty())
			error_uri = allocated.c_str();
478

479
		throw FormatRuntimeError("Failed to decode %s", error_uri);
480
	}
481

482
	dc.client_cond.signal();
483 484
}

485 486 487 488
/**
 *
 * Caller holds DecoderControl::mutex.
 */
489
static void
490
decoder_run(DecoderControl &dc)
491
try {
492
	dc.ClearError();
493

494
	assert(dc.song != nullptr);
495
	const DetachedSong &song = *dc.song;
496

497
	const char *const uri_utf8 = song.GetRealURI();
498

499 500
	Path path_fs = Path::Null();
	AllocatedPath path_buffer = AllocatedPath::Null();
501
	if (PathTraitsUTF8::IsAbsolute(uri_utf8)) {
502
		path_buffer = AllocatedPath::FromUTF8Throw(uri_utf8);
503
		path_fs = path_buffer;
504 505
	}

506
	decoder_run_song(dc, song, uri_utf8, path_fs);
507 508 509 510
} catch (...) {
	dc.state = DecoderState::ERROR;
	dc.error = std::current_exception();
	dc.client_cond.signal();
511 512
}

513 514
static void
decoder_task(void *arg)
Avuton Olrich's avatar
Avuton Olrich committed
515
{
516
	DecoderControl &dc = *(DecoderControl *)arg;
517

518 519
	SetThreadName("decoder");

520
	const ScopeLock protect(dc.mutex);
521

522
	do {
523 524
		assert(dc.state == DecoderState::STOP ||
		       dc.state == DecoderState::ERROR);
525

526
		switch (dc.command) {
527
		case DecoderCommand::START:
528
			dc.CycleMixRamp();
529 530
			dc.replay_gain_prev_db = dc.replay_gain_db;
			dc.replay_gain_db = 0;
531

532
			decoder_run(dc);
533

534 535 536 537 538 539 540 541
			if (dc.state == DecoderState::ERROR) {
				try {
					std::rethrow_exception(dc.error);
				} catch (const std::exception &e) {
					LogError(e);
				} catch (...) {
				}
			}
542

543
			break;
544

545
		case DecoderCommand::SEEK:
546 547 548 549 550 551 552 553
			/* this seek was too late, and the decoder had
			   already finished; start a new decoder */

			/* we need to clear the pipe here; usually the
			   PlayerThread is responsible, but it is not
			   aware that the decoder has finished */
			dc.pipe->Clear(*dc.buffer);

554
			decoder_run(dc);
555 556
			break;

557
		case DecoderCommand::STOP:
558
			dc.CommandFinishedLocked();
559 560
			break;

561
		case DecoderCommand::NONE:
562
			dc.Wait();
563
			break;
Warren Dukes's avatar
Warren Dukes committed
564
		}
565
	} while (dc.command != DecoderCommand::NONE || !dc.quit);
566
}
Warren Dukes's avatar
Warren Dukes committed
567

568
void
569
decoder_thread_start(DecoderControl &dc)
570
{
571
	assert(!dc.thread.IsDefined());
572

573
	dc.quit = false;
574
	dc.thread.Start(decoder_task, &dc);
Warren Dukes's avatar
Warren Dukes committed
575
}