1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * KMVC decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2006 Konstantin Shishkov 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/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Karl Morton's Video Codec decoder 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <stdio.h> 28cabdff1aSopenharmony_ci#include <stdlib.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "avcodec.h" 31cabdff1aSopenharmony_ci#include "bytestream.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "decode.h" 34cabdff1aSopenharmony_ci#include "internal.h" 35cabdff1aSopenharmony_ci#include "libavutil/common.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define KMVC_KEYFRAME 0x80 38cabdff1aSopenharmony_ci#define KMVC_PALETTE 0x40 39cabdff1aSopenharmony_ci#define KMVC_METHOD 0x0F 40cabdff1aSopenharmony_ci#define MAX_PALSIZE 256 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci/* 43cabdff1aSopenharmony_ci * Decoder context 44cabdff1aSopenharmony_ci */ 45cabdff1aSopenharmony_citypedef struct KmvcContext { 46cabdff1aSopenharmony_ci AVCodecContext *avctx; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci GetByteContext g; 49cabdff1aSopenharmony_ci uint8_t *cur, *prev; 50cabdff1aSopenharmony_ci int setpal; 51cabdff1aSopenharmony_ci int palsize; 52cabdff1aSopenharmony_ci uint32_t pal[MAX_PALSIZE]; 53cabdff1aSopenharmony_ci uint8_t frm0[320 * 200], frm1[320 * 200]; 54cabdff1aSopenharmony_ci} KmvcContext; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_citypedef struct BitBuf { 57cabdff1aSopenharmony_ci int bits; 58cabdff1aSopenharmony_ci int bitbuf; 59cabdff1aSopenharmony_ci} BitBuf; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci#define BLK(data, x, y) data[av_clip((x) + (y) * 320, 0, 320 * 200 -1)] 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci#define kmvc_init_getbits(bb, g) bb.bits = 7; bb.bitbuf = bytestream2_get_byte(g); 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci#define kmvc_getbit(bb, g, res) {\ 66cabdff1aSopenharmony_ci res = 0; \ 67cabdff1aSopenharmony_ci if (bb.bitbuf & (1 << bb.bits)) res = 1; \ 68cabdff1aSopenharmony_ci bb.bits--; \ 69cabdff1aSopenharmony_ci if(bb.bits == -1) { \ 70cabdff1aSopenharmony_ci bb.bitbuf = bytestream2_get_byte(g); \ 71cabdff1aSopenharmony_ci bb.bits = 7; \ 72cabdff1aSopenharmony_ci } \ 73cabdff1aSopenharmony_ci} 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_cistatic int kmvc_decode_intra_8x8(KmvcContext * ctx, int w, int h) 76cabdff1aSopenharmony_ci{ 77cabdff1aSopenharmony_ci BitBuf bb; 78cabdff1aSopenharmony_ci int res, val; 79cabdff1aSopenharmony_ci int i, j; 80cabdff1aSopenharmony_ci int bx, by; 81cabdff1aSopenharmony_ci int l0x, l1x, l0y, l1y; 82cabdff1aSopenharmony_ci int mx, my; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci kmvc_init_getbits(bb, &ctx->g); 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci for (by = 0; by < h; by += 8) 87cabdff1aSopenharmony_ci for (bx = 0; bx < w; bx += 8) { 88cabdff1aSopenharmony_ci if (!bytestream2_get_bytes_left(&ctx->g)) { 89cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); 90cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 93cabdff1aSopenharmony_ci if (!res) { // fill whole 8x8 block 94cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 95cabdff1aSopenharmony_ci for (i = 0; i < 64; i++) 96cabdff1aSopenharmony_ci BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; 97cabdff1aSopenharmony_ci } else { // handle four 4x4 subblocks 98cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 99cabdff1aSopenharmony_ci l0x = bx + (i & 1) * 4; 100cabdff1aSopenharmony_ci l0y = by + (i & 2) * 2; 101cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 102cabdff1aSopenharmony_ci if (!res) { 103cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 104cabdff1aSopenharmony_ci if (!res) { // fill whole 4x4 block 105cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 106cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) 107cabdff1aSopenharmony_ci BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; 108cabdff1aSopenharmony_ci } else { // copy block from already decoded place 109cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 110cabdff1aSopenharmony_ci mx = val & 0xF; 111cabdff1aSopenharmony_ci my = val >> 4; 112cabdff1aSopenharmony_ci if ((l0x-mx) + 320*(l0y-my) < 0 || (l0x-mx) + 320*(l0y-my) > 320*197 - 4) { 113cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); 114cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) 117cabdff1aSopenharmony_ci BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = 118cabdff1aSopenharmony_ci BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my); 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci } else { // descend to 2x2 sub-sub-blocks 121cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 122cabdff1aSopenharmony_ci l1x = l0x + (j & 1) * 2; 123cabdff1aSopenharmony_ci l1y = l0y + (j & 2); 124cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 125cabdff1aSopenharmony_ci if (!res) { 126cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 127cabdff1aSopenharmony_ci if (!res) { // fill whole 2x2 block 128cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 129cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = val; 130cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = val; 131cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = val; 132cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = val; 133cabdff1aSopenharmony_ci } else { // copy block from already decoded place 134cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 135cabdff1aSopenharmony_ci mx = val & 0xF; 136cabdff1aSopenharmony_ci my = val >> 4; 137cabdff1aSopenharmony_ci if ((l1x-mx) + 320*(l1y-my) < 0 || (l1x-mx) + 320*(l1y-my) > 320*199 - 2) { 138cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); 139cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my); 142cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = 143cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1 - mx, l1y - my); 144cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = 145cabdff1aSopenharmony_ci BLK(ctx->cur, l1x - mx, l1y + 1 - my); 146cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = 147cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my); 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci } else { // read values for block 150cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); 151cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); 152cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); 153cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); 154cabdff1aSopenharmony_ci } 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci } 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci return 0; 162cabdff1aSopenharmony_ci} 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_cistatic int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h) 165cabdff1aSopenharmony_ci{ 166cabdff1aSopenharmony_ci BitBuf bb; 167cabdff1aSopenharmony_ci int res, val; 168cabdff1aSopenharmony_ci int i, j; 169cabdff1aSopenharmony_ci int bx, by; 170cabdff1aSopenharmony_ci int l0x, l1x, l0y, l1y; 171cabdff1aSopenharmony_ci int mx, my; 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci kmvc_init_getbits(bb, &ctx->g); 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci for (by = 0; by < h; by += 8) 176cabdff1aSopenharmony_ci for (bx = 0; bx < w; bx += 8) { 177cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 178cabdff1aSopenharmony_ci if (!res) { 179cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 180cabdff1aSopenharmony_ci if (!res) { // fill whole 8x8 block 181cabdff1aSopenharmony_ci if (!bytestream2_get_bytes_left(&ctx->g)) { 182cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); 183cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 186cabdff1aSopenharmony_ci for (i = 0; i < 64; i++) 187cabdff1aSopenharmony_ci BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; 188cabdff1aSopenharmony_ci } else { // copy block from previous frame 189cabdff1aSopenharmony_ci for (i = 0; i < 64; i++) 190cabdff1aSopenharmony_ci BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = 191cabdff1aSopenharmony_ci BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3)); 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci } else { // handle four 4x4 subblocks 194cabdff1aSopenharmony_ci if (!bytestream2_get_bytes_left(&ctx->g)) { 195cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); 196cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 199cabdff1aSopenharmony_ci l0x = bx + (i & 1) * 4; 200cabdff1aSopenharmony_ci l0y = by + (i & 2) * 2; 201cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 202cabdff1aSopenharmony_ci if (!res) { 203cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 204cabdff1aSopenharmony_ci if (!res) { // fill whole 4x4 block 205cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 206cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) 207cabdff1aSopenharmony_ci BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; 208cabdff1aSopenharmony_ci } else { // copy block 209cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 210cabdff1aSopenharmony_ci mx = (val & 0xF) - 8; 211cabdff1aSopenharmony_ci my = (val >> 4) - 8; 212cabdff1aSopenharmony_ci if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 320*197 - 4) { 213cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); 214cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 215cabdff1aSopenharmony_ci } 216cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) 217cabdff1aSopenharmony_ci BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = 218cabdff1aSopenharmony_ci BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my); 219cabdff1aSopenharmony_ci } 220cabdff1aSopenharmony_ci } else { // descend to 2x2 sub-sub-blocks 221cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 222cabdff1aSopenharmony_ci l1x = l0x + (j & 1) * 2; 223cabdff1aSopenharmony_ci l1y = l0y + (j & 2); 224cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 225cabdff1aSopenharmony_ci if (!res) { 226cabdff1aSopenharmony_ci kmvc_getbit(bb, &ctx->g, res); 227cabdff1aSopenharmony_ci if (!res) { // fill whole 2x2 block 228cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 229cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = val; 230cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = val; 231cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = val; 232cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = val; 233cabdff1aSopenharmony_ci } else { // copy block 234cabdff1aSopenharmony_ci val = bytestream2_get_byte(&ctx->g); 235cabdff1aSopenharmony_ci mx = (val & 0xF) - 8; 236cabdff1aSopenharmony_ci my = (val >> 4) - 8; 237cabdff1aSopenharmony_ci if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 320*199 - 2) { 238cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); 239cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my); 242cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = 243cabdff1aSopenharmony_ci BLK(ctx->prev, l1x + 1 + mx, l1y + my); 244cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = 245cabdff1aSopenharmony_ci BLK(ctx->prev, l1x + mx, l1y + 1 + my); 246cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = 247cabdff1aSopenharmony_ci BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my); 248cabdff1aSopenharmony_ci } 249cabdff1aSopenharmony_ci } else { // read values for block 250cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); 251cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); 252cabdff1aSopenharmony_ci BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); 253cabdff1aSopenharmony_ci BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); 254cabdff1aSopenharmony_ci } 255cabdff1aSopenharmony_ci } 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci } 259cabdff1aSopenharmony_ci } 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci return 0; 262cabdff1aSopenharmony_ci} 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext * avctx, AVFrame *frame, 265cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 266cabdff1aSopenharmony_ci{ 267cabdff1aSopenharmony_ci KmvcContext *const ctx = avctx->priv_data; 268cabdff1aSopenharmony_ci uint8_t *out, *src; 269cabdff1aSopenharmony_ci int i, ret; 270cabdff1aSopenharmony_ci int header; 271cabdff1aSopenharmony_ci int blocksize; 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci bytestream2_init(&ctx->g, avpkt->data, avpkt->size); 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 276cabdff1aSopenharmony_ci return ret; 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci frame->palette_has_changed = ff_copy_palette(ctx->pal, avpkt, avctx); 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci header = bytestream2_get_byte(&ctx->g); 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci /* blocksize 127 is really palette change event */ 283cabdff1aSopenharmony_ci if (bytestream2_peek_byte(&ctx->g) == 127) { 284cabdff1aSopenharmony_ci bytestream2_skip(&ctx->g, 3); 285cabdff1aSopenharmony_ci for (i = 0; i < 127; i++) { 286cabdff1aSopenharmony_ci ctx->pal[i + (header & 0x81)] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); 287cabdff1aSopenharmony_ci bytestream2_skip(&ctx->g, 1); 288cabdff1aSopenharmony_ci } 289cabdff1aSopenharmony_ci bytestream2_seek(&ctx->g, -127 * 4 - 3, SEEK_CUR); 290cabdff1aSopenharmony_ci } 291cabdff1aSopenharmony_ci 292cabdff1aSopenharmony_ci if (header & KMVC_KEYFRAME) { 293cabdff1aSopenharmony_ci frame->key_frame = 1; 294cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_I; 295cabdff1aSopenharmony_ci } else { 296cabdff1aSopenharmony_ci frame->key_frame = 0; 297cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_P; 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci if (header & KMVC_PALETTE) { 301cabdff1aSopenharmony_ci frame->palette_has_changed = 1; 302cabdff1aSopenharmony_ci // palette starts from index 1 and has 127 entries 303cabdff1aSopenharmony_ci for (i = 1; i <= ctx->palsize; i++) { 304cabdff1aSopenharmony_ci ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci } 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci if (ctx->setpal) { 309cabdff1aSopenharmony_ci ctx->setpal = 0; 310cabdff1aSopenharmony_ci frame->palette_has_changed = 1; 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci /* make the palette available on the way out */ 314cabdff1aSopenharmony_ci memcpy(frame->data[1], ctx->pal, 1024); 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci blocksize = bytestream2_get_byte(&ctx->g); 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci if (blocksize != 8 && blocksize != 127) { 319cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize); 320cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 321cabdff1aSopenharmony_ci } 322cabdff1aSopenharmony_ci memset(ctx->cur, 0, 320 * 200); 323cabdff1aSopenharmony_ci switch (header & KMVC_METHOD) { 324cabdff1aSopenharmony_ci case 0: 325cabdff1aSopenharmony_ci case 1: // used in palette changed event 326cabdff1aSopenharmony_ci memcpy(ctx->cur, ctx->prev, 320 * 200); 327cabdff1aSopenharmony_ci break; 328cabdff1aSopenharmony_ci case 3: 329cabdff1aSopenharmony_ci kmvc_decode_intra_8x8(ctx, avctx->width, avctx->height); 330cabdff1aSopenharmony_ci break; 331cabdff1aSopenharmony_ci case 4: 332cabdff1aSopenharmony_ci kmvc_decode_inter_8x8(ctx, avctx->width, avctx->height); 333cabdff1aSopenharmony_ci break; 334cabdff1aSopenharmony_ci default: 335cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD); 336cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci 339cabdff1aSopenharmony_ci out = frame->data[0]; 340cabdff1aSopenharmony_ci src = ctx->cur; 341cabdff1aSopenharmony_ci for (i = 0; i < avctx->height; i++) { 342cabdff1aSopenharmony_ci memcpy(out, src, avctx->width); 343cabdff1aSopenharmony_ci src += 320; 344cabdff1aSopenharmony_ci out += frame->linesize[0]; 345cabdff1aSopenharmony_ci } 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci /* flip buffers */ 348cabdff1aSopenharmony_ci FFSWAP(uint8_t *, ctx->cur, ctx->prev); 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci *got_frame = 1; 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci /* always report that the buffer was completely consumed */ 353cabdff1aSopenharmony_ci return avpkt->size; 354cabdff1aSopenharmony_ci} 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci/* 359cabdff1aSopenharmony_ci * Init kmvc decoder 360cabdff1aSopenharmony_ci */ 361cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext * avctx) 362cabdff1aSopenharmony_ci{ 363cabdff1aSopenharmony_ci KmvcContext *const c = avctx->priv_data; 364cabdff1aSopenharmony_ci int i; 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_ci c->avctx = avctx; 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci if (avctx->width > 320 || avctx->height > 200) { 369cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n"); 370cabdff1aSopenharmony_ci return AVERROR(EINVAL); 371cabdff1aSopenharmony_ci } 372cabdff1aSopenharmony_ci 373cabdff1aSopenharmony_ci c->cur = c->frm0; 374cabdff1aSopenharmony_ci c->prev = c->frm1; 375cabdff1aSopenharmony_ci 376cabdff1aSopenharmony_ci for (i = 0; i < 256; i++) { 377cabdff1aSopenharmony_ci c->pal[i] = 0xFFU << 24 | i * 0x10101; 378cabdff1aSopenharmony_ci } 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci if (avctx->extradata_size < 12) { 381cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 382cabdff1aSopenharmony_ci "Extradata missing, decoding may not work properly...\n"); 383cabdff1aSopenharmony_ci c->palsize = 127; 384cabdff1aSopenharmony_ci } else { 385cabdff1aSopenharmony_ci c->palsize = AV_RL16(avctx->extradata + 10); 386cabdff1aSopenharmony_ci if (c->palsize >= (unsigned)MAX_PALSIZE) { 387cabdff1aSopenharmony_ci c->palsize = 127; 388cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "KMVC palette too large\n"); 389cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 390cabdff1aSopenharmony_ci } 391cabdff1aSopenharmony_ci } 392cabdff1aSopenharmony_ci 393cabdff1aSopenharmony_ci if (avctx->extradata_size == 1036) { // palette in extradata 394cabdff1aSopenharmony_ci uint8_t *src = avctx->extradata + 12; 395cabdff1aSopenharmony_ci for (i = 0; i < 256; i++) { 396cabdff1aSopenharmony_ci c->pal[i] = AV_RL32(src); 397cabdff1aSopenharmony_ci src += 4; 398cabdff1aSopenharmony_ci } 399cabdff1aSopenharmony_ci c->setpal = 1; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci return 0; 405cabdff1aSopenharmony_ci} 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ciconst FFCodec ff_kmvc_decoder = { 408cabdff1aSopenharmony_ci .p.name = "kmvc", 409cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"), 410cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 411cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_KMVC, 412cabdff1aSopenharmony_ci .priv_data_size = sizeof(KmvcContext), 413cabdff1aSopenharmony_ci .init = decode_init, 414cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 415cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 416cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 417cabdff1aSopenharmony_ci}; 418