diff -ur src/plugins/avcodec.orig/avcodec.c src/plugins/avcodec/avcodec.c
--- src/plugins/avcodec.orig/avcodec.c	2016-02-24 11:59:39.000000000 -0800
+++ src/plugins/avcodec/avcodec.c	2016-02-24 12:01:27.000000000 -0800
@@ -1,7 +1,7 @@
 /** @file avcodec.c
  *  Decoder plugin for ffmpeg avcodec formats
  *
- *  Copyright (C) 2006-2011 XMMS2 Team
+ *  Copyright (C) 2006-2014 XMMS2 Team
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -14,20 +14,20 @@
  *  Lesser General Public License for more details.
  */
 
-#include "xmms_configuration.h"
-#include "xmms/xmms_xformplugin.h"
-#include "xmms/xmms_sample.h"
-#include "xmms/xmms_log.h"
+#include <xmms_configuration.h>
+#include <xmms/xmms_xformplugin.h>
+#include <xmms/xmms_sample.h>
+#include <xmms/xmms_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <glib.h>
+#include <libavutil/mem.h>
 
 #include "avcodec_compat.h"
 
 #define AVCODEC_BUFFER_SIZE 16384
-#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
 
 typedef struct {
 	AVCodecContext *codecctx;
@@ -37,6 +37,8 @@
 	guint buffer_size;
 	gboolean no_demuxer;
 
+	AVFrame *read_out_frame;
+
 	guint channels;
 	guint samplerate;
 	xmms_sample_format_t sampleformat;
@@ -54,10 +56,14 @@
 static gboolean xmms_avcodec_plugin_setup (xmms_xform_plugin_t *xform_plugin);
 static gboolean xmms_avcodec_init (xmms_xform_t *xform);
 static void xmms_avcodec_destroy (xmms_xform_t *xform);
+static gint xmms_avcodec_internal_read_some (xmms_xform_t *xform, xmms_avcodec_data_t *data, xmms_error_t *error);
+static gint xmms_avcodec_internal_decode_some (xmms_avcodec_data_t *data);
+static void xmms_avcodec_internal_append (xmms_avcodec_data_t *data);
 static gint xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
                                xmms_error_t *error);
 static gint64 xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples,
                                  xmms_xform_seek_mode_t whence, xmms_error_t *err);
+static xmms_sample_format_t xmms_avcodec_translate_sample_format (enum AVSampleFormat av_sample_format);
 
 /*
  * Plugin header
@@ -93,6 +99,16 @@
 	                              "audio/x-ffmpeg-*",
 	                              NULL);
 
+	XMMS_DBG ("avcodec version at build time is %d.%d.%d",
+	          (LIBAVCODEC_VERSION_INT >> 16),
+	          (LIBAVCODEC_VERSION_INT >> 8) & 0xff,
+	          LIBAVCODEC_VERSION_INT & 0xff);
+	XMMS_DBG ("avcodec version at run time is %d.%d.%d",
+	          (avcodec_version() >> 16),
+	          (avcodec_version() >> 8) & 0xff,
+	          avcodec_version() & 0xff);
+	XMMS_DBG ("avcodec configuration is %s", avcodec_configuration());
+
 	return TRUE;
 }
 
@@ -108,6 +124,7 @@
 
 	avcodec_close (data->codecctx);
 	av_free (data->codecctx);
+	av_frame_free (&data->read_out_frame);
 
 	g_string_free (data->outbuf, TRUE);
 	g_free (data->buffer);
@@ -133,8 +150,11 @@
 	data->buffer_size = AVCODEC_BUFFER_SIZE;
 	data->codecctx = NULL;
 
+	data->read_out_frame = av_frame_alloc ();
+
 	xmms_xform_private_data_set (xform, data);
 
+	avcodec_init ();
 	avcodec_register_all ();
 
 	mimetype = xmms_xform_indata_get_str (xform,
@@ -161,12 +181,12 @@
 		data->channels = ret;
 	}
 
-	/* bitrate required for WMA files */
+	/* Required by WMA xform. */
 	xmms_xform_auxdata_get_int (xform,
 	                            "bitrate",
 	                            &data->bitrate);
 
-	/* ALAC and MAC require bits per sample field to be 16 */
+	/* Required by tta and apefile xforms. */
 	xmms_xform_auxdata_get_int (xform,
 	                            "samplebits",
 	                            &data->samplebits);
