FfmpegDecoderPlugin.cxx 17.7 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3
 * 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 21 22
/* necessary because libavutil/common.h uses UINT64_C */
#define __STDC_CONSTANT_MACROS

23
#include "config.h"
24
#include "FfmpegDecoderPlugin.hxx"
25
#include "lib/ffmpeg/Domain.hxx"
26
#include "../DecoderAPI.hxx"
27
#include "FfmpegMetaData.hxx"
28
#include "tag/TagHandler.hxx"
Max Kellermann's avatar
Max Kellermann committed
29
#include "input/InputStream.hxx"
30
#include "CheckAudioFormat.hxx"
31
#include "util/Error.hxx"
32 33
#include "util/Domain.hxx"
#include "LogV.hxx"
34 35

extern "C" {
36 37 38
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
39
#include <libavutil/avutil.h>
40
#include <libavutil/log.h>
41
#include <libavutil/mathematics.h>
42 43 44 45

#if LIBAVUTIL_VERSION_MAJOR >= 53
#include <libavutil/frame.h>
#endif
46
}
47

48 49 50
#include <assert.h>
#include <string.h>

51 52 53 54 55
/* suppress the ffmpeg compatibility macro */
#ifdef SampleFormat
#undef SampleFormat
#endif

56 57
static LogLevel
import_ffmpeg_level(int level)
58 59
{
	if (level <= AV_LOG_FATAL)
60
		return LogLevel::ERROR;
61

62 63
	if (level <= AV_LOG_WARNING)
		return LogLevel::WARNING;
64 65

	if (level <= AV_LOG_INFO)
66
		return LogLevel::INFO;
67

68
	return LogLevel::DEBUG;
69 70 71
}

static void
72
mpd_ffmpeg_log_callback(gcc_unused void *ptr, int level,
73 74
			const char *fmt, va_list vl)
{
75
	const AVClass * cls = nullptr;
76

77
	if (ptr != nullptr)
78 79
		cls = *(const AVClass *const*)ptr;

80
	if (cls != nullptr) {
81 82 83
		char domain[64];
		snprintf(domain, sizeof(domain), "%s/%s",
			 ffmpeg_domain.GetName(), cls->item_name(ptr));
84 85
		const Domain d(domain);
		LogFormatV(d, import_ffmpeg_level(level), fmt, vl);
86
	}
87 88
}

89
struct AvioStream {
90
	Decoder *const decoder;
91
	InputStream &input;
92

93
	AVIOContext *io;
94

95
	unsigned char buffer[8192];
96

97
	AvioStream(Decoder *_decoder, InputStream &_input)
98 99 100 101 102 103 104 105
		:decoder(_decoder), input(_input), io(nullptr) {}

	~AvioStream() {
		if (io != nullptr)
			av_free(io);
	}

	bool Open();
106
};
107

108 109
static int
mpd_ffmpeg_stream_read(void *opaque, uint8_t *buf, int size)
110
{
111
	AvioStream *stream = (AvioStream *)opaque;
112

113 114
	return decoder_read(stream->decoder, stream->input,
			    (void *)buf, size);
115 116
}

117 118
static int64_t
mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence)
119
{
120
	AvioStream *stream = (AvioStream *)opaque;
121

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
	switch (whence) {
	case SEEK_SET:
		break;

	case SEEK_CUR:
		pos += stream->input.GetOffset();
		break;

	case SEEK_END:
		if (!stream->input.KnownSize())
			return -1;

		pos += stream->input.GetSize();
		break;

	case AVSEEK_SIZE:
138 139 140
		if (!stream->input.KnownSize())
			return -1;

141
		return stream->input.GetSize();
142

143 144 145 146 147
	default:
		return -1;
	}

	if (!stream->input.LockSeek(pos, IgnoreError()))
148 149
		return -1;

150
	return stream->input.GetOffset();
151 152
}

153 154
bool
AvioStream::Open()
155
{
156 157 158
	io = avio_alloc_context(buffer, sizeof(buffer),
				false, this,
				mpd_ffmpeg_stream_read, nullptr,
159
				input.IsSeekable()
160 161
				? mpd_ffmpeg_stream_seek : nullptr);
	return io != nullptr;
162 163
}

