1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Gremlin Digital Video (GDV) decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2017 Konstantin Shishkov 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#include "libavutil/common.h" 24cabdff1aSopenharmony_ci#include "avcodec.h" 25cabdff1aSopenharmony_ci#include "bytestream.h" 26cabdff1aSopenharmony_ci#include "codec_internal.h" 27cabdff1aSopenharmony_ci#include "decode.h" 28cabdff1aSopenharmony_ci#include "internal.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_citypedef struct GDVContext { 31cabdff1aSopenharmony_ci AVCodecContext *avctx; 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci GetByteContext gb; 34cabdff1aSopenharmony_ci GetByteContext g2; 35cabdff1aSopenharmony_ci PutByteContext pb; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci uint32_t pal[256]; 38cabdff1aSopenharmony_ci uint8_t *frame; 39cabdff1aSopenharmony_ci unsigned frame_size; 40cabdff1aSopenharmony_ci unsigned scale_h, scale_v; 41cabdff1aSopenharmony_ci} GDVContext; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_citypedef struct Bits8 { 44cabdff1aSopenharmony_ci uint8_t queue; 45cabdff1aSopenharmony_ci uint8_t fill; 46cabdff1aSopenharmony_ci} Bits8; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_citypedef struct Bits32 { 49cabdff1aSopenharmony_ci uint32_t queue; 50cabdff1aSopenharmony_ci uint8_t fill; 51cabdff1aSopenharmony_ci} Bits32; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci#define PREAMBLE_SIZE 4096 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic av_cold int gdv_decode_init(AVCodecContext *avctx) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 58cabdff1aSopenharmony_ci int i, j, k; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 61cabdff1aSopenharmony_ci gdv->frame_size = avctx->width * avctx->height + PREAMBLE_SIZE; 62cabdff1aSopenharmony_ci gdv->frame = av_calloc(gdv->frame_size, 1); 63cabdff1aSopenharmony_ci if (!gdv->frame) 64cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) { 67cabdff1aSopenharmony_ci for (j = 0; j < 256; j++) { 68cabdff1aSopenharmony_ci for (k = 0; k < 8; k++) { 69cabdff1aSopenharmony_ci gdv->frame[i * 2048 + j * 8 + k] = j; 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci return 0; 75cabdff1aSopenharmony_ci} 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic void scaleup(uint8_t *dst, const uint8_t *src, int w) 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci int x; 80cabdff1aSopenharmony_ci for (x = 0; x < w - 7; x+=8) { 81cabdff1aSopenharmony_ci dst[x + 0] = 82cabdff1aSopenharmony_ci dst[x + 1] = src[(x>>1) + 0]; 83cabdff1aSopenharmony_ci dst[x + 2] = 84cabdff1aSopenharmony_ci dst[x + 3] = src[(x>>1) + 1]; 85cabdff1aSopenharmony_ci dst[x + 4] = 86cabdff1aSopenharmony_ci dst[x + 5] = src[(x>>1) + 2]; 87cabdff1aSopenharmony_ci dst[x + 6] = 88cabdff1aSopenharmony_ci dst[x + 7] = src[(x>>1) + 3]; 89cabdff1aSopenharmony_ci } 90cabdff1aSopenharmony_ci for (; x < w; x++) { 91cabdff1aSopenharmony_ci dst[x] = src[(x>>1)]; 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci} 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_cistatic void scaleup_rev(uint8_t *dst, const uint8_t *src, int w) 96cabdff1aSopenharmony_ci{ 97cabdff1aSopenharmony_ci int x; 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci for (x = w - 1; (x+1) & 7; x--) { 100cabdff1aSopenharmony_ci dst[x] = src[(x>>1)]; 101cabdff1aSopenharmony_ci } 102cabdff1aSopenharmony_ci for (x -= 7; x >= 0; x -= 8) { 103cabdff1aSopenharmony_ci dst[x + 6] = 104cabdff1aSopenharmony_ci dst[x + 7] = src[(x>>1) + 3]; 105cabdff1aSopenharmony_ci dst[x + 4] = 106cabdff1aSopenharmony_ci dst[x + 5] = src[(x>>1) + 2]; 107cabdff1aSopenharmony_ci dst[x + 2] = 108cabdff1aSopenharmony_ci dst[x + 3] = src[(x>>1) + 1]; 109cabdff1aSopenharmony_ci dst[x + 0] = 110cabdff1aSopenharmony_ci dst[x + 1] = src[(x>>1) + 0]; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_cistatic void scaledown(uint8_t *dst, const uint8_t *src, int w) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci int x; 117cabdff1aSopenharmony_ci for (x = 0; x < w - 7; x+=8) { 118cabdff1aSopenharmony_ci dst[x + 0] = src[2*x + 0]; 119cabdff1aSopenharmony_ci dst[x + 1] = src[2*x + 2]; 120cabdff1aSopenharmony_ci dst[x + 2] = src[2*x + 4]; 121cabdff1aSopenharmony_ci dst[x + 3] = src[2*x + 6]; 122cabdff1aSopenharmony_ci dst[x + 4] = src[2*x + 8]; 123cabdff1aSopenharmony_ci dst[x + 5] = src[2*x +10]; 124cabdff1aSopenharmony_ci dst[x + 6] = src[2*x +12]; 125cabdff1aSopenharmony_ci dst[x + 7] = src[2*x +14]; 126cabdff1aSopenharmony_ci } 127cabdff1aSopenharmony_ci for (; x < w; x++) { 128cabdff1aSopenharmony_ci dst[x] = src[2*x]; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci} 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_cistatic void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, int scale_h) 133cabdff1aSopenharmony_ci{ 134cabdff1aSopenharmony_ci int j, y; 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci if ((gdv->scale_v == scale_v) && (gdv->scale_h == scale_h)) { 137cabdff1aSopenharmony_ci return; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci if (gdv->scale_v) { 141cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 142cabdff1aSopenharmony_ci int y = h - j - 1; 143cabdff1aSopenharmony_ci uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; 144cabdff1aSopenharmony_ci uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>!!gdv->scale_h) * (w>>1); 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci scaleup_rev(dst1, src1, w); 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } else if (gdv->scale_h) { 149cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 150cabdff1aSopenharmony_ci int y = h - j - 1; 151cabdff1aSopenharmony_ci uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; 152cabdff1aSopenharmony_ci uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>1) * w; 153cabdff1aSopenharmony_ci memcpy(dst1, src1, w); 154cabdff1aSopenharmony_ci } 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci if (scale_h && scale_v) { 158cabdff1aSopenharmony_ci for (y = 0; y < (h>>1); y++) { 159cabdff1aSopenharmony_ci uint8_t *dst1 = dst + PREAMBLE_SIZE + y * (w>>1); 160cabdff1aSopenharmony_ci uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w; 161cabdff1aSopenharmony_ci scaledown(dst1, src1, w>>1); 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci } else if (scale_h) { 164cabdff1aSopenharmony_ci for (y = 0; y < (h>>1); y++) { 165cabdff1aSopenharmony_ci uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; 166cabdff1aSopenharmony_ci uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w; 167cabdff1aSopenharmony_ci memcpy(dst1, src1, w); 168cabdff1aSopenharmony_ci } 169cabdff1aSopenharmony_ci } else if (scale_v) { 170cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 171cabdff1aSopenharmony_ci uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; 172cabdff1aSopenharmony_ci scaledown(dst1, dst1, w>>1); 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci } 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci gdv->scale_v = scale_v; 177cabdff1aSopenharmony_ci gdv->scale_h = scale_h; 178cabdff1aSopenharmony_ci} 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_cistatic int read_bits2(Bits8 *bits, GetByteContext *gb) 181cabdff1aSopenharmony_ci{ 182cabdff1aSopenharmony_ci int res; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci if (bits->fill == 0) { 185cabdff1aSopenharmony_ci bits->queue |= bytestream2_get_byte(gb); 186cabdff1aSopenharmony_ci bits->fill = 8; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci res = bits->queue >> 6; 189cabdff1aSopenharmony_ci bits->queue <<= 2; 190cabdff1aSopenharmony_ci bits->fill -= 2; 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci return res; 193cabdff1aSopenharmony_ci} 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_cistatic void fill_bits32(Bits32 *bits, GetByteContext *gb) 196cabdff1aSopenharmony_ci{ 197cabdff1aSopenharmony_ci bits->queue = bytestream2_get_le32(gb); 198cabdff1aSopenharmony_ci bits->fill = 32; 199cabdff1aSopenharmony_ci} 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_cistatic int read_bits32(Bits32 *bits, GetByteContext *gb, int nbits) 202cabdff1aSopenharmony_ci{ 203cabdff1aSopenharmony_ci int res = bits->queue & ((1 << nbits) - 1); 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci bits->queue >>= nbits; 206cabdff1aSopenharmony_ci bits->fill -= nbits; 207cabdff1aSopenharmony_ci if (bits->fill <= 16) { 208cabdff1aSopenharmony_ci bits->queue |= bytestream2_get_le16(gb) << bits->fill; 209cabdff1aSopenharmony_ci bits->fill += 16; 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci return res; 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_cistatic void lz_copy(PutByteContext *pb, GetByteContext *g2, int offset, unsigned len) 216cabdff1aSopenharmony_ci{ 217cabdff1aSopenharmony_ci int i; 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci if (offset == -1) { 220cabdff1aSopenharmony_ci int c; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci bytestream2_seek(g2, bytestream2_tell_p(pb) - 1, SEEK_SET); 223cabdff1aSopenharmony_ci c = bytestream2_get_byte(g2); 224cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 225cabdff1aSopenharmony_ci bytestream2_put_byte(pb, c); 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci } else if (offset < 0) { 228cabdff1aSopenharmony_ci int start = bytestream2_tell_p(pb) - (-offset); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci bytestream2_seek(g2, start, SEEK_SET); 231cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 232cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(g2)); 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci } else { 235cabdff1aSopenharmony_ci int start = bytestream2_tell_p(pb) + offset; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci bytestream2_seek(g2, start, SEEK_SET); 238cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 239cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(g2)); 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci} 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_cistatic int decompress_2(AVCodecContext *avctx) 245cabdff1aSopenharmony_ci{ 246cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 247cabdff1aSopenharmony_ci GetByteContext *gb = &gdv->gb; 248cabdff1aSopenharmony_ci GetByteContext *g2 = &gdv->g2; 249cabdff1aSopenharmony_ci PutByteContext *pb = &gdv->pb; 250cabdff1aSopenharmony_ci Bits8 bits = { 0 }; 251cabdff1aSopenharmony_ci int c, i; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci bytestream2_init(g2, gdv->frame, gdv->frame_size); 254cabdff1aSopenharmony_ci bytestream2_skip_p(pb, PREAMBLE_SIZE); 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_ci for (c = 0; c < 256; c++) { 257cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 258cabdff1aSopenharmony_ci gdv->frame[c * 16 + i] = c; 259cabdff1aSopenharmony_ci } 260cabdff1aSopenharmony_ci } 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) { 263cabdff1aSopenharmony_ci int tag = read_bits2(&bits, gb); 264cabdff1aSopenharmony_ci if (tag == 0) { 265cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(gb)); 266cabdff1aSopenharmony_ci } else if (tag == 1) { 267cabdff1aSopenharmony_ci int b = bytestream2_get_byte(gb); 268cabdff1aSopenharmony_ci int len = (b & 0xF) + 3; 269cabdff1aSopenharmony_ci int top = (b >> 4) & 0xF; 270cabdff1aSopenharmony_ci int off = (bytestream2_get_byte(gb) << 4) + top - 4096; 271cabdff1aSopenharmony_ci lz_copy(pb, g2, off, len); 272cabdff1aSopenharmony_ci } else if (tag == 2) { 273cabdff1aSopenharmony_ci int len = (bytestream2_get_byte(gb)) + 2; 274cabdff1aSopenharmony_ci bytestream2_skip_p(pb, len); 275cabdff1aSopenharmony_ci } else { 276cabdff1aSopenharmony_ci break; 277cabdff1aSopenharmony_ci } 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left_p(pb) > 0) 281cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci return 0; 284cabdff1aSopenharmony_ci} 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_cistatic int decompress_5(AVCodecContext *avctx, unsigned skip) 287cabdff1aSopenharmony_ci{ 288cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 289cabdff1aSopenharmony_ci GetByteContext *gb = &gdv->gb; 290cabdff1aSopenharmony_ci GetByteContext *g2 = &gdv->g2; 291cabdff1aSopenharmony_ci PutByteContext *pb = &gdv->pb; 292cabdff1aSopenharmony_ci Bits8 bits = { 0 }; 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci bytestream2_init(g2, gdv->frame, gdv->frame_size); 295cabdff1aSopenharmony_ci bytestream2_skip_p(pb, skip + PREAMBLE_SIZE); 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) { 298cabdff1aSopenharmony_ci int tag = read_bits2(&bits, gb); 299cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 1) 300cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 301cabdff1aSopenharmony_ci if (tag == 0) { 302cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(gb)); 303cabdff1aSopenharmony_ci } else if (tag == 1) { 304cabdff1aSopenharmony_ci int b = bytestream2_get_byte(gb); 305cabdff1aSopenharmony_ci int len = (b & 0xF) + 3; 306cabdff1aSopenharmony_ci int top = b >> 4; 307cabdff1aSopenharmony_ci int off = (bytestream2_get_byte(gb) << 4) + top - 4096; 308cabdff1aSopenharmony_ci lz_copy(pb, g2, off, len); 309cabdff1aSopenharmony_ci } else if (tag == 2) { 310cabdff1aSopenharmony_ci int len; 311cabdff1aSopenharmony_ci int b = bytestream2_get_byte(gb); 312cabdff1aSopenharmony_ci if (b == 0) { 313cabdff1aSopenharmony_ci return 0; 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci if (b != 0xFF) { 316cabdff1aSopenharmony_ci len = b; 317cabdff1aSopenharmony_ci } else { 318cabdff1aSopenharmony_ci len = bytestream2_get_le16(gb); 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci bytestream2_skip_p(pb, len + 1); 321cabdff1aSopenharmony_ci } else { 322cabdff1aSopenharmony_ci int b = bytestream2_get_byte(gb); 323cabdff1aSopenharmony_ci int len = (b & 0x3) + 2; 324cabdff1aSopenharmony_ci int off = -(b >> 2) - 1; 325cabdff1aSopenharmony_ci lz_copy(pb, g2, off, len); 326cabdff1aSopenharmony_ci } 327cabdff1aSopenharmony_ci } 328cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left_p(pb) > 0) 329cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 330cabdff1aSopenharmony_ci return 0; 331cabdff1aSopenharmony_ci} 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_cistatic int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8) 334cabdff1aSopenharmony_ci{ 335cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 336cabdff1aSopenharmony_ci GetByteContext *gb = &gdv->gb; 337cabdff1aSopenharmony_ci GetByteContext *g2 = &gdv->g2; 338cabdff1aSopenharmony_ci PutByteContext *pb = &gdv->pb; 339cabdff1aSopenharmony_ci Bits32 bits; 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci bytestream2_init(g2, gdv->frame, gdv->frame_size); 342cabdff1aSopenharmony_ci bytestream2_skip_p(pb, skip + PREAMBLE_SIZE); 343cabdff1aSopenharmony_ci fill_bits32(&bits, gb); 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) { 346cabdff1aSopenharmony_ci int tag = read_bits32(&bits, gb, 2); 347cabdff1aSopenharmony_ci if (tag == 0) { 348cabdff1aSopenharmony_ci int b = read_bits32(&bits, gb, 1); 349cabdff1aSopenharmony_ci if (b == 0) { 350cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(gb)); 351cabdff1aSopenharmony_ci } else { 352cabdff1aSopenharmony_ci int i, len = 2; 353cabdff1aSopenharmony_ci int lbits = 0; 354cabdff1aSopenharmony_ci while (1) { 355cabdff1aSopenharmony_ci int val; 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci lbits += 1; 358cabdff1aSopenharmony_ci val = read_bits32(&bits, gb, lbits); 359cabdff1aSopenharmony_ci len += val; 360cabdff1aSopenharmony_ci if (val != ((1 << lbits) - 1)) { 361cabdff1aSopenharmony_ci break; 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci if (lbits >= 16) 364cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 365cabdff1aSopenharmony_ci } 366cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 367cabdff1aSopenharmony_ci bytestream2_put_byte(pb, bytestream2_get_byte(gb)); 368cabdff1aSopenharmony_ci } 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci } else if (tag == 1) { 371cabdff1aSopenharmony_ci int b = read_bits32(&bits, gb, 1); 372cabdff1aSopenharmony_ci int len; 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci if (b == 0) { 375cabdff1aSopenharmony_ci len = (read_bits32(&bits, gb, 4)) + 2; 376cabdff1aSopenharmony_ci } else { 377cabdff1aSopenharmony_ci int bb = bytestream2_get_byte(gb); 378cabdff1aSopenharmony_ci if ((bb & 0x80) == 0) { 379cabdff1aSopenharmony_ci len = bb + 18; 380cabdff1aSopenharmony_ci } else { 381cabdff1aSopenharmony_ci int top = (bb & 0x7F) << 8; 382cabdff1aSopenharmony_ci len = top + bytestream2_get_byte(gb) + 146; 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci bytestream2_skip_p(pb, len); 386cabdff1aSopenharmony_ci } else if (tag == 2) { 387cabdff1aSopenharmony_ci int i, subtag = read_bits32(&bits, gb, 2); 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_ci if (subtag != 3) { 390cabdff1aSopenharmony_ci int top = (read_bits32(&bits, gb, 4)) << 8; 391cabdff1aSopenharmony_ci int offs = top + bytestream2_get_byte(gb); 392cabdff1aSopenharmony_ci if ((subtag != 0) || (offs <= 0xF80)) { 393cabdff1aSopenharmony_ci int len = (subtag) + 3; 394cabdff1aSopenharmony_ci lz_copy(pb, g2, (offs) - 4096, len); 395cabdff1aSopenharmony_ci } else { 396cabdff1aSopenharmony_ci int real_off, len, c1, c2; 397cabdff1aSopenharmony_ci 398cabdff1aSopenharmony_ci if (offs == 0xFFF) { 399cabdff1aSopenharmony_ci return 0; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci real_off = ((offs >> 4) & 0x7) + 1; 403cabdff1aSopenharmony_ci len = ((offs & 0xF) + 2) * 2; 404cabdff1aSopenharmony_ci c1 = gdv->frame[bytestream2_tell_p(pb) - real_off]; 405cabdff1aSopenharmony_ci c2 = gdv->frame[bytestream2_tell_p(pb) - real_off + 1]; 406cabdff1aSopenharmony_ci for (i = 0; i < len/2; i++) { 407cabdff1aSopenharmony_ci bytestream2_put_byte(pb, c1); 408cabdff1aSopenharmony_ci bytestream2_put_byte(pb, c2); 409cabdff1aSopenharmony_ci } 410cabdff1aSopenharmony_ci } 411cabdff1aSopenharmony_ci } else { 412cabdff1aSopenharmony_ci int b = bytestream2_get_byte(gb); 413cabdff1aSopenharmony_ci int off = ((b & 0x7F)) + 1; 414cabdff1aSopenharmony_ci int len = ((b & 0x80) == 0) ? 2 : 3; 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci lz_copy(pb, g2, -off, len); 417cabdff1aSopenharmony_ci } 418cabdff1aSopenharmony_ci } else { 419cabdff1aSopenharmony_ci int len; 420cabdff1aSopenharmony_ci int off; 421cabdff1aSopenharmony_ci if (use8) { 422cabdff1aSopenharmony_ci int q, b = bytestream2_get_byte(gb); 423cabdff1aSopenharmony_ci if ((b & 0xC0) == 0xC0) { 424cabdff1aSopenharmony_ci len = ((b & 0x3F)) + 8; 425cabdff1aSopenharmony_ci q = read_bits32(&bits, gb, 4); 426cabdff1aSopenharmony_ci off = (q << 8) + (bytestream2_get_byte(gb)) + 1; 427cabdff1aSopenharmony_ci } else { 428cabdff1aSopenharmony_ci int ofs1; 429cabdff1aSopenharmony_ci if ((b & 0x80) == 0) { 430cabdff1aSopenharmony_ci len = ((b >> 4)) + 6; 431cabdff1aSopenharmony_ci ofs1 = (b & 0xF); 432cabdff1aSopenharmony_ci } else { 433cabdff1aSopenharmony_ci len = ((b & 0x3F)) + 14; 434cabdff1aSopenharmony_ci ofs1 = read_bits32(&bits, gb, 4); 435cabdff1aSopenharmony_ci } 436cabdff1aSopenharmony_ci off = (ofs1 << 8) + (bytestream2_get_byte(gb)) - 4096; 437cabdff1aSopenharmony_ci } 438cabdff1aSopenharmony_ci } else { 439cabdff1aSopenharmony_ci int ofs1, b = bytestream2_get_byte(gb); 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci if ((b >> 4) == 0xF) { 442cabdff1aSopenharmony_ci len = bytestream2_get_byte(gb) + 21; 443cabdff1aSopenharmony_ci } else { 444cabdff1aSopenharmony_ci len = (b >> 4) + 6; 445cabdff1aSopenharmony_ci } 446cabdff1aSopenharmony_ci ofs1 = (b & 0xF); 447cabdff1aSopenharmony_ci off = (ofs1 << 8) + bytestream2_get_byte(gb) - 4096; 448cabdff1aSopenharmony_ci } 449cabdff1aSopenharmony_ci lz_copy(pb, g2, off, len); 450cabdff1aSopenharmony_ci } 451cabdff1aSopenharmony_ci } 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left_p(pb) > 0) 454cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci return 0; 457cabdff1aSopenharmony_ci} 458cabdff1aSopenharmony_ci 459cabdff1aSopenharmony_cistatic int gdv_decode_frame(AVCodecContext *avctx, AVFrame *frame, 460cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 461cabdff1aSopenharmony_ci{ 462cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 463cabdff1aSopenharmony_ci GetByteContext *gb = &gdv->gb; 464cabdff1aSopenharmony_ci PutByteContext *pb = &gdv->pb; 465cabdff1aSopenharmony_ci int ret, i; 466cabdff1aSopenharmony_ci int compression; 467cabdff1aSopenharmony_ci unsigned flags; 468cabdff1aSopenharmony_ci uint8_t *dst; 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci bytestream2_init(gb, avpkt->data, avpkt->size); 471cabdff1aSopenharmony_ci bytestream2_init_writer(pb, gdv->frame, gdv->frame_size); 472cabdff1aSopenharmony_ci 473cabdff1aSopenharmony_ci flags = bytestream2_get_le32(gb); 474cabdff1aSopenharmony_ci compression = flags & 0xF; 475cabdff1aSopenharmony_ci 476cabdff1aSopenharmony_ci if (compression == 4 || compression == 7 || compression > 8) 477cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 478cabdff1aSopenharmony_ci 479cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 480cabdff1aSopenharmony_ci return ret; 481cabdff1aSopenharmony_ci ff_copy_palette(gdv->pal, avpkt, avctx); 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci if (compression < 2 && bytestream2_get_bytes_left(gb) < 256*3) 484cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 485cabdff1aSopenharmony_ci rescale(gdv, gdv->frame, avctx->width, avctx->height, 486cabdff1aSopenharmony_ci !!(flags & 0x10), !!(flags & 0x20)); 487cabdff1aSopenharmony_ci 488cabdff1aSopenharmony_ci switch (compression) { 489cabdff1aSopenharmony_ci case 1: 490cabdff1aSopenharmony_ci memset(gdv->frame + PREAMBLE_SIZE, 0, gdv->frame_size - PREAMBLE_SIZE); 491cabdff1aSopenharmony_ci case 0: 492cabdff1aSopenharmony_ci for (i = 0; i < 256; i++) { 493cabdff1aSopenharmony_ci unsigned r = bytestream2_get_byte(gb); 494cabdff1aSopenharmony_ci unsigned g = bytestream2_get_byte(gb); 495cabdff1aSopenharmony_ci unsigned b = bytestream2_get_byte(gb); 496cabdff1aSopenharmony_ci gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci break; 499cabdff1aSopenharmony_ci case 2: 500cabdff1aSopenharmony_ci ret = decompress_2(avctx); 501cabdff1aSopenharmony_ci break; 502cabdff1aSopenharmony_ci case 3: 503cabdff1aSopenharmony_ci break; 504cabdff1aSopenharmony_ci case 5: 505cabdff1aSopenharmony_ci ret = decompress_5(avctx, flags >> 8); 506cabdff1aSopenharmony_ci break; 507cabdff1aSopenharmony_ci case 6: 508cabdff1aSopenharmony_ci ret = decompress_68(avctx, flags >> 8, 0); 509cabdff1aSopenharmony_ci break; 510cabdff1aSopenharmony_ci case 8: 511cabdff1aSopenharmony_ci ret = decompress_68(avctx, flags >> 8, 1); 512cabdff1aSopenharmony_ci break; 513cabdff1aSopenharmony_ci default: 514cabdff1aSopenharmony_ci av_assert0(0); 515cabdff1aSopenharmony_ci } 516cabdff1aSopenharmony_ci if (ret < 0) 517cabdff1aSopenharmony_ci return ret; 518cabdff1aSopenharmony_ci 519cabdff1aSopenharmony_ci memcpy(frame->data[1], gdv->pal, AVPALETTE_SIZE); 520cabdff1aSopenharmony_ci dst = frame->data[0]; 521cabdff1aSopenharmony_ci 522cabdff1aSopenharmony_ci if (!gdv->scale_v && !gdv->scale_h) { 523cabdff1aSopenharmony_ci int sidx = PREAMBLE_SIZE, didx = 0; 524cabdff1aSopenharmony_ci int y; 525cabdff1aSopenharmony_ci 526cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 527cabdff1aSopenharmony_ci memcpy(dst + didx, gdv->frame + sidx, avctx->width); 528cabdff1aSopenharmony_ci sidx += avctx->width; 529cabdff1aSopenharmony_ci didx += frame->linesize[0]; 530cabdff1aSopenharmony_ci } 531cabdff1aSopenharmony_ci } else { 532cabdff1aSopenharmony_ci int sidx = PREAMBLE_SIZE, didx = 0; 533cabdff1aSopenharmony_ci int y; 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 536cabdff1aSopenharmony_ci if (!gdv->scale_v) { 537cabdff1aSopenharmony_ci memcpy(dst + didx, gdv->frame + sidx, avctx->width); 538cabdff1aSopenharmony_ci } else { 539cabdff1aSopenharmony_ci uint8_t *dst2 = dst + didx; 540cabdff1aSopenharmony_ci uint8_t *src2 = gdv->frame + sidx; 541cabdff1aSopenharmony_ci 542cabdff1aSopenharmony_ci scaleup(dst2, src2, avctx->width); 543cabdff1aSopenharmony_ci } 544cabdff1aSopenharmony_ci if (!gdv->scale_h || ((y & 1) == 1)) { 545cabdff1aSopenharmony_ci sidx += !gdv->scale_v ? avctx->width : avctx->width/2; 546cabdff1aSopenharmony_ci } 547cabdff1aSopenharmony_ci didx += frame->linesize[0]; 548cabdff1aSopenharmony_ci } 549cabdff1aSopenharmony_ci } 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_ci *got_frame = 1; 552cabdff1aSopenharmony_ci 553cabdff1aSopenharmony_ci return avpkt->size; 554cabdff1aSopenharmony_ci} 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_cistatic av_cold int gdv_decode_close(AVCodecContext *avctx) 557cabdff1aSopenharmony_ci{ 558cabdff1aSopenharmony_ci GDVContext *gdv = avctx->priv_data; 559cabdff1aSopenharmony_ci av_freep(&gdv->frame); 560cabdff1aSopenharmony_ci return 0; 561cabdff1aSopenharmony_ci} 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ciconst FFCodec ff_gdv_decoder = { 564cabdff1aSopenharmony_ci .p.name = "gdv", 565cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), 566cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 567cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_GDV, 568cabdff1aSopenharmony_ci .priv_data_size = sizeof(GDVContext), 569cabdff1aSopenharmony_ci .init = gdv_decode_init, 570cabdff1aSopenharmony_ci .close = gdv_decode_close, 571cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(gdv_decode_frame), 572cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 573cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 574cabdff1aSopenharmony_ci}; 575