1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Zip Motion Blocks Video (ZMBV) 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 * Zip Motion Blocks Video decoder 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <stdio.h> 28cabdff1aSopenharmony_ci#include <stdlib.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/common.h" 31cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 32cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 33cabdff1aSopenharmony_ci#include "avcodec.h" 34cabdff1aSopenharmony_ci#include "codec_internal.h" 35cabdff1aSopenharmony_ci#include "internal.h" 36cabdff1aSopenharmony_ci#include "zlib_wrapper.h" 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci#include <zlib.h> 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#define ZMBV_KEYFRAME 1 41cabdff1aSopenharmony_ci#define ZMBV_DELTAPAL 2 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_cienum ZmbvFormat { 44cabdff1aSopenharmony_ci ZMBV_FMT_NONE = 0, 45cabdff1aSopenharmony_ci ZMBV_FMT_1BPP = 1, 46cabdff1aSopenharmony_ci ZMBV_FMT_2BPP = 2, 47cabdff1aSopenharmony_ci ZMBV_FMT_4BPP = 3, 48cabdff1aSopenharmony_ci ZMBV_FMT_8BPP = 4, 49cabdff1aSopenharmony_ci ZMBV_FMT_15BPP = 5, 50cabdff1aSopenharmony_ci ZMBV_FMT_16BPP = 6, 51cabdff1aSopenharmony_ci ZMBV_FMT_24BPP = 7, 52cabdff1aSopenharmony_ci ZMBV_FMT_32BPP = 8 53cabdff1aSopenharmony_ci}; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci/* 56cabdff1aSopenharmony_ci * Decoder context 57cabdff1aSopenharmony_ci */ 58cabdff1aSopenharmony_citypedef struct ZmbvContext { 59cabdff1aSopenharmony_ci AVCodecContext *avctx; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci int bpp; 62cabdff1aSopenharmony_ci int alloc_bpp; 63cabdff1aSopenharmony_ci unsigned int decomp_size; 64cabdff1aSopenharmony_ci uint8_t* decomp_buf; 65cabdff1aSopenharmony_ci uint8_t pal[768]; 66cabdff1aSopenharmony_ci uint8_t *prev, *cur; 67cabdff1aSopenharmony_ci int width, height; 68cabdff1aSopenharmony_ci int fmt; 69cabdff1aSopenharmony_ci int comp; 70cabdff1aSopenharmony_ci int flags; 71cabdff1aSopenharmony_ci int stride; 72cabdff1aSopenharmony_ci int bw, bh, bx, by; 73cabdff1aSopenharmony_ci int decomp_len; 74cabdff1aSopenharmony_ci int got_keyframe; 75cabdff1aSopenharmony_ci FFZStream zstream; 76cabdff1aSopenharmony_ci int (*decode_xor)(struct ZmbvContext *c); 77cabdff1aSopenharmony_ci} ZmbvContext; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci/** 80cabdff1aSopenharmony_ci * Decode XOR'ed frame - 8bpp version 81cabdff1aSopenharmony_ci */ 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_cistatic int zmbv_decode_xor_8(ZmbvContext *c) 84cabdff1aSopenharmony_ci{ 85cabdff1aSopenharmony_ci uint8_t *src = c->decomp_buf; 86cabdff1aSopenharmony_ci uint8_t *output, *prev; 87cabdff1aSopenharmony_ci int8_t *mvec; 88cabdff1aSopenharmony_ci int x, y; 89cabdff1aSopenharmony_ci int d, dx, dy, bw2, bh2; 90cabdff1aSopenharmony_ci int block; 91cabdff1aSopenharmony_ci int i, j; 92cabdff1aSopenharmony_ci int mx, my; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci output = c->cur; 95cabdff1aSopenharmony_ci prev = c->prev; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci if (c->flags & ZMBV_DELTAPAL) { 98cabdff1aSopenharmony_ci for (i = 0; i < 768; i++) 99cabdff1aSopenharmony_ci c->pal[i] ^= *src++; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci mvec = (int8_t*)src; 103cabdff1aSopenharmony_ci src += ((c->bx * c->by * 2 + 3) & ~3); 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci block = 0; 106cabdff1aSopenharmony_ci for (y = 0; y < c->height; y += c->bh) { 107cabdff1aSopenharmony_ci bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 108cabdff1aSopenharmony_ci for (x = 0; x < c->width; x += c->bw) { 109cabdff1aSopenharmony_ci uint8_t *out, *tprev; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci d = mvec[block] & 1; 112cabdff1aSopenharmony_ci dx = mvec[block] >> 1; 113cabdff1aSopenharmony_ci dy = mvec[block + 1] >> 1; 114cabdff1aSopenharmony_ci block += 2; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci /* copy block - motion vectors out of bounds are used to zero blocks */ 119cabdff1aSopenharmony_ci out = output + x; 120cabdff1aSopenharmony_ci tprev = prev + x + dx + dy * c->width; 121cabdff1aSopenharmony_ci mx = x + dx; 122cabdff1aSopenharmony_ci my = y + dy; 123cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 124cabdff1aSopenharmony_ci if (my + j < 0 || my + j >= c->height) { 125cabdff1aSopenharmony_ci memset(out, 0, bw2); 126cabdff1aSopenharmony_ci } else if (mx >= 0 && mx + bw2 <= c->width){ 127cabdff1aSopenharmony_ci memcpy(out, tprev, sizeof(*out) * bw2); 128cabdff1aSopenharmony_ci } else { 129cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) { 130cabdff1aSopenharmony_ci if (mx + i < 0 || mx + i >= c->width) 131cabdff1aSopenharmony_ci out[i] = 0; 132cabdff1aSopenharmony_ci else 133cabdff1aSopenharmony_ci out[i] = tprev[i]; 134cabdff1aSopenharmony_ci } 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci out += c->width; 137cabdff1aSopenharmony_ci tprev += c->width; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci if (d) { /* apply XOR'ed difference */ 141cabdff1aSopenharmony_ci out = output + x; 142cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 143cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) 144cabdff1aSopenharmony_ci out[i] ^= *src++; 145cabdff1aSopenharmony_ci out += c->width; 146cabdff1aSopenharmony_ci } 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci output += c->width * c->bh; 150cabdff1aSopenharmony_ci prev += c->width * c->bh; 151cabdff1aSopenharmony_ci } 152cabdff1aSopenharmony_ci if (src - c->decomp_buf != c->decomp_len) 153cabdff1aSopenharmony_ci av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", 154cabdff1aSopenharmony_ci src-c->decomp_buf, c->decomp_len); 155cabdff1aSopenharmony_ci return 0; 156cabdff1aSopenharmony_ci} 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci/** 159cabdff1aSopenharmony_ci * Decode XOR'ed frame - 15bpp and 16bpp version 160cabdff1aSopenharmony_ci */ 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_cistatic int zmbv_decode_xor_16(ZmbvContext *c) 163cabdff1aSopenharmony_ci{ 164cabdff1aSopenharmony_ci uint8_t *src = c->decomp_buf; 165cabdff1aSopenharmony_ci uint16_t *output, *prev; 166cabdff1aSopenharmony_ci int8_t *mvec; 167cabdff1aSopenharmony_ci int x, y; 168cabdff1aSopenharmony_ci int d, dx, dy, bw2, bh2; 169cabdff1aSopenharmony_ci int block; 170cabdff1aSopenharmony_ci int i, j; 171cabdff1aSopenharmony_ci int mx, my; 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci output = (uint16_t*)c->cur; 174cabdff1aSopenharmony_ci prev = (uint16_t*)c->prev; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci mvec = (int8_t*)src; 177cabdff1aSopenharmony_ci src += ((c->bx * c->by * 2 + 3) & ~3); 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci block = 0; 180cabdff1aSopenharmony_ci for (y = 0; y < c->height; y += c->bh) { 181cabdff1aSopenharmony_ci bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 182cabdff1aSopenharmony_ci for (x = 0; x < c->width; x += c->bw) { 183cabdff1aSopenharmony_ci uint16_t *out, *tprev; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci d = mvec[block] & 1; 186cabdff1aSopenharmony_ci dx = mvec[block] >> 1; 187cabdff1aSopenharmony_ci dy = mvec[block + 1] >> 1; 188cabdff1aSopenharmony_ci block += 2; 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ci bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci /* copy block - motion vectors out of bounds are used to zero blocks */ 193cabdff1aSopenharmony_ci out = output + x; 194cabdff1aSopenharmony_ci tprev = prev + x + dx + dy * c->width; 195cabdff1aSopenharmony_ci mx = x + dx; 196cabdff1aSopenharmony_ci my = y + dy; 197cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 198cabdff1aSopenharmony_ci if (my + j < 0 || my + j >= c->height) { 199cabdff1aSopenharmony_ci memset(out, 0, bw2 * 2); 200cabdff1aSopenharmony_ci } else if (mx >= 0 && mx + bw2 <= c->width){ 201cabdff1aSopenharmony_ci memcpy(out, tprev, sizeof(*out) * bw2); 202cabdff1aSopenharmony_ci } else { 203cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) { 204cabdff1aSopenharmony_ci if (mx + i < 0 || mx + i >= c->width) 205cabdff1aSopenharmony_ci out[i] = 0; 206cabdff1aSopenharmony_ci else 207cabdff1aSopenharmony_ci out[i] = tprev[i]; 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci } 210cabdff1aSopenharmony_ci out += c->width; 211cabdff1aSopenharmony_ci tprev += c->width; 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci if (d) { /* apply XOR'ed difference */ 215cabdff1aSopenharmony_ci out = output + x; 216cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++){ 217cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) { 218cabdff1aSopenharmony_ci out[i] ^= *((uint16_t*)src); 219cabdff1aSopenharmony_ci src += 2; 220cabdff1aSopenharmony_ci } 221cabdff1aSopenharmony_ci out += c->width; 222cabdff1aSopenharmony_ci } 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci } 225cabdff1aSopenharmony_ci output += c->width * c->bh; 226cabdff1aSopenharmony_ci prev += c->width * c->bh; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci if (src - c->decomp_buf != c->decomp_len) 229cabdff1aSopenharmony_ci av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", 230cabdff1aSopenharmony_ci src-c->decomp_buf, c->decomp_len); 231cabdff1aSopenharmony_ci return 0; 232cabdff1aSopenharmony_ci} 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci#ifdef ZMBV_ENABLE_24BPP 235cabdff1aSopenharmony_ci/** 236cabdff1aSopenharmony_ci * Decode XOR'ed frame - 24bpp version 237cabdff1aSopenharmony_ci */ 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_cistatic int zmbv_decode_xor_24(ZmbvContext *c) 240cabdff1aSopenharmony_ci{ 241cabdff1aSopenharmony_ci uint8_t *src = c->decomp_buf; 242cabdff1aSopenharmony_ci uint8_t *output, *prev; 243cabdff1aSopenharmony_ci int8_t *mvec; 244cabdff1aSopenharmony_ci int x, y; 245cabdff1aSopenharmony_ci int d, dx, dy, bw2, bh2; 246cabdff1aSopenharmony_ci int block; 247cabdff1aSopenharmony_ci int i, j; 248cabdff1aSopenharmony_ci int mx, my; 249cabdff1aSopenharmony_ci int stride; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci output = c->cur; 252cabdff1aSopenharmony_ci prev = c->prev; 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_ci stride = c->width * 3; 255cabdff1aSopenharmony_ci mvec = (int8_t*)src; 256cabdff1aSopenharmony_ci src += ((c->bx * c->by * 2 + 3) & ~3); 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci block = 0; 259cabdff1aSopenharmony_ci for (y = 0; y < c->height; y += c->bh) { 260cabdff1aSopenharmony_ci bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 261cabdff1aSopenharmony_ci for (x = 0; x < c->width; x += c->bw) { 262cabdff1aSopenharmony_ci uint8_t *out, *tprev; 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci d = mvec[block] & 1; 265cabdff1aSopenharmony_ci dx = mvec[block] >> 1; 266cabdff1aSopenharmony_ci dy = mvec[block + 1] >> 1; 267cabdff1aSopenharmony_ci block += 2; 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci /* copy block - motion vectors out of bounds are used to zero blocks */ 272cabdff1aSopenharmony_ci out = output + x * 3; 273cabdff1aSopenharmony_ci tprev = prev + (x + dx) * 3 + dy * stride; 274cabdff1aSopenharmony_ci mx = x + dx; 275cabdff1aSopenharmony_ci my = y + dy; 276cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 277cabdff1aSopenharmony_ci if (my + j < 0 || my + j >= c->height) { 278cabdff1aSopenharmony_ci memset(out, 0, bw2 * 3); 279cabdff1aSopenharmony_ci } else if (mx >= 0 && mx + bw2 <= c->width){ 280cabdff1aSopenharmony_ci memcpy(out, tprev, 3 * bw2); 281cabdff1aSopenharmony_ci } else { 282cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++){ 283cabdff1aSopenharmony_ci if (mx + i < 0 || mx + i >= c->width) { 284cabdff1aSopenharmony_ci out[i * 3 + 0] = 0; 285cabdff1aSopenharmony_ci out[i * 3 + 1] = 0; 286cabdff1aSopenharmony_ci out[i * 3 + 2] = 0; 287cabdff1aSopenharmony_ci } else { 288cabdff1aSopenharmony_ci out[i * 3 + 0] = tprev[i * 3 + 0]; 289cabdff1aSopenharmony_ci out[i * 3 + 1] = tprev[i * 3 + 1]; 290cabdff1aSopenharmony_ci out[i * 3 + 2] = tprev[i * 3 + 2]; 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci out += stride; 295cabdff1aSopenharmony_ci tprev += stride; 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci if (d) { /* apply XOR'ed difference */ 299cabdff1aSopenharmony_ci out = output + x * 3; 300cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 301cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) { 302cabdff1aSopenharmony_ci out[i * 3 + 0] ^= *src++; 303cabdff1aSopenharmony_ci out[i * 3 + 1] ^= *src++; 304cabdff1aSopenharmony_ci out[i * 3 + 2] ^= *src++; 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci out += stride; 307cabdff1aSopenharmony_ci } 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci } 310cabdff1aSopenharmony_ci output += stride * c->bh; 311cabdff1aSopenharmony_ci prev += stride * c->bh; 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci if (src - c->decomp_buf != c->decomp_len) 314cabdff1aSopenharmony_ci av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", 315cabdff1aSopenharmony_ci src-c->decomp_buf, c->decomp_len); 316cabdff1aSopenharmony_ci return 0; 317cabdff1aSopenharmony_ci} 318cabdff1aSopenharmony_ci#endif //ZMBV_ENABLE_24BPP 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci/** 321cabdff1aSopenharmony_ci * Decode XOR'ed frame - 32bpp version 322cabdff1aSopenharmony_ci */ 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_cistatic int zmbv_decode_xor_32(ZmbvContext *c) 325cabdff1aSopenharmony_ci{ 326cabdff1aSopenharmony_ci uint8_t *src = c->decomp_buf; 327cabdff1aSopenharmony_ci uint32_t *output, *prev; 328cabdff1aSopenharmony_ci int8_t *mvec; 329cabdff1aSopenharmony_ci int x, y; 330cabdff1aSopenharmony_ci int d, dx, dy, bw2, bh2; 331cabdff1aSopenharmony_ci int block; 332cabdff1aSopenharmony_ci int i, j; 333cabdff1aSopenharmony_ci int mx, my; 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci output = (uint32_t*)c->cur; 336cabdff1aSopenharmony_ci prev = (uint32_t*)c->prev; 337cabdff1aSopenharmony_ci 338cabdff1aSopenharmony_ci mvec = (int8_t*)src; 339cabdff1aSopenharmony_ci src += ((c->bx * c->by * 2 + 3) & ~3); 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci block = 0; 342cabdff1aSopenharmony_ci for (y = 0; y < c->height; y += c->bh) { 343cabdff1aSopenharmony_ci bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); 344cabdff1aSopenharmony_ci for (x = 0; x < c->width; x += c->bw) { 345cabdff1aSopenharmony_ci uint32_t *out, *tprev; 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci d = mvec[block] & 1; 348cabdff1aSopenharmony_ci dx = mvec[block] >> 1; 349cabdff1aSopenharmony_ci dy = mvec[block + 1] >> 1; 350cabdff1aSopenharmony_ci block += 2; 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); 353cabdff1aSopenharmony_ci 354cabdff1aSopenharmony_ci /* copy block - motion vectors out of bounds are used to zero blocks */ 355cabdff1aSopenharmony_ci out = output + x; 356cabdff1aSopenharmony_ci tprev = prev + x + dx + dy * c->width; 357cabdff1aSopenharmony_ci mx = x + dx; 358cabdff1aSopenharmony_ci my = y + dy; 359cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++) { 360cabdff1aSopenharmony_ci if (my + j < 0 || my + j >= c->height) { 361cabdff1aSopenharmony_ci memset(out, 0, bw2 * 4); 362cabdff1aSopenharmony_ci } else if (mx >= 0 && mx + bw2 <= c->width){ 363cabdff1aSopenharmony_ci memcpy(out, tprev, sizeof(*out) * bw2); 364cabdff1aSopenharmony_ci } else { 365cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++){ 366cabdff1aSopenharmony_ci if (mx + i < 0 || mx + i >= c->width) 367cabdff1aSopenharmony_ci out[i] = 0; 368cabdff1aSopenharmony_ci else 369cabdff1aSopenharmony_ci out[i] = tprev[i]; 370cabdff1aSopenharmony_ci } 371cabdff1aSopenharmony_ci } 372cabdff1aSopenharmony_ci out += c->width; 373cabdff1aSopenharmony_ci tprev += c->width; 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci 376cabdff1aSopenharmony_ci if (d) { /* apply XOR'ed difference */ 377cabdff1aSopenharmony_ci out = output + x; 378cabdff1aSopenharmony_ci for (j = 0; j < bh2; j++){ 379cabdff1aSopenharmony_ci for (i = 0; i < bw2; i++) { 380cabdff1aSopenharmony_ci out[i] ^= *((uint32_t *) src); 381cabdff1aSopenharmony_ci src += 4; 382cabdff1aSopenharmony_ci } 383cabdff1aSopenharmony_ci out += c->width; 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci } 387cabdff1aSopenharmony_ci output += c->width * c->bh; 388cabdff1aSopenharmony_ci prev += c->width * c->bh; 389cabdff1aSopenharmony_ci } 390cabdff1aSopenharmony_ci if (src - c->decomp_buf != c->decomp_len) 391cabdff1aSopenharmony_ci av_log(c->avctx, AV_LOG_ERROR, "Used %"PTRDIFF_SPECIFIER" of %i bytes\n", 392cabdff1aSopenharmony_ci src-c->decomp_buf, c->decomp_len); 393cabdff1aSopenharmony_ci return 0; 394cabdff1aSopenharmony_ci} 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci/** 397cabdff1aSopenharmony_ci * Decode intraframe 398cabdff1aSopenharmony_ci */ 399cabdff1aSopenharmony_cistatic int zmbv_decode_intra(ZmbvContext *c) 400cabdff1aSopenharmony_ci{ 401cabdff1aSopenharmony_ci uint8_t *src = c->decomp_buf; 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci /* make the palette available on the way out */ 404cabdff1aSopenharmony_ci if (c->fmt == ZMBV_FMT_8BPP) { 405cabdff1aSopenharmony_ci memcpy(c->pal, src, 768); 406cabdff1aSopenharmony_ci src += 768; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci memcpy(c->cur, src, c->width * c->height * (c->bpp / 8)); 410cabdff1aSopenharmony_ci return 0; 411cabdff1aSopenharmony_ci} 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame, 414cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 415cabdff1aSopenharmony_ci{ 416cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 417cabdff1aSopenharmony_ci int buf_size = avpkt->size; 418cabdff1aSopenharmony_ci ZmbvContext * const c = avctx->priv_data; 419cabdff1aSopenharmony_ci int zret = Z_OK; // Zlib return code 420cabdff1aSopenharmony_ci int len = buf_size; 421cabdff1aSopenharmony_ci int hi_ver, lo_ver, ret; 422cabdff1aSopenharmony_ci int expected_size; 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci /* parse header */ 425cabdff1aSopenharmony_ci if (len < 1) 426cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 427cabdff1aSopenharmony_ci c->flags = buf[0]; 428cabdff1aSopenharmony_ci buf++; len--; 429cabdff1aSopenharmony_ci if (c->flags & ZMBV_KEYFRAME) { 430cabdff1aSopenharmony_ci c->got_keyframe = 0; 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci if (len < 6) 433cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 434cabdff1aSopenharmony_ci hi_ver = buf[0]; 435cabdff1aSopenharmony_ci lo_ver = buf[1]; 436cabdff1aSopenharmony_ci c->comp = buf[2]; 437cabdff1aSopenharmony_ci c->fmt = buf[3]; 438cabdff1aSopenharmony_ci c->bw = buf[4]; 439cabdff1aSopenharmony_ci c->bh = buf[5]; 440cabdff1aSopenharmony_ci c->decode_xor = NULL; 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ci buf += 6; 443cabdff1aSopenharmony_ci len -= 6; 444cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, 445cabdff1aSopenharmony_ci "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n", 446cabdff1aSopenharmony_ci c->flags,hi_ver,lo_ver,c->comp,c->fmt,c->bw,c->bh); 447cabdff1aSopenharmony_ci if (hi_ver != 0 || lo_ver != 1) { 448cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Version %i.%i", hi_ver, lo_ver); 449cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 450cabdff1aSopenharmony_ci } 451cabdff1aSopenharmony_ci if (c->bw == 0 || c->bh == 0) { 452cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Block size %ix%i", c->bw, c->bh); 453cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 454cabdff1aSopenharmony_ci } 455cabdff1aSopenharmony_ci if (c->comp != 0 && c->comp != 1) { 456cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Compression type %i", c->comp); 457cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 458cabdff1aSopenharmony_ci } 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci switch (c->fmt) { 461cabdff1aSopenharmony_ci case ZMBV_FMT_8BPP: 462cabdff1aSopenharmony_ci c->bpp = 8; 463cabdff1aSopenharmony_ci c->decode_xor = zmbv_decode_xor_8; 464cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 465cabdff1aSopenharmony_ci c->stride = c->width; 466cabdff1aSopenharmony_ci break; 467cabdff1aSopenharmony_ci case ZMBV_FMT_15BPP: 468cabdff1aSopenharmony_ci case ZMBV_FMT_16BPP: 469cabdff1aSopenharmony_ci c->bpp = 16; 470cabdff1aSopenharmony_ci c->decode_xor = zmbv_decode_xor_16; 471cabdff1aSopenharmony_ci if (c->fmt == ZMBV_FMT_15BPP) 472cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_RGB555LE; 473cabdff1aSopenharmony_ci else 474cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_RGB565LE; 475cabdff1aSopenharmony_ci c->stride = c->width * 2; 476cabdff1aSopenharmony_ci break; 477cabdff1aSopenharmony_ci#ifdef ZMBV_ENABLE_24BPP 478cabdff1aSopenharmony_ci case ZMBV_FMT_24BPP: 479cabdff1aSopenharmony_ci c->bpp = 24; 480cabdff1aSopenharmony_ci c->decode_xor = zmbv_decode_xor_24; 481cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR24; 482cabdff1aSopenharmony_ci c->stride = c->width * 3; 483cabdff1aSopenharmony_ci break; 484cabdff1aSopenharmony_ci#endif //ZMBV_ENABLE_24BPP 485cabdff1aSopenharmony_ci case ZMBV_FMT_32BPP: 486cabdff1aSopenharmony_ci c->bpp = 32; 487cabdff1aSopenharmony_ci c->decode_xor = zmbv_decode_xor_32; 488cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR0; 489cabdff1aSopenharmony_ci c->stride = c->width * 4; 490cabdff1aSopenharmony_ci break; 491cabdff1aSopenharmony_ci default: 492cabdff1aSopenharmony_ci c->decode_xor = NULL; 493cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Format %i", c->fmt); 494cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 495cabdff1aSopenharmony_ci } 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci zret = inflateReset(&c->zstream.zstream); 498cabdff1aSopenharmony_ci if (zret != Z_OK) { 499cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); 500cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 501cabdff1aSopenharmony_ci } 502cabdff1aSopenharmony_ci 503cabdff1aSopenharmony_ci if (c->alloc_bpp < c->bpp) { 504cabdff1aSopenharmony_ci c->cur = av_realloc_f(c->cur, avctx->width * avctx->height, (c->bpp / 8)); 505cabdff1aSopenharmony_ci c->prev = av_realloc_f(c->prev, avctx->width * avctx->height, (c->bpp / 8)); 506cabdff1aSopenharmony_ci c->alloc_bpp = c->bpp; 507cabdff1aSopenharmony_ci } 508cabdff1aSopenharmony_ci c->bx = (c->width + c->bw - 1) / c->bw; 509cabdff1aSopenharmony_ci c->by = (c->height+ c->bh - 1) / c->bh; 510cabdff1aSopenharmony_ci if (!c->cur || !c->prev) { 511cabdff1aSopenharmony_ci c->alloc_bpp = 0; 512cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 513cabdff1aSopenharmony_ci } 514cabdff1aSopenharmony_ci memset(c->cur, 0, avctx->width * avctx->height * (c->bpp / 8)); 515cabdff1aSopenharmony_ci memset(c->prev, 0, avctx->width * avctx->height * (c->bpp / 8)); 516cabdff1aSopenharmony_ci c->got_keyframe = 1; 517cabdff1aSopenharmony_ci } 518cabdff1aSopenharmony_ci if (c->flags & ZMBV_KEYFRAME) { 519cabdff1aSopenharmony_ci expected_size = avctx->width * avctx->height * (c->bpp / 8); 520cabdff1aSopenharmony_ci } else { 521cabdff1aSopenharmony_ci expected_size = (c->bx * c->by * 2 + 3) & ~3; 522cabdff1aSopenharmony_ci } 523cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && 524cabdff1aSopenharmony_ci (c->flags & (ZMBV_DELTAPAL | ZMBV_KEYFRAME))) 525cabdff1aSopenharmony_ci expected_size += 768; 526cabdff1aSopenharmony_ci 527cabdff1aSopenharmony_ci if (!c->got_keyframe) { 528cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); 529cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 530cabdff1aSopenharmony_ci } 531cabdff1aSopenharmony_ci 532cabdff1aSopenharmony_ci if (c->comp == 0) { // uncompressed data 533cabdff1aSopenharmony_ci if (c->decomp_size < len) { 534cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Buffer too small\n"); 535cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 536cabdff1aSopenharmony_ci } 537cabdff1aSopenharmony_ci memcpy(c->decomp_buf, buf, len); 538cabdff1aSopenharmony_ci c->decomp_len = len; 539cabdff1aSopenharmony_ci } else { // ZLIB-compressed data 540cabdff1aSopenharmony_ci z_stream *const zstream = &c->zstream.zstream; 541cabdff1aSopenharmony_ci 542cabdff1aSopenharmony_ci zstream->total_in = zstream->total_out = 0; 543cabdff1aSopenharmony_ci zstream->next_in = buf; 544cabdff1aSopenharmony_ci zstream->avail_in = len; 545cabdff1aSopenharmony_ci zstream->next_out = c->decomp_buf; 546cabdff1aSopenharmony_ci zstream->avail_out = c->decomp_size; 547cabdff1aSopenharmony_ci zret = inflate(zstream, Z_SYNC_FLUSH); 548cabdff1aSopenharmony_ci if (zret != Z_OK && zret != Z_STREAM_END) { 549cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "inflate error %d\n", zret); 550cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 551cabdff1aSopenharmony_ci } 552cabdff1aSopenharmony_ci c->decomp_len = zstream->total_out; 553cabdff1aSopenharmony_ci } 554cabdff1aSopenharmony_ci if (expected_size > c->decomp_len || 555cabdff1aSopenharmony_ci (c->flags & ZMBV_KEYFRAME) && expected_size < c->decomp_len) { 556cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "decompressed size %d is incorrect, expected %d\n", c->decomp_len, expected_size); 557cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 558cabdff1aSopenharmony_ci } 559cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 560cabdff1aSopenharmony_ci return ret; 561cabdff1aSopenharmony_ci 562cabdff1aSopenharmony_ci if (c->flags & ZMBV_KEYFRAME) { 563cabdff1aSopenharmony_ci frame->key_frame = 1; 564cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_I; 565cabdff1aSopenharmony_ci zmbv_decode_intra(c); 566cabdff1aSopenharmony_ci } else { 567cabdff1aSopenharmony_ci frame->key_frame = 0; 568cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_P; 569cabdff1aSopenharmony_ci if (c->decomp_len < 2LL * ((c->width + c->bw - 1) / c->bw) * ((c->height + c->bh - 1) / c->bh)) 570cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 571cabdff1aSopenharmony_ci if (c->decomp_len) 572cabdff1aSopenharmony_ci c->decode_xor(c); 573cabdff1aSopenharmony_ci } 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_ci /* update frames */ 576cabdff1aSopenharmony_ci { 577cabdff1aSopenharmony_ci uint8_t *out, *src; 578cabdff1aSopenharmony_ci int j; 579cabdff1aSopenharmony_ci 580cabdff1aSopenharmony_ci out = frame->data[0]; 581cabdff1aSopenharmony_ci src = c->cur; 582cabdff1aSopenharmony_ci switch (c->fmt) { 583cabdff1aSopenharmony_ci case ZMBV_FMT_8BPP: 584cabdff1aSopenharmony_ci for (j = 0; j < 256; j++) 585cabdff1aSopenharmony_ci AV_WN32(&frame->data[1][j * 4], 0xFFU << 24 | AV_RB24(&c->pal[j * 3])); 586cabdff1aSopenharmony_ci case ZMBV_FMT_15BPP: 587cabdff1aSopenharmony_ci case ZMBV_FMT_16BPP: 588cabdff1aSopenharmony_ci#ifdef ZMBV_ENABLE_24BPP 589cabdff1aSopenharmony_ci case ZMBV_FMT_24BPP: 590cabdff1aSopenharmony_ci#endif 591cabdff1aSopenharmony_ci case ZMBV_FMT_32BPP: 592cabdff1aSopenharmony_ci av_image_copy_plane(out, frame->linesize[0], src, c->stride, 593cabdff1aSopenharmony_ci c->stride, c->height); 594cabdff1aSopenharmony_ci break; 595cabdff1aSopenharmony_ci default: 596cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt); 597cabdff1aSopenharmony_ci } 598cabdff1aSopenharmony_ci FFSWAP(uint8_t *, c->cur, c->prev); 599cabdff1aSopenharmony_ci } 600cabdff1aSopenharmony_ci *got_frame = 1; 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_ci /* always report that the buffer was completely consumed */ 603cabdff1aSopenharmony_ci return buf_size; 604cabdff1aSopenharmony_ci} 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx) 607cabdff1aSopenharmony_ci{ 608cabdff1aSopenharmony_ci ZmbvContext * const c = avctx->priv_data; 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci c->avctx = avctx; 611cabdff1aSopenharmony_ci 612cabdff1aSopenharmony_ci c->width = avctx->width; 613cabdff1aSopenharmony_ci c->height = avctx->height; 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci c->bpp = avctx->bits_per_coded_sample; 616cabdff1aSopenharmony_ci 617cabdff1aSopenharmony_ci if ((avctx->width + 255ULL) * (avctx->height + 64ULL) > FFMIN(avctx->max_pixels, INT_MAX / 4) ) { 618cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Internal buffer (decomp_size) larger than max_pixels or too large\n"); 619cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 620cabdff1aSopenharmony_ci } 621cabdff1aSopenharmony_ci 622cabdff1aSopenharmony_ci c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64); 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci /* Allocate decompression buffer */ 625cabdff1aSopenharmony_ci c->decomp_buf = av_mallocz(c->decomp_size); 626cabdff1aSopenharmony_ci if (!c->decomp_buf) { 627cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 628cabdff1aSopenharmony_ci "Can't allocate decompression buffer.\n"); 629cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 630cabdff1aSopenharmony_ci } 631cabdff1aSopenharmony_ci 632cabdff1aSopenharmony_ci return ff_inflate_init(&c->zstream, avctx); 633cabdff1aSopenharmony_ci} 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx) 636cabdff1aSopenharmony_ci{ 637cabdff1aSopenharmony_ci ZmbvContext * const c = avctx->priv_data; 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_ci av_freep(&c->decomp_buf); 640cabdff1aSopenharmony_ci 641cabdff1aSopenharmony_ci av_freep(&c->cur); 642cabdff1aSopenharmony_ci av_freep(&c->prev); 643cabdff1aSopenharmony_ci ff_inflate_end(&c->zstream); 644cabdff1aSopenharmony_ci 645cabdff1aSopenharmony_ci return 0; 646cabdff1aSopenharmony_ci} 647cabdff1aSopenharmony_ci 648cabdff1aSopenharmony_ciconst FFCodec ff_zmbv_decoder = { 649cabdff1aSopenharmony_ci .p.name = "zmbv", 650cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), 651cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 652cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_ZMBV, 653cabdff1aSopenharmony_ci .priv_data_size = sizeof(ZmbvContext), 654cabdff1aSopenharmony_ci .init = decode_init, 655cabdff1aSopenharmony_ci .close = decode_end, 656cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 657cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 658cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 659cabdff1aSopenharmony_ci}; 660