164 165 166 167 168 169 170 171 172 173 174
/**
 * API compatibility wrapper for av_open_input_stream() and
 * avformat_open_input().
 */
static int
mpd_ffmpeg_open_input(AVFormatContext **ic_ptr,
		      AVIOContext *pb,
		      const char *filename,
		      AVInputFormat *fmt)
{
	AVFormatContext *context = avformat_alloc_context();
175
	if (context == nullptr)
176 177 178 179
		return AVERROR(ENOMEM);

	context->pb = pb;
	*ic_ptr = context;
180
	return avformat_open_input(ic_ptr, filename, fmt, nullptr);
181 182
}

183
static bool
184
ffmpeg_init(gcc_unused const config_param &param)
185
{
186 187
	av_log_set_callback(mpd_ffmpeg_log_callback);

188
	av_register_all();
189
	return true;
190 191
}

192 193 194 195 196
static int
ffmpeg_find_audio_stream(const AVFormatContext *format_context)
{
	for (unsigned i = 0; i < format_context->nb_streams; ++i)
		if (format_context->streams[i]->codec->codec_type ==
197
		    AVMEDIA_TYPE_AUDIO)
198 199 200 201 202
			return i;

	return -1;
}

203
gcc_const
204 205 206 207 208
static double
time_from_ffmpeg(int64_t t, const AVRational time_base)
{
	assert(t != (int64_t)AV_NOPTS_VALUE);

209 210
	return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
		/ (double)1024;
211 212
}

213
gcc_const
214 215 216 217 218 219 220
static int64_t
time_to_ffmpeg(double t, const AVRational time_base)
{
	return av_rescale_q((int64_t)(t * 1024), (AVRational){1, 1024},
			    time_base);
}

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
/**
 * Replace #AV_NOPTS_VALUE with the given fallback.
 */
static constexpr int64_t
timestamp_fallback(int64_t t, int64_t fallback)
{
	return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
		? t
		: fallback;
}

/**
 * Accessor for AVStream::start_time that replaces AV_NOPTS_VALUE with
 * zero.  We can't use AV_NOPTS_VALUE in calculations, and we simply
 * assume that the stream's start time is zero, which appears to be
 * the best way out of that situation.
 */
static int64_t
start_time_fallback(const AVStream &stream)
{
	return timestamp_fallback(stream.start_time, 0);
}

244
static void
245 246 247
copy_interleave_frame2(uint8_t *dest, uint8_t **src,
		       unsigned nframes, unsigned nchannels,
		       unsigned sample_size)
248
{
249 250 251 252 253 254
	for (unsigned frame = 0; frame < nframes; ++frame) {
		for (unsigned channel = 0; channel < nchannels; ++channel) {
			memcpy(dest, src[channel] + frame * sample_size,
			       sample_size);
			dest += sample_size;
		}
255 256 257
	}
}

258 259 260 261 262 263
/**
 * Copy PCM data from a AVFrame to an interleaved buffer.
 */
static int
copy_interleave_frame(const AVCodecContext *codec_context,
		      const AVFrame *frame,
264 265
		      uint8_t **output_buffer,
		      uint8_t **global_buffer, int *global_buffer_size)
266 267 268 269 270 271 272
{
	int plane_size;
	const int data_size =
		av_samples_get_buffer_size(&plane_size,
					   codec_context->channels,
					   frame->nb_samples,
					   codec_context->sample_fmt, 1);
273 274 275
	if (data_size <= 0)
		return data_size;

276 277
	if (av_sample_fmt_is_planar(codec_context->sample_fmt) &&
	    codec_context->channels > 1) {
278 279 280 281 282 283 284 285 286 287 288 289
		if(*global_buffer_size < data_size) {
			av_freep(global_buffer);

			*global_buffer = (uint8_t*)av_malloc(data_size);

			if (!*global_buffer)
				/* Not enough memory - shouldn't happen */
				return AVERROR(ENOMEM);
			*global_buffer_size = data_size;
		}
		*output_buffer = *global_buffer;
		copy_interleave_frame2(*output_buffer, frame->extended_data,
290 291 292
				       frame->nb_samples,
				       codec_context->channels,
				       av_get_bytes_per_sample(codec_context->sample_fmt));
293
	} else {
294
		*output_buffer = frame->extended_data[0];
295 296 297 298 299
	}

	return data_size;
}

