1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Tiertex Limited SEQ Video Decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Tiertex Limited SEQ video decoder 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#define BITSTREAM_READER_LE 28cabdff1aSopenharmony_ci#include "avcodec.h" 29cabdff1aSopenharmony_ci#include "codec_internal.h" 30cabdff1aSopenharmony_ci#include "get_bits.h" 31cabdff1aSopenharmony_ci#include "internal.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct SeqVideoContext { 35cabdff1aSopenharmony_ci AVCodecContext *avctx; 36cabdff1aSopenharmony_ci AVFrame *frame; 37cabdff1aSopenharmony_ci} SeqVideoContext; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic const unsigned char *seq_unpack_rle_block(const unsigned char *src, 41cabdff1aSopenharmony_ci const unsigned char *src_end, 42cabdff1aSopenharmony_ci unsigned char *dst, int dst_size) 43cabdff1aSopenharmony_ci{ 44cabdff1aSopenharmony_ci int i, len, sz; 45cabdff1aSopenharmony_ci GetBitContext gb; 46cabdff1aSopenharmony_ci int code_table[64]; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci /* get the rle codes */ 49cabdff1aSopenharmony_ci init_get_bits(&gb, src, (src_end - src) * 8); 50cabdff1aSopenharmony_ci for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { 51cabdff1aSopenharmony_ci if (get_bits_left(&gb) < 4) 52cabdff1aSopenharmony_ci return NULL; 53cabdff1aSopenharmony_ci code_table[i] = get_sbits(&gb, 4); 54cabdff1aSopenharmony_ci sz += FFABS(code_table[i]); 55cabdff1aSopenharmony_ci } 56cabdff1aSopenharmony_ci src += (get_bits_count(&gb) + 7) / 8; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci /* do the rle unpacking */ 59cabdff1aSopenharmony_ci for (i = 0; i < 64 && dst_size > 0; i++) { 60cabdff1aSopenharmony_ci len = code_table[i]; 61cabdff1aSopenharmony_ci if (len < 0) { 62cabdff1aSopenharmony_ci len = -len; 63cabdff1aSopenharmony_ci if (src_end - src < 1) 64cabdff1aSopenharmony_ci return NULL; 65cabdff1aSopenharmony_ci memset(dst, *src++, FFMIN(len, dst_size)); 66cabdff1aSopenharmony_ci } else { 67cabdff1aSopenharmony_ci if (src_end - src < len) 68cabdff1aSopenharmony_ci return NULL; 69cabdff1aSopenharmony_ci memcpy(dst, src, FFMIN(len, dst_size)); 70cabdff1aSopenharmony_ci src += len; 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci dst += len; 73cabdff1aSopenharmony_ci dst_size -= len; 74cabdff1aSopenharmony_ci } 75cabdff1aSopenharmony_ci return src; 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic const unsigned char *seq_decode_op1(SeqVideoContext *seq, 79cabdff1aSopenharmony_ci const unsigned char *src, 80cabdff1aSopenharmony_ci const unsigned char *src_end, 81cabdff1aSopenharmony_ci unsigned char *dst) 82cabdff1aSopenharmony_ci{ 83cabdff1aSopenharmony_ci const unsigned char *color_table; 84cabdff1aSopenharmony_ci int b, i, len, bits; 85cabdff1aSopenharmony_ci GetBitContext gb; 86cabdff1aSopenharmony_ci unsigned char block[8 * 8]; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci if (src_end - src < 1) 89cabdff1aSopenharmony_ci return NULL; 90cabdff1aSopenharmony_ci len = *src++; 91cabdff1aSopenharmony_ci if (len & 0x80) { 92cabdff1aSopenharmony_ci switch (len & 3) { 93cabdff1aSopenharmony_ci case 1: 94cabdff1aSopenharmony_ci src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 95cabdff1aSopenharmony_ci for (b = 0; b < 8; b++) { 96cabdff1aSopenharmony_ci memcpy(dst, &block[b * 8], 8); 97cabdff1aSopenharmony_ci dst += seq->frame->linesize[0]; 98cabdff1aSopenharmony_ci } 99cabdff1aSopenharmony_ci break; 100cabdff1aSopenharmony_ci case 2: 101cabdff1aSopenharmony_ci src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 102cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 103cabdff1aSopenharmony_ci for (b = 0; b < 8; b++) 104cabdff1aSopenharmony_ci dst[b * seq->frame->linesize[0]] = block[i * 8 + b]; 105cabdff1aSopenharmony_ci ++dst; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci break; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci } else { 110cabdff1aSopenharmony_ci if (len <= 0) 111cabdff1aSopenharmony_ci return NULL; 112cabdff1aSopenharmony_ci bits = ff_log2_tab[len - 1] + 1; 113cabdff1aSopenharmony_ci if (src_end - src < len + 8 * bits) 114cabdff1aSopenharmony_ci return NULL; 115cabdff1aSopenharmony_ci color_table = src; 116cabdff1aSopenharmony_ci src += len; 117cabdff1aSopenharmony_ci init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; 118cabdff1aSopenharmony_ci for (b = 0; b < 8; b++) { 119cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) 120cabdff1aSopenharmony_ci dst[i] = color_table[get_bits(&gb, bits)]; 121cabdff1aSopenharmony_ci dst += seq->frame->linesize[0]; 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci return src; 126cabdff1aSopenharmony_ci} 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_cistatic const unsigned char *seq_decode_op2(SeqVideoContext *seq, 129cabdff1aSopenharmony_ci const unsigned char *src, 130cabdff1aSopenharmony_ci const unsigned char *src_end, 131cabdff1aSopenharmony_ci unsigned char *dst) 132cabdff1aSopenharmony_ci{ 133cabdff1aSopenharmony_ci int i; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci if (src_end - src < 8 * 8) 136cabdff1aSopenharmony_ci return NULL; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 139cabdff1aSopenharmony_ci memcpy(dst, src, 8); 140cabdff1aSopenharmony_ci src += 8; 141cabdff1aSopenharmony_ci dst += seq->frame->linesize[0]; 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci return src; 145cabdff1aSopenharmony_ci} 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_cistatic const unsigned char *seq_decode_op3(SeqVideoContext *seq, 148cabdff1aSopenharmony_ci const unsigned char *src, 149cabdff1aSopenharmony_ci const unsigned char *src_end, 150cabdff1aSopenharmony_ci unsigned char *dst) 151cabdff1aSopenharmony_ci{ 152cabdff1aSopenharmony_ci int pos, offset; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci do { 155cabdff1aSopenharmony_ci if (src_end - src < 2) 156cabdff1aSopenharmony_ci return NULL; 157cabdff1aSopenharmony_ci pos = *src++; 158cabdff1aSopenharmony_ci offset = ((pos >> 3) & 7) * seq->frame->linesize[0] + (pos & 7); 159cabdff1aSopenharmony_ci dst[offset] = *src++; 160cabdff1aSopenharmony_ci } while (!(pos & 0x80)); 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci return src; 163cabdff1aSopenharmony_ci} 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_cistatic int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) 166cabdff1aSopenharmony_ci{ 167cabdff1aSopenharmony_ci const unsigned char *data_end = data + data_size; 168cabdff1aSopenharmony_ci GetBitContext gb; 169cabdff1aSopenharmony_ci int flags, i, j, x, y, op; 170cabdff1aSopenharmony_ci unsigned char c[3]; 171cabdff1aSopenharmony_ci unsigned char *dst; 172cabdff1aSopenharmony_ci uint32_t *palette; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci flags = *data++; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci if (flags & 1) { 177cabdff1aSopenharmony_ci palette = (uint32_t *)seq->frame->data[1]; 178cabdff1aSopenharmony_ci if (data_end - data < 256 * 3) 179cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 180cabdff1aSopenharmony_ci for (i = 0; i < 256; i++) { 181cabdff1aSopenharmony_ci for (j = 0; j < 3; j++, data++) 182cabdff1aSopenharmony_ci c[j] = (*data << 2) | (*data >> 4); 183cabdff1aSopenharmony_ci palette[i] = 0xFFU << 24 | AV_RB24(c); 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci seq->frame->palette_has_changed = 1; 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci if (flags & 2) { 189cabdff1aSopenharmony_ci if (data_end - data < 128) 190cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 191cabdff1aSopenharmony_ci init_get_bits(&gb, data, 128 * 8); data += 128; 192cabdff1aSopenharmony_ci for (y = 0; y < 128; y += 8) 193cabdff1aSopenharmony_ci for (x = 0; x < 256; x += 8) { 194cabdff1aSopenharmony_ci dst = &seq->frame->data[0][y * seq->frame->linesize[0] + x]; 195cabdff1aSopenharmony_ci op = get_bits(&gb, 2); 196cabdff1aSopenharmony_ci switch (op) { 197cabdff1aSopenharmony_ci case 1: 198cabdff1aSopenharmony_ci data = seq_decode_op1(seq, data, data_end, dst); 199cabdff1aSopenharmony_ci break; 200cabdff1aSopenharmony_ci case 2: 201cabdff1aSopenharmony_ci data = seq_decode_op2(seq, data, data_end, dst); 202cabdff1aSopenharmony_ci break; 203cabdff1aSopenharmony_ci case 3: 204cabdff1aSopenharmony_ci data = seq_decode_op3(seq, data, data_end, dst); 205cabdff1aSopenharmony_ci break; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci if (!data) 208cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 209cabdff1aSopenharmony_ci } 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci return 0; 212cabdff1aSopenharmony_ci} 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_cistatic av_cold int seqvideo_decode_init(AVCodecContext *avctx) 215cabdff1aSopenharmony_ci{ 216cabdff1aSopenharmony_ci SeqVideoContext *seq = avctx->priv_data; 217cabdff1aSopenharmony_ci int ret; 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci seq->avctx = avctx; 220cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci ret = ff_set_dimensions(avctx, 256, 128); 223cabdff1aSopenharmony_ci if (ret < 0) 224cabdff1aSopenharmony_ci return ret; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci seq->frame = av_frame_alloc(); 227cabdff1aSopenharmony_ci if (!seq->frame) 228cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci return 0; 231cabdff1aSopenharmony_ci} 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_cistatic int seqvideo_decode_frame(AVCodecContext *avctx, AVFrame *rframe, 234cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 235cabdff1aSopenharmony_ci{ 236cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 237cabdff1aSopenharmony_ci int buf_size = avpkt->size; 238cabdff1aSopenharmony_ci int ret; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci SeqVideoContext *seq = avctx->priv_data; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, seq->frame, 0)) < 0) 243cabdff1aSopenharmony_ci return ret; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci if (seqvideo_decode(seq, buf, buf_size)) 246cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci if ((ret = av_frame_ref(rframe, seq->frame)) < 0) 249cabdff1aSopenharmony_ci return ret; 250cabdff1aSopenharmony_ci *got_frame = 1; 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci return buf_size; 253cabdff1aSopenharmony_ci} 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_cistatic av_cold int seqvideo_decode_end(AVCodecContext *avctx) 256cabdff1aSopenharmony_ci{ 257cabdff1aSopenharmony_ci SeqVideoContext *seq = avctx->priv_data; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci av_frame_free(&seq->frame); 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci return 0; 262cabdff1aSopenharmony_ci} 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ciconst FFCodec ff_tiertexseqvideo_decoder = { 265cabdff1aSopenharmony_ci .p.name = "tiertexseqvideo", 266cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), 267cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 268cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_TIERTEXSEQVIDEO, 269cabdff1aSopenharmony_ci .priv_data_size = sizeof(SeqVideoContext), 270cabdff1aSopenharmony_ci .init = seqvideo_decode_init, 271cabdff1aSopenharmony_ci .close = seqvideo_decode_end, 272cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(seqvideo_decode_frame), 273cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 274cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 275cabdff1aSopenharmony_ci}; 276