1/* 2 * Tiertex Limited SEQ Video Decoder 3 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; 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 31 32typedef struct SeqVideoContext { 33 AVCodecContext *avctx; 34 AVFrame frame; 35} SeqVideoContext; 36 37 38static const unsigned char *seq_unpack_rle_block(const unsigned char *src, 39 const unsigned char *src_end, 40 unsigned char *dst, int dst_size) 41{ 42 int i, len, sz; 43 GetBitContext gb; 44 int code_table[64]; 45 46 /* get the rle codes */ 47 init_get_bits(&gb, src, (src_end - src) * 8); 48 for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { 49 if (get_bits_left(&gb) < 4) 50 return NULL; 51 code_table[i] = get_sbits(&gb, 4); 52 sz += FFABS(code_table[i]); 53 } 54 src += (get_bits_count(&gb) + 7) / 8; 55 56 /* do the rle unpacking */ 57 for (i = 0; i < 64 && dst_size > 0; i++) { 58 len = code_table[i]; 59 if (len < 0) { 60 len = -len; 61 if (src_end - src < 1) 62 return NULL; 63 memset(dst, *src++, FFMIN(len, dst_size)); 64 } else { 65 if (src_end - src < len) 66 return NULL; 67 memcpy(dst, src, FFMIN(len, dst_size)); 68 src += len; 69 } 70 dst += len; 71 dst_size -= len; 72 } 73 return src; 74} 75 76static const unsigned char *seq_decode_op1(SeqVideoContext *seq, 77 const unsigned char *src, 78 const unsigned char *src_end, 79 unsigned char *dst) 80{ 81 const unsigned char *color_table; 82 int b, i, len, bits; 83 GetBitContext gb; 84 unsigned char block[8 * 8]; 85 86 if (src_end - src < 1) 87 return NULL; 88 len = *src++; 89 if (len & 0x80) { 90 switch (len & 3) { 91 case 1: 92 src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 93 for (b = 0; b < 8; b++) { 94 memcpy(dst, &block[b * 8], 8); 95 dst += seq->frame.linesize[0]; 96 } 97 break; 98 case 2: 99 src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 100 for (i = 0; i < 8; i++) { 101 for (b = 0; b < 8; b++) 102 dst[b * seq->frame.linesize[0]] = block[i * 8 + b]; 103 ++dst; 104 } 105 break; 106 } 107 } else { 108 if (len <= 0) 109 return NULL; 110 bits = ff_log2_tab[len - 1] + 1; 111 if (src_end - src < len + 8 * bits) 112 return NULL; 113 color_table = src; 114 src += len; 115 init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; 116 for (b = 0; b < 8; b++) { 117 for (i = 0; i < 8; i++) 118 dst[i] = color_table[get_bits(&gb, bits)]; 119 dst += seq->frame.linesize[0]; 120 } 121 } 122 123 return src; 124} 125 126static const unsigned char *seq_decode_op2(SeqVideoContext *seq, 127 const unsigned char *src, 128 const unsigned char *src_end, 129 unsigned char *dst) 130{ 131 int i; 132 133 if (src_end - src < 8 * 8) 134 return NULL; 135 136 for (i = 0; i < 8; i++) { 137 memcpy(dst, src, 8); 138 src += 8; 139 dst += seq->frame.linesize[0]; 140 } 141 142 return src; 143} 144 145static const unsigned char *seq_decode_op3(SeqVideoContext *seq, 146 const unsigned char *src, 147 const unsigned char *src_end, 148 unsigned char *dst) 149{ 150 int pos, offset; 151 152 do { 153 if (src_end - src < 2) 154 return NULL; 155 pos = *src++; 156 offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); 157 dst[offset] = *src++; 158 } while (!(pos & 0x80)); 159 160 return src; 161} 162 163static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) 164{ 165 const unsigned char *data_end = data + data_size; 166 GetBitContext gb; 167 int flags, i, j, x, y, op; 168 unsigned char c[3]; 169 unsigned char *dst; 170 uint32_t *palette; 171 172 flags = *data++; 173 174 if (flags & 1) { 175 palette = (uint32_t *)seq->frame.data[1]; 176 if (data_end - data < 256 * 3) 177 return AVERROR_INVALIDDATA; 178 for (i = 0; i < 256; i++) { 179 for (j = 0; j < 3; j++, data++) 180 c[j] = (*data << 2) | (*data >> 4); 181 palette[i] = AV_RB24(c); 182 } 183 seq->frame.palette_has_changed = 1; 184 } 185 186 if (flags & 2) { 187 if (data_end - data < 128) 188 return AVERROR_INVALIDDATA; 189 init_get_bits(&gb, data, 128 * 8); data += 128; 190 for (y = 0; y < 128; y += 8) 191 for (x = 0; x < 256; x += 8) { 192 dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x]; 193 op = get_bits(&gb, 2); 194 switch (op) { 195 case 1: 196 data = seq_decode_op1(seq, data, data_end, dst); 197 break; 198 case 2: 199 data = seq_decode_op2(seq, data, data_end, dst); 200 break; 201 case 3: 202 data = seq_decode_op3(seq, data, data_end, dst); 203 break; 204 } 205 if (!data) 206 return AVERROR_INVALIDDATA; 207 } 208 } 209 return 0; 210} 211 212static av_cold int seqvideo_decode_init(AVCodecContext *avctx) 213{ 214 SeqVideoContext *seq = avctx->priv_data; 215 216 seq->avctx = avctx; 217 avctx->pix_fmt = PIX_FMT_PAL8; 218 219 seq->frame.data[0] = NULL; 220 221 return 0; 222} 223 224static int seqvideo_decode_frame(AVCodecContext *avctx, 225 void *data, int *data_size, 226 AVPacket *avpkt) 227{ 228 const uint8_t *buf = avpkt->data; 229 int buf_size = avpkt->size; 230 231 SeqVideoContext *seq = avctx->priv_data; 232 233 seq->frame.reference = 1; 234 seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 235 if (avctx->reget_buffer(avctx, &seq->frame)) { 236 av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n"); 237 return -1; 238 } 239 240 if (seqvideo_decode(seq, buf, buf_size)) 241 return AVERROR_INVALIDDATA; 242 243 *data_size = sizeof(AVFrame); 244 *(AVFrame *)data = seq->frame; 245 246 return buf_size; 247} 248 249static av_cold int seqvideo_decode_end(AVCodecContext *avctx) 250{ 251 SeqVideoContext *seq = avctx->priv_data; 252 253 if (seq->frame.data[0]) 254 avctx->release_buffer(avctx, &seq->frame); 255 256 return 0; 257} 258 259AVCodec ff_tiertexseqvideo_decoder = { 260 .name = "tiertexseqvideo", 261 .type = AVMEDIA_TYPE_VIDEO, 262 .id = CODEC_ID_TIERTEXSEQVIDEO, 263 .priv_data_size = sizeof(SeqVideoContext), 264 .init = seqvideo_decode_init, 265 .close = seqvideo_decode_end, 266 .decode = seqvideo_decode_frame, 267 .capabilities = CODEC_CAP_DR1, 268 .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), 269}; 270