300
static DecoderCommand
301
ffmpeg_send_packet(Decoder &decoder, InputStream &is,
302
		   const AVPacket *packet,
303
		   AVCodecContext *codec_context,
304
		   const AVStream *stream,
305 306
		   AVFrame *frame,
		   uint8_t **buffer, int *buffer_size)
307
{
308
	if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE)
309
		decoder_timestamp(decoder,
310
				  time_from_ffmpeg(packet->pts - start_time_fallback(*stream),
311
				  stream->time_base));
312

313
	AVPacket packet2 = *packet;
314

315
	uint8_t *output_buffer;
316

317 318
	DecoderCommand cmd = DecoderCommand::NONE;
	while (packet2.size > 0 && cmd == DecoderCommand::NONE) {
319
		int audio_size = 0;
320 321
		int got_frame = 0;
		int len = avcodec_decode_audio4(codec_context,
322
						frame, &got_frame,
323 324 325
						&packet2);
		if (len >= 0 && got_frame) {
			audio_size = copy_interleave_frame(codec_context,
326
							   frame,
327 328
							   &output_buffer,
							   buffer, buffer_size);
329 330
			if (audio_size < 0)
				len = audio_size;
331
		}
332 333 334

		if (len < 0) {
			/* if error, we skip the frame */
335 336
			LogDefault(ffmpeg_domain,
				   "decoding failed, frame skipped");
337 338 339
			break;
		}

340 341
		packet2.data += len;
		packet2.size -= len;
342

343
		if (audio_size <= 0)
344
			continue;
345

346
		cmd = decoder_data(decoder, is,
347
				   output_buffer, audio_size,
348
				   codec_context->bit_rate / 1000);
349
	}
350
	return cmd;
351 352
}

353
gcc_const
354
static SampleFormat
355
ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
356
{
357
	switch (sample_fmt) {
358
	case AV_SAMPLE_FMT_S16:
359
	case AV_SAMPLE_FMT_S16P:
360
		return SampleFormat::S16;
361

362
	case AV_SAMPLE_FMT_S32:
363
	case AV_SAMPLE_FMT_S32P:
364
		return SampleFormat::S32;
365

366
	case AV_SAMPLE_FMT_FLTP:
367
		return SampleFormat::FLOAT;
368

369
	default:
370 371 372 373 374 375
		break;
	}

	char buffer[64];
	const char *name = av_get_sample_fmt_string(buffer, sizeof(buffer),
						    sample_fmt);
376
	if (name != nullptr)
377 378 379
		FormatError(ffmpeg_domain,
			    "Unsupported libavcodec SampleFormat value: %s (%d)",
			    name, sample_fmt);
380
	else
381 382 383
		FormatError(ffmpeg_domain,
			    "Unsupported libavcodec SampleFormat value: %d",
			    sample_fmt);
384
	return SampleFormat::UNDEFINED;
385 386
}

387
static AVInputFormat *
388
ffmpeg_probe(Decoder *decoder, InputStream &is)
389 390 391 392 393 394
{
	enum {
		BUFFER_SIZE = 16384,
		PADDING = 16,
	};

395
	unsigned char buffer[BUFFER_SIZE];
396
	size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE);
397
	if (nbytes <= PADDING || !is.LockRewind(IgnoreError()))
398
		return nullptr;
399 400 401 402 403 404 405

	/* some ffmpeg parsers (e.g. ac3_parser.c) read a few bytes
	   beyond the declared buffer limit, which makes valgrind
	   angry; this workaround removes some padding from the buffer
	   size */
	nbytes -= PADDING;

406 407 408
	AVProbeData avpd;
	avpd.buf = buffer;
	avpd.buf_size = nbytes;
409
	avpd.filename = is.GetURI();
410

411
	return av_probe_input_format(&avpd, true);
412 413
}

414
static void
415
ffmpeg_decode(Decoder &decoder, InputStream &input)
416
{
417
	AVInputFormat *input_format = ffmpeg_probe(&decoder, input);
418
	if (input_format == nullptr)
419 420
		return;

421 422
	FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)",
		    input_format->name, input_format->long_name);
