1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Chronomaster DFA Video Decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2011 Konstantin Shishkov 4cabdff1aSopenharmony_ci * based on work by Vladimir "VAG" Gneushev 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <inttypes.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "avcodec.h" 26cabdff1aSopenharmony_ci#include "bytestream.h" 27cabdff1aSopenharmony_ci#include "codec_internal.h" 28cabdff1aSopenharmony_ci#include "internal.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 31cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 32cabdff1aSopenharmony_ci#include "libavutil/mem.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct DfaContext { 35cabdff1aSopenharmony_ci uint32_t pal[256]; 36cabdff1aSopenharmony_ci uint8_t *frame_buf; 37cabdff1aSopenharmony_ci} DfaContext; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_cistatic av_cold int dfa_decode_init(AVCodecContext *avctx) 40cabdff1aSopenharmony_ci{ 41cabdff1aSopenharmony_ci DfaContext *s = avctx->priv_data; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16)) 46cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0); 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci s->frame_buf = av_mallocz(avctx->width * avctx->height); 51cabdff1aSopenharmony_ci if (!s->frame_buf) 52cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci return 0; 55cabdff1aSopenharmony_ci} 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_cistatic int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height) 58cabdff1aSopenharmony_ci{ 59cabdff1aSopenharmony_ci const int size = width * height; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci if (bytestream2_get_buffer(gb, frame, size) != size) 62cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 63cabdff1aSopenharmony_ci return 0; 64cabdff1aSopenharmony_ci} 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci const uint8_t *frame_start = frame; 69cabdff1aSopenharmony_ci const uint8_t *frame_end = frame + width * height; 70cabdff1aSopenharmony_ci int mask = 0x10000, bitbuf = 0; 71cabdff1aSopenharmony_ci int v, count; 72cabdff1aSopenharmony_ci unsigned segments; 73cabdff1aSopenharmony_ci unsigned offset; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci segments = bytestream2_get_le32(gb); 76cabdff1aSopenharmony_ci offset = bytestream2_get_le32(gb); 77cabdff1aSopenharmony_ci if (segments == 0 && offset == frame_end - frame) 78cabdff1aSopenharmony_ci return 0; // skip frame 79cabdff1aSopenharmony_ci if (frame_end - frame <= offset) 80cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 81cabdff1aSopenharmony_ci frame += offset; 82cabdff1aSopenharmony_ci while (segments--) { 83cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 2) 84cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 85cabdff1aSopenharmony_ci if (mask == 0x10000) { 86cabdff1aSopenharmony_ci bitbuf = bytestream2_get_le16u(gb); 87cabdff1aSopenharmony_ci mask = 1; 88cabdff1aSopenharmony_ci } 89cabdff1aSopenharmony_ci if (frame_end - frame < 2) 90cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 91cabdff1aSopenharmony_ci if (bitbuf & mask) { 92cabdff1aSopenharmony_ci v = bytestream2_get_le16(gb); 93cabdff1aSopenharmony_ci offset = (v & 0x1FFF) << 1; 94cabdff1aSopenharmony_ci count = ((v >> 13) + 2) << 1; 95cabdff1aSopenharmony_ci if (frame - frame_start < offset || frame_end - frame < count) 96cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 97cabdff1aSopenharmony_ci av_memcpy_backptr(frame, offset, count); 98cabdff1aSopenharmony_ci frame += count; 99cabdff1aSopenharmony_ci } else { 100cabdff1aSopenharmony_ci *frame++ = bytestream2_get_byte(gb); 101cabdff1aSopenharmony_ci *frame++ = bytestream2_get_byte(gb); 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci mask <<= 1; 104cabdff1aSopenharmony_ci } 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci return 0; 107cabdff1aSopenharmony_ci} 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_cistatic int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height) 110cabdff1aSopenharmony_ci{ 111cabdff1aSopenharmony_ci const uint8_t *frame_start = frame; 112cabdff1aSopenharmony_ci const uint8_t *frame_end = frame + width * height; 113cabdff1aSopenharmony_ci int mask = 0x10000, bitbuf = 0; 114cabdff1aSopenharmony_ci int v, offset, count, segments; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci segments = bytestream2_get_le16(gb); 117cabdff1aSopenharmony_ci while (segments--) { 118cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 2) 119cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 120cabdff1aSopenharmony_ci if (mask == 0x10000) { 121cabdff1aSopenharmony_ci bitbuf = bytestream2_get_le16u(gb); 122cabdff1aSopenharmony_ci mask = 1; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci if (frame_end - frame < 2) 125cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 126cabdff1aSopenharmony_ci if (bitbuf & mask) { 127cabdff1aSopenharmony_ci v = bytestream2_get_le16(gb); 128cabdff1aSopenharmony_ci offset = (v & 0x1FFF) << 1; 129cabdff1aSopenharmony_ci count = ((v >> 13) + 2) << 1; 130cabdff1aSopenharmony_ci if (frame - frame_start < offset || frame_end - frame < count) 131cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 132cabdff1aSopenharmony_ci av_memcpy_backptr(frame, offset, count); 133cabdff1aSopenharmony_ci frame += count; 134cabdff1aSopenharmony_ci } else if (bitbuf & (mask << 1)) { 135cabdff1aSopenharmony_ci frame += bytestream2_get_le16(gb); 136cabdff1aSopenharmony_ci } else { 137cabdff1aSopenharmony_ci *frame++ = bytestream2_get_byte(gb); 138cabdff1aSopenharmony_ci *frame++ = bytestream2_get_byte(gb); 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci mask <<= 2; 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci return 0; 144cabdff1aSopenharmony_ci} 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_cistatic int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height) 147cabdff1aSopenharmony_ci{ 148cabdff1aSopenharmony_ci const uint8_t *frame_start = frame; 149cabdff1aSopenharmony_ci const uint8_t *frame_end = frame + width * height; 150cabdff1aSopenharmony_ci int mask = 0x10000, bitbuf = 0; 151cabdff1aSopenharmony_ci int i, v, offset, count, segments; 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if ((width | height) & 1) 154cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 155cabdff1aSopenharmony_ci segments = bytestream2_get_le16(gb); 156cabdff1aSopenharmony_ci while (segments--) { 157cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 2) 158cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 159cabdff1aSopenharmony_ci if (mask == 0x10000) { 160cabdff1aSopenharmony_ci bitbuf = bytestream2_get_le16u(gb); 161cabdff1aSopenharmony_ci mask = 1; 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci if (bitbuf & mask) { 165cabdff1aSopenharmony_ci v = bytestream2_get_le16(gb); 166cabdff1aSopenharmony_ci offset = (v & 0x1FFF) << 2; 167cabdff1aSopenharmony_ci count = ((v >> 13) + 2) << 1; 168cabdff1aSopenharmony_ci if (frame - frame_start < offset || frame_end - frame < count*2 + width) 169cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 170cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 171cabdff1aSopenharmony_ci frame[0] = frame[1] = 172cabdff1aSopenharmony_ci frame[width] = frame[width + 1] = frame[-offset]; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci frame += 2; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci } else if (bitbuf & (mask << 1)) { 177cabdff1aSopenharmony_ci v = bytestream2_get_le16(gb)*2; 178cabdff1aSopenharmony_ci if (frame - frame_end < v) 179cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 180cabdff1aSopenharmony_ci frame += v; 181cabdff1aSopenharmony_ci } else { 182cabdff1aSopenharmony_ci if (width < 4 || frame_end - frame < width + 4) 183cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 184cabdff1aSopenharmony_ci frame[0] = frame[1] = 185cabdff1aSopenharmony_ci frame[width] = frame[width + 1] = bytestream2_get_byte(gb); 186cabdff1aSopenharmony_ci frame += 2; 187cabdff1aSopenharmony_ci frame[0] = frame[1] = 188cabdff1aSopenharmony_ci frame[width] = frame[width + 1] = bytestream2_get_byte(gb); 189cabdff1aSopenharmony_ci frame += 2; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci mask <<= 2; 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci return 0; 195cabdff1aSopenharmony_ci} 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_cistatic int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height) 198cabdff1aSopenharmony_ci{ 199cabdff1aSopenharmony_ci uint8_t *line_ptr; 200cabdff1aSopenharmony_ci int count, lines, segments; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci count = bytestream2_get_le16(gb); 203cabdff1aSopenharmony_ci if (count >= height) 204cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 205cabdff1aSopenharmony_ci frame += width * count; 206cabdff1aSopenharmony_ci lines = bytestream2_get_le16(gb); 207cabdff1aSopenharmony_ci if (count + lines > height) 208cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 209cabdff1aSopenharmony_ci 210cabdff1aSopenharmony_ci while (lines--) { 211cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 1) 212cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 213cabdff1aSopenharmony_ci line_ptr = frame; 214cabdff1aSopenharmony_ci frame += width; 215cabdff1aSopenharmony_ci segments = bytestream2_get_byteu(gb); 216cabdff1aSopenharmony_ci while (segments--) { 217cabdff1aSopenharmony_ci if (frame - line_ptr <= bytestream2_peek_byte(gb)) 218cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 219cabdff1aSopenharmony_ci line_ptr += bytestream2_get_byte(gb); 220cabdff1aSopenharmony_ci count = (int8_t)bytestream2_get_byte(gb); 221cabdff1aSopenharmony_ci if (count >= 0) { 222cabdff1aSopenharmony_ci if (frame - line_ptr < count) 223cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 224cabdff1aSopenharmony_ci if (bytestream2_get_buffer(gb, line_ptr, count) != count) 225cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 226cabdff1aSopenharmony_ci } else { 227cabdff1aSopenharmony_ci count = -count; 228cabdff1aSopenharmony_ci if (frame - line_ptr < count) 229cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 230cabdff1aSopenharmony_ci memset(line_ptr, bytestream2_get_byte(gb), count); 231cabdff1aSopenharmony_ci } 232cabdff1aSopenharmony_ci line_ptr += count; 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci return 0; 237cabdff1aSopenharmony_ci} 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_cistatic int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height) 240cabdff1aSopenharmony_ci{ 241cabdff1aSopenharmony_ci const uint8_t *frame_end = frame + width * height; 242cabdff1aSopenharmony_ci uint8_t *line_ptr; 243cabdff1aSopenharmony_ci int count, i, v, lines, segments; 244cabdff1aSopenharmony_ci int y = 0; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci lines = bytestream2_get_le16(gb); 247cabdff1aSopenharmony_ci if (lines > height) 248cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci while (lines--) { 251cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 2) 252cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 253cabdff1aSopenharmony_ci segments = bytestream2_get_le16u(gb); 254cabdff1aSopenharmony_ci while ((segments & 0xC000) == 0xC000) { 255cabdff1aSopenharmony_ci unsigned skip_lines = -(int16_t)segments; 256cabdff1aSopenharmony_ci int64_t delta = -((int16_t)segments * (int64_t)width); 257cabdff1aSopenharmony_ci if (frame_end - frame <= delta || y + lines + skip_lines > height) 258cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 259cabdff1aSopenharmony_ci frame += delta; 260cabdff1aSopenharmony_ci y += skip_lines; 261cabdff1aSopenharmony_ci segments = bytestream2_get_le16(gb); 262cabdff1aSopenharmony_ci } 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci if (frame_end <= frame) 265cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 266cabdff1aSopenharmony_ci if (segments & 0x8000) { 267cabdff1aSopenharmony_ci frame[width - 1] = segments & 0xFF; 268cabdff1aSopenharmony_ci segments = bytestream2_get_le16(gb); 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci line_ptr = frame; 271cabdff1aSopenharmony_ci if (frame_end - frame < width) 272cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 273cabdff1aSopenharmony_ci frame += width; 274cabdff1aSopenharmony_ci y++; 275cabdff1aSopenharmony_ci while (segments--) { 276cabdff1aSopenharmony_ci if (frame - line_ptr <= bytestream2_peek_byte(gb)) 277cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 278cabdff1aSopenharmony_ci line_ptr += bytestream2_get_byte(gb); 279cabdff1aSopenharmony_ci count = (int8_t)bytestream2_get_byte(gb); 280cabdff1aSopenharmony_ci if (count >= 0) { 281cabdff1aSopenharmony_ci if (frame - line_ptr < count * 2) 282cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 283cabdff1aSopenharmony_ci if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2) 284cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 285cabdff1aSopenharmony_ci line_ptr += count * 2; 286cabdff1aSopenharmony_ci } else { 287cabdff1aSopenharmony_ci count = -count; 288cabdff1aSopenharmony_ci if (frame - line_ptr < count * 2) 289cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 290cabdff1aSopenharmony_ci v = bytestream2_get_le16(gb); 291cabdff1aSopenharmony_ci for (i = 0; i < count; i++) 292cabdff1aSopenharmony_ci bytestream_put_le16(&line_ptr, v); 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci return 0; 298cabdff1aSopenharmony_ci} 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_cistatic int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height) 301cabdff1aSopenharmony_ci{ 302cabdff1aSopenharmony_ci const uint8_t *frame_end = frame + width * height; 303cabdff1aSopenharmony_ci uint32_t segments = bytestream2_get_le32(gb); 304cabdff1aSopenharmony_ci int skip, copy; 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci while (segments--) { 307cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(gb) < 2) 308cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 309cabdff1aSopenharmony_ci copy = bytestream2_get_byteu(gb) * 2; 310cabdff1aSopenharmony_ci skip = bytestream2_get_byteu(gb) * 2; 311cabdff1aSopenharmony_ci if (frame_end - frame < copy + skip || 312cabdff1aSopenharmony_ci bytestream2_get_bytes_left(gb) < copy) 313cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 314cabdff1aSopenharmony_ci frame += skip; 315cabdff1aSopenharmony_ci bytestream2_get_buffer(gb, frame, copy); 316cabdff1aSopenharmony_ci frame += copy; 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_ci return 0; 320cabdff1aSopenharmony_ci} 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_cistatic int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height) 323cabdff1aSopenharmony_ci{ 324cabdff1aSopenharmony_ci memset(frame, 0, width * height); 325cabdff1aSopenharmony_ci return 0; 326cabdff1aSopenharmony_ci} 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_citypedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height); 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_cistatic const chunk_decoder decoder[8] = { 332cabdff1aSopenharmony_ci decode_copy, decode_tsw1, decode_bdlt, decode_wdlt, 333cabdff1aSopenharmony_ci decode_tdlt, decode_dsw1, decode_blck, decode_dds1, 334cabdff1aSopenharmony_ci}; 335cabdff1aSopenharmony_ci 336cabdff1aSopenharmony_cistatic const char chunk_name[8][5] = { 337cabdff1aSopenharmony_ci "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1" 338cabdff1aSopenharmony_ci}; 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_cistatic int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame, 341cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 342cabdff1aSopenharmony_ci{ 343cabdff1aSopenharmony_ci DfaContext *s = avctx->priv_data; 344cabdff1aSopenharmony_ci GetByteContext gb; 345cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 346cabdff1aSopenharmony_ci uint32_t chunk_type, chunk_size; 347cabdff1aSopenharmony_ci uint8_t *dst; 348cabdff1aSopenharmony_ci int ret; 349cabdff1aSopenharmony_ci int i, pal_elems; 350cabdff1aSopenharmony_ci int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0; 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 353cabdff1aSopenharmony_ci return ret; 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci bytestream2_init(&gb, avpkt->data, avpkt->size); 356cabdff1aSopenharmony_ci while (bytestream2_get_bytes_left(&gb) > 0) { 357cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&gb) < 12) 358cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 359cabdff1aSopenharmony_ci bytestream2_skip(&gb, 4); 360cabdff1aSopenharmony_ci chunk_size = bytestream2_get_le32(&gb); 361cabdff1aSopenharmony_ci chunk_type = bytestream2_get_le32(&gb); 362cabdff1aSopenharmony_ci if (!chunk_type) 363cabdff1aSopenharmony_ci break; 364cabdff1aSopenharmony_ci if (chunk_type == 1) { 365cabdff1aSopenharmony_ci pal_elems = FFMIN(chunk_size / 3, 256); 366cabdff1aSopenharmony_ci for (i = 0; i < pal_elems; i++) { 367cabdff1aSopenharmony_ci s->pal[i] = bytestream2_get_be24(&gb) << 2; 368cabdff1aSopenharmony_ci s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303; 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci frame->palette_has_changed = 1; 371cabdff1aSopenharmony_ci } else if (chunk_type <= 9) { 372cabdff1aSopenharmony_ci if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) { 373cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n", 374cabdff1aSopenharmony_ci chunk_name[chunk_type - 2]); 375cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci } else { 378cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 379cabdff1aSopenharmony_ci "Ignoring unknown chunk type %"PRIu32"\n", 380cabdff1aSopenharmony_ci chunk_type); 381cabdff1aSopenharmony_ci } 382cabdff1aSopenharmony_ci buf += chunk_size; 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci 385cabdff1aSopenharmony_ci buf = s->frame_buf; 386cabdff1aSopenharmony_ci dst = frame->data[0]; 387cabdff1aSopenharmony_ci if (version == 0x100) { 388cabdff1aSopenharmony_ci for (i = 0; i < avctx->height; i++) { 389cabdff1aSopenharmony_ci int j; 390cabdff1aSopenharmony_ci const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width; 391cabdff1aSopenharmony_ci int stride = (avctx->height/4)*avctx->width; 392cabdff1aSopenharmony_ci for(j = 0; j < avctx->width/4; j++) { 393cabdff1aSopenharmony_ci dst[4*j+0] = buf1[j + 0*stride]; 394cabdff1aSopenharmony_ci dst[4*j+1] = buf1[j + 1*stride]; 395cabdff1aSopenharmony_ci dst[4*j+2] = buf1[j + 2*stride]; 396cabdff1aSopenharmony_ci dst[4*j+3] = buf1[j + 3*stride]; 397cabdff1aSopenharmony_ci } 398cabdff1aSopenharmony_ci j *= 4; 399cabdff1aSopenharmony_ci for(; j < avctx->width; j++) { 400cabdff1aSopenharmony_ci dst[j] = buf1[(j/4) + (j&3)*stride]; 401cabdff1aSopenharmony_ci } 402cabdff1aSopenharmony_ci dst += frame->linesize[0]; 403cabdff1aSopenharmony_ci } 404cabdff1aSopenharmony_ci } else 405cabdff1aSopenharmony_ci av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width, 406cabdff1aSopenharmony_ci avctx->width, avctx->height); 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci memcpy(frame->data[1], s->pal, sizeof(s->pal)); 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_ci *got_frame = 1; 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci return avpkt->size; 413cabdff1aSopenharmony_ci} 414cabdff1aSopenharmony_ci 415cabdff1aSopenharmony_cistatic av_cold int dfa_decode_end(AVCodecContext *avctx) 416cabdff1aSopenharmony_ci{ 417cabdff1aSopenharmony_ci DfaContext *s = avctx->priv_data; 418cabdff1aSopenharmony_ci 419cabdff1aSopenharmony_ci av_freep(&s->frame_buf); 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci return 0; 422cabdff1aSopenharmony_ci} 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ciconst FFCodec ff_dfa_decoder = { 425cabdff1aSopenharmony_ci .p.name = "dfa", 426cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), 427cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 428cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_DFA, 429cabdff1aSopenharmony_ci .priv_data_size = sizeof(DfaContext), 430cabdff1aSopenharmony_ci .init = dfa_decode_init, 431cabdff1aSopenharmony_ci .close = dfa_decode_end, 432cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(dfa_decode_frame), 433cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 434cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 435cabdff1aSopenharmony_ci}; 436