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