423

424
	AvioStream stream(&decoder, input);
425
	if (!stream.Open()) {
426
		LogError(ffmpeg_domain, "Failed to open stream");
427 428 429
		return;
	}

430
	//ffmpeg works with ours "fileops" helper
431
	AVFormatContext *format_context = nullptr;
432
	if (mpd_ffmpeg_open_input(&format_context, stream.io,
433
				  input.GetURI(),
434
				  input_format) != 0) {
435
		LogError(ffmpeg_domain, "Open failed");
436 437 438
		return;
	}

439
	const int find_result =
440
		avformat_find_stream_info(format_context, nullptr);
441
	if (find_result < 0) {
442
		LogError(ffmpeg_domain, "Couldn't find stream info");
443
		avformat_close_input(&format_context);
444 445
		return;
	}
446

447
	int audio_stream = ffmpeg_find_audio_stream(format_context);
448
	if (audio_stream == -1) {
449
		LogError(ffmpeg_domain, "No audio stream inside");
450
		avformat_close_input(&format_context);
451 452
		return;
	}
453

454 455 456
	AVStream *av_stream = format_context->streams[audio_stream];

	AVCodecContext *codec_context = av_stream->codec;
457 458 459 460 461 462 463 464

#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0)
	const AVCodecDescriptor *codec_descriptor =
		avcodec_descriptor_get(codec_context->codec_id);
	if (codec_descriptor != nullptr)
		FormatDebug(ffmpeg_domain, "codec '%s'",
			    codec_descriptor->name);
#else
465
	if (codec_context->codec_name[0] != 0)
466 467
		FormatDebug(ffmpeg_domain, "codec '%s'",
			    codec_context->codec_name);
468
#endif
469

470
	AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);
471 472

	if (!codec) {
473
		LogError(ffmpeg_domain, "Unsupported audio codec");
474
		avformat_close_input(&format_context);
475 476 477
		return;
	}

478
	const SampleFormat sample_format =
479
		ffmpeg_sample_format(codec_context->sample_fmt);
480 481 482
	if (sample_format == SampleFormat::UNDEFINED) {
		// (error message already done by ffmpeg_sample_format())
		avformat_close_input(&format_context);
483
		return;
484
	}
485

486
	Error error;
487 488
	AudioFormat audio_format;
	if (!audio_format_init_checked(audio_format,
489
				       codec_context->sample_rate,
490
				       sample_format,
491
				       codec_context->channels, error)) {
492
		LogError(error);
493
		avformat_close_input(&format_context);
494 495 496 497 498 499 500 501
		return;
	}

	/* the audio format must be read from AVCodecContext by now,
	   because avcodec_open() has been demonstrated to fill bogus
	   values into AVCodecContext.channels - a change that will be
	   reverted later by avcodec_decode_audio3() */

502
	const int open_result = avcodec_open2(codec_context, codec, nullptr);
503
	if (open_result < 0) {
504
		LogError(ffmpeg_domain, "Could not open codec");
505
		avformat_close_input(&format_context);
506
		return;
507 508
	}

509 510 511
	int total_time = format_context->duration != (int64_t)AV_NOPTS_VALUE
		? format_context->duration / AV_TIME_BASE
		: 0;
512

513
	decoder_initialized(decoder, audio_format,
514
			    input.IsSeekable(), total_time);
515

516 517 518
#if LIBAVUTIL_VERSION_MAJOR >= 53
	AVFrame *frame = av_frame_alloc();
#else
519
	AVFrame *frame = avcodec_alloc_frame();
520
#endif
521
	if (!frame) {
522
		LogError(ffmpeg_domain, "Could not allocate frame");
523 524 525 526
		avformat_close_input(&format_context);
		return;
	}

527
	uint8_t *interleaved_buffer = nullptr;
528 529
	int interleaved_buffer_size = 0;

530
	DecoderCommand cmd;
