2 * Tiertex Limited SEQ Video Decoder
3 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
5 * This file is part of FFmpeg.
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.
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.
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
24 * Tiertex Limited SEQ video decoder
28 #define ALT_BITSTREAM_READER_LE
29 #include "bitstream.h"
32 typedef struct SeqVideoContext
{
33 AVCodecContext
*avctx
;
35 unsigned int palette
[256];
36 unsigned char block
[8 * 8];
40 static const unsigned char *seq_unpack_rle_block(const unsigned char *src
, unsigned char *dst
, int dst_size
)
46 /* get the rle codes (at most 64 bytes) */
47 init_get_bits(&gb
, src
, 64 * 8);
48 for (i
= 0, sz
= 0; i
< 64 && sz
< dst_size
; i
++) {
49 code_table
[i
] = get_sbits(&gb
, 4);
50 sz
+= FFABS(code_table
[i
]);
52 src
+= (get_bits_count(&gb
) + 7) / 8;
54 /* do the rle unpacking */
55 for (i
= 0; i
< 64 && dst_size
> 0; i
++) {
59 memset(dst
, *src
++, FFMIN(len
, dst_size
));
61 memcpy(dst
, src
, FFMIN(len
, dst_size
));
70 static const unsigned char *seq_decode_op1(SeqVideoContext
*seq
, const unsigned char *src
, unsigned char *dst
)
72 const unsigned char *color_table
;
80 src
= seq_unpack_rle_block(src
, seq
->block
, sizeof(seq
->block
));
81 for (b
= 0; b
< 8; b
++) {
82 memcpy(dst
, &seq
->block
[b
* 8], 8);
83 dst
+= seq
->frame
.linesize
[0];
87 src
= seq_unpack_rle_block(src
, seq
->block
, sizeof(seq
->block
));
88 for (i
= 0; i
< 8; i
++) {
89 for (b
= 0; b
< 8; b
++)
90 dst
[b
* seq
->frame
.linesize
[0]] = seq
->block
[i
* 8 + b
];
98 bits
= ff_log2_tab
[len
- 1] + 1;
99 init_get_bits(&gb
, src
, bits
* 8 * 8); src
+= bits
* 8;
100 for (b
= 0; b
< 8; b
++) {
101 for (i
= 0; i
< 8; i
++)
102 dst
[i
] = color_table
[get_bits(&gb
, bits
)];
103 dst
+= seq
->frame
.linesize
[0];
110 static const unsigned char *seq_decode_op2(SeqVideoContext
*seq
, const unsigned char *src
, unsigned char *dst
)
114 for (i
= 0; i
< 8; i
++) {
117 dst
+= seq
->frame
.linesize
[0];
123 static const unsigned char *seq_decode_op3(SeqVideoContext
*seq
, const unsigned char *src
, unsigned char *dst
)
129 offset
= ((pos
>> 3) & 7) * seq
->frame
.linesize
[0] + (pos
& 7);
130 dst
[offset
] = *src
++;
131 } while (!(pos
& 0x80));
136 static void seqvideo_decode(SeqVideoContext
*seq
, const unsigned char *data
, int data_size
)
139 int flags
, i
, j
, x
, y
, op
;
146 for (i
= 0; i
< 256; i
++) {
147 for (j
= 0; j
< 3; j
++, data
++)
148 c
[j
] = (*data
<< 2) | (*data
>> 4);
149 seq
->palette
[i
] = AV_RB24(c
);
151 memcpy(seq
->frame
.data
[1], seq
->palette
, sizeof(seq
->palette
));
152 seq
->frame
.palette_has_changed
= 1;
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);
163 data
= seq_decode_op1(seq
, data
, dst
);
166 data
= seq_decode_op2(seq
, data
, dst
);
169 data
= seq_decode_op3(seq
, data
, dst
);
176 static av_cold
int seqvideo_decode_init(AVCodecContext
*avctx
)
178 SeqVideoContext
*seq
= avctx
->priv_data
;
181 avctx
->pix_fmt
= PIX_FMT_PAL8
;
183 seq
->frame
.data
[0] = NULL
;
188 static av_cold
int seqvideo_decode_frame(AVCodecContext
*avctx
,
189 void *data
, int *data_size
,
190 const uint8_t *buf
, int buf_size
)
193 SeqVideoContext
*seq
= avctx
->priv_data
;
195 seq
->frame
.reference
= 1;
196 seq
->frame
.buffer_hints
= FF_BUFFER_HINTS_VALID
| FF_BUFFER_HINTS_PRESERVE
| FF_BUFFER_HINTS_REUSABLE
;
197 if (avctx
->reget_buffer(avctx
, &seq
->frame
)) {
198 av_log(seq
->avctx
, AV_LOG_ERROR
, "tiertexseqvideo: reget_buffer() failed\n");
202 seqvideo_decode(seq
, buf
, buf_size
);
204 *data_size
= sizeof(AVFrame
);
205 *(AVFrame
*)data
= seq
->frame
;
210 static int seqvideo_decode_end(AVCodecContext
*avctx
)
212 SeqVideoContext
*seq
= avctx
->priv_data
;
214 if (seq
->frame
.data
[0])
215 avctx
->release_buffer(avctx
, &seq
->frame
);
220 AVCodec tiertexseqvideo_decoder
= {
223 CODEC_ID_TIERTEXSEQVIDEO
,
224 sizeof(SeqVideoContext
),
225 seqvideo_decode_init
,
228 seqvideo_decode_frame
,
230 .long_name
= NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"),