1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2010 Peter Ross <pross@xvid.org> 4cabdff1aSopenharmony_ci * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> 5cabdff1aSopenharmony_ci * Copyright (c) 2016 Paul B Mahol 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci/** 25cabdff1aSopenharmony_ci * @file 26cabdff1aSopenharmony_ci * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder 27cabdff1aSopenharmony_ci */ 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include <stdint.h> 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci#include "bytestream.h" 34cabdff1aSopenharmony_ci#include "avcodec.h" 35cabdff1aSopenharmony_ci#include "codec_internal.h" 36cabdff1aSopenharmony_ci#include "internal.h" 37cabdff1aSopenharmony_ci#include "mathops.h" 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci// TODO: masking bits 40cabdff1aSopenharmony_citypedef enum { 41cabdff1aSopenharmony_ci MASK_NONE, 42cabdff1aSopenharmony_ci MASK_HAS_MASK, 43cabdff1aSopenharmony_ci MASK_HAS_TRANSPARENT_COLOR, 44cabdff1aSopenharmony_ci MASK_LASSO 45cabdff1aSopenharmony_ci} mask_type; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_citypedef struct IffContext { 48cabdff1aSopenharmony_ci AVFrame *frame; 49cabdff1aSopenharmony_ci int planesize; 50cabdff1aSopenharmony_ci uint8_t * planebuf; 51cabdff1aSopenharmony_ci uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation 52cabdff1aSopenharmony_ci uint32_t *ham_palbuf; ///< HAM decode table 53cabdff1aSopenharmony_ci uint32_t *mask_buf; ///< temporary buffer for palette indices 54cabdff1aSopenharmony_ci uint32_t *mask_palbuf; ///< masking palette table 55cabdff1aSopenharmony_ci unsigned compression; ///< delta compression method used 56cabdff1aSopenharmony_ci unsigned is_short; ///< short compression method used 57cabdff1aSopenharmony_ci unsigned is_interlaced;///< video is interlaced 58cabdff1aSopenharmony_ci unsigned is_brush; ///< video is in ANBR format 59cabdff1aSopenharmony_ci unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) 60cabdff1aSopenharmony_ci unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) 61cabdff1aSopenharmony_ci unsigned flags; ///< 1 for EHB, 0 is no extra half darkening 62cabdff1aSopenharmony_ci unsigned transparency; ///< TODO: transparency color index in palette 63cabdff1aSopenharmony_ci unsigned masking; ///< TODO: masking method used 64cabdff1aSopenharmony_ci int init; // 1 if buffer and palette data already initialized, 0 otherwise 65cabdff1aSopenharmony_ci int16_t tvdc[16]; ///< TVDC lookup table 66cabdff1aSopenharmony_ci GetByteContext gb; 67cabdff1aSopenharmony_ci uint8_t *video[2]; 68cabdff1aSopenharmony_ci unsigned video_size; 69cabdff1aSopenharmony_ci uint32_t *pal; 70cabdff1aSopenharmony_ci} IffContext; 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci#define LUT8_PART(plane, v) \ 73cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \ 74cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \ 75cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \ 76cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \ 77cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \ 78cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \ 79cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \ 80cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \ 81cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \ 82cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \ 83cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \ 84cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \ 85cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \ 86cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \ 87cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \ 88cabdff1aSopenharmony_ci AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci#define LUT8(plane) { \ 91cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0000000), \ 92cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1000000), \ 93cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0010000), \ 94cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1010000), \ 95cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0000100), \ 96cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1000100), \ 97cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0010100), \ 98cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1010100), \ 99cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0000001), \ 100cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1000001), \ 101cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0010001), \ 102cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1010001), \ 103cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0000101), \ 104cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1000101), \ 105cabdff1aSopenharmony_ci LUT8_PART(plane, 0x0010101), \ 106cabdff1aSopenharmony_ci LUT8_PART(plane, 0x1010101), \ 107cabdff1aSopenharmony_ci} 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci// 8 planes * 8-bit mask 110cabdff1aSopenharmony_cistatic const uint64_t plane8_lut[8][256] = { 111cabdff1aSopenharmony_ci LUT8(0), LUT8(1), LUT8(2), LUT8(3), 112cabdff1aSopenharmony_ci LUT8(4), LUT8(5), LUT8(6), LUT8(7), 113cabdff1aSopenharmony_ci}; 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci#define LUT32(plane) { \ 116cabdff1aSopenharmony_ci 0, 0, 0, 0, \ 117cabdff1aSopenharmony_ci 0, 0, 0, 1U << plane, \ 118cabdff1aSopenharmony_ci 0, 0, 1U << plane, 0, \ 119cabdff1aSopenharmony_ci 0, 0, 1U << plane, 1U << plane, \ 120cabdff1aSopenharmony_ci 0, 1U << plane, 0, 0, \ 121cabdff1aSopenharmony_ci 0, 1U << plane, 0, 1U << plane, \ 122cabdff1aSopenharmony_ci 0, 1U << plane, 1U << plane, 0, \ 123cabdff1aSopenharmony_ci 0, 1U << plane, 1U << plane, 1U << plane, \ 124cabdff1aSopenharmony_ci 1U << plane, 0, 0, 0, \ 125cabdff1aSopenharmony_ci 1U << plane, 0, 0, 1U << plane, \ 126cabdff1aSopenharmony_ci 1U << plane, 0, 1U << plane, 0, \ 127cabdff1aSopenharmony_ci 1U << plane, 0, 1U << plane, 1U << plane, \ 128cabdff1aSopenharmony_ci 1U << plane, 1U << plane, 0, 0, \ 129cabdff1aSopenharmony_ci 1U << plane, 1U << plane, 0, 1U << plane, \ 130cabdff1aSopenharmony_ci 1U << plane, 1U << plane, 1U << plane, 0, \ 131cabdff1aSopenharmony_ci 1U << plane, 1U << plane, 1U << plane, 1U << plane, \ 132cabdff1aSopenharmony_ci} 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci// 32 planes * 4-bit mask * 4 lookup tables each 135cabdff1aSopenharmony_cistatic const uint32_t plane32_lut[32][16*4] = { 136cabdff1aSopenharmony_ci LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3), 137cabdff1aSopenharmony_ci LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7), 138cabdff1aSopenharmony_ci LUT32( 8), LUT32( 9), LUT32(10), LUT32(11), 139cabdff1aSopenharmony_ci LUT32(12), LUT32(13), LUT32(14), LUT32(15), 140cabdff1aSopenharmony_ci LUT32(16), LUT32(17), LUT32(18), LUT32(19), 141cabdff1aSopenharmony_ci LUT32(20), LUT32(21), LUT32(22), LUT32(23), 142cabdff1aSopenharmony_ci LUT32(24), LUT32(25), LUT32(26), LUT32(27), 143cabdff1aSopenharmony_ci LUT32(28), LUT32(29), LUT32(30), LUT32(31), 144cabdff1aSopenharmony_ci}; 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci// Gray to RGB, required for palette table of grayscale images with bpp < 8 147cabdff1aSopenharmony_cistatic av_always_inline uint32_t gray2rgb(const uint32_t x) { 148cabdff1aSopenharmony_ci return x << 16 | x << 8 | x; 149cabdff1aSopenharmony_ci} 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci/** 152cabdff1aSopenharmony_ci * Convert CMAP buffer (stored in extradata) to lavc palette format 153cabdff1aSopenharmony_ci */ 154cabdff1aSopenharmony_cistatic int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) 155cabdff1aSopenharmony_ci{ 156cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 157cabdff1aSopenharmony_ci int count, i; 158cabdff1aSopenharmony_ci const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); 159cabdff1aSopenharmony_ci int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci if (avctx->bits_per_coded_sample > 8) { 162cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n"); 163cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci count = 1 << avctx->bits_per_coded_sample; 167cabdff1aSopenharmony_ci // If extradata is smaller than actually needed, fill the remaining with black. 168cabdff1aSopenharmony_ci count = FFMIN(palette_size / 3, count); 169cabdff1aSopenharmony_ci if (count) { 170cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 171cabdff1aSopenharmony_ci pal[i] = 0xFF000000 | AV_RB24(palette + i*3); 172cabdff1aSopenharmony_ci if (s->flags && count >= 32) { // EHB 173cabdff1aSopenharmony_ci for (i = 0; i < 32; i++) 174cabdff1aSopenharmony_ci pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1; 175cabdff1aSopenharmony_ci count = FFMAX(count, 64); 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci } else { // Create gray-scale color palette for bps < 8 178cabdff1aSopenharmony_ci count = 1 << avctx->bits_per_coded_sample; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 181cabdff1aSopenharmony_ci pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample); 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci if (s->masking == MASK_HAS_MASK) { 184cabdff1aSopenharmony_ci if ((1 << avctx->bits_per_coded_sample) < count) { 185cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "overlapping mask"); 186cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4); 189cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 190cabdff1aSopenharmony_ci pal[i] &= 0xFFFFFF; 191cabdff1aSopenharmony_ci } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR && 192cabdff1aSopenharmony_ci s->transparency < 1 << avctx->bits_per_coded_sample) 193cabdff1aSopenharmony_ci pal[s->transparency] &= 0xFFFFFF; 194cabdff1aSopenharmony_ci return 0; 195cabdff1aSopenharmony_ci} 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci/** 198cabdff1aSopenharmony_ci * Extracts the IFF extra context and updates internal 199cabdff1aSopenharmony_ci * decoder structures. 200cabdff1aSopenharmony_ci * 201cabdff1aSopenharmony_ci * @param avctx the AVCodecContext where to extract extra context to 202cabdff1aSopenharmony_ci * @param avpkt the AVPacket to extract extra context from or NULL to use avctx 203cabdff1aSopenharmony_ci * @return >= 0 in case of success, a negative error code otherwise 204cabdff1aSopenharmony_ci */ 205cabdff1aSopenharmony_cistatic int extract_header(AVCodecContext *const avctx, 206cabdff1aSopenharmony_ci const AVPacket *const avpkt) 207cabdff1aSopenharmony_ci{ 208cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 209cabdff1aSopenharmony_ci const uint8_t *buf; 210cabdff1aSopenharmony_ci unsigned buf_size = 0; 211cabdff1aSopenharmony_ci int i, palette_size; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci if (avctx->extradata_size < 2) { 214cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); 215cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 216cabdff1aSopenharmony_ci } 217cabdff1aSopenharmony_ci palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci if (avpkt && avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 220cabdff1aSopenharmony_ci uint32_t chunk_id; 221cabdff1aSopenharmony_ci uint64_t data_size; 222cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_ci bytestream2_skip(gb, 4); 225cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) >= 1) { 226cabdff1aSopenharmony_ci chunk_id = bytestream2_get_le32(gb); 227cabdff1aSopenharmony_ci data_size = bytestream2_get_be32(gb); 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci if (chunk_id == MKTAG('B', 'M', 'H', 'D')) { 230cabdff1aSopenharmony_ci bytestream2_skip(gb, data_size + (data_size & 1)); 231cabdff1aSopenharmony_ci } else if (chunk_id == MKTAG('A', 'N', 'H', 'D')) { 232cabdff1aSopenharmony_ci unsigned extra; 233cabdff1aSopenharmony_ci if (data_size < 40) 234cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci s->compression = (bytestream2_get_byte(gb) << 8) | (s->compression & 0xFF); 237cabdff1aSopenharmony_ci bytestream2_skip(gb, 19); 238cabdff1aSopenharmony_ci extra = bytestream2_get_be32(gb); 239cabdff1aSopenharmony_ci s->is_short = !(extra & 1); 240cabdff1aSopenharmony_ci s->is_brush = extra == 2; 241cabdff1aSopenharmony_ci s->is_interlaced = !!(extra & 0x40); 242cabdff1aSopenharmony_ci data_size -= 24; 243cabdff1aSopenharmony_ci bytestream2_skip(gb, data_size + (data_size & 1)); 244cabdff1aSopenharmony_ci } else if (chunk_id == MKTAG('D', 'L', 'T', 'A') || 245cabdff1aSopenharmony_ci chunk_id == MKTAG('B', 'O', 'D', 'Y')) { 246cabdff1aSopenharmony_ci if (chunk_id == MKTAG('B','O','D','Y')) 247cabdff1aSopenharmony_ci s->compression &= 0xFF; 248cabdff1aSopenharmony_ci break; 249cabdff1aSopenharmony_ci } else if (chunk_id == MKTAG('C', 'M', 'A', 'P')) { 250cabdff1aSopenharmony_ci int count = data_size / 3; 251cabdff1aSopenharmony_ci uint32_t *pal = s->pal; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci if (count > 256) 254cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 255cabdff1aSopenharmony_ci if (s->ham) { 256cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 257cabdff1aSopenharmony_ci pal[i] = 0xFF000000 | bytestream2_get_le24(gb); 258cabdff1aSopenharmony_ci } else { 259cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 260cabdff1aSopenharmony_ci pal[i] = 0xFF000000 | bytestream2_get_be24(gb); 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci bytestream2_skip(gb, data_size & 1); 263cabdff1aSopenharmony_ci } else { 264cabdff1aSopenharmony_ci bytestream2_skip(gb, data_size + (data_size&1)); 265cabdff1aSopenharmony_ci } 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci } else if (!avpkt) { 268cabdff1aSopenharmony_ci buf = avctx->extradata; 269cabdff1aSopenharmony_ci buf_size = bytestream_get_be16(&buf); 270cabdff1aSopenharmony_ci if (buf_size <= 1 || palette_size < 0) { 271cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 272cabdff1aSopenharmony_ci "Invalid palette size received: %u -> palette data offset: %d\n", 273cabdff1aSopenharmony_ci buf_size, palette_size); 274cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci if (buf_size >= 41) { 279cabdff1aSopenharmony_ci s->compression = bytestream_get_byte(&buf); 280cabdff1aSopenharmony_ci s->bpp = bytestream_get_byte(&buf); 281cabdff1aSopenharmony_ci s->ham = bytestream_get_byte(&buf); 282cabdff1aSopenharmony_ci s->flags = bytestream_get_byte(&buf); 283cabdff1aSopenharmony_ci s->transparency = bytestream_get_be16(&buf); 284cabdff1aSopenharmony_ci s->masking = bytestream_get_byte(&buf); 285cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) 286cabdff1aSopenharmony_ci s->tvdc[i] = bytestream_get_be16(&buf); 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci if (s->ham) { 289cabdff1aSopenharmony_ci if (s->bpp > 8) { 290cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham); 291cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 292cabdff1aSopenharmony_ci } else if (s->ham != (s->bpp > 6 ? 6 : 4)) { 293cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u, BPP: %u\n", s->ham, s->bpp); 294cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci if (s->masking == MASK_HAS_MASK) { 299cabdff1aSopenharmony_ci if (s->bpp >= 8 && !s->ham) { 300cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_RGB32; 301cabdff1aSopenharmony_ci av_freep(&s->mask_buf); 302cabdff1aSopenharmony_ci av_freep(&s->mask_palbuf); 303cabdff1aSopenharmony_ci if (s->bpp > 16) { 304cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "bpp %d too large for palette\n", s->bpp); 305cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 306cabdff1aSopenharmony_ci } 307cabdff1aSopenharmony_ci s->mask_buf = av_malloc((s->planesize * 32) + AV_INPUT_BUFFER_PADDING_SIZE); 308cabdff1aSopenharmony_ci if (!s->mask_buf) 309cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 310cabdff1aSopenharmony_ci s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE); 311cabdff1aSopenharmony_ci if (!s->mask_palbuf) { 312cabdff1aSopenharmony_ci av_freep(&s->mask_buf); 313cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci } 316cabdff1aSopenharmony_ci s->bpp++; 317cabdff1aSopenharmony_ci } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) { 318cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Masking not supported\n"); 319cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci if (!s->bpp || s->bpp > 32) { 322cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp); 323cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 324cabdff1aSopenharmony_ci } 325cabdff1aSopenharmony_ci if (s->video_size && s->planesize * s->bpp * avctx->height > s->video_size) 326cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci av_freep(&s->ham_buf); 329cabdff1aSopenharmony_ci av_freep(&s->ham_palbuf); 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci if (s->ham) { 332cabdff1aSopenharmony_ci int i, count = FFMIN(palette_size / 3, 1 << s->ham); 333cabdff1aSopenharmony_ci int ham_count; 334cabdff1aSopenharmony_ci const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); 335cabdff1aSopenharmony_ci int extra_space = 1; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ') && s->ham == 4) 338cabdff1aSopenharmony_ci extra_space = 4; 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci s->ham_buf = av_malloc((s->planesize * 8) + AV_INPUT_BUFFER_PADDING_SIZE); 341cabdff1aSopenharmony_ci if (!s->ham_buf) 342cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci ham_count = 8 * (1 << s->ham); 345cabdff1aSopenharmony_ci s->ham_palbuf = av_malloc(extra_space * (ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE); 346cabdff1aSopenharmony_ci if (!s->ham_palbuf) { 347cabdff1aSopenharmony_ci av_freep(&s->ham_buf); 348cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci if (count) { // HAM with color palette attached 352cabdff1aSopenharmony_ci // prefill with black and palette and set HAM take direct value mask to zero 353cabdff1aSopenharmony_ci memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t)); 354cabdff1aSopenharmony_ci for (i=0; i < count; i++) { 355cabdff1aSopenharmony_ci s->ham_palbuf[i*2+1] = 0xFF000000 | AV_RL24(palette + i*3); 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci count = 1 << s->ham; 358cabdff1aSopenharmony_ci } else { // HAM with grayscale color palette 359cabdff1aSopenharmony_ci count = 1 << s->ham; 360cabdff1aSopenharmony_ci for (i=0; i < count; i++) { 361cabdff1aSopenharmony_ci s->ham_palbuf[i*2] = 0xFF000000; // take direct color value from palette 362cabdff1aSopenharmony_ci s->ham_palbuf[i*2+1] = 0xFF000000 | av_le2ne32(gray2rgb((i * 255) >> s->ham)); 363cabdff1aSopenharmony_ci } 364cabdff1aSopenharmony_ci } 365cabdff1aSopenharmony_ci for (i=0; i < count; i++) { 366cabdff1aSopenharmony_ci uint32_t tmp = i << (8 - s->ham); 367cabdff1aSopenharmony_ci tmp |= tmp >> s->ham; 368cabdff1aSopenharmony_ci s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; // just modify blue color component 369cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; // just modify red color component 370cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; // just modify green color component 371cabdff1aSopenharmony_ci s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16; 372cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp; 373cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8; 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci if (s->masking == MASK_HAS_MASK) { 376cabdff1aSopenharmony_ci for (i = 0; i < ham_count; i++) 377cabdff1aSopenharmony_ci s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000; 378cabdff1aSopenharmony_ci } 379cabdff1aSopenharmony_ci } 380cabdff1aSopenharmony_ci } 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci return 0; 383cabdff1aSopenharmony_ci} 384cabdff1aSopenharmony_ci 385cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx) 386cabdff1aSopenharmony_ci{ 387cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 388cabdff1aSopenharmony_ci av_freep(&s->planebuf); 389cabdff1aSopenharmony_ci av_freep(&s->ham_buf); 390cabdff1aSopenharmony_ci av_freep(&s->ham_palbuf); 391cabdff1aSopenharmony_ci av_freep(&s->mask_buf); 392cabdff1aSopenharmony_ci av_freep(&s->mask_palbuf); 393cabdff1aSopenharmony_ci av_freep(&s->video[0]); 394cabdff1aSopenharmony_ci av_freep(&s->video[1]); 395cabdff1aSopenharmony_ci av_freep(&s->pal); 396cabdff1aSopenharmony_ci return 0; 397cabdff1aSopenharmony_ci} 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx) 400cabdff1aSopenharmony_ci{ 401cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 402cabdff1aSopenharmony_ci int err; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci if (avctx->bits_per_coded_sample <= 8) { 405cabdff1aSopenharmony_ci int palette_size; 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci if (avctx->extradata_size >= 2) 408cabdff1aSopenharmony_ci palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 409cabdff1aSopenharmony_ci else 410cabdff1aSopenharmony_ci palette_size = 0; 411cabdff1aSopenharmony_ci avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) || 412cabdff1aSopenharmony_ci (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; 413cabdff1aSopenharmony_ci } else if (avctx->bits_per_coded_sample <= 32) { 414cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8')) { 415cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_RGB32; 416cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N')) { 417cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_RGB444; 418cabdff1aSopenharmony_ci } else if (avctx->codec_tag != MKTAG('D', 'E', 'E', 'P')) { 419cabdff1aSopenharmony_ci if (avctx->bits_per_coded_sample == 24) { 420cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_0BGR32; 421cabdff1aSopenharmony_ci } else if (avctx->bits_per_coded_sample == 32) { 422cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR32; 423cabdff1aSopenharmony_ci } else { 424cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "unknown bits_per_coded_sample"); 425cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 426cabdff1aSopenharmony_ci } 427cabdff1aSopenharmony_ci } 428cabdff1aSopenharmony_ci } else { 429cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 430cabdff1aSopenharmony_ci } 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx))) 433cabdff1aSopenharmony_ci return err; 434cabdff1aSopenharmony_ci s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary 435cabdff1aSopenharmony_ci s->planebuf = av_malloc(s->planesize * avctx->height + AV_INPUT_BUFFER_PADDING_SIZE); 436cabdff1aSopenharmony_ci if (!s->planebuf) 437cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 438cabdff1aSopenharmony_ci 439cabdff1aSopenharmony_ci s->bpp = avctx->bits_per_coded_sample; 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 442cabdff1aSopenharmony_ci s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp; 443cabdff1aSopenharmony_ci if (!s->video_size) 444cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 445cabdff1aSopenharmony_ci s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); 446cabdff1aSopenharmony_ci s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); 447cabdff1aSopenharmony_ci s->pal = av_calloc(256, sizeof(*s->pal)); 448cabdff1aSopenharmony_ci if (!s->video[0] || !s->video[1] || !s->pal) 449cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 450cabdff1aSopenharmony_ci } 451cabdff1aSopenharmony_ci 452cabdff1aSopenharmony_ci if ((err = extract_header(avctx, NULL)) < 0) 453cabdff1aSopenharmony_ci return err; 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci return 0; 456cabdff1aSopenharmony_ci} 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci/** 459cabdff1aSopenharmony_ci * Decode interleaved plane buffer up to 8bpp 460cabdff1aSopenharmony_ci * @param dst Destination buffer 461cabdff1aSopenharmony_ci * @param buf Source buffer 462cabdff1aSopenharmony_ci * @param buf_size 463cabdff1aSopenharmony_ci * @param plane plane number to decode as 464cabdff1aSopenharmony_ci */ 465cabdff1aSopenharmony_cistatic void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane) 466cabdff1aSopenharmony_ci{ 467cabdff1aSopenharmony_ci const uint64_t *lut; 468cabdff1aSopenharmony_ci if (plane >= 8) { 469cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n"); 470cabdff1aSopenharmony_ci return; 471cabdff1aSopenharmony_ci } 472cabdff1aSopenharmony_ci lut = plane8_lut[plane]; 473cabdff1aSopenharmony_ci do { 474cabdff1aSopenharmony_ci uint64_t v = AV_RN64A(dst) | lut[*buf++]; 475cabdff1aSopenharmony_ci AV_WN64A(dst, v); 476cabdff1aSopenharmony_ci dst += 8; 477cabdff1aSopenharmony_ci } while (--buf_size); 478cabdff1aSopenharmony_ci} 479cabdff1aSopenharmony_ci 480cabdff1aSopenharmony_ci/** 481cabdff1aSopenharmony_ci * Decode interleaved plane buffer up to 24bpp 482cabdff1aSopenharmony_ci * @param dst Destination buffer 483cabdff1aSopenharmony_ci * @param buf Source buffer 484cabdff1aSopenharmony_ci * @param buf_size 485cabdff1aSopenharmony_ci * @param plane plane number to decode as 486cabdff1aSopenharmony_ci */ 487cabdff1aSopenharmony_cistatic void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane) 488cabdff1aSopenharmony_ci{ 489cabdff1aSopenharmony_ci const uint32_t *lut = plane32_lut[plane]; 490cabdff1aSopenharmony_ci do { 491cabdff1aSopenharmony_ci unsigned mask = (*buf >> 2) & ~3; 492cabdff1aSopenharmony_ci dst[0] |= lut[mask++]; 493cabdff1aSopenharmony_ci dst[1] |= lut[mask++]; 494cabdff1aSopenharmony_ci dst[2] |= lut[mask++]; 495cabdff1aSopenharmony_ci dst[3] |= lut[mask]; 496cabdff1aSopenharmony_ci mask = (*buf++ << 2) & 0x3F; 497cabdff1aSopenharmony_ci dst[4] |= lut[mask++]; 498cabdff1aSopenharmony_ci dst[5] |= lut[mask++]; 499cabdff1aSopenharmony_ci dst[6] |= lut[mask++]; 500cabdff1aSopenharmony_ci dst[7] |= lut[mask]; 501cabdff1aSopenharmony_ci dst += 8; 502cabdff1aSopenharmony_ci } while (--buf_size); 503cabdff1aSopenharmony_ci} 504cabdff1aSopenharmony_ci 505cabdff1aSopenharmony_ci#define DECODE_HAM_PLANE32(x) \ 506cabdff1aSopenharmony_ci first = buf[x] << 1; \ 507cabdff1aSopenharmony_ci second = buf[(x)+1] << 1; \ 508cabdff1aSopenharmony_ci delta &= pal[first++]; \ 509cabdff1aSopenharmony_ci delta |= pal[first]; \ 510cabdff1aSopenharmony_ci dst[x] = delta; \ 511cabdff1aSopenharmony_ci delta &= pal[second++]; \ 512cabdff1aSopenharmony_ci delta |= pal[second]; \ 513cabdff1aSopenharmony_ci dst[(x)+1] = delta 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_ci/** 516cabdff1aSopenharmony_ci * Converts one line of HAM6/8-encoded chunky buffer to 24bpp. 517cabdff1aSopenharmony_ci * 518cabdff1aSopenharmony_ci * @param dst the destination 24bpp buffer 519cabdff1aSopenharmony_ci * @param buf the source 8bpp chunky buffer 520cabdff1aSopenharmony_ci * @param pal the HAM decode table 521cabdff1aSopenharmony_ci * @param buf_size the plane size in bytes 522cabdff1aSopenharmony_ci */ 523cabdff1aSopenharmony_cistatic void decode_ham_plane32(uint32_t *dst, const uint8_t *buf, 524cabdff1aSopenharmony_ci const uint32_t *const pal, unsigned buf_size) 525cabdff1aSopenharmony_ci{ 526cabdff1aSopenharmony_ci uint32_t delta = pal[1]; /* first palette entry */ 527cabdff1aSopenharmony_ci do { 528cabdff1aSopenharmony_ci uint32_t first, second; 529cabdff1aSopenharmony_ci DECODE_HAM_PLANE32(0); 530cabdff1aSopenharmony_ci DECODE_HAM_PLANE32(2); 531cabdff1aSopenharmony_ci DECODE_HAM_PLANE32(4); 532cabdff1aSopenharmony_ci DECODE_HAM_PLANE32(6); 533cabdff1aSopenharmony_ci buf += 8; 534cabdff1aSopenharmony_ci dst += 8; 535cabdff1aSopenharmony_ci } while (--buf_size); 536cabdff1aSopenharmony_ci} 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_cistatic void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf, 539cabdff1aSopenharmony_ci const uint32_t *const pal, unsigned width) 540cabdff1aSopenharmony_ci{ 541cabdff1aSopenharmony_ci do { 542cabdff1aSopenharmony_ci *dst++ = pal[*buf++]; 543cabdff1aSopenharmony_ci } while (--width); 544cabdff1aSopenharmony_ci} 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci/** 547cabdff1aSopenharmony_ci * Decode one complete byterun1 encoded line. 548cabdff1aSopenharmony_ci * 549cabdff1aSopenharmony_ci * @param dst the destination buffer where to store decompressed bitstream 550cabdff1aSopenharmony_ci * @param dst_size the destination plane size in bytes 551cabdff1aSopenharmony_ci * @param buf the source byterun1 compressed bitstream 552cabdff1aSopenharmony_ci * @param buf_end the EOF of source byterun1 compressed bitstream 553cabdff1aSopenharmony_ci * @return number of consumed bytes in byterun1 compressed bitstream 554cabdff1aSopenharmony_ci */ 555cabdff1aSopenharmony_cistatic int decode_byterun(uint8_t *dst, int dst_size, 556cabdff1aSopenharmony_ci GetByteContext *gb) 557cabdff1aSopenharmony_ci{ 558cabdff1aSopenharmony_ci unsigned x; 559cabdff1aSopenharmony_ci for (x = 0; x < dst_size && bytestream2_get_bytes_left(gb) > 0;) { 560cabdff1aSopenharmony_ci unsigned length; 561cabdff1aSopenharmony_ci const int8_t value = bytestream2_get_byte(gb); 562cabdff1aSopenharmony_ci if (value >= 0) { 563cabdff1aSopenharmony_ci length = FFMIN3(value + 1, dst_size - x, bytestream2_get_bytes_left(gb)); 564cabdff1aSopenharmony_ci bytestream2_get_buffer(gb, dst + x, length); 565cabdff1aSopenharmony_ci if (length < value + 1) 566cabdff1aSopenharmony_ci bytestream2_skip(gb, value + 1 - length); 567cabdff1aSopenharmony_ci } else if (value > -128) { 568cabdff1aSopenharmony_ci length = FFMIN(-value + 1, dst_size - x); 569cabdff1aSopenharmony_ci memset(dst + x, bytestream2_get_byte(gb), length); 570cabdff1aSopenharmony_ci } else { // noop 571cabdff1aSopenharmony_ci continue; 572cabdff1aSopenharmony_ci } 573cabdff1aSopenharmony_ci x += length; 574cabdff1aSopenharmony_ci } 575cabdff1aSopenharmony_ci if (x < dst_size) { 576cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "decode_byterun ended before plane size\n"); 577cabdff1aSopenharmony_ci memset(dst+x, 0, dst_size - x); 578cabdff1aSopenharmony_ci } 579cabdff1aSopenharmony_ci return bytestream2_tell(gb); 580cabdff1aSopenharmony_ci} 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_cistatic int decode_byterun2(uint8_t *dst, int height, int line_size, 583cabdff1aSopenharmony_ci GetByteContext *gb) 584cabdff1aSopenharmony_ci{ 585cabdff1aSopenharmony_ci GetByteContext cmds; 586cabdff1aSopenharmony_ci unsigned count; 587cabdff1aSopenharmony_ci int i, y_pos = 0, x_pos = 0; 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_ci if (bytestream2_get_be32(gb) != MKBETAG('V', 'D', 'A', 'T')) 590cabdff1aSopenharmony_ci return 0; 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_ci bytestream2_skip(gb, 4); 593cabdff1aSopenharmony_ci count = bytestream2_get_be16(gb) - 2; 594cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < count) 595cabdff1aSopenharmony_ci return 0; 596cabdff1aSopenharmony_ci 597cabdff1aSopenharmony_ci bytestream2_init(&cmds, gb->buffer, count); 598cabdff1aSopenharmony_ci bytestream2_skip(gb, count); 599cabdff1aSopenharmony_ci 600cabdff1aSopenharmony_ci for (i = 0; i < count && x_pos < line_size; i++) { 601cabdff1aSopenharmony_ci int8_t cmd = bytestream2_get_byte(&cmds); 602cabdff1aSopenharmony_ci int l, r; 603cabdff1aSopenharmony_ci 604cabdff1aSopenharmony_ci if (cmd == 0) { 605cabdff1aSopenharmony_ci l = bytestream2_get_be16(gb); 606cabdff1aSopenharmony_ci while (l-- > 0 && x_pos < line_size) { 607cabdff1aSopenharmony_ci dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb); 608cabdff1aSopenharmony_ci dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb); 609cabdff1aSopenharmony_ci if (y_pos >= height) { 610cabdff1aSopenharmony_ci y_pos = 0; 611cabdff1aSopenharmony_ci x_pos += 2; 612cabdff1aSopenharmony_ci } 613cabdff1aSopenharmony_ci } 614cabdff1aSopenharmony_ci } else if (cmd < 0) { 615cabdff1aSopenharmony_ci l = -cmd; 616cabdff1aSopenharmony_ci while (l-- > 0 && x_pos < line_size) { 617cabdff1aSopenharmony_ci dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb); 618cabdff1aSopenharmony_ci dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb); 619cabdff1aSopenharmony_ci if (y_pos >= height) { 620cabdff1aSopenharmony_ci y_pos = 0; 621cabdff1aSopenharmony_ci x_pos += 2; 622cabdff1aSopenharmony_ci } 623cabdff1aSopenharmony_ci } 624cabdff1aSopenharmony_ci } else if (cmd == 1) { 625cabdff1aSopenharmony_ci l = bytestream2_get_be16(gb); 626cabdff1aSopenharmony_ci r = bytestream2_get_be16(gb); 627cabdff1aSopenharmony_ci while (l-- > 0 && x_pos < line_size) { 628cabdff1aSopenharmony_ci dst[x_pos + y_pos * line_size ] = r >> 8; 629cabdff1aSopenharmony_ci dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF; 630cabdff1aSopenharmony_ci if (y_pos >= height) { 631cabdff1aSopenharmony_ci y_pos = 0; 632cabdff1aSopenharmony_ci x_pos += 2; 633cabdff1aSopenharmony_ci } 634cabdff1aSopenharmony_ci } 635cabdff1aSopenharmony_ci } else { 636cabdff1aSopenharmony_ci l = cmd; 637cabdff1aSopenharmony_ci r = bytestream2_get_be16(gb); 638cabdff1aSopenharmony_ci while (l-- > 0 && x_pos < line_size) { 639cabdff1aSopenharmony_ci dst[x_pos + y_pos * line_size ] = r >> 8; 640cabdff1aSopenharmony_ci dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF; 641cabdff1aSopenharmony_ci if (y_pos >= height) { 642cabdff1aSopenharmony_ci y_pos = 0; 643cabdff1aSopenharmony_ci x_pos += 2; 644cabdff1aSopenharmony_ci } 645cabdff1aSopenharmony_ci } 646cabdff1aSopenharmony_ci } 647cabdff1aSopenharmony_ci } 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_ci return bytestream2_tell(gb); 650cabdff1aSopenharmony_ci} 651cabdff1aSopenharmony_ci 652cabdff1aSopenharmony_ci#define DECODE_RGBX_COMMON(type) \ 653cabdff1aSopenharmony_ci if (!length) { \ 654cabdff1aSopenharmony_ci length = bytestream2_get_byte(gb); \ 655cabdff1aSopenharmony_ci if (!length) { \ 656cabdff1aSopenharmony_ci length = bytestream2_get_be16(gb); \ 657cabdff1aSopenharmony_ci if (!length) \ 658cabdff1aSopenharmony_ci return; \ 659cabdff1aSopenharmony_ci } \ 660cabdff1aSopenharmony_ci } \ 661cabdff1aSopenharmony_ci for (i = 0; i < length; i++) { \ 662cabdff1aSopenharmony_ci *(type *)(dst + y*linesize + x * sizeof(type)) = pixel; \ 663cabdff1aSopenharmony_ci x += 1; \ 664cabdff1aSopenharmony_ci if (x >= width) { \ 665cabdff1aSopenharmony_ci y += 1; \ 666cabdff1aSopenharmony_ci if (y >= height) \ 667cabdff1aSopenharmony_ci return; \ 668cabdff1aSopenharmony_ci x = 0; \ 669cabdff1aSopenharmony_ci } \ 670cabdff1aSopenharmony_ci } 671cabdff1aSopenharmony_ci 672cabdff1aSopenharmony_ci/** 673cabdff1aSopenharmony_ci * Decode RGB8 buffer 674cabdff1aSopenharmony_ci * @param[out] dst Destination buffer 675cabdff1aSopenharmony_ci * @param width Width of destination buffer (pixels) 676cabdff1aSopenharmony_ci * @param height Height of destination buffer (pixels) 677cabdff1aSopenharmony_ci * @param linesize Line size of destination buffer (bytes) 678cabdff1aSopenharmony_ci */ 679cabdff1aSopenharmony_cistatic void decode_rgb8(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) 680cabdff1aSopenharmony_ci{ 681cabdff1aSopenharmony_ci int x = 0, y = 0, i, length; 682cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) >= 4) { 683cabdff1aSopenharmony_ci uint32_t pixel = 0xFF000000 | bytestream2_get_be24(gb); 684cabdff1aSopenharmony_ci length = bytestream2_get_byte(gb) & 0x7F; 685cabdff1aSopenharmony_ci DECODE_RGBX_COMMON(uint32_t) 686cabdff1aSopenharmony_ci } 687cabdff1aSopenharmony_ci} 688cabdff1aSopenharmony_ci 689cabdff1aSopenharmony_ci/** 690cabdff1aSopenharmony_ci * Decode RGBN buffer 691cabdff1aSopenharmony_ci * @param[out] dst Destination buffer 692cabdff1aSopenharmony_ci * @param width Width of destination buffer (pixels) 693cabdff1aSopenharmony_ci * @param height Height of destination buffer (pixels) 694cabdff1aSopenharmony_ci * @param linesize Line size of destination buffer (bytes) 695cabdff1aSopenharmony_ci */ 696cabdff1aSopenharmony_cistatic void decode_rgbn(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) 697cabdff1aSopenharmony_ci{ 698cabdff1aSopenharmony_ci int x = 0, y = 0, i, length; 699cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(gb) >= 2) { 700cabdff1aSopenharmony_ci uint32_t pixel = bytestream2_get_be16u(gb); 701cabdff1aSopenharmony_ci length = pixel & 0x7; 702cabdff1aSopenharmony_ci pixel >>= 4; 703cabdff1aSopenharmony_ci DECODE_RGBX_COMMON(uint16_t) 704cabdff1aSopenharmony_ci } 705cabdff1aSopenharmony_ci} 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci/** 708cabdff1aSopenharmony_ci * Decode DEEP RLE 32-bit buffer 709cabdff1aSopenharmony_ci * @param[out] dst Destination buffer 710cabdff1aSopenharmony_ci * @param[in] src Source buffer 711cabdff1aSopenharmony_ci * @param src_size Source buffer size (bytes) 712cabdff1aSopenharmony_ci * @param width Width of destination buffer (pixels) 713cabdff1aSopenharmony_ci * @param height Height of destination buffer (pixels) 714cabdff1aSopenharmony_ci * @param linesize Line size of destination buffer (bytes) 715cabdff1aSopenharmony_ci */ 716cabdff1aSopenharmony_cistatic void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) 717cabdff1aSopenharmony_ci{ 718cabdff1aSopenharmony_ci const uint8_t *src_end = src + src_size; 719cabdff1aSopenharmony_ci int x = 0, y = 0, i; 720cabdff1aSopenharmony_ci while (src_end - src >= 5) { 721cabdff1aSopenharmony_ci int opcode; 722cabdff1aSopenharmony_ci opcode = *(int8_t *)src++; 723cabdff1aSopenharmony_ci if (opcode >= 0) { 724cabdff1aSopenharmony_ci int size = opcode + 1; 725cabdff1aSopenharmony_ci for (i = 0; i < size; i++) { 726cabdff1aSopenharmony_ci int length = FFMIN(size - i, width - x); 727cabdff1aSopenharmony_ci if (src_end - src < length * 4) 728cabdff1aSopenharmony_ci return; 729cabdff1aSopenharmony_ci memcpy(dst + y*linesize + x * 4, src, length * 4); 730cabdff1aSopenharmony_ci src += length * 4; 731cabdff1aSopenharmony_ci x += length; 732cabdff1aSopenharmony_ci i += length; 733cabdff1aSopenharmony_ci if (x >= width) { 734cabdff1aSopenharmony_ci x = 0; 735cabdff1aSopenharmony_ci y += 1; 736cabdff1aSopenharmony_ci if (y >= height) 737cabdff1aSopenharmony_ci return; 738cabdff1aSopenharmony_ci } 739cabdff1aSopenharmony_ci } 740cabdff1aSopenharmony_ci } else { 741cabdff1aSopenharmony_ci int size = -opcode + 1; 742cabdff1aSopenharmony_ci uint32_t pixel = AV_RN32(src); 743cabdff1aSopenharmony_ci for (i = 0; i < size; i++) { 744cabdff1aSopenharmony_ci *(uint32_t *)(dst + y*linesize + x * 4) = pixel; 745cabdff1aSopenharmony_ci x += 1; 746cabdff1aSopenharmony_ci if (x >= width) { 747cabdff1aSopenharmony_ci x = 0; 748cabdff1aSopenharmony_ci y += 1; 749cabdff1aSopenharmony_ci if (y >= height) 750cabdff1aSopenharmony_ci return; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci } 753cabdff1aSopenharmony_ci src += 4; 754cabdff1aSopenharmony_ci } 755cabdff1aSopenharmony_ci } 756cabdff1aSopenharmony_ci} 757cabdff1aSopenharmony_ci 758cabdff1aSopenharmony_ci/** 759cabdff1aSopenharmony_ci * Decode DEEP TVDC 32-bit buffer 760cabdff1aSopenharmony_ci * @param[out] dst Destination buffer 761cabdff1aSopenharmony_ci * @param[in] src Source buffer 762cabdff1aSopenharmony_ci * @param src_size Source buffer size (bytes) 763cabdff1aSopenharmony_ci * @param width Width of destination buffer (pixels) 764cabdff1aSopenharmony_ci * @param height Height of destination buffer (pixels) 765cabdff1aSopenharmony_ci * @param linesize Line size of destination buffer (bytes) 766cabdff1aSopenharmony_ci * @param[int] tvdc TVDC lookup table 767cabdff1aSopenharmony_ci */ 768cabdff1aSopenharmony_cistatic void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize, const int16_t *tvdc) 769cabdff1aSopenharmony_ci{ 770cabdff1aSopenharmony_ci int x = 0, y = 0, plane = 0; 771cabdff1aSopenharmony_ci int8_t pixel = 0; 772cabdff1aSopenharmony_ci int i, j; 773cabdff1aSopenharmony_ci 774cabdff1aSopenharmony_ci for (i = 0; i < src_size * 2;) { 775cabdff1aSopenharmony_ci#define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4)) 776cabdff1aSopenharmony_ci int d = tvdc[GETNIBBLE]; 777cabdff1aSopenharmony_ci i++; 778cabdff1aSopenharmony_ci if (d) { 779cabdff1aSopenharmony_ci pixel += d; 780cabdff1aSopenharmony_ci dst[y * linesize + x*4 + plane] = pixel; 781cabdff1aSopenharmony_ci x++; 782cabdff1aSopenharmony_ci } else { 783cabdff1aSopenharmony_ci if (i >= src_size * 2) 784cabdff1aSopenharmony_ci return; 785cabdff1aSopenharmony_ci d = GETNIBBLE + 1; 786cabdff1aSopenharmony_ci i++; 787cabdff1aSopenharmony_ci d = FFMIN(d, width - x); 788cabdff1aSopenharmony_ci for (j = 0; j < d; j++) { 789cabdff1aSopenharmony_ci dst[y * linesize + x*4 + plane] = pixel; 790cabdff1aSopenharmony_ci x++; 791cabdff1aSopenharmony_ci } 792cabdff1aSopenharmony_ci } 793cabdff1aSopenharmony_ci if (x >= width) { 794cabdff1aSopenharmony_ci plane++; 795cabdff1aSopenharmony_ci if (plane >= 4) { 796cabdff1aSopenharmony_ci y++; 797cabdff1aSopenharmony_ci if (y >= height) 798cabdff1aSopenharmony_ci return; 799cabdff1aSopenharmony_ci plane = 0; 800cabdff1aSopenharmony_ci } 801cabdff1aSopenharmony_ci x = 0; 802cabdff1aSopenharmony_ci pixel = 0; 803cabdff1aSopenharmony_ci i = (i + 1) & ~1; 804cabdff1aSopenharmony_ci } 805cabdff1aSopenharmony_ci } 806cabdff1aSopenharmony_ci} 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_cistatic void decode_short_horizontal_delta(uint8_t *dst, 809cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 810cabdff1aSopenharmony_ci int w, int bpp, int dst_size) 811cabdff1aSopenharmony_ci{ 812cabdff1aSopenharmony_ci int planepitch = FFALIGN(w, 16) >> 3; 813cabdff1aSopenharmony_ci int pitch = planepitch * bpp; 814cabdff1aSopenharmony_ci GetByteContext ptrs, gb; 815cabdff1aSopenharmony_ci PutByteContext pb; 816cabdff1aSopenharmony_ci unsigned ofssrc, pos; 817cabdff1aSopenharmony_ci int i, k; 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 820cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 821cabdff1aSopenharmony_ci 822cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 823cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 824cabdff1aSopenharmony_ci pos = 0; 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci if (!ofssrc) 827cabdff1aSopenharmony_ci continue; 828cabdff1aSopenharmony_ci 829cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 830cabdff1aSopenharmony_ci continue; 831cabdff1aSopenharmony_ci 832cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 833cabdff1aSopenharmony_ci while (bytestream2_peek_be16(&gb) != 0xFFFF && bytestream2_get_bytes_left(&gb) > 3) { 834cabdff1aSopenharmony_ci int16_t offset = bytestream2_get_be16(&gb); 835cabdff1aSopenharmony_ci unsigned noffset; 836cabdff1aSopenharmony_ci 837cabdff1aSopenharmony_ci if (offset >= 0) { 838cabdff1aSopenharmony_ci unsigned data = bytestream2_get_be16(&gb); 839cabdff1aSopenharmony_ci 840cabdff1aSopenharmony_ci pos += offset * 2; 841cabdff1aSopenharmony_ci noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch; 842cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, noffset, SEEK_SET); 843cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, data); 844cabdff1aSopenharmony_ci } else { 845cabdff1aSopenharmony_ci uint16_t count = bytestream2_get_be16(&gb); 846cabdff1aSopenharmony_ci 847cabdff1aSopenharmony_ci pos += 2 * -(offset + 2); 848cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 849cabdff1aSopenharmony_ci uint16_t data = bytestream2_get_be16(&gb); 850cabdff1aSopenharmony_ci 851cabdff1aSopenharmony_ci pos += 2; 852cabdff1aSopenharmony_ci noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch; 853cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, noffset, SEEK_SET); 854cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, data); 855cabdff1aSopenharmony_ci } 856cabdff1aSopenharmony_ci } 857cabdff1aSopenharmony_ci } 858cabdff1aSopenharmony_ci } 859cabdff1aSopenharmony_ci} 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_cistatic void decode_byte_vertical_delta(uint8_t *dst, 862cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 863cabdff1aSopenharmony_ci int w, int xor, int bpp, int dst_size) 864cabdff1aSopenharmony_ci{ 865cabdff1aSopenharmony_ci int ncolumns = ((w + 15) / 16) * 2; 866cabdff1aSopenharmony_ci int dstpitch = ncolumns * bpp; 867cabdff1aSopenharmony_ci unsigned ofsdst, ofssrc, opcode, x; 868cabdff1aSopenharmony_ci GetByteContext ptrs, gb; 869cabdff1aSopenharmony_ci PutByteContext pb; 870cabdff1aSopenharmony_ci int i, j, k; 871cabdff1aSopenharmony_ci 872cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 873cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 874cabdff1aSopenharmony_ci 875cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 876cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 877cabdff1aSopenharmony_ci 878cabdff1aSopenharmony_ci if (!ofssrc) 879cabdff1aSopenharmony_ci continue; 880cabdff1aSopenharmony_ci 881cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 882cabdff1aSopenharmony_ci continue; 883cabdff1aSopenharmony_ci 884cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 885cabdff1aSopenharmony_ci for (j = 0; j < ncolumns; j++) { 886cabdff1aSopenharmony_ci ofsdst = j + k * ncolumns; 887cabdff1aSopenharmony_ci 888cabdff1aSopenharmony_ci i = bytestream2_get_byte(&gb); 889cabdff1aSopenharmony_ci while (i > 0) { 890cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 891cabdff1aSopenharmony_ci 892cabdff1aSopenharmony_ci if (opcode == 0) { 893cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 894cabdff1aSopenharmony_ci x = bytestream2_get_byte(&gb); 895cabdff1aSopenharmony_ci 896cabdff1aSopenharmony_ci while (opcode) { 897cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 898cabdff1aSopenharmony_ci if (xor && ofsdst < dst_size) { 899cabdff1aSopenharmony_ci bytestream2_put_byte(&pb, dst[ofsdst] ^ x); 900cabdff1aSopenharmony_ci } else { 901cabdff1aSopenharmony_ci bytestream2_put_byte(&pb, x); 902cabdff1aSopenharmony_ci } 903cabdff1aSopenharmony_ci ofsdst += dstpitch; 904cabdff1aSopenharmony_ci opcode--; 905cabdff1aSopenharmony_ci } 906cabdff1aSopenharmony_ci } else if (opcode < 0x80) { 907cabdff1aSopenharmony_ci ofsdst += opcode * dstpitch; 908cabdff1aSopenharmony_ci } else { 909cabdff1aSopenharmony_ci opcode &= 0x7f; 910cabdff1aSopenharmony_ci 911cabdff1aSopenharmony_ci while (opcode) { 912cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 913cabdff1aSopenharmony_ci if (xor && ofsdst < dst_size) { 914cabdff1aSopenharmony_ci bytestream2_put_byte(&pb, dst[ofsdst] ^ bytestream2_get_byte(&gb)); 915cabdff1aSopenharmony_ci } else { 916cabdff1aSopenharmony_ci bytestream2_put_byte(&pb, bytestream2_get_byte(&gb)); 917cabdff1aSopenharmony_ci } 918cabdff1aSopenharmony_ci ofsdst += dstpitch; 919cabdff1aSopenharmony_ci opcode--; 920cabdff1aSopenharmony_ci } 921cabdff1aSopenharmony_ci } 922cabdff1aSopenharmony_ci i--; 923cabdff1aSopenharmony_ci } 924cabdff1aSopenharmony_ci } 925cabdff1aSopenharmony_ci } 926cabdff1aSopenharmony_ci} 927cabdff1aSopenharmony_ci 928cabdff1aSopenharmony_cistatic void decode_delta_j(uint8_t *dst, 929cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 930cabdff1aSopenharmony_ci int w, int h, int bpp, int dst_size) 931cabdff1aSopenharmony_ci{ 932cabdff1aSopenharmony_ci int32_t pitch; 933cabdff1aSopenharmony_ci uint8_t *ptr; 934cabdff1aSopenharmony_ci uint32_t type, flag, cols, groups, rows, bytes; 935cabdff1aSopenharmony_ci uint32_t offset; 936cabdff1aSopenharmony_ci int planepitch_byte = (w + 7) / 8; 937cabdff1aSopenharmony_ci int planepitch = ((w + 15) / 16) * 2; 938cabdff1aSopenharmony_ci int kludge_j, b, g, r, d; 939cabdff1aSopenharmony_ci GetByteContext gb; 940cabdff1aSopenharmony_ci 941cabdff1aSopenharmony_ci pitch = planepitch * bpp; 942cabdff1aSopenharmony_ci kludge_j = w < 320 ? (320 - w) / 8 / 2 : 0; 943cabdff1aSopenharmony_ci 944cabdff1aSopenharmony_ci bytestream2_init(&gb, buf, buf_end - buf); 945cabdff1aSopenharmony_ci 946cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(&gb) >= 2) { 947cabdff1aSopenharmony_ci type = bytestream2_get_be16(&gb); 948cabdff1aSopenharmony_ci 949cabdff1aSopenharmony_ci switch (type) { 950cabdff1aSopenharmony_ci case 0: 951cabdff1aSopenharmony_ci return; 952cabdff1aSopenharmony_ci case 1: 953cabdff1aSopenharmony_ci flag = bytestream2_get_be16(&gb); 954cabdff1aSopenharmony_ci cols = bytestream2_get_be16(&gb); 955cabdff1aSopenharmony_ci groups = bytestream2_get_be16(&gb); 956cabdff1aSopenharmony_ci 957cabdff1aSopenharmony_ci for (g = 0; g < groups; g++) { 958cabdff1aSopenharmony_ci offset = bytestream2_get_be16(&gb); 959cabdff1aSopenharmony_ci 960cabdff1aSopenharmony_ci if (cols * bpp == 0 || bytestream2_get_bytes_left(&gb) < cols * bpp) { 961cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "cols*bpp is invalid (%"PRId32"*%d)", cols, bpp); 962cabdff1aSopenharmony_ci return; 963cabdff1aSopenharmony_ci } 964cabdff1aSopenharmony_ci 965cabdff1aSopenharmony_ci if (kludge_j) 966cabdff1aSopenharmony_ci offset = ((offset / (320 / 8)) * pitch) + (offset % (320 / 8)) - kludge_j; 967cabdff1aSopenharmony_ci else 968cabdff1aSopenharmony_ci offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte); 969cabdff1aSopenharmony_ci 970cabdff1aSopenharmony_ci for (b = 0; b < cols; b++) { 971cabdff1aSopenharmony_ci for (d = 0; d < bpp; d++) { 972cabdff1aSopenharmony_ci uint8_t value = bytestream2_get_byte(&gb); 973cabdff1aSopenharmony_ci 974cabdff1aSopenharmony_ci if (offset >= dst_size) 975cabdff1aSopenharmony_ci return; 976cabdff1aSopenharmony_ci ptr = dst + offset; 977cabdff1aSopenharmony_ci 978cabdff1aSopenharmony_ci if (flag) 979cabdff1aSopenharmony_ci ptr[0] ^= value; 980cabdff1aSopenharmony_ci else 981cabdff1aSopenharmony_ci ptr[0] = value; 982cabdff1aSopenharmony_ci 983cabdff1aSopenharmony_ci offset += planepitch; 984cabdff1aSopenharmony_ci } 985cabdff1aSopenharmony_ci } 986cabdff1aSopenharmony_ci if ((cols * bpp) & 1) 987cabdff1aSopenharmony_ci bytestream2_skip(&gb, 1); 988cabdff1aSopenharmony_ci } 989cabdff1aSopenharmony_ci break; 990cabdff1aSopenharmony_ci case 2: 991cabdff1aSopenharmony_ci flag = bytestream2_get_be16(&gb); 992cabdff1aSopenharmony_ci rows = bytestream2_get_be16(&gb); 993cabdff1aSopenharmony_ci bytes = bytestream2_get_be16(&gb); 994cabdff1aSopenharmony_ci groups = bytestream2_get_be16(&gb); 995cabdff1aSopenharmony_ci 996cabdff1aSopenharmony_ci for (g = 0; g < groups; g++) { 997cabdff1aSopenharmony_ci offset = bytestream2_get_be16(&gb); 998cabdff1aSopenharmony_ci 999cabdff1aSopenharmony_ci if (kludge_j) 1000cabdff1aSopenharmony_ci offset = ((offset / (320 / 8)) * pitch) + (offset % (320/ 8)) - kludge_j; 1001cabdff1aSopenharmony_ci else 1002cabdff1aSopenharmony_ci offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte); 1003cabdff1aSopenharmony_ci 1004cabdff1aSopenharmony_ci for (r = 0; r < rows; r++) { 1005cabdff1aSopenharmony_ci for (d = 0; d < bpp; d++) { 1006cabdff1aSopenharmony_ci unsigned noffset = offset + (r * pitch) + d * planepitch; 1007cabdff1aSopenharmony_ci 1008cabdff1aSopenharmony_ci if (!bytes || bytestream2_get_bytes_left(&gb) < bytes) { 1009cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "bytes %"PRId32" is invalid", bytes); 1010cabdff1aSopenharmony_ci return; 1011cabdff1aSopenharmony_ci } 1012cabdff1aSopenharmony_ci 1013cabdff1aSopenharmony_ci for (b = 0; b < bytes; b++) { 1014cabdff1aSopenharmony_ci uint8_t value = bytestream2_get_byte(&gb); 1015cabdff1aSopenharmony_ci 1016cabdff1aSopenharmony_ci if (noffset >= dst_size) 1017cabdff1aSopenharmony_ci return; 1018cabdff1aSopenharmony_ci ptr = dst + noffset; 1019cabdff1aSopenharmony_ci 1020cabdff1aSopenharmony_ci if (flag) 1021cabdff1aSopenharmony_ci ptr[0] ^= value; 1022cabdff1aSopenharmony_ci else 1023cabdff1aSopenharmony_ci ptr[0] = value; 1024cabdff1aSopenharmony_ci 1025cabdff1aSopenharmony_ci noffset++; 1026cabdff1aSopenharmony_ci } 1027cabdff1aSopenharmony_ci } 1028cabdff1aSopenharmony_ci } 1029cabdff1aSopenharmony_ci if ((rows * bytes * bpp) & 1) 1030cabdff1aSopenharmony_ci bytestream2_skip(&gb, 1); 1031cabdff1aSopenharmony_ci } 1032cabdff1aSopenharmony_ci break; 1033cabdff1aSopenharmony_ci default: 1034cabdff1aSopenharmony_ci return; 1035cabdff1aSopenharmony_ci } 1036cabdff1aSopenharmony_ci } 1037cabdff1aSopenharmony_ci} 1038cabdff1aSopenharmony_ci 1039cabdff1aSopenharmony_cistatic void decode_short_vertical_delta(uint8_t *dst, 1040cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1041cabdff1aSopenharmony_ci int w, int bpp, int dst_size) 1042cabdff1aSopenharmony_ci{ 1043cabdff1aSopenharmony_ci int ncolumns = (w + 15) >> 4; 1044cabdff1aSopenharmony_ci int dstpitch = ncolumns * bpp * 2; 1045cabdff1aSopenharmony_ci unsigned ofsdst, ofssrc, ofsdata, opcode, x; 1046cabdff1aSopenharmony_ci GetByteContext ptrs, gb, dptrs, dgb; 1047cabdff1aSopenharmony_ci PutByteContext pb; 1048cabdff1aSopenharmony_ci int i, j, k; 1049cabdff1aSopenharmony_ci 1050cabdff1aSopenharmony_ci if (buf_end - buf <= 64) 1051cabdff1aSopenharmony_ci return; 1052cabdff1aSopenharmony_ci 1053cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 1054cabdff1aSopenharmony_ci bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32); 1055cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1056cabdff1aSopenharmony_ci 1057cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1058cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1059cabdff1aSopenharmony_ci ofsdata = bytestream2_get_be32(&dptrs); 1060cabdff1aSopenharmony_ci 1061cabdff1aSopenharmony_ci if (!ofssrc) 1062cabdff1aSopenharmony_ci continue; 1063cabdff1aSopenharmony_ci 1064cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1065cabdff1aSopenharmony_ci return; 1066cabdff1aSopenharmony_ci 1067cabdff1aSopenharmony_ci if (ofsdata >= buf_end - buf) 1068cabdff1aSopenharmony_ci return; 1069cabdff1aSopenharmony_ci 1070cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1071cabdff1aSopenharmony_ci bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata)); 1072cabdff1aSopenharmony_ci for (j = 0; j < ncolumns; j++) { 1073cabdff1aSopenharmony_ci ofsdst = (j + k * ncolumns) * 2; 1074cabdff1aSopenharmony_ci 1075cabdff1aSopenharmony_ci i = bytestream2_get_byte(&gb); 1076cabdff1aSopenharmony_ci while (i > 0) { 1077cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 1078cabdff1aSopenharmony_ci 1079cabdff1aSopenharmony_ci if (opcode == 0) { 1080cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 1081cabdff1aSopenharmony_ci x = bytestream2_get_be16(&dgb); 1082cabdff1aSopenharmony_ci 1083cabdff1aSopenharmony_ci while (opcode) { 1084cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1085cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, x); 1086cabdff1aSopenharmony_ci ofsdst += dstpitch; 1087cabdff1aSopenharmony_ci opcode--; 1088cabdff1aSopenharmony_ci } 1089cabdff1aSopenharmony_ci } else if (opcode < 0x80) { 1090cabdff1aSopenharmony_ci ofsdst += opcode * dstpitch; 1091cabdff1aSopenharmony_ci } else { 1092cabdff1aSopenharmony_ci opcode &= 0x7f; 1093cabdff1aSopenharmony_ci 1094cabdff1aSopenharmony_ci while (opcode) { 1095cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1096cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb)); 1097cabdff1aSopenharmony_ci ofsdst += dstpitch; 1098cabdff1aSopenharmony_ci opcode--; 1099cabdff1aSopenharmony_ci } 1100cabdff1aSopenharmony_ci } 1101cabdff1aSopenharmony_ci i--; 1102cabdff1aSopenharmony_ci } 1103cabdff1aSopenharmony_ci } 1104cabdff1aSopenharmony_ci } 1105cabdff1aSopenharmony_ci} 1106cabdff1aSopenharmony_ci 1107cabdff1aSopenharmony_cistatic void decode_long_vertical_delta(uint8_t *dst, 1108cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1109cabdff1aSopenharmony_ci int w, int bpp, int dst_size) 1110cabdff1aSopenharmony_ci{ 1111cabdff1aSopenharmony_ci int ncolumns = (w + 31) >> 5; 1112cabdff1aSopenharmony_ci int dstpitch = ((w + 15) / 16 * 2) * bpp; 1113cabdff1aSopenharmony_ci unsigned ofsdst, ofssrc, ofsdata, opcode, x; 1114cabdff1aSopenharmony_ci GetByteContext ptrs, gb, dptrs, dgb; 1115cabdff1aSopenharmony_ci PutByteContext pb; 1116cabdff1aSopenharmony_ci int i, j, k, h; 1117cabdff1aSopenharmony_ci 1118cabdff1aSopenharmony_ci if (buf_end - buf <= 64) 1119cabdff1aSopenharmony_ci return; 1120cabdff1aSopenharmony_ci 1121cabdff1aSopenharmony_ci h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0; 1122cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 1123cabdff1aSopenharmony_ci bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32); 1124cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1125cabdff1aSopenharmony_ci 1126cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1127cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1128cabdff1aSopenharmony_ci ofsdata = bytestream2_get_be32(&dptrs); 1129cabdff1aSopenharmony_ci 1130cabdff1aSopenharmony_ci if (!ofssrc) 1131cabdff1aSopenharmony_ci continue; 1132cabdff1aSopenharmony_ci 1133cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1134cabdff1aSopenharmony_ci return; 1135cabdff1aSopenharmony_ci 1136cabdff1aSopenharmony_ci if (ofsdata >= buf_end - buf) 1137cabdff1aSopenharmony_ci return; 1138cabdff1aSopenharmony_ci 1139cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1140cabdff1aSopenharmony_ci bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata)); 1141cabdff1aSopenharmony_ci for (j = 0; j < ncolumns; j++) { 1142cabdff1aSopenharmony_ci ofsdst = (j + k * ncolumns) * 4 - h * (2 * k); 1143cabdff1aSopenharmony_ci 1144cabdff1aSopenharmony_ci i = bytestream2_get_byte(&gb); 1145cabdff1aSopenharmony_ci while (i > 0) { 1146cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 1147cabdff1aSopenharmony_ci 1148cabdff1aSopenharmony_ci if (opcode == 0) { 1149cabdff1aSopenharmony_ci opcode = bytestream2_get_byte(&gb); 1150cabdff1aSopenharmony_ci if (h && (j == (ncolumns - 1))) { 1151cabdff1aSopenharmony_ci x = bytestream2_get_be16(&dgb); 1152cabdff1aSopenharmony_ci bytestream2_skip(&dgb, 2); 1153cabdff1aSopenharmony_ci } else { 1154cabdff1aSopenharmony_ci x = bytestream2_get_be32(&dgb); 1155cabdff1aSopenharmony_ci } 1156cabdff1aSopenharmony_ci 1157cabdff1aSopenharmony_ci if (ofsdst + (opcode - 1LL) * dstpitch > bytestream2_size_p(&pb)) 1158cabdff1aSopenharmony_ci return; 1159cabdff1aSopenharmony_ci 1160cabdff1aSopenharmony_ci while (opcode) { 1161cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1162cabdff1aSopenharmony_ci if (h && (j == (ncolumns - 1))) { 1163cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, x); 1164cabdff1aSopenharmony_ci } else { 1165cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, x); 1166cabdff1aSopenharmony_ci } 1167cabdff1aSopenharmony_ci ofsdst += dstpitch; 1168cabdff1aSopenharmony_ci opcode--; 1169cabdff1aSopenharmony_ci } 1170cabdff1aSopenharmony_ci } else if (opcode < 0x80) { 1171cabdff1aSopenharmony_ci ofsdst += opcode * dstpitch; 1172cabdff1aSopenharmony_ci } else { 1173cabdff1aSopenharmony_ci opcode &= 0x7f; 1174cabdff1aSopenharmony_ci 1175cabdff1aSopenharmony_ci while (opcode) { 1176cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1177cabdff1aSopenharmony_ci if (h && (j == (ncolumns - 1))) { 1178cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb)); 1179cabdff1aSopenharmony_ci bytestream2_skip(&dgb, 2); 1180cabdff1aSopenharmony_ci } else { 1181cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, bytestream2_get_be32(&dgb)); 1182cabdff1aSopenharmony_ci } 1183cabdff1aSopenharmony_ci ofsdst += dstpitch; 1184cabdff1aSopenharmony_ci opcode--; 1185cabdff1aSopenharmony_ci } 1186cabdff1aSopenharmony_ci } 1187cabdff1aSopenharmony_ci i--; 1188cabdff1aSopenharmony_ci } 1189cabdff1aSopenharmony_ci } 1190cabdff1aSopenharmony_ci } 1191cabdff1aSopenharmony_ci} 1192cabdff1aSopenharmony_ci 1193cabdff1aSopenharmony_cistatic void decode_short_vertical_delta2(uint8_t *dst, 1194cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1195cabdff1aSopenharmony_ci int w, int bpp, int dst_size) 1196cabdff1aSopenharmony_ci{ 1197cabdff1aSopenharmony_ci int ncolumns = (w + 15) >> 4; 1198cabdff1aSopenharmony_ci int dstpitch = ncolumns * bpp * 2; 1199cabdff1aSopenharmony_ci unsigned ofsdst, ofssrc, opcode, x; 1200cabdff1aSopenharmony_ci GetByteContext ptrs, gb; 1201cabdff1aSopenharmony_ci PutByteContext pb; 1202cabdff1aSopenharmony_ci int i, j, k; 1203cabdff1aSopenharmony_ci 1204cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 1205cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1206cabdff1aSopenharmony_ci 1207cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1208cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1209cabdff1aSopenharmony_ci 1210cabdff1aSopenharmony_ci if (!ofssrc) 1211cabdff1aSopenharmony_ci continue; 1212cabdff1aSopenharmony_ci 1213cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1214cabdff1aSopenharmony_ci continue; 1215cabdff1aSopenharmony_ci 1216cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1217cabdff1aSopenharmony_ci for (j = 0; j < ncolumns; j++) { 1218cabdff1aSopenharmony_ci ofsdst = (j + k * ncolumns) * 2; 1219cabdff1aSopenharmony_ci 1220cabdff1aSopenharmony_ci i = bytestream2_get_be16(&gb); 1221cabdff1aSopenharmony_ci while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) { 1222cabdff1aSopenharmony_ci opcode = bytestream2_get_be16(&gb); 1223cabdff1aSopenharmony_ci 1224cabdff1aSopenharmony_ci if (opcode == 0) { 1225cabdff1aSopenharmony_ci opcode = bytestream2_get_be16(&gb); 1226cabdff1aSopenharmony_ci x = bytestream2_get_be16(&gb); 1227cabdff1aSopenharmony_ci 1228cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) { 1229cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1230cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, x); 1231cabdff1aSopenharmony_ci ofsdst += dstpitch; 1232cabdff1aSopenharmony_ci opcode--; 1233cabdff1aSopenharmony_ci } 1234cabdff1aSopenharmony_ci } else if (opcode < 0x8000) { 1235cabdff1aSopenharmony_ci ofsdst += opcode * dstpitch; 1236cabdff1aSopenharmony_ci } else { 1237cabdff1aSopenharmony_ci opcode &= 0x7fff; 1238cabdff1aSopenharmony_ci 1239cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left(&gb) > 1 && 1240cabdff1aSopenharmony_ci bytestream2_get_bytes_left_p(&pb) > 1) { 1241cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1242cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, bytestream2_get_be16(&gb)); 1243cabdff1aSopenharmony_ci ofsdst += dstpitch; 1244cabdff1aSopenharmony_ci opcode--; 1245cabdff1aSopenharmony_ci } 1246cabdff1aSopenharmony_ci } 1247cabdff1aSopenharmony_ci i--; 1248cabdff1aSopenharmony_ci } 1249cabdff1aSopenharmony_ci } 1250cabdff1aSopenharmony_ci } 1251cabdff1aSopenharmony_ci} 1252cabdff1aSopenharmony_ci 1253cabdff1aSopenharmony_cistatic void decode_long_vertical_delta2(uint8_t *dst, 1254cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1255cabdff1aSopenharmony_ci int w, int bpp, int dst_size) 1256cabdff1aSopenharmony_ci{ 1257cabdff1aSopenharmony_ci int ncolumns = (w + 31) >> 5; 1258cabdff1aSopenharmony_ci int dstpitch = ((w + 15) / 16 * 2) * bpp; 1259cabdff1aSopenharmony_ci unsigned ofsdst, ofssrc, opcode, x; 1260cabdff1aSopenharmony_ci unsigned skip = 0x80000000, mask = skip - 1; 1261cabdff1aSopenharmony_ci GetByteContext ptrs, gb; 1262cabdff1aSopenharmony_ci PutByteContext pb; 1263cabdff1aSopenharmony_ci int i, j, k, h; 1264cabdff1aSopenharmony_ci 1265cabdff1aSopenharmony_ci h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0; 1266cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, buf_end - buf); 1267cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1268cabdff1aSopenharmony_ci 1269cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1270cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1271cabdff1aSopenharmony_ci 1272cabdff1aSopenharmony_ci if (!ofssrc) 1273cabdff1aSopenharmony_ci continue; 1274cabdff1aSopenharmony_ci 1275cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1276cabdff1aSopenharmony_ci continue; 1277cabdff1aSopenharmony_ci 1278cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1279cabdff1aSopenharmony_ci for (j = 0; j < ncolumns; j++) { 1280cabdff1aSopenharmony_ci ofsdst = (j + k * ncolumns) * 4 - h * (2 * k); 1281cabdff1aSopenharmony_ci 1282cabdff1aSopenharmony_ci if (h && (j == (ncolumns - 1))) { 1283cabdff1aSopenharmony_ci skip = 0x8000; 1284cabdff1aSopenharmony_ci mask = skip - 1; 1285cabdff1aSopenharmony_ci } 1286cabdff1aSopenharmony_ci 1287cabdff1aSopenharmony_ci i = bytestream2_get_be32(&gb); 1288cabdff1aSopenharmony_ci while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) { 1289cabdff1aSopenharmony_ci opcode = bytestream2_get_be32(&gb); 1290cabdff1aSopenharmony_ci 1291cabdff1aSopenharmony_ci if (opcode == 0) { 1292cabdff1aSopenharmony_ci if (h && (j == ncolumns - 1)) { 1293cabdff1aSopenharmony_ci opcode = bytestream2_get_be16(&gb); 1294cabdff1aSopenharmony_ci x = bytestream2_get_be16(&gb); 1295cabdff1aSopenharmony_ci } else { 1296cabdff1aSopenharmony_ci opcode = bytestream2_get_be32(&gb); 1297cabdff1aSopenharmony_ci x = bytestream2_get_be32(&gb); 1298cabdff1aSopenharmony_ci } 1299cabdff1aSopenharmony_ci 1300cabdff1aSopenharmony_ci if (ofsdst + (opcode - 1LL) * dstpitch > bytestream2_size_p(&pb)) 1301cabdff1aSopenharmony_ci return; 1302cabdff1aSopenharmony_ci 1303cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) { 1304cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1305cabdff1aSopenharmony_ci if (h && (j == ncolumns - 1)) 1306cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, x); 1307cabdff1aSopenharmony_ci else 1308cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, x); 1309cabdff1aSopenharmony_ci ofsdst += dstpitch; 1310cabdff1aSopenharmony_ci opcode--; 1311cabdff1aSopenharmony_ci } 1312cabdff1aSopenharmony_ci } else if (opcode < skip) { 1313cabdff1aSopenharmony_ci ofsdst += opcode * dstpitch; 1314cabdff1aSopenharmony_ci } else { 1315cabdff1aSopenharmony_ci opcode &= mask; 1316cabdff1aSopenharmony_ci 1317cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left(&gb) > 1 && 1318cabdff1aSopenharmony_ci bytestream2_get_bytes_left_p(&pb) > 1) { 1319cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, ofsdst, SEEK_SET); 1320cabdff1aSopenharmony_ci if (h && (j == ncolumns - 1)) { 1321cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, bytestream2_get_be16(&gb)); 1322cabdff1aSopenharmony_ci } else { 1323cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, bytestream2_get_be32(&gb)); 1324cabdff1aSopenharmony_ci } 1325cabdff1aSopenharmony_ci ofsdst += dstpitch; 1326cabdff1aSopenharmony_ci opcode--; 1327cabdff1aSopenharmony_ci } 1328cabdff1aSopenharmony_ci } 1329cabdff1aSopenharmony_ci i--; 1330cabdff1aSopenharmony_ci } 1331cabdff1aSopenharmony_ci } 1332cabdff1aSopenharmony_ci } 1333cabdff1aSopenharmony_ci} 1334cabdff1aSopenharmony_ci 1335cabdff1aSopenharmony_cistatic void decode_delta_d(uint8_t *dst, 1336cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1337cabdff1aSopenharmony_ci int w, int flag, int bpp, int dst_size) 1338cabdff1aSopenharmony_ci{ 1339cabdff1aSopenharmony_ci int planepitch = FFALIGN(w, 16) >> 3; 1340cabdff1aSopenharmony_ci int pitch = planepitch * bpp; 1341cabdff1aSopenharmony_ci int planepitch_byte = (w + 7) / 8; 1342cabdff1aSopenharmony_ci unsigned entries, ofssrc; 1343cabdff1aSopenharmony_ci GetByteContext gb, ptrs; 1344cabdff1aSopenharmony_ci PutByteContext pb; 1345cabdff1aSopenharmony_ci int k; 1346cabdff1aSopenharmony_ci 1347cabdff1aSopenharmony_ci if (buf_end - buf <= 4 * bpp) 1348cabdff1aSopenharmony_ci return; 1349cabdff1aSopenharmony_ci 1350cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1351cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, bpp * 4); 1352cabdff1aSopenharmony_ci 1353cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1354cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1355cabdff1aSopenharmony_ci 1356cabdff1aSopenharmony_ci if (!ofssrc) 1357cabdff1aSopenharmony_ci continue; 1358cabdff1aSopenharmony_ci 1359cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1360cabdff1aSopenharmony_ci continue; 1361cabdff1aSopenharmony_ci 1362cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1363cabdff1aSopenharmony_ci 1364cabdff1aSopenharmony_ci entries = bytestream2_get_be32(&gb); 1365cabdff1aSopenharmony_ci if (entries * 8LL > bytestream2_get_bytes_left(&gb)) 1366cabdff1aSopenharmony_ci return; 1367cabdff1aSopenharmony_ci 1368cabdff1aSopenharmony_ci while (entries && bytestream2_get_bytes_left(&gb) >= 8) { 1369cabdff1aSopenharmony_ci int32_t opcode = bytestream2_get_be32(&gb); 1370cabdff1aSopenharmony_ci unsigned offset = bytestream2_get_be32(&gb); 1371cabdff1aSopenharmony_ci 1372cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET); 1373cabdff1aSopenharmony_ci if (opcode >= 0) { 1374cabdff1aSopenharmony_ci uint32_t x = bytestream2_get_be32(&gb); 1375cabdff1aSopenharmony_ci if (opcode && 4 + (opcode - 1LL) * pitch > bytestream2_get_bytes_left_p(&pb)) 1376cabdff1aSopenharmony_ci continue; 1377cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) { 1378cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, x); 1379cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, pitch - 4); 1380cabdff1aSopenharmony_ci opcode--; 1381cabdff1aSopenharmony_ci } 1382cabdff1aSopenharmony_ci } else { 1383cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left(&gb) > 0) { 1384cabdff1aSopenharmony_ci bytestream2_put_be32(&pb, bytestream2_get_be32(&gb)); 1385cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, pitch - 4); 1386cabdff1aSopenharmony_ci opcode++; 1387cabdff1aSopenharmony_ci } 1388cabdff1aSopenharmony_ci } 1389cabdff1aSopenharmony_ci entries--; 1390cabdff1aSopenharmony_ci } 1391cabdff1aSopenharmony_ci } 1392cabdff1aSopenharmony_ci} 1393cabdff1aSopenharmony_ci 1394cabdff1aSopenharmony_cistatic void decode_delta_e(uint8_t *dst, 1395cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1396cabdff1aSopenharmony_ci int w, int flag, int bpp, int dst_size) 1397cabdff1aSopenharmony_ci{ 1398cabdff1aSopenharmony_ci int planepitch = FFALIGN(w, 16) >> 3; 1399cabdff1aSopenharmony_ci int pitch = planepitch * bpp; 1400cabdff1aSopenharmony_ci int planepitch_byte = (w + 7) / 8; 1401cabdff1aSopenharmony_ci unsigned entries, ofssrc; 1402cabdff1aSopenharmony_ci GetByteContext gb, ptrs; 1403cabdff1aSopenharmony_ci PutByteContext pb; 1404cabdff1aSopenharmony_ci int k; 1405cabdff1aSopenharmony_ci 1406cabdff1aSopenharmony_ci if (buf_end - buf <= 4 * bpp) 1407cabdff1aSopenharmony_ci return; 1408cabdff1aSopenharmony_ci 1409cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1410cabdff1aSopenharmony_ci bytestream2_init(&ptrs, buf, bpp * 4); 1411cabdff1aSopenharmony_ci 1412cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1413cabdff1aSopenharmony_ci ofssrc = bytestream2_get_be32(&ptrs); 1414cabdff1aSopenharmony_ci 1415cabdff1aSopenharmony_ci if (!ofssrc) 1416cabdff1aSopenharmony_ci continue; 1417cabdff1aSopenharmony_ci 1418cabdff1aSopenharmony_ci if (ofssrc >= buf_end - buf) 1419cabdff1aSopenharmony_ci continue; 1420cabdff1aSopenharmony_ci 1421cabdff1aSopenharmony_ci bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); 1422cabdff1aSopenharmony_ci 1423cabdff1aSopenharmony_ci entries = bytestream2_get_be16(&gb); 1424cabdff1aSopenharmony_ci while (entries && bytestream2_get_bytes_left(&gb) >= 6) { 1425cabdff1aSopenharmony_ci int16_t opcode = bytestream2_get_be16(&gb); 1426cabdff1aSopenharmony_ci unsigned offset = bytestream2_get_be32(&gb); 1427cabdff1aSopenharmony_ci 1428cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET); 1429cabdff1aSopenharmony_ci if (opcode >= 0) { 1430cabdff1aSopenharmony_ci uint16_t x = bytestream2_get_be16(&gb); 1431cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) { 1432cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, x); 1433cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, pitch - 2); 1434cabdff1aSopenharmony_ci opcode--; 1435cabdff1aSopenharmony_ci } 1436cabdff1aSopenharmony_ci } else { 1437cabdff1aSopenharmony_ci opcode = -opcode; 1438cabdff1aSopenharmony_ci while (opcode && bytestream2_get_bytes_left(&gb) > 0) { 1439cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, bytestream2_get_be16(&gb)); 1440cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, pitch - 2); 1441cabdff1aSopenharmony_ci opcode--; 1442cabdff1aSopenharmony_ci } 1443cabdff1aSopenharmony_ci } 1444cabdff1aSopenharmony_ci entries--; 1445cabdff1aSopenharmony_ci } 1446cabdff1aSopenharmony_ci } 1447cabdff1aSopenharmony_ci} 1448cabdff1aSopenharmony_ci 1449cabdff1aSopenharmony_cistatic void decode_delta_l(uint8_t *dst, 1450cabdff1aSopenharmony_ci const uint8_t *buf, const uint8_t *buf_end, 1451cabdff1aSopenharmony_ci int w, int flag, int bpp, int dst_size) 1452cabdff1aSopenharmony_ci{ 1453cabdff1aSopenharmony_ci GetByteContext off0, off1, dgb, ogb; 1454cabdff1aSopenharmony_ci PutByteContext pb; 1455cabdff1aSopenharmony_ci unsigned poff0, poff1; 1456cabdff1aSopenharmony_ci int i, k, dstpitch; 1457cabdff1aSopenharmony_ci int planepitch_byte = (w + 7) / 8; 1458cabdff1aSopenharmony_ci int planepitch = ((w + 15) / 16) * 2; 1459cabdff1aSopenharmony_ci int pitch = planepitch * bpp; 1460cabdff1aSopenharmony_ci int count = 0; 1461cabdff1aSopenharmony_ci 1462cabdff1aSopenharmony_ci if (buf_end - buf <= 64) 1463cabdff1aSopenharmony_ci return; 1464cabdff1aSopenharmony_ci 1465cabdff1aSopenharmony_ci bytestream2_init(&off0, buf, buf_end - buf); 1466cabdff1aSopenharmony_ci bytestream2_init(&off1, buf + 32, buf_end - (buf + 32)); 1467cabdff1aSopenharmony_ci bytestream2_init_writer(&pb, dst, dst_size); 1468cabdff1aSopenharmony_ci 1469cabdff1aSopenharmony_ci dstpitch = flag ? (((w + 7) / 8) * bpp): 2; 1470cabdff1aSopenharmony_ci 1471cabdff1aSopenharmony_ci for (k = 0; k < bpp; k++) { 1472cabdff1aSopenharmony_ci poff0 = bytestream2_get_be32(&off0); 1473cabdff1aSopenharmony_ci poff1 = bytestream2_get_be32(&off1); 1474cabdff1aSopenharmony_ci 1475cabdff1aSopenharmony_ci if (!poff0) 1476cabdff1aSopenharmony_ci continue; 1477cabdff1aSopenharmony_ci 1478cabdff1aSopenharmony_ci if (2LL * poff0 >= buf_end - buf) 1479cabdff1aSopenharmony_ci return; 1480cabdff1aSopenharmony_ci 1481cabdff1aSopenharmony_ci if (2LL * poff1 >= buf_end - buf) 1482cabdff1aSopenharmony_ci return; 1483cabdff1aSopenharmony_ci 1484cabdff1aSopenharmony_ci bytestream2_init(&dgb, buf + 2 * poff0, buf_end - (buf + 2 * poff0)); 1485cabdff1aSopenharmony_ci bytestream2_init(&ogb, buf + 2 * poff1, buf_end - (buf + 2 * poff1)); 1486cabdff1aSopenharmony_ci 1487cabdff1aSopenharmony_ci while (bytestream2_peek_be16(&ogb) != 0xFFFF && bytestream2_get_bytes_left(&ogb) >= 4) { 1488cabdff1aSopenharmony_ci uint32_t offset = bytestream2_get_be16(&ogb); 1489cabdff1aSopenharmony_ci int16_t cnt = bytestream2_get_be16(&ogb); 1490cabdff1aSopenharmony_ci uint16_t data; 1491cabdff1aSopenharmony_ci 1492cabdff1aSopenharmony_ci if (count > dst_size) 1493cabdff1aSopenharmony_ci break; 1494cabdff1aSopenharmony_ci offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch; 1495cabdff1aSopenharmony_ci if (cnt < 0) { 1496cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&dgb) < 2) 1497cabdff1aSopenharmony_ci break; 1498cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, offset, SEEK_SET); 1499cabdff1aSopenharmony_ci cnt = -cnt; 1500cabdff1aSopenharmony_ci data = bytestream2_get_be16(&dgb); 1501cabdff1aSopenharmony_ci count += cnt; 1502cabdff1aSopenharmony_ci for (i = 0; i < cnt; i++) { 1503cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, data); 1504cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, dstpitch - 2); 1505cabdff1aSopenharmony_ci } 1506cabdff1aSopenharmony_ci } else { 1507cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&dgb) < 2*cnt) 1508cabdff1aSopenharmony_ci break; 1509cabdff1aSopenharmony_ci bytestream2_seek_p(&pb, offset, SEEK_SET); 1510cabdff1aSopenharmony_ci count += cnt; 1511cabdff1aSopenharmony_ci for (i = 0; i < cnt; i++) { 1512cabdff1aSopenharmony_ci data = bytestream2_get_be16(&dgb); 1513cabdff1aSopenharmony_ci bytestream2_put_be16(&pb, data); 1514cabdff1aSopenharmony_ci bytestream2_skip_p(&pb, dstpitch - 2); 1515cabdff1aSopenharmony_ci } 1516cabdff1aSopenharmony_ci } 1517cabdff1aSopenharmony_ci } 1518cabdff1aSopenharmony_ci } 1519cabdff1aSopenharmony_ci} 1520cabdff1aSopenharmony_ci 1521cabdff1aSopenharmony_cistatic int unsupported(AVCodecContext *avctx) 1522cabdff1aSopenharmony_ci{ 1523cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 1524cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "bitmap (compression 0x%0x, bpp %i, ham %i, interlaced %i)", s->compression, s->bpp, s->ham, s->is_interlaced); 1525cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1526cabdff1aSopenharmony_ci} 1527cabdff1aSopenharmony_ci 1528cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame, 1529cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 1530cabdff1aSopenharmony_ci{ 1531cabdff1aSopenharmony_ci IffContext *s = avctx->priv_data; 1532cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 1533cabdff1aSopenharmony_ci int buf_size = avpkt->size; 1534cabdff1aSopenharmony_ci const uint8_t *buf_end = buf + buf_size; 1535cabdff1aSopenharmony_ci int y, plane, res; 1536cabdff1aSopenharmony_ci GetByteContext *gb = &s->gb; 1537cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc; 1538cabdff1aSopenharmony_ci 1539cabdff1aSopenharmony_ci bytestream2_init(gb, avpkt->data, avpkt->size); 1540cabdff1aSopenharmony_ci 1541cabdff1aSopenharmony_ci if ((res = extract_header(avctx, avpkt)) < 0) 1542cabdff1aSopenharmony_ci return res; 1543cabdff1aSopenharmony_ci 1544cabdff1aSopenharmony_ci if ((res = ff_get_buffer(avctx, frame, 0)) < 0) 1545cabdff1aSopenharmony_ci return res; 1546cabdff1aSopenharmony_ci s->frame = frame; 1547cabdff1aSopenharmony_ci 1548cabdff1aSopenharmony_ci buf += bytestream2_tell(gb); 1549cabdff1aSopenharmony_ci buf_size -= bytestream2_tell(gb); 1550cabdff1aSopenharmony_ci desc = av_pix_fmt_desc_get(avctx->pix_fmt); 1551cabdff1aSopenharmony_ci 1552cabdff1aSopenharmony_ci if (!s->init && avctx->bits_per_coded_sample <= 8 - (s->masking == MASK_HAS_MASK) && 1553cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_PAL8) { 1554cabdff1aSopenharmony_ci if ((res = cmap_read_palette(avctx, (uint32_t *)frame->data[1])) < 0) 1555cabdff1aSopenharmony_ci return res; 1556cabdff1aSopenharmony_ci } else if (!s->init && avctx->bits_per_coded_sample <= 8 && 1557cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_RGB32) { 1558cabdff1aSopenharmony_ci if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0) 1559cabdff1aSopenharmony_ci return res; 1560cabdff1aSopenharmony_ci } 1561cabdff1aSopenharmony_ci s->init = 1; 1562cabdff1aSopenharmony_ci 1563cabdff1aSopenharmony_ci if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) { 1564cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) 1565cabdff1aSopenharmony_ci memcpy(s->pal, s->frame->data[1], 256 * 4); 1566cabdff1aSopenharmony_ci } 1567cabdff1aSopenharmony_ci 1568cabdff1aSopenharmony_ci switch (s->compression) { 1569cabdff1aSopenharmony_ci case 0x0: 1570cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) { 1571cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1572cabdff1aSopenharmony_ci memset(frame->data[0], 0, avctx->height * frame->linesize[0]); 1573cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1574cabdff1aSopenharmony_ci for (y = 0; y < avctx->height && buf < buf_end; y++) { 1575cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1576cabdff1aSopenharmony_ci decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); 1577cabdff1aSopenharmony_ci buf += s->planesize; 1578cabdff1aSopenharmony_ci } 1579cabdff1aSopenharmony_ci } 1580cabdff1aSopenharmony_ci } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 1581cabdff1aSopenharmony_ci memset(frame->data[0], 0, avctx->height * frame->linesize[0]); 1582cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1583cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1584cabdff1aSopenharmony_ci memset(s->ham_buf, 0, s->planesize * 8); 1585cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1586cabdff1aSopenharmony_ci const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize; 1587cabdff1aSopenharmony_ci if (start >= buf_end) 1588cabdff1aSopenharmony_ci break; 1589cabdff1aSopenharmony_ci decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane); 1590cabdff1aSopenharmony_ci } 1591cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1592cabdff1aSopenharmony_ci } 1593cabdff1aSopenharmony_ci } else 1594cabdff1aSopenharmony_ci return unsupported(avctx); 1595cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { 1596cabdff1aSopenharmony_ci int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3); 1597cabdff1aSopenharmony_ci int x; 1598cabdff1aSopenharmony_ci for (y = 0; y < avctx->height && buf < buf_end; y++) { 1599cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1600cabdff1aSopenharmony_ci memcpy(row, buf, FFMIN(raw_width, buf_end - buf)); 1601cabdff1aSopenharmony_ci buf += raw_width; 1602cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_BGR32) { 1603cabdff1aSopenharmony_ci for (x = 0; x < avctx->width; x++) 1604cabdff1aSopenharmony_ci row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4); 1605cabdff1aSopenharmony_ci } 1606cabdff1aSopenharmony_ci } 1607cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved 1608cabdff1aSopenharmony_ci avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 1609cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) 1610cabdff1aSopenharmony_ci memcpy(s->video[0], buf, FFMIN(buf_end - buf, s->video_size)); 1611cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1612cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1613cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1614cabdff1aSopenharmony_ci memset(row, 0, avctx->width); 1615cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 1616cabdff1aSopenharmony_ci decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); 1617cabdff1aSopenharmony_ci buf += s->planesize; 1618cabdff1aSopenharmony_ci } 1619cabdff1aSopenharmony_ci } 1620cabdff1aSopenharmony_ci } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 1621cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1622cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1623cabdff1aSopenharmony_ci memset(s->ham_buf, 0, s->planesize * 8); 1624cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 1625cabdff1aSopenharmony_ci decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane); 1626cabdff1aSopenharmony_ci buf += s->planesize; 1627cabdff1aSopenharmony_ci } 1628cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1629cabdff1aSopenharmony_ci } 1630cabdff1aSopenharmony_ci } else { // AV_PIX_FMT_BGR32 1631cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1632cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1633cabdff1aSopenharmony_ci memset(row, 0, avctx->width << 2); 1634cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 1635cabdff1aSopenharmony_ci decodeplane32((uint32_t *)row, buf, 1636cabdff1aSopenharmony_ci FFMIN(s->planesize, buf_end - buf), plane); 1637cabdff1aSopenharmony_ci buf += s->planesize; 1638cabdff1aSopenharmony_ci } 1639cabdff1aSopenharmony_ci } 1640cabdff1aSopenharmony_ci } 1641cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM 1642cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1643cabdff1aSopenharmony_ci for (y = 0; y < avctx->height && buf_end > buf; y++) { 1644cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1645cabdff1aSopenharmony_ci memcpy(row, buf, FFMIN(avctx->width, buf_end - buf)); 1646cabdff1aSopenharmony_ci buf += avctx->width + (avctx->width % 2); // padding if odd 1647cabdff1aSopenharmony_ci } 1648cabdff1aSopenharmony_ci } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 1649cabdff1aSopenharmony_ci for (y = 0; y < avctx->height && buf_end > buf; y++) { 1650cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1651cabdff1aSopenharmony_ci memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf)); 1652cabdff1aSopenharmony_ci buf += avctx->width + (avctx->width & 1); // padding if odd 1653cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1654cabdff1aSopenharmony_ci } 1655cabdff1aSopenharmony_ci } else 1656cabdff1aSopenharmony_ci return unsupported(avctx); 1657cabdff1aSopenharmony_ci } else { 1658cabdff1aSopenharmony_ci return unsupported(avctx); 1659cabdff1aSopenharmony_ci } 1660cabdff1aSopenharmony_ci break; 1661cabdff1aSopenharmony_ci case 0x1: 1662cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved 1663cabdff1aSopenharmony_ci avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 1664cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1665cabdff1aSopenharmony_ci uint8_t *video = s->video[0]; 1666cabdff1aSopenharmony_ci 1667cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1668cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1669cabdff1aSopenharmony_ci memset(row, 0, avctx->width); 1670cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1671cabdff1aSopenharmony_ci buf += decode_byterun(s->planebuf, s->planesize, gb); 1672cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 1673cabdff1aSopenharmony_ci memcpy(video, s->planebuf, s->planesize); 1674cabdff1aSopenharmony_ci video += s->planesize; 1675cabdff1aSopenharmony_ci } 1676cabdff1aSopenharmony_ci decodeplane8(row, s->planebuf, s->planesize, plane); 1677cabdff1aSopenharmony_ci } 1678cabdff1aSopenharmony_ci } 1679cabdff1aSopenharmony_ci } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32 1680cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1681cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1682cabdff1aSopenharmony_ci memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t)); 1683cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1684cabdff1aSopenharmony_ci buf += decode_byterun(s->planebuf, s->planesize, gb); 1685cabdff1aSopenharmony_ci decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane); 1686cabdff1aSopenharmony_ci } 1687cabdff1aSopenharmony_ci lookup_pal_indicies((uint32_t *)row, s->mask_buf, s->mask_palbuf, avctx->width); 1688cabdff1aSopenharmony_ci } 1689cabdff1aSopenharmony_ci } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 1690cabdff1aSopenharmony_ci uint8_t *video = s->video[0]; 1691cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1692cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1693cabdff1aSopenharmony_ci memset(s->ham_buf, 0, s->planesize * 8); 1694cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1695cabdff1aSopenharmony_ci buf += decode_byterun(s->planebuf, s->planesize, gb); 1696cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { 1697cabdff1aSopenharmony_ci memcpy(video, s->planebuf, s->planesize); 1698cabdff1aSopenharmony_ci video += s->planesize; 1699cabdff1aSopenharmony_ci } 1700cabdff1aSopenharmony_ci decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane); 1701cabdff1aSopenharmony_ci } 1702cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1703cabdff1aSopenharmony_ci } 1704cabdff1aSopenharmony_ci } else { // AV_PIX_FMT_BGR32 1705cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1706cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1707cabdff1aSopenharmony_ci memset(row, 0, avctx->width << 2); 1708cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1709cabdff1aSopenharmony_ci buf += decode_byterun(s->planebuf, s->planesize, gb); 1710cabdff1aSopenharmony_ci decodeplane32((uint32_t *)row, s->planebuf, s->planesize, plane); 1711cabdff1aSopenharmony_ci } 1712cabdff1aSopenharmony_ci } 1713cabdff1aSopenharmony_ci } 1714cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM 1715cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1716cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1717cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1718cabdff1aSopenharmony_ci buf += decode_byterun(row, avctx->width, gb); 1719cabdff1aSopenharmony_ci } 1720cabdff1aSopenharmony_ci } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 1721cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1722cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1723cabdff1aSopenharmony_ci buf += decode_byterun(s->ham_buf, avctx->width, gb); 1724cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1725cabdff1aSopenharmony_ci } 1726cabdff1aSopenharmony_ci } else 1727cabdff1aSopenharmony_ci return unsupported(avctx); 1728cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { // IFF-DEEP 1729cabdff1aSopenharmony_ci if (av_get_bits_per_pixel(desc) == 32) 1730cabdff1aSopenharmony_ci decode_deep_rle32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0]); 1731cabdff1aSopenharmony_ci else 1732cabdff1aSopenharmony_ci return unsupported(avctx); 1733cabdff1aSopenharmony_ci } else if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) { 1734cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1735cabdff1aSopenharmony_ci memset(frame->data[0], 0, avctx->height * frame->linesize[0]); 1736cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1737cabdff1aSopenharmony_ci for (y = 0; y < avctx->height && buf < buf_end; y++) { 1738cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1739cabdff1aSopenharmony_ci decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); 1740cabdff1aSopenharmony_ci buf += s->planesize; 1741cabdff1aSopenharmony_ci } 1742cabdff1aSopenharmony_ci } 1743cabdff1aSopenharmony_ci } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 1744cabdff1aSopenharmony_ci memset(frame->data[0], 0, avctx->height * frame->linesize[0]); 1745cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1746cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1747cabdff1aSopenharmony_ci memset(s->ham_buf, 0, s->planesize * 8); 1748cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1749cabdff1aSopenharmony_ci const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize; 1750cabdff1aSopenharmony_ci if (start >= buf_end) 1751cabdff1aSopenharmony_ci break; 1752cabdff1aSopenharmony_ci decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane); 1753cabdff1aSopenharmony_ci } 1754cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1755cabdff1aSopenharmony_ci } 1756cabdff1aSopenharmony_ci } else { 1757cabdff1aSopenharmony_ci return unsupported(avctx); 1758cabdff1aSopenharmony_ci } 1759cabdff1aSopenharmony_ci } else { 1760cabdff1aSopenharmony_ci return unsupported(avctx); 1761cabdff1aSopenharmony_ci } 1762cabdff1aSopenharmony_ci break; 1763cabdff1aSopenharmony_ci case 0x2: 1764cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') && avctx->pix_fmt == AV_PIX_FMT_PAL8) { 1765cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1766cabdff1aSopenharmony_ci decode_byterun2(s->planebuf, avctx->height, s->planesize, gb); 1767cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1768cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1769cabdff1aSopenharmony_ci decodeplane8(row, s->planebuf + s->planesize * y, s->planesize, plane); 1770cabdff1aSopenharmony_ci } 1771cabdff1aSopenharmony_ci } 1772cabdff1aSopenharmony_ci } else { 1773cabdff1aSopenharmony_ci return unsupported(avctx); 1774cabdff1aSopenharmony_ci } 1775cabdff1aSopenharmony_ci break; 1776cabdff1aSopenharmony_ci case 0x4: 1777cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32) 1778cabdff1aSopenharmony_ci decode_rgb8(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]); 1779cabdff1aSopenharmony_ci else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N') && avctx->pix_fmt == AV_PIX_FMT_RGB444) 1780cabdff1aSopenharmony_ci decode_rgbn(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]); 1781cabdff1aSopenharmony_ci else 1782cabdff1aSopenharmony_ci return unsupported(avctx); 1783cabdff1aSopenharmony_ci break; 1784cabdff1aSopenharmony_ci case 0x5: 1785cabdff1aSopenharmony_ci if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { 1786cabdff1aSopenharmony_ci if (av_get_bits_per_pixel(desc) == 32) 1787cabdff1aSopenharmony_ci decode_deep_tvdc32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0], s->tvdc); 1788cabdff1aSopenharmony_ci else 1789cabdff1aSopenharmony_ci return unsupported(avctx); 1790cabdff1aSopenharmony_ci } else 1791cabdff1aSopenharmony_ci return unsupported(avctx); 1792cabdff1aSopenharmony_ci break; 1793cabdff1aSopenharmony_ci case 0x300: 1794cabdff1aSopenharmony_ci case 0x301: 1795cabdff1aSopenharmony_ci decode_short_horizontal_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); 1796cabdff1aSopenharmony_ci break; 1797cabdff1aSopenharmony_ci case 0x500: 1798cabdff1aSopenharmony_ci case 0x501: 1799cabdff1aSopenharmony_ci decode_byte_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->is_brush, s->bpp, s->video_size); 1800cabdff1aSopenharmony_ci break; 1801cabdff1aSopenharmony_ci case 0x700: 1802cabdff1aSopenharmony_ci case 0x701: 1803cabdff1aSopenharmony_ci if (s->is_short) 1804cabdff1aSopenharmony_ci decode_short_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); 1805cabdff1aSopenharmony_ci else 1806cabdff1aSopenharmony_ci decode_long_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); 1807cabdff1aSopenharmony_ci break; 1808cabdff1aSopenharmony_ci case 0x800: 1809cabdff1aSopenharmony_ci case 0x801: 1810cabdff1aSopenharmony_ci if (s->is_short) 1811cabdff1aSopenharmony_ci decode_short_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); 1812cabdff1aSopenharmony_ci else 1813cabdff1aSopenharmony_ci decode_long_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); 1814cabdff1aSopenharmony_ci break; 1815cabdff1aSopenharmony_ci case 0x4a00: 1816cabdff1aSopenharmony_ci case 0x4a01: 1817cabdff1aSopenharmony_ci decode_delta_j(s->video[0], buf, buf_end, avctx->width, avctx->height, s->bpp, s->video_size); 1818cabdff1aSopenharmony_ci break; 1819cabdff1aSopenharmony_ci case 0x6400: 1820cabdff1aSopenharmony_ci case 0x6401: 1821cabdff1aSopenharmony_ci if (s->is_interlaced) 1822cabdff1aSopenharmony_ci return unsupported(avctx); 1823cabdff1aSopenharmony_ci decode_delta_d(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size); 1824cabdff1aSopenharmony_ci break; 1825cabdff1aSopenharmony_ci case 0x6500: 1826cabdff1aSopenharmony_ci case 0x6501: 1827cabdff1aSopenharmony_ci if (s->is_interlaced) 1828cabdff1aSopenharmony_ci return unsupported(avctx); 1829cabdff1aSopenharmony_ci decode_delta_e(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size); 1830cabdff1aSopenharmony_ci break; 1831cabdff1aSopenharmony_ci case 0x6c00: 1832cabdff1aSopenharmony_ci case 0x6c01: 1833cabdff1aSopenharmony_ci decode_delta_l(s->video[0], buf, buf_end, avctx->width, s->is_short, s->bpp, s->video_size); 1834cabdff1aSopenharmony_ci break; 1835cabdff1aSopenharmony_ci default: 1836cabdff1aSopenharmony_ci return unsupported(avctx); 1837cabdff1aSopenharmony_ci } 1838cabdff1aSopenharmony_ci 1839cabdff1aSopenharmony_ci if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) { 1840cabdff1aSopenharmony_ci memcpy(s->video[1], s->video[0], s->video_size); 1841cabdff1aSopenharmony_ci } 1842cabdff1aSopenharmony_ci 1843cabdff1aSopenharmony_ci if (s->compression > 0xff) { 1844cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 1845cabdff1aSopenharmony_ci buf = s->video[0]; 1846cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1847cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1848cabdff1aSopenharmony_ci memset(row, 0, avctx->width); 1849cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1850cabdff1aSopenharmony_ci decodeplane8(row, buf, s->planesize, plane); 1851cabdff1aSopenharmony_ci buf += s->planesize; 1852cabdff1aSopenharmony_ci } 1853cabdff1aSopenharmony_ci } 1854cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_PAL8) 1855cabdff1aSopenharmony_ci memcpy(frame->data[1], s->pal, 256 * 4); 1856cabdff1aSopenharmony_ci } else if (s->ham) { 1857cabdff1aSopenharmony_ci int i, count = 1 << s->ham; 1858cabdff1aSopenharmony_ci 1859cabdff1aSopenharmony_ci buf = s->video[0]; 1860cabdff1aSopenharmony_ci memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof(uint32_t)); 1861cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 1862cabdff1aSopenharmony_ci s->ham_palbuf[i*2+1] = s->pal[i]; 1863cabdff1aSopenharmony_ci } 1864cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 1865cabdff1aSopenharmony_ci uint32_t tmp = i << (8 - s->ham); 1866cabdff1aSopenharmony_ci tmp |= tmp >> s->ham; 1867cabdff1aSopenharmony_ci s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; 1868cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; 1869cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; 1870cabdff1aSopenharmony_ci s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16; 1871cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp; 1872cabdff1aSopenharmony_ci s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8; 1873cabdff1aSopenharmony_ci } 1874cabdff1aSopenharmony_ci if (s->masking == MASK_HAS_MASK) { 1875cabdff1aSopenharmony_ci for (i = 0; i < 8 * (1 << s->ham); i++) 1876cabdff1aSopenharmony_ci s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000; 1877cabdff1aSopenharmony_ci } 1878cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 1879cabdff1aSopenharmony_ci uint8_t *row = &frame->data[0][y * frame->linesize[0]]; 1880cabdff1aSopenharmony_ci memset(s->ham_buf, 0, s->planesize * 8); 1881cabdff1aSopenharmony_ci for (plane = 0; plane < s->bpp; plane++) { 1882cabdff1aSopenharmony_ci decodeplane8(s->ham_buf, buf, s->planesize, plane); 1883cabdff1aSopenharmony_ci buf += s->planesize; 1884cabdff1aSopenharmony_ci } 1885cabdff1aSopenharmony_ci decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 1886cabdff1aSopenharmony_ci } 1887cabdff1aSopenharmony_ci } else { 1888cabdff1aSopenharmony_ci return unsupported(avctx); 1889cabdff1aSopenharmony_ci } 1890cabdff1aSopenharmony_ci 1891cabdff1aSopenharmony_ci if (!s->is_brush) { 1892cabdff1aSopenharmony_ci FFSWAP(uint8_t *, s->video[0], s->video[1]); 1893cabdff1aSopenharmony_ci } 1894cabdff1aSopenharmony_ci } 1895cabdff1aSopenharmony_ci 1896cabdff1aSopenharmony_ci if (avpkt->flags & AV_PKT_FLAG_KEY) { 1897cabdff1aSopenharmony_ci frame->key_frame = 1; 1898cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_I; 1899cabdff1aSopenharmony_ci } else { 1900cabdff1aSopenharmony_ci frame->key_frame = 0; 1901cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_P; 1902cabdff1aSopenharmony_ci } 1903cabdff1aSopenharmony_ci 1904cabdff1aSopenharmony_ci *got_frame = 1; 1905cabdff1aSopenharmony_ci 1906cabdff1aSopenharmony_ci return buf_size; 1907cabdff1aSopenharmony_ci} 1908cabdff1aSopenharmony_ci 1909cabdff1aSopenharmony_ciconst FFCodec ff_iff_ilbm_decoder = { 1910cabdff1aSopenharmony_ci .p.name = "iff", 1911cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"), 1912cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 1913cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_IFF_ILBM, 1914cabdff1aSopenharmony_ci .priv_data_size = sizeof(IffContext), 1915cabdff1aSopenharmony_ci .init = decode_init, 1916cabdff1aSopenharmony_ci .close = decode_end, 1917cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 1918cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 1919cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 1920cabdff1aSopenharmony_ci}; 1921