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 BITSTREAM_READER_LE
33 typedef struct SeqVideoContext
{
34 AVCodecContext
*avctx
;
39 static const unsigned char *seq_unpack_rle_block(const unsigned char *src
,
40 const unsigned char *src_end
,
41 unsigned char *dst
, int dst_size
)
47 /* get the rle codes */
48 init_get_bits(&gb
, src
, (src_end
- src
) * 8);
49 for (i
= 0, sz
= 0; i
< 64 && sz
< dst_size
; i
++) {
50 if (get_bits_left(&gb
) < 4)
52 code_table
[i
] = get_sbits(&gb
, 4);
53 sz
+= FFABS(code_table
[i
]);
55 src
+= (get_bits_count(&gb
) + 7) / 8;
57 /* do the rle unpacking */
58 for (i
= 0; i
< 64 && dst_size
> 0; i
++) {
62 if (src_end
- src
< 1)
64 memset(dst
, *src
++, FFMIN(len
, dst_size
));
66 if (src_end
- src
< len
)
68 memcpy(dst
, src
, FFMIN(len
, dst_size
));
77 static const unsigned char *seq_decode_op1(SeqVideoContext
*seq
,
78 const unsigned char *src
,
79 const unsigned char *src_end
,
82 const unsigned char *color_table
;
85 unsigned char block
[8 * 8];
87 if (src_end
- src
< 1)
93 src
= seq_unpack_rle_block(src
, src_end
, block
, sizeof(block
));
94 for (b
= 0; b
< 8; b
++) {
95 memcpy(dst
, &block
[b
* 8], 8);
96 dst
+= seq
->frame
->linesize
[0];
100 src
= seq_unpack_rle_block(src
, src_end
, block
, sizeof(block
));
101 for (i
= 0; i
< 8; i
++) {
102 for (b
= 0; b
< 8; b
++)
103 dst
[b
* seq
->frame
->linesize
[0]] = block
[i
* 8 + b
];
111 bits
= ff_log2_tab
[len
- 1] + 1;
112 if (src_end
- src
< len
+ 8 * bits
)
116 init_get_bits(&gb
, src
, bits
* 8 * 8); src
+= bits
* 8;
117 for (b
= 0; b
< 8; b
++) {
118 for (i
= 0; i
< 8; i
++)
119 dst
[i
] = color_table
[get_bits(&gb
, bits
)];
120 dst
+= seq
->frame
->linesize
[0];
127 static const unsigned char *seq_decode_op2(SeqVideoContext
*seq
,
128 const unsigned char *src
,
129 const unsigned char *src_end
,
134 if (src_end
- src
< 8 * 8)
137 for (i
= 0; i
< 8; i
++) {
140 dst
+= seq
->frame
->linesize
[0];
146 static const unsigned char *seq_decode_op3(SeqVideoContext
*seq
,
147 const unsigned char *src
,
148 const unsigned char *src_end
,
154 if (src_end
- src
< 2)
157 offset
= ((pos
>> 3) & 7) * seq
->frame
->linesize
[0] + (pos
& 7);
158 dst
[offset
] = *src
++;
159 } while (!(pos
& 0x80));
164 static int seqvideo_decode(SeqVideoContext
*seq
, const unsigned char *data
, int data_size
)
166 const unsigned char *data_end
= data
+ data_size
;
168 int flags
, i
, j
, x
, y
, op
;
176 palette
= (uint32_t *)seq
->frame
->data
[1];
177 if (data_end
- data
< 256 * 3)
178 return AVERROR_INVALIDDATA
;
179 for (i
= 0; i
< 256; i
++) {
180 for (j
= 0; j
< 3; j
++, data
++)
181 c
[j
] = (*data
<< 2) | (*data
>> 4);
182 palette
[i
] = 0xFFU
<< 24 | AV_RB24(c
);
184 seq
->frame
->palette_has_changed
= 1;
188 if (data_end
- data
< 128)
189 return AVERROR_INVALIDDATA
;
190 init_get_bits(&gb
, data
, 128 * 8); data
+= 128;
191 for (y
= 0; y
< 128; y
+= 8)
192 for (x
= 0; x
< 256; x
+= 8) {
193 dst
= &seq
->frame
->data
[0][y
* seq
->frame
->linesize
[0] + x
];
194 op
= get_bits(&gb
, 2);
197 data
= seq_decode_op1(seq
, data
, data_end
, dst
);
200 data
= seq_decode_op2(seq
, data
, data_end
, dst
);
203 data
= seq_decode_op3(seq
, data
, data_end
, dst
);
207 return AVERROR_INVALIDDATA
;
213 static av_cold
int seqvideo_decode_init(AVCodecContext
*avctx
)
215 SeqVideoContext
*seq
= avctx
->priv_data
;
218 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
220 seq
->frame
= av_frame_alloc();
222 return AVERROR(ENOMEM
);
227 static int seqvideo_decode_frame(AVCodecContext
*avctx
,
228 void *data
, int *got_frame
,
231 const uint8_t *buf
= avpkt
->data
;
232 int buf_size
= avpkt
->size
;
235 SeqVideoContext
*seq
= avctx
->priv_data
;
237 if ((ret
= ff_reget_buffer(avctx
, seq
->frame
)) < 0)
240 if (seqvideo_decode(seq
, buf
, buf_size
))
241 return AVERROR_INVALIDDATA
;
243 if ((ret
= av_frame_ref(data
, seq
->frame
)) < 0)
250 static av_cold
int seqvideo_decode_end(AVCodecContext
*avctx
)
252 SeqVideoContext
*seq
= avctx
->priv_data
;
254 av_frame_free(&seq
->frame
);
259 AVCodec ff_tiertexseqvideo_decoder
= {
260 .name
= "tiertexseqvideo",
261 .long_name
= NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"),
262 .type
= AVMEDIA_TYPE_VIDEO
,
263 .id
= AV_CODEC_ID_TIERTEXSEQVIDEO
,
264 .priv_data_size
= sizeof(SeqVideoContext
),
265 .init
= seqvideo_decode_init
,
266 .close
= seqvideo_decode_end
,
267 .decode
= seqvideo_decode_frame
,
268 .capabilities
= CODEC_CAP_DR1
,