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