1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * ScreenPressor decoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2017 Paul B Mahol 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#ifndef AVCODEC_SCPR_H 24cabdff1aSopenharmony_ci#define AVCODEC_SCPR_H 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "avcodec.h" 27cabdff1aSopenharmony_ci#include "bytestream.h" 28cabdff1aSopenharmony_ci#include "scpr3.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_citypedef struct RangeCoder { 31cabdff1aSopenharmony_ci uint32_t code; 32cabdff1aSopenharmony_ci uint32_t range; 33cabdff1aSopenharmony_ci uint32_t code1; 34cabdff1aSopenharmony_ci} RangeCoder; 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_citypedef struct PixelModel { 37cabdff1aSopenharmony_ci uint32_t freq[256]; 38cabdff1aSopenharmony_ci uint32_t lookup[16]; 39cabdff1aSopenharmony_ci uint32_t total_freq; 40cabdff1aSopenharmony_ci} PixelModel; 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_citypedef struct SCPRContext { 43cabdff1aSopenharmony_ci int version; 44cabdff1aSopenharmony_ci AVFrame *last_frame; 45cabdff1aSopenharmony_ci AVFrame *current_frame; 46cabdff1aSopenharmony_ci GetByteContext gb; 47cabdff1aSopenharmony_ci RangeCoder rc; 48cabdff1aSopenharmony_ci PixelModel pixel_model[3][4096]; 49cabdff1aSopenharmony_ci uint32_t op_model[6][7]; 50cabdff1aSopenharmony_ci uint32_t run_model[6][257]; 51cabdff1aSopenharmony_ci uint32_t range_model[257]; 52cabdff1aSopenharmony_ci uint32_t count_model[257]; 53cabdff1aSopenharmony_ci uint32_t fill_model[6]; 54cabdff1aSopenharmony_ci uint32_t sxy_model[4][17]; 55cabdff1aSopenharmony_ci uint32_t mv_model[2][513]; 56cabdff1aSopenharmony_ci uint32_t nbx, nby; 57cabdff1aSopenharmony_ci uint32_t nbcount; 58cabdff1aSopenharmony_ci uint32_t *blocks; 59cabdff1aSopenharmony_ci uint32_t cbits; 60cabdff1aSopenharmony_ci int cxshift; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci PixelModel3 pixel_model3[3][4096]; 63cabdff1aSopenharmony_ci RunModel3 run_model3[6]; 64cabdff1aSopenharmony_ci RunModel3 range_model3; 65cabdff1aSopenharmony_ci RunModel3 count_model3; 66cabdff1aSopenharmony_ci FillModel3 fill_model3; 67cabdff1aSopenharmony_ci SxyModel3 sxy_model3[4]; 68cabdff1aSopenharmony_ci MVModel3 mv_model3[2]; 69cabdff1aSopenharmony_ci OpModel3 op_model3[6]; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci int (*get_freq)(RangeCoder *rc, uint32_t total_freq, uint32_t *freq); 72cabdff1aSopenharmony_ci int (*decode)(GetByteContext *gb, RangeCoder *rc, uint32_t cumFreq, uint32_t freq, uint32_t total_freq); 73cabdff1aSopenharmony_ci} SCPRContext; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_cistatic int decode_run_i(AVCodecContext *avctx, uint32_t ptype, int run, 76cabdff1aSopenharmony_ci int *px, int *py, uint32_t clr, uint32_t *dst, 77cabdff1aSopenharmony_ci int linesize, uint32_t *plx, uint32_t *ply, 78cabdff1aSopenharmony_ci uint32_t backstep, int off, int *cx, int *cx1) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci uint32_t r, g, b; 81cabdff1aSopenharmony_ci int z; 82cabdff1aSopenharmony_ci int x = *px, 83cabdff1aSopenharmony_ci y = *py; 84cabdff1aSopenharmony_ci uint32_t lx = *plx, 85cabdff1aSopenharmony_ci ly = *ply; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci if (y >= avctx->height) 88cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci switch (ptype) { 91cabdff1aSopenharmony_ci case 0: 92cabdff1aSopenharmony_ci while (run-- > 0) { 93cabdff1aSopenharmony_ci dst[y * linesize + x] = clr; 94cabdff1aSopenharmony_ci lx = x; 95cabdff1aSopenharmony_ci ly = y; 96cabdff1aSopenharmony_ci (x)++; 97cabdff1aSopenharmony_ci if (x >= avctx->width) { 98cabdff1aSopenharmony_ci x = 0; 99cabdff1aSopenharmony_ci (y)++; 100cabdff1aSopenharmony_ci if (y >= avctx->height && run) 101cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci break; 105cabdff1aSopenharmony_ci case 1: 106cabdff1aSopenharmony_ci while (run-- > 0) { 107cabdff1aSopenharmony_ci dst[y * linesize + x] = dst[ly * linesize + lx]; 108cabdff1aSopenharmony_ci lx = x; 109cabdff1aSopenharmony_ci ly = y; 110cabdff1aSopenharmony_ci (x)++; 111cabdff1aSopenharmony_ci if (x >= avctx->width) { 112cabdff1aSopenharmony_ci x = 0; 113cabdff1aSopenharmony_ci (y)++; 114cabdff1aSopenharmony_ci if (y >= avctx->height && run) 115cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci } 118cabdff1aSopenharmony_ci clr = dst[ly * linesize + lx]; 119cabdff1aSopenharmony_ci break; 120cabdff1aSopenharmony_ci case 2: 121cabdff1aSopenharmony_ci if (y < 1) 122cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci while (run-- > 0) { 125cabdff1aSopenharmony_ci clr = dst[y * linesize + x + off + 1]; 126cabdff1aSopenharmony_ci dst[y * linesize + x] = clr; 127cabdff1aSopenharmony_ci lx = x; 128cabdff1aSopenharmony_ci ly = y; 129cabdff1aSopenharmony_ci (x)++; 130cabdff1aSopenharmony_ci if (x >= avctx->width) { 131cabdff1aSopenharmony_ci x = 0; 132cabdff1aSopenharmony_ci (y)++; 133cabdff1aSopenharmony_ci if (y >= avctx->height && run) 134cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci } 137cabdff1aSopenharmony_ci break; 138cabdff1aSopenharmony_ci case 4: 139cabdff1aSopenharmony_ci if (y < 1 || (y == 1 && x == 0)) 140cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci while (run-- > 0) { 143cabdff1aSopenharmony_ci uint8_t *odst = (uint8_t *)dst; 144cabdff1aSopenharmony_ci int off1 = (ly * linesize + lx) * 4; 145cabdff1aSopenharmony_ci int off2 = ((y * linesize + x) + off) * 4; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci if (x == 0) { 148cabdff1aSopenharmony_ci z = backstep * 4; 149cabdff1aSopenharmony_ci } else { 150cabdff1aSopenharmony_ci z = 0; 151cabdff1aSopenharmony_ci } 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci r = odst[off1] + 154cabdff1aSopenharmony_ci odst[off2 + 4] - 155cabdff1aSopenharmony_ci odst[off2 - z ]; 156cabdff1aSopenharmony_ci g = odst[off1 + 1] + 157cabdff1aSopenharmony_ci odst[off2 + 5] - 158cabdff1aSopenharmony_ci odst[off2 - z + 1]; 159cabdff1aSopenharmony_ci b = odst[off1 + 2] + 160cabdff1aSopenharmony_ci odst[off2 + 6] - 161cabdff1aSopenharmony_ci odst[off2 - z + 2]; 162cabdff1aSopenharmony_ci clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); 163cabdff1aSopenharmony_ci dst[y * linesize + x] = clr; 164cabdff1aSopenharmony_ci lx = x; 165cabdff1aSopenharmony_ci ly = y; 166cabdff1aSopenharmony_ci (x)++; 167cabdff1aSopenharmony_ci if (x >= avctx->width) { 168cabdff1aSopenharmony_ci x = 0; 169cabdff1aSopenharmony_ci (y)++; 170cabdff1aSopenharmony_ci if (y >= avctx->height && run) 171cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci break; 175cabdff1aSopenharmony_ci case 5: 176cabdff1aSopenharmony_ci if (y < 1 || (y == 1 && x == 0)) 177cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci while (run-- > 0) { 180cabdff1aSopenharmony_ci if (x == 0) { 181cabdff1aSopenharmony_ci z = backstep; 182cabdff1aSopenharmony_ci } else { 183cabdff1aSopenharmony_ci z = 0; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci clr = dst[y * linesize + x + off - z]; 187cabdff1aSopenharmony_ci dst[y * linesize + x] = clr; 188cabdff1aSopenharmony_ci lx = x; 189cabdff1aSopenharmony_ci ly = y; 190cabdff1aSopenharmony_ci (x)++; 191cabdff1aSopenharmony_ci if (x >= avctx->width) { 192cabdff1aSopenharmony_ci x = 0; 193cabdff1aSopenharmony_ci (y)++; 194cabdff1aSopenharmony_ci if (y >= avctx->height && run) 195cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci break; 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci *px = x; 202cabdff1aSopenharmony_ci *py = y; 203cabdff1aSopenharmony_ci *plx= lx; 204cabdff1aSopenharmony_ci *ply= ly; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (avctx->bits_per_coded_sample == 16) { 207cabdff1aSopenharmony_ci *cx1 = (clr & 0x3F00) >> 2; 208cabdff1aSopenharmony_ci *cx = (clr & 0x3FFFFF) >> 16; 209cabdff1aSopenharmony_ci } else { 210cabdff1aSopenharmony_ci *cx1 = (clr & 0xFC00) >> 4; 211cabdff1aSopenharmony_ci *cx = (clr & 0xFFFFFF) >> 18; 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci return 0; 215cabdff1aSopenharmony_ci} 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_cistatic int decode_run_p(AVCodecContext *avctx, uint32_t ptype, int run, 218cabdff1aSopenharmony_ci int x, int y, uint32_t clr, 219cabdff1aSopenharmony_ci uint32_t *dst, uint32_t *prev, 220cabdff1aSopenharmony_ci int linesize, int plinesize, 221cabdff1aSopenharmony_ci uint32_t *bx, uint32_t *by, 222cabdff1aSopenharmony_ci uint32_t backstep, int sx1, int sx2, 223cabdff1aSopenharmony_ci int *cx, int *cx1) 224cabdff1aSopenharmony_ci{ 225cabdff1aSopenharmony_ci uint32_t r, g, b; 226cabdff1aSopenharmony_ci int z; 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci switch (ptype) { 229cabdff1aSopenharmony_ci case 0: 230cabdff1aSopenharmony_ci while (run-- > 0) { 231cabdff1aSopenharmony_ci if (*by >= avctx->height) 232cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 235cabdff1aSopenharmony_ci (*bx)++; 236cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 237cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 238cabdff1aSopenharmony_ci (*by)++; 239cabdff1aSopenharmony_ci } 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci break; 242cabdff1aSopenharmony_ci case 1: 243cabdff1aSopenharmony_ci while (run-- > 0) { 244cabdff1aSopenharmony_ci if (*bx == 0) { 245cabdff1aSopenharmony_ci if (*by < 1) 246cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 247cabdff1aSopenharmony_ci z = backstep; 248cabdff1aSopenharmony_ci } else { 249cabdff1aSopenharmony_ci z = 0; 250cabdff1aSopenharmony_ci } 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci if (*by >= avctx->height) 253cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci clr = dst[*by * linesize + *bx - 1 - z]; 256cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 257cabdff1aSopenharmony_ci (*bx)++; 258cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 259cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 260cabdff1aSopenharmony_ci (*by)++; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci } 263cabdff1aSopenharmony_ci break; 264cabdff1aSopenharmony_ci case 2: 265cabdff1aSopenharmony_ci while (run-- > 0) { 266cabdff1aSopenharmony_ci if (*by < 1 || *by >= avctx->height) 267cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci clr = dst[(*by - 1) * linesize + *bx]; 270cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 271cabdff1aSopenharmony_ci (*bx)++; 272cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 273cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 274cabdff1aSopenharmony_ci (*by)++; 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci break; 278cabdff1aSopenharmony_ci case 3: 279cabdff1aSopenharmony_ci while (run-- > 0) { 280cabdff1aSopenharmony_ci if (*by >= avctx->height) 281cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci clr = prev[*by * plinesize + *bx]; 284cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 285cabdff1aSopenharmony_ci (*bx)++; 286cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 287cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 288cabdff1aSopenharmony_ci (*by)++; 289cabdff1aSopenharmony_ci } 290cabdff1aSopenharmony_ci } 291cabdff1aSopenharmony_ci break; 292cabdff1aSopenharmony_ci case 4: 293cabdff1aSopenharmony_ci while (run-- > 0) { 294cabdff1aSopenharmony_ci uint8_t *odst = (uint8_t *)dst; 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci if (*by < 1 || *by >= avctx->height) 297cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci if (*bx == 0) { 300cabdff1aSopenharmony_ci if (*by < 2) 301cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 302cabdff1aSopenharmony_ci z = backstep; 303cabdff1aSopenharmony_ci } else { 304cabdff1aSopenharmony_ci z = 0; 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci r = odst[((*by - 1) * linesize + *bx) * 4] + 308cabdff1aSopenharmony_ci odst[(*by * linesize + *bx - 1 - z) * 4] - 309cabdff1aSopenharmony_ci odst[((*by - 1) * linesize + *bx - 1 - z) * 4]; 310cabdff1aSopenharmony_ci g = odst[((*by - 1) * linesize + *bx) * 4 + 1] + 311cabdff1aSopenharmony_ci odst[(*by * linesize + *bx - 1 - z) * 4 + 1] - 312cabdff1aSopenharmony_ci odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1]; 313cabdff1aSopenharmony_ci b = odst[((*by - 1) * linesize + *bx) * 4 + 2] + 314cabdff1aSopenharmony_ci odst[(*by * linesize + *bx - 1 - z) * 4 + 2] - 315cabdff1aSopenharmony_ci odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2]; 316cabdff1aSopenharmony_ci clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); 317cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 318cabdff1aSopenharmony_ci (*bx)++; 319cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 320cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 321cabdff1aSopenharmony_ci (*by)++; 322cabdff1aSopenharmony_ci } 323cabdff1aSopenharmony_ci } 324cabdff1aSopenharmony_ci break; 325cabdff1aSopenharmony_ci case 5: 326cabdff1aSopenharmony_ci while (run-- > 0) { 327cabdff1aSopenharmony_ci if (*by < 1 || *by >= avctx->height) 328cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 329cabdff1aSopenharmony_ci 330cabdff1aSopenharmony_ci if (*bx == 0) { 331cabdff1aSopenharmony_ci if (*by < 2) 332cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 333cabdff1aSopenharmony_ci z = backstep; 334cabdff1aSopenharmony_ci } else { 335cabdff1aSopenharmony_ci z = 0; 336cabdff1aSopenharmony_ci } 337cabdff1aSopenharmony_ci 338cabdff1aSopenharmony_ci clr = dst[(*by - 1) * linesize + *bx - 1 - z]; 339cabdff1aSopenharmony_ci dst[*by * linesize + *bx] = clr; 340cabdff1aSopenharmony_ci (*bx)++; 341cabdff1aSopenharmony_ci if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { 342cabdff1aSopenharmony_ci *bx = x * 16 + sx1; 343cabdff1aSopenharmony_ci (*by)++; 344cabdff1aSopenharmony_ci } 345cabdff1aSopenharmony_ci } 346cabdff1aSopenharmony_ci break; 347cabdff1aSopenharmony_ci } 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_ci if (avctx->bits_per_coded_sample == 16) { 350cabdff1aSopenharmony_ci *cx1 = (clr & 0x3F00) >> 2; 351cabdff1aSopenharmony_ci *cx = (clr & 0x3FFFFF) >> 16; 352cabdff1aSopenharmony_ci } else { 353cabdff1aSopenharmony_ci *cx1 = (clr & 0xFC00) >> 4; 354cabdff1aSopenharmony_ci *cx = (clr & 0xFFFFFF) >> 18; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci return 0; 358cabdff1aSopenharmony_ci} 359cabdff1aSopenharmony_ci 360cabdff1aSopenharmony_ci#endif /* AVCODEC_SCPR_H */ 361