On 2/16/2021 5:24 PM, Anton Khirnov wrote:
It shares very little code with pngdec, so keeping them together only
makes the code harder to read.
---
  libavcodec/Makefile  |   2 +-
  libavcodec/lscrdec.c | 279 +++++++++++++++++++++++++++++++++++++++++++
  libavcodec/png.h     |   5 +
  libavcodec/pngdec.c  | 174 +--------------------------
  4 files changed, 291 insertions(+), 169 deletions(-)
  create mode 100644 libavcodec/lscrdec.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3341801b97..b0c6d675d0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -439,7 +439,7 @@ OBJS-$(CONFIG_KMVC_DECODER)            += kmvc.o
  OBJS-$(CONFIG_LAGARITH_DECODER)        += lagarith.o lagarithrac.o
  OBJS-$(CONFIG_LJPEG_ENCODER)           += ljpegenc.o mjpegenc_common.o
  OBJS-$(CONFIG_LOCO_DECODER)            += loco.o
-OBJS-$(CONFIG_LSCR_DECODER)            += png.o pngdec.o pngdsp.o
+OBJS-$(CONFIG_LSCR_DECODER)            += lscrdec.o png.o pngdec.o pngdsp.o
  OBJS-$(CONFIG_M101_DECODER)            += m101.o
  OBJS-$(CONFIG_MACE3_DECODER)           += mace.o
  OBJS-$(CONFIG_MACE6_DECODER)           += mace.o
diff --git a/libavcodec/lscrdec.c b/libavcodec/lscrdec.c
new file mode 100644
index 0000000000..242ae8fcb2
--- /dev/null
+++ b/libavcodec/lscrdec.c
@@ -0,0 +1,279 @@
+/*
+ * 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 <stdint.h>
+#include <zlib.h>
+
+#include "libavutil/frame.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+
+#include "avcodec.h"
+#include "bytestream.h"
+#include "codec.h"
+#include "internal.h"
+#include "packet.h"
+#include "png.h"
+#include "pngdsp.h"
+
+typedef struct LSCRContext {
+    PNGDSPContext   dsp;
+    AVCodecContext *avctx;
+
+    AVFrame        *last_picture;
+    uint8_t        *buffer;
+    int             buffer_size;
+    uint8_t        *crow_buf;
+    int             crow_size;
+    uint8_t        *last_row;
+    unsigned int    last_row_size;
+
+    GetByteContext  gb;
+    uint8_t        *image_buf;
+    int             image_linesize;
+    int             row_size;
+    int             cur_h;
+    int             y;
+
+    z_stream        zstream;
+} LSCRContext;
+
+static void handle_row(LSCRContext *s, AVFrame *frame)

Unused frame argument.

+{
+    uint8_t *ptr, *last_row;
+
+    ptr = s->image_buf + s->image_linesize * s->y;
+    if (s->y == 0)
+        last_row = s->last_row;
+    else
+        last_row = ptr - s->image_linesize;
+
+    ff_png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,
+                      last_row, s->row_size, 3);
+
+    s->y++;
+}
+
+static int decode_idat(LSCRContext *s, AVFrame *frame, int length)
+{
+    int ret;
+    s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
+    s->zstream.next_in  = s->gb.buffer;
+    bytestream2_skip(&s->gb, length);
+
+    /* decode one line if possible */
+    while (s->zstream.avail_in > 0) {
+        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
+        if (ret != Z_OK && ret != Z_STREAM_END) {
+            av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret);
+            return AVERROR_EXTERNAL;
+        }
+        if (s->zstream.avail_out == 0) {
+            if (s->y < s->cur_h) {
+                handle_row(s, frame);
+            }
+            s->zstream.avail_out = s->crow_size;
+            s->zstream.next_out  = s->crow_buf;
+        }
+        if (ret == Z_STREAM_END && s->zstream.avail_in > 0) {
+            av_log(s->avctx, AV_LOG_WARNING,
+                   "%d undecompressed bytes left in buffer\n", 
s->zstream.avail_in);
+            return 0;
+        }
+    }
+    return 0;
+}
+
+static int decode_frame_lscr(AVCodecContext *avctx,
+                             void *data, int *got_frame,
+                             AVPacket *avpkt)
+{
+    LSCRContext *const s = avctx->priv_data;
+    GetByteContext *gb = &s->gb;
+    AVFrame *frame = data;
+    int ret, nb_blocks, offset = 0;
+
+    if (avpkt->size < 2)
+        return AVERROR_INVALIDDATA;
+    if (avpkt->size == 2)
+        return 0;
+
+    bytestream2_init(gb, avpkt->data, avpkt->size);
+
+    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+        return ret;
+
+    nb_blocks = bytestream2_get_le16(gb);
+    if (bytestream2_get_bytes_left(gb) < 2 + nb_blocks * (12 + 8))
+        return AVERROR_INVALIDDATA;
+
+    if (s->last_picture->data[0]) {
+        ret = av_frame_copy(frame, s->last_picture);

You could use ff_reget_buf() instead. And if nb_blocks can be 0 (meaning no changes since the previous frame), you could even use the FF_REGET_BUFFER_FLAG_READONLY flag and completely avoid any memcpy.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to