2 * Chronomaster DFA Video Decoder
3 * Copyright (c) 2011 Konstantin Shishkov
4 * based on work by Vladimir "VAG" Gneushev
6 * This file is part of Libav.
8 * Libav is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * Libav is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with Libav; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "bytestream.h"
29 #include "libavutil/imgutils.h"
30 #include "libavutil/mem.h"
32 typedef struct DfaContext
{
37 static av_cold
int dfa_decode_init(AVCodecContext
*avctx
)
39 DfaContext
*s
= avctx
->priv_data
;
42 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
44 if ((ret
= av_image_check_size(avctx
->width
, avctx
->height
, 0, avctx
)) < 0)
47 s
->frame_buf
= av_mallocz(avctx
->width
* avctx
->height
);
49 return AVERROR(ENOMEM
);
54 static int decode_copy(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
56 const int size
= width
* height
;
58 if (bytestream2_get_buffer(gb
, frame
, size
) != size
)
59 return AVERROR_INVALIDDATA
;
63 static int decode_tsw1(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
65 const uint8_t *frame_start
= frame
;
66 const uint8_t *frame_end
= frame
+ width
* height
;
67 int mask
= 0x10000, bitbuf
= 0;
68 int v
, count
, segments
;
71 segments
= bytestream2_get_le32(gb
);
72 offset
= bytestream2_get_le32(gb
);
73 if (frame_end
- frame
<= offset
)
74 return AVERROR_INVALIDDATA
;
77 if (bytestream2_get_bytes_left(gb
) < 2)
78 return AVERROR_INVALIDDATA
;
79 if (mask
== 0x10000) {
80 bitbuf
= bytestream2_get_le16u(gb
);
83 if (frame_end
- frame
< 2)
84 return AVERROR_INVALIDDATA
;
86 v
= bytestream2_get_le16(gb
);
87 offset
= (v
& 0x1FFF) << 1;
88 count
= ((v
>> 13) + 2) << 1;
89 if (frame
- frame_start
< offset
|| frame_end
- frame
< count
)
90 return AVERROR_INVALIDDATA
;
91 av_memcpy_backptr(frame
, offset
, count
);
94 *frame
++ = bytestream2_get_byte(gb
);
95 *frame
++ = bytestream2_get_byte(gb
);
103 static int decode_dsw1(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
105 const uint8_t *frame_start
= frame
;
106 const uint8_t *frame_end
= frame
+ width
* height
;
107 int mask
= 0x10000, bitbuf
= 0;
108 int v
, offset
, count
, segments
;
110 segments
= bytestream2_get_le16(gb
);
112 if (bytestream2_get_bytes_left(gb
) < 2)
113 return AVERROR_INVALIDDATA
;
114 if (mask
== 0x10000) {
115 bitbuf
= bytestream2_get_le16u(gb
);
118 if (frame_end
- frame
< 2)
119 return AVERROR_INVALIDDATA
;
121 v
= bytestream2_get_le16(gb
);
122 offset
= (v
& 0x1FFF) << 1;
123 count
= ((v
>> 13) + 2) << 1;
124 if (frame
- frame_start
< offset
|| frame_end
- frame
< count
)
125 return AVERROR_INVALIDDATA
;
126 av_memcpy_backptr(frame
, offset
, count
);
128 } else if (bitbuf
& (mask
<< 1)) {
129 frame
+= bytestream2_get_le16(gb
);
131 *frame
++ = bytestream2_get_byte(gb
);
132 *frame
++ = bytestream2_get_byte(gb
);
140 static int decode_dds1(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
142 const uint8_t *frame_start
= frame
;
143 const uint8_t *frame_end
= frame
+ width
* height
;
144 int mask
= 0x10000, bitbuf
= 0;
145 int i
, v
, offset
, count
, segments
;
147 if ((width
| height
) & 1)
148 return AVERROR_INVALIDDATA
;
149 segments
= bytestream2_get_le16(gb
);
151 if (bytestream2_get_bytes_left(gb
) < 2)
152 return AVERROR_INVALIDDATA
;
153 if (mask
== 0x10000) {
154 bitbuf
= bytestream2_get_le16u(gb
);
159 v
= bytestream2_get_le16(gb
);
160 offset
= (v
& 0x1FFF) << 2;
161 count
= ((v
>> 13) + 2) << 1;
162 if (frame
- frame_start
< offset
|| frame_end
- frame
< count
*2 + width
)
163 return AVERROR_INVALIDDATA
;
164 for (i
= 0; i
< count
; i
++) {
165 frame
[0] = frame
[1] =
166 frame
[width
] = frame
[width
+ 1] = frame
[-offset
];
170 } else if (bitbuf
& (mask
<< 1)) {
171 v
= bytestream2_get_le16(gb
)*2;
172 if (frame
- frame_end
< v
)
173 return AVERROR_INVALIDDATA
;
176 if (width
< 4 || frame_end
- frame
< width
+ 4)
177 return AVERROR_INVALIDDATA
;
178 frame
[0] = frame
[1] =
179 frame
[width
] = frame
[width
+ 1] = bytestream2_get_byte(gb
);
181 frame
[0] = frame
[1] =
182 frame
[width
] = frame
[width
+ 1] = bytestream2_get_byte(gb
);
191 static int decode_bdlt(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
194 int count
, lines
, segments
;
196 count
= bytestream2_get_le16(gb
);
198 return AVERROR_INVALIDDATA
;
199 frame
+= width
* count
;
200 lines
= bytestream2_get_le16(gb
);
201 if (count
+ lines
> height
)
202 return AVERROR_INVALIDDATA
;
205 if (bytestream2_get_bytes_left(gb
) < 1)
206 return AVERROR_INVALIDDATA
;
209 segments
= bytestream2_get_byteu(gb
);
211 if (frame
- line_ptr
<= bytestream2_peek_byte(gb
))
212 return AVERROR_INVALIDDATA
;
213 line_ptr
+= bytestream2_get_byte(gb
);
214 count
= (int8_t)bytestream2_get_byte(gb
);
216 if (frame
- line_ptr
< count
)
217 return AVERROR_INVALIDDATA
;
218 if (bytestream2_get_buffer(gb
, line_ptr
, count
) != count
)
219 return AVERROR_INVALIDDATA
;
222 if (frame
- line_ptr
< count
)
223 return AVERROR_INVALIDDATA
;
224 memset(line_ptr
, bytestream2_get_byte(gb
), count
);
233 static int decode_wdlt(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
235 const uint8_t *frame_end
= frame
+ width
* height
;
237 int count
, i
, v
, lines
, segments
;
240 lines
= bytestream2_get_le16(gb
);
242 return AVERROR_INVALIDDATA
;
245 if (bytestream2_get_bytes_left(gb
) < 2)
246 return AVERROR_INVALIDDATA
;
247 segments
= bytestream2_get_le16u(gb
);
248 while ((segments
& 0xC000) == 0xC000) {
249 unsigned skip_lines
= -(int16_t)segments
;
250 unsigned delta
= -((int16_t)segments
* width
);
251 if (frame_end
- frame
<= delta
|| y
+ lines
+ skip_lines
> height
)
252 return AVERROR_INVALIDDATA
;
255 segments
= bytestream2_get_le16(gb
);
257 if (segments
& 0x8000) {
258 frame
[width
- 1] = segments
& 0xFF;
259 segments
= bytestream2_get_le16(gb
);
262 if (frame_end
- frame
< width
)
263 return AVERROR_INVALIDDATA
;
267 if (frame
- line_ptr
<= bytestream2_peek_byte(gb
))
268 return AVERROR_INVALIDDATA
;
269 line_ptr
+= bytestream2_get_byte(gb
);
270 count
= (int8_t)bytestream2_get_byte(gb
);
272 if (frame
- line_ptr
< count
* 2)
273 return AVERROR_INVALIDDATA
;
274 if (bytestream2_get_buffer(gb
, line_ptr
, count
* 2) != count
* 2)
275 return AVERROR_INVALIDDATA
;
276 line_ptr
+= count
* 2;
279 if (frame
- line_ptr
< count
* 2)
280 return AVERROR_INVALIDDATA
;
281 v
= bytestream2_get_le16(gb
);
282 for (i
= 0; i
< count
; i
++)
283 bytestream_put_le16(&line_ptr
, v
);
291 static int decode_tdlt(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
293 const uint8_t *frame_end
= frame
+ width
* height
;
294 int segments
= bytestream2_get_le32(gb
);
298 if (bytestream2_get_bytes_left(gb
) < 2)
299 return AVERROR_INVALIDDATA
;
300 copy
= bytestream2_get_byteu(gb
) * 2;
301 skip
= bytestream2_get_byteu(gb
) * 2;
302 if (frame_end
- frame
< copy
+ skip
||
303 bytestream2_get_bytes_left(gb
) < copy
)
304 return AVERROR_INVALIDDATA
;
306 bytestream2_get_buffer(gb
, frame
, copy
);
313 static int decode_blck(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
)
315 memset(frame
, 0, width
* height
);
320 typedef int (*chunk_decoder
)(GetByteContext
*gb
, uint8_t *frame
, int width
, int height
);
322 static const chunk_decoder decoder
[8] = {
323 decode_copy
, decode_tsw1
, decode_bdlt
, decode_wdlt
,
324 decode_tdlt
, decode_dsw1
, decode_blck
, decode_dds1
,
327 static const char * const chunk_name
[8] = {
328 "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
331 static int dfa_decode_frame(AVCodecContext
*avctx
,
332 void *data
, int *got_frame
,
335 AVFrame
*frame
= data
;
336 DfaContext
*s
= avctx
->priv_data
;
338 const uint8_t *buf
= avpkt
->data
;
339 uint32_t chunk_type
, chunk_size
;
344 if ((ret
= ff_get_buffer(avctx
, frame
, 0))) {
345 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
349 bytestream2_init(&gb
, avpkt
->data
, avpkt
->size
);
350 while (bytestream2_get_bytes_left(&gb
) > 0) {
351 bytestream2_skip(&gb
, 4);
352 chunk_size
= bytestream2_get_le32(&gb
);
353 chunk_type
= bytestream2_get_le32(&gb
);
356 if (chunk_type
== 1) {
357 pal_elems
= FFMIN(chunk_size
/ 3, 256);
358 for (i
= 0; i
< pal_elems
; i
++) {
359 s
->pal
[i
] = bytestream2_get_be24(&gb
) << 2;
360 s
->pal
[i
] |= (s
->pal
[i
] >> 6) & 0x333;
362 frame
->palette_has_changed
= 1;
363 } else if (chunk_type
<= 9) {
364 if (decoder
[chunk_type
- 2](&gb
, s
->frame_buf
, avctx
->width
, avctx
->height
)) {
365 av_log(avctx
, AV_LOG_ERROR
, "Error decoding %s chunk\n",
366 chunk_name
[chunk_type
- 2]);
367 return AVERROR_INVALIDDATA
;
370 av_log(avctx
, AV_LOG_WARNING
,
371 "Ignoring unknown chunk type %"PRIu32
"\n",
378 dst
= frame
->data
[0];
379 for (i
= 0; i
< avctx
->height
; i
++) {
380 memcpy(dst
, buf
, avctx
->width
);
381 dst
+= frame
->linesize
[0];
384 memcpy(frame
->data
[1], s
->pal
, sizeof(s
->pal
));
391 static av_cold
int dfa_decode_end(AVCodecContext
*avctx
)
393 DfaContext
*s
= avctx
->priv_data
;
395 av_freep(&s
->frame_buf
);
400 AVCodec ff_dfa_decoder
= {
402 .long_name
= NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
403 .type
= AVMEDIA_TYPE_VIDEO
,
404 .id
= AV_CODEC_ID_DFA
,
405 .priv_data_size
= sizeof(DfaContext
),
406 .init
= dfa_decode_init
,
407 .close
= dfa_decode_end
,
408 .decode
= dfa_decode_frame
,
409 .capabilities
= AV_CODEC_CAP_DR1
,