Libav 0.7.1
|
00001 /* 00002 * Tiertex Limited SEQ Video Decoder 00003 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "avcodec.h" 00028 #define ALT_BITSTREAM_READER_LE 00029 #include "get_bits.h" 00030 00031 00032 typedef struct SeqVideoContext { 00033 AVCodecContext *avctx; 00034 AVFrame frame; 00035 } SeqVideoContext; 00036 00037 00038 static const unsigned char *seq_unpack_rle_block(const unsigned char *src, 00039 const unsigned char *src_end, 00040 unsigned char *dst, int dst_size) 00041 { 00042 int i, len, sz; 00043 GetBitContext gb; 00044 int code_table[64]; 00045 00046 /* get the rle codes */ 00047 init_get_bits(&gb, src, (src_end - src) * 8); 00048 for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { 00049 if (get_bits_left(&gb) < 4) 00050 return NULL; 00051 code_table[i] = get_sbits(&gb, 4); 00052 sz += FFABS(code_table[i]); 00053 } 00054 src += (get_bits_count(&gb) + 7) / 8; 00055 00056 /* do the rle unpacking */ 00057 for (i = 0; i < 64 && dst_size > 0; i++) { 00058 len = code_table[i]; 00059 if (len < 0) { 00060 len = -len; 00061 if (src_end - src < 1) 00062 return NULL; 00063 memset(dst, *src++, FFMIN(len, dst_size)); 00064 } else { 00065 if (src_end - src < len) 00066 return NULL; 00067 memcpy(dst, src, FFMIN(len, dst_size)); 00068 src += len; 00069 } 00070 dst += len; 00071 dst_size -= len; 00072 } 00073 return src; 00074 } 00075 00076 static const unsigned char *seq_decode_op1(SeqVideoContext *seq, 00077 const unsigned char *src, 00078 const unsigned char *src_end, 00079 unsigned char *dst) 00080 { 00081 const unsigned char *color_table; 00082 int b, i, len, bits; 00083 GetBitContext gb; 00084 unsigned char block[8 * 8]; 00085 00086 if (src_end - src < 1) 00087 return NULL; 00088 len = *src++; 00089 if (len & 0x80) { 00090 switch (len & 3) { 00091 case 1: 00092 src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 00093 for (b = 0; b < 8; b++) { 00094 memcpy(dst, &block[b * 8], 8); 00095 dst += seq->frame.linesize[0]; 00096 } 00097 break; 00098 case 2: 00099 src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); 00100 for (i = 0; i < 8; i++) { 00101 for (b = 0; b < 8; b++) 00102 dst[b * seq->frame.linesize[0]] = block[i * 8 + b]; 00103 ++dst; 00104 } 00105 break; 00106 } 00107 } else { 00108 if (len <= 0) 00109 return NULL; 00110 bits = ff_log2_tab[len - 1] + 1; 00111 if (src_end - src < len + 8 * bits) 00112 return NULL; 00113 color_table = src; 00114 src += len; 00115 init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; 00116 for (b = 0; b < 8; b++) { 00117 for (i = 0; i < 8; i++) 00118 dst[i] = color_table[get_bits(&gb, bits)]; 00119 dst += seq->frame.linesize[0]; 00120 } 00121 } 00122 00123 return src; 00124 } 00125 00126 static const unsigned char *seq_decode_op2(SeqVideoContext *seq, 00127 const unsigned char *src, 00128 const unsigned char *src_end, 00129 unsigned char *dst) 00130 { 00131 int i; 00132 00133 if (src_end - src < 8 * 8) 00134 return NULL; 00135 00136 for (i = 0; i < 8; i++) { 00137 memcpy(dst, src, 8); 00138 src += 8; 00139 dst += seq->frame.linesize[0]; 00140 } 00141 00142 return src; 00143 } 00144 00145 static const unsigned char *seq_decode_op3(SeqVideoContext *seq, 00146 const unsigned char *src, 00147 const unsigned char *src_end, 00148 unsigned char *dst) 00149 { 00150 int pos, offset; 00151 00152 do { 00153 if (src_end - src < 2) 00154 return NULL; 00155 pos = *src++; 00156 offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); 00157 dst[offset] = *src++; 00158 } while (!(pos & 0x80)); 00159 00160 return src; 00161 } 00162 00163 static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) 00164 { 00165 const unsigned char *data_end = data + data_size; 00166 GetBitContext gb; 00167 int flags, i, j, x, y, op; 00168 unsigned char c[3]; 00169 unsigned char *dst; 00170 uint32_t *palette; 00171 00172 flags = *data++; 00173 00174 if (flags & 1) { 00175 palette = (uint32_t *)seq->frame.data[1]; 00176 if (data_end - data < 256 * 3) 00177 return AVERROR_INVALIDDATA; 00178 for (i = 0; i < 256; i++) { 00179 for (j = 0; j < 3; j++, data++) 00180 c[j] = (*data << 2) | (*data >> 4); 00181 palette[i] = AV_RB24(c); 00182 } 00183 seq->frame.palette_has_changed = 1; 00184 } 00185 00186 if (flags & 2) { 00187 if (data_end - data < 128) 00188 return AVERROR_INVALIDDATA; 00189 init_get_bits(&gb, data, 128 * 8); data += 128; 00190 for (y = 0; y < 128; y += 8) 00191 for (x = 0; x < 256; x += 8) { 00192 dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x]; 00193 op = get_bits(&gb, 2); 00194 switch (op) { 00195 case 1: 00196 data = seq_decode_op1(seq, data, data_end, dst); 00197 break; 00198 case 2: 00199 data = seq_decode_op2(seq, data, data_end, dst); 00200 break; 00201 case 3: 00202 data = seq_decode_op3(seq, data, data_end, dst); 00203 break; 00204 } 00205 if (!data) 00206 return AVERROR_INVALIDDATA; 00207 } 00208 } 00209 return 0; 00210 } 00211 00212 static av_cold int seqvideo_decode_init(AVCodecContext *avctx) 00213 { 00214 SeqVideoContext *seq = avctx->priv_data; 00215 00216 seq->avctx = avctx; 00217 avctx->pix_fmt = PIX_FMT_PAL8; 00218 00219 seq->frame.data[0] = NULL; 00220 00221 return 0; 00222 } 00223 00224 static int seqvideo_decode_frame(AVCodecContext *avctx, 00225 void *data, int *data_size, 00226 AVPacket *avpkt) 00227 { 00228 const uint8_t *buf = avpkt->data; 00229 int buf_size = avpkt->size; 00230 00231 SeqVideoContext *seq = avctx->priv_data; 00232 00233 seq->frame.reference = 1; 00234 seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00235 if (avctx->reget_buffer(avctx, &seq->frame)) { 00236 av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n"); 00237 return -1; 00238 } 00239 00240 if (seqvideo_decode(seq, buf, buf_size)) 00241 return AVERROR_INVALIDDATA; 00242 00243 *data_size = sizeof(AVFrame); 00244 *(AVFrame *)data = seq->frame; 00245 00246 return buf_size; 00247 } 00248 00249 static av_cold int seqvideo_decode_end(AVCodecContext *avctx) 00250 { 00251 SeqVideoContext *seq = avctx->priv_data; 00252 00253 if (seq->frame.data[0]) 00254 avctx->release_buffer(avctx, &seq->frame); 00255 00256 return 0; 00257 } 00258 00259 AVCodec ff_tiertexseqvideo_decoder = { 00260 "tiertexseqvideo", 00261 AVMEDIA_TYPE_VIDEO, 00262 CODEC_ID_TIERTEXSEQVIDEO, 00263 sizeof(SeqVideoContext), 00264 seqvideo_decode_init, 00265 NULL, 00266 seqvideo_decode_end, 00267 seqvideo_decode_frame, 00268 CODEC_CAP_DR1, 00269 .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), 00270 };