FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dfa.c
Date: 2024-12-12 01:08:13
Exec Total Coverage
Lines: 133 256 52.0%
Functions: 6 11 54.5%
Branches: 70 160 43.8%

Line Branch Exec Source
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 "decode.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
39 22 static av_cold int dfa_decode_init(AVCodecContext *avctx)
40 {
41 22 DfaContext *s = avctx->priv_data;
42
43 22 avctx->pix_fmt = AV_PIX_FMT_PAL8;
44
45
3/6
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 22 times.
22 if (!avctx->width || !avctx->height || FFMAX(avctx->width, avctx->height) >= (1<<16))
46 return AVERROR_INVALIDDATA;
47
48
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0);
49
50 22 s->frame_buf = av_mallocz(avctx->width * avctx->height);
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (!s->frame_buf)
52 return AVERROR(ENOMEM);
53
54 22 return 0;
55 }
56
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
66 35 static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
67 {
68 35 const uint8_t *frame_start = frame;
69 35 const uint8_t *frame_end = frame + width * height;
70 35 int mask = 0x10000, bitbuf = 0;
71 int v, count;
72 unsigned segments;
73 unsigned offset;
74
75 35 segments = bytestream2_get_le32(gb);
76 35 offset = bytestream2_get_le32(gb);
77
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
35 if (segments == 0 && offset == frame_end - frame)
78 1 return 0; // skip frame
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (frame_end - frame <= offset)
80 return AVERROR_INVALIDDATA;
81 34 frame += offset;
82
2/2
✓ Branch 0 taken 566883 times.
✓ Branch 1 taken 32 times.
566915 while (segments--) {
83
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 566881 times.
566883 if (bytestream2_get_bytes_left(gb) < 2)
84 2 return AVERROR_INVALIDDATA;
85
2/2
✓ Branch 0 taken 35445 times.
✓ Branch 1 taken 531436 times.
566881 if (mask == 0x10000) {
86 35445 bitbuf = bytestream2_get_le16u(gb);
87 35445 mask = 1;
88 }
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 566881 times.
566881 if (frame_end - frame < 2)
90 return AVERROR_INVALIDDATA;
91
2/2
✓ Branch 0 taken 222937 times.
✓ Branch 1 taken 343944 times.
566881 if (bitbuf & mask) {
92 222937 v = bytestream2_get_le16(gb);
93 222937 offset = (v & 0x1FFF) << 1;
94 222937 count = ((v >> 13) + 2) << 1;
95
2/4
✓ Branch 0 taken 222937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 222937 times.
222937 if (frame - frame_start < offset || frame_end - frame < count)
96 return AVERROR_INVALIDDATA;
97 222937 av_memcpy_backptr(frame, offset, count);
98 222937 frame += count;
99 } else {
100 343944 *frame++ = bytestream2_get_byte(gb);
101 343944 *frame++ = bytestream2_get_byte(gb);
102 }
103 566881 mask <<= 1;
104 }
105
106 32 return 0;
107 }
108
109 121 static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height)
110 {
111 121 const uint8_t *frame_start = frame;
112 121 const uint8_t *frame_end = frame + width * height;
113 121 int mask = 0x10000, bitbuf = 0;
114 int v, offset, count, segments;
115
116 121 segments = bytestream2_get_le16(gb);
117
2/2
✓ Branch 0 taken 460846 times.
✓ Branch 1 taken 116 times.
460962 while (segments--) {
118
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 460841 times.
460846 if (bytestream2_get_bytes_left(gb) < 2)
119 5 return AVERROR_INVALIDDATA;
120
2/2
✓ Branch 0 taken 57659 times.
✓ Branch 1 taken 403182 times.
460841 if (mask == 0x10000) {
121 57659 bitbuf = bytestream2_get_le16u(gb);
122 57659 mask = 1;
123 }
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 460841 times.
460841 if (frame_end - frame < 2)
125 return AVERROR_INVALIDDATA;
126
2/2
✓ Branch 0 taken 124238 times.
✓ Branch 1 taken 336603 times.
460841 if (bitbuf & mask) {
127 124238 v = bytestream2_get_le16(gb);
128 124238 offset = (v & 0x1FFF) << 1;
129 124238 count = ((v >> 13) + 2) << 1;
130
2/4
✓ Branch 0 taken 124238 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 124238 times.
124238 if (frame - frame_start < offset || frame_end - frame < count)
131 return AVERROR_INVALIDDATA;
132 124238 av_memcpy_backptr(frame, offset, count);
133 124238 frame += count;
134
2/2
✓ Branch 0 taken 70168 times.
✓ Branch 1 taken 266435 times.
336603 } else if (bitbuf & (mask << 1)) {
135 70168 frame += bytestream2_get_le16(gb);
136 } else {
137 266435 *frame++ = bytestream2_get_byte(gb);
138 266435 *frame++ = bytestream2_get_byte(gb);
139 }
140 460841 mask <<= 2;
141 }
142
143 116 return 0;
144 }
145
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
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
239 11 static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
240 {
241 11 const uint8_t *frame_end = frame + width * height;
242 uint8_t *line_ptr;
243 int count, i, v, lines, segments;
244 11 int y = 0;
245
246 11 lines = bytestream2_get_le16(gb);
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (lines > height)
248 return AVERROR_INVALIDDATA;
249
250
2/2
✓ Branch 0 taken 1438 times.
✓ Branch 1 taken 10 times.
1448 while (lines--) {
251
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1438 times.
1438 if (bytestream2_get_bytes_left(gb) < 2)
252 return AVERROR_INVALIDDATA;
253 1438 segments = bytestream2_get_le16u(gb);
254
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1438 times.
1452 while ((segments & 0xC000) == 0xC000) {
255 14 unsigned skip_lines = -(int16_t)segments;
256 14 int64_t delta = -((int16_t)segments * (int64_t)width);
257
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (frame_end - frame <= delta || y + lines + skip_lines > height)
258 return AVERROR_INVALIDDATA;
259 14 frame += delta;
260 14 y += skip_lines;
261 14 segments = bytestream2_get_le16(gb);
262 }
263
264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1438 times.
1438 if (frame_end <= frame)
265 return AVERROR_INVALIDDATA;
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1438 times.
1438 if (segments & 0x8000) {
267 frame[width - 1] = segments & 0xFF;
268 segments = bytestream2_get_le16(gb);
269 }
270 1438 line_ptr = frame;
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1438 times.
1438 if (frame_end - frame < width)
272 return AVERROR_INVALIDDATA;
273 1438 frame += width;
274 1438 y++;
275
2/2
✓ Branch 0 taken 5140 times.
✓ Branch 1 taken 1437 times.
6577 while (segments--) {
276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5140 times.
5140 if (frame - line_ptr <= bytestream2_peek_byte(gb))
277 return AVERROR_INVALIDDATA;
278 5140 line_ptr += bytestream2_get_byte(gb);
279 5140 count = (int8_t)bytestream2_get_byte(gb);
280
2/2
✓ Branch 0 taken 4691 times.
✓ Branch 1 taken 449 times.
5140 if (count >= 0) {
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4691 times.
4691 if (frame - line_ptr < count * 2)
282 return AVERROR_INVALIDDATA;
283
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4690 times.
4691 if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2)
284 1 return AVERROR_INVALIDDATA;
285 4690 line_ptr += count * 2;
286 } else {
287 449 count = -count;
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
449 if (frame - line_ptr < count * 2)
289 return AVERROR_INVALIDDATA;
290 449 v = bytestream2_get_le16(gb);
291
2/2
✓ Branch 0 taken 16595 times.
✓ Branch 1 taken 449 times.
17044 for (i = 0; i < count; i++)
292 16595 bytestream_put_le16(&line_ptr, v);
293 }
294 }
295 }
296
297 10 return 0;
298 }
299
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
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
340 172 static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame,
341 int *got_frame, AVPacket *avpkt)
342 {
343 172 DfaContext *s = avctx->priv_data;
344 GetByteContext gb;
345 172 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
1/2
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
172 int version = avctx->extradata_size==2 ? AV_RL16(avctx->extradata) : 0;
351
352
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 172 times.
172 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
353 return ret;
354
355 172 bytestream2_init(&gb, avpkt->data, avpkt->size);
356
1/2
✓ Branch 1 taken 343 times.
✗ Branch 2 not taken.
343 while (bytestream2_get_bytes_left(&gb) > 0) {
357
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 343 times.
343 if (bytestream2_get_bytes_left(&gb) < 12)
358 return AVERROR_INVALIDDATA;
359 343 bytestream2_skip(&gb, 4);
360 343 chunk_size = bytestream2_get_le32(&gb);
361 343 chunk_type = bytestream2_get_le32(&gb);
362
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 179 times.
343 if (!chunk_type)
363 164 break;
364
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 167 times.
179 if (chunk_type == 1) {
365
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 pal_elems = FFMIN(chunk_size / 3, 256);
366
2/2
✓ Branch 0 taken 3072 times.
✓ Branch 1 taken 12 times.
3084 for (i = 0; i < pal_elems; i++) {
367 3072 s->pal[i] = bytestream2_get_be24(&gb) << 2;
368 3072 s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
369 }
370 #if FF_API_PALETTE_HAS_CHANGED
371 FF_DISABLE_DEPRECATION_WARNINGS
372 12 frame->palette_has_changed = 1;
373 FF_ENABLE_DEPRECATION_WARNINGS
374 #endif
375
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 } else if (chunk_type <= 9) {
376
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 159 times.
167 if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
377 8 av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
378 8 chunk_name[chunk_type - 2]);
379 8 return AVERROR_INVALIDDATA;
380 }
381 } else {
382 av_log(avctx, AV_LOG_WARNING,
383 "Ignoring unknown chunk type %"PRIu32"\n",
384 chunk_type);
385 }
386 171 buf += chunk_size;
387 }
388
389 164 buf = s->frame_buf;
390 164 dst = frame->data[0];
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (version == 0x100) {
392 for (i = 0; i < avctx->height; i++) {
393 int j;
394 const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width;
395 int stride = (avctx->height/4)*avctx->width;
396 for(j = 0; j < avctx->width/4; j++) {
397 dst[4*j+0] = buf1[j + 0*stride];
398 dst[4*j+1] = buf1[j + 1*stride];
399 dst[4*j+2] = buf1[j + 2*stride];
400 dst[4*j+3] = buf1[j + 3*stride];
401 }
402 j *= 4;
403 for(; j < avctx->width; j++) {
404 dst[j] = buf1[(j/4) + (j&3)*stride];
405 }
406 dst += frame->linesize[0];
407 }
408 } else
409 164 av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width,
410 avctx->width, avctx->height);
411
412 164 memcpy(frame->data[1], s->pal, sizeof(s->pal));
413
414 164 *got_frame = 1;
415
416 164 return avpkt->size;
417 }
418
419 22 static av_cold int dfa_decode_end(AVCodecContext *avctx)
420 {
421 22 DfaContext *s = avctx->priv_data;
422
423 22 av_freep(&s->frame_buf);
424
425 22 return 0;
426 }
427
428 const FFCodec ff_dfa_decoder = {
429 .p.name = "dfa",
430 CODEC_LONG_NAME("Chronomaster DFA"),
431 .p.type = AVMEDIA_TYPE_VIDEO,
432 .p.id = AV_CODEC_ID_DFA,
433 .priv_data_size = sizeof(DfaContext),
434 .init = dfa_decode_init,
435 .close = dfa_decode_end,
436 FF_CODEC_DECODE_CB(dfa_decode_frame),
437 .p.capabilities = AV_CODEC_CAP_DR1,
438 };
439