FFmpeg coverage


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