From patchwork Thu Sep 6 09:45:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 10251 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:12c4:0:0:0:0:0 with SMTP id 65-v6csp278327jap; Thu, 6 Sep 2018 02:46:02 -0700 (PDT) X-Google-Smtp-Source: ANB0VdaZReX0NilJwKqWddWwc1ZpM9+ha/QNN459H+CsyV7gfLQPr222ubnQEYKikXQ84Amp1VEW X-Received: by 2002:adf:f5c9:: with SMTP id k9-v6mr1631953wrp.59.1536227162341; Thu, 06 Sep 2018 02:46:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536227162; cv=none; d=google.com; s=arc-20160816; b=Om411IY9/HIGiDf5KUpZ9AeiEjhAigHbHq0MULEdYh9hTR71RA7OyX3bWWqkdrtIOU eCTs5MKphg9UobIMMI1RHqF3FfVwTrqYlo5FsGoeDv0nG6g5C0AGcwuheS24NYN6bgTy TYXrujodd7XrXDLaeMmqlXtp0afUZ93EqNWj/iay1tEGN69QP+OkQkkOv4DnRjOJ+4Z6 B7yGfCyJEZdJUDfaY48pYM+927QEtXUR21WqOdHXPMAehnzzdwmVhWthh+kEMVWjB+n+ dE36+E6nKqzf8zTwW4a2/ecRBMrfUzeFOEbPTPJiNeU9m2boZuEThUGLBWA5BYzlUcpW itJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to; bh=6oktH4mNKwG1bpXjGzTD6UUvpoIJZAhyjQEmzng+i2w=; b=posWN71dRXLatvF0aZsBurVMrQeZ2RXuPhqnMhRZ4WJkYUcbmvhudaaticq5ifLRAb cqsOeZkbQGF/tr0ZU1O8d1O/IkL6wHUmENqYqk5fhZDBH3r1FZsWhBHYChohSYw4EL1u GXDabO3HgJ97wPW4s3N8xvgwHqFfWwHxwQrIHHzyQJozM1KccwymMJdDPq2Vzv5AGEwc Wh6hAHlGYbZIudTbIXQ3AopQn+Enxg25irzzF1QlWxJc6w0nxz/PsNkbn5PpIm3cH5aJ I62626OMNVB/AJnq1Cc9+WDSxdgYE4YSDacBKVpV7CRXSqJPYz+246bFO5DSNv/Y4D0U YgiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=VYuKcZX4; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id h5-v6si4436400wrp.34.2018.09.06.02.46.01; Thu, 06 Sep 2018 02:46:02 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=VYuKcZX4; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 40283689EE4; Thu, 6 Sep 2018 12:45:52 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f65.google.com (mail-ed1-f65.google.com [209.85.208.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2661A680964 for ; Thu, 6 Sep 2018 12:45:45 +0300 (EEST) Received: by mail-ed1-f65.google.com with SMTP id p52-v6so8337161eda.12 for ; Thu, 06 Sep 2018 02:45: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=dYdNfpp8jdzId+sC4U8fasr79zqoxrxRAhmbeoHpPZg=; b=VYuKcZX42iMwxV1KSqBnYTItj79SCkV899ViUIFD9U+nID5GHATuI1KwjEFHLX9ARi axBVNXWphF8Z4BxjcfvhGQ7vXTa57NXBoE+V9FlIuV2B1RxeK40EeGmIGlzxplJj0LOM p2Nk2DQ7KF31qpW07Ki5xtWRMVSVEg8kAmylyYzgH5gShcllaN5a+AES/IzlsiLlg0Ri jnaRWihUDjQKdhwqQdD4WrUSIah+C2F9MI23qL4iwpeCyPywE3PqcX5v5se07+Vw/U3w PO5EbuMuQhBfpbmy2gd0pb35Ct5KETPjLZJZ4HYjSMwIfZLC9OLijVf7EnkRg/LzHXMy /0Ig== 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=dYdNfpp8jdzId+sC4U8fasr79zqoxrxRAhmbeoHpPZg=; b=F29HI6PqDDOmo55/QCfkEjXUbBQ0pTJcvCcd9eFYN3olQXkwcv/MZOO6t/PGBHiJNi D7MXGiA6WPkqaEsmLYRZ2HuB6nIBHSPiQD+l5HU5Ehlb5pMuTouSmExQ5yItmMjTeRhx o9mrHUv14EGpDMjHFZey83ZKUcuSedVbJrYoePoLAUVke9h7lO4t9axqi3lbxImPoBn3 B1ARYnjVzotyYt3il9yNIWSquuxi7BsGQWbW1WXyd+zjupPcNiKZ2usnK8Z6qR5fTtYO O4nauIvMROuUqbdtOoe1uTO4nV2U730KrOAfmjUo43u+ouETOG6z6LYJ130arQ5k1gkN DrVw== X-Gm-Message-State: APzg51DuHaZ385rqe0iuXH7d3uLHNf3SVobl+Pz+BaiJZqbe1NyaCjmg 9CSHnZut598w6/IqwJywYNbG1WEt X-Received: by 2002:a50:8a23:: with SMTP id i32-v6mr2660554edi.49.1536227150784; Thu, 06 Sep 2018 02:45:50 -0700 (PDT) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id r35-v6sm4419243edr.59.2018.09.06.02.45.48 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Sep 2018 02:45:49 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Thu, 6 Sep 2018 11:45:39 +0200 Message-Id: <20180906094539.31378-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] avcodec/scpr: add version 3 support 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/scpr.c | 368 +++----------- libavcodec/scpr.h | 349 +++++++++++++ libavcodec/scpr3.c | 1189 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/scpr3.h | 82 +++ 4 files changed, 1680 insertions(+), 308 deletions(-) create mode 100644 libavcodec/scpr.h create mode 100644 libavcodec/scpr3.c create mode 100644 libavcodec/scpr3.h diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index ee6bf21b71..d1e07b875c 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -24,47 +24,18 @@ #include #include +#include "libavutil/qsort.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" +#include "scpr.h" +#include "scpr3.h" #define TOP 0x01000000 #define BOT 0x010000 -typedef struct RangeCoder { - unsigned code; - unsigned range; - unsigned code1; -} RangeCoder; - -typedef struct PixelModel { - unsigned freq[256]; - unsigned lookup[16]; - unsigned total_freq; -} PixelModel; - -typedef struct SCPRContext { - AVFrame *last_frame; - AVFrame *current_frame; - GetByteContext gb; - RangeCoder rc; - PixelModel pixel_model[3][4096]; - unsigned op_model[6][7]; - unsigned run_model[6][257]; - unsigned range_model[257]; - unsigned count_model[257]; - unsigned fill_model[6]; - unsigned sxy_model[4][17]; - unsigned mv_model[2][513]; - unsigned nbx, nby; - unsigned nbcount; - unsigned *blocks; - unsigned cbits; - int cxshift; - - int (*get_freq)(RangeCoder *rc, unsigned total_freq, unsigned *freq); - int (*decode)(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned freq, unsigned total_freq); -} SCPRContext; +#include "scpr3.c" static void init_rangecoder(RangeCoder *rc, GetByteContext *gb) { @@ -90,14 +61,14 @@ static void reinit_tables(SCPRContext *s) } for (j = 0; j < 6; j++) { - unsigned *p = s->run_model[j]; + uint32_t *p = s->run_model[j]; for (i = 0; i < 256; i++) p[i] = 1; p[256] = 256; } for (j = 0; j < 6; j++) { - unsigned *op = s->op_model[j]; + uint32_t *op = s->op_model[j]; for (i = 0; i < 6; i++) op[i] = 1; op[6] = 6; @@ -130,13 +101,13 @@ static void reinit_tables(SCPRContext *s) s->mv_model[1][512] = 512; } -static int decode(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned freq, unsigned total_freq) +static int decode(GetByteContext *gb, RangeCoder *rc, uint32_t cumFreq, uint32_t freq, uint32_t total_freq) { rc->code -= cumFreq * rc->range; rc->range *= freq; while (rc->range < TOP && bytestream2_get_bytes_left(gb) > 0) { - unsigned byte = bytestream2_get_byte(gb); + uint32_t byte = bytestream2_get_byte(gb); rc->code = (rc->code << 8) | byte; rc->range <<= 8; } @@ -144,7 +115,7 @@ static int decode(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned return 0; } -static int get_freq(RangeCoder *rc, unsigned total_freq, unsigned *freq) +static int get_freq(RangeCoder *rc, uint32_t total_freq, uint32_t *freq) { if (total_freq == 0) return AVERROR_INVALIDDATA; @@ -159,9 +130,9 @@ static int get_freq(RangeCoder *rc, unsigned total_freq, unsigned *freq) return 0; } -static int decode0(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned freq, unsigned total_freq) +static int decode0(GetByteContext *gb, RangeCoder *rc, uint32_t cumFreq, uint32_t freq, uint32_t total_freq) { - unsigned t; + uint32_t t; if (total_freq == 0) return AVERROR_INVALIDDATA; @@ -172,7 +143,7 @@ static int decode0(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigne rc->range = rc->range * (uint64_t)(freq + cumFreq) / total_freq - (t + 1); while (rc->range < TOP && bytestream2_get_bytes_left(gb) > 0) { - unsigned byte = bytestream2_get_byte(gb); + uint32_t byte = bytestream2_get_byte(gb); rc->code = (rc->code << 8) | byte; rc->code1 <<= 8; rc->range <<= 8; @@ -181,7 +152,7 @@ static int decode0(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigne return 0; } -static int get_freq0(RangeCoder *rc, unsigned total_freq, unsigned *freq) +static int get_freq0(RangeCoder *rc, uint32_t total_freq, uint32_t *freq) { if (rc->range == 0) return AVERROR_INVALIDDATA; @@ -191,13 +162,13 @@ static int get_freq0(RangeCoder *rc, unsigned total_freq, unsigned *freq) return 0; } -static int decode_value(SCPRContext *s, unsigned *cnt, unsigned maxc, unsigned step, unsigned *rval) +static int decode_value(SCPRContext *s, uint32_t *cnt, uint32_t maxc, uint32_t step, uint32_t *rval) { GetByteContext *gb = &s->gb; RangeCoder *rc = &s->rc; - unsigned totfr = cnt[maxc]; - unsigned value; - unsigned c = 0, cumfr = 0, cnt_c = 0; + uint32_t totfr = cnt[maxc]; + uint32_t value; + uint32_t c = 0, cumfr = 0, cnt_c = 0; int i, ret; if ((ret = s->get_freq(rc, totfr, &value)) < 0) @@ -223,7 +194,7 @@ static int decode_value(SCPRContext *s, unsigned *cnt, unsigned maxc, unsigned s if (totfr > BOT) { totfr = 0; for (i = 0; i < maxc; i++) { - unsigned nc = (cnt[i] >> 1) + 1; + uint32_t nc = (cnt[i] >> 1) + 1; cnt[i] = nc; totfr += nc; } @@ -235,12 +206,12 @@ static int decode_value(SCPRContext *s, unsigned *cnt, unsigned maxc, unsigned s return 0; } -static int decode_unit(SCPRContext *s, PixelModel *pixel, unsigned step, unsigned *rval) +static int decode_unit(SCPRContext *s, PixelModel *pixel, uint32_t step, uint32_t *rval) { GetByteContext *gb = &s->gb; RangeCoder *rc = &s->rc; - unsigned totfr = pixel->total_freq; - unsigned value, x = 0, cumfr = 0, cnt_x = 0; + uint32_t totfr = pixel->total_freq; + uint32_t value, x = 0, cumfr = 0, cnt_x = 0; int i, j, ret, c, cnt_c; if ((ret = s->get_freq(rc, totfr, &value)) < 0) @@ -278,13 +249,13 @@ static int decode_unit(SCPRContext *s, PixelModel *pixel, unsigned step, unsigne if (totfr > BOT) { totfr = 0; for (i = 0; i < 256; i++) { - unsigned nc = (pixel->freq[i] >> 1) + 1; + uint32_t nc = (pixel->freq[i] >> 1) + 1; pixel->freq[i] = nc; totfr += nc; } for (i = 0; i < 16; i++) { - unsigned sum = 0; - unsigned i16_17 = i << 4; + uint32_t sum = 0; + uint32_t i16_17 = i << 4; for (j = 0; j < 16; j++) sum += pixel->freq[i16_17 + j]; pixel->lookup[i] = sum; @@ -297,7 +268,7 @@ static int decode_unit(SCPRContext *s, PixelModel *pixel, unsigned step, unsigne return 0; } -static int decode_units(SCPRContext *s, unsigned *r, unsigned *g, unsigned *b, +static int decode_units(SCPRContext *s, uint32_t *r, uint32_t *g, uint32_t *b, int *cx, int *cx1) { const int cxshift = s->cxshift; @@ -329,10 +300,10 @@ static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize) { SCPRContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - int cx = 0, cx1 = 0, k = 0, clr = 0; - int run, off, y = 0, x = 0, z, ret; - unsigned r, g, b, backstep = linesize - avctx->width; - unsigned lx, ly, ptype; + int cx = 0, cx1 = 0, k = 0; + int run, off, y = 0, x = 0, ret; + uint32_t clr = 0, r, g, b, backstep = linesize - avctx->width; + uint32_t lx, ly, ptype; reinit_tables(s); bytestream2_skip(gb, 2); @@ -387,120 +358,11 @@ static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize) if (run <= 0) return AVERROR_INVALIDDATA; - switch (ptype) { - case 0: - while (run-- > 0) { - if (y >= avctx->height) - return AVERROR_INVALIDDATA; - - dst[y * linesize + x] = clr; - lx = x; - ly = y; - x++; - if (x >= avctx->width) { - x = 0; - y++; - } - } - break; - case 1: - while (run-- > 0) { - if (y >= avctx->height) - return AVERROR_INVALIDDATA; - - dst[y * linesize + x] = dst[ly * linesize + lx]; - lx = x; - ly = y; - x++; - if (x >= avctx->width) { - x = 0; - y++; - } - } - clr = dst[ly * linesize + lx]; - break; - case 2: - while (run-- > 0) { - if (y < 1 || y >= avctx->height) - return AVERROR_INVALIDDATA; - - clr = dst[y * linesize + x + off + 1]; - dst[y * linesize + x] = clr; - lx = x; - ly = y; - x++; - if (x >= avctx->width) { - x = 0; - y++; - } - } - break; - case 4: - while (run-- > 0) { - uint8_t *odst = (uint8_t *)dst; - - if (y < 1 || y >= avctx->height || - (y == 1 && x == 0)) - return AVERROR_INVALIDDATA; - - if (x == 0) { - z = backstep; - } else { - z = 0; - } - - r = odst[(ly * linesize + lx) * 4] + - odst[((y * linesize + x) + off) * 4 + 4] - - odst[((y * linesize + x) + off - z) * 4]; - g = odst[(ly * linesize + lx) * 4 + 1] + - odst[((y * linesize + x) + off) * 4 + 5] - - odst[((y * linesize + x) + off - z) * 4 + 1]; - b = odst[(ly * linesize + lx) * 4 + 2] + - odst[((y * linesize + x) + off) * 4 + 6] - - odst[((y * linesize + x) + off - z) * 4 + 2]; - clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); - dst[y * linesize + x] = clr; - lx = x; - ly = y; - x++; - if (x >= avctx->width) { - x = 0; - y++; - } - } - break; - case 5: - while (run-- > 0) { - if (y < 1 || y >= avctx->height || - (y == 1 && x == 0)) - return AVERROR_INVALIDDATA; - - if (x == 0) { - z = backstep; - } else { - z = 0; - } - - clr = dst[y * linesize + x + off - z]; - dst[y * linesize + x] = clr; - lx = x; - ly = y; - x++; - if (x >= avctx->width) { - x = 0; - y++; - } - } - break; - } - - if (avctx->bits_per_coded_sample == 16) { - cx1 = (clr & 0x3F00) >> 2; - cx = (clr & 0x3FFFFF) >> 16; - } else { - cx1 = (clr & 0xFC00) >> 4; - cx = (clr & 0xFFFFFF) >> 18; - } + ret = decode_run_i(avctx, ptype, run, &x, &y, clr, + dst, linesize, &lx, &ly, + backstep, off, &cx, &cx1); + if (run < 0) + return ret; } return 0; @@ -587,8 +449,8 @@ static int decompress_p(AVCodecContext *avctx, } } } else { - int run, z, bx = x * 16 + sx1, by = y * 16 + sy1; - unsigned r, g, b, clr, ptype = 0; + int run, bx = x * 16 + sx1, by = y * 16 + sy1; + uint32_t r, g, b, clr, ptype = 0; for (; by < y * 16 + sy2 && by < avctx->height;) { ret = decode_value(s, s->op_model[ptype], 6, 1000, &ptype); @@ -609,134 +471,11 @@ static int decompress_p(AVCodecContext *avctx, if (run <= 0) return AVERROR_INVALIDDATA; - switch (ptype) { - case 0: - while (run-- > 0) { - if (by >= avctx->height) - return AVERROR_INVALIDDATA; - - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - case 1: - while (run-- > 0) { - if (bx == 0) { - if (by < 1) - return AVERROR_INVALIDDATA; - z = backstep; - } else { - z = 0; - } - - if (by >= avctx->height) - return AVERROR_INVALIDDATA; - - clr = dst[by * linesize + bx - 1 - z]; - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - case 2: - while (run-- > 0) { - if (by < 1 || by >= avctx->height) - return AVERROR_INVALIDDATA; - - clr = dst[(by - 1) * linesize + bx]; - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - case 3: - while (run-- > 0) { - if (by >= avctx->height) - return AVERROR_INVALIDDATA; - - clr = prev[by * plinesize + bx]; - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - case 4: - while (run-- > 0) { - uint8_t *odst = (uint8_t *)dst; - - if (by < 1 || by >= avctx->height) - return AVERROR_INVALIDDATA; - - if (bx == 0) { - if (by < 2) - return AVERROR_INVALIDDATA; - z = backstep; - } else { - z = 0; - } - - r = odst[((by - 1) * linesize + bx) * 4] + - odst[(by * linesize + bx - 1 - z) * 4] - - odst[((by - 1) * linesize + bx - 1 - z) * 4]; - g = odst[((by - 1) * linesize + bx) * 4 + 1] + - odst[(by * linesize + bx - 1 - z) * 4 + 1] - - odst[((by - 1) * linesize + bx - 1 - z) * 4 + 1]; - b = odst[((by - 1) * linesize + bx) * 4 + 2] + - odst[(by * linesize + bx - 1 - z) * 4 + 2] - - odst[((by - 1) * linesize + bx - 1 - z) * 4 + 2]; - clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - case 5: - while (run-- > 0) { - if (by < 1 || by >= avctx->height) - return AVERROR_INVALIDDATA; - - if (bx == 0) { - if (by < 2) - return AVERROR_INVALIDDATA; - z = backstep; - } else { - z = 0; - } - - clr = dst[(by - 1) * linesize + bx - 1 - z]; - dst[by * linesize + bx] = clr; - bx++; - if (bx >= x * 16 + sx2 || bx >= avctx->width) { - bx = x * 16 + sx1; - by++; - } - } - break; - } - - if (avctx->bits_per_coded_sample == 16) { - cx1 = (clr & 0x3F00) >> 2; - cx = (clr & 0x3FFFFF) >> 16; - } else { - cx1 = (clr & 0xFC00) >> 4; - cx = (clr & 0xFFFFFF) >> 18; - } + ret = decode_run_p(avctx, ptype, run, x, y, clr, + dst, prev, linesize, plinesize, &bx, &by, + backstep, sx1, sx2, &cx, &cx1); + if (ret < 0) + return ret; } } } @@ -766,18 +505,25 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, type = bytestream2_peek_byte(gb); if (type == 2) { + s->version = 1; s->get_freq = get_freq0; s->decode = decode0; frame->key_frame = 1; ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0], s->current_frame->linesize[0] / 4); } else if (type == 18) { + s->version = 2; s->get_freq = get_freq; s->decode = decode; frame->key_frame = 1; ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0], s->current_frame->linesize[0] / 4); - } else if (type == 17) { + } else if (type == 34) { + frame->key_frame = 1; + s->version = 3; + ret = decompress_i3(avctx, (uint32_t *)s->current_frame->data[0], + s->current_frame->linesize[0] / 4); + } else if (type == 17 || type == 33) { uint32_t clr, *dst = (uint32_t *)s->current_frame->data[0]; int x, y; @@ -807,10 +553,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ret < 0) return ret; - ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0], - s->current_frame->linesize[0] / 4, - (uint32_t *)s->last_frame->data[0], - s->last_frame->linesize[0] / 4); + if (s->version == 1 || s->version == 2) + ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0], + s->current_frame->linesize[0] / 4, + (uint32_t *)s->last_frame->data[0], + s->last_frame->linesize[0] / 4); + else + ret = decompress_p3(avctx, (uint32_t *)s->current_frame->data[0], + s->current_frame->linesize[0] / 4, + (uint32_t *)s->last_frame->data[0], + s->last_frame->linesize[0] / 4); } else { return AVERROR_PATCHWELCOME; } diff --git a/libavcodec/scpr.h b/libavcodec/scpr.h new file mode 100644 index 0000000000..a013d7e600 --- /dev/null +++ b/libavcodec/scpr.h @@ -0,0 +1,349 @@ +/* + * ScreenPressor decoder + * + * Copyright (c) 2017 Paul B Mahol + * + * 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 + */ + +#ifndef AVCODEC_SCPR_H +#define AVCODEC_SCPR_H + +#include +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "scpr3.h" + +typedef struct RangeCoder { + uint32_t code; + uint32_t range; + uint32_t code1; +} RangeCoder; + +typedef struct PixelModel { + uint32_t freq[256]; + uint32_t lookup[16]; + uint32_t total_freq; +} PixelModel; + +typedef struct SCPRContext { + int version; + AVFrame *last_frame; + AVFrame *current_frame; + GetByteContext gb; + RangeCoder rc; + PixelModel pixel_model[3][4096]; + uint32_t op_model[6][7]; + uint32_t run_model[6][257]; + uint32_t range_model[257]; + uint32_t count_model[257]; + uint32_t fill_model[6]; + uint32_t sxy_model[4][17]; + uint32_t mv_model[2][513]; + uint32_t nbx, nby; + uint32_t nbcount; + uint32_t *blocks; + uint32_t cbits; + int cxshift; + + PixelModel3 pixel_model3[3][4096]; + RunModel3 run_model3[6]; + RunModel3 range_model3; + RunModel3 count_model3; + FillModel3 fill_model3; + SxyModel3 sxy_model3[4]; + MVModel3 mv_model3[2]; + OpModel3 op_model3[6]; + + int (*get_freq)(RangeCoder *rc, uint32_t total_freq, uint32_t *freq); + int (*decode)(GetByteContext *gb, RangeCoder *rc, uint32_t cumFreq, uint32_t freq, uint32_t total_freq); +} SCPRContext; + +static int decode_run_i(AVCodecContext *avctx, uint32_t ptype, int run, + int *x, int *y, uint32_t clr, uint32_t *dst, + int linesize, uint32_t *lx, uint32_t *ly, + uint32_t backstep, int off, int *cx, int *cx1) +{ + uint32_t r, g, b; + int z; + + switch (ptype) { + case 0: + while (run-- > 0) { + if (*y >= avctx->height) + return AVERROR_INVALIDDATA; + + dst[*y * linesize + *x] = clr; + *lx = *x; + *ly = *y; + (*x)++; + if (*x >= avctx->width) { + *x = 0; + (*y)++; + } + } + break; + case 1: + while (run-- > 0) { + if (*y >= avctx->height) + return AVERROR_INVALIDDATA; + + dst[*y * linesize + *x] = dst[*ly * linesize + *lx]; + *lx = *x; + *ly = *y; + (*x)++; + if (*x >= avctx->width) { + *x = 0; + (*y)++; + } + } + clr = dst[*ly * linesize + *lx]; + break; + case 2: + while (run-- > 0) { + if (*y < 1 || *y >= avctx->height) + return AVERROR_INVALIDDATA; + + clr = dst[*y * linesize + *x + off + 1]; + dst[*y * linesize + *x] = clr; + *lx = *x; + *ly = *y; + (*x)++; + if (*x >= avctx->width) { + *x = 0; + (*y)++; + } + } + break; + case 4: + while (run-- > 0) { + uint8_t *odst = (uint8_t *)dst; + + if (*y < 1 || *y >= avctx->height || + (*y == 1 && *x == 0)) + return AVERROR_INVALIDDATA; + + if (*x == 0) { + z = backstep; + } else { + z = 0; + } + + r = odst[(*ly * linesize + *lx) * 4] + + odst[((*y * linesize + *x) + off) * 4 + 4] - + odst[((*y * linesize + *x) + off - z) * 4]; + g = odst[(*ly * linesize + *lx) * 4 + 1] + + odst[((*y * linesize + *x) + off) * 4 + 5] - + odst[((*y * linesize + *x) + off - z) * 4 + 1]; + b = odst[(*ly * linesize + *lx) * 4 + 2] + + odst[((*y * linesize + *x) + off) * 4 + 6] - + odst[((*y * linesize + *x) + off - z) * 4 + 2]; + clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); + dst[*y * linesize + *x] = clr; + *lx = *x; + *ly = *y; + (*x)++; + if (*x >= avctx->width) { + *x = 0; + (*y)++; + } + } + break; + case 5: + while (run-- > 0) { + if (*y < 1 || *y >= avctx->height || + (*y == 1 && *x == 0)) + return AVERROR_INVALIDDATA; + + if (*x == 0) { + z = backstep; + } else { + z = 0; + } + + clr = dst[*y * linesize + *x + off - z]; + dst[*y * linesize + *x] = clr; + *lx = *x; + *ly = *y; + (*x)++; + if (*x >= avctx->width) { + *x = 0; + (*y)++; + } + } + break; + } + + if (avctx->bits_per_coded_sample == 16) { + *cx1 = (clr & 0x3F00) >> 2; + *cx = (clr & 0x3FFFFF) >> 16; + } else { + *cx1 = (clr & 0xFC00) >> 4; + *cx = (clr & 0xFFFFFF) >> 18; + } + + return 0; +} + +static int decode_run_p(AVCodecContext *avctx, uint32_t ptype, int run, + int x, int y, uint32_t clr, + uint32_t *dst, uint32_t *prev, + int linesize, int plinesize, + uint32_t *bx, uint32_t *by, + uint32_t backstep, int sx1, int sx2, + int *cx, int *cx1) +{ + uint32_t r, g, b; + int z; + + switch (ptype) { + case 0: + while (run-- > 0) { + if (*by >= avctx->height) + return AVERROR_INVALIDDATA; + + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + case 1: + while (run-- > 0) { + if (*bx == 0) { + if (*by < 1) + return AVERROR_INVALIDDATA; + z = backstep; + } else { + z = 0; + } + + if (*by >= avctx->height) + return AVERROR_INVALIDDATA; + + clr = dst[*by * linesize + *bx - 1 - z]; + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + case 2: + while (run-- > 0) { + if (*by < 1 || *by >= avctx->height) + return AVERROR_INVALIDDATA; + + clr = dst[(*by - 1) * linesize + *bx]; + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + case 3: + while (run-- > 0) { + if (*by >= avctx->height) + return AVERROR_INVALIDDATA; + + clr = prev[*by * plinesize + *bx]; + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + case 4: + while (run-- > 0) { + uint8_t *odst = (uint8_t *)dst; + + if (*by < 1 || *by >= avctx->height) + return AVERROR_INVALIDDATA; + + if (*bx == 0) { + if (*by < 2) + return AVERROR_INVALIDDATA; + z = backstep; + } else { + z = 0; + } + + r = odst[((*by - 1) * linesize + *bx) * 4] + + odst[(*by * linesize + *bx - 1 - z) * 4] - + odst[((*by - 1) * linesize + *bx - 1 - z) * 4]; + g = odst[((*by - 1) * linesize + *bx) * 4 + 1] + + odst[(*by * linesize + *bx - 1 - z) * 4 + 1] - + odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1]; + b = odst[((*by - 1) * linesize + *bx) * 4 + 2] + + odst[(*by * linesize + *bx - 1 - z) * 4 + 2] - + odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2]; + clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + case 5: + while (run-- > 0) { + if (*by < 1 || *by >= avctx->height) + return AVERROR_INVALIDDATA; + + if (*bx == 0) { + if (*by < 2) + return AVERROR_INVALIDDATA; + z = backstep; + } else { + z = 0; + } + + clr = dst[(*by - 1) * linesize + *bx - 1 - z]; + dst[*by * linesize + *bx] = clr; + (*bx)++; + if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { + *bx = x * 16 + sx1; + (*by)++; + } + } + break; + } + + if (avctx->bits_per_coded_sample == 16) { + *cx1 = (clr & 0x3F00) >> 2; + *cx = (clr & 0x3FFFFF) >> 16; + } else { + *cx1 = (clr & 0xFC00) >> 4; + *cx = (clr & 0xFFFFFF) >> 18; + } + + return 0; +} + +#endif /* AVCODEC_SCPR_H */ diff --git a/libavcodec/scpr3.c b/libavcodec/scpr3.c new file mode 100644 index 0000000000..da31e0a7a9 --- /dev/null +++ b/libavcodec/scpr3.c @@ -0,0 +1,1189 @@ +/* + * ScreenPressor version 3 decoder + * + * Copyright (c) 2017 Paul B Mahol + * + * 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 +#include +#include + +#include "libavutil/qsort.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "scpr.h" + +static void renew_table3(uint32_t nsym, uint32_t *cntsum, + uint16_t *freqs, uint16_t *freqs1, + uint16_t *cnts, uint8_t *dectab) +{ + uint32_t a = 0, b = 4096 / nsym, c = b - (b >> 1); + + *cntsum = c * nsym; + + for (int d = 0; d < nsym; d++) { + freqs[d] = b; + freqs1[d] = a; + cnts[d] = c; + for (int q = a + 128 - 1 >> 7, f = (a + b - 1 >> 7) + 1; q < f; q++) + dectab[q] = d; + + a += b; + } +} + +static void reinit_tables3(SCPRContext * s) +{ + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 4096; j++) { + PixelModel3 *m = &s->pixel_model3[i][j]; + m->type = 0; + } + } + + for (int i = 0; i < 6; i++) { + renew_table3(256, &s->run_model3[i].cntsum, + s->run_model3[i].freqs[0], s->run_model3[i].freqs[1], + s->run_model3[i].cnts, s->run_model3[i].dectab); + } + + renew_table3(256, &s->range_model3.cntsum, + s->range_model3.freqs[0], s->range_model3.freqs[1], + s->range_model3.cnts, s->range_model3.dectab); + + renew_table3(5, &s->fill_model3.cntsum, + s->fill_model3.freqs[0], s->fill_model3.freqs[1], + s->fill_model3.cnts, s->fill_model3.dectab); + + renew_table3(256, &s->count_model3.cntsum, + s->count_model3.freqs[0], s->count_model3.freqs[1], + s->count_model3.cnts, s->count_model3.dectab); + + for (int i = 0; i < 4; i++) { + renew_table3(16, &s->sxy_model3[i].cntsum, + s->sxy_model3[i].freqs[0], s->sxy_model3[i].freqs[1], + s->sxy_model3[i].cnts, s->sxy_model3[i].dectab); + } + + for (int i = 0; i < 2; i++) { + renew_table3(512, &s->mv_model3[i].cntsum, + s->mv_model3[i].freqs[0], s->mv_model3[i].freqs[1], + s->mv_model3[i].cnts, s->mv_model3[i].dectab); + } + + for (int i = 0; i < 6; i++) { + renew_table3(6, &s->op_model3[i].cntsum, + s->op_model3[i].freqs[0], s->op_model3[i].freqs[1], + s->op_model3[i].cnts, s->op_model3[i].dectab); + } +} + +static int decode3(GetByteContext *gb, RangeCoder *rc, uint32_t a, uint32_t b) +{ + uint32_t code = a * (rc->code >> 12) + (rc->code & 0xFFF) - b; + + while (code < 0x800000 && bytestream2_get_bytes_left(gb) > 0) + code = bytestream2_get_byte(gb) | (code << 8); + rc->code = code; + + return 0; +} + +static void rescale(PixelModel3 *m, int *totfr) +{ + uint32_t a; + + a = 256 - m->size; + for (int b = 0; b < m->size; b++) { + m->freqs[b] -= m->freqs[b] >> 1; + a += m->freqs[b]; + } + + *totfr = a; +} + +static int add_symbol(PixelModel3 *m, int index, uint32_t symbol, int *totfr, int max) +{ + if (m->size == max) + return 0; + + for (int c = m->size - 1; c >= index; c--) { + m->symbols[c + 1] = m->symbols[c]; + m->freqs[c + 1] = m->freqs[c]; + } + + m->symbols[index] = symbol; + m->freqs[index] = 50; + m->size++; + + if (m->maxpos >= index) + m->maxpos++; + + *totfr += 50; + if (*totfr + 50 > 4096) + rescale(m, totfr); + + return 1; +} + +static int decode_adaptive45(PixelModel3 *m, int rccode, uint32_t *value, + uint16_t *a, uint16_t *b, uint32_t *c, int max) +{ + uint32_t q, g, maxpos, d, e = *c, totfr = *c; + int ret; + + for (d = 0; e <= 2048; d++) + e <<= 1; + maxpos = m->maxpos; + rccode >>= d; + *c = m->freqs[maxpos]; + m->freqs[maxpos] += 4096 - e >> d; + + for (q = 0, g = 0, e = 0; q < m->size; q++) { + uint32_t f = m->symbols[q]; + uint32_t p = e + f - g; + uint32_t k = m->freqs[q]; + + if (rccode < p) { + *value = rccode - e + g; + *b = rccode << d; + *a = 1 << d; + m->freqs[maxpos] = *c; + ret = add_symbol(m, q, *value, &totfr, max); + *c = totfr; + return ret; + } + + if (p + k > rccode) { + *value = f; + e += *value - g; + *b = e << d; + *a = k << d; + m->freqs[maxpos] = *c; + m->freqs[q] += 50; + totfr += 50; + if ((q != maxpos) && (m->freqs[q] > m->freqs[maxpos])) + m->maxpos = q; + if (totfr + 50 > 4096) + rescale(m, &totfr); + *c = totfr; + return 1; + } + + e += f - g + k; + g = f + 1; + } + + m->freqs[maxpos] = *c; + *value = g + rccode - e; + *b = rccode << d; + *a = 1 << d; + ret = add_symbol(m, q, *value, &totfr, max); + *c = totfr; + return ret; +} + +static int update_model6_to_7(PixelModel3 *n, PixelModel3 *m) +{ + int c, d, e, f, k, p, length, i, j, index; + uint16_t *freqs, *freqs1, *cnts; + + n->type = 7; + + length = m->length; + freqs = n->freqs; + freqs1 = n->freqs1; + cnts = n->cnts; + n->cntsum = m->cnts[length]; + for (i = 0; i < length; i++) { + if (!m->cnts[i]) + continue; + index = m->symbols[i]; + freqs[index] = m->freqs[2 * i]; + freqs1[index] = m->freqs[2 * i + 1]; + cnts[index] = m->cnts[i]; + } + c = 1 << m->fshift; + d = c - (c >> 1); + for (j = 0, e = 0; j < 256; j++) { + f = freqs[j]; + if (!f) { + f = c; + freqs[j] = c; + freqs1[j] = e; + cnts[j] = d; + } + p = (e + 127) >> 7; + k = ((f + e - 1) >> 7) + 1; + for (i = 0; i < k - p; i++) + n->dectab[p + i] = j; + e += f; + } + + memcpy(m, n, sizeof(*n)); + + return 0; +} + +static void calc_sum(PixelModel3 *m) +{ + uint32_t a; + int b; + + b = m->length; + a = 256 - m->size << (m->fshift > 0 ? m->fshift - 1 : 0); + for (int c = 0; c < b; c++) + a += m->cnts[c]; + m->cnts[b] = a; +} + +static void rescale_dec(PixelModel3 *m) +{ + uint16_t cnts[256] = {0}; + uint16_t freqs[512] = {0}; + int b, c, e, g; + uint32_t a; + + for (a = 1 << (0 < m->fshift ? m->fshift - 1 : 0), b = 0; b < 256; b++) + cnts[b] = a; + + for (a = 0, b = m->size; a < b; a++) + cnts[m->symbols[a]] = m->cnts[a]; + + for (b = a = 0; b < 256; b++) { + freqs[2 * b] = cnts[b]; + freqs[2 * b + 1] = a; + a += cnts[b]; + } + + if (m->fshift > 0) + m->fshift--; + + a = 256 - m->size << (0 < m->fshift ? m->fshift - 1 : 0); + for (b = 0, c = m->size; b < c; b++) { + m->cnts[b] -= m->cnts[b] >> 1; + a = a + m->cnts[b]; + e = m->symbols[b]; + g = freqs[2 * e + 1]; + m->freqs[2 * b] = freqs[2 * e]; + m->freqs[2 * b + 1] = g; + } + m->cnts[m->length] = a; +} + +static int update_model5_to_6(PixelModel3 *n, PixelModel3 *m, uint8_t value) +{ + int c, d, e, f, g, k, q, p; + + n->type = 6; + n->length = 32; + + for (c = m->size, d = 256 - c, e = 0; e < c; e++) + d = d + m->freqs[e]; + + for (e = 0; d <= 2048; e++) + d <<= 1; + + for (q = d = 0, g = q = 0; g < c; g++) { + p = m->symbols[g]; + d = d + (p - q); + q = m->freqs[g]; + k = q << e; + n->freqs[2 * g] = k; + n->freqs[2 * g + 1] = d << e; + n->cnts[g] = k - (k >> 1); + n->symbols[g] = p; + d += q; + q = p + 1; + } + + n->fshift = e; + e = 1 << n->fshift; + d = 0; + if (value > 0) { + d = -1; + for (p = f = g = 0; p < c; p++) { + k = n->symbols[p]; + if (k > d && k < value) { + d = k; + g = n->freqs[2 * p]; + f = n->freqs[2 * p + 1]; + } + } + d = 0 < g ? f + g + (value - d - 1 << n->fshift) : value << n->fshift; + } + n->freqs[2 * c] = e; + n->freqs[2 * c + 1] = d; + n->cnts[c] = e - (e >> 1); + n->symbols[c] = value; + n->size = c + 1; + e = 25 << n->fshift; + n->cnts[c] += e; + n->cnts[32] += e; + if (n->cnts[32] + e > 4096) + rescale_dec(n); + + calc_sum(n); + for (c = 0, e = n->size - 1; c < e; c++) { + for (g = c + 1, f = n->size; g < f;) { + if (p = g++, q = n->freqs[2 * p], k = n->freqs[2 * c], q > k) { + int l = n->freqs[2 * c + 1]; + int h = n->freqs[2 * p + 1]; + n->freqs[2 * c] = q; + n->freqs[2 * c + 1] = h; + n->freqs[2 * p] = k; + n->freqs[2 * p + 1] = l; + FFSWAP(uint16_t, n->cnts[c], n->cnts[p]); + FFSWAP(uint8_t, n->symbols[c], n->symbols[p]); + } + } + } + + memcpy(m, n, sizeof(*n)); + + return 0; +} + +static void grow_dec(PixelModel3 *m) +{ + int a; + + a = 2 * m->length; + m->cnts[2 * m->length] = m->cnts[m->length]; + m->length = a; +} + +static int add_dec(PixelModel3 *m, int a, int b, int c) +{ + int d; + + if (m->size >= 40 || m->size >= m->length) + return -1; + + d = m->size; + m->symbols[d] = a; + m->freqs[2 * d] = b; + m->freqs[2 * d + 1] = c; + m->cnts[d] = b - (b >> 1); + m->size++; + + return d; +} + +static void incr_cntdec(PixelModel3 *m, int a) +{ + int b, c, d, e, g; + + b = 25 << m->fshift; + c = m->length; + m->cnts[a] += b; + m->cnts[c] += b; + if (a > 0 && m->cnts[a] > m->cnts[a - 1]) { + d = m->cnts[a]; + m->cnts[a] = m->cnts[a - 1]; + m->cnts[a - 1] = d; + d = m->freqs[2 * a]; + e = m->freqs[2 * a + 1]; + g = m->freqs[2 * (a - 1) + 1]; + m->freqs[2 * a] = m->freqs[2 * (a - 1)]; + m->freqs[2 * a + 1] = g; + g = a - 1; + m->freqs[2 * g] = d; + m->freqs[2 * g + 1] = e; + d = m->symbols[a]; + m->symbols[a] = m->symbols[a - 1]; + m->symbols[a - 1] = d; + } + + if (m->cnts[c] + b > 4096) + rescale_dec(m); +} + +static int decode_adaptive6(PixelModel3 *m, uint32_t code, uint32_t *value, + uint16_t *a, uint16_t *b) +{ + int c, d, e, f, g, q; + + for (c = 0, d = 0, e = 0, f = 0, g = 0, q = m->size; g < q; g++) { + uint32_t p = m->freqs[2 * g + 1]; + + if (p <= code) { + uint32_t k = m->freqs[2 * g]; + + if (p + k > code) { + *value = m->symbols[g]; + *a = k; + *b = p; + incr_cntdec(m, g); + return 1; + } + + if (p >= d) { + c = k; + d = p; + e = m->symbols[g]; + } + } + } + + g = 1 << m->fshift; + q = f = 0; + + if (c > 0) { + f = code - (d + c) >> m->fshift; + q = f + e + 1; + f = d + c + (f << m->fshift); + } else { + q = code >> m->fshift; + f = q << m->fshift; + } + + *a = g; + *b = f; + *value = q; + + c = add_dec(m, q, g, f); + if (c < 0) { + if (m->length == 64) + return 0; + grow_dec(m); + c = add_dec(m, q, g, f); + } + + incr_cntdec(m, c); + return 1; +} + +static int cmpbytes(const void *p1, const void *p2) +{ + int left = *(const uint8_t *)p1; + int right = *(const uint8_t *)p2; + return FFDIFFSIGN(left, right); +} + +static int update_model1_to_2(PixelModel3 *m, uint32_t val) +{ + PixelModel3 n = {0}; + int i, b; + + n.type = 2; + n.size = m->size + 1; + b = m->size; + for (i = 0; i < b; i++) + n.symbols[i] = m->symbols[i]; + n.symbols[b] = val; + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int update_model1_to_4(PixelModel3 *m, uint32_t val) +{ + PixelModel3 n = {0}; + int size, i; + + size = m->size; + n.type = 4; + n.size = size; + for (i = 0; i < n.size; i++) { + n.symbols[i] = m->symbols[i]; + } + AV_QSORT(n.symbols, size, uint8_t, cmpbytes); + for (i = 0; i < n.size; i++) { + if (val == n.symbols[i]) { + n.freqs[i] = 100; + n.maxpos = i; + } else { + n.freqs[i] = 50; + } + } + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int update_model1_to_5(PixelModel3 *m, uint32_t val) +{ + PixelModel3 n = {0}; + int i, size, freqs; + uint32_t a; + + size = m->size; + n.size = size; + for (i = 0; i < size; i++) { + n.symbols[i] = m->symbols[i]; + } + AV_QSORT(n.symbols, size, uint8_t, cmpbytes); + size = n.size; + for (i = 0; i < size; i++) { + if (val == n.symbols[i]) { + n.freqs[i] = 100; + n.maxpos = i; + } else { + n.freqs[i] = 50; + } + } + a = 256 - size; + for (i = 0; i < size; i++, a += freqs) + freqs = n.freqs[i]; + n.type = 5; + n.cntsum = a; + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int decode_static1(PixelModel3 *m, uint32_t val) +{ + uint32_t size; + + size = m->size; + for (int i = 0; i < size; i++) { + if (val == m->symbols[i]) { + if (size <= 4) + return update_model1_to_4(m, val); + else + return update_model1_to_5(m, val); + } + } + + if (size >= 14) + return update_model1_to_2(m, val); + + m->symbols[size] = val; + m->size++; + return 0; +} + +static int update_model2_to_6(PixelModel3 *m, uint8_t value, int a4) +{ + PixelModel3 n = {0}; + int c, d, e, f, g, q; + + n.type = 6; + n.length = a4; + + memset(n.symbols, 1u, a4); + + c = m->size; + d = 256 - c + (64 * c + 64); + for (e = 0; d <= 2048; e++) { + d <<= 1; + } + + g = q = 0; + AV_QSORT(m->symbols, c, uint8_t, cmpbytes); + for (f = d = 0; f < c; f++) { + int p = f; + int k = m->symbols[p]; + int l; + g = g + (k - q); + + if (k == value) { + d = p; + q = 128; + } else { + q = 64; + } + l = q << e; + n.freqs[2 * p] = l; + n.freqs[2 * p + 1] = g << e; + n.symbols[p] = k; + n.cnts[p] = l - (l >> 1); + g += q; + q = k + 1; + } + n.size = c; + n.fshift = e; + calc_sum(&n); + + if (d > 0) { + c = n.freqs[0]; + e = n.freqs[1]; + g = n.freqs[2 * d + 1]; + n.freqs[0] = n.freqs[2 * d]; + n.freqs[1] = g; + n.freqs[2 * d] = c; + n.freqs[2 * d + 1] = e; + FFSWAP(uint16_t, n.cnts[0], n.cnts[d]); + FFSWAP(uint8_t, n.symbols[0], n.symbols[d]); + } + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int update_model2_to_3(PixelModel3 *m, uint32_t val) +{ + PixelModel3 n = {0}; + uint32_t size; + + n.type = 3; + n.size = m->size + 1; + + size = m->size; + for (int i = 0; i < size; i++) + n.symbols[i] = m->symbols[i]; + n.symbols[size] = val; + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int decode_static2(PixelModel3 *m, uint32_t val) +{ + uint32_t size; + + size = m->size; + for (int i = 0; i < size; i++) { + if (val == m->symbols[i]) { + int a; + + if (m->size <= 32) + a = 32; + else + a = 64; + return update_model2_to_6(m, val, a); + } + } + + if (size >= 64) + return update_model2_to_3(m, val); + + m->symbols[size] = val; + m->size++; + + return 0; +} + +static int update_model3_to_7(PixelModel3 *m, uint8_t value) +{ + PixelModel3 n = {0}; + int c, d, e, f, g, q; + + n.type = 7; + + for (c = 0; c < 256; c++) { + d = c; + n.freqs[d] = 1; + n.cnts[d] = 1; + } + + for (c = m->size, d = (4096 - (256 - c)) / (c + 1) | 0, e = d - (d >> 1), g = 0; g < c;) { + q = g++; + q = m->symbols[q]; + n.freqs[q] = d; + n.cnts[q] = e; + } + n.freqs[value] += d; + n.cnts[value] += 16; + for (d = c = n.cntsum = 0; 256 > d; d++) { + e = d; + n.cntsum += n.cnts[e]; + n.freqs1[e] = c; + for (g = n.freqs[e], q = c + 128 - 1 >> 7, f = (c + g - 1 >> 7) + 1; q < f; q++) { + n.dectab[q] = e; + } + c += g; + } + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static int decode_static3(PixelModel3 *m, uint32_t val) +{ + uint32_t size = m->size; + + for (int i = 0; i < size; i++) { + if (val == m->symbols[i]) + return update_model3_to_7(m, val); + } + + if (size >= 256) + return 0; + + m->symbols[size] = val; + m->size++; + return 0; +} + +static void sync_code3(GetByteContext *gb, RangeCoder *rc) +{ + rc->code1++; + if (rc->code1 == 0x20000) { + rc->code = bytestream2_get_le32(gb); + rc->code1 = 0; + } +} + +static int decode_value3(SCPRContext *s, uint32_t max, uint32_t *cntsum, + uint16_t *freqs1, uint16_t *freqs2, + uint16_t *cnts, uint8_t *dectable, + uint32_t *value) +{ + GetByteContext *gb = &s->gb; + RangeCoder *rc = &s->rc; + uint32_t r, y, a, b, e, g, q; + + r = dectable[(rc->code & 0xFFFu) >> 7]; + if (r < max) { + while (freqs2[r + 1] <= (rc->code & 0xFFF)) { + if (++r >= max) + break; + } + } + + cnts[r] += 16; + a = freqs1[r]; + b = freqs2[r]; + *cntsum += 16; + if (*cntsum + 16 > 4096) { + *cntsum = 0; + for (int c = 0, i = 0; i < max + 1; i++) { + e = cnts[i]; + freqs2[i] = c; + freqs1[i] = e; + g = (c + 127) >> 7; + c += e; + q = ((c - 1) >> 7) + 1; + if (q > g) { + for (int j = 0; j < q - g; j++) + dectable[j + g] = i; + } + y = e - (e >> 1); + cnts[i] = y; + *cntsum += y; + } + } + + decode3(gb, rc, a, b); + sync_code3(gb, rc); + + *value = r; + + return 0; +} + +static void calc_sum5(PixelModel3 *m) +{ + uint32_t a; + + a = 256 - m->size; + for (int b = 0; b < m->size; b++) + a += m->freqs[b]; + m->cntsum = a; +} + +static int update_model4_to_5(PixelModel3 *m, uint32_t value) +{ + PixelModel3 n = {0}; + int c, e, g, totfr; + + n.type = 5; + + for (c = 0, e = 0; c < m->size && m->symbols[c] < value; c++) { + n.symbols[c] = m->symbols[c]; + e += n.freqs[c] = m->freqs[c]; + } + + g = c; + n.symbols[g] = value; + e += n.freqs[g++] = 50; + for (; c < m->size; g++, c++) { + n.symbols[g] = m->symbols[c]; + e += n.freqs[g] = m->freqs[c]; + } + n.size = m->size + 1; + if (e > 4096) + rescale(&n, &totfr); + + calc_sum5(&n); + + memcpy(m, &n, sizeof(n)); + + return 0; +} + +static signed int decode_unit3(SCPRContext *s, PixelModel3 *m, uint32_t code, uint32_t *value) +{ + PixelModel3 n = {0}; + GetByteContext *gb = &s->gb; + RangeCoder *rc = &s->rc; + uint16_t a = 0, b = 0; + uint32_t param; + int type; + + type = m->type; + switch (type) { + case 0: + *value = bytestream2_get_byte(&s->gb); + m->type = 1; + m->size = 1; + m->symbols[0] = *value; + sync_code3(gb, rc); + break; + case 1: + *value = bytestream2_get_byte(&s->gb); + decode_static1(m, *value); + sync_code3(gb, rc); + break; + case 2: + *value = bytestream2_get_byte(&s->gb); + decode_static2(m, *value); + sync_code3(gb, rc); + break; + case 3: + *value = bytestream2_get_byte(&s->gb); + decode_static3(m, *value); + sync_code3(gb, rc); + break; + case 4: + param = m->freqs[0] + m->freqs[1] + m->freqs[2] + m->freqs[3] + 256 - m->size; + if (!decode_adaptive45(m, code, value, &a, &b, ¶m, 4)) { + update_model4_to_5(m, *value); + } + decode3(gb, rc, a, b); + sync_code3(gb, rc); + break; + case 5: + if (!decode_adaptive45(m, code, value, &a, &b, &m->cntsum, 16)) { + update_model5_to_6(&n, m, *value); + } + decode3(gb, rc, a, b); + sync_code3(gb, rc); + break; + case 6: + if (!decode_adaptive6(m, code, value, &a, &b)) { + update_model6_to_7(&n, m); + } + decode3(gb, rc, a, b); + sync_code3(gb, rc); + break; + case 7: + return decode_value3(s, 255, &m->cntsum, + m->freqs, m->freqs1, + m->cnts, m->dectab, value); + } + return 0; +} + +static int decode_units3(SCPRContext * s, uint32_t *red, + uint32_t *green, uint32_t *blue, + int *cx, int *cx1) +{ + RangeCoder *rc = &s->rc; + + decode_unit3(s, &s->pixel_model3[0][*cx + *cx1], rc->code & 0xFFF, red); + + *cx1 = (*cx << 6) & 0xFC0; + *cx = *red >> 2; + + decode_unit3(s, &s->pixel_model3[1][*cx + *cx1], rc->code & 0xFFF, green); + + *cx1 = (*cx << 6) & 0xFC0; + *cx = *green >> 2; + + decode_unit3(s, &s->pixel_model3[2][*cx + *cx1], rc->code & 0xFFF, blue); + + *cx1 = (*cx << 6) & 0xFC0; + *cx = *blue >> 2; + + return 0; +} + +static void init_rangecoder3(RangeCoder *rc, GetByteContext *gb) +{ + rc->code = bytestream2_get_le32(gb); + rc->code1 = 0; +} + +static int decompress_i3(AVCodecContext *avctx, uint32_t *dst, int linesize) +{ + SCPRContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + RangeCoder *rc = &s->rc; + int cx = 0, cx1 = 0, k = 0; + int run, off, y = 0, x = 0, ret; + uint32_t backstep = linesize - avctx->width; + uint32_t clr = 0, lx, ly, ptype, r, g, b; + + bytestream2_skip(gb, 1); + init_rangecoder3(rc, gb); + reinit_tables3(s); + + while (k < avctx->width + 1) { + decode_units3(s, &r, &g, &b, &cx, &cx1); + ret = decode_value3(s, 255, &s->run_model3[0].cntsum, + s->run_model3[0].freqs[0], + s->run_model3[0].freqs[1], + s->run_model3[0].cnts, + s->run_model3[0].dectab, &run); + if (ret < 0) + return ret; + if (run <= 0) + return AVERROR_INVALIDDATA; + + clr = (b << 16) + (g << 8) + r; + k += run; + while (run-- > 0) { + if (y >= avctx->height) + return AVERROR_INVALIDDATA; + + dst[y * linesize + x] = clr; + lx = x; + ly = y; + x++; + if (x >= avctx->width) { + x = 0; + y++; + } + } + } + off = -linesize - 1; + ptype = 0; + + while (x < avctx->width && y < avctx->height) { + ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum, + s->op_model3[ptype].freqs[0], + s->op_model3[ptype].freqs[1], + s->op_model3[ptype].cnts, + s->op_model3[ptype].dectab, &ptype); + if (ret < 0) + return ret; + if (ptype == 0) { + decode_units3(s, &r, &g, &b, &cx, &cx1); + clr = (b << 16) + (g << 8) + r; + } + if (ptype > 5) + return AVERROR_INVALIDDATA; + ret = decode_value3(s, 255, &s->run_model3[ptype].cntsum, + s->run_model3[ptype].freqs[0], + s->run_model3[ptype].freqs[1], + s->run_model3[ptype].cnts, + s->run_model3[ptype].dectab, &run); + if (ret < 0) + return ret; + if (run <= 0) + return AVERROR_INVALIDDATA; + + ret = decode_run_i(avctx, ptype, run, &x, &y, clr, + dst, linesize, &lx, &ly, + backstep, off, &cx, &cx1); + if (run < 0) + return ret; + } + + return 0; +} + +static int decompress_p3(AVCodecContext *avctx, + uint32_t *dst, int linesize, + uint32_t *prev, int plinesize) +{ + SCPRContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + int ret, temp, min, max, x, y, cx = 0, cx1 = 0; + int backstep = linesize - avctx->width; + int mvx = 0, mvy = 0; + + if (bytestream2_get_byte(gb) == 0) + return 0; + init_rangecoder3(&s->rc, gb); + + ret = decode_value3(s, 255, &s->range_model3.cntsum, + s->range_model3.freqs[0], + s->range_model3.freqs[1], + s->range_model3.cnts, + s->range_model3.dectab, &min); + ret |= decode_value3(s, 255, &s->range_model3.cntsum, + s->range_model3.freqs[0], + s->range_model3.freqs[1], + s->range_model3.cnts, + s->range_model3.dectab, &temp); + min += temp << 8; + ret |= decode_value3(s, 255, &s->range_model3.cntsum, + s->range_model3.freqs[0], + s->range_model3.freqs[1], + s->range_model3.cnts, + s->range_model3.dectab, &max); + ret |= decode_value3(s, 255, &s->range_model3.cntsum, + s->range_model3.freqs[0], + s->range_model3.freqs[1], + s->range_model3.cnts, + s->range_model3.dectab, &temp); + if (ret < 0) + return ret; + + max += temp << 8; + memset(s->blocks, 0, sizeof(*s->blocks) * s->nbcount); + + while (min <= max) { + int fill, count; + + ret = decode_value3(s, 4, &s->fill_model3.cntsum, + s->fill_model3.freqs[0], + s->fill_model3.freqs[1], + s->fill_model3.cnts, + s->fill_model3.dectab, &fill); + ret |= decode_value3(s, 255, &s->count_model3.cntsum, + s->count_model3.freqs[0], + s->count_model3.freqs[1], + s->count_model3.cnts, + s->count_model3.dectab, &count); + if (ret < 0) + return ret; + + while (min < s->nbcount && count-- > 0) { + s->blocks[min++] = fill; + } + } + + for (y = 0; y < s->nby; y++) { + for (x = 0; x < s->nbx; x++) { + int sy1 = 0, sy2 = 16, sx1 = 0, sx2 = 16; + + if (s->blocks[y * s->nbx + x] == 0) + continue; + + if (((s->blocks[y * s->nbx + x] + 1) & 1) > 0) { + ret = decode_value3(s, 15, &s->sxy_model3[0].cntsum, + s->sxy_model3[0].freqs[0], + s->sxy_model3[0].freqs[1], + s->sxy_model3[0].cnts, + s->sxy_model3[0].dectab, &sx1); + ret |= decode_value3(s, 15, &s->sxy_model3[1].cntsum, + s->sxy_model3[1].freqs[0], + s->sxy_model3[1].freqs[1], + s->sxy_model3[1].cnts, + s->sxy_model3[1].dectab, &sy1); + ret |= decode_value3(s, 15, &s->sxy_model3[2].cntsum, + s->sxy_model3[2].freqs[0], + s->sxy_model3[2].freqs[1], + s->sxy_model3[2].cnts, + s->sxy_model3[2].dectab, &sx2); + ret |= decode_value3(s, 15, &s->sxy_model3[3].cntsum, + s->sxy_model3[3].freqs[0], + s->sxy_model3[3].freqs[1], + s->sxy_model3[3].cnts, + s->sxy_model3[3].dectab, &sy2); + if (ret < 0) + return ret; + + sx2++; + sy2++; + } + if (((s->blocks[y * s->nbx + x] + 3) & 2) > 0) { + int i, a, b, c, j, by = y * 16, bx = x * 16; + uint32_t code; + + a = s->rc.code & 0xFFF; + c = 1; + + if (a < 0x800) + c = 0; + b = 2048; + if (!c) + b = 0; + + code = a + ((s->rc.code >> 1) & 0xFFFFF800) - b; + while (code < 0x800000 && bytestream2_get_bytes_left(gb) > 0) + code = bytestream2_get_byte(gb) | (code << 8); + s->rc.code = code; + + sync_code3(gb, &s->rc); + + if (!c) { + ret = decode_value3(s, 511, &s->mv_model3[0].cntsum, + s->mv_model3[0].freqs[0], + s->mv_model3[0].freqs[1], + s->mv_model3[0].cnts, + s->mv_model3[0].dectab, &mvx); + ret |= decode_value3(s, 511, &s->mv_model3[1].cntsum, + s->mv_model3[1].freqs[0], + s->mv_model3[1].freqs[1], + s->mv_model3[1].cnts, + s->mv_model3[1].dectab, &mvy); + if (ret < 0) + return ret; + + mvx -= 256; + mvy -= 256; + } + + if (by + mvy + sy1 < 0 || bx + mvx + sx1 < 0 || + by + mvy + sy1 >= avctx->height || bx + mvx + sx1 >= avctx->width) + return AVERROR_INVALIDDATA; + + for (i = 0; i < sy2 - sy1 && (by + sy1 + i) < avctx->height && (by + mvy + sy1 + i) < avctx->height; i++) { + for (j = 0; j < sx2 - sx1 && (bx + sx1 + j) < avctx->width && (bx + mvx + sx1 + j) < avctx->width; j++) { + dst[(by + i + sy1) * linesize + bx + sx1 + j] = prev[(by + mvy + sy1 + i) * plinesize + bx + sx1 + mvx + j]; + } + } + } else { + int run, bx = x * 16 + sx1, by = y * 16 + sy1; + uint32_t clr, ptype = 0, r, g, b; + + for (; by < y * 16 + sy2 && by < avctx->height;) { + ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum, + s->op_model3[ptype].freqs[0], + s->op_model3[ptype].freqs[1], + s->op_model3[ptype].cnts, + s->op_model3[ptype].dectab, &ptype); + if (ret < 0) + return ret; + if (ptype == 0) { + ret = decode_units3(s, &r, &g, &b, &cx, &cx1); + if (ret < 0) + return ret; + + clr = (b << 16) + (g << 8) + r; + } + if (ptype > 5) + return AVERROR_INVALIDDATA; + ret = decode_value3(s, 255, &s->run_model3[ptype].cntsum, + s->run_model3[ptype].freqs[0], + s->run_model3[ptype].freqs[1], + s->run_model3[ptype].cnts, + s->run_model3[ptype].dectab, &run); + if (ret < 0) + return ret; + if (run <= 0) + return AVERROR_INVALIDDATA; + + ret = decode_run_p(avctx, ptype, run, x, y, clr, + dst, prev, linesize, plinesize, &bx, &by, + backstep, sx1, sx2, &cx, &cx1); + if (ret < 0) + return ret; + } + } + } + } + + return 0; +} diff --git a/libavcodec/scpr3.h b/libavcodec/scpr3.h new file mode 100644 index 0000000000..92ad968882 --- /dev/null +++ b/libavcodec/scpr3.h @@ -0,0 +1,82 @@ +/* + * ScreenPressor version 3 decoder + * + * Copyright (c) 2017 Paul B Mahol + * + * 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 + */ + +#ifndef AVCODEC_SCPR3_H +#define AVCODEC_SCPR3_H + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" + +typedef struct PixelModel3 { + uint8_t type; + uint8_t length; + uint8_t maxpos; + uint8_t fshift; + uint16_t size; + uint32_t cntsum; + uint8_t symbols[256]; + uint16_t freqs[256]; + uint16_t freqs1[256]; + uint16_t cnts[256]; + uint8_t dectab[32]; +} PixelModel3; + +typedef struct FillModel3 { + uint32_t cntsum; + uint16_t freqs[2][5]; + uint16_t cnts[5]; + uint8_t dectab[32]; +} FillModel3; + +typedef struct OpModel3 { + uint32_t cntsum; + uint16_t freqs[2][6]; + uint16_t cnts[6]; + uint8_t dectab[32]; +} OpModel3; + +typedef struct RunModel3 { + uint32_t cntsum; + uint16_t freqs[2][256]; + uint16_t cnts[256]; + uint8_t dectab[32]; +} RunModel3; + +typedef struct SxyModel3 { + uint32_t cntsum; + uint16_t freqs[2][16]; + uint16_t cnts[16]; + uint8_t dectab[32]; +} SxyModel3; + +typedef struct MVModel3 { + uint32_t cntsum; + uint16_t freqs[2][512]; + uint16_t cnts[512]; + uint8_t dectab[32]; +} MVModel3; + +#endif /* AVCODEC_SCPR3_H */