531
	do {
532
		AVPacket packet;
Max Kellermann's avatar
Max Kellermann committed
533
		if (av_read_frame(format_context, &packet) < 0)
534 535 536
			/* end of file */
			break;

537 538
		if (packet.stream_index == audio_stream)
			cmd = ffmpeg_send_packet(decoder, input,
Max Kellermann's avatar
Max Kellermann committed
539
						 &packet, codec_context,
540
						 av_stream,
541 542
						 frame,
						 &interleaved_buffer, &interleaved_buffer_size);
543 544 545 546
		else
			cmd = decoder_get_command(decoder);

		av_free_packet(&packet);
547

548
		if (cmd == DecoderCommand::SEEK) {
549
			int64_t where =
550
				time_to_ffmpeg(decoder_seek_where(decoder),
551
					       av_stream->time_base) +
552
				start_time_fallback(*av_stream);
553

554
			if (av_seek_frame(format_context, audio_stream, where,
555
					  AVSEEK_FLAG_ANY) < 0)
556
				decoder_seek_error(decoder);
557 558
			else {
				avcodec_flush_buffers(codec_context);
559
				decoder_command_finished(decoder);
560
			}
561
		}
562
	} while (cmd != DecoderCommand::STOP);
563

564 565 566
#if LIBAVUTIL_VERSION_MAJOR >= 53
	av_frame_free(&frame);
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
567 568 569 570
	avcodec_free_frame(&frame);
#else
	av_freep(&frame);
#endif
571
	av_freep(&interleaved_buffer);
572

573
	avcodec_close(codec_context);
574
	avformat_close_input(&format_context);
575 576
}

577
//no tag reading in ffmpeg, check if playable
578
static bool
579
ffmpeg_scan_stream(InputStream &is,
580
		   const struct tag_handler *handler, void *handler_ctx)
581
{
582 583
	AVInputFormat *input_format = ffmpeg_probe(nullptr, is);
	if (input_format == nullptr)
584
		return false;
585

586 587
	AvioStream stream(nullptr, is);
	if (!stream.Open())
588
		return false;
589

590
	AVFormatContext *f = nullptr;
591
	if (mpd_ffmpeg_open_input(&f, stream.io, is.GetURI(),
592
				  input_format) != 0)
593
		return false;
594

595
	const int find_result =
596
		avformat_find_stream_info(f, nullptr);
597 598
	if (find_result < 0) {
		avformat_close_input(&f);
599
		return false;
600 601
	}

602 603 604
	if (f->duration != (int64_t)AV_NOPTS_VALUE)
		tag_handler_invoke_duration(handler, handler_ctx,
					    f->duration / AV_TIME_BASE);
605

606
	ffmpeg_scan_dictionary(f->metadata, handler, handler_ctx);
607 608
	int idx = ffmpeg_find_audio_stream(f);
	if (idx >= 0)
609 610
		ffmpeg_scan_dictionary(f->streams[idx]->metadata,
				       handler, handler_ctx);
611

612
	avformat_close_input(&f);
613
	return true;
614 615 616
}

/**
617 618 619 620
 * A list of extensions found for the formats supported by ffmpeg.
 * This list is current as of 02-23-09; To find out if there are more
 * supported formats, check the ffmpeg changelog since this date for
 * more formats.
621
 */
Max Kellermann's avatar
Max Kellermann committed
622
static const char *const ffmpeg_suffixes[] = {
623 624 625 626 627
	"16sv", "3g2", "3gp", "4xm", "8svx", "aa3", "aac", "ac3", "afc", "aif",
	"aifc", "aiff", "al", "alaw", "amr", "anim", "apc", "ape", "asf",
	"atrac", "au", "aud", "avi", "avm2", "avs", "bap", "bfi", "c93", "cak",
	"cin", "cmv", "cpk", "daud", "dct", "divx", "dts", "dv", "dvd", "dxa",
	"eac3", "film", "flac", "flc", "fli", "fll", "flx", "flv", "g726",
628 629 630
	"gsm", "gxf", "iss", "m1v", "m2v", "m2t", "m2ts",
	"m4a", "m4b", "m4v",
	"mad",
631 632 633 634 635 636 637
	"mj2", "mjpeg", "mjpg", "mka", "mkv", "mlp", "mm", "mmf", "mov", "mp+",
	"mp1", "mp2", "mp3", "mp4", "mpc", "mpeg", "mpg", "mpga", "mpp", "mpu",
	"mve", "mvi", "mxf", "nc", "nsv", "nut", "nuv", "oga", "ogm", "ogv",
	"ogx", "oma", "ogg", "omg", "psp", "pva", "qcp", "qt", "r3d", "ra",
	"ram", "rl2", "rm", "rmvb", "roq", "rpl", "rvc", "shn", "smk", "snd",
	"sol", "son", "spx", "str", "swf", "tgi", "tgq", "tgv", "thp", "ts",
	"tsp", "tta", "xa", "xvid", "uv", "uv2", "vb", "vid", "vob", "voc",
638 639
	"vp6", "vmd", "wav", "webm", "wma", "wmv", "wsaud", "wsvga", "wv",
	"wve",
640
	nullptr
641 642
};

