diff mbox series

[FFmpeg-devel,2/3] avcodec/msp2dec: Microsoft Paint (MSP) version 2 decoder

Message ID c9de5f8127550fe67f76e98a3dee1b12bedfcf76.1602154882.git.pross@xvid.org
State New
Headers show
Series [FFmpeg-devel,1/3] avformat/mspdec: Microsoft Paint (MSP) demuxer | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Peter Ross Oct. 8, 2020, 11:02 a.m. UTC
Signed-off-by: Peter Ross <pross@xvid.org>
---
 Changelog               |   1 +
 libavcodec/Makefile     |   1 +
 libavcodec/allcodecs.c  |   1 +
 libavcodec/codec_desc.c |   7 +++
 libavcodec/codec_id.h   |   1 +
 libavcodec/msp2dec.c    | 100 ++++++++++++++++++++++++++++++++++++++++
 libavformat/mspdec.c    |   8 ++--
 7 files changed, 114 insertions(+), 5 deletions(-)
 create mode 100644 libavcodec/msp2dec.c

Comments

Paul B Mahol Oct. 8, 2020, 12:43 p.m. UTC | #1
On Thu, Oct 08, 2020 at 10:02:32PM +1100, Peter Ross wrote:
> Signed-off-by: Peter Ross <pross@xvid.org>
> ---
>  Changelog               |   1 +
>  libavcodec/Makefile     |   1 +
>  libavcodec/allcodecs.c  |   1 +
>  libavcodec/codec_desc.c |   7 +++
>  libavcodec/codec_id.h   |   1 +
>  libavcodec/msp2dec.c    | 100 ++++++++++++++++++++++++++++++++++++++++
>  libavformat/mspdec.c    |   8 ++--
>  7 files changed, 114 insertions(+), 5 deletions(-)
>  create mode 100644 libavcodec/msp2dec.c
> 
> diff --git a/Changelog b/Changelog
> index 84690791af..3d81e52e86 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -36,6 +36,7 @@ version <next>:
>  - AVS3 video decoder via libuavs3d
>  - Cintel RAW decoder
>  - Microsoft Paint (MSP) demuxer
> +- Microsoft Paint (MSP) version 2 decoder
>  
>  

This unfortunately always assumes that pixel format is set in demuxer.

This is not correct, therefore patch is not acceptable.
diff mbox series

Patch

diff --git a/Changelog b/Changelog
index 84690791af..3d81e52e86 100644
--- a/Changelog
+++ b/Changelog
@@ -36,6 +36,7 @@  version <next>:
 - AVS3 video decoder via libuavs3d
 - Cintel RAW decoder
 - Microsoft Paint (MSP) demuxer
+- Microsoft Paint (MSP) version 2 decoder
 
 
 version 4.3:
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 2af93586dc..f307b1c7d0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -506,6 +506,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 fb8b2ad035..486175ecc6 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..8ea7cf3238
--- /dev/null
+++ b/libavcodec/msp2dec.c
@@ -0,0 +1,100 @@ 
+/*
+ * 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;
+
+    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,
+};
diff --git a/libavformat/mspdec.c b/libavformat/mspdec.c
index 8f67a82424..005cb045d7 100644
--- a/libavformat/mspdec.c
+++ b/libavformat/mspdec.c
@@ -34,7 +34,7 @@  static int msp_probe(const AVProbeData *p)
 {
     unsigned int i, sum;
 
-    if (p->buf_size <= 32 || memcmp(p->buf, "DanM", 4))
+    if (p->buf_size <= 32 || (memcmp(p->buf, "DanM", 4) && memcmp(p->buf, "LinS", 4)))
         return 0;
 
     sum = 0;
@@ -54,10 +54,9 @@  static int msp_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    avio_skip(pb, 4);
-
     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codecpar->codec_id = s->iformat->raw_codec_id;
+    st->codecpar->codec_id = avio_rl32(pb) == MKTAG('D', 'a', 'n', 'M') ? AV_CODEC_ID_RAWVIDEO : AV_CODEC_ID_MSP2;
+
     st->codecpar->width  = avio_rl16(pb);
     st->codecpar->height = avio_rl16(pb);
     st->codecpar->format = AV_PIX_FMT_MONOBLACK;
@@ -90,6 +89,5 @@  AVInputFormat ff_msp_demuxer = {
     .read_header  = msp_read_header,
     .read_packet  = msp_read_packet,
     .flags        = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK,
-    .raw_codec_id = AV_CODEC_ID_RAWVIDEO,
     .priv_data_size = sizeof(FFRawDemuxerContext),
 };