1 /*
2 * Chronomaster DFA Video Decoder
3 * Copyright (c) 2011 Konstantin Shishkov
4 * based on work by Vladimir "VAG" Gneushev
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg 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.
12 *
13 * FFmpeg 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.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <inttypes.h>
24
25 #include "avcodec.h"
26 #include "bytestream.h"
27 #include "codec_internal.h"
28 #include "internal.h"
29
30 #include "libavutil/avassert.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/mem.h"
33
34 typedef struct DfaContext {
35 uint32_t pal[256];
36 uint8_t *frame_buf;
37 } DfaContext;
38
dfa_decode_init(AVCodecContext * avctx)39 static av_cold int dfa_decode_init(AVCodecContext *avctx)
40 {
41 DfaContext *s = avctx->priv_data;
42
43 avctx->pix_fmt = AV_PIX_FMT_PAL8;
44
45 if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16))
46 return AVERROR_INVALIDDATA;
47
48 av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0);
49
50 s->frame_buf = av_mallocz(avctx->width * avctx->height);
51 if (!s->frame_buf)
52 return AVERROR(ENOMEM);
53
54 return 0;
55 }
56
decode_copy(GetByteContext * gb,uint8_t * frame,int width,int height)57 static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height)
58 {
59 const int size = width * height;
60
61 if (bytestream2_get_buffer(gb, frame, size) != size)
62 return AVERROR_INVALIDDATA;
63 return 0;
64 }
65
decode_tsw1(GetByteContext * gb,uint8_t * frame,int width,int height)66 static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
67 {
68 const uint8_t *frame_start = frame;
69 const uint8_t *frame_end = frame + width * height;
70 int mask = 0x10000, bitbuf = 0;
71 int v, count;
72 unsigned segments;
73 unsigned offset;
74
75 segments = bytestream2_get_le32(gb);
76 offset = bytestream2_get_le32(gb);
77 if (segments == 0 && offset == frame_end - frame)
78 return 0; // skip frame
79 if (frame_end - frame <= offset)
80 return AVERROR_INVALIDDATA;
81 frame += offset;
82 while (segments--) {
83 if (bytestream2_get_bytes_left(gb) < 2)
84 return AVERROR_INVALIDDATA;
85 if (mask == 0x10000) {
86 bitbuf = bytestream2_get_le16u(gb);
87 mask = 1;
88 }
89 if (frame_end - frame < 2)
90 return AVERROR_INVALIDDATA;
91 if (bitbuf & mask) {
92 v = bytestream2_get_le16(gb);
93 offset = (v & 0x1FFF) << 1;
94 count = ((v >> 13) + 2) << 1;
95 if (frame - frame_start < offset || frame_end - frame < count)
96 return AVERROR_INVALIDDATA;
97 av_memcpy_backptr(frame, offset, count);
98 frame += count;
99 } else {
100 *frame++ = bytestream2_get_byte(gb);
101 *frame++ = bytestream2_get_byte(gb);
102 }
103 mask <<= 1;
104 }
105
106 return 0;
107 }
108
decode_dsw1(GetByteContext * gb,uint8_t * frame,int width,int height)109 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
110 {
111 const uint8_t *frame_start = frame;
112 const uint8_t *frame_end = frame + width * height;
113 int mask = 0x10000, bitbuf = 0;
114 int v, offset, count, segments;
115
116 segments = bytestream2_get_le16(gb);
117 while (segments--) {
118 if (bytestream2_get_bytes_left(gb) < 2)
119 return AVERROR_INVALIDDATA;
120 if (mask == 0x10000) {
121 bitbuf = bytestream2_get_le16u(gb);
122 mask = 1;
123 }
124 if (frame_end - frame < 2)
125 return AVERROR_INVALIDDATA;
126 if (bitbuf & mask) {
127 v = bytestream2_get_le16(gb);
128 offset = (v & 0x1FFF) << 1;
129 count = ((v >> 13) + 2) << 1;
130 if (frame - frame_start < offset || frame_end - frame < count)
131 return AVERROR_INVALIDDATA;
132 av_memcpy_backptr(frame, offset, count);
133 frame += count;
134 } else if (bitbuf & (mask << 1)) {
135 frame += bytestream2_get_le16(gb);
136 } else {
137 *frame++ = bytestream2_get_byte(gb);
138 *frame++ = bytestream2_get_byte(gb);
139 }
140 mask <<= 2;
141 }
142
143 return 0;
144 }
145
decode_dds1(GetByteContext * gb,uint8_t * frame,int width,int height)146 static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height)
147 {
148 const uint8_t *frame_start = frame;
149 const uint8_t *frame_end = frame + width * height;
150 int mask = 0x10000, bitbuf = 0;
151 int i, v, offset, count, segments;
152
153 if ((width | height) & 1)
154 return AVERROR_INVALIDDATA;
155 segments = bytestream2_get_le16(gb);
156 while (segments--) {
157 if (bytestream2_get_bytes_left(gb) < 2)
158 return AVERROR_INVALIDDATA;
159 if (mask == 0x10000) {
160 bitbuf = bytestream2_get_le16u(gb);
161 mask = 1;
162 }
163
164 if (bitbuf & mask) {
165 v = bytestream2_get_le16(gb);
166 offset = (v & 0x1FFF) << 2;
167 count = ((v >> 13) + 2) << 1;
168 if (frame - frame_start < offset || frame_end - frame < count*2 + width)
169 return AVERROR_INVALIDDATA;
170 for (i = 0; i < count; i++) {
171 frame[0] = frame[1] =
172 frame[width] = frame[width + 1] = frame[-offset];
173
174 frame += 2;
175 }
176 } else if (bitbuf & (mask << 1)) {
177 v = bytestream2_get_le16(gb)*2;
178 if (frame - frame_end < v)
179 return AVERROR_INVALIDDATA;
180 frame += v;
181 } else {
182 if (width < 4 || frame_end - frame < width + 4)
183 return AVERROR_INVALIDDATA;
184 frame[0] = frame[1] =
185 frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
186 frame += 2;
187 frame[0] = frame[1] =
188 frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
189 frame += 2;
190 }
191 mask <<= 2;
192 }
193
194 return 0;
195 }
196
decode_bdlt(GetByteContext * gb,uint8_t * frame,int width,int height)197 static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
198 {
199 uint8_t *line_ptr;
200 int count, lines, segments;
201
202 count = bytestream2_get_le16(gb);
203 if (count >= height)
204 return AVERROR_INVALIDDATA;
205 frame += width * count;
206 lines = bytestream2_get_le16(gb);
207 if (count + lines > height)
208 return AVERROR_INVALIDDATA;
209
210 while (lines--) {
211 if (bytestream2_get_bytes_left(gb) < 1)
212 return AVERROR_INVALIDDATA;
213 line_ptr = frame;
214 frame += width;
215 segments = bytestream2_get_byteu(gb);
216 while (segments--) {
217 if (frame - line_ptr <= bytestream2_peek_byte(gb))
218 return AVERROR_INVALIDDATA;
219 line_ptr += bytestream2_get_byte(gb);
220 count = (int8_t)bytestream2_get_byte(gb);
221 if (count >= 0) {
222 if (frame - line_ptr < count)
223 return AVERROR_INVALIDDATA;
224 if (bytestream2_get_buffer(gb, line_ptr, count) != count)
225 return AVERROR_INVALIDDATA;
226 } else {
227 count = -count;
228 if (frame - line_ptr < count)
229 return AVERROR_INVALIDDATA;
230 memset(line_ptr, bytestream2_get_byte(gb), count);
231 }
232 line_ptr += count;
233 }
234 }
235
236 return 0;
237 }
238
decode_wdlt(GetByteContext * gb,uint8_t * frame,int width,int height)239 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
240 {
241 const uint8_t *frame_end = frame + width * height;
242 uint8_t *line_ptr;
243 int count, i, v, lines, segments;
244 int y = 0;
245
246 lines = bytestream2_get_le16(gb);
247 if (lines > height)
248 return AVERROR_INVALIDDATA;
249
250 while (lines--) {
251 if (bytestream2_get_bytes_left(gb) < 2)
252 return AVERROR_INVALIDDATA;
253 segments = bytestream2_get_le16u(gb);
254 while ((segments & 0xC000) == 0xC000) {
255 unsigned skip_lines = -(int16_t)segments;
256 int64_t delta = -((int16_t)segments * (int64_t)width);
257 if (frame_end - frame <= delta || y + lines + skip_lines > height)
258 return AVERROR_INVALIDDATA;
259 frame += delta;
260 y += skip_lines;
261 segments = bytestream2_get_le16(gb);
262 }
263
264 if (frame_end <= frame)
265 return AVERROR_INVALIDDATA;
266 if (segments & 0x8000) {
267 frame[width - 1] = segments & 0xFF;
268 segments = bytestream2_get_le16(gb);
269 }
270 line_ptr = frame;
271 if (frame_end - frame < width)
272 return AVERROR_INVALIDDATA;
273 frame += width;
274 y++;
275 while (segments--) {
276 if (frame - line_ptr <= bytestream2_peek_byte(gb))
277 return AVERROR_INVALIDDATA;
278 line_ptr += bytestream2_get_byte(gb);
279 count = (int8_t)bytestream2_get_byte(gb);
280 if (count >= 0) {
281 if (frame - line_ptr < count * 2)
282 return AVERROR_INVALIDDATA;
283 if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
284 return AVERROR_INVALIDDATA;
285 line_ptr += count * 2;
286 } else {
287 count = -count;
288 if (frame - line_ptr < count * 2)
289 return AVERROR_INVALIDDATA;
290 v = bytestream2_get_le16(gb);
291 for (i = 0; i < count; i++)
292 bytestream_put_le16(&line_ptr, v);
293 }
294 }
295 }
296
297 return 0;
298 }
299
decode_tdlt(GetByteContext * gb,uint8_t * frame,int width,int height)300 static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
301 {
302 const uint8_t *frame_end = frame + width * height;
303 uint32_t segments = bytestream2_get_le32(gb);
304 int skip, copy;
305
306 while (segments--) {
307 if (bytestream2_get_bytes_left(gb) < 2)
308 return AVERROR_INVALIDDATA;
309 copy = bytestream2_get_byteu(gb) * 2;
310 skip = bytestream2_get_byteu(gb) * 2;
311 if (frame_end - frame < copy + skip ||
312 bytestream2_get_bytes_left(gb) < copy)
313 return AVERROR_INVALIDDATA;
314 frame += skip;
315 bytestream2_get_buffer(gb, frame, copy);
316 frame += copy;
317 }
318
319 return 0;
320 }
321
decode_blck(GetByteContext * gb,uint8_t * frame,int width,int height)322 static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height)
323 {
324 memset(frame, 0, width * height);
325 return 0;
326 }
327
328
329 typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height);
330
331 static const chunk_decoder decoder[8] = {
332 decode_copy, decode_tsw1, decode_bdlt, decode_wdlt,
333 decode_tdlt, decode_dsw1, decode_blck, decode_dds1,
334 };
335
336 static const char chunk_name[8][5] = {
337 "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1"
338 };
339
dfa_decode_frame(AVCodecContext * avctx,AVFrame * frame,int * got_frame,AVPacket * avpkt)340 static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame,
341 int *got_frame, AVPacket *avpkt)
342 {
343 DfaContext *s = avctx->priv_data;
344 GetByteContext gb;
345 const uint8_t *buf = avpkt->data;
346 uint32_t chunk_type, chunk_size;
347 uint8_t *dst;
348 int ret;
349 int i, pal_elems;
350 int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
351
352 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
353 return ret;
354
355 bytestream2_init(&gb, avpkt->data, avpkt->size);
356 while (bytestream2_get_bytes_left(&gb) > 0) {
357 if (bytestream2_get_bytes_left(&gb) < 12)
358 return AVERROR_INVALIDDATA;
359 bytestream2_skip(&gb, 4);
360 chunk_size = bytestream2_get_le32(&gb);
361 chunk_type = bytestream2_get_le32(&gb);
362 if (!chunk_type)
363 break;
364 if (chunk_type == 1) {
365 pal_elems = FFMIN(chunk_size / 3, 256);
366 for (i = 0; i < pal_elems; i++) {
367 s->pal[i] = bytestream2_get_be24(&gb) << 2;
368 s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
369 }
370 frame->palette_has_changed = 1;
371 } else if (chunk_type <= 9) {
372 if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
373 av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
374 chunk_name[chunk_type - 2]);
375 return AVERROR_INVALIDDATA;
376 }
377 } else {
378 av_log(avctx, AV_LOG_WARNING,
379 "Ignoring unknown chunk type %"PRIu32"\n",
380 chunk_type);
381 }
382 buf += chunk_size;
383 }
384
385 buf = s->frame_buf;
386 dst = frame->data[0];
387 if (version == 0x100) {
388 for (i = 0; i < avctx->height; i++) {
389 int j;
390 const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width;
391 int stride = (avctx->height/4)*avctx->width;
392 for(j = 0; j < avctx->width/4; j++) {
393 dst[4*j+0] = buf1[j + 0*stride];
394 dst[4*j+1] = buf1[j + 1*stride];
395 dst[4*j+2] = buf1[j + 2*stride];
396 dst[4*j+3] = buf1[j + 3*stride];
397 }
398 j *= 4;
399 for(; j < avctx->width; j++) {
400 dst[j] = buf1[(j/4) + (j&3)*stride];
401 }
402 dst += frame->linesize[0];
403 }
404 } else
405 av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width,
406 avctx->width, avctx->height);
407
408 memcpy(frame->data[1], s->pal, sizeof(s->pal));
409
410 *got_frame = 1;
411
412 return avpkt->size;
413 }
414
dfa_decode_end(AVCodecContext * avctx)415 static av_cold int dfa_decode_end(AVCodecContext *avctx)
416 {
417 DfaContext *s = avctx->priv_data;
418
419 av_freep(&s->frame_buf);
420
421 return 0;
422 }
423
424 const FFCodec ff_dfa_decoder = {
425 .p.name = "dfa",
426 .p.long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"),
427 .p.type = AVMEDIA_TYPE_VIDEO,
428 .p.id = AV_CODEC_ID_DFA,
429 .priv_data_size = sizeof(DfaContext),
430 .init = dfa_decode_init,
431 .close = dfa_decode_end,
432 FF_CODEC_DECODE_CB(dfa_decode_frame),
433 .p.capabilities = AV_CODEC_CAP_DR1,
434 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
435 };
436