@@ -197,11 +217,11 @@
 		} else {
 			/* A demuxer plugin forgot to give decoder config? */
 			xmms_log_error ("Decoder config data not found!");
-			return FALSE;
+			goto err;
 		}
 	}
 
-	data->codecctx = avcodec_alloc_context3 (NULL);
+	data->codecctx = avcodec_alloc_context3 (codec);
 	data->codecctx->sample_rate = data->samplerate;
 	data->codecctx->channels = data->channels;
 	data->codecctx->bit_rate = data->bitrate;
@@ -221,7 +241,7 @@
 
 		/* some codecs need to have something read before they set
 		 * the samplerate and channels correctly, unfortunately... */
-		if ((ret = xmms_avcodec_read (xform, buf, 42, &error)) > 0) {
+		if ((ret = xmms_avcodec_read (xform, buf, sizeof (buf), &error)) > 0) {
 			g_string_insert_len (data->outbuf, 0, buf, ret);
 		} else {
 			XMMS_DBG ("First read failed, codec is not working...");
@@ -232,12 +252,17 @@
 
 	data->samplerate = data->codecctx->sample_rate;
 	data->channels = data->codecctx->channels;
+	data->sampleformat = xmms_avcodec_translate_sample_format (data->codecctx->sample_fmt);
+	if (data->sampleformat == XMMS_SAMPLE_FORMAT_UNKNOWN) {
+		avcodec_close (data->codecctx);
+		goto err;
+	}
 
 	xmms_xform_outdata_type_add (xform,
 	                             XMMS_STREAM_TYPE_MIMETYPE,
 	                             "audio/pcm",
 	                             XMMS_STREAM_TYPE_FMT_FORMAT,
-	                             XMMS_SAMPLE_FORMAT_S16,
+	                             data->sampleformat,
 	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
 	                             data->channels,
 	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
@@ -252,6 +277,9 @@
 	if (data->codecctx) {
 		av_free (data->codecctx);
 	}
+	if (data->read_out_frame) {
+		avcodec_free_frame (&data->read_out_frame);
+	}
 	g_string_free (data->outbuf, TRUE);
 	g_free (data->extradata);
 	g_free (data);
@@ -264,102 +292,24 @@
                    xmms_error_t *error)
 {
 	xmms_avcodec_data_t *data;
-	char outbuf[MAX_AUDIO_FRAME_SIZE];
-	gint outbufsize, bytes_read = 0;
 	guint size;
 
 	data = xmms_xform_private_data_get (xform);
 	g_return_val_if_fail (data, -1);
 
-	size = MIN (data->outbuf->len, len);
-	while (size == 0) {
-		AVPacket packet;
-		av_init_packet (&packet);
+	while (0 == (size = MIN (data->outbuf->len, len))) {
+		gint res;
 
 		if (data->no_demuxer || data->buffer_length == 0) {
-			gint read_total;
-
-			bytes_read = xmms_xform_read (xform,
-			                              (gchar *) (data->buffer + data->buffer_length),
-			                              data->buffer_size - data->buffer_length,
-			                              error);
-
-			if (bytes_read < 0) {
-				XMMS_DBG ("Error while reading data");
-				return bytes_read;
-			} else if (bytes_read == 0) {
-				XMMS_DBG ("EOF");
-				return 0;
-			}
+			gint bytes_read;
 
-			read_total = bytes_read;
-
-			/* If we have a demuxer plugin, make sure we read the whole packet */
-			while (read_total == data->buffer_size && !data->no_demuxer) {
-				/* multiply the buffer size and try to read again */
-				data->buffer = g_realloc (data->buffer, data->buffer_size * 2);
-				bytes_read = xmms_xform_read (xform,
-				                              (gchar *) data->buffer +
-				                                data->buffer_size,
-				                              data->buffer_size,
-				                              error);
-				data->buffer_size *= 2;
-
-				if (bytes_read < 0) {
-					XMMS_DBG ("Error while reading data");
-					return bytes_read;
-				}
-
-				read_total += bytes_read;
-
-				if (read_total < data->buffer_size) {
-					/* finally double the buffer size for performance reasons, the
-					 * hotspot handling likes to fit two frames in the buffer */
-					data->buffer = g_realloc (data->buffer, data->buffer_size * 2);
-					data->buffer_size *= 2;
-					XMMS_DBG ("Reallocated avcodec internal buffer to be %d bytes",
-					          data->buffer_size);
-
-					break;
-				}
-			}
-
-			/* Update the buffer length */
-			data->buffer_length += read_total;
+			bytes_read = xmms_avcodec_internal_read_some (xform, data, error);
+			if (bytes_read <= 0) { return bytes_read; }
 		}
 
-		packet.data = data->buffer;
-		packet.size = data->buffer_length;
-
-		outbufsize = sizeof (outbuf);
-		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) outbuf,
-		                                    &outbufsize, &packet);
-
-		/* The DTS decoder of ffmpeg is buggy and always returns
-		 * the input buffer length, get frame length from header */
-		if (!strcmp (data->codec_id, "dca") && bytes_read > 0) {
-			bytes_read = ((int)data->buffer[5] << 12) |
-			             ((int)data->buffer[6] << 4) |
-			             ((int)data->buffer[7] >> 4);
-			bytes_read = (bytes_read & 0x3fff) + 1;
-		}
-
-		if (bytes_read < 0 || bytes_read > data->buffer_length) {
-			XMMS_DBG ("Error decoding data!");
-			return -1;
-		} else if (bytes_read != data->buffer_length) {
-			g_memmove (data->buffer,
-			           data->buffer + bytes_read,
-			           data->buffer_length - bytes_read);
-		}
-
-		data->buffer_length -= bytes_read;
-
-		if (outbufsize > 0) {
-			g_string_append_len (data->outbuf, outbuf, outbufsize);
-		}
-
-		size = MIN (data->outbuf->len, len);
+		res = xmms_avcodec_internal_decode_some (data);
+		if (res < 0) { return res; }
+		if (res > 0) { xmms_avcodec_internal_append (data); }
 	}
 
 	memcpy (buf, data->outbuf->str, size);
@@ -372,8 +322,6 @@
 xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t whence, xmms_error_t *err)
 {
 	xmms_avcodec_data_t *data;
-	char outbuf[MAX_AUDIO_FRAME_SIZE];
-	gint outbufsize, bytes_read = 0;
 	gint64 ret = -1;
 
 	g_return_val_if_fail (xform, -1);
@@ -391,23 +339,11 @@
 
 	/* The buggy ape decoder doesn't flush buffers, so we need to finish decoding
 	 * the frame before seeking to avoid segfaults... this hack sucks */
+	/* FIXME: Is ^^^ still true? */
 	while (data->buffer_length > 0) {
-		AVPacket packet;
-		av_init_packet (&packet);
-		packet.data = data->buffer;
-		packet.size = data->buffer_length;
-
-		outbufsize = sizeof (outbuf);
-		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) outbuf,
-		                                    &outbufsize, &packet);
-
-		if (bytes_read < 0 || bytes_read > data->buffer_length) {
-			XMMS_DBG ("Error decoding data!");
+		if (xmms_avcodec_internal_decode_some (data) < 0) {
 			return -1;
 		}
-
-		data->buffer_length -= bytes_read;
-		g_memmove (data->buffer, data->buffer + bytes_read, data->buffer_length);
 	}
 
 	ret = xmms_xform_seek (xform, samples, whence, err);
@@ -421,3 +357,178 @@
 
 	return ret;
 }
