123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /*
- * 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 <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #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 *px, int *py, uint32_t clr, uint32_t *dst,
- int linesize, uint32_t *plx, uint32_t *ply,
- uint32_t backstep, int off, int *cx, int *cx1)
- {
- uint32_t r, g, b;
- int z;
- int x = *px,
- y = *py;
- uint32_t lx = *plx,
- ly = *ply;
- if (y >= avctx->height)
- return AVERROR_INVALIDDATA;
- switch (ptype) {
- case 0:
- while (run-- > 0) {
- dst[y * linesize + x] = clr;
- lx = x;
- ly = y;
- (x)++;
- if (x >= avctx->width) {
- x = 0;
- (y)++;
- if (y >= avctx->height && run)
- return AVERROR_INVALIDDATA;
- }
- }
- break;
- case 1:
- while (run-- > 0) {
- dst[y * linesize + x] = dst[ly * linesize + lx];
- lx = x;
- ly = y;
- (x)++;
- if (x >= avctx->width) {
- x = 0;
- (y)++;
- if (y >= avctx->height && run)
- return AVERROR_INVALIDDATA;
- }
- }
- clr = dst[ly * linesize + lx];
- break;
- case 2:
- if (y < 1)
- return AVERROR_INVALIDDATA;
- while (run-- > 0) {
- clr = dst[y * linesize + x + off + 1];
- dst[y * linesize + x] = clr;
- lx = x;
- ly = y;
- (x)++;
- if (x >= avctx->width) {
- x = 0;
- (y)++;
- if (y >= avctx->height && run)
- return AVERROR_INVALIDDATA;
- }
- }
- break;
- case 4:
- if (y < 1 || (y == 1 && x == 0))
- return AVERROR_INVALIDDATA;
- while (run-- > 0) {
- uint8_t *odst = (uint8_t *)dst;
- int off1 = (ly * linesize + lx) * 4;
- int off2 = ((y * linesize + x) + off) * 4;
- if (x == 0) {
- z = backstep * 4;
- } else {
- z = 0;
- }
- r = odst[off1] +
- odst[off2 + 4] -
- odst[off2 - z ];
- g = odst[off1 + 1] +
- odst[off2 + 5] -
- odst[off2 - z + 1];
- b = odst[off1 + 2] +
- odst[off2 + 6] -
- odst[off2 - z + 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)++;
- if (y >= avctx->height && run)
- return AVERROR_INVALIDDATA;
- }
- }
- break;
- case 5:
- if (y < 1 || (y == 1 && x == 0))
- return AVERROR_INVALIDDATA;
- while (run-- > 0) {
- 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)++;
- if (y >= avctx->height && run)
- return AVERROR_INVALIDDATA;
- }
- }
- break;
- }
- *px = x;
- *py = y;
- *plx= lx;
- *ply= ly;
- 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 */
|