diff --git a/Changelog b/Changelog
index 21a4be731b..ff2db9e083 100644
--- a/Changelog
+++ b/Changelog
@@ -37,6 +37,7 @@ version <next>:
 - Cintel RAW decoder
 - VDPAU accelerated VP9 10/12bit decoding
 - afreqshift and aphaseshift filters
+- Microsoft Paint (MSP) version 2 decoder
 
 
 version 4.3:
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 9c49d8c01a..5de2e1cfb6 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -507,6 +507,7 @@ OBJS-$(CONFIG_MSMPEG4V2_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V2_ENCODER)       += msmpeg4enc.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V3_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4enc.o msmpeg4.o msmpeg4data.o
+OBJS-$(CONFIG_MSP2_DECODER)            += msp2dec.o
 OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o
 OBJS-$(CONFIG_MSS1_DECODER)            += mss1.o mss12.o
 OBJS-$(CONFIG_MSS2_DECODER)            += mss2.o mss12.o mss2dsp.o wmv2data.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 82dee16973..5b13423ca3 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -215,6 +215,7 @@ extern AVCodec ff_msmpeg4v2_decoder;
 extern AVCodec ff_msmpeg4v3_encoder;
 extern AVCodec ff_msmpeg4v3_decoder;
 extern AVCodec ff_msmpeg4_crystalhd_decoder;
+extern AVCodec ff_msp2_decoder;
 extern AVCodec ff_msrle_decoder;
 extern AVCodec ff_mss1_decoder;
 extern AVCodec ff_mss2_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 3b148883b8..40a5a9a9e5 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1419,6 +1419,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_MSP2,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "msp2",
+        .long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+    },
     {
         .id        = AV_CODEC_ID_Y41P,
         .type      = AVMEDIA_TYPE_VIDEO,
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 668c565788..6133e03bb9 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -243,6 +243,7 @@ enum AVCodecID {
     AV_CODEC_ID_AVS2,
     AV_CODEC_ID_PGX,
     AV_CODEC_ID_AVS3,
+    AV_CODEC_ID_MSP2,
 
     AV_CODEC_ID_Y41P = 0x8000,
     AV_CODEC_ID_AVRP,
diff --git a/libavcodec/msp2dec.c b/libavcodec/msp2dec.c
new file mode 100644
index 0000000000..cc548d218a
--- /dev/null
+++ b/libavcodec/msp2dec.c
@@ -0,0 +1,102 @@
+/*
+ * Microsoft Paint (MSP) version 2 decoder
+ * Copyright (c) 2020 Peter Ross (pross@xvid.org)
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * Microsoft Paint (MSP) version 2 decoder
+ */
+
+#include "avcodec.h"
+#include "bytestream.h"
+#include "internal.h"
+
+static int msp2_decode_frame(AVCodecContext *avctx,
+                            void *data, int *got_frame,
+                            AVPacket *avpkt)
+{
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+    AVFrame *p         = data;
+    int ret;
+    unsigned int x, y, width = (avctx->width + 7) / 8;
+    GetByteContext idx, gb;
+
+    if (buf_size <= 2 * avctx->height)
+        return AVERROR_INVALIDDATA;
+
+    avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
+
+    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
+        return ret;
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+
+    bytestream2_init(&idx, buf, 2 * avctx->height);
+    buf += 2 * avctx->height;
+    buf_size -= 2 * avctx->height;
+
+    for (y = 0; y < avctx->height; y++) {
+        unsigned int pkt_size = bytestream2_get_le16(&idx);
+        if (!pkt_size) {
+            memset(p->data[0] + y * p->linesize[0], 0xFF, width);
+            continue;
+        }
+
+        if (pkt_size > buf_size) {
+            av_log(avctx, AV_LOG_WARNING, "image probably corrupt\n");
+            pkt_size = buf_size;
+        }
+
+        bytestream2_init(&gb, buf, pkt_size);
+        x = 0;
+        while (bytestream2_get_bytes_left(&gb) && x < width) {
+            int size = bytestream2_get_byte(&gb);
+            if (size) {
+                memcpy(p->data[0] + y * p->linesize[0] + x, gb.buffer, FFMIN(size, width - x));
+                bytestream2_skip(&gb, size);
+            } else {
+                int value;
+                size = bytestream2_get_byte(&gb);
+                if (!size)
+                    avpriv_request_sample(avctx, "escape value");
+                value = bytestream2_get_byte(&gb);
+                memset(p->data[0] + y * p->linesize[0] + x, value, FFMIN(size, width - x));
+            }
+            x += size;
+        }
+
+        buf += pkt_size;
+        buf_size -= pkt_size;
+    }
+
+    *got_frame = 1;
+    return buf_size;
+}
+
+AVCodec ff_msp2_decoder = {
+    .name           = "msp2",
+    .long_name      = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_MSP2,
+    .decode         = msp2_decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+};