+
+static xmms_sample_format_t
+xmms_avcodec_translate_sample_format (enum AVSampleFormat av_sample_format)
+{
+	switch (av_sample_format) {
+	case AV_SAMPLE_FMT_U8:
+	case AV_SAMPLE_FMT_U8P:
+		return XMMS_SAMPLE_FORMAT_U8;
+	case AV_SAMPLE_FMT_S16:
+	case AV_SAMPLE_FMT_S16P:
+		return XMMS_SAMPLE_FORMAT_S16;
+	case AV_SAMPLE_FMT_S32:
+	case AV_SAMPLE_FMT_S32P:
+		return XMMS_SAMPLE_FORMAT_S32;
+	case AV_SAMPLE_FMT_FLT:
+	case AV_SAMPLE_FMT_FLTP:
+		return XMMS_SAMPLE_FORMAT_FLOAT;
+	case AV_SAMPLE_FMT_DBL:
+	case AV_SAMPLE_FMT_DBLP:
+		return XMMS_SAMPLE_FORMAT_DOUBLE;
+	default:
+		XMMS_DBG ("AVSampleFormat (%i: %s) not supported.", av_sample_format,
+		          av_get_sample_fmt_name (av_sample_format));
+		return XMMS_SAMPLE_FORMAT_UNKNOWN;
+	}
+}
+
+/*
+Read some data from our source of data to data->buffer, updating buffer_length
+and buffer_size as needed.
+
+Returns: on error: negative
+         on EOF: zero
+         otherwise: number of bytes read.
+*/
+static gint
+xmms_avcodec_internal_read_some (xmms_xform_t *xform,
+                                 xmms_avcodec_data_t *data,
+                                 xmms_error_t *error)
+{
+	gint bytes_read, read_total;
+
+	bytes_read = xmms_xform_read (xform,
+	                              (gchar *) (data->buffer + data->buffer_length),
+	                              data->buffer_size - data->buffer_length,
+	                              error);
+
+	if (bytes_read < 0) {
+		XMMS_DBG ("Error while reading data");
+		return bytes_read;
+	} else if (bytes_read == 0) {
+		XMMS_DBG ("EOF");
+		return 0;
+	}
+
+	read_total = bytes_read;
+
+	/* If we have a demuxer plugin, make sure we read the whole packet */
+	while (read_total == data->buffer_size && !data->no_demuxer) {
+		/* multiply the buffer size and try to read again */
+		data->buffer = g_realloc (data->buffer, data->buffer_size * 2);
+		bytes_read = xmms_xform_read (xform,
+		                              (gchar *) data->buffer +
+		                                data->buffer_size,
+		                              data->buffer_size,
+		                              error);
+		data->buffer_size *= 2;
+
+		if (bytes_read < 0) {
+			XMMS_DBG ("Error while reading data");
+			return bytes_read;
+		}
+
+		read_total += bytes_read;
+
+		if (read_total < data->buffer_size) {
+			/* finally double the buffer size for performance reasons, the
+			 * hotspot handling likes to fit two frames in the buffer */
+			data->buffer = g_realloc (data->buffer, data->buffer_size * 2);
+			data->buffer_size *= 2;
+			XMMS_DBG ("Reallocated avcodec internal buffer to be %d bytes",
+			          data->buffer_size);
+
+			break;
+		}
+	}
+
+	/* Update the buffer length */
+	data->buffer_length += read_total;
+
+	return read_total;
+}
+
+/*
+Decode some data from data->buffer[0..data->buffer_length-1] to
+data->read_out_frame
+
+Returns: on error: negative
+         on no new data produced: zero
+         otherwise: positive
+
+FIXME: data->buffer should be at least data->buffer_length +
+FF_INPUT_BUFFER_PADDING_SIZE long.
+*/
+static gint
+xmms_avcodec_internal_decode_some (xmms_avcodec_data_t *data)
+{
+	int got_frame = 0;
+	gint bytes_read = 0;
+	AVPacket packet;
+
+	av_init_packet (&packet);
+	packet.data = data->buffer;
+	packet.size = data->buffer_length;
+
+	/* clear buffers and reset fields to defaults */
+	av_frame_unref (data->read_out_frame);
+
+	bytes_read = avcodec_decode_audio4 (
+		data->codecctx, data->read_out_frame, &got_frame, &packet);
+
+	/* The DTS decoder of ffmpeg is buggy and always returns
+	 * the input buffer length, get frame length from header */
+	/* FIXME: Is ^^^^ still true? */
+	if (!strcmp (data->codec_id, "dca") && bytes_read > 0) {
+		bytes_read = ((int)data->buffer[5] << 12) |
+		             ((int)data->buffer[6] << 4) |
+		             ((int)data->buffer[7] >> 4);
+		bytes_read = (bytes_read & 0x3fff) + 1;
+	}
+
+	if (bytes_read < 0 || bytes_read > data->buffer_length) {
+		XMMS_DBG ("Error decoding data!");
+		return -1;
+	}
+
+	if (bytes_read < data->buffer_length) {
+		data->buffer_length -= bytes_read;
+		g_memmove (data->buffer,
+		           data->buffer + bytes_read,
+		           data->buffer_length);
+	} else {
+		data->buffer_length = 0;
+	}
+
+	return got_frame ? 1 : 0;
+}
+
+static void
+xmms_avcodec_internal_append (xmms_avcodec_data_t *data)
+{
+	enum AVSampleFormat fmt = (enum AVSampleFormat) data->read_out_frame->format;
+	int samples = data->read_out_frame->nb_samples;
+	int channels = data->codecctx->channels;
+	int bps = av_get_bytes_per_sample (fmt);
+
+	if (av_sample_fmt_is_planar (fmt)) {
+		/* Convert from planar to packed format */
+		gint i, j;
+
+		for (i = 0; i < samples; i++) {
+			for (j = 0; j < channels; j++) {
+				g_string_append_len (
+					data->outbuf,
+					(gchar *) (data->read_out_frame->extended_data[j] + i*bps),
+					bps
+				);
+			}
+		}
+	} else {
+		g_string_append_len (data->outbuf,
+		                     (gchar *) data->read_out_frame->extended_data[0],
+		                     samples * channels * bps);
+	}
+}
diff -ur src/plugins/avcodec.orig/avcodec_compat.h src/plugins/avcodec/avcodec_compat.h
--- src/plugins/avcodec.orig/avcodec_compat.h	2016-02-24 11:59:39.000000000 -0800
+++ src/plugins/avcodec/avcodec_compat.h	2016-02-24 12:02:03.000000000 -0800
@@ -1,7 +1,7 @@
 /** @file avcodec_compat.h
  *  Compatibility header for libavcodec backwards compatibility
  *
- *  Copyright (C) 2011 XMMS2 Team
+ *  Copyright (C) 2011-2014 XMMS2 Team
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -65,3 +65,35 @@
 # define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
 #endif
 
+/* Calling avcodec_init is not necessary after 53.04 (ffmpeg 0.9) */
+#if LIBAVCODEC_VERSION_INT >= 0x350400
+# define avcodec_init()
+#endif
+
+/* Map avcodec_alloc_context3 into the deprecated version
+ * avcodec_alloc_context in versions earlier than 53.04 (ffmpeg 0.9) */
+#if LIBAVCODEC_VERSION_INT < 0x350400
+# define avcodec_alloc_context3(codec) \
+    avcodec_alloc_context()
+#endif
+
+/* Map avcodec_open2 into the deprecated version
+ * avcodec_open in versions earlier than 53.04 (ffmpeg 0.9) */
+#if LIBAVCODEC_VERSION_INT < 0x350400
+# define avcodec_open2(avctx, codec, options) \
+    avcodec_open(avctx, codec)
+#endif
+
+/* Map avcodec_free_frame to av_freep if the former doesn't exist.
+ * (This is in versions earlier than 54.28.0 (libav) or 54.59.100 (ffmpeg)) */
+#if ! HAVE_AVCODEC_FREE_FRAME
+# define avcodec_free_frame av_freep
+#endif
+
+/* Map av_frame_alloc, av_frame_unref, av_frame_free into their
+ * deprecated versions in versions earlier than 55.28.1 */
+#if LIBAVCODEC_VERSION_INT < 0x371c01
+# define av_frame_alloc avcodec_alloc_frame
+# define av_frame_unref avcodec_get_frame_defaults
+# define av_frame_free avcodec_free_frame
+#endif
diff -ur src/plugins/avcodec.orig/wscript src/plugins/avcodec/wscript
--- src/plugins/avcodec.orig/wscript	2016-02-24 11:59:39.000000000 -0800
+++ src/plugins/avcodec/wscript	2016-02-24 12:00:41.000000000 -0800
@@ -1,10 +1,33 @@
 from waftools.plugin import plugin
 
