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, unsigned char *dst, int dst_size) 00039 { 00040 int i, len, sz; 00041 GetBitContext gb; 00042 int code_table[64]; 00043 00044 /* get the rle codes (at most 64 bytes) */ 00045 init_get_bits(&gb, src, 64 * 8); 00046 for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { 00047 code_table[i] = get_sbits(&gb, 4); 00048 sz += FFABS(code_table[i]); 00049 } 00050 src += (get_bits_count(&gb) + 7) / 8; 00051 00052 /* do the rle unpacking */ 00053 for (i = 0; i < 64 && dst_size > 0; i++) { 00054 len = code_table[i]; 00055 if (len < 0) { 00056 len = -len; 00057 memset(dst, *src++, FFMIN(len, dst_size)); 00058 } else { 00059 memcpy(dst, src, FFMIN(len, dst_size)); 00060 src += len; 00061 } 00062 dst += len; 00063 dst_size -= len; 00064 } 00065 return src; 00066 } 00067 00068 static const unsigned char *seq_decode_op1(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) 00069 { 00070 const unsigned char *color_table; 00071 int b, i, len, bits; 00072 GetBitContext gb; 00073 unsigned char block[8 * 8]; 00074 00075 len = *src++; 00076 if (len & 0x80) { 00077 switch (len & 3) { 00078 case 1: 00079 src = seq_unpack_rle_block(src, block, sizeof(block)); 00080 for (b = 0; b < 8; b++) { 00081 memcpy(dst, &block[b * 8], 8); 00082 dst += seq->frame.linesize[0]; 00083 } 00084 break; 00085 case 2: 00086 src = seq_unpack_rle_block(src, block, sizeof(block)); 00087 for (i = 0; i < 8; i++) { 00088 for (b = 0; b < 8; b++) 00089 dst[b * seq->frame.linesize[0]] = block[i * 8 + b]; 00090 ++dst; 00091 } 00092 break; 00093 } 00094 } else { 00095 color_table = src; 00096 src += len; 00097 bits = ff_log2_tab[len - 1] + 1; 00098 init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; 00099 for (b = 0; b < 8; b++) { 00100 for (i = 0; i < 8; i++) 00101 dst[i] = color_table[get_bits(&gb, bits)]; 00102 dst += seq->frame.linesize[0]; 00103 } 00104 } 00105 00106 return src; 00107 } 00108 00109 static const unsigned char *seq_decode_op2(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) 00110 { 00111 int i; 00112 00113 for (i = 0; i < 8; i++) { 00114 memcpy(dst, src, 8); 00115 src += 8; 00116 dst += seq->frame.linesize[0]; 00117 } 00118 00119 return src; 00120 } 00121 00122 static const unsigned char *seq_decode_op3(SeqVideoContext *seq, const unsigned char *src, unsigned char *dst) 00123 { 00124 int pos, offset; 00125 00126 do { 00127 pos = *src++; 00128 offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); 00129 dst[offset] = *src++; 00130 } while (!(pos & 0x80)); 00131 00132 return src; 00133 } 00134 00135 static void seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) 00136 { 00137 GetBitContext gb; 00138 int flags, i, j, x, y, op; 00139 unsigned char c[3]; 00140 unsigned char *dst; 00141 uint32_t *palette; 00142 00143 flags = *data++; 00144 00145 if (flags & 1) { 00146 palette = (uint32_t *)seq->frame.data[1]; 00147 for (i = 0; i < 256; i++) { 00148 for (j = 0; j < 3; j++, data++) 00149 c[j] = (*data << 2) | (*data >> 4); 00150 palette[i] = AV_RB24(c); 00151 } 00152 seq->frame.palette_has_changed = 1; 00153 } 00154 00155 if (flags & 2) { 00156 init_get_bits(&gb, data, 128 * 8); data += 128; 00157 for (y = 0; y < 128; y += 8) 00158 for (x = 0; x < 256; x += 8) { 00159 dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x]; 00160 op = get_bits(&gb, 2); 00161 switch (op) { 00162 case 1: 00163 data = seq_decode_op1(seq, data, dst); 00164 break; 00165 case 2: 00166 data = seq_decode_op2(seq, data, dst); 00167 break; 00168 case 3: 00169 data = seq_decode_op3(seq, data, dst); 00170 break; 00171 } 00172 } 00173 } 00174 } 00175 00176 static av_cold int seqvideo_decode_init(AVCodecContext *avctx) 00177 { 00178 SeqVideoContext *seq = avctx->priv_data; 00179 00180 seq->avctx = avctx; 00181 avctx->pix_fmt = PIX_FMT_PAL8; 00182 00183 seq->frame.data[0] = NULL; 00184 00185 return 0; 00186 } 00187 00188 static int seqvideo_decode_frame(AVCodecContext *avctx, 00189 void *data, int *data_size, 00190 AVPacket *avpkt) 00191 { 00192 const uint8_t *buf = avpkt->data; 00193 int buf_size = avpkt->size; 00194 00195 SeqVideoContext *seq = avctx->priv_data; 00196 00197 seq->frame.reference = 1; 00198 seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00199 if (avctx->reget_buffer(avctx, &seq->frame)) { 00200 av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n"); 00201 return -1; 00202 } 00203 00204 seqvideo_decode(seq, buf, buf_size); 00205 00206 *data_size = sizeof(AVFrame); 00207 *(AVFrame *)data = seq->frame; 00208 00209 return buf_size; 00210 } 00211 00212 static av_cold int seqvideo_decode_end(AVCodecContext *avctx) 00213 { 00214 SeqVideoContext *seq = avctx->priv_data; 00215 00216 if (seq->frame.data[0]) 00217 avctx->release_buffer(avctx, &seq->frame); 00218 00219 return 0; 00220 } 00221 00222 AVCodec ff_tiertexseqvideo_decoder = { 00223 "tiertexseqvideo", 00224 AVMEDIA_TYPE_VIDEO, 00225 CODEC_ID_TIERTEXSEQVIDEO, 00226 sizeof(SeqVideoContext), 00227 seqvideo_decode_init, 00228 NULL, 00229 seqvideo_decode_end, 00230 seqvideo_decode_frame, 00231 CODEC_CAP_DR1, 00232 .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), 00233 };