diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 054fa0a73dd4304853ad9f3d83172c346992f1eb..2dc3e6b50dc0308b6c8f2af7eeef973a0fa6d555 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -134,7 +134,26 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     default:
         break;
     }
-    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+
+    switch(avctx->codec->id) {
+        case AV_CODEC_ID_ADPCM_IMA_QT:
+        case AV_CODEC_ID_ADPCM_IMA_WAV:
+        case AV_CODEC_ID_ADPCM_4XM:
+        case AV_CODEC_ID_ADPCM_XA:
+        case AV_CODEC_ID_ADPCM_EA_R1:
+        case AV_CODEC_ID_ADPCM_EA_R2:
+        case AV_CODEC_ID_ADPCM_EA_R3:
+        case AV_CODEC_ID_ADPCM_EA_XAS:
+        case AV_CODEC_ID_ADPCM_THP:
+            avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
+            break;
+        case AV_CODEC_ID_ADPCM_IMA_WS:
+            avctx->sample_fmt = c->vqa_version == 3 ? AV_SAMPLE_FMT_S16P :
+                                                      AV_SAMPLE_FMT_S16;
+            break;
+        default:
+            avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+    }
 
     avcodec_get_frame_defaults(&c->frame);
     avctx->coded_frame = &c->frame;
@@ -264,17 +283,22 @@ static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned c
     return c->predictor;
 }
 