Max Kellermann's avatar
Max Kellermann committed
643
static const char *const ffmpeg_mime_types[] = {
644
	"application/flv",
645
	"application/m4a",
646 647 648 649 650
	"application/mp4",
	"application/octet-stream",
	"application/ogg",
	"application/x-ms-wmz",
	"application/x-ms-wmd",
651
	"application/x-ogg",
652 653 654 655 656 657
	"application/x-shockwave-flash",
	"application/x-shorten",
	"audio/8svx",
	"audio/16sv",
	"audio/aac",
	"audio/ac3",
658
	"audio/aiff"
659 660 661
	"audio/amr",
	"audio/basic",
	"audio/flac",
662 663
	"audio/m4a",
	"audio/mp4",
664 665 666 667 668
	"audio/mpeg",
	"audio/musepack",
	"audio/ogg",
	"audio/qcelp",
	"audio/vorbis",
669
	"audio/vorbis+ogg",
670 671 672 673 674 675 676 677 678 679 680 681
	"audio/x-8svx",
	"audio/x-16sv",
	"audio/x-aac",
	"audio/x-ac3",
	"audio/x-aiff"
	"audio/x-alaw",
	"audio/x-au",
	"audio/x-dca",
	"audio/x-eac3",
	"audio/x-flac",
	"audio/x-gsm",
	"audio/x-mace",
682
	"audio/x-matroska",
683 684
	"audio/x-monkeys-audio",
	"audio/x-mpeg",
685 686
	"audio/x-ms-wma",
	"audio/x-ms-wax",
687
	"audio/x-musepack",
688 689 690
	"audio/x-ogg",
	"audio/x-vorbis",
	"audio/x-vorbis+ogg",
691 692 693 694
	"audio/x-pn-realaudio",
	"audio/x-pn-multirate-realaudio",
	"audio/x-speex",
	"audio/x-tta"
695
	"audio/x-voc",
696 697 698 699 700 701 702 703
	"audio/x-wav",
	"audio/x-wma",
	"audio/x-wv",
	"video/anim",
	"video/quicktime",
	"video/msvideo",
	"video/ogg",
	"video/theora",
704
	"video/webm",
705 706 707 708 709 710 711
	"video/x-dv",
	"video/x-flv",
	"video/x-matroska",
	"video/x-mjpeg",
	"video/x-mpeg",
	"video/x-ms-asf",
	"video/x-msvideo",
712 713 714 715
	"video/x-ms-wmv",
	"video/x-ms-wvx",
	"video/x-ms-wm",
	"video/x-ms-wmx",
716 717 718 719 720 721
	"video/x-nut",
	"video/x-pva",
	"video/x-theora",
	"video/x-vid",
	"video/x-wmv",
	"video/x-xvid",
722 723 724 725 726 727

	/* special value for the "ffmpeg" input plugin: all streams by
	   the "ffmpeg" input plugin shall be decoded by this
	   plugin */
	"audio/x-mpd-ffmpeg",

728
	nullptr
729 730
};

731
const struct DecoderPlugin ffmpeg_decoder_plugin = {
732 733 734 735 736 737 738 739 740 741
	"ffmpeg",
	ffmpeg_init,
	nullptr,
	ffmpeg_decode,
	nullptr,
	nullptr,
	ffmpeg_scan_stream,
	nullptr,
	ffmpeg_suffixes,
	ffmpeg_mime_types
742
};