comparison tiertexseqv.c @ 4006:986d6651a452 libavcodec

support for Tiertex .seq files demuxing/video decoding, by Gregory Montoir %cyx A users P sourceforge P net%
author bcoudurier
date Thu, 12 Oct 2006 12:02:58 +0000
parents
children 66ef3690d108
comparison
equal deleted inserted replaced
4005:3ccdff1e5221 4006:986d6651a452
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 tiertexseqv.c
24 * Tiertex Limited SEQ video decoder
25 */
26
27 #include "avcodec.h"
28 #include "common.h"
29 #define ALT_BITSTREAM_READER_LE
30 #include "bitstream.h"
31
32
33 typedef struct SeqVideoContext {
34 AVCodecContext *avctx;
35 AVFrame frame;
36 unsigned int palette[256];
37 unsigned char block[8 * 8];
38 } SeqVideoContext;
39
40
41 static unsigned char *seq_unpack_rle_block(unsigned char *src, 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 (at most 64 bytes) */
48 init_get_bits(&gb, src, 64 * 8);
49 for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) {
50 code_table[i] = get_sbits(&gb, 4);
51 sz += FFABS(code_table[i]);
52 }
53 src += (get_bits_count(&gb) + 7) / 8;
54
55 /* do the rle unpacking */
56 for (i = 0; i < 64 && dst_size > 0; i++) {
57 len = code_table[i];
58 if (len < 0) {
59 len = -len;
60 memset(dst, *src++, FFMIN(len, dst_size));
61 } else {
62 memcpy(dst, src, FFMIN(len, dst_size));
63 src += len;
64 }
65 dst += len;
66 dst_size -= len;
67 }
68 return src;
69 }
70
71 static unsigned char *seq_decode_op1(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
72 {
73 unsigned char *color_table;
74 int b, i, len, bits;
75 GetBitContext gb;
76
77 len = *src++;
78 if (len & 0x80) {
79 switch (len & 3) {
80 case 1:
81 src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block));
82 for (b = 0; b < 8; b++) {
83 memcpy(dst, &seq->block[b * 8], 8);
84 dst += seq->frame.linesize[0];
85 }
86 break;
87 case 2:
88 src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block));
89 for (i = 0; i < 8; i++) {
90 for (b = 0; b < 8; b++)
91 dst[b * seq->frame.linesize[0]] = seq->block[i * 8 + b];
92 ++dst;
93 }
94 break;
95 }
96 } else {
97 color_table = src;
98 src += len;
99 bits = ff_log2_tab[len - 1] + 1;
100 init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8;
101 for (b = 0; b < 8; b++) {
102 for (i = 0; i < 8; i++)
103 dst[i] = color_table[get_bits(&gb, bits)];
104 dst += seq->frame.linesize[0];
105 }
106 }
107
108 return src;
109 }
110
111 static unsigned char *seq_decode_op2(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
112 {
113 int i;
114
115 for (i = 0; i < 8; i++) {
116 memcpy(dst, src, 8);
117 src += 8;
118 dst += seq->frame.linesize[0];
119 }
120
121 return src;
122 }
123
124 static unsigned char *seq_decode_op3(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
125 {
126 int pos, offset;
127
128 do {
129 pos = *src++;
130 offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7);
131 dst[offset] = *src++;
132 } while (!(pos & 0x80));
133
134 return src;
135 }
136
137 static void seqvideo_decode(SeqVideoContext *seq, unsigned char *data, int data_size)
138 {
139 GetBitContext gb;
140 int flags, i, j, x, y, op;
141 unsigned char c[3];
142 unsigned char *dst;
143
144 flags = *data++;
145
146 if (flags & 1) {
147 for (i = 0; i < 256; i++) {
148 for (j = 0; j < 3; j++, data++)
149 c[j] = (*data << 2) | (*data >> 4);
150 seq->palette[i] = (c[0] << 16) | (c[1] << 8) | c[2];
151 }
152 memcpy(seq->frame.data[1], seq->palette, sizeof(seq->palette));
153 seq->frame.palette_has_changed = 1;
154 }
155
156 if (flags & 2) {
157 init_get_bits(&gb, data, 128 * 8); data += 128;
158 for (y = 0; y < 128; y += 8)
159 for (x = 0; x < 256; x += 8) {
160 dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x];
161 op = get_bits(&gb, 2);
162 switch (op) {
163 case 1:
164 data = seq_decode_op1(seq, data, dst);
165 break;
166 case 2:
167 data = seq_decode_op2(seq, data, dst);
168 break;
169 case 3:
170 data = seq_decode_op3(seq, data, dst);
171 break;
172 }
173 }
174 }
175 }
176
177 static int seqvideo_decode_init(AVCodecContext *avctx)
178 {
179 SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
180
181 seq->avctx = avctx;
182 avctx->pix_fmt = PIX_FMT_PAL8;
183 avctx->has_b_frames = 0;
184
185 seq->frame.data[0] = NULL;
186
187 return 0;
188 }
189
190 static int seqvideo_decode_frame(AVCodecContext *avctx,
191 void *data, int *data_size,
192 uint8_t *buf, int buf_size)
193 {
194
195 SeqVideoContext *seq = (SeqVideoContext *)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
212 static int seqvideo_decode_end(AVCodecContext *avctx)
213 {
214 SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
215
216 if (seq->frame.data[0])
217 avctx->release_buffer(avctx, &seq->frame);
218
219 return 0;
220 }
221
222 AVCodec tiertexseqvideo_decoder = {
223 "tiertexseqvideo",
224 CODEC_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 };