commit:     45fc303a416aa252542c49b9383ad148f9022974
Author:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
AuthorDate: Sat Apr  2 10:43:39 2016 +0000
Commit:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
CommitDate: Sat Apr  2 10:43:47 2016 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=45fc303a

media-sound/xmms2: support stable API for libav, bug #540890

Latest stable media-video/ffmpeg-2.8.6 provides both functions:
  avcodec_decode_audio3
  avcodec_decode_audio4

While latest stable media-video/libav-11.3 provides only
  avcodec_decode_audio4

Pulled large patchset from upstream to support audio4 API.

Builds fine on both stable virtual/ffmpeg implementations
and unstable libav.

Reported-by: Toralf Förster
Bug: https://bugs.gentoo.org/540890

Package-Manager: portage-2.2.28

 media-sound/xmms2/files/xmms2-0.8-audio4-p1.patch | 123 +++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p2.patch | 171 ++++++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p3.patch | 388 ++++++++++++++++++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p4.patch | 296 +++++++++++++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p5.patch | 154 +++++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p6.patch | 106 ++++++
 media-sound/xmms2/files/xmms2-0.8-audio4-p7.patch | 147 ++++++++
 media-sound/xmms2/xmms2-0.8-r2.ebuild             |   7 +
 8 files changed, 1392 insertions(+)

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p1.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p1.patch
new file mode 100644
index 0000000..21ed649
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p1.patch
@@ -0,0 +1,123 @@
+commit 8831bc77d705c03b3f8081de0520dd10afa85c69
+Author: Uli Franke <[email protected]>
+Date:   Tue Jan 17 23:23:46 2012 +0100
+
+    BUG(2509): Avoid unaligned reads in avcodec xform.
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index fe58fc5..1b4a659 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -36,6 +36,9 @@ typedef struct {
+       guint buffer_size;
+       gboolean no_demuxer;
+ 
++      gchar *read_out_buffer;
++      gint read_out_buffer_size;
++
+       guint channels;
+       guint samplerate;
+       xmms_sample_format_t sampleformat;
+@@ -107,6 +110,7 @@ xmms_avcodec_destroy (xmms_xform_t *xform)
+ 
+       avcodec_close (data->codecctx);
+       av_free (data->codecctx);
++      av_free (data->read_out_buffer);
+ 
+       g_string_free (data->outbuf, TRUE);
+       g_free (data->buffer);
+@@ -132,6 +136,9 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->buffer_size = AVCODEC_BUFFER_SIZE;
+       data->codecctx = NULL;
+ 
++      data->read_out_buffer = av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
++      data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
++
+       xmms_xform_private_data_set (xform, data);
+ 
+       avcodec_init ();
+@@ -196,7 +203,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+               } else {
+                       /* A demuxer plugin forgot to give decoder config? */
+                       xmms_log_error ("Decoder config data not found!");
+-                      return FALSE;
++                      goto err;
+               }
+       }
+ 
+@@ -220,7 +227,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+ 
+               /* 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...");
+@@ -251,6 +258,9 @@ err:
+       if (data->codecctx) {
+               av_free (data->codecctx);
+       }
++      if (data->read_out_buffer) {
++              av_free (data->read_out_buffer);
++      }
+       g_string_free (data->outbuf, TRUE);
+       g_free (data->extradata);
+       g_free (data);
+@@ -263,8 +273,7 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t 
*buf, gint len,
+                    xmms_error_t *error)
+ {
+       xmms_avcodec_data_t *data;
+-      char outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+-      gint outbufsize, bytes_read = 0;
++      gint bytes_read = 0;
+       guint size;
+ 
+       data = xmms_xform_private_data_get (xform);
+@@ -330,9 +339,9 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t 
*buf, gint len,
+               packet.data = data->buffer;
+               packet.size = data->buffer_length;
+ 
+-              outbufsize = sizeof (outbuf);
+-              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
outbuf,
+-                                                  &outbufsize, &packet);
++              data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
++              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
data->read_out_buffer,
++                                                  
&data->read_out_buffer_size, &packet);
+ 
+               /* The DTS decoder of ffmpeg is buggy and always returns
+                * the input buffer length, get frame length from header */
+@@ -354,8 +363,8 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t 
*buf, gint len,
+ 
+               data->buffer_length -= bytes_read;
+ 
+-              if (outbufsize > 0) {
+-                      g_string_append_len (data->outbuf, outbuf, outbufsize);
++              if (data->read_out_buffer_size > 0) {
++                      g_string_append_len (data->outbuf, 
data->read_out_buffer, data->read_out_buffer_size);
+               }
+ 
+               size = MIN (data->outbuf->len, len);
+@@ -371,8 +380,7 @@ static gint64
+ 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[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+-      gint outbufsize, bytes_read = 0;
++      gint bytes_read = 0;
+       gint64 ret = -1;
+ 
+       g_return_val_if_fail (xform, -1);
+@@ -396,9 +404,9 @@ xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, 
xmms_xform_seek_mode_t w
+               packet.data = data->buffer;
+               packet.size = data->buffer_length;
+ 
+-              outbufsize = sizeof (outbuf);
+-              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
outbuf,
+-                                                  &outbufsize, &packet);
++              data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
++              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
data->read_out_buffer,
++                                                  
&data->read_out_buffer_size, &packet);
+ 
+               if (bytes_read < 0 || bytes_read > data->buffer_length) {
+                       XMMS_DBG ("Error decoding data!");

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p2.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p2.patch
new file mode 100644
index 0000000..46b5b1d
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p2.patch
@@ -0,0 +1,171 @@
+commit b614459dc1ea353d6c24b4a77c7f92a5577d5bc3
+Author: Uli Franke <[email protected]>
+Date:   Thu Jan 19 11:53:57 2012 +0100
+
+    BUG(2510): Add more bitrates/samplerates to AAC/ALAC.
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index 1b4a659..b32de4d 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -60,6 +60,7 @@ 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
+@@ -168,12 +169,12 @@ xmms_avcodec_init (xmms_xform_t *xform)
+               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);
+@@ -238,12 +239,17 @@ xmms_avcodec_init (xmms_xform_t *xform)
+ 
+       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,
+@@ -428,3 +434,23 @@ xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, 
xmms_xform_seek_mode_t w
+ 
+       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:
++              return XMMS_SAMPLE_FORMAT_U8;
++      case AV_SAMPLE_FMT_S16:
++              return XMMS_SAMPLE_FORMAT_S16;
++      case AV_SAMPLE_FMT_S32:
++              return XMMS_SAMPLE_FORMAT_S32;
++      case AV_SAMPLE_FMT_FLT:
++              return XMMS_SAMPLE_FORMAT_FLOAT;
++      case AV_SAMPLE_FMT_DBL:
++              return XMMS_SAMPLE_FORMAT_DOUBLE;
++      default:
++              XMMS_DBG ("AVSampleFormat (%i) not supported.", 
av_sample_format);
++              return XMMS_SAMPLE_FORMAT_UNKNOWN;
++      }
++}
+diff --git a/src/plugins/mp4/mp4.c b/src/plugins/mp4/mp4.c
+index 7c915c4..3ee9357 100644
+--- a/src/plugins/mp4/mp4.c
++++ b/src/plugins/mp4/mp4.c
+@@ -186,9 +186,6 @@ xmms_mp4_init (xmms_xform_t *xform)
+       xmms_xform_auxdata_set_bin (xform, "decoder_config", tmpbuf, tmpbuflen);
+       g_free (tmpbuf);
+ 
+-      /* This is only for ALAC to set 16-bit samples, ignored for AAC */
+-      xmms_xform_auxdata_set_int (xform, "samplebits", 16);
+-
+       xmms_mp4_get_mediainfo (xform);
+ 
+       XMMS_DBG ("MP4 demuxer inited successfully!");
+@@ -288,7 +285,7 @@ xmms_mp4_get_mediainfo (xmms_xform_t *xform)
+       data = xmms_xform_private_data_get (xform);
+       g_return_if_fail (data);
+ 
+-      if ((temp = mp4ff_get_sample_rate (data->mp4ff, data->track)) >= 0) {
++      if ((temp = mp4ff_get_sample_rate (data->mp4ff, data->track)) > 0) {
+               glong srate = temp;
+ 
+               if ((temp = mp4ff_get_track_duration_use_offsets (data->mp4ff,
+@@ -492,7 +489,7 @@ xmms_mp4_get_track (xmms_xform_t *xform, mp4ff_t *infile)
+               case 0x69: /* MPEG-2 audio */
+               case 0x6B: /* MPEG-1 audio */
+                       continue;
+-              case 0xff:
++              case 0xff: /* ALAC */
+                       chans = mp4ff_get_channel_count (infile, i);
+                       rate = mp4ff_get_sample_rate (infile, i);
+                       if (chans <= 0 || rate <= 0) {
+diff --git a/src/plugins/mp4/mp4ff/README.xmms2 
b/src/plugins/mp4/mp4ff/README.xmms2
+index c2737c5..8021618 100644
+--- a/src/plugins/mp4/mp4ff/README.xmms2
++++ b/src/plugins/mp4/mp4ff/README.xmms2
+@@ -12,3 +12,4 @@ Changes:
+  * Add value_length variable to tag type and use it when adding new 
item-value pairs,
+    necessary for cover art since it's binary data and can't be handled as a 
string
+  * Add support for Apple Lossless audio files
++ * Add a workaround for supporting higher samplerates.
+diff --git a/src/plugins/mp4/mp4ff/mp4ff.c b/src/plugins/mp4/mp4ff/mp4ff.c
+index ee7f7fb..b6f0a37 100644
+--- a/src/plugins/mp4/mp4ff/mp4ff.c
++++ b/src/plugins/mp4/mp4ff/mp4ff.c
+@@ -32,6 +32,8 @@
+ #include <string.h>
+ #include "mp4ffint.h"
+ 
++static uint32_t mp4ff_normalize_flawed_sample_rate (uint16_t samplerate);
++
+ mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f)
+ {
+     mp4ff_t *ff = malloc(sizeof(mp4ff_t));
+@@ -304,12 +306,39 @@ int32_t mp4ff_num_samples(const mp4ff_t *f, const 
int32_t track)
+     return total;
+ }
+ 
++static uint32_t
++mp4ff_normalize_flawed_sample_rate (uint16_t samplerate)
++{
++      /* A list of common rates can be found at
++       * http://en.wikipedia.org/wiki/Sampling_rate */
++      uint32_t rates[] = {8000, 11025, 16000, 22050, 32000, 44056, 44100,
++                        47250, 48000, 50000, 50400, 88200, 96000, 176400,
++                        192000, 352800, 384000, 0};
++      uint32_t* rate;
++
++      /* First check standard rates. */
++      for (rate = rates; *rate; rate++) {
++              if (*rate == samplerate) {
++                      return *rate;
++              }
++      }
++
++      /* No standard rates matching - check if sample rate got truncated when
++       * added to MP4 container */
++      for (rate = rates; *rate; rate++) {
++              if ((*rate & 0x0000FFFF) == samplerate) {
++                      return *rate;
++              }
++      }
+ 
++      /* Failed to find a standard rate - we give up returning the original 
rate */
++      return samplerate;
++}
+ 
+ 
+ uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track)
+ {
+-      return f->track[track]->sampleRate;
++      return mp4ff_normalize_flawed_sample_rate (f->track[track]->sampleRate);
+ }
+ 
+ uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track)

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p3.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p3.patch
new file mode 100644
index 0000000..a9145c0
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p3.patch
@@ -0,0 +1,388 @@
+commit 4d0682030e20a8ed218f4ff924554f93d276d9ee
+Author: Anthony Garcia <[email protected]>
+Date:   Thu Apr 22 16:59:37 2010 -0700
+
+    OTHER: Cleanup
+    
+    Re-enabled nellymoser (ffmpeg appears to be okay with it now)
+    
+    Fixed possible infinite loop in the code that handles the data (if any)
+    between the header and tag data.
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index 6c9fea8..5554056 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -90,7 +90,7 @@ xmms_avcodec_plugin_setup (xmms_xform_plugin_t *xform_plugin)
+       xmms_magic_add ("A/52 (AC-3) header", "audio/x-ffmpeg-ac3",
+                       "0 beshort 0x0b77", NULL);
+       xmms_magic_add ("DTS header", "audio/x-ffmpeg-dca",
+-                      "0 belong 0x7ffe8001", NULL); 
++                      "0 belong 0x7ffe8001", NULL);
+ 
+       xmms_xform_plugin_indata_add (xform_plugin,
+                                     XMMS_STREAM_TYPE_MIMETYPE,
+@@ -197,7 +197,8 @@ xmms_avcodec_init (xmms_xform_t *xform)
+                   !strcmp (data->codec_id, "adpcm_swf") ||
+                   !strcmp (data->codec_id, "pcm_s16le") ||
+                   !strcmp (data->codec_id, "ac3") ||
+-                  !strcmp (data->codec_id, "dca")) {
++                  !strcmp (data->codec_id, "dca") ||
++                  !strcmp (data->codec_id, "nellymoser")) {
+                       /* number 1024 taken from libavformat raw.c 
RAW_PACKET_SIZE */
+                       data->extradata = g_malloc0 (1024);
+                       data->extradata_size = 1024;
+diff --git a/src/plugins/flv/flv.c b/src/plugins/flv/flv.c
+index 440010c..266fea6 100644
+--- a/src/plugins/flv/flv.c
++++ b/src/plugins/flv/flv.c
+@@ -25,29 +25,41 @@
+  * and other info, then data
+  */
+ #define FLV_TAG_SIZE 11
+-/* random constant */
+ #define FLV_CHUNK_SIZE 4096
+ 
+-/* let libavcodec take care of swapping sample bytes */
+-static const gchar *mime_pcm_s16le = "audio/x-ffmpeg-pcm_s16le";
+-static const gchar *fmt_mime[11] = {
+-      /* Supported when samples are 8 bit
+-       * (otherwise there's no way of knowing endianness)
+-       */
+-      "audio/pcm",
+-      "audio/x-ffmpeg-adpcm_swf",
+-      "audio/mpeg",
+-      /* if bps is 8 bit u8
+-       * if bps is 16 bit sle16
+-       */
+-      "audio/pcm",
+-      /* libavcodec can't handle nelly without dying yet */
+-      /*"audio/x-ffmpeg-nellymoser",
+-      "audio/x-ffmpeg-nellymoser",
+-      "audio/x-ffmpeg-nellymoser",*/
+-      "", "", "",
+-      "", "", "",
+-      "audio/aac"
++typedef enum {
++      /* Only u8 bit samples since
++         there's no way to determine endianness
++      */
++      CODEC_PCM_HOST,
++      CODEC_ADPCM,
++      CODEC_MP3,
++      /* 8 bps: unsigned
++         16 bps: signed
++      */
++      CODEC_PCM_LE,
++      CODEC_NELLYMOSER_16K,
++      CODEC_NELLYMOSER_8K,
++      /* Uses the sample rate in
++         the tag as normal
++      */
++      CODEC_NELLYMOSER,
++      CODEC_AAC = 10
++} xmms_flv_codec_id;
++
++struct xmms_flv_codec_table {
++      xmms_flv_codec_id id;
++      const gchar *mime;
++} static flv_codecs[] = {
++      {CODEC_PCM_HOST, "audio/pcm"},
++      {CODEC_ADPCM, "audio/x-ffmpeg-adpcm_swf"},
++      {CODEC_MP3, "audio/mpeg"},
++      /* Will be audio/x-ffmpeg-pcm_s16le if bps is 16 */
++      {CODEC_PCM_LE, "audio/pcm"},
++      {CODEC_NELLYMOSER_16K, "audio/x-ffmpeg-nellymoser"},
++      {CODEC_NELLYMOSER_8K, "audio/x-ffmpeg-nellymoser"},
++      {CODEC_NELLYMOSER, "audio/x-ffmpeg-nellymoser"},
++      {CODEC_AAC, "audio/aac"}
+ };
+ 
+ typedef struct {
+@@ -111,23 +123,26 @@ static gboolean
+ xmms_flv_init (xmms_xform_t *xform)
+ {
+       xmms_sample_format_t bps;
+-      gint readret;
++      gint readret, i;
+       guint8 channels, flags, format;
+-      guint8 header[FLV_TAG_SIZE + 5];
+-      const gchar *mime;
++      guint8 header[FLV_TAG_SIZE + 1];
+       guint32 dataoffset, samplerate;
+       xmms_error_t err;
+       xmms_flv_data_t *flvdata;
++      struct xmms_flv_codec_table *codec = NULL;
++
++      flvdata = g_new0 (xmms_flv_data_t, 1);
++      xmms_xform_private_data_set (xform, flvdata);
+ 
+       readret = xmms_xform_read (xform, header, FLV_HDR_SIZE, &err);
+       if (readret != FLV_HDR_SIZE) {
+               xmms_log_error ("Header read error");
+-              return FALSE;
++              goto init_err;
+       }
+ 
+       if ((header[4] & HAS_AUDIO) != HAS_AUDIO) {
+               xmms_log_error ("FLV has no audio stream");
+-              return FALSE;
++              goto init_err;
+       }
+ 
+       dataoffset = get_be32 (&header[5]) - FLV_HDR_SIZE;
+@@ -140,7 +155,7 @@ xmms_flv_init (xmms_xform_t *xform)
+                                          dataoffset : FLV_HDR_SIZE, &err);
+               if (readret <= 0) {
+                       xmms_log_error ("Error reading header:tag body gap");
+-                      return FALSE;
++                      goto init_err;
+               }
+ 
+               dataoffset -= readret;
+@@ -148,86 +163,99 @@ xmms_flv_init (xmms_xform_t *xform)
+ 
+       if (next_audio_tag (xform) <= 0) {
+               xmms_log_error ("Can't find first audio tag");
+-              return FALSE;
++              goto init_err;
+       }
+ 
+-      if (xmms_xform_peek (xform, header, FLV_TAG_SIZE + 5, &err) < 
FLV_TAG_SIZE + 5) {
++      if (xmms_xform_read (xform, header, FLV_TAG_SIZE + 1, &err) < 
FLV_TAG_SIZE + 1) {
+               xmms_log_error ("Can't read first audio tag");
+-              return FALSE;
++              goto init_err;
+       }
+ 
+-      flags = header[FLV_TAG_SIZE + 4];
++      flags = header[11];
+       XMMS_DBG ("Audio flags: %X", flags);
+ 
+-      switch (flags&12) {
+-              case 0: samplerate = 5512; break;
+-              case 4: samplerate = 11025; break;
+-              case 8: samplerate = 22050; break;
+-              case 12: samplerate = 44100; break;
+-              default: samplerate = 8000; break;
++      format = flags >> 4;
++      for (i = 0; i < G_N_ELEMENTS (flv_codecs); i++) {
++              if (flv_codecs[i].id == format) {
++                      codec = &flv_codecs[i];
++                      break;
++              }
+       }
+ 
+-      if (flags&2) {
+-              bps = XMMS_SAMPLE_FORMAT_S16;
++      if (flags & 1) {
++              channels = 2;
+       } else {
+-              bps = XMMS_SAMPLE_FORMAT_U8;
++              channels = 1;
+       }
+ 
+-      if (flags&1) {
+-              channels = 2;
++      if (flags & 2) {
++              bps = XMMS_SAMPLE_FORMAT_S16;
+       } else {
+-              channels = 1;
++              bps = XMMS_SAMPLE_FORMAT_U8;
+       }
+ 
+-      format = flags >> 4;
+-      mime = (format <= 10)? fmt_mime[format] : NULL;
+-      switch (format) {
+-              case 0:
+-                      /* If the flv has an HE PCM audio stream, the
+-                       * samples must be unsigned and 8 bits long
+-                       */
+-                      if (bps != XMMS_SAMPLE_FORMAT_U8) {
+-                              xmms_log_error ("Only u8 HE PCM is supported");
+-                              return FALSE;
+-                      }
+-                      break;
+-              case 3:
+-                      if (bps == XMMS_SAMPLE_FORMAT_S16) {
+-                              mime = mime_pcm_s16le;
+-                      }
+-                      break;
++      switch ((flags & 12) >> 2) {
++              case 0: samplerate = 5512; break;
++              case 1: samplerate = 11025; break;
++              case 2: samplerate = 22050; break;
++              case 3: samplerate = 44100; break;
++              default: samplerate = 8000; break;
+       }
+ 
+-      if (mime && *mime) {
+-              flvdata = g_new0 (xmms_flv_data_t, 1);
++      if (codec) {
++              switch (codec->id) {
++                      case CODEC_PCM_HOST:
++                              if (bps != XMMS_SAMPLE_FORMAT_U8) {
++                                      xmms_log_error ("Only u8 HE PCM is 
supported");
++                                      goto init_err;
++                              }
++                              break;
++                      case CODEC_PCM_LE:
++                              if (bps == XMMS_SAMPLE_FORMAT_S16) {
++                                      codec->mime = 
"audio/x-ffmpeg-pcm_s16le";
++                              }
++                              break;
++                      case CODEC_NELLYMOSER_16K:
++                              samplerate = 16000;
++                              break;
++                      case CODEC_NELLYMOSER_8K:
++                              samplerate = 8000;
++                              break;
++                      default:
++                              break;
++              }
++
+               flvdata->format = format;
++              flvdata->last_datasize = get_be24 (&header[1]) - 1;
+ 
+               XMMS_DBG ("Rate: %d, bps: %d, channels: %d", samplerate,
+                         bps, channels);
+ 
+-              xmms_xform_private_data_set (xform, flvdata);
+               xmms_xform_outdata_type_add (xform,
+                                            XMMS_STREAM_TYPE_MIMETYPE,
+-                                           mime,
+-                                           XMMS_STREAM_TYPE_FMT_SAMPLERATE,
+-                                           samplerate,
+-                                           XMMS_STREAM_TYPE_FMT_FORMAT,
+-                                           bps,
+-                                           XMMS_STREAM_TYPE_FMT_CHANNELS,
+-                                           channels,
+-                                           XMMS_STREAM_TYPE_END);
++                                           codec->mime,
++                                           XMMS_STREAM_TYPE_FMT_SAMPLERATE,
++                                           samplerate,
++                                           XMMS_STREAM_TYPE_FMT_FORMAT,
++                                           bps,
++                                           XMMS_STREAM_TYPE_FMT_CHANNELS,
++                                           channels,
++                                           XMMS_STREAM_TYPE_END);
+               return TRUE;
+       } else {
+               xmms_log_error ("Unsupported audio format");
+-              return FALSE;
+       }
++
++init_err:
++      g_free (flvdata);
++      return FALSE;
+ }
+ 
+ static gint
+ xmms_flv_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, 
xmms_error_t *err)
+ {
+-      gint ret = 0, thismuch = FLV_TAG_SIZE + 5;
+-      guint8 header[FLV_TAG_SIZE + 6], gap = 1;
++      gint ret = 0, thismuch = FLV_TAG_SIZE + 1;
++      guint8 header[FLV_TAG_SIZE + 1];
+       xmms_flv_data_t *data = NULL;
+ 
+       data = xmms_xform_private_data_get (xform);
+@@ -236,12 +264,8 @@ xmms_flv_read (xmms_xform_t *xform, xmms_sample_t *buf, 
gint len, xmms_error_t *
+               xmms_xform_auxdata_barrier (xform);
+               ret = next_audio_tag (xform);
+               if (ret > 0) {
+-                      if (data->format == 10) {
+-                              thismuch++;
+-                              gap++;
+-                      }
+                       if (xmms_xform_read (xform, header, thismuch, err) == 
thismuch) {
+-                              data->last_datasize = get_be24 (&header[5]) - 
gap;
++                              data->last_datasize = get_be24 (&header[1]) - 1;
+                       } else {
+                               xmms_log_error ("Need %d bytes", thismuch);
+                               return -1;
+@@ -280,40 +304,51 @@ xmms_flv_destroy (xmms_xform_t *xform)
+ static gint
+ next_audio_tag (xmms_xform_t *xform)
+ {
+-      guint8 header[FLV_TAG_SIZE + 4];
++      guint8 header[FLV_TAG_SIZE];
+       guint8 dumb[FLV_CHUNK_SIZE];
+       gint ret = 0;
+       xmms_error_t err;
+-      guint32 datasize = 0;
++      xmms_flv_data_t *data;
++
++      data = xmms_xform_private_data_get (xform);
+ 
+       do {
+-              /* there's a last 4 bytes at the end of an FLV giving the final
+-               * tag's size, this isn't an error
+-               */
+-              ret = xmms_xform_peek (xform, header, FLV_TAG_SIZE + 4, &err);
+-              if ((ret < FLV_TAG_SIZE) && (ret > -1)) {
+-                      ret = 0;
+-                      break;
+-              } else if (ret == -1) {
+-                      xmms_log_error ("%s", xmms_error_message_get (&err));
+-                      break;
+-              }
++              /* If > 0 assume we're in the middle of a tag's data */
++              if (!data->last_datasize) {
++                      /* There are 4 bytes before an actual tag giving
++                         the previous tag's size. The first size in an
++                         flv is always 0.
++                      */
++                      if (xmms_xform_read (xform, header, 4, &err) != 4) {
++                              xmms_log_error ("Couldn't read last tag size");
++                              return -1;
++                      }
+ 
+-              if (header[4] == 8) {
+-                      /* woo audio tag! */
+-                      break;
+-              }
++                      ret = xmms_xform_peek (xform, header, FLV_TAG_SIZE, 
&err);
++                      if ((ret < FLV_TAG_SIZE) && (ret > -1)) {
++                              return 0;
++                      } else if (ret == -1) {
++                              xmms_log_error ("%s", xmms_error_message_get 
(&err));
++                              return ret;
++                      }
++
++                      if (header[0] == 8) {
++                              /* woo audio tag! */
++                              break;
++                      }
+ 
+-              ret = xmms_xform_read (xform, header, FLV_TAG_SIZE + 4, &err);
+-              if (ret <= 0) { return ret; }
++                      if ((ret = xmms_xform_read (xform, header, 
FLV_TAG_SIZE, &err)) <= 0) {
++                              return ret;
++                      }
+ 
+-              datasize = get_be24 (&header[5]);
++                      data->last_datasize = get_be24 (&header[1]);
++              }
+ 
+-              while (datasize) {
++              while (data->last_datasize) {
+                       ret = xmms_xform_read (xform, dumb,
+-                                               (datasize < FLV_CHUNK_SIZE) ?
+-                                               datasize : FLV_CHUNK_SIZE,
+-                                               &err);
++                                             (data->last_datasize < 
FLV_CHUNK_SIZE) ?
++                                             data->last_datasize : 
FLV_CHUNK_SIZE,
++                                             &err);
+                       if (ret == 0) {
+                               xmms_log_error ("Data field short!");
+                               break;
+@@ -323,7 +358,7 @@ next_audio_tag (xmms_xform_t *xform)
+                               break;
+                       }
+ 
+-                      datasize -= ret;
++                      data->last_datasize -= ret;
+               }
+ 
+       } while (ret);

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p4.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p4.patch
new file mode 100644
index 0000000..552f202
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p4.patch
@@ -0,0 +1,296 @@
+commit 4198d9bf5dff517740ed51b22313367f156107e1
+Author: Erik Massop <[email protected]>
+Date:   Sun Dec 22 17:19:30 2013 +0100
+
+    OTHER: Split xmms_avcodec_read, remove some duplicate code
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index 5b9b606..eed7964 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -57,6 +57,9 @@ typedef struct {
+ 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,
+@@ -281,101 +284,24 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t 
*buf, gint len,
+                    xmms_error_t *error)
+ {
+       xmms_avcodec_data_t *data;
+-      gint 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;
+-                      }
+-
+-                      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;
+-              }
+-
+-              packet.data = data->buffer;
+-              packet.size = data->buffer_length;
+-
+-              data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+-              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
data->read_out_buffer,
+-                                                  
&data->read_out_buffer_size, &packet);
++                      gint bytes_read;
+ 
+-              /* 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;
++                      bytes_read = xmms_avcodec_internal_read_some (xform, 
data, error);
++                      if (bytes_read <= 0) { return bytes_read; }
+               }
+ 
+-              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 (data->read_out_buffer_size > 0) {
+-                      g_string_append_len (data->outbuf, 
data->read_out_buffer, data->read_out_buffer_size);
+-              }
+-
+-              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);
+@@ -388,7 +314,6 @@ static gint64
+ xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, 
xmms_xform_seek_mode_t whence, xmms_error_t *err)
+ {
+       xmms_avcodec_data_t *data;
+-      gint bytes_read = 0;
+       gint64 ret = -1;
+ 
+       g_return_val_if_fail (xform, -1);
+@@ -406,23 +331,11 @@ xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, 
xmms_xform_seek_mode_t w
+ 
+       /* 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;
+-
+-              data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+-              bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) 
data->read_out_buffer,
+-                                                  
&data->read_out_buffer_size, &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);
+@@ -456,3 +369,131 @@ xmms_avcodec_translate_sample_format (enum 
AVSampleFormat 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_buffer. Number of bytes in data->read_out_buffer
++is stored in data->read_out_buffer_size.
++
++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)
++{
++      gint bytes_read = 0;
++      AVPacket packet;
++
++      av_init_packet (&packet);
++      packet.data = data->buffer;
++      packet.size = data->buffer_length;
++
++      data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
++      bytes_read = avcodec_decode_audio3 (data->codecctx,
++                                          (short *) data->read_out_buffer,
++                                          &data->read_out_buffer_size, 
&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 data->read_out_buffer_size;
++}
++
++static void
++xmms_avcodec_internal_append (xmms_avcodec_data_t *data)
++{
++      g_string_append_len (data->outbuf,
++                           (gchar *) data->read_out_buffer,
++                           data->read_out_buffer_size);
++}

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p5.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p5.patch
new file mode 100644
index 0000000..8ed5bb4
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p5.patch
@@ -0,0 +1,154 @@
+commit d44312fb14bde0ab47ee6de1b3fe7435d4a97c99
+Author: Erik Massop <[email protected]>
+Date:   Sun Dec 22 20:01:18 2013 +0100
+
+    BUG(2572): Use avcodec_decode_audio4
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index 266a607..a41a675 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -37,8 +37,7 @@ typedef struct {
+       guint buffer_size;
+       gboolean no_demuxer;
+ 
+-      gchar *read_out_buffer;
+-      gint read_out_buffer_size;
++      AVFrame *read_out_frame;
+ 
+       guint channels;
+       guint samplerate;
+@@ -125,7 +124,7 @@ xmms_avcodec_destroy (xmms_xform_t *xform)
+ 
+       avcodec_close (data->codecctx);
+       av_free (data->codecctx);
+-      av_free (data->read_out_buffer);
++      avcodec_free_frame (&data->read_out_frame);
+ 
+       g_string_free (data->outbuf, TRUE);
+       g_free (data->buffer);
+@@ -151,8 +150,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->buffer_size = AVCODEC_BUFFER_SIZE;
+       data->codecctx = NULL;
+ 
+-      data->read_out_buffer = av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
+-      data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
++      data->read_out_frame = avcodec_alloc_frame ();
+ 
+       xmms_xform_private_data_set (xform, data);
+ 
+@@ -233,6 +231,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->codecctx->extradata_size = data->extradata_size;
+       data->codecctx->codec_id = codec->id;
+       data->codecctx->codec_type = codec->type;
++      data->codecctx->refcounted_frames = 0;
+ 
+       if (avcodec_open2 (data->codecctx, codec, NULL) < 0) {
+               XMMS_DBG ("Opening decoder '%s' failed", codec->name);
+@@ -279,8 +278,8 @@ err:
+       if (data->codecctx) {
+               av_free (data->codecctx);
+       }
+-      if (data->read_out_buffer) {
+-              av_free (data->read_out_buffer);
++      if (data->read_out_frame) {
++              avcodec_free_frame (&data->read_out_frame);
+       }
+       g_string_free (data->outbuf, TRUE);
+       g_free (data->extradata);
+@@ -365,17 +364,23 @@ 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) not supported.", 
av_sample_format);
++              XMMS_DBG ("AVSampleFormat (%i: %s) not supported.", 
av_sample_format,
++                        av_get_sample_fmt_name (av_sample_format));
+               return XMMS_SAMPLE_FORMAT_UNKNOWN;
+       }
+ }
+@@ -448,8 +453,7 @@ xmms_avcodec_internal_read_some (xmms_xform_t *xform,
+ 
+ /*
+ Decode some data from data->buffer[0..data->buffer_length-1] to
+-data->read_out_buffer. Number of bytes in data->read_out_buffer
+-is stored in data->read_out_buffer_size.
++data->read_out_frame
+ 
+ Returns: on error: negative
+          on no new data produced: zero
+@@ -461,6 +465,7 @@ 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;
+ 
+@@ -468,10 +473,10 @@ xmms_avcodec_internal_decode_some (xmms_avcodec_data_t 
*data)
+       packet.data = data->buffer;
+       packet.size = data->buffer_length;
+ 
+-      data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+-      bytes_read = avcodec_decode_audio3 (data->codecctx,
+-                                          (short *) data->read_out_buffer,
+-                                          &data->read_out_buffer_size, 
&packet);
++      avcodec_get_frame_defaults (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 */
+@@ -497,13 +502,33 @@ xmms_avcodec_internal_decode_some (xmms_avcodec_data_t 
*data)
+               data->buffer_length = 0;
+       }
+ 
+-      return data->read_out_buffer_size;
++      return got_frame ? 1 : 0;
+ }
+ 
+ static void
+ xmms_avcodec_internal_append (xmms_avcodec_data_t *data)
+ {
+-      g_string_append_len (data->outbuf,
+-                           (gchar *) data->read_out_buffer,
+-                           data->read_out_buffer_size);
++      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 --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p6.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p6.patch
new file mode 100644
index 0000000..b1bc1c5
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p6.patch
@@ -0,0 +1,106 @@
+commit fc66249e69f53eef709c5210546fdd92e1c89554
+Author: Erik Massop <[email protected]>
+Date:   Sun Dec 22 23:04:08 2013 +0100
+
+    OTHER: Some compatibility with different avcodec versions
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index a41a675..023833d 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -124,7 +124,7 @@ xmms_avcodec_destroy (xmms_xform_t *xform)
+ 
+       avcodec_close (data->codecctx);
+       av_free (data->codecctx);
+-      avcodec_free_frame (&data->read_out_frame);
++      av_frame_free (&data->read_out_frame);
+ 
+       g_string_free (data->outbuf, TRUE);
+       g_free (data->buffer);
+@@ -150,7 +150,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->buffer_size = AVCODEC_BUFFER_SIZE;
+       data->codecctx = NULL;
+ 
+-      data->read_out_frame = avcodec_alloc_frame ();
++      data->read_out_frame = av_frame_alloc ();
+ 
+       xmms_xform_private_data_set (xform, data);
+ 
+@@ -231,7 +231,6 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->codecctx->extradata_size = data->extradata_size;
+       data->codecctx->codec_id = codec->id;
+       data->codecctx->codec_type = codec->type;
+-      data->codecctx->refcounted_frames = 0;
+ 
+       if (avcodec_open2 (data->codecctx, codec, NULL) < 0) {
+               XMMS_DBG ("Opening decoder '%s' failed", codec->name);
+@@ -473,7 +472,8 @@ xmms_avcodec_internal_decode_some (xmms_avcodec_data_t 
*data)
+       packet.data = data->buffer;
+       packet.size = data->buffer_length;
+ 
+-      avcodec_get_frame_defaults (data->read_out_frame);
++      /* 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);
+diff --git a/src/plugins/avcodec/avcodec_compat.h 
b/src/plugins/avcodec/avcodec_compat.h
+index 73ac2ab..e74b3f8 100644
+--- a/src/plugins/avcodec/avcodec_compat.h
++++ b/src/plugins/avcodec/avcodec_compat.h
+@@ -83,3 +83,17 @@ typedef struct AVPacket {
+ # 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 --git a/src/plugins/avcodec/wscript b/src/plugins/avcodec/wscript
+index 03ba7d8..d367816 100644
+--- a/src/plugins/avcodec/wscript
++++ b/src/plugins/avcodec/wscript
+@@ -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"])

diff --git a/media-sound/xmms2/files/xmms2-0.8-audio4-p7.patch 
b/media-sound/xmms2/files/xmms2-0.8-audio4-p7.patch
new file mode 100644
index 0000000..2d4bafd
--- /dev/null
+++ b/media-sound/xmms2/files/xmms2-0.8-audio4-p7.patch
@@ -0,0 +1,147 @@
+commit f460440b3f2a9db1a9deef3faf7dae6e626dd7b5
+Author: Erik Massop <[email protected]>
+Date:   Sun Dec 22 23:34:12 2013 +0100
+
+    OTHER: Require avcodec_decode_audio4
+    
+    This was introduced in versions 53.40.0 (ffmpeg) and 53.25.0 (libav) of
+    avcodec. Hence we drop compatibility for earlier versions.
+
+diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
+index 023833d..6d0b667 100644
+--- a/src/plugins/avcodec/avcodec.c
++++ b/src/plugins/avcodec/avcodec.c
+@@ -154,7 +154,6 @@ xmms_avcodec_init (xmms_xform_t *xform)
+ 
+       xmms_xform_private_data_set (xform, data);
+ 
+-      avcodec_init ();
+       avcodec_register_all ();
+ 
+       mimetype = xmms_xform_indata_get_str (xform,
+@@ -225,7 +224,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
+       data->codecctx->sample_rate = data->samplerate;
+       data->codecctx->channels = data->channels;
+       data->codecctx->bit_rate = data->bitrate;
+-      CONTEXT_BPS (data->codecctx) = data->samplebits;
++      data->codecctx->bits_per_coded_sample = data->samplebits;
+       data->codecctx->block_align = data->block_align;
+       data->codecctx->extradata = data->extradata;
+       data->codecctx->extradata_size = data->extradata_size;
+diff --git a/src/plugins/avcodec/avcodec_compat.h 
b/src/plugins/avcodec/avcodec_compat.h
+index e74b3f8..b50fa4b 100644
+--- a/src/plugins/avcodec/avcodec_compat.h
++++ b/src/plugins/avcodec/avcodec_compat.h
+@@ -21,69 +21,6 @@
+ # include "avcodec.h"
+ #endif
+ 
+-/* Map avcodec_decode_audio2 into the deprecated version
+- * avcodec_decode_audio in versions earlier than 51.28 */
+-#if LIBAVCODEC_VERSION_INT < 0x331c00
+-# define avcodec_decode_audio2 avcodec_decode_audio
+-#endif
+-
+-/* Handle API change that happened in libavcodec 52.00 */
+-#if LIBAVCODEC_VERSION_INT < 0x340000
+-# define CONTEXT_BPS(codecctx) (codecctx)->bits_per_sample
+-#else
+-# define CONTEXT_BPS(codecctx) (codecctx)->bits_per_coded_sample
+-#endif
+-
+-/* Before 52.23 AVPacket was defined in avformat.h which we
+- * do not want to depend on, so we define part of it manually
+- * on versions smaller than 52.23 (this makes me cry) */
+-#if LIBAVCODEC_VERSION_INT < 0x341700
+-typedef struct AVPacket {
+-        uint8_t *data;
+-        int size;
+-} AVPacket;
+-#endif
+-
+-/* Same thing as above for av_init_packet and version 52.25 */
+-#if LIBAVCODEC_VERSION_INT < 0x341900
+-# define av_init_packet(pkt) do { \
+-    (pkt)->data = NULL; \
+-    (pkt)->size = 0; \
+-  } while(0)
+-#endif
+-
+-/* Map avcodec_decode_audio3 into the deprecated version
+- * avcodec_decode_audio2 in versions earlier than 52.26 */
+-#if LIBAVCODEC_VERSION_INT < 0x341a00
+-# define avcodec_decode_audio3(avctx, samples, frame_size_ptr, avpkt) \
+-    avcodec_decode_audio2(avctx, samples, frame_size_ptr, \
+-                          (avpkt)->data, (avpkt)->size)
+-#endif
+-
+-/* Handle API change that happened in libavcodec 52.64 */
+-#if LIBAVCODEC_VERSION_INT < 0x344000
+-# 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
+diff --git a/src/plugins/avcodec/wscript b/src/plugins/avcodec/wscript
+index d367816..00b182b 100644
+--- a/src/plugins/avcodec/wscript
++++ b/src/plugins/avcodec/wscript
+@@ -1,6 +1,24 @@
+ from waftools.plugin import plugin
+ 
+ ## Code fragments for configuration
++avcodec_decode_audio4_fragment = """
++#ifdef HAVE_LIBAVCODEC_AVCODEC_H
++# include "libavcodec/avcodec.h"
++#else
++# include "avcodec.h"
++#endif
++int main(void) {
++    AVCodecContext *ctx;
++    AVFrame *frame;
++    int got_frame;
++    AVPacket *pkt;
++
++    avcodec_decode_audio4 (ctx, frame, &got_frame, pkt);
++
++    return 0;
++}
++"""
++
+ avcodec_free_frame_fragment = """
+ #ifdef HAVE_LIBAVCODEC_AVCODEC_H
+ # include "libavcodec/avcodec.h"
+@@ -22,6 +40,13 @@ def plugin_configure(conf):
+     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)
+ 
++    # mandatory function avcodec_decode_audio4 available since
++    # * ffmpeg: commit e4de716, lavc 53.40.0, release 0.9
++    # * libav: commit 0eea212, lavc 53.25.0, release 0.8
++    conf.check_cc(fragment=avcodec_decode_audio4_fragment, uselib="avcodec",
++                  uselib_store="avcodec_decode_audio4",
++                  msg="Checking for function avcodec_decode_audio4", 
mandatory=True)
++
+     # 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

diff --git a/media-sound/xmms2/xmms2-0.8-r2.ebuild 
b/media-sound/xmms2/xmms2-0.8-r2.ebuild
index 4661d2d4..4500c37 100644
--- a/media-sound/xmms2/xmms2-0.8-r2.ebuild
+++ b/media-sound/xmms2/xmms2-0.8-r2.ebuild
@@ -116,6 +116,13 @@ src_prepare() {
        epatch "${FILESDIR}/${P}"-ffmpeg2.patch #536232
        epatch "${FILESDIR}/${P}"-cpython.patch
        epatch "${FILESDIR}/${P}"-modpug.patch #536046
+       epatch "${FILESDIR}/${P}"-audio4-p1.patch
+       epatch "${FILESDIR}/${P}"-audio4-p2.patch
+       epatch "${FILESDIR}/${P}"-audio4-p3.patch
+       epatch "${FILESDIR}/${P}"-audio4-p4.patch
+       epatch "${FILESDIR}/${P}"-audio4-p5.patch
+       epatch "${FILESDIR}/${P}"-audio4-p6.patch
+       epatch "${FILESDIR}/${P}"-audio4-p7.patch
 
        if has_version dev-libs/libcdio-paranoia; then
                sed -i -e 's:cdio/cdda.h:cdio/paranoia/cdda.h:' 
src/plugins/cdda/cdda.c || die

Reply via email to