-static int xa_decode(AVCodecContext *avctx,
-                     short *out, const unsigned char *in,
-                     ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
+static int xa_decode(AVCodecContext *avctx, int16_t *out0, int16_t *out1,
+                     const uint8_t *in, ADPCMChannelStatus *left,
+                     ADPCMChannelStatus *right, int channels, int sample_offset)
 {
     int i, j;
     int shift,filter,f0,f1;
     int s_1,s_2;
     int d,s,t;
 
-    for(i=0;i<4;i++) {
+    out0 += sample_offset;
+    if (channels == 1)
+        out1 = out0 + 28;
+    else
+        out1 += sample_offset;
 
+    for(i=0;i<4;i++) {
         shift  = 12 - (in[4+i*2] & 15);
         filter = in[4+i*2] >> 4;
         if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) {
@@ -294,16 +318,14 @@ static int xa_decode(AVCodecContext *avctx,
             s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
             s_2 = s_1;
             s_1 = av_clip_int16(s);
-            *out = s_1;
-            out += inc;
+            out0[j] = s_1;
         }
 
-        if (inc==2) { /* stereo */
+        if (channels == 2) {
             left->sample1 = s_1;
             left->sample2 = s_2;
             s_1 = right->sample1;
             s_2 = right->sample2;
-            out = out + 1 - 28*2;
         }
 
         shift  = 12 - (in[5+i*2] & 15);
@@ -323,18 +345,19 @@ static int xa_decode(AVCodecContext *avctx,
             s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
             s_2 = s_1;
             s_1 = av_clip_int16(s);
-            *out = s_1;
-            out += inc;
+            out1[j] = s_1;
         }
 
-        if (inc==2) { /* stereo */
+        if (channels == 2) {
             right->sample1 = s_1;
             right->sample2 = s_2;
-            out -= 1;
         } else {
             left->sample1 = s_1;
             left->sample2 = s_2;
         }
+
+        out0 += 28 * (3 - channels);
+        out1 += 28 * (3 - channels);
     }
 
     return 0;
@@ -573,6 +596,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     ADPCMChannelStatus *cs;
     int n, m, channel, i;
     short *samples;
+    int16_t **samples_p;
     int st; /* stereo */
     int count1, count2;
     int nb_samples, coded_samples, ret;
@@ -592,6 +616,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         return ret;
     }
     samples = (short *)c->frame.data[0];
+    samples_p = (int16_t **)c->frame.extended_data;
 
     /* use coded_samples when applicable */
     /* it is always <= nb_samples, so the output buffer will be large enough */
@@ -636,21 +661,19 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
                 return AVERROR_INVALIDDATA;
             }
 
-            samples = (short *)c->frame.data[0] + channel;
+            samples = samples_p[channel];
 
-            for (m = 0; m < 32; m++) {
+            for (m = 0; m < 64; m += 2) {
                 int byte = bytestream2_get_byteu(&gb);
-                *samples = adpcm_ima_qt_expand_nibble(cs, byte & 0x0F, 3);
-                samples += avctx->channels;
-                *samples = adpcm_ima_qt_expand_nibble(cs, byte >> 4  , 3);
-                samples += avctx->channels;
+                samples[m    ] = adpcm_ima_qt_expand_nibble(cs, byte & 0x0F, 3);
+                samples[m + 1] = adpcm_ima_qt_expand_nibble(cs, byte >> 4  , 3);
             }
         }
         break;
     case AV_CODEC_ID_ADPCM_IMA_WAV:
         for(i=0; i<avctx->channels; i++){
             cs = &(c->status[i]);
-            cs->predictor = *samples++ = sign_extend(bytestream2_get_le16u(&gb), 16);
+            cs->predictor = samples_p[i][0] = sign_extend(bytestream2_get_le16u(&gb), 16);
 
             cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16);
             if (cs->step_index > 88u){
@@ -660,19 +683,16 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
             }
         }
 
-        for (n = (nb_samples - 1) / 8; n > 0; n--) {
+        for (n = 0; n < (nb_samples - 1) / 8; n++) {
             for (i = 0; i < avctx->channels; i++) {
                 cs = &c->status[i];
-                for (m = 0; m < 4; m++) {
+                samples = &samples_p[i][1 + n * 8];
+                for (m = 0; m < 8; m += 2) {
                     int v = bytestream2_get_byteu(&gb);
-                    *samples = adpcm_ima_expand_nibble(cs, v & 0x0F, 3);
-                    samples += avctx->channels;
-                    *samples = adpcm_ima_expand_nibble(cs, v >> 4  , 3);
-                    samples += avctx->channels;
+                    samples[m    ] = adpcm_ima_expand_nibble(cs, v & 0x0F, 3);
+                    samples[m + 1] = adpcm_ima_expand_nibble(cs, v >> 4  , 3);
                 }
-                samples -= 8 * avctx->channels - 1;
             }
-            samples += 7 * avctx->channels;
         }
         break;
     case AV_CODEC_ID_ADPCM_4XM:
@@ -689,14 +709,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
 
         for (i = 0; i < avctx->channels; i++) {
-            samples = (short *)c->frame.data[0] + i;
+            samples = (int16_t *)c->frame.data[i];
             cs = &c->status[i];
             for (n = nb_samples >> 1; n > 0; n--) {
                 int v = bytestream2_get_byteu(&gb);
-                *samples = adpcm_ima_expand_nibble(cs, v & 0x0F, 4);
-                samples += avctx->channels;
-                *samples = adpcm_ima_expand_nibble(cs, v >> 4  , 4);
-                samples += avctx->channels;
+                *samples++ = adpcm_ima_expand_nibble(cs, v & 0x0F, 4);
+                *samples++ = adpcm_ima_expand_nibble(cs, v >> 4  , 4);
             }
         }
         break;
@@ -858,14 +876,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     case AV_CODEC_ID_ADPCM_IMA_WS:
         if (c->vqa_version == 3) {
             for (channel = 0; channel < avctx->channels; channel++) {
-                int16_t *smp = samples + channel;
+                int16_t *smp = samples_p[channel];
 
                 for (n = nb_samples / 2; n > 0; n--) {
                     int v = bytestream2_get_byteu(&gb);
-                    *smp = adpcm_ima_expand_nibble(&c->status[channel], v >> 4  , 3);
-                    smp += avctx->channels;
-                    *smp = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3);
-                    smp += avctx->channels;
+                    *smp++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4  , 3);
+                    *smp++ = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3);
                 }
             }
         } else {
@@ -881,14 +897,21 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         bytestream2_seek(&gb, 0, SEEK_END);
         break;
     case AV_CODEC_ID_ADPCM_XA:
+    {
+        int16_t *out0 = samples_p[0];
+        int16_t *out1 = samples_p[1];
+        int samples_per_block = 28 * (3 - avctx->channels) * 4;
+        int sample_offset = 0;
         while (bytestream2_get_bytes_left(&gb) >= 128) {
-            if ((ret = xa_decode(avctx, samples, buf + bytestream2_tell(&gb), &c->status[0],
-                                 &c->status[1], avctx->channels)) < 0)
+            if ((ret = xa_decode(avctx, out0, out1, buf + bytestream2_tell(&gb),
+                                 &c->status[0], &c->status[1],
+                                 avctx->channels, sample_offset)) < 0)
                 return ret;
             bytestream2_skipu(&gb, 128);
-            samples += 28 * 8;
+            sample_offset += samples_per_block;
         }
         break;
+    }
     case AV_CODEC_ID_ADPCM_IMA_EA_EACS:
         for (i=0; i<=st; i++) {
             c->status[i].step_index = bytestream2_get_le32u(&gb);
@@ -1022,7 +1045,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
         for (channel=0; channel<avctx->channels; channel++) {
             bytestream2_seek(&gb, offsets[channel], SEEK_SET);
-            samplesC = samples + channel;
+            samplesC = samples_p[channel];
 
             if (avctx->codec->id == AV_CODEC_ID_ADPCM_EA_R1) {
                 current_sample  = sign_extend(bytestream2_get_le16(&gb), 16);
@@ -1038,10 +1061,8 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
                     current_sample  = sign_extend(bytestream2_get_be16(&gb), 16);
                     previous_sample = sign_extend(bytestream2_get_be16(&gb), 16);
 
-                    for (count2=0; count2<28; count2++) {
-                        *samplesC = sign_extend(bytestream2_get_be16(&gb), 16);
-                        samplesC += avctx->channels;
-                    }
+                    for (count2=0; count2<28; count2++)
+                        *samplesC++ = sign_extend(bytestream2_get_be16(&gb), 16);
                 } else {
                     coeff1 = ea_adpcm_table[ byte >> 4     ];
                     coeff2 = ea_adpcm_table[(byte >> 4) + 4];
@@ -1061,8 +1082,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
                         previous_sample = current_sample;
                         current_sample  = next_sample;
-                        *samplesC = current_sample;
-                        samplesC += avctx->channels;
+                        *samplesC++ = current_sample;
                     }
                 }
             }
@@ -1086,8 +1106,8 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     case AV_CODEC_ID_ADPCM_EA_XAS:
         for (channel=0; channel<avctx->channels; channel++) {
             int coeff[2][4], shift[4];
-            short *s2, *s = &samples[channel];
-            for (n=0; n<4; n++, s+=32*avctx->channels) {
+            int16_t *s = samples_p[channel];
+            for (n = 0; n < 4; n++, s += 32) {
                 int val = sign_extend(bytestream2_get_le16u(&gb), 16);
                 for (i=0; i<2; i++)
                     coeff[i][n] = ea_adpcm_table[(val&0x0F)+4*i];
@@ -1095,19 +1115,22 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
                 val = sign_extend(bytestream2_get_le16u(&gb), 16);
                 shift[n] = 20 - (val & 0x0F);
-                s[avctx->channels] = val & ~0x0F;
+                s[1] = val & ~0x0F;
             }
 
             for (m=2; m<32; m+=2) {
-                s = &samples[m*avctx->channels + channel];
-                for (n=0; n<4; n++, s+=32*avctx->channels) {
+                s = &samples_p[channel][m];
+                for (n = 0; n < 4; n++, s += 32) {
+                    int level, pred;
                     int byte = bytestream2_get_byteu(&gb);
-                    for (s2=s, i=0; i<8; i+=4, s2+=avctx->channels) {
-                        int level = sign_extend(byte >> (4 - i), 4) << shift[n];
-                        int pred  = s2[-1*avctx->channels] * coeff[0][n]
-                                  + s2[-2*avctx->channels] * coeff[1][n];
-                        s2[0] = av_clip_int16((level + pred + 0x80) >> 8);
-                    }
+
+                    level = sign_extend(byte >> 4, 4) << shift[n];
+                    pred  = s[-1] * coeff[0][n] + s[-2] * coeff[1][n];
+                    s[0]  = av_clip_int16((level + pred + 0x80) >> 8);
+
+                    level = sign_extend(byte, 4) << shift[n];
+                    pred  = s[0] * coeff[0][n] + s[-1] * coeff[1][n];
+                    s[1]  = av_clip_int16((level + pred + 0x80) >> 8);
                 }
             }
         }
@@ -1221,7 +1244,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
                 prev[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16);
 
         for (ch = 0; ch <= st; ch++) {
-            samples = (short *)c->frame.data[0] + ch;
+            samples = samples_p[ch];
 
             /* Read in every sample for this channel.  */
             for (i = 0; i < nb_samples / 14; i++) {
@@ -1247,10 +1270,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
                     *samples = av_clip_int16(sampledat);
                     prev[ch][1] = prev[ch][0];
                     prev[ch][0] = *samples++;
-
-                    /* In case of stereo, skip one sample, this sample
-                       is for the other channel.  */
-                    samples += st;
                 }
             }
         }
@@ -1270,6 +1289,11 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
 static const enum AVSampleFormat sample_fmts_s16[]  = { AV_SAMPLE_FMT_S16,
                                                         AV_SAMPLE_FMT_NONE };
+static const enum AVSampleFormat sample_fmts_s16p[] = { AV_SAMPLE_FMT_S16,
+                                                        AV_SAMPLE_FMT_NONE };
+static const enum AVSampleFormat sample_fmts_both[] = { AV_SAMPLE_FMT_S16,
+                                                        AV_SAMPLE_FMT_S16P,
+                                                        AV_SAMPLE_FMT_NONE };
 
 #define ADPCM_DECODER(id_, sample_fmts_, name_, long_name_) \
 AVCodec ff_ ## name_ ## _decoder = {                        \
@@ -1285,14 +1309,14 @@ AVCodec ff_ ## name_ ## _decoder = {                        \
 }
 
 /* Note: Do not forget to add new entries to the Makefile as well. */
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM,         sample_fmts_s16,  adpcm_4xm,         "ADPCM 4X Movie");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM,         sample_fmts_s16p, adpcm_4xm,         "ADPCM 4X Movie");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_CT,          sample_fmts_s16,  adpcm_ct,          "ADPCM Creative Technology");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA,          sample_fmts_s16,  adpcm_ea,          "ADPCM Electronic Arts");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_MAXIS_XA, sample_fmts_s16,  adpcm_ea_maxis_xa, "ADPCM Electronic Arts Maxis CDROM XA");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R1,       sample_fmts_s16,  adpcm_ea_r1,       "ADPCM Electronic Arts R1");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R2,       sample_fmts_s16,  adpcm_ea_r2,       "ADPCM Electronic Arts R2");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R3,       sample_fmts_s16,  adpcm_ea_r3,       "ADPCM Electronic Arts R3");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS,      sample_fmts_s16,  adpcm_ea_xas,      "ADPCM Electronic Arts XAS");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R1,       sample_fmts_s16p, adpcm_ea_r1,       "ADPCM Electronic Arts R1");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R2,       sample_fmts_s16p, adpcm_ea_r2,       "ADPCM Electronic Arts R2");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R3,       sample_fmts_s16p, adpcm_ea_r3,       "ADPCM Electronic Arts R3");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS,      sample_fmts_s16p, adpcm_ea_xas,      "ADPCM Electronic Arts XAS");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV,     sample_fmts_s16,  adpcm_ima_amv,     "ADPCM IMA AMV");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC,     sample_fmts_s16,  adpcm_ima_apc,     "ADPCM IMA CRYO APC");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA Duck DK3");
@@ -1300,15 +1324,15 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16,  adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16,  adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS,     sample_fmts_s16,  adpcm_ima_iss,     "ADPCM IMA Funcom ISS");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT,      sample_fmts_s16,  adpcm_ima_qt,      "ADPCM IMA QuickTime");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT,      sample_fmts_s16p, adpcm_ima_qt,      "ADPCM IMA QuickTime");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG,  sample_fmts_s16,  adpcm_ima_smjpeg,  "ADPCM IMA Loki SDL MJPEG");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV,     sample_fmts_s16,  adpcm_ima_wav,     "ADPCM IMA WAV");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS,      sample_fmts_s16,  adpcm_ima_ws,      "ADPCM IMA Westwood");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV,     sample_fmts_s16p, adpcm_ima_wav,     "ADPCM IMA WAV");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS,      sample_fmts_both, adpcm_ima_ws,      "ADPCM IMA Westwood");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS,          sample_fmts_s16,  adpcm_ms,          "ADPCM Microsoft");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_2,     sample_fmts_s16,  adpcm_sbpro_2,     "ADPCM Sound Blaster Pro 2-bit");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_3,     sample_fmts_s16,  adpcm_sbpro_3,     "ADPCM Sound Blaster Pro 2.6-bit");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_4,     sample_fmts_s16,  adpcm_sbpro_4,     "ADPCM Sound Blaster Pro 4-bit");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SWF,         sample_fmts_s16,  adpcm_swf,         "ADPCM Shockwave Flash");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_THP,         sample_fmts_s16,  adpcm_thp,         "ADPCM Nintendo Gamecube THP");
-ADPCM_DECODER(AV_CODEC_ID_ADPCM_XA,          sample_fmts_s16,  adpcm_xa,          "ADPCM CDROM XA");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_THP,         sample_fmts_s16p, adpcm_thp,         "ADPCM Nintendo Gamecube THP");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_XA,          sample_fmts_s16p, adpcm_xa,          "ADPCM CDROM XA");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_YAMAHA,      sample_fmts_s16,  adpcm_yamaha,      "ADPCM Yamaha");
diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c
index 0ac9bce1e40e71c2dd5c47f2622f74e200e39a34..901d717cdfdcb1cb79759ff44e15349c598f55e7 100644
--- a/libavcodec/adxdec.c
+++ b/libavcodec/adxdec.c
@@ -49,7 +49,7 @@ static av_cold int adx_decode_init(AVCodecContext *avctx)
         c->header_parsed = 1;
     }
 