+## Code fragments for configuration
+avcodec_free_frame_fragment = """
+#ifdef HAVE_LIBAVCODEC_AVCODEC_H
+# include "libavcodec/avcodec.h"
+#else
+# include "avcodec.h"
+#endif
+int main(void) {
+    AVFrame *frame;
+
+    avcodec_free_frame (&frame);
+
+    return 0;
+}
+"""
+
 def plugin_configure(conf):
     conf.check_cfg(package="libavcodec", uselib_store="avcodec",
             args="--cflags --libs")
     conf.check_cc(header_name="avcodec.h", uselib="avcodec", type="cshlib", mandatory=False)
     conf.check_cc(header_name="libavcodec/avcodec.h", uselib="avcodec", type="cshlib", mandatory=False)
 
+    # non-mandatory function avcodec_free_frame since
+    # * ffmpeg: commit 46a3595, lavc 54.59.100, release 1.0
+    # * libav: commit a42aada, lavc 54.28.0, release 9
+    conf.check_cc(fragment=avcodec_free_frame_fragment, uselib="avcodec",
+                  uselib_store="avcodec_free_frame",
+                  msg="Checking for function avcodec_free_frame", mandatory=False)
+
 configure, build = plugin('avcodec', configure=plugin_configure,
                           libs=["avcodec"])