From patchwork Fri Apr 12 20:12:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 12711 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 3A1CE44904F for ; Fri, 12 Apr 2019 23:12:58 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0DCBC68AC0E; Fri, 12 Apr 2019 23:12:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f68.google.com (mail-wr1-f68.google.com [209.85.221.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3278268AAC7 for ; Fri, 12 Apr 2019 23:12:52 +0300 (EEST) Received: by mail-wr1-f68.google.com with SMTP id w1so13461086wrp.2 for ; Fri, 12 Apr 2019 13:12:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=dLWA1qafC1mucHeJ5C2YURPD6mnS2V+Q8K2iC8ckEBM=; b=tAMmVhOeuKxfO5MNM27sNyrqqaNtZa+RxcEKloZrdIBiGWyrVjoia3KqMZouXxbpST PCtkvXfC6c/5qot8fqQwXl4NZA1mdeELsM7oUHHyaIIvvWskthcD6Db0jFYCQF5T50gu xl/mK4pCVUcAMoPI3lQIvEWS22g8p4hzsxF/F8kS7gUfawbdmeHsuzWnL+d2SJ3tVCqY Vnbuj+up5EZZZpofD30x1jQMkHXWww07mXN8qOiXatZdqyZkKxDkCJvsTkz9W1evTL9V DAr+QXJr6dPoIrRMW2JTLGGNw5bkrmEiXGmSkvx2YbKbynq42rnjJxiuqABus/xUzdFy +EBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=dLWA1qafC1mucHeJ5C2YURPD6mnS2V+Q8K2iC8ckEBM=; b=pXRznCpUTK+tZJZVmIDHiHqjqOSfelVMCjIKmmJJD1CCh9eOz5DSGSMLCMOBTT7Hzc FBDd5rCyMssLSrNuYsY0oHD4Wp7LSQ6a0qIRh1h27ohUqvL3GYWYaZSa2aRQlvIlObVc BDZ6RG5/EJtyotZMQtyZn+hpsylDA0ze8jO4J5qqHyyvNj4yU7pYmLLb6x+O+eOts8cy IUGugbNVOmG/3TZHuWrr/bp7quTXDKTo5kiHdgoszVm+uwYQo4iTCAroAGrdPjxSVel2 TVo7PknbnxC6Zx+Qg0e7SAuoKPgWisNpEKUssAT14CmOzLLxPFlK3ysvGMQNv53YOqNM 7Lmg== X-Gm-Message-State: APjAAAVeItUQ/nuCo/wh7tKrQGi4w9RBJ8xi4sAO5AQGRY1U12WpHDzm Qv5zh8RJ0AiCPBR5YoWxdTUG1pv6 X-Google-Smtp-Source: APXvYqxiwSjlDsx1bu3NfSj2RMejdaYiOxCkyU8ELjsD7Pz/7HkBf+rB1/bJGMkYH4RzimflqpESzw== X-Received: by 2002:adf:ed8f:: with SMTP id c15mr13201863wro.144.1555099971485; Fri, 12 Apr 2019 13:12:51 -0700 (PDT) Received: from localhost.localdomain ([37.244.238.255]) by smtp.gmail.com with ESMTPSA id r18sm10683671wme.18.2019.04.12.13.12.50 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Apr 2019 13:12:50 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Fri, 12 Apr 2019 22:12:42 +0200 Message-Id: <20190412201242.5219-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] avcodec: add LSCR decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 +++ libavcodec/pngdec.c | 135 ++++++++++++++++++++++++++++++++++++++++ libavformat/riff.c | 1 + 6 files changed, 146 insertions(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2e35681867..f37135fc07 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -413,6 +413,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_M101_DECODER) += m101.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 9ae8a779b3..6178d31b5c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -173,6 +173,7 @@ extern AVCodec ff_kmvc_decoder; extern AVCodec ff_lagarith_decoder; extern AVCodec ff_ljpeg_encoder; extern AVCodec ff_loco_decoder; +extern AVCodec ff_lscr_decoder; extern AVCodec ff_m101_decoder; extern AVCodec ff_magicyuv_encoder; extern AVCodec ff_magicyuv_decoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 4218cff6c4..9e37466641 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -455,6 +455,7 @@ enum AVCodecID { AV_CODEC_ID_HYMT, AV_CODEC_ID_ARBC, AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 8295221d15..621b16e160 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1712,6 +1712,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Amuse Graphics Movie"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_LSCR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "lscr", + .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 189bb9a4c1..c55340a28e 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -1525,6 +1525,123 @@ end: } #endif +#if CONFIG_LSCR_DECODER + +static int decode_frame_lscr(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + PNGDecContext *const s = avctx->priv_data; + GetByteContext *gb = &s->gb; + AVFrame *frame = data; + int ret, nb_blocks, offset = 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 (s->last_picture.f->data[0]) { + ret = av_frame_copy(frame, s->last_picture.f); + if (ret < 0) + return ret; + } + + for (int b = 0; b < nb_blocks; b++) { + uint16_t x, y, x2, y2, w, h; + uint32_t csize, size; + int left; + + s->zstream.zalloc = ff_png_zalloc; + s->zstream.zfree = ff_png_zfree; + s->zstream.opaque = NULL; + + if ((ret = inflateInit(&s->zstream)) != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); + ret = AVERROR_EXTERNAL; + goto end; + } + + bytestream2_seek(gb, 2 + b * 12, SEEK_SET); + + x = bytestream2_get_le16(gb); + y = bytestream2_get_le16(gb); + x2 = bytestream2_get_le16(gb); + y2 = bytestream2_get_le16(gb); + s->width = s->cur_w = w = x2-x; + s->height = s->cur_h = h = y2-y; + size = bytestream2_get_le32(gb); + + frame->key_frame = (nb_blocks == 1) && + (w == avctx->width) && + (h == avctx->height) && + (x == 0) && (y == 0); + + bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); + csize = bytestream2_get_be32(gb); + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { + ret = AVERROR_INVALIDDATA; + goto end; + } + offset += size; + left = size; + + s->y = 0; + s->row_size = w * 3; + + av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16); + if (!s->buffer) + return AVERROR(ENOMEM); + + s->crow_size = w * 3 + 1; + s->crow_buf = s->buffer + 15; + s->zstream.avail_out = s->crow_size; + s->zstream.next_out = s->crow_buf; + s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3; + s->image_linesize =-frame->linesize[0]; + s->bpp = 3; + s->pic_state = 0; + + av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size); + if (!s->last_row) + return AVERROR_INVALIDDATA; + + while (left > 16) { + ret = png_decode_idat(s, csize); + if (ret < 0) + goto end; + left -= csize + 16; + if (left > 16) { + bytestream2_skip(gb, 4); + csize = bytestream2_get_be32(gb); + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { + ret = AVERROR_INVALIDDATA; + goto end; + } + } + } + + inflateEnd(&s->zstream); + } + + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + av_frame_unref(s->last_picture.f); + if ((ret = av_frame_ref(s->last_picture.f, frame)) < 0) + return ret; + + *got_frame = 1; +end: + inflateEnd(&s->zstream); + + if (ret < 0) + return ret; + return avpkt->size; +} +#endif + #if HAVE_THREADS static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { @@ -1581,6 +1698,9 @@ static av_cold int png_dec_init(AVCodecContext *avctx) avctx->color_range = AVCOL_RANGE_JPEG; + if (avctx->codec_id == AV_CODEC_ID_LSCR) + avctx->pix_fmt = AV_PIX_FMT_BGR24; + s->avctx = avctx; s->previous_picture.f = av_frame_alloc(); s->last_picture.f = av_frame_alloc(); @@ -1653,3 +1773,18 @@ AVCodec ff_png_decoder = { .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, }; #endif + +#if CONFIG_LSCR_DECODER +AVCodec ff_lscr_decoder = { + .name = "lscr", + .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_LSCR, + .priv_data_size = sizeof(PNGDecContext), + .init = png_dec_init, + .close = png_dec_end, + .decode = decode_frame_lscr, + .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, +}; +#endif diff --git a/libavformat/riff.c b/libavformat/riff.c index 741a6515df..0f5cd62547 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -485,6 +485,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '5') }, { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '6') }, { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '7') }, + { AV_CODEC_ID_LSCR, MKTAG('L', 'S', 'C', 'R') }, { AV_CODEC_ID_NONE, 0 } };