-    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+    avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
 
     avcodec_get_frame_defaults(&c->frame);
     avctx->coded_frame = &c->frame;
@@ -64,7 +64,8 @@ static av_cold int adx_decode_init(AVCodecContext *avctx)
  * 2nd-order LPC filter applied to it to form the output signal for a single
  * channel.
  */
-static int adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch)
+static int adx_decode(ADXContext *c, int16_t *out, int offset,
+                      const uint8_t *in, int ch)
 {
     ADXChannelState *prev = &c->prev[ch];
     GetBitContext gb;
@@ -77,6 +78,7 @@ static int adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch)
         return -1;
 
     init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8);
+    out += offset;
     s1 = prev->s1;
     s2 = prev->s2;
     for (i = 0; i < BLOCK_SAMPLES; i++) {
@@ -84,8 +86,7 @@ static int adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch)
         s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS;
         s2 = s1;
         s1 = av_clip_int16(s0);
-        *out = s1;
-        out += c->channels;
+        *out++ = s1;
     }
     prev->s1 = s1;
     prev->s2 = s2;
@@ -98,7 +99,8 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data,
 {
     int buf_size        = avpkt->size;
     ADXContext *c       = avctx->priv_data;
-    int16_t *samples;
+    int16_t **samples;
+    int samples_offset;
     const uint8_t *buf  = avpkt->data;
     const uint8_t *buf_end = buf + avpkt->size;
     int num_blocks, ch, ret;
@@ -145,11 +147,12 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data,
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
-    samples = (int16_t *)c->frame.data[0];
+    samples = (int16_t **)c->frame.extended_data;
+    samples_offset = 0;
 
     while (num_blocks--) {
         for (ch = 0; ch < c->channels; ch++) {
-            if (buf_end - buf < BLOCK_SIZE || adx_decode(c, samples + ch, buf, ch)) {
+            if (buf_end - buf < BLOCK_SIZE || adx_decode(c, samples[ch], samples_offset, buf, ch)) {
                 c->eof = 1;
                 buf = avpkt->data + avpkt->size;
                 break;
@@ -157,7 +160,7 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data,
             buf_size -= BLOCK_SIZE;
             buf      += BLOCK_SIZE;
         }
-        samples += BLOCK_SAMPLES * c->channels;
+        samples_offset += BLOCK_SAMPLES;
     }
 
     *got_frame_ptr   = 1;
@@ -183,4 +186,6 @@ AVCodec ff_adpcm_adx_decoder = {
     .flush          = adx_decode_flush,
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+                                                      AV_SAMPLE_FMT_NONE },
 };
diff --git a/libavcodec/alpha/Makefile b/libavcodec/alpha/Makefile
index e55fe49b7bdd3b0f3ec31e54bb5f2074f891bdb9..e28200d45a41e428b47b625dbd253a06046003bc 100644
--- a/libavcodec/alpha/Makefile
+++ b/libavcodec/alpha/Makefile
@@ -2,5 +2,6 @@ OBJS += alpha/dsputil_alpha.o                                           \
         alpha/dsputil_alpha_asm.o                                       \
         alpha/motion_est_alpha.o                                        \
         alpha/motion_est_mvi_asm.o                                      \
-        alpha/mpegvideo_alpha.o                                         \
         alpha/simple_idct_alpha.o                                       \
+
+OBJS-$(CONFIG_MPEGVIDEO)                += alpha/mpegvideo_alpha.o
diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile
index 745a5bdfe2414d85f62171135e95fd3f8cfe2be6..f537e4f3e2b260d7a7a21e7c843740797e0a3793 100644
--- a/libavcodec/arm/Makefile
+++ b/libavcodec/arm/Makefile
@@ -14,6 +14,7 @@ OBJS-$(CONFIG_FLAC_DECODER)            += arm/flacdsp_init_arm.o        \
 OBJS-$(CONFIG_MPEGAUDIODSP)            += arm/mpegaudiodsp_init_arm.o
 ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP)      += arm/mpegaudiodsp_fixed_armv6.o
 
+OBJS-$(CONFIG_MPEGVIDEO)               += arm/mpegvideo_arm.o
 OBJS-$(CONFIG_VP3DSP)                  += arm/vp3dsp_init_arm.o
 OBJS-$(CONFIG_VP5_DECODER)             += arm/vp56dsp_init_arm.o
 OBJS-$(CONFIG_VP6_DECODER)             += arm/vp56dsp_init_arm.o
@@ -31,12 +32,12 @@ OBJS                                   += arm/dsputil_init_arm.o        \
                                           arm/fft_fixed_init_arm.o      \
                                           arm/fmtconvert_init_arm.o     \
                                           arm/jrevdct_arm.o             \
-                                          arm/mpegvideo_arm.o           \
                                           arm/simple_idct_arm.o         \
 
-ARMV5TE-OBJS                           += arm/dsputil_init_armv5te.o    \
-                                          arm/mpegvideo_armv5te.o       \
+ARMV5TE-OBJS-$(CONFIG_MPEGVIDEO)       += arm/mpegvideo_armv5te.o       \
                                           arm/mpegvideo_armv5te_s.o     \
+
+ARMV5TE-OBJS                           += arm/dsputil_init_armv5te.o    \
                                           arm/simple_idct_armv5te.o     \
 
 ARMV6-OBJS                             += arm/dsputil_init_armv6.o      \
@@ -70,6 +71,7 @@ NEON-OBJS-$(CONFIG_AAC_DECODER)        += arm/sbrdsp_neon.o             \
 NEON-OBJS-$(CONFIG_DCA_DECODER)        += arm/dcadsp_neon.o             \
                                           arm/synth_filter_neon.o       \
 
+NEON-OBJS-$(CONFIG_MPEGVIDEO)          += arm/mpegvideo_neon.o
 NEON-OBJS-$(CONFIG_RV30_DECODER)       += arm/rv34dsp_init_neon.o       \
                                           arm/rv34dsp_neon.o            \
 
@@ -92,5 +94,4 @@ NEON-OBJS                              += arm/dsputil_init_neon.o       \
                                           arm/dsputil_neon.o            \
                                           arm/fmtconvert_neon.o         \
                                           arm/int_neon.o                \
-                                          arm/mpegvideo_neon.o          \
                                           arm/simple_idct_neon.o        \
diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c
index 669035d15def53e498b2a208b35f86778dbc86e2..86d371e8c894f069b8e4898114f55cfda9a75310 100644
--- a/libavcodec/atrac1.c
+++ b/libavcodec/atrac1.c
@@ -36,7 +36,6 @@
 #include "get_bits.h"
 #include "dsputil.h"
 #include "fft.h"
-#include "fmtconvert.h"
 #include "sinewin.h"
 
 #include "atrac.h"
@@ -80,11 +79,9 @@ typedef struct {
     DECLARE_ALIGNED(32, float,  mid)[256];
     DECLARE_ALIGNED(32, float, high)[512];
     float*              bands[3];
-    float              *out_samples[AT1_MAX_CHANNELS];
     FFTContext          mdct_ctx[3];
     int                 channels;
     DSPContext          dsp;
-    FmtConvertContext   fmt_conv;
 } AT1Ctx;
 
 /** size of the transform in samples in the long mode for each QMF band */
@@ -281,7 +278,6 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data,
     AT1Ctx *q          = avctx->priv_data;
     int ch, ret;
     GetBitContext gb;
-    float *samples;
 
 
     if (buf_size < 212 * q->channels) {
@@ -295,7 +291,6 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data,
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
-    samples = (float *)q->frame.data[0];
 
     for (ch = 0; ch < q->channels; ch++) {
         AT1SUCtx* su = &q->SUs[ch];
@@ -314,13 +309,7 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data,
         ret = at1_imdct_block(su, q);
         if (ret < 0)
             return ret;
-        at1_subband_synthesis(q, su, q->channels == 1 ? samples : q->out_samples[ch]);
-    }
-
-    /* interleave */
-    if (q->channels == 2) {
-        q->fmt_conv.float_interleave(samples, (const float **)q->out_samples,
-                                     AT1_SU_SAMPLES, 2);
+        at1_subband_synthesis(q, su, (float *)q->frame.extended_data[ch]);
     }
 
     *got_frame_ptr   = 1;
@@ -334,8 +323,6 @@ static av_cold int atrac1_decode_end(AVCodecContext * avctx)
 {
     AT1Ctx *q = avctx->priv_data;
 
-    av_freep(&q->out_samples[0]);
-
     ff_mdct_end(&q->mdct_ctx[0]);
     ff_mdct_end(&q->mdct_ctx[1]);
     ff_mdct_end(&q->mdct_ctx[2]);
@@ -349,7 +336,7 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx)
     AT1Ctx *q = avctx->priv_data;
     int ret;
 
-    avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
+    avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
 
     if (avctx->channels < 1 || avctx->channels > AT1_MAX_CHANNELS) {
         av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %d\n",
@@ -358,15 +345,6 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx)
     }
     q->channels = avctx->channels;
 
-    if (avctx->channels == 2) {
-        q->out_samples[0] = av_malloc(2 * AT1_SU_SAMPLES * sizeof(*q->out_samples[0]));
-        q->out_samples[1] = q->out_samples[0] + AT1_SU_SAMPLES;
-        if (!q->out_samples[0]) {
-            av_freep(&q->out_samples[0]);
-            return AVERROR(ENOMEM);
-        }
-    }
-
     /* Init the mdct transforms */
     if ((ret = ff_mdct_init(&q->mdct_ctx[0], 6, 1, -1.0/ (1 << 15))) ||
         (ret = ff_mdct_init(&q->mdct_ctx[1], 8, 1, -1.0/ (1 << 15))) ||
@@ -381,7 +359,6 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx)
     ff_atrac_generate_tables();
 
     ff_dsputil_init(&q->dsp, avctx);
-    ff_fmt_convert_init(&q->fmt_conv, avctx);
 
     q->bands[0] = q->low;
     q->bands[1] = q->mid;
@@ -410,4 +387,6 @@ AVCodec ff_atrac1_decoder = {
     .decode         = atrac1_decode_frame,
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("Atrac 1 (Adaptive TRansform Acoustic Coding)"),
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
+                                                      AV_SAMPLE_FMT_NONE },
 };
