diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index 9439bfa771..e9cc5d4ed9 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -216,9 +216,9 @@ typedef struct WMAProDecodeCtx {
     GetBitContext    gb;                            ///< bitstream reader context
     int              buf_bit_size;                  ///< buffer size in bits
     uint8_t          drc_gain;                      ///< gain for the DRC tool
-    int8_t           skip_frame;                    ///< skip output step
     int8_t           parsed_all_subframes;          ///< all subframes decoded?
     uint8_t          skip_packets;                  ///< packets to skip to find next packet in a stream (XMA1/2)
+    int8_t           eof_done;                      ///< set when EOF reached and extra subframe is written (XMA1/2)
 
     /* subframe/block decode state */
     int16_t          subframe_len;                  ///< current subframe length
@@ -379,12 +379,6 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu
         return AVERROR_PATCHWELCOME;
     }
 
-    /** frame info */
-    if (avctx->codec_id != AV_CODEC_ID_WMAPRO)
-        s->skip_frame = 0;
-    else
-        s->skip_frame = 1; /* skip first frame */
-
     s->packet_loss = 1;
     s->len_prefix  = (s->decode_flags & 0x40);
 
@@ -1450,21 +1444,34 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr)
         ff_dlog(s->avctx, "drc_gain %i\n", s->drc_gain);
     }
 
-    /** no idea what these are for, might be the number of samples
-        that need to be skipped at the beginning or end of a stream */
+    /** read encoder delay/padding (gapless) info */
     if (get_bits1(gb)) {
-        int av_unused skip;
+        int start_skip, end_skip;
+
 
-        /** usually true for the first frame */
+        /** usually true for the first frame and equal to 1 frame */
         if (get_bits1(gb)) {
-            skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
-            ff_dlog(s->avctx, "start skip: %i\n", skip);
+            start_skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
+            start_skip = FFMIN(start_skip, s->samples_per_frame);
+
+            /* must add for XMA to respect starting skip_samples */
+            s->avctx->internal->skip_samples += start_skip;
         }
 
-        /** sometimes true for the last frame */
+        /** usually true for the last frame and less than 1 frame */
         if (get_bits1(gb)) {
-            skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
-            ff_dlog(s->avctx, "end skip: %i\n", skip);
+            end_skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
+            end_skip = FFMIN(end_skip, s->samples_per_frame);
+
+            if (s->avctx->codec_id == AV_CODEC_ID_WMAPRO) {
+                frame->nb_samples = s->samples_per_frame - end_skip;
+            }
+
+            //TODO XMA end skip (needs changes in multistream's handling)
+            /* for XMA this skip seems to consider last frame + extra subframe,
+             * and (unlike WMAPRO?) files may have only 1 packet. Last packet
+             * nb_samples would be: 512 + 128 - start_skip - end_skip
+             * (theoretically skips happen anywhere, test more_frames too) */
         }
 
     }
@@ -1500,13 +1507,9 @@ static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr)
                s->samples_per_frame * sizeof(*s->channel[i].out) >> 1);
     }
 
-    if (s->skip_frame) {
-        s->skip_frame = 0;
-        *got_frame_ptr = 0;
-        av_frame_unref(frame);
-    } else {
-        *got_frame_ptr = 1;
-    }
+    /** frame may be partially discarded with gapless info in the bitstream */
+    *got_frame_ptr = 1;
+
 
     if (s->len_prefix) {
         if (len != (get_bits_count(gb) - s->frame_offset) + 2) {
@@ -1609,7 +1612,33 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s,
 
     *got_frame_ptr = 0;
 
-    if (s->packet_done || s->packet_loss) {
+    if (!buf_size) {
+        AVFrame *frame = data;
+        int i;
+
+        /** XMA must output one extra subframe after stream end with
+         * remaining samples (WMAPRO encoder adds padding instead). */
+        s->packet_done = 0;
+        if (s->eof_done || avctx->codec_id == AV_CODEC_ID_WMAPRO)
+            return 0;
+
+        /** clean output buffer and copy last IMCDT samples */
+        for (i = 0; i < s->nb_channels; i++) {
+            memset(frame->extended_data[i], 0,
+            s->samples_per_frame * sizeof(*s->channel[i].out));
+
+            memcpy(frame->extended_data[i], s->channel[i].out,
+                   s->samples_per_frame * sizeof(*s->channel[i].out) >> 1);
+        }
+        /* TODO: should output 128 samples only, but needs changes in
+         * multi-stream handling, so currently writes full 512 samples. */
+
+        s->eof_done = 1;
+        s->packet_done = 1;
+        *got_frame_ptr = 1;
+        return 0;
+    }
+    else if (s->packet_done || s->packet_loss) {
         s->packet_done = 0;
 
         /** sanity check for the buffer length */
@@ -1896,6 +1925,12 @@ static av_cold int xma_decode_init(AVCodecContext *avctx)
         start_channels += s->xma[i].nb_channels;
     }
 
+    /** XMA seems to require this to create gapless files (WMAPRO encoder
+     * pads files with silence, while XMA can encode any nb_samples).
+     * This value seems to counter the extra subframe output at EOF
+     * (or perhaps, XMA decoder should output 64 samples earlier?) */
+    avctx->internal->skip_samples = 128/2;
+
     return ret;
 }
 
@@ -1922,6 +1957,7 @@ static void flush(WMAProDecodeCtx *s)
                sizeof(*s->channel[i].out));
     s->packet_loss = 1;
     s->skip_packets = 0;
+    s->eof_done = 0;
 }
 
 
@@ -1934,6 +1970,8 @@ static void wmapro_flush(AVCodecContext *avctx)
     WMAProDecodeCtx *s = avctx->priv_data;
 
     flush(s);
+
+    avctx->internal->skip_samples = 0;
 }
 
 static void xma_flush(AVCodecContext *avctx)
@@ -1946,6 +1984,8 @@ static void xma_flush(AVCodecContext *avctx)
 
     memset(s->offset, 0, sizeof(s->offset));
     s->current_stream = 0;
+
+    avctx->internal->skip_samples = 128/2;
 }
 
 
@@ -1976,7 +2016,7 @@ AVCodec ff_xma1_decoder = {
     .init           = xma_decode_init,
     .close          = xma_decode_end,
     .decode         = xma_decode_packet,
-    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
 };
@@ -1991,7 +2031,7 @@ AVCodec ff_xma2_decoder = {
     .close          = xma_decode_end,
     .decode         = xma_decode_packet,
     .flush          = xma_flush,
-    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
 };
