1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Argonaut Games Video decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2020 Paul B Mahol 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include <stdio.h> 23cabdff1aSopenharmony_ci#include <stdlib.h> 24cabdff1aSopenharmony_ci#include <string.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 27cabdff1aSopenharmony_ci#include "libavutil/internal.h" 28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "avcodec.h" 31cabdff1aSopenharmony_ci#include "bytestream.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_citypedef struct ArgoContext { 36cabdff1aSopenharmony_ci GetByteContext gb; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci int bpp; 39cabdff1aSopenharmony_ci int key; 40cabdff1aSopenharmony_ci int mv0[128][2]; 41cabdff1aSopenharmony_ci int mv1[16][2]; 42cabdff1aSopenharmony_ci uint32_t pal[256]; 43cabdff1aSopenharmony_ci AVFrame *frame; 44cabdff1aSopenharmony_ci} ArgoContext; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic int decode_pal8(AVCodecContext *avctx, uint32_t *pal) 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 49cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 50cabdff1aSopenharmony_ci int start, count; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci start = bytestream2_get_le16(gb); 53cabdff1aSopenharmony_ci count = bytestream2_get_le16(gb); 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci if (start + count > 256) 56cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 3 * count) 59cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci for (int i = 0; i < count; i++) 62cabdff1aSopenharmony_ci pal[start + i] = (0xFFU << 24) | bytestream2_get_be24u(gb); 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci return 0; 65cabdff1aSopenharmony_ci} 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic int decode_avcf(AVCodecContext *avctx, AVFrame *frame) 68cabdff1aSopenharmony_ci{ 69cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 70cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 71cabdff1aSopenharmony_ci const int l = frame->linesize[0]; 72cabdff1aSopenharmony_ci const uint8_t *map = gb->buffer; 73cabdff1aSopenharmony_ci uint8_t *dst = frame->data[0]; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2)) 76cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci bytestream2_skipu(gb, 1024); 79cabdff1aSopenharmony_ci for (int y = 0; y < frame->height; y += 2) { 80cabdff1aSopenharmony_ci for (int x = 0; x < frame->width; x += 2) { 81cabdff1aSopenharmony_ci int index = bytestream2_get_byteu(gb); 82cabdff1aSopenharmony_ci const uint8_t *block = map + index * 4; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci dst[x+0] = block[0]; 85cabdff1aSopenharmony_ci dst[x+1] = block[1]; 86cabdff1aSopenharmony_ci dst[x+l] = block[2]; 87cabdff1aSopenharmony_ci dst[x+l+1] = block[3]; 88cabdff1aSopenharmony_ci } 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci dst += frame->linesize[0] * 2; 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci return 0; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_cistatic int decode_alcd(AVCodecContext *avctx, AVFrame *frame) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 99cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 100cabdff1aSopenharmony_ci GetByteContext sb; 101cabdff1aSopenharmony_ci const int l = frame->linesize[0]; 102cabdff1aSopenharmony_ci const uint8_t *map = gb->buffer; 103cabdff1aSopenharmony_ci uint8_t *dst = frame->data[0]; 104cabdff1aSopenharmony_ci uint8_t codes = 0; 105cabdff1aSopenharmony_ci int count = 0; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3)) 108cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci bytestream2_skipu(gb, 1024); 111cabdff1aSopenharmony_ci sb = *gb; 112cabdff1aSopenharmony_ci bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3); 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci for (int y = 0; y < frame->height; y += 2) { 115cabdff1aSopenharmony_ci for (int x = 0; x < frame->width; x += 2) { 116cabdff1aSopenharmony_ci const uint8_t *block; 117cabdff1aSopenharmony_ci int index; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci if (count == 0) { 120cabdff1aSopenharmony_ci codes = bytestream2_get_byteu(&sb); 121cabdff1aSopenharmony_ci count = 8; 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci if (codes & 0x80) { 125cabdff1aSopenharmony_ci index = bytestream2_get_byte(gb); 126cabdff1aSopenharmony_ci block = map + index * 4; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci dst[x+0] = block[0]; 129cabdff1aSopenharmony_ci dst[x+1] = block[1]; 130cabdff1aSopenharmony_ci dst[x+l] = block[2]; 131cabdff1aSopenharmony_ci dst[x+l+1] = block[3]; 132cabdff1aSopenharmony_ci } 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci codes <<= 1; 135cabdff1aSopenharmony_ci count--; 136cabdff1aSopenharmony_ci } 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci dst += frame->linesize[0] * 2; 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci return 0; 142cabdff1aSopenharmony_ci} 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_cistatic int decode_mad1(AVCodecContext *avctx, AVFrame *frame) 145cabdff1aSopenharmony_ci{ 146cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 147cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 148cabdff1aSopenharmony_ci const int w = frame->width; 149cabdff1aSopenharmony_ci const int h = frame->height; 150cabdff1aSopenharmony_ci const int l = frame->linesize[0]; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 153cabdff1aSopenharmony_ci int size, type, pos, dy; 154cabdff1aSopenharmony_ci uint8_t *dst; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci type = bytestream2_get_byte(gb); 157cabdff1aSopenharmony_ci if (type == 0xFF) 158cabdff1aSopenharmony_ci break; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci switch (type) { 161cabdff1aSopenharmony_ci case 8: 162cabdff1aSopenharmony_ci dst = frame->data[0]; 163cabdff1aSopenharmony_ci for (int y = 0; y < h; y += 8) { 164cabdff1aSopenharmony_ci for (int x = 0; x < w; x += 8) { 165cabdff1aSopenharmony_ci int fill = bytestream2_get_byte(gb); 166cabdff1aSopenharmony_ci uint8_t *ddst = dst + x; 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci for (int by = 0; by < 8; by++) { 169cabdff1aSopenharmony_ci memset(ddst, fill, 8); 170cabdff1aSopenharmony_ci ddst += l; 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci dst += 8 * l; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci break; 177cabdff1aSopenharmony_ci case 7: 178cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 179cabdff1aSopenharmony_ci int bsize = bytestream2_get_byte(gb); 180cabdff1aSopenharmony_ci uint8_t *src; 181cabdff1aSopenharmony_ci int count; 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci if (!bsize) 184cabdff1aSopenharmony_ci break; 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci count = bytestream2_get_be16(gb); 187cabdff1aSopenharmony_ci while (count > 0) { 188cabdff1aSopenharmony_ci int mvx, mvy, a, b, c, mx, my; 189cabdff1aSopenharmony_ci int bsize_w, bsize_h; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci bsize_w = bsize_h = bsize; 192cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 4) 193cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 194cabdff1aSopenharmony_ci mvx = bytestream2_get_byte(gb) * bsize; 195cabdff1aSopenharmony_ci mvy = bytestream2_get_byte(gb) * bsize; 196cabdff1aSopenharmony_ci a = bytestream2_get_byte(gb); 197cabdff1aSopenharmony_ci b = bytestream2_get_byte(gb); 198cabdff1aSopenharmony_ci c = ((a & 0x3F) << 8) + b; 199cabdff1aSopenharmony_ci mx = mvx + (c & 0x7F) - 64; 200cabdff1aSopenharmony_ci my = mvy + (c >> 7) - 64; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci if (mvy < 0 || mvy >= h) 203cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci if (mvx < 0 || mvx >= w) 206cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci if (my < 0 || my >= h) 209cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci if (mx < 0 || mx >= w) 212cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci dst = frame->data[0] + mvx + l * mvy; 215cabdff1aSopenharmony_ci src = frame->data[0] + mx + l * my; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci bsize_w = FFMIN3(bsize_w, w - mvx, w - mx); 218cabdff1aSopenharmony_ci bsize_h = FFMIN3(bsize_h, h - mvy, h - my); 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci if (mvy >= my && (mvy != my || mvx >= mx)) { 221cabdff1aSopenharmony_ci src += (bsize_h - 1) * l; 222cabdff1aSopenharmony_ci dst += (bsize_h - 1) * l; 223cabdff1aSopenharmony_ci for (int by = 0; by < bsize_h; by++) { 224cabdff1aSopenharmony_ci memmove(dst, src, bsize_w); 225cabdff1aSopenharmony_ci src -= l; 226cabdff1aSopenharmony_ci dst -= l; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci } else { 229cabdff1aSopenharmony_ci for (int by = 0; by < bsize_h; by++) { 230cabdff1aSopenharmony_ci memmove(dst, src, bsize_w); 231cabdff1aSopenharmony_ci src += l; 232cabdff1aSopenharmony_ci dst += l; 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci count--; 237cabdff1aSopenharmony_ci } 238cabdff1aSopenharmony_ci } 239cabdff1aSopenharmony_ci break; 240cabdff1aSopenharmony_ci case 6: 241cabdff1aSopenharmony_ci dst = frame->data[0]; 242cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < w * h) 243cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 244cabdff1aSopenharmony_ci for (int y = 0; y < h; y++) { 245cabdff1aSopenharmony_ci bytestream2_get_bufferu(gb, dst, w); 246cabdff1aSopenharmony_ci dst += l; 247cabdff1aSopenharmony_ci } 248cabdff1aSopenharmony_ci break; 249cabdff1aSopenharmony_ci case 5: 250cabdff1aSopenharmony_ci dst = frame->data[0]; 251cabdff1aSopenharmony_ci for (int y = 0; y < h; y += 2) { 252cabdff1aSopenharmony_ci for (int x = 0; x < w; x += 2) { 253cabdff1aSopenharmony_ci int fill = bytestream2_get_byte(gb); 254cabdff1aSopenharmony_ci uint8_t *ddst = dst + x; 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_ci fill = (fill << 8) | fill; 257cabdff1aSopenharmony_ci for (int by = 0; by < 2; by++) { 258cabdff1aSopenharmony_ci AV_WN16(ddst, fill); 259cabdff1aSopenharmony_ci 260cabdff1aSopenharmony_ci ddst += l; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci } 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci dst += 2 * l; 265cabdff1aSopenharmony_ci } 266cabdff1aSopenharmony_ci break; 267cabdff1aSopenharmony_ci case 3: 268cabdff1aSopenharmony_ci size = bytestream2_get_le16(gb); 269cabdff1aSopenharmony_ci if (size > 0) { 270cabdff1aSopenharmony_ci int x = bytestream2_get_byte(gb) * 4; 271cabdff1aSopenharmony_ci int y = bytestream2_get_byte(gb) * 4; 272cabdff1aSopenharmony_ci int count = bytestream2_get_byte(gb); 273cabdff1aSopenharmony_ci int fill = bytestream2_get_byte(gb); 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill); 276cabdff1aSopenharmony_ci for (int i = 0; i < count; i++) 277cabdff1aSopenharmony_ci ; 278cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci break; 281cabdff1aSopenharmony_ci case 2: 282cabdff1aSopenharmony_ci dst = frame->data[0]; 283cabdff1aSopenharmony_ci pos = 0; 284cabdff1aSopenharmony_ci dy = 0; 285cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 286cabdff1aSopenharmony_ci int count = bytestream2_get_byteu(gb); 287cabdff1aSopenharmony_ci int skip = count & 0x3F; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci count = count >> 6; 290cabdff1aSopenharmony_ci if (skip == 0x3F) { 291cabdff1aSopenharmony_ci pos += 0x3E; 292cabdff1aSopenharmony_ci while (pos >= w) { 293cabdff1aSopenharmony_ci pos -= w; 294cabdff1aSopenharmony_ci dst += l; 295cabdff1aSopenharmony_ci dy++; 296cabdff1aSopenharmony_ci if (dy >= h) 297cabdff1aSopenharmony_ci return 0; 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci } else { 300cabdff1aSopenharmony_ci pos += skip; 301cabdff1aSopenharmony_ci while (pos >= w) { 302cabdff1aSopenharmony_ci pos -= w; 303cabdff1aSopenharmony_ci dst += l; 304cabdff1aSopenharmony_ci dy++; 305cabdff1aSopenharmony_ci if (dy >= h) 306cabdff1aSopenharmony_ci return 0; 307cabdff1aSopenharmony_ci } 308cabdff1aSopenharmony_ci while (count >= 0) { 309cabdff1aSopenharmony_ci int bits = bytestream2_get_byte(gb); 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci for (int i = 0; i < 4; i++) { 312cabdff1aSopenharmony_ci switch (bits & 3) { 313cabdff1aSopenharmony_ci case 0: 314cabdff1aSopenharmony_ci break; 315cabdff1aSopenharmony_ci case 1: 316cabdff1aSopenharmony_ci if (dy < 1 && !pos) 317cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 318cabdff1aSopenharmony_ci else 319cabdff1aSopenharmony_ci dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1]; 320cabdff1aSopenharmony_ci break; 321cabdff1aSopenharmony_ci case 2: 322cabdff1aSopenharmony_ci if (dy < 1) 323cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 324cabdff1aSopenharmony_ci dst[pos] = dst[pos - l]; 325cabdff1aSopenharmony_ci break; 326cabdff1aSopenharmony_ci case 3: 327cabdff1aSopenharmony_ci dst[pos] = bytestream2_get_byte(gb); 328cabdff1aSopenharmony_ci break; 329cabdff1aSopenharmony_ci } 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci pos++; 332cabdff1aSopenharmony_ci if (pos >= w) { 333cabdff1aSopenharmony_ci pos -= w; 334cabdff1aSopenharmony_ci dst += l; 335cabdff1aSopenharmony_ci dy++; 336cabdff1aSopenharmony_ci if (dy >= h) 337cabdff1aSopenharmony_ci return 0; 338cabdff1aSopenharmony_ci } 339cabdff1aSopenharmony_ci bits >>= 2; 340cabdff1aSopenharmony_ci } 341cabdff1aSopenharmony_ci count--; 342cabdff1aSopenharmony_ci } 343cabdff1aSopenharmony_ci } 344cabdff1aSopenharmony_ci } 345cabdff1aSopenharmony_ci break; 346cabdff1aSopenharmony_ci default: 347cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 348cabdff1aSopenharmony_ci } 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci return 0; 352cabdff1aSopenharmony_ci} 353cabdff1aSopenharmony_ci 354cabdff1aSopenharmony_cistatic int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame) 355cabdff1aSopenharmony_ci{ 356cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 357cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 358cabdff1aSopenharmony_ci const int w = frame->width; 359cabdff1aSopenharmony_ci const int h = frame->height; 360cabdff1aSopenharmony_ci const int l = frame->linesize[0] / 4; 361cabdff1aSopenharmony_ci 362cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 363cabdff1aSopenharmony_ci int osize, type, pos, dy, di, bcode, value, v14; 364cabdff1aSopenharmony_ci const uint8_t *bits; 365cabdff1aSopenharmony_ci uint32_t *dst; 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci type = bytestream2_get_byte(gb); 368cabdff1aSopenharmony_ci if (type == 0xFF) 369cabdff1aSopenharmony_ci return 0; 370cabdff1aSopenharmony_ci 371cabdff1aSopenharmony_ci switch (type) { 372cabdff1aSopenharmony_ci case 8: 373cabdff1aSopenharmony_ci dst = (uint32_t *)frame->data[0]; 374cabdff1aSopenharmony_ci for (int y = 0; y + 12 <= h; y += 12) { 375cabdff1aSopenharmony_ci for (int x = 0; x + 12 <= w; x += 12) { 376cabdff1aSopenharmony_ci int fill = bytestream2_get_be24(gb); 377cabdff1aSopenharmony_ci uint32_t *dstp = dst + x; 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_ci for (int by = 0; by < 12; by++) { 380cabdff1aSopenharmony_ci for (int bx = 0; bx < 12; bx++) 381cabdff1aSopenharmony_ci dstp[bx] = fill; 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_ci dstp += l; 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci dst += 12 * l; 388cabdff1aSopenharmony_ci } 389cabdff1aSopenharmony_ci break; 390cabdff1aSopenharmony_ci case 7: 391cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 392cabdff1aSopenharmony_ci int bsize = bytestream2_get_byte(gb); 393cabdff1aSopenharmony_ci uint32_t *src; 394cabdff1aSopenharmony_ci int count; 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci if (!bsize) 397cabdff1aSopenharmony_ci break; 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci count = bytestream2_get_be16(gb); 400cabdff1aSopenharmony_ci while (count > 0) { 401cabdff1aSopenharmony_ci int mvx, mvy, a, b, c, mx, my; 402cabdff1aSopenharmony_ci int bsize_w, bsize_h; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci bsize_w = bsize_h = bsize; 405cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 4) 406cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 407cabdff1aSopenharmony_ci mvx = bytestream2_get_byte(gb) * bsize; 408cabdff1aSopenharmony_ci mvy = bytestream2_get_byte(gb) * bsize; 409cabdff1aSopenharmony_ci a = bytestream2_get_byte(gb); 410cabdff1aSopenharmony_ci b = bytestream2_get_byte(gb); 411cabdff1aSopenharmony_ci c = ((a & 0x3F) << 8) + b; 412cabdff1aSopenharmony_ci mx = mvx + (c & 0x7F) - 64; 413cabdff1aSopenharmony_ci my = mvy + (c >> 7) - 64; 414cabdff1aSopenharmony_ci 415cabdff1aSopenharmony_ci if (mvy < 0 || mvy >= h) 416cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci if (mvx < 0 || mvx >= w) 419cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci if (my < 0 || my >= h) 422cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci if (mx < 0 || mx >= w) 425cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci dst = (uint32_t *)frame->data[0] + mvx + l * mvy; 428cabdff1aSopenharmony_ci src = (uint32_t *)frame->data[0] + mx + l * my; 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci bsize_w = FFMIN3(bsize_w, w - mvx, w - mx); 431cabdff1aSopenharmony_ci bsize_h = FFMIN3(bsize_h, h - mvy, h - my); 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_ci if (mvy >= my && (mvy != my || mvx >= mx)) { 434cabdff1aSopenharmony_ci src += (bsize_h - 1) * l; 435cabdff1aSopenharmony_ci dst += (bsize_h - 1) * l; 436cabdff1aSopenharmony_ci for (int by = 0; by < bsize_h; by++) { 437cabdff1aSopenharmony_ci memmove(dst, src, bsize_w * 4); 438cabdff1aSopenharmony_ci src -= l; 439cabdff1aSopenharmony_ci dst -= l; 440cabdff1aSopenharmony_ci } 441cabdff1aSopenharmony_ci } else { 442cabdff1aSopenharmony_ci for (int by = 0; by < bsize_h; by++) { 443cabdff1aSopenharmony_ci memmove(dst, src, bsize_w * 4); 444cabdff1aSopenharmony_ci src += l; 445cabdff1aSopenharmony_ci dst += l; 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci } 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci count--; 450cabdff1aSopenharmony_ci } 451cabdff1aSopenharmony_ci } 452cabdff1aSopenharmony_ci break; 453cabdff1aSopenharmony_ci case 12: 454cabdff1aSopenharmony_ci osize = ((h + 3) / 4) * ((w + 3) / 4) + 7; 455cabdff1aSopenharmony_ci bits = gb->buffer; 456cabdff1aSopenharmony_ci di = 0; 457cabdff1aSopenharmony_ci bcode = v14 = 0; 458cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < osize >> 3) 459cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 460cabdff1aSopenharmony_ci bytestream2_skip(gb, osize >> 3); 461cabdff1aSopenharmony_ci for (int x = 0; x < w; x += 4) { 462cabdff1aSopenharmony_ci for (int y = 0; y < h; y += 4) { 463cabdff1aSopenharmony_ci int astate = 0; 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_ci if (bits[di >> 3] & (1 << (di & 7))) { 466cabdff1aSopenharmony_ci int codes = bytestream2_get_byte(gb); 467cabdff1aSopenharmony_ci 468cabdff1aSopenharmony_ci for (int count = 0; count < 4; count++) { 469cabdff1aSopenharmony_ci uint32_t *src = (uint32_t *)frame->data[0]; 470cabdff1aSopenharmony_ci size_t src_size = l * (h - 1) + (w - 1); 471cabdff1aSopenharmony_ci int nv, v, code = codes & 3; 472cabdff1aSopenharmony_ci 473cabdff1aSopenharmony_ci pos = x; 474cabdff1aSopenharmony_ci dy = y + count; 475cabdff1aSopenharmony_ci dst = (uint32_t *)frame->data[0] + pos + dy * l; 476cabdff1aSopenharmony_ci if (code & 1) 477cabdff1aSopenharmony_ci bcode = bytestream2_get_byte(gb); 478cabdff1aSopenharmony_ci if (code == 3) { 479cabdff1aSopenharmony_ci for (int j = 0; j < 4; j++) { 480cabdff1aSopenharmony_ci switch (bcode & 3) { 481cabdff1aSopenharmony_ci case 0: 482cabdff1aSopenharmony_ci break; 483cabdff1aSopenharmony_ci case 1: 484cabdff1aSopenharmony_ci if (dy < 1 && !pos) 485cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 486cabdff1aSopenharmony_ci dst[0] = dst[-1]; 487cabdff1aSopenharmony_ci break; 488cabdff1aSopenharmony_ci case 2: 489cabdff1aSopenharmony_ci if (dy < 1) 490cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 491cabdff1aSopenharmony_ci dst[0] = dst[-l]; 492cabdff1aSopenharmony_ci break; 493cabdff1aSopenharmony_ci case 3: 494cabdff1aSopenharmony_ci if (astate) { 495cabdff1aSopenharmony_ci nv = value >> 4; 496cabdff1aSopenharmony_ci } else { 497cabdff1aSopenharmony_ci value = bytestream2_get_byte(gb); 498cabdff1aSopenharmony_ci nv = value & 0xF; 499cabdff1aSopenharmony_ci } 500cabdff1aSopenharmony_ci astate ^= 1; 501cabdff1aSopenharmony_ci dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos + 502cabdff1aSopenharmony_ci s->mv1[nv][0], 0, src_size)]; 503cabdff1aSopenharmony_ci break; 504cabdff1aSopenharmony_ci } 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci bcode >>= 2; 507cabdff1aSopenharmony_ci dst++; 508cabdff1aSopenharmony_ci pos++; 509cabdff1aSopenharmony_ci } 510cabdff1aSopenharmony_ci } else if (code) { 511cabdff1aSopenharmony_ci if (code == 1) 512cabdff1aSopenharmony_ci v14 = bcode; 513cabdff1aSopenharmony_ci else 514cabdff1aSopenharmony_ci bcode = v14; 515cabdff1aSopenharmony_ci for (int j = 0; j < 4; j++) { 516cabdff1aSopenharmony_ci switch (bcode & 3) { 517cabdff1aSopenharmony_ci case 0: 518cabdff1aSopenharmony_ci break; 519cabdff1aSopenharmony_ci case 1: 520cabdff1aSopenharmony_ci if (dy < 1 && !pos) 521cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 522cabdff1aSopenharmony_ci dst[0] = dst[-1]; 523cabdff1aSopenharmony_ci break; 524cabdff1aSopenharmony_ci case 2: 525cabdff1aSopenharmony_ci if (dy < 1) 526cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 527cabdff1aSopenharmony_ci dst[0] = dst[-l]; 528cabdff1aSopenharmony_ci break; 529cabdff1aSopenharmony_ci case 3: 530cabdff1aSopenharmony_ci v = bytestream2_get_byte(gb); 531cabdff1aSopenharmony_ci if (v < 128) { 532cabdff1aSopenharmony_ci dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos + 533cabdff1aSopenharmony_ci s->mv0[v][0], 0, src_size)]; 534cabdff1aSopenharmony_ci } else { 535cabdff1aSopenharmony_ci dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb); 536cabdff1aSopenharmony_ci } 537cabdff1aSopenharmony_ci break; 538cabdff1aSopenharmony_ci } 539cabdff1aSopenharmony_ci 540cabdff1aSopenharmony_ci bcode >>= 2; 541cabdff1aSopenharmony_ci dst++; 542cabdff1aSopenharmony_ci pos++; 543cabdff1aSopenharmony_ci } 544cabdff1aSopenharmony_ci } 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci codes >>= 2; 547cabdff1aSopenharmony_ci } 548cabdff1aSopenharmony_ci } 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci di++; 551cabdff1aSopenharmony_ci } 552cabdff1aSopenharmony_ci } 553cabdff1aSopenharmony_ci break; 554cabdff1aSopenharmony_ci default: 555cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 556cabdff1aSopenharmony_ci } 557cabdff1aSopenharmony_ci } 558cabdff1aSopenharmony_ci 559cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 560cabdff1aSopenharmony_ci} 561cabdff1aSopenharmony_ci 562cabdff1aSopenharmony_cistatic int decode_rle(AVCodecContext *avctx, AVFrame *frame) 563cabdff1aSopenharmony_ci{ 564cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 565cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 566cabdff1aSopenharmony_ci const int w = frame->width; 567cabdff1aSopenharmony_ci const int h = frame->height; 568cabdff1aSopenharmony_ci const int l = frame->linesize[0]; 569cabdff1aSopenharmony_ci uint8_t *dst = frame->data[0]; 570cabdff1aSopenharmony_ci int pos = 0, y = 0; 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) > 0) { 573cabdff1aSopenharmony_ci int count = bytestream2_get_byte(gb); 574cabdff1aSopenharmony_ci int pixel = bytestream2_get_byte(gb); 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci if (!count) { 577cabdff1aSopenharmony_ci pos += pixel; 578cabdff1aSopenharmony_ci while (pos >= w) { 579cabdff1aSopenharmony_ci pos -= w; 580cabdff1aSopenharmony_ci y++; 581cabdff1aSopenharmony_ci if (y >= h) 582cabdff1aSopenharmony_ci return 0; 583cabdff1aSopenharmony_ci } 584cabdff1aSopenharmony_ci } else { 585cabdff1aSopenharmony_ci while (count > 0) { 586cabdff1aSopenharmony_ci dst[pos + y * l] = pixel; 587cabdff1aSopenharmony_ci count--; 588cabdff1aSopenharmony_ci pos++; 589cabdff1aSopenharmony_ci if (pos >= w) { 590cabdff1aSopenharmony_ci pos = 0; 591cabdff1aSopenharmony_ci y++; 592cabdff1aSopenharmony_ci if (y >= h) 593cabdff1aSopenharmony_ci return 0; 594cabdff1aSopenharmony_ci } 595cabdff1aSopenharmony_ci } 596cabdff1aSopenharmony_ci } 597cabdff1aSopenharmony_ci } 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci return 0; 600cabdff1aSopenharmony_ci} 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *rframe, 603cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 604cabdff1aSopenharmony_ci{ 605cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 606cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 607cabdff1aSopenharmony_ci AVFrame *frame = s->frame; 608cabdff1aSopenharmony_ci uint32_t chunk; 609cabdff1aSopenharmony_ci int ret; 610cabdff1aSopenharmony_ci 611cabdff1aSopenharmony_ci if (avpkt->size < 4) 612cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 613cabdff1aSopenharmony_ci 614cabdff1aSopenharmony_ci bytestream2_init(gb, avpkt->data, avpkt->size); 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) 617cabdff1aSopenharmony_ci return ret; 618cabdff1aSopenharmony_ci 619cabdff1aSopenharmony_ci chunk = bytestream2_get_be32(gb); 620cabdff1aSopenharmony_ci switch (chunk) { 621cabdff1aSopenharmony_ci case MKBETAG('P', 'A', 'L', '8'): 622cabdff1aSopenharmony_ci for (int y = 0; y < frame->height; y++) 623cabdff1aSopenharmony_ci memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp); 624cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) 625cabdff1aSopenharmony_ci memset(frame->data[1], 0, AVPALETTE_SIZE); 626cabdff1aSopenharmony_ci return decode_pal8(avctx, s->pal); 627cabdff1aSopenharmony_ci case MKBETAG('M', 'A', 'D', '1'): 628cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) 629cabdff1aSopenharmony_ci ret = decode_mad1(avctx, frame); 630cabdff1aSopenharmony_ci else 631cabdff1aSopenharmony_ci ret = decode_mad1_24(avctx, frame); 632cabdff1aSopenharmony_ci break; 633cabdff1aSopenharmony_ci case MKBETAG('A', 'V', 'C', 'F'): 634cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 635cabdff1aSopenharmony_ci s->key = 1; 636cabdff1aSopenharmony_ci ret = decode_avcf(avctx, frame); 637cabdff1aSopenharmony_ci break; 638cabdff1aSopenharmony_ci } 639cabdff1aSopenharmony_ci case MKBETAG('A', 'L', 'C', 'D'): 640cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 641cabdff1aSopenharmony_ci s->key = 0; 642cabdff1aSopenharmony_ci ret = decode_alcd(avctx, frame); 643cabdff1aSopenharmony_ci break; 644cabdff1aSopenharmony_ci } 645cabdff1aSopenharmony_ci case MKBETAG('R', 'L', 'E', 'F'): 646cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 647cabdff1aSopenharmony_ci s->key = 1; 648cabdff1aSopenharmony_ci ret = decode_rle(avctx, frame); 649cabdff1aSopenharmony_ci break; 650cabdff1aSopenharmony_ci } 651cabdff1aSopenharmony_ci case MKBETAG('R', 'L', 'E', 'D'): 652cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 653cabdff1aSopenharmony_ci s->key = 0; 654cabdff1aSopenharmony_ci ret = decode_rle(avctx, frame); 655cabdff1aSopenharmony_ci break; 656cabdff1aSopenharmony_ci } 657cabdff1aSopenharmony_ci default: 658cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk); 659cabdff1aSopenharmony_ci break; 660cabdff1aSopenharmony_ci } 661cabdff1aSopenharmony_ci 662cabdff1aSopenharmony_ci if (ret < 0) 663cabdff1aSopenharmony_ci return ret; 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) 666cabdff1aSopenharmony_ci memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci if ((ret = av_frame_ref(rframe, s->frame)) < 0) 669cabdff1aSopenharmony_ci return ret; 670cabdff1aSopenharmony_ci 671cabdff1aSopenharmony_ci frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; 672cabdff1aSopenharmony_ci frame->key_frame = s->key; 673cabdff1aSopenharmony_ci *got_frame = 1; 674cabdff1aSopenharmony_ci 675cabdff1aSopenharmony_ci return avpkt->size; 676cabdff1aSopenharmony_ci} 677cabdff1aSopenharmony_ci 678cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx) 679cabdff1aSopenharmony_ci{ 680cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci switch (avctx->bits_per_coded_sample) { 683cabdff1aSopenharmony_ci case 8: s->bpp = 1; 684cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; break; 685cabdff1aSopenharmony_ci case 24: s->bpp = 4; 686cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR0; break; 687cabdff1aSopenharmony_ci default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_coded_sample); 688cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 689cabdff1aSopenharmony_ci } 690cabdff1aSopenharmony_ci 691cabdff1aSopenharmony_ci if (avctx->width % 2 || avctx->height % 2) { 692cabdff1aSopenharmony_ci avpriv_request_sample(s, "Odd dimensions\n"); 693cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 694cabdff1aSopenharmony_ci } 695cabdff1aSopenharmony_ci 696cabdff1aSopenharmony_ci s->frame = av_frame_alloc(); 697cabdff1aSopenharmony_ci if (!s->frame) 698cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 699cabdff1aSopenharmony_ci 700cabdff1aSopenharmony_ci for (int n = 0, i = -4; i < 4; i++) { 701cabdff1aSopenharmony_ci for (int j = -14; j < 2; j++) { 702cabdff1aSopenharmony_ci s->mv0[n][0] = j; 703cabdff1aSopenharmony_ci s->mv0[n++][1] = i; 704cabdff1aSopenharmony_ci } 705cabdff1aSopenharmony_ci } 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci for (int n = 0, i = -5; i <= 1; i += 2) { 708cabdff1aSopenharmony_ci int j = -5; 709cabdff1aSopenharmony_ci 710cabdff1aSopenharmony_ci while (j <= 1) { 711cabdff1aSopenharmony_ci s->mv1[n][0] = j; 712cabdff1aSopenharmony_ci s->mv1[n++][1] = i; 713cabdff1aSopenharmony_ci j += 2; 714cabdff1aSopenharmony_ci } 715cabdff1aSopenharmony_ci } 716cabdff1aSopenharmony_ci 717cabdff1aSopenharmony_ci return 0; 718cabdff1aSopenharmony_ci} 719cabdff1aSopenharmony_ci 720cabdff1aSopenharmony_cistatic void decode_flush(AVCodecContext *avctx) 721cabdff1aSopenharmony_ci{ 722cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 723cabdff1aSopenharmony_ci 724cabdff1aSopenharmony_ci av_frame_unref(s->frame); 725cabdff1aSopenharmony_ci} 726cabdff1aSopenharmony_ci 727cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx) 728cabdff1aSopenharmony_ci{ 729cabdff1aSopenharmony_ci ArgoContext *s = avctx->priv_data; 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci av_frame_free(&s->frame); 732cabdff1aSopenharmony_ci 733cabdff1aSopenharmony_ci return 0; 734cabdff1aSopenharmony_ci} 735cabdff1aSopenharmony_ci 736cabdff1aSopenharmony_ciconst FFCodec ff_argo_decoder = { 737cabdff1aSopenharmony_ci .p.name = "argo", 738cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"), 739cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 740cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_ARGO, 741cabdff1aSopenharmony_ci .priv_data_size = sizeof(ArgoContext), 742cabdff1aSopenharmony_ci .init = decode_init, 743cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 744cabdff1aSopenharmony_ci .flush = decode_flush, 745cabdff1aSopenharmony_ci .close = decode_close, 746cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 747cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 748cabdff1aSopenharmony_ci}; 749