diff --git a/libavcodec/bfin/Makefile b/libavcodec/bfin/Makefile
index 6b3e7cf67c0c0051e1ac4c0f3fc2726e11ba0989..be81e6c39a30e84dc2bb7c8a955d6c962ebe0ff6 100644
--- a/libavcodec/bfin/Makefile
+++ b/libavcodec/bfin/Makefile
@@ -1,7 +1,8 @@
 OBJS += bfin/dsputil_bfin.o                                             \
         bfin/fdct_bfin.o                                                \
         bfin/idct_bfin.o                                                \
-        bfin/mpegvideo_bfin.o                                           \
         bfin/pixels_bfin.o                                              \
         bfin/vp3_bfin.o                                                 \
         bfin/vp3_idct_bfin.o                                            \
+
+OBJS-$(CONFIG_MPEGVIDEOENC)             += bfin/mpegvideo_bfin.o
diff --git a/libavcodec/mace.c b/libavcodec/mace.c
index 4c7097943fe1cb0774754ae01c1969936c27dae3..c76f4860631503a6aed34272d7c9b13f228b9510 100644
--- a/libavcodec/mace.c
+++ b/libavcodec/mace.c
@@ -187,9 +187,7 @@ static int16_t read_table(ChannelData *chd, uint8_t val, int tab_idx)
     return current;
 }
 
-static void chomp3(ChannelData *chd, int16_t *output, uint8_t val,
-                   int tab_idx,
-                   uint32_t numChannels)
+static void chomp3(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx)
 {
 
     int16_t current = read_table(chd, val, tab_idx);
@@ -200,9 +198,7 @@ static void chomp3(ChannelData *chd, int16_t *output, uint8_t val,
     *output = QT_8S_2_16S(current);
 }
 
-static void chomp6(ChannelData *chd, int16_t *output, uint8_t val,
-                   int tab_idx,
-                   uint32_t numChannels)
+static void chomp6(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx)
 {
     int16_t current = read_table(chd, val, tab_idx);
 
@@ -222,8 +218,8 @@ static void chomp6(ChannelData *chd, int16_t *output, uint8_t val,
 
     output[0] = QT_8S_2_16S(chd->previous + chd->prev2 -
                             ((chd->prev2-current) >> 2));
-    output[numChannels] = QT_8S_2_16S(chd->previous + current +
-                                      ((chd->prev2-current) >> 2));
+    output[1] = QT_8S_2_16S(chd->previous + current +
+                            ((chd->prev2-current) >> 2));
     chd->prev2 = chd->previous;
     chd->previous = current;
 }
@@ -234,7 +230,7 @@ static av_cold int mace_decode_init(AVCodecContext * avctx)
 
     if (avctx->channels > 2 || avctx->channels <= 0)
         return -1;
-    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+    avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
 
     avcodec_get_frame_defaults(&ctx->frame);
     avctx->coded_frame = &ctx->frame;
@@ -247,7 +243,7 @@ static int mace_decode_frame(AVCodecContext *avctx, void *data,
 {
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
-    int16_t *samples;
+    int16_t **samples;
     MACEContext *ctx = avctx->priv_data;
     int i, j, k, l, ret;
     int is_mace3 = (avctx->codec_id == AV_CODEC_ID_MACE3);
@@ -258,10 +254,10 @@ static int mace_decode_frame(AVCodecContext *avctx, void *data,
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
-    samples = (int16_t *)ctx->frame.data[0];
+    samples = (int16_t **)ctx->frame.extended_data;
 
     for(i = 0; i < avctx->channels; i++) {
-        int16_t *output = samples + i;
+        int16_t *output = samples[i];
 
         for (j=0; j < buf_size / (avctx->channels << is_mace3); j++)
             for (k=0; k < (1 << is_mace3); k++) {
@@ -273,13 +269,11 @@ static int mace_decode_frame(AVCodecContext *avctx, void *data,
 
                 for (l=0; l < 3; l++) {
                     if (is_mace3)
-                        chomp3(&ctx->chd[i], output, val[1][l], l,
-                               avctx->channels);
+                        chomp3(&ctx->chd[i], output, val[1][l], l);
                     else
-                        chomp6(&ctx->chd[i], output, val[0][l], l,
-                               avctx->channels);
+                        chomp6(&ctx->chd[i], output, val[0][l], l);
 
-                    output += avctx->channels << (1-is_mace3);
+                    output += 1 << (1-is_mace3);
                 }
             }
     }
@@ -299,6 +293,8 @@ AVCodec ff_mace3_decoder = {
     .decode         = mace_decode_frame,
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"),
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+                                                      AV_SAMPLE_FMT_NONE },
 };
 
 AVCodec ff_mace6_decoder = {
@@ -310,4 +306,6 @@ AVCodec ff_mace6_decoder = {
     .decode         = mace_decode_frame,
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"),
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+                                                      AV_SAMPLE_FMT_NONE },
 };
diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile
index ff467684298c396120156df29efa3d16c82352b2..8f64f8292af08287d153f4ebae2793555cdc1871 100644
--- a/libavcodec/mips/Makefile
+++ b/libavcodec/mips/Makefile
@@ -1,6 +1,7 @@
 MMI-OBJS += mips/dsputil_mmi.o                                          \
             mips/idct_mmi.o                                             \
-            mips/mpegvideo_mmi.o
+
+MMI-OBJS-$(CONFIG_MPEGVIDEO)            += mips/mpegvideo_mmi.o
 
 MIPSFPU-OBJS-$(CONFIG_AMRNB_DECODER)      += mips/acelp_filters_mips.o     \
                                              mips/celp_filters_mips.o      \
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index cc94a5e247c42e2b7b0567e31aefeb55e6477294..dd626dc58b7a7e9d7a63ecb74ed8e607613f6358 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -446,22 +446,21 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
     {
         int i;
         n /= avctx->channels;
-        //unpack
         for (c = 0; c < avctx->channels; c++) {
-            dst_int32_t = (int32_t *)s->frame.data[c];
+            dst_int32_t = (int32_t *)s->frame.extended_data[c];
             for (i = 0; i < n; i++) {
-                //extract low 20 bits and expand to 32 bits
-                *dst_int32_t++ = (src[2] << 28) |
-                                 (src[1] << 20) |
-                                 (src[0] << 12) |
-                                 ((src[2] & 0xF) << 8) |
-                                 src[1];
-                //extract high 20 bits and expand to 32 bits
-                *dst_int32_t++ = (src[4] << 24) |
-                                 (src[3] << 16) |
-                                 ((src[2] & 0xF0) << 8) |
-                                 (src[4] << 4) |
-                                 (src[3] >> 4);
+                // extract low 20 bits and expand to 32 bits
+                *dst_int32_t++ =  (src[2]         << 28) |
+                                  (src[1]         << 20) |
+                                  (src[0]         << 12) |
+                                 ((src[2] & 0x0F) <<  8) |
+                                   src[1];
+                // extract high 20 bits and expand to 32 bits
+                *dst_int32_t++ =  (src[4]         << 24) |
+                                  (src[3]         << 16) |
+                                 ((src[2] & 0xF0) <<  8) |
+                                  (src[4]         <<  4) |
+                                  (src[3]         >>  4);
                 src += 5;
             }
         }
diff --git a/libavcodec/ppc/Makefile b/libavcodec/ppc/Makefile
index e5d1d39d43f4aa303d6f7e71d77fcf965dad6a63..f7548e375a6f4af3aca9e180edc2bb18a46aca98 100644
--- a/libavcodec/ppc/Makefile
+++ b/libavcodec/ppc/Makefile
@@ -7,6 +7,7 @@ ALTIVEC-OBJS-$(CONFIG_FFT)             += ppc/fft_altivec.o             \
                                           $(FFT-OBJS-yes)
 ALTIVEC-OBJS-$(CONFIG_H264DSP)         += ppc/h264_altivec.o
 ALTIVEC-OBJS-$(CONFIG_MPEGAUDIODSP)    += ppc/mpegaudiodec_altivec.o
+ALTIVEC-OBJS-$(CONFIG_MPEGVIDEO)       += ppc/mpegvideo_altivec.o
 ALTIVEC-OBJS-$(CONFIG_VC1_DECODER)     += ppc/vc1dsp_altivec.o
 ALTIVEC-OBJS-$(CONFIG_VP8_DECODER)     += ppc/vp8dsp_altivec.o
 
@@ -17,4 +18,3 @@ ALTIVEC-OBJS                           += ppc/dsputil_altivec.o         \
                                           ppc/gmc_altivec.o             \
                                           ppc/idct_altivec.o            \
                                           ppc/int_altivec.o             \
-                                          ppc/mpegvideo_altivec.o       \
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 036cbdf7bbc6c5aab2bcc6418ba40683bfc8b717..8b65976806f534dd359d109b45378cc1964025cf 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -393,7 +393,7 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
         if (buf->extended_data[0] && buf_size > buf->audio_data_size) {
             av_free(buf->extended_data[0]);
             if (buf->extended_data != buf->data)
-                av_freep(&buf->extended_data);
+                av_free(buf->extended_data);
             buf->extended_data = NULL;
             buf->data[0]       = NULL;
         }
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 6f8a9faa4b895e432b6c33c7893868b05d106a83..bddd7e17d941ff06c68cd89613617eee954ea533 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -412,7 +412,8 @@ OBJS-$(CONFIG_UDP_PROTOCOL)              += udp.o
 
 SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
 SKIPHEADERS-$(CONFIG_NETWORK)            += network.h rtsp.h
-TESTPROGS = seek
+TESTPROGS = seek                                                        \
+            url                                                         \
 
 TOOLS     = aviocat                                                     \
             ismindex                                                    \
diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c
index 7b16d12dfa0c75fb39848e75f5038f752c66bd4a..a647169e0e5f0aa3bdfdd8a99ac32aeeba4862b4 100644
--- a/libavformat/rtpdec_mpeg4.c
+++ b/libavformat/rtpdec_mpeg4.c
@@ -93,15 +93,7 @@ static PayloadContext *new_context(void)
 
 static void free_context(PayloadContext * data)
 {
-    int i;
-    for (i = 0; i < data->nb_au_headers; i++) {
-         /* according to rtp_parse_mp4_au, we treat multiple
-          * au headers as one, so nb_au_headers is always 1.
-          * loop anyway in case this changes.
-          * (note: changes done carelessly might lead to a double free)
-          */
-       av_free(&data->au_headers[i]);
-    }
+    av_free(data->au_headers);
     av_free(data->mode);
     av_free(data);
 }
diff --git a/libavformat/url-test.c b/libavformat/url-test.c
new file mode 100644
index 0000000000000000000000000000000000000000..ceaffe8e9a92c788e5400de499eec3760d73ba2b
--- /dev/null
+++ b/libavformat/url-test.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "internal.h"
+
+#undef printf
+#undef exit
+
+static void test(const char *base, const char *rel)
+{
+    char buf[200], buf2[200];
+    ff_make_absolute_url(buf, sizeof(buf), base, rel);
+    printf("%s\n", buf);
+    if (base) {
+        /* Test in-buffer replacement */
+        snprintf(buf2, sizeof(buf2), "%s", base);
+        ff_make_absolute_url(buf2, sizeof(buf2), buf2, rel);
+        if (strcmp(buf, buf2)) {
+            printf("In-place handling of %s + %s failed\n", base, rel);
+            exit(1);
+        }
+    }
+}
+
+int main(void)
+{
+    test(NULL, "baz");
+    test("/foo/bar", "baz");
+    test("/foo/bar", "../baz");
+    test("/foo/bar", "/baz");
+    test("http://server/foo/", "baz");
+    test("http://server/foo/bar", "baz");
+    test("http://server/foo/", "../baz");
+    test("http://server/foo/bar/123", "../../baz");
+    test("http://server/foo/bar/123", "/baz");
+    test("http://server/foo/bar/123", "https://other/url");
+    test("http://server/foo/bar?param=value/with/slashes", "/baz");
+    test("http://server/foo/bar?param&otherparam", "?someparam");
+    test("http://server/foo/bar", "//other/url");
+    return 0;
+}
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 4399de76297d0131fd75a99eef986ab61ee3b676..9074f0e2fc8270e3ad1602e3d5b708327fe7257a 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3824,9 +3824,9 @@ void ff_make_absolute_url(char *buf, int size, const char *base,
         sep = strstr(buf, "://");
         if (sep) {
             /* Take scheme from base url */
-            if (rel[1] == '/')
+            if (rel[1] == '/') {
                 sep[1] = '\0';
-            else {
+            } else {
                 /* Take scheme and host from base url */
                 sep += 3;
                 sep = strchr(sep, '/');
diff --git a/tests/Makefile b/tests/Makefile
index f4b58213d4df140ae61c067b8831eaaa384b6637..ac74b44b83c09738fe518c07ecba0fc8d1c1c717 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -69,6 +69,7 @@ include $(SRC_PATH)/tests/fate/h264.mak
 include $(SRC_PATH)/tests/fate/image.mak
 include $(SRC_PATH)/tests/fate/indeo.mak
 include $(SRC_PATH)/tests/fate/libavcodec.mak
+include $(SRC_PATH)/tests/fate/libavformat.mak
 include $(SRC_PATH)/tests/fate/libavutil.mak
 include $(SRC_PATH)/tests/fate/mapchan.mak
 include $(SRC_PATH)/tests/fate/lossless-audio.mak
@@ -108,6 +109,7 @@ FATE-$(CONFIG_FFMPEG) += $(FATE_FFMPEG)
 FATE-$(CONFIG_FFPROBE) += $(FATE_FFPROBE)
 
 FATE-$(CONFIG_AVCODEC)  += $(FATE_LIBAVCODEC)
+FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT)
 
 FATE_EXTERN-$(CONFIG_FFMPEG) += $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG)
 FATE_EXTERN += $(FATE_EXTERN-yes)
diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak
new file mode 100644
index 0000000000000000000000000000000000000000..9e5a9f05b03bae58fd70ec4ae74a7f0c563c3c51
--- /dev/null
+++ b/tests/fate/libavformat.mak
@@ -0,0 +1,5 @@
+FATE_LIBAVFORMAT += fate-url
+fate-url: libavformat/url-test$(EXESUF)
+fate-url: CMD = run libavformat/url-test
+
+fate-libavformat: $(FATE_LIBAVFORMAT)
diff --git a/tests/ref/fate/url b/tests/ref/fate/url
new file mode 100644
index 0000000000000000000000000000000000000000..1a6051ee0fdb940ceb49344e1c03edaf176ed760
--- /dev/null
+++ b/tests/ref/fate/url
@@ -0,0 +1,13 @@
+baz
+/foo/baz
+/baz
+/baz
+http://server/foo/baz
+http://server/foo/baz
+http://server/baz
+http://server/baz
+http://server/baz
+https://other/url
+http://server/baz
+http://server/foo/bar?someparam
+http://other/url