FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dxtory.c
Date: 2026-05-03 13:33:45
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