dxtory: compressed RGB555/RGB565 decoding support
[libav.git] / libavcodec / dxtory.c
1 /*
2 * Dxtory decoder
3 *
4 * Copyright (c) 2011 Konstantin Shishkov
5 *
6 * This file is part of Libav.
7 *
8 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #define BITSTREAM_READER_LE
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "get_bits.h"
27 #include "internal.h"
28 #include "unary.h"
29 #include "libavutil/common.h"
30 #include "libavutil/intreadwrite.h"
31
32 static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic,
33 const uint8_t *src, int src_size,
34 int id, int bpp)
35 {
36 int h;
37 uint8_t *dst;
38 int ret;
39
40 if (src_size < avctx->width * avctx->height * bpp) {
41 av_log(avctx, AV_LOG_ERROR, "packet too small\n");
42 return AVERROR_INVALIDDATA;
43 }
44
45 avctx->pix_fmt = id;
46 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
47 return ret;
48
49 dst = pic->data[0];
50 for (h = 0; h < avctx->height; h++) {
51 memcpy(dst, src, avctx->width * bpp);
52 src += avctx->width * bpp;
53 dst += pic->linesize[0];
54 }
55
56 return 0;
57 }
58
59 static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic,
60 const uint8_t *src, int src_size)
61 {
62 int h, w;
63 uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V;
64 int ret;
65
66 if (src_size < avctx->width * avctx->height * 18 / 16) {
67 av_log(avctx, AV_LOG_ERROR, "packet too small\n");
68 return AVERROR_INVALIDDATA;
69 }
70
71 avctx->pix_fmt = AV_PIX_FMT_YUV410P;
72 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
73 return ret;
74
75 Y1 = pic->data[0];
76 Y2 = pic->data[0] + pic->linesize[0];
77 Y3 = pic->data[0] + pic->linesize[0] * 2;
78 Y4 = pic->data[0] + pic->linesize[0] * 3;
79 U = pic->data[1];
80 V = pic->data[2];
81 for (h = 0; h < avctx->height; h += 4) {
82 for (w = 0; w < avctx->width; w += 4) {
83 AV_COPY32(Y1 + w, src);
84 AV_COPY32(Y2 + w, src + 4);
85 AV_COPY32(Y3 + w, src + 8);
86 AV_COPY32(Y4 + w, src + 12);
87 U[w >> 2] = src[16] + 0x80;
88 V[w >> 2] = src[17] + 0x80;
89 src += 18;
90 }
91 Y1 += pic->linesize[0] << 2;
92 Y2 += pic->linesize[0] << 2;
93 Y3 += pic->linesize[0] << 2;
94 Y4 += pic->linesize[0] << 2;
95 U += pic->linesize[1];
96 V += pic->linesize[2];
97 }
98
99 return 0;
100 }
101
102 static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic,
103 const uint8_t *src, int src_size)
104 {
105 int h, w;
106 uint8_t *Y1, *Y2, *U, *V;
107 int ret;
108
109 if (src_size < avctx->width * avctx->height * 3 / 2) {
110 av_log(avctx, AV_LOG_ERROR, "packet too small\n");
111 return AVERROR_INVALIDDATA;
112 }
113
114 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
115 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
116 return ret;
117
118 Y1 = pic->data[0];
119 Y2 = pic->data[0] + pic->linesize[0];
120 U = pic->data[1];
121 V = pic->data[2];
122 for (h = 0; h < avctx->height; h += 2) {
123 for (w = 0; w < avctx->width; w += 2) {
124 AV_COPY16(Y1 + w, src);
125 AV_COPY16(Y2 + w, src + 2);
126 U[w >> 1] = src[4] + 0x80;
127 V[w >> 1] = src[5] + 0x80;
128 src += 6;
129 }
130 Y1 += pic->linesize[0] << 1;
131 Y2 += pic->linesize[0] << 1;
132 U += pic->linesize[1];
133 V += pic->linesize[2];
134 }
135
136 return 0;
137 }
138
139 static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic,
140 const uint8_t *src, int src_size)
141 {
142 int h, w;
143 uint8_t *Y, *U, *V;
144 int ret;
145
146 if (src_size < avctx->width * avctx->height * 3) {
147 av_log(avctx, AV_LOG_ERROR, "packet too small\n");
148 return AVERROR_INVALIDDATA;
149 }
150
151 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
152 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
153 return ret;
154
155 Y = pic->data[0];
156 U = pic->data[1];
157 V = pic->data[2];
158 for (h = 0; h < avctx->height; h++) {
159 for (w = 0; w < avctx->width; w++) {
160 Y[w] = *src++;
161 U[w] = *src++ ^ 0x80;
162 V[w] = *src++ ^ 0x80;
163 }
164 Y += pic->linesize[0];
165 U += pic->linesize[1];
166 V += pic->linesize[2];
167 }
168
169 return 0;
170 }
171
172 const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF };
173 const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F };
174 const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F };
175
176 static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
177 {
178 uint8_t c, val;
179
180 c = get_unary(gb, 0, 8);
181 if (!c) {
182 val = get_bits(gb, 8);
183 memmove(lru + 1, lru, sizeof(*lru) * (8 - 1));
184 } else {
185 val = lru[c - 1];
186 memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
187 }
188 lru[0] = val;
189
190 return val;
191 }
192
193 static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8],
194 int bits)
195 {
196 uint8_t c, val;
197
198 c = get_unary(gb, 0, bits);
199 if (!c) {
200 val = get_bits(gb, bits);
201 memmove(lru + 1, lru, sizeof(*lru) * (6 - 1));
202 } else {
203 val = lru[c - 1];
204 memmove(lru + 1, lru, sizeof(*lru) * (c - 1));
205 }
206 lru[0] = val;
207
208 return val;
209 }
210
211 static int dx2_decode_slice_565(GetBitContext *gb, int width, int height,
212 uint8_t *dst, int stride, int is_565)
213 {
214 int x, y;
215 int r, g, b;
216 uint8_t lru[3][8];
217
218 memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru));
219 memcpy(lru[1], is_565 ? def_lru_565 : def_lru_555, 8 * sizeof(*def_lru));
220 memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru));
221
222 for (y = 0; y < height; y++) {
223 for (x = 0; x < width; x++) {
224 b = decode_sym_565(gb, lru[0], 5);
225 g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5);
226 r = decode_sym_565(gb, lru[2], 5);
227 dst[x * 3 + 0] = (r << 3) | (r >> 2);
228 dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2);
229 dst[x * 3 + 2] = (b << 3) | (b >> 2);
230 }
231
232 dst += stride;
233 }
234
235 return 0;
236 }
237
238 static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
239 const uint8_t *src, int src_size, int is_565)
240 {
241 GetByteContext gb;
242 GetBitContext gb2;
243 int nslices, slice, slice_height;
244 uint32_t off, slice_size;
245 uint8_t *dst;
246 int ret;
247
248 bytestream2_init(&gb, src, src_size);
249 nslices = bytestream2_get_le16(&gb);
250 off = FFALIGN(nslices * 4 + 2, 16);
251 if (src_size < off) {
252 av_log(avctx, AV_LOG_ERROR, "no slice data\n");
253 return AVERROR_INVALIDDATA;
254 }
255
256 if (!nslices || avctx->height % nslices) {
257 avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
258 avctx->width, avctx->height);
259 return AVERROR_PATCHWELCOME;
260 }
261
262 slice_height = avctx->height / nslices;
263 avctx->pix_fmt = AV_PIX_FMT_RGB24;
264 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
265 return ret;
266
267 dst = pic->data[0];
268 for (slice = 0; slice < nslices; slice++) {
269 slice_size = bytestream2_get_le32(&gb);
270 if (slice_size > src_size - off) {
271 av_log(avctx, AV_LOG_ERROR,
272 "invalid slice size %d (only %d bytes left)\n",
273 slice_size, src_size - off);
274 return AVERROR_INVALIDDATA;
275 }
276 if (slice_size <= 16) {
277 av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
278 return AVERROR_INVALIDDATA;
279 }
280
281 if (AV_RL32(src + off) != slice_size - 16) {
282 av_log(avctx, AV_LOG_ERROR,
283 "Slice sizes mismatch: got %d instead of %d\n",
284 AV_RL32(src + off), slice_size - 16);
285 }
286 init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
287 dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst,
288 pic->linesize[0], is_565);
289
290 dst += pic->linesize[0] * slice_height;
291 off += slice_size;
292 }
293
294 return 0;
295 }
296
297 static int dx2_decode_slice_rgb(GetBitContext *gb, int width, int height,
298 uint8_t *dst, int stride)
299 {
300 int x, y, i;
301 uint8_t lru[3][8];
302
303 for (i = 0; i < 3; i++)
304 memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
305
306 for (y = 0; y < height; y++) {
307 for (x = 0; x < width; x++) {
308 dst[x * 3 + 0] = decode_sym(gb, lru[0]);
309 dst[x * 3 + 1] = decode_sym(gb, lru[1]);
310 dst[x * 3 + 2] = decode_sym(gb, lru[2]);
311 }
312
313 dst += stride;
314 }
315
316 return 0;
317 }
318
319 static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
320 const uint8_t *src, int src_size)
321 {
322 GetByteContext gb;
323 GetBitContext gb2;
324 int nslices, slice, slice_height;
325 uint32_t off, slice_size;
326 uint8_t *dst;
327 int ret;
328
329 bytestream2_init(&gb, src, src_size);
330 nslices = bytestream2_get_le16(&gb);
331 off = FFALIGN(nslices * 4 + 2, 16);
332 if (src_size < off) {
333 av_log(avctx, AV_LOG_ERROR, "no slice data\n");
334 return AVERROR_INVALIDDATA;
335 }
336
337 if (!nslices || avctx->height % nslices) {
338 avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
339 avctx->width, avctx->height);
340 return AVERROR_PATCHWELCOME;
341 }
342
343 slice_height = avctx->height / nslices;
344 avctx->pix_fmt = AV_PIX_FMT_BGR24;
345 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
346 return ret;
347
348 dst = pic->data[0];
349 for (slice = 0; slice < nslices; slice++) {
350 slice_size = bytestream2_get_le32(&gb);
351 if (slice_size > src_size - off) {
352 av_log(avctx, AV_LOG_ERROR,
353 "invalid slice size %d (only %d bytes left)\n",
354 slice_size, src_size - off);
355 return AVERROR_INVALIDDATA;
356 }
357 if (slice_size <= 16) {
358 av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
359 return AVERROR_INVALIDDATA;
360 }
361
362 if (AV_RL32(src + off) != slice_size - 16) {
363 av_log(avctx, AV_LOG_ERROR,
364 "Slice sizes mismatch: got %d instead of %d\n",
365 AV_RL32(src + off), slice_size - 16);
366 }
367 init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
368 dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst,
369 pic->linesize[0]);
370
371 dst += pic->linesize[0] * slice_height;
372 off += slice_size;
373 }
374
375 return 0;
376 }
377
378 static int dx2_decode_slice_410(GetBitContext *gb, int width, int height,
379 uint8_t *Y, uint8_t *U, uint8_t *V,
380 int ystride, int ustride, int vstride)
381 {
382 int x, y, i, j;
383 uint8_t lru[3][8];
384
385 for (i = 0; i < 3; i++)
386 memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
387
388 for (y = 0; y < height; y += 4) {
389 for (x = 0; x < width; x += 4) {
390 for (j = 0; j < 4; j++)
391 for (i = 0; i < 4; i++)
392 Y[x + i + j * ystride] = decode_sym(gb, lru[0]);
393 U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80;
394 V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80;
395 }
396
397 Y += ystride << 2;
398 U += ustride;
399 V += vstride;
400 }
401
402 return 0;
403 }
404
405 static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
406 const uint8_t *src, int src_size)
407 {
408 GetByteContext gb;
409 GetBitContext gb2;
410 int nslices, slice, slice_height, ref_slice_height;
411 int cur_y, next_y;
412 uint32_t off, slice_size;
413 uint8_t *Y, *U, *V;
414 int ret;
415
416 bytestream2_init(&gb, src, src_size);
417 nslices = bytestream2_get_le16(&gb);
418 off = FFALIGN(nslices * 4 + 2, 16);
419 if (src_size < off) {
420 av_log(avctx, AV_LOG_ERROR, "no slice data\n");
421 return AVERROR_INVALIDDATA;
422 }
423
424 if (!nslices || avctx->height % nslices) {
425 avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
426 avctx->width, avctx->height);
427 return AVERROR_PATCHWELCOME;
428 }
429
430 ref_slice_height = avctx->height / nslices;
431 if ((avctx->width & 3) || (avctx->height & 3)) {
432 avpriv_request_sample(avctx, "Frame dimensions %dx%d",
433 avctx->width, avctx->height);
434 }
435
436 avctx->pix_fmt = AV_PIX_FMT_YUV410P;
437 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
438 return ret;
439
440 Y = pic->data[0];
441 U = pic->data[1];
442 V = pic->data[2];
443
444 cur_y = 0;
445 next_y = ref_slice_height;
446 for (slice = 0; slice < nslices; slice++) {
447 slice_size = bytestream2_get_le32(&gb);
448 slice_height = (next_y & ~3) - (cur_y & ~3);
449 if (slice_size > src_size - off) {
450 av_log(avctx, AV_LOG_ERROR,
451 "invalid slice size %d (only %d bytes left)\n",
452 slice_size, src_size - off);
453 return AVERROR_INVALIDDATA;
454 }
455 if (slice_size <= 16) {
456 av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
457 return AVERROR_INVALIDDATA;
458 }
459
460 if (AV_RL32(src + off) != slice_size - 16) {
461 av_log(avctx, AV_LOG_ERROR,
462 "Slice sizes mismatch: got %d instead of %d\n",
463 AV_RL32(src + off), slice_size - 16);
464 }
465 init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
466 dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V,
467 pic->linesize[0], pic->linesize[1],
468 pic->linesize[2]);
469
470 Y += pic->linesize[0] * slice_height;
471 U += pic->linesize[1] * (slice_height >> 2);
472 V += pic->linesize[2] * (slice_height >> 2);
473 off += slice_size;
474 cur_y = next_y;
475 next_y += ref_slice_height;
476 }
477
478 return 0;
479 }
480
481 static int dx2_decode_slice_420(GetBitContext *gb, int width, int height,
482 uint8_t *Y, uint8_t *U, uint8_t *V,
483 int ystride, int ustride, int vstride)
484 {
485 int x, y, i;
486 uint8_t lru[3][8];
487
488 for (i = 0; i < 3; i++)
489 memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
490
491 for (y = 0; y < height; y+=2) {
492 for (x = 0; x < width; x += 2) {
493 Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
494 Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
495 Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
496 Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
497 U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
498 V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
499 }
500
501 Y += ystride << 1;
502 U += ustride;
503 V += vstride;
504 }
505
506 return 0;
507 }
508
509 static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
510 const uint8_t *src, int src_size)
511 {
512 GetByteContext gb;
513 GetBitContext gb2;
514 int nslices, slice, slice_height, ref_slice_height;
515 int cur_y, next_y;
516 uint32_t off, slice_size;
517 uint8_t *Y, *U, *V;
518 int ret;
519
520 bytestream2_init(&gb, src, src_size);
521 nslices = bytestream2_get_le16(&gb);
522 off = FFALIGN(nslices * 4 + 2, 16);
523 if (src_size < off) {
524 av_log(avctx, AV_LOG_ERROR, "no slice data\n");
525 return AVERROR_INVALIDDATA;
526 }
527
528 if (!nslices || avctx->height % nslices) {
529 avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
530 avctx->width, avctx->height);
531 return AVERROR_PATCHWELCOME;
532 }
533
534 ref_slice_height = avctx->height / nslices;
535 if ((avctx->width & 1) || (avctx->height & 1)) {
536 avpriv_request_sample(avctx, "Frame dimensions %dx%d",
537 avctx->width, avctx->height);
538 }
539
540 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
541 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
542 return ret;
543
544 Y = pic->data[0];
545 U = pic->data[1];
546 V = pic->data[2];
547
548 cur_y = 0;
549 next_y = ref_slice_height;
550 for (slice = 0; slice < nslices; slice++) {
551 slice_size = bytestream2_get_le32(&gb);
552 slice_height = (next_y & ~1) - (cur_y & ~1);
553 if (slice_size > src_size - off) {
554 av_log(avctx, AV_LOG_ERROR,
555 "invalid slice size %d (only %d bytes left)\n",
556 slice_size, src_size - off);
557 return AVERROR_INVALIDDATA;
558 }
559 if (slice_size <= 16) {
560 av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
561 return AVERROR_INVALIDDATA;
562 }
563
564 if (AV_RL32(src + off) != slice_size - 16) {
565 av_log(avctx, AV_LOG_ERROR,
566 "Slice sizes mismatch: got %d instead of %d\n",
567 AV_RL32(src + off), slice_size - 16);
568 }
569 init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
570 dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
571 pic->linesize[0], pic->linesize[1],
572 pic->linesize[2]);
573
574 Y += pic->linesize[0] * slice_height;
575 U += pic->linesize[1] * (slice_height >> 1);
576 V += pic->linesize[2] * (slice_height >> 1);
577 off += slice_size;
578 cur_y = next_y;
579 next_y += ref_slice_height;
580 }
581
582 return 0;
583 }
584
585 static int dx2_decode_slice_444(GetBitContext *gb, int width, int height,
586 uint8_t *Y, uint8_t *U, uint8_t *V,
587 int ystride, int ustride, int vstride)
588 {
589 int x, y, i;
590 uint8_t lru[3][8];
591
592 for (i = 0; i < 3; i++)
593 memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
594
595 for (y = 0; y < height; y++) {
596 for (x = 0; x < width; x++) {
597 Y[x] = decode_sym(gb, lru[0]);
598 U[x] = decode_sym(gb, lru[1]) ^ 0x80;
599 V[x] = decode_sym(gb, lru[2]) ^ 0x80;
600 }
601
602 Y += ystride;
603 U += ustride;
604 V += vstride;
605 }
606
607 return 0;
608 }
609
610 static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
611 const uint8_t *src, int src_size)
612 {
613 GetByteContext gb;
614 GetBitContext gb2;
615 int nslices, slice, slice_height;
616 uint32_t off, slice_size;
617 uint8_t *Y, *U, *V;
618 int ret;
619
620 bytestream2_init(&gb, src, src_size);
621 nslices = bytestream2_get_le16(&gb);
622 off = FFALIGN(nslices * 4 + 2, 16);
623 if (src_size < off) {
624 av_log(avctx, AV_LOG_ERROR, "no slice data\n");
625 return AVERROR_INVALIDDATA;
626 }
627
628 if (!nslices || avctx->height % nslices) {
629 avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
630 avctx->width, avctx->height);
631 return AVERROR_PATCHWELCOME;
632 }
633
634 slice_height = avctx->height / nslices;
635
636 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
637 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
638 return ret;
639
640 Y = pic->data[0];
641 U = pic->data[1];
642 V = pic->data[2];
643
644 for (slice = 0; slice < nslices; slice++) {
645 slice_size = bytestream2_get_le32(&gb);
646 if (slice_size > src_size - off) {
647 av_log(avctx, AV_LOG_ERROR,
648 "invalid slice size %d (only %d bytes left)\n",
649 slice_size, src_size - off);
650 return AVERROR_INVALIDDATA;
651 }
652 if (slice_size <= 16) {
653 av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
654 return AVERROR_INVALIDDATA;
655 }
656
657 if (AV_RL32(src + off) != slice_size - 16) {
658 av_log(avctx, AV_LOG_ERROR,
659 "Slice sizes mismatch: got %d instead of %d\n",
660 AV_RL32(src + off), slice_size - 16);
661 }
662 init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
663 dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V,
664 pic->linesize[0], pic->linesize[1],
665 pic->linesize[2]);
666
667 Y += pic->linesize[0] * slice_height;
668 U += pic->linesize[1] * slice_height;
669 V += pic->linesize[2] * slice_height;
670 off += slice_size;
671 }
672
673 return 0;
674 }
675
676 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
677 AVPacket *avpkt)
678 {
679 AVFrame *pic = data;
680 const uint8_t *src = avpkt->data;
681 int ret;
682
683 if (avpkt->size < 16) {
684 av_log(avctx, AV_LOG_ERROR, "packet too small\n");
685 return AVERROR_INVALIDDATA;
686 }
687
688 switch (AV_RB32(src)) {
689 case 0x01000001:
690 ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
691 AV_PIX_FMT_BGR24, 3);
692 break;
693 case 0x01000009:
694 ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16);
695 break;
696 case 0x02000001:
697 ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16);
698 break;
699 case 0x02000009:
700 ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16);
701 break;
702 case 0x03000001:
703 ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16);
704 break;
705 case 0x03000009:
706 ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16);
707 break;
708 case 0x04000001:
709 ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16);
710 break;
711 case 0x04000009:
712 ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16);
713 break;
714 case 0x17000001:
715 ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
716 AV_PIX_FMT_RGB565LE, 2);
717 break;
718 case 0x17000009:
719 ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1);
720 break;
721 case 0x18000001:
722 case 0x19000001:
723 ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16,
724 AV_PIX_FMT_RGB555LE, 2);
725 break;
726 case 0x18000009:
727 case 0x19000009:
728 ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0);
729 break;
730 default:
731 avpriv_request_sample(avctx, "Frame header %X", AV_RB32(src));
732 return AVERROR_PATCHWELCOME;
733 }
734
735 if (ret)
736 return ret;
737
738 pic->pict_type = AV_PICTURE_TYPE_I;
739 pic->key_frame = 1;
740 *got_frame = 1;
741
742 return avpkt->size;
743 }
744
745 AVCodec ff_dxtory_decoder = {
746 .name = "dxtory",
747 .long_name = NULL_IF_CONFIG_SMALL("Dxtory"),
748 .type = AVMEDIA_TYPE_VIDEO,
749 .id = AV_CODEC_ID_DXTORY,
750 .decode = decode_frame,
751 .capabilities = CODEC_CAP_DR1,
752 };