FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dxtory.c
Date: 2026-09-25 02:02:46
Exec Total Coverage
Lines: 48 470 10.2%
Functions: 4 27 14.8%
Branches: 13 193 6.7%

Line Branch Exec Source
1 /*
2 * Dxtory decoder
3 *
4 * Copyright (c) 2011 Konstantin Shishkov
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 "libavutil/attributes.h"
26 #include "libavutil/common.h"
27 #include "libavutil/intreadwrite.h"
28
29 #define BITSTREAM_READER_LE
30 #include "avcodec.h"
31 #include "bytestream.h"
32 #include "codec_internal.h"
33 #include "get_bits.h"
34 #include "unary.h"
35 #include "thread.h"
36
37 2 static int64_t get_raw_size(enum AVPixelFormat fmt, int width, int height)
38 {
39
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 switch (fmt) {
40 ✗ case AV_PIX_FMT_RGB555LE:
41 case AV_PIX_FMT_RGB565LE:
42 ✗ return width * height * 2LL;
43 ✗ case AV_PIX_FMT_RGB24:
44 case AV_PIX_FMT_BGR24:
45 case AV_PIX_FMT_YUV444P:
46 ✗ return width * height * 3LL;
47 2 case AV_PIX_FMT_YUV420P:
48 2 return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 1) * AV_CEIL_RSHIFT(height, 1);
49 ✗ case AV_PIX_FMT_YUV410P:
50 ✗ return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 2) * AV_CEIL_RSHIFT(height, 2);
51 }
52
53 ✗ return 0;
54 }
55
56 4 static void do_vflip(AVCodecContext *avctx, AVFrame *pic, int vflip)
57 {
58
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!vflip)
59 4 return;
60
61 ✗ switch (pic->format) {
62 ✗ case AV_PIX_FMT_YUV444P:
63 ✗ pic->data[1] += (avctx->height - 1) * pic->linesize[1];
64 ✗ pic->linesize[1] = -pic->linesize[1];
65 ✗ pic->data[2] += (avctx->height - 1) * pic->linesize[2];
66 ✗ pic->linesize[2] = -pic->linesize[2];
67 av_fallthrough;
68 ✗ case AV_PIX_FMT_RGB555LE:
69 case AV_PIX_FMT_RGB565LE:
70 case AV_PIX_FMT_BGR24:
71 case AV_PIX_FMT_RGB24:
72 ✗ pic->data[0] += (avctx->height - 1) * pic->linesize[0];
73 ✗ pic->linesize[0] = -pic->linesize[0];
74 ✗ break;
75 ✗ case AV_PIX_FMT_YUV410P:
76 ✗ pic->data[0] += (avctx->height - 1) * pic->linesize[0];
77 ✗ pic->linesize[0] = -pic->linesize[0];
78 ✗ pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[1];
79 ✗ pic->linesize[1] = -pic->linesize[1];
80 ✗ pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[2];
81 ✗ pic->linesize[2] = -pic->linesize[2];
82 ✗ break;
83 ✗ case AV_PIX_FMT_YUV420P:
84 ✗ pic->data[0] += (avctx->height - 1) * pic->linesize[0];
85 ✗ pic->linesize[0] = -pic->linesize[0];
86 ✗ pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[1];
87 ✗ pic->linesize[1] = -pic->linesize[1];
88 ✗ pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[2];
89 ✗ pic->linesize[2] = -pic->linesize[2];
90 ✗ break;
91 }
92 }
93
94 ✗ static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,
95 const uint8_t *src, int src_size,
96 int id, int bpp, uint32_t vflipped)
97 {
98 int h;
99 uint8_t *dst;
100 int ret;
101
102 ✗ if (src_size < get_raw_size(id, avctx->width, avctx->height)) {
103 ✗ av_log(avctx, AV_LOG_ERROR, "packet too small\n");
104 ✗ return AVERROR_INVALIDDATA;
105 }
106
107 ✗ avctx->pix_fmt = id;
108 ✗ if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
109 ✗ return ret;
110
111 ✗ do_vflip(avctx, pic, vflipped);
112
113 ✗ dst = pic->data[0];
114 ✗ for (h = 0; h < avctx->height; h++) {
115 ✗ memcpy(dst, src, avctx->width * bpp);
116 ✗ src += avctx->width * bpp;
117 ✗ dst += pic->linesize[0];
118 }
119
120 ✗ do_vflip(avctx, pic, vflipped);
121
122 ✗ return 0;
123 }
124
125 ✗ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic,
126 const uint8_t *src, int src_size,
127 uint32_t vflipped)
128 {
129 int h, w;
130 uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V;
131 int height, width, hmargin, vmargin;
132 int huvborder;
133 int ret;
134
135 ✗ if (src_size < get_raw_size(AV_PIX_FMT_YUV410P, avctx->width, avctx->height)) {
136 ✗ av_log(avctx, AV_LOG_ERROR, "packet too small\n");
137 ✗ return AVERROR_INVALIDDATA;
138 }
139
140 ✗ avctx->pix_fmt = AV_PIX_FMT_YUV410P;
141 ✗ if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
142 ✗ return ret;
143
144 ✗ do_vflip(avctx, pic, vflipped);
145
146 ✗ height = avctx->height & ~3;
147 ✗ width = avctx->width & ~3;
148 ✗ hmargin = avctx->width - width;
149 ✗ vmargin = avctx->height - height;
150 ✗ huvborder = AV_CEIL_RSHIFT(avctx->width, 2) - 1;
151
152 ✗ Y1 = pic->data[0];
153 ✗ Y2 = pic->data[0] + pic->linesize[0];
154 ✗ Y3 = pic->data[0] + pic->linesize[0] * 2;
155 ✗ Y4 = pic->data[0] + pic->linesize[0] * 3;
156 ✗ U = pic->data[1];
157 ✗ V = pic->data[2];
158 ✗ for (h = 0; h < height; h += 4) {
159 ✗ for (w = 0; w < width; w += 4) {
160 ✗ AV_COPY32U(Y1 + w, src);
161 ✗ AV_COPY32U(Y2 + w, src + 4);
162 ✗ AV_COPY32U(Y3 + w, src + 8);
163 ✗ AV_COPY32U(Y4 + w, src + 12);
164 ✗ U[w >> 2] = src[16] + 0x80;
165 ✗ V[w >> 2] = src[17] + 0x80;
166 ✗ src += 18;
167 }
168 ✗ if (hmargin) {
169 ✗ for (w = 0; w < hmargin; w++) {
170 ✗ Y1[width + w] = src[w];
171 ✗ Y2[width + w] = src[w + hmargin * 1];
172 ✗ Y3[width + w] = src[w + hmargin * 2];
173 ✗ Y4[width + w] = src[w + hmargin * 3];
174 }
175 ✗ src += 4 * hmargin;
176 ✗ U[huvborder] = src[0] + 0x80;
177 ✗ V[huvborder] = src[1] + 0x80;
178 ✗ src += 2;
179 }
180 ✗ Y1 += pic->linesize[0] * 4;
181 ✗ Y2 += pic->linesize[0] * 4;
182 ✗ Y3 += pic->linesize[0] * 4;
183 ✗ Y4 += pic->linesize[0] * 4;
184 ✗ U += pic->linesize[1];
185 ✗ V += pic->linesize[2];
186 }
187
188 ✗ if (vmargin) {
189 ✗ for (w = 0; w < width; w += 4) {
190 ✗ AV_COPY32U(Y1 + w, src);
191 ✗ if (vmargin > 1)
192 ✗ AV_COPY32U(Y2 + w, src + 4);
193 ✗ if (vmargin > 2)
194 ✗ AV_COPY32U(Y3 + w, src + 8);
195 ✗ src += 4 * vmargin;
196 ✗ U[w >> 2] = src[0] + 0x80;
197 ✗ V[w >> 2] = src[1] + 0x80;
198 ✗ src += 2;
199 }
200 ✗ if (hmargin) {
201 ✗ for (w = 0; w < hmargin; w++) {
202 ✗ AV_COPY32U(Y1 + w, src);
203 ✗ if (vmargin > 1)
204 ✗ AV_COPY32U(Y2 + w, src + 4);
205 ✗ if (vmargin > 2)
206 ✗ AV_COPY32U(Y3 + w, src + 8);
207 ✗ src += 4 * vmargin;
208 }
209 ✗ U[huvborder] = src[0] + 0x80;
210 ✗ V[huvborder] = src[1] + 0x80;
211 ✗ src += 2;
212 }
213 }
214
215 ✗ do_vflip(avctx, pic, vflipped);
216
217 ✗ return 0;
218 }
219
220 2 static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic,
221 const uint8_t *src, int src_size,
222 uint32_t vflipped)
223 {
224 int h, w;
225 uint8_t *Y1, *Y2, *U, *V;
226 int height, width, hmargin, vmargin;
227 int huvborder;
228 int ret;
229
230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (src_size < get_raw_size(AV_PIX_FMT_YUV420P, avctx->width, avctx->height)) {
231 ✗ av_log(avctx, AV_LOG_ERROR, "packet too small\n");
232 ✗ return AVERROR_INVALIDDATA;
233 }
234
235 2 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
236
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
237 ✗ return ret;
238
239 2 do_vflip(avctx, pic, vflipped);
240
241 2 height = avctx->height & ~1;
242 2 width = avctx->width & ~1;
243 2 hmargin = avctx->width - width;
244 2 vmargin = avctx->height - height;
245 2 huvborder = AV_CEIL_RSHIFT(avctx->width, 1) - 1;
246
247 2 Y1 = pic->data[0];
248 2 Y2 = pic->data[0] + pic->linesize[0];
249 2 U = pic->data[1];
250 2 V = pic->data[2];
251
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 2 times.
722 for (h = 0; h < height; h += 2) {
252
2/2
✓ Branch 0 taken 460800 times.
✓ Branch 1 taken 720 times.
461520 for (w = 0; w < width; w += 2) {
253 460800 AV_COPY16(Y1 + w, src);
254 460800 AV_COPY16(Y2 + w, src + 2);
255 460800 U[w >> 1] = src[4] + 0x80;
256 460800 V[w >> 1] = src[5] + 0x80;
257 460800 src += 6;
258 }
259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 720 times.
720 if (hmargin) {
260 ✗ Y1[width + 1] = src[0];
261 ✗ Y2[width + 1] = src[1];
262 ✗ U[huvborder] = src[2] + 0x80;
263 ✗ V[huvborder] = src[3] + 0x80;
264 ✗ src += 4;
265 }
266 720 Y1 += pic->linesize[0] * 2;
267 720 Y2 += pic->linesize[0] * 2;
268 720 U += pic->linesize[1];
269 720 V += pic->linesize[2];
270 }
271
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (vmargin) {
273 ✗ for (w = 0; w < width; w += 2) {
274 ✗ AV_COPY16U(Y1 + w, src);
275 ✗ U[w >> 1] = src[0] + 0x80;
276 ✗ V[w >> 1] = src[1] + 0x80;
277 ✗ src += 4;
278 }
279 ✗ if (hmargin) {
280 ✗ Y1[w] = src[0];
281 ✗ U[huvborder] = src[1] + 0x80;
282 ✗ V[huvborder] = src[2] + 0x80;
283 ✗ src += 3;
284 }
285 }
286
287 2 do_vflip(avctx, pic, vflipped);
288
289 2 return 0;
290 }
291
292 ✗ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic,
293 const uint8_t *src, int src_size,
294 uint32_t vflipped)
295 {
296 int h, w;
297 uint8_t *Y, *U, *V;
298 int ret;
299
300 ✗ if (src_size < get_raw_size(AV_PIX_FMT_YUV444P, avctx->width, avctx->height)) {
301 ✗ av_log(avctx, AV_LOG_ERROR, "packet too small\n");
302 ✗ return AVERROR_INVALIDDATA;
303 }
304
305 ✗ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
306 ✗ if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
307 ✗ return ret;
308
309 ✗ do_vflip(avctx, pic, vflipped);
310
311 ✗ Y = pic->data[0];
312 ✗ U = pic->data[1];
313 ✗ V = pic->data[2];
314 ✗ for (h = 0; h < avctx->height; h++) {
315 ✗ for (w = 0; w < avctx->width; w++) {
316 ✗ Y[w] = *src++;
317 ✗ U[w] = *src++ ^ 0x80;
318 ✗ V[w] = *src++ ^ 0x80;
319 }
320 ✗ Y += pic->linesize[0];
321 ✗ U += pic->linesize[1];
322 ✗ V += pic->linesize[2];
323 }
324
325 ✗ do_vflip(avctx, pic, vflipped);
326
327 ✗ return 0;
328 }
329
330 static const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
331 static const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F };
332 static const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F };
333
334 ✗ static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
335 {
336 uint8_t c, val;
337
338 ✗ c = get_unary(gb, 0, 8);
339 ✗ if (!c) {
340 ✗ val = get_bits(gb, 8);
341 ✗ memmove(lru + 1, lru, sizeof(*lru) * (8 - 1));
342 } else {
343 ✗ val = lru[c - 1];
344 ✗ memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
345 }
346 ✗ lru[0] = val;
347
348 ✗ return val;
349 }
350
351 ✗ static int check_slice_size(AVCodecContext *avctx,
352 const uint8_t *src, int src_size,
353 int slice_size, int off)
354 {
355 int cur_slice_size;
356
357 ✗ if (slice_size > src_size - off) {
358 ✗ av_log(avctx, AV_LOG_ERROR,
359 "invalid slice size %d (only %d bytes left)\n",
360 slice_size, src_size - off);
361 ✗ return AVERROR_INVALIDDATA;
362 }
363 ✗ if (slice_size <= 16) {
364 ✗ av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n",
365 slice_size);
366 ✗ return AVERROR_INVALIDDATA;
367 }
368
369 ✗ cur_slice_size = AV_RL32(src + off);
370 ✗ if (cur_slice_size != slice_size - 16) {
371 ✗ av_log(avctx, AV_LOG_ERROR,
372 "Slice sizes mismatch: got %d instead of %d\n",
373 cur_slice_size, slice_size - 16);
374 }
375
376 ✗ return 0;
377 }
378
379 ✗ static int load_buffer(AVCodecContext *avctx,
380 const uint8_t *src, int src_size,
381 GetByteContext *gb,
382 int *nslices, int *off)
383 {
384 ✗ bytestream2_init(gb, src, src_size);
385 ✗ *nslices = bytestream2_get_le16(gb);
386 ✗ *off = FFALIGN(*nslices * 4 + 2, 16);
387 ✗ if (src_size < *off) {
388 ✗ av_log(avctx, AV_LOG_ERROR, "no slice data\n");
389 ✗ return AVERROR_INVALIDDATA;
390 }
391
392 ✗ if (!*nslices) {
393 ✗ avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices,
394 avctx->width, avctx->height);
395 ✗ return AVERROR_PATCHWELCOME;
396 }
397
398 ✗ return 0;
399 }
400
401 ✗ static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8],
402 int bits)
403 {
404 uint8_t c, val;
405
406 ✗ c = get_unary(gb, 0, bits);
407 ✗ if (!c) {
408 ✗ val = get_bits(gb, bits);
409 ✗ memmove(lru + 1, lru, sizeof(*lru) * (6 - 1));
410 } else {
411 ✗ val = lru[c - 1];
412 ✗ memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
413 }
414 ✗ lru[0] = val;
415
416 ✗ return val;
417 }
418
419 typedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame,
420 int line, int height, uint8_t lru[3][8]);
421
422 typedef void (*setup_lru_func)(uint8_t lru[3][8]);
423
424 ✗ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic,
425 const uint8_t *src, int src_size,
426 decode_slice_func decode_slice,
427 setup_lru_func setup_lru,
428 enum AVPixelFormat fmt,
429 uint32_t vflipped)
430 {
431 GetByteContext gb, gb_check;
432 GetBitContext gb2;
433 ✗ int nslices, slice, line = 0;
434 uint32_t off, slice_size;
435 uint64_t off_check;
436 uint8_t lru[3][8];
437 int ret;
438
439 ✗ ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
440 ✗ if (ret < 0)
441 ✗ return ret;
442
443 ✗ off_check = off;
444 ✗ gb_check = gb;
445 ✗ for (slice = 0; slice < nslices; slice++) {
446 ✗ slice_size = bytestream2_get_le32(&gb_check);
447
448 ✗ if (slice_size <= 16 + (avctx->height * avctx->width / (8 * nslices)))
449 ✗ return AVERROR_INVALIDDATA;
450 ✗ off_check += slice_size;
451 }
452
453 ✗ if (off_check - avctx->discard_damaged_percentage*off_check/100 > src_size)
454 ✗ return AVERROR_INVALIDDATA;
455
456 ✗ avctx->pix_fmt = fmt;
457 ✗ if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
458 ✗ return ret;
459
460 ✗ do_vflip(avctx, pic, vflipped);
461
462 ✗ for (slice = 0; slice < nslices; slice++) {
463 ✗ slice_size = bytestream2_get_le32(&gb);
464
465 ✗ setup_lru(lru);
466
467 ✗ ret = check_slice_size(avctx, src, src_size, slice_size, off);
468 ✗ if (ret < 0)
469 ✗ return ret;
470
471 ✗ if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
472 ✗ return ret;
473
474 ✗ line += decode_slice(&gb2, pic, line, avctx->height - line, lru);
475
476 ✗ off += slice_size;
477 }
478
479 ✗ if (avctx->height - line) {
480 ✗ avpriv_request_sample(avctx, "Not enough slice data available");
481 }
482
483 ✗ do_vflip(avctx, pic, vflipped);
484
485 ✗ return 0;
486 }
487
488 av_always_inline
489 ✗ static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame,
490 int line, int left, uint8_t lru[3][8],
491 int is_565)
492 {
493 int x, y;
494 int r, g, b;
495 ✗ int width = frame->width;
496 ✗ int stride = frame->linesize[0];
497 ✗ uint8_t *dst = frame->data[0] + stride * line;
498
499 ✗ for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
500 ✗ for (x = 0; x < width; x++) {
501 ✗ b = decode_sym_565(gb, lru[0], 5);
502 ✗ g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5);
503 ✗ r = decode_sym_565(gb, lru[2], 5);
504 ✗ dst[x * 3 + 0] = (r << 3) | (r >> 2);
505 ✗ dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2);
506 ✗ dst[x * 3 + 2] = (b << 3) | (b >> 2);
507 }
508
509 ✗ dst += stride;
510 }
511
512 ✗ return y;
513 }
514
515 ✗ static void setup_lru_555(uint8_t lru[3][8])
516 {
517 ✗ memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
518 ✗ memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru));
519 ✗ memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
520 ✗ }
521
522 ✗ static void setup_lru_565(uint8_t lru[3][8])
523 {
524 ✗ memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
525 ✗ memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru));
526 ✗ memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
527 ✗ }
528
529 ✗ static int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame,
530 int line, int left, uint8_t lru[3][8])
531 {
532 ✗ return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0);
533 }
534
535 ✗ static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame,
536 int line, int left, uint8_t lru[3][8])
537 {
538 ✗ return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1);
539 }
540
541 ✗ static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
542 const uint8_t *src, int src_size, int is_565,
543 uint32_t vflipped)
544 {
545 ✗ enum AVPixelFormat fmt = AV_PIX_FMT_RGB24;
546 ✗ if (is_565)
547 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
548 dx2_decode_slice_565,
549 setup_lru_565,
550 fmt, vflipped);
551 else
552 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
553 dx2_decode_slice_555,
554 setup_lru_555,
555 fmt, vflipped);
556 }
557
558 ✗ static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame,
559 int line, int left, uint8_t lru[3][8])
560 {
561 int x, y;
562 ✗ int width = frame->width;
563 ✗ int stride = frame->linesize[0];
564 ✗ uint8_t *dst = frame->data[0] + stride * line;
565
566 ✗ for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
567 ✗ for (x = 0; x < width; x++) {
568 ✗ dst[x * 3 + 0] = decode_sym(gb, lru[0]);
569 ✗ dst[x * 3 + 1] = decode_sym(gb, lru[1]);
570 ✗ dst[x * 3 + 2] = decode_sym(gb, lru[2]);
571 }
572
573 ✗ dst += stride;
574 }
575
576 ✗ return y;
577 }
578
579 ✗ static void default_setup_lru(uint8_t lru[3][8])
580 {
581 int i;
582
583 ✗ for (i = 0; i < 3; i++)
584 ✗ memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
585 ✗ }
586
587 ✗ static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
588 const uint8_t *src, int src_size,
589 uint32_t vflipped)
590 {
591 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
592 dx2_decode_slice_rgb,
593 default_setup_lru,
594 AV_PIX_FMT_BGR24, vflipped);
595 }
596
597 ✗ static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame,
598 int line, int left,
599 uint8_t lru[3][8])
600 {
601 int x, y, i, j;
602 ✗ int width = frame->width;
603
604 ✗ int ystride = frame->linesize[0];
605 ✗ int ustride = frame->linesize[1];
606 ✗ int vstride = frame->linesize[2];
607
608 ✗ uint8_t *Y = frame->data[0] + ystride * line;
609 ✗ uint8_t *U = frame->data[1] + (ustride >> 2) * line;
610 ✗ uint8_t *V = frame->data[2] + (vstride >> 2) * line;
611
612 int h, w, hmargin, vmargin;
613 int huvborder;
614
615 ✗ h = frame->height & ~3;
616 ✗ w = frame->width & ~3;
617 ✗ hmargin = frame->width - w;
618 ✗ vmargin = frame->height - h;
619 ✗ huvborder = AV_CEIL_RSHIFT(frame->width, 2) - 1;
620
621 ✗ for (y = 0; y < left - 3 && get_bits_left(gb) >= 18 * w / 4 + hmargin * 4 + (!!hmargin * 2); y += 4) {
622 ✗ for (x = 0; x < w; x += 4) {
623 ✗ for (j = 0; j < 4; j++)
624 ✗ for (i = 0; i < 4; i++)
625 ✗ Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
626 ✗ U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
627 ✗ V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
628 }
629 ✗ if (hmargin) {
630 ✗ for (j = 0; j < 4; j++)
631 ✗ for (i = 0; i < hmargin; i++)
632 ✗ Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
633 ✗ U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
634 ✗ V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
635 }
636
637 ✗ Y += ystride * 4;
638 ✗ U += ustride;
639 ✗ V += vstride;
640 }
641
642 ✗ if (vmargin && y + vmargin == left) {
643 ✗ for (x = 0; x < width; x += 4) {
644 ✗ for (j = 0; j < vmargin; j++)
645 ✗ for (i = 0; i < 4; i++)
646 ✗ Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
647 ✗ U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
648 ✗ V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
649 }
650 ✗ if (hmargin) {
651 ✗ for (j = 0; j < vmargin; j++) {
652 ✗ for (i = 0; i < hmargin; i++)
653 ✗ Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
654 }
655 ✗ U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
656 ✗ V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
657 }
658
659 ✗ y += vmargin;
660 }
661
662 ✗ return y;
663 }
664
665
666 ✗ static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
667 const uint8_t *src, int src_size,
668 uint32_t vflipped)
669 {
670 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
671 dx2_decode_slice_410,
672 default_setup_lru,
673 AV_PIX_FMT_YUV410P, vflipped);
674 }
675
676 ✗ static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame,
677 int line, int left,
678 uint8_t lru[3][8])
679 {
680 int x, y;
681
682 ✗ int width = frame->width;
683
684 ✗ int ystride = frame->linesize[0];
685 ✗ int ustride = frame->linesize[1];
686 ✗ int vstride = frame->linesize[2];
687
688 ✗ uint8_t *Y = frame->data[0] + ystride * line;
689 ✗ uint8_t *U = frame->data[1] + (ustride >> 1) * line;
690 ✗ uint8_t *V = frame->data[2] + (vstride >> 1) * line;
691
692 int h, w, hmargin, vmargin;
693 int huvborder;
694
695 ✗ h = frame->height & ~1;
696 ✗ w = frame->width & ~1;
697 ✗ hmargin = frame->width - w;
698 ✗ vmargin = frame->height - h;
699 ✗ huvborder = AV_CEIL_RSHIFT(frame->width, 1) - 1;
700
701 ✗ for (y = 0; y < left - 1 && get_bits_left(gb) >= 3 * w + hmargin * 4; y += 2) {
702 ✗ for (x = 0; x < w; x += 2) {
703 ✗ Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
704 ✗ Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
705 ✗ Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
706 ✗ Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
707 ✗ U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
708 ✗ V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
709 }
710 ✗ if (hmargin) {
711 ✗ Y[x + 0 * ystride] = decode_sym(gb, lru[0]);
712 ✗ Y[x + 1 * ystride] = decode_sym(gb, lru[0]);
713 ✗ U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
714 ✗ V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
715 }
716
717 ✗ Y += ystride * 2;
718 ✗ U += ustride;
719 ✗ V += vstride;
720 }
721
722 ✗ if (vmargin) {
723 ✗ for (x = 0; x < width; x += 2) {
724 ✗ Y[x + 0] = decode_sym(gb, lru[0]);
725 ✗ U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
726 ✗ V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
727 }
728 ✗ if (hmargin) {
729 ✗ Y[x] = decode_sym(gb, lru[0]);
730 ✗ U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80;
731 ✗ V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80;
732 }
733 }
734
735 ✗ return y;
736 }
737
738 ✗ static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
739 const uint8_t *src, int src_size,
740 uint32_t vflipped)
741 {
742 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
743 dx2_decode_slice_420,
744 default_setup_lru,
745 AV_PIX_FMT_YUV420P, vflipped);
746 }
747
748 ✗ static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame,
749 int line, int left,
750 uint8_t lru[3][8])
751 {
752 int x, y;
753
754 ✗ int width = frame->width;
755
756 ✗ int ystride = frame->linesize[0];
757 ✗ int ustride = frame->linesize[1];
758 ✗ int vstride = frame->linesize[2];
759
760 ✗ uint8_t *Y = frame->data[0] + ystride * line;
761 ✗ uint8_t *U = frame->data[1] + ustride * line;
762 ✗ uint8_t *V = frame->data[2] + vstride * line;
763
764 ✗ for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) {
765 ✗ for (x = 0; x < width; x++) {
766 ✗ Y[x] = decode_sym(gb, lru[0]);
767 ✗ U[x] = decode_sym(gb, lru[1]) ^ 0x80;
768 ✗ V[x] = decode_sym(gb, lru[2]) ^ 0x80;
769 }
770
771 ✗ Y += ystride;
772 ✗ U += ustride;
773 ✗ V += vstride;
774 }
775
776 ✗ return y;
777 }
778
779 ✗ static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
780 const uint8_t *src, int src_size,
781 uint32_t vflipped)
782 {
783 ✗ return dxtory_decode_v2(avctx, pic, src, src_size,
784 dx2_decode_slice_444,
785 default_setup_lru,
786 AV_PIX_FMT_YUV444P, vflipped);
787 }
788
789 2 static int decode_frame(AVCodecContext *avctx, AVFrame *pic,
790 int *got_frame, AVPacket *avpkt)
791 {
792 2 const uint8_t *src = avpkt->data;
793 uint32_t type;
794 int vflipped, ret;
795
796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (avpkt->size < 16) {
797 ✗ av_log(avctx, AV_LOG_ERROR, "packet too small\n");
798 ✗ return AVERROR_INVALIDDATA;
799 }
800
801 2 type = AV_RB32(src);
802 2 vflipped = !!(type & 0x20);
803
804
1/13
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
2 switch (type) {
805 ✗ case 0x01000021:
806 case 0x01000001:
807 ✗ ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
808 AV_PIX_FMT_BGR24, 3, vflipped);
809 ✗ break;
810 ✗ case 0x01000029:
811 case 0x01000009:
812 ✗ ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16, vflipped);
813 ✗ break;
814 2 case 0x02000021:
815 case 0x02000001:
816 2 ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16, vflipped);
817 2 break;
818 ✗ case 0x02000029:
819 case 0x02000009:
820 ✗ ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16, vflipped);
821 ✗ break;
822 ✗ case 0x03000021:
823 case 0x03000001:
824 ✗ ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16, vflipped);
825 ✗ break;
826 ✗ case 0x03000029:
827 case 0x03000009:
828 ✗ ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16, vflipped);
829 ✗ break;
830 ✗ case 0x04000021:
831 case 0x04000001:
832 ✗ ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16, vflipped);
833 ✗ break;
834 ✗ case 0x04000029:
835 case 0x04000009:
836 ✗ ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16, vflipped);
837 ✗ break;
838 ✗ case 0x17000021:
839 case 0x17000001:
840 ✗ ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
841 AV_PIX_FMT_RGB565LE, 2, vflipped);
842 ✗ break;
843 ✗ case 0x17000029:
844 case 0x17000009:
845 ✗ ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1, vflipped);
846 ✗ break;
847 ✗ case 0x18000021:
848 case 0x19000021:
849 case 0x18000001:
850 case 0x19000001:
851 ✗ ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
852 AV_PIX_FMT_RGB555LE, 2, vflipped);
853 ✗ break;
854 ✗ case 0x18000029:
855 case 0x19000029:
856 case 0x18000009:
857 case 0x19000009:
858 ✗ ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0, vflipped);
859 ✗ break;
860 ✗ default:
861 ✗ avpriv_request_sample(avctx, "Frame header %"PRIX32, type);
862 ✗ return AVERROR_PATCHWELCOME;
863 }
864
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret)
866 ✗ return ret;
867
868 2 *got_frame = 1;
869
870 2 return avpkt->size;
871 }
872
873 const FFCodec ff_dxtory_decoder = {
874 .p.name = "dxtory",
875 CODEC_LONG_NAME("Dxtory"),
876 .p.type = AVMEDIA_TYPE_VIDEO,
877 .p.id = AV_CODEC_ID_DXTORY,
878 FF_CODEC_DECODE_CB(decode_frame),
879 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
880 };
881