blob: 6f8652ad499db66b6c3ed08ad05b0bd8d8b5456c
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 "get_bits.h" |
32 | #include "internal.h" |
33 | #include "unary.h" |
34 | |
35 | static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, |
36 | const uint8_t *src, int src_size, |
37 | int id, int bpp) |
38 | { |
39 | int h; |
40 | uint8_t *dst; |
41 | int ret; |
42 | |
43 | if (src_size < avctx->width * avctx->height * (int64_t)bpp) { |
44 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
45 | return AVERROR_INVALIDDATA; |
46 | } |
47 | |
48 | avctx->pix_fmt = id; |
49 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
50 | return ret; |
51 | |
52 | dst = pic->data[0]; |
53 | for (h = 0; h < avctx->height; h++) { |
54 | memcpy(dst, src, avctx->width * bpp); |
55 | src += avctx->width * bpp; |
56 | dst += pic->linesize[0]; |
57 | } |
58 | |
59 | return 0; |
60 | } |
61 | |
62 | static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, |
63 | const uint8_t *src, int src_size) |
64 | { |
65 | int h, w; |
66 | uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; |
67 | int ret; |
68 | |
69 | if (src_size < FFALIGN(avctx->width, 4) * FFALIGN(avctx->height, 4) * 9LL / 8) { |
70 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
71 | return AVERROR_INVALIDDATA; |
72 | } |
73 | |
74 | avctx->pix_fmt = AV_PIX_FMT_YUV410P; |
75 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
76 | return ret; |
77 | |
78 | Y1 = pic->data[0]; |
79 | Y2 = pic->data[0] + pic->linesize[0]; |
80 | Y3 = pic->data[0] + pic->linesize[0] * 2; |
81 | Y4 = pic->data[0] + pic->linesize[0] * 3; |
82 | U = pic->data[1]; |
83 | V = pic->data[2]; |
84 | for (h = 0; h < avctx->height; h += 4) { |
85 | for (w = 0; w < avctx->width; w += 4) { |
86 | AV_COPY32U(Y1 + w, src); |
87 | AV_COPY32U(Y2 + w, src + 4); |
88 | AV_COPY32U(Y3 + w, src + 8); |
89 | AV_COPY32U(Y4 + w, src + 12); |
90 | U[w >> 2] = src[16] + 0x80; |
91 | V[w >> 2] = src[17] + 0x80; |
92 | src += 18; |
93 | } |
94 | Y1 += pic->linesize[0] << 2; |
95 | Y2 += pic->linesize[0] << 2; |
96 | Y3 += pic->linesize[0] << 2; |
97 | Y4 += pic->linesize[0] << 2; |
98 | U += pic->linesize[1]; |
99 | V += pic->linesize[2]; |
100 | } |
101 | |
102 | return 0; |
103 | } |
104 | |
105 | static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, |
106 | const uint8_t *src, int src_size) |
107 | { |
108 | int h, w; |
109 | uint8_t *Y1, *Y2, *U, *V; |
110 | int ret; |
111 | |
112 | if (src_size < FFALIGN(avctx->width, 2) * FFALIGN(avctx->height, 2) * 3LL / 2) { |
113 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
114 | return AVERROR_INVALIDDATA; |
115 | } |
116 | |
117 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
118 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
119 | return ret; |
120 | |
121 | Y1 = pic->data[0]; |
122 | Y2 = pic->data[0] + pic->linesize[0]; |
123 | U = pic->data[1]; |
124 | V = pic->data[2]; |
125 | for (h = 0; h < avctx->height; h += 2) { |
126 | for (w = 0; w < avctx->width; w += 2) { |
127 | AV_COPY16(Y1 + w, src); |
128 | AV_COPY16(Y2 + w, src + 2); |
129 | U[w >> 1] = src[4] + 0x80; |
130 | V[w >> 1] = src[5] + 0x80; |
131 | src += 6; |
132 | } |
133 | Y1 += pic->linesize[0] << 1; |
134 | Y2 += pic->linesize[0] << 1; |
135 | U += pic->linesize[1]; |
136 | V += pic->linesize[2]; |
137 | } |
138 | |
139 | return 0; |
140 | } |
141 | |
142 | static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, |
143 | const uint8_t *src, int src_size) |
144 | { |
145 | int h, w; |
146 | uint8_t *Y, *U, *V; |
147 | int ret; |
148 | |
149 | if (src_size < avctx->width * avctx->height * 3LL) { |
150 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
151 | return AVERROR_INVALIDDATA; |
152 | } |
153 | |
154 | avctx->pix_fmt = AV_PIX_FMT_YUV444P; |
155 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
156 | return ret; |
157 | |
158 | Y = pic->data[0]; |
159 | U = pic->data[1]; |
160 | V = pic->data[2]; |
161 | for (h = 0; h < avctx->height; h++) { |
162 | for (w = 0; w < avctx->width; w++) { |
163 | Y[w] = *src++; |
164 | U[w] = *src++ ^ 0x80; |
165 | V[w] = *src++ ^ 0x80; |
166 | } |
167 | Y += pic->linesize[0]; |
168 | U += pic->linesize[1]; |
169 | V += pic->linesize[2]; |
170 | } |
171 | |
172 | return 0; |
173 | } |
174 | |
175 | static const uint8_t def_lru[8] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xFF }; |
176 | static const uint8_t def_lru_555[8] = { 0x00, 0x08, 0x10, 0x18, 0x1F }; |
177 | static const uint8_t def_lru_565[8] = { 0x00, 0x08, 0x10, 0x20, 0x30, 0x3F }; |
178 | |
179 | static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8]) |
180 | { |
181 | uint8_t c, val; |
182 | |
183 | c = get_unary(gb, 0, 8); |
184 | if (!c) { |
185 | val = get_bits(gb, 8); |
186 | memmove(lru + 1, lru, sizeof(*lru) * (8 - 1)); |
187 | } else { |
188 | val = lru[c - 1]; |
189 | memmove(lru + 1, lru, sizeof(*lru) * (c - 1)); |
190 | } |
191 | lru[0] = val; |
192 | |
193 | return val; |
194 | } |
195 | |
196 | static int check_slice_size(AVCodecContext *avctx, |
197 | const uint8_t *src, int src_size, |
198 | int slice_size, int off) |
199 | { |
200 | int cur_slice_size; |
201 | |
202 | if (slice_size > src_size - off) { |
203 | av_log(avctx, AV_LOG_ERROR, |
204 | "invalid slice size %d (only %d bytes left)\n", |
205 | slice_size, src_size - off); |
206 | return AVERROR_INVALIDDATA; |
207 | } |
208 | if (slice_size <= 16) { |
209 | av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", |
210 | slice_size); |
211 | return AVERROR_INVALIDDATA; |
212 | } |
213 | |
214 | cur_slice_size = AV_RL32(src + off); |
215 | if (cur_slice_size != slice_size - 16) { |
216 | av_log(avctx, AV_LOG_ERROR, |
217 | "Slice sizes mismatch: got %d instead of %d\n", |
218 | cur_slice_size, slice_size - 16); |
219 | } |
220 | |
221 | return 0; |
222 | } |
223 | |
224 | static int load_buffer(AVCodecContext *avctx, |
225 | const uint8_t *src, int src_size, |
226 | GetByteContext *gb, |
227 | int *nslices, int *off) |
228 | { |
229 | bytestream2_init(gb, src, src_size); |
230 | *nslices = bytestream2_get_le16(gb); |
231 | *off = FFALIGN(*nslices * 4 + 2, 16); |
232 | if (src_size < *off) { |
233 | av_log(avctx, AV_LOG_ERROR, "no slice data\n"); |
234 | return AVERROR_INVALIDDATA; |
235 | } |
236 | |
237 | if (!*nslices) { |
238 | avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices, |
239 | avctx->width, avctx->height); |
240 | return AVERROR_PATCHWELCOME; |
241 | } |
242 | |
243 | return 0; |
244 | } |
245 | |
246 | static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8], |
247 | int bits) |
248 | { |
249 | uint8_t c, val; |
250 | |
251 | c = get_unary(gb, 0, bits); |
252 | if (!c) { |
253 | val = get_bits(gb, bits); |
254 | memmove(lru + 1, lru, sizeof(*lru) * (6 - 1)); |
255 | } else { |
256 | val = lru[c - 1]; |
257 | memmove(lru + 1, lru, sizeof(*lru) * (c - 1)); |
258 | } |
259 | lru[0] = val; |
260 | |
261 | return val; |
262 | } |
263 | |
264 | typedef int (*decode_slice_func)(GetBitContext *gb, AVFrame *frame, |
265 | int line, int height, uint8_t lru[3][8]); |
266 | |
267 | typedef void (*setup_lru_func)(uint8_t lru[3][8]); |
268 | |
269 | static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, |
270 | const uint8_t *src, int src_size, |
271 | decode_slice_func decode_slice, |
272 | setup_lru_func setup_lru, |
273 | enum AVPixelFormat fmt) |
274 | { |
275 | GetByteContext gb; |
276 | GetBitContext gb2; |
277 | int nslices, slice, line = 0; |
278 | uint32_t off, slice_size; |
279 | uint8_t lru[3][8]; |
280 | int ret; |
281 | |
282 | ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off); |
283 | if (ret < 0) |
284 | return ret; |
285 | |
286 | avctx->pix_fmt = fmt; |
287 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
288 | return ret; |
289 | |
290 | for (slice = 0; slice < nslices; slice++) { |
291 | slice_size = bytestream2_get_le32(&gb); |
292 | |
293 | setup_lru(lru); |
294 | |
295 | ret = check_slice_size(avctx, src, src_size, slice_size, off); |
296 | if (ret < 0) |
297 | return ret; |
298 | |
299 | if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0) |
300 | return ret; |
301 | |
302 | line += decode_slice(&gb2, pic, line, avctx->height - line, lru); |
303 | |
304 | off += slice_size; |
305 | } |
306 | |
307 | if (avctx->height - line) { |
308 | av_log(avctx, AV_LOG_VERBOSE, |
309 | "Not enough slice data available, " |
310 | "cropping the frame by %d pixels\n", |
311 | avctx->height - line); |
312 | avctx->height = line; |
313 | } |
314 | |
315 | return 0; |
316 | } |
317 | |
318 | av_always_inline |
319 | static int dx2_decode_slice_5x5(GetBitContext *gb, AVFrame *frame, |
320 | int line, int left, uint8_t lru[3][8], |
321 | int is_565) |
322 | { |
323 | int x, y; |
324 | int r, g, b; |
325 | int width = frame->width; |
326 | int stride = frame->linesize[0]; |
327 | uint8_t *dst = frame->data[0] + stride * line; |
328 | |
329 | for (y = 0; y < left && get_bits_left(gb) > 16; y++) { |
330 | for (x = 0; x < width; x++) { |
331 | b = decode_sym_565(gb, lru[0], 5); |
332 | g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); |
333 | r = decode_sym_565(gb, lru[2], 5); |
334 | dst[x * 3 + 0] = (r << 3) | (r >> 2); |
335 | dst[x * 3 + 1] = is_565 ? (g << 2) | (g >> 4) : (g << 3) | (g >> 2); |
336 | dst[x * 3 + 2] = (b << 3) | (b >> 2); |
337 | } |
338 | |
339 | dst += stride; |
340 | } |
341 | |
342 | return y; |
343 | } |
344 | |
345 | static void setup_lru_555(uint8_t lru[3][8]) |
346 | { |
347 | memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); |
348 | memcpy(lru[1], def_lru_555, 8 * sizeof(*def_lru)); |
349 | memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); |
350 | } |
351 | |
352 | static void setup_lru_565(uint8_t lru[3][8]) |
353 | { |
354 | memcpy(lru[0], def_lru_555, 8 * sizeof(*def_lru)); |
355 | memcpy(lru[1], def_lru_565, 8 * sizeof(*def_lru)); |
356 | memcpy(lru[2], def_lru_555, 8 * sizeof(*def_lru)); |
357 | } |
358 | |
359 | static int dx2_decode_slice_555(GetBitContext *gb, AVFrame *frame, |
360 | int line, int left, uint8_t lru[3][8]) |
361 | { |
362 | return dx2_decode_slice_5x5(gb, frame, line, left, lru, 0); |
363 | } |
364 | |
365 | static int dx2_decode_slice_565(GetBitContext *gb, AVFrame *frame, |
366 | int line, int left, uint8_t lru[3][8]) |
367 | { |
368 | return dx2_decode_slice_5x5(gb, frame, line, left, lru, 1); |
369 | } |
370 | |
371 | static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, |
372 | const uint8_t *src, int src_size, int is_565) |
373 | { |
374 | enum AVPixelFormat fmt = AV_PIX_FMT_RGB24; |
375 | if (is_565) |
376 | return dxtory_decode_v2(avctx, pic, src, src_size, |
377 | dx2_decode_slice_565, |
378 | setup_lru_565, |
379 | fmt); |
380 | else |
381 | return dxtory_decode_v2(avctx, pic, src, src_size, |
382 | dx2_decode_slice_555, |
383 | setup_lru_555, |
384 | fmt); |
385 | } |
386 | |
387 | static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, |
388 | int line, int left, uint8_t lru[3][8]) |
389 | { |
390 | int x, y; |
391 | int width = frame->width; |
392 | int stride = frame->linesize[0]; |
393 | uint8_t *dst = frame->data[0] + stride * line; |
394 | |
395 | for (y = 0; y < left && get_bits_left(gb) > 16; y++) { |
396 | for (x = 0; x < width; x++) { |
397 | dst[x * 3 + 0] = decode_sym(gb, lru[0]); |
398 | dst[x * 3 + 1] = decode_sym(gb, lru[1]); |
399 | dst[x * 3 + 2] = decode_sym(gb, lru[2]); |
400 | } |
401 | |
402 | dst += stride; |
403 | } |
404 | |
405 | return y; |
406 | } |
407 | |
408 | static void default_setup_lru(uint8_t lru[3][8]) |
409 | { |
410 | int i; |
411 | |
412 | for (i = 0; i < 3; i++) |
413 | memcpy(lru[i], def_lru, 8 * sizeof(*def_lru)); |
414 | } |
415 | |
416 | static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, |
417 | const uint8_t *src, int src_size) |
418 | { |
419 | return dxtory_decode_v2(avctx, pic, src, src_size, |
420 | dx2_decode_slice_rgb, |
421 | default_setup_lru, |
422 | AV_PIX_FMT_BGR24); |
423 | } |
424 | |
425 | static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, |
426 | int line, int left, |
427 | uint8_t lru[3][8]) |
428 | { |
429 | int x, y, i, j; |
430 | int width = frame->width; |
431 | |
432 | int ystride = frame->linesize[0]; |
433 | int ustride = frame->linesize[1]; |
434 | int vstride = frame->linesize[2]; |
435 | |
436 | uint8_t *Y = frame->data[0] + ystride * line; |
437 | uint8_t *U = frame->data[1] + (ustride >> 2) * line; |
438 | uint8_t *V = frame->data[2] + (vstride >> 2) * line; |
439 | |
440 | for (y = 0; y < left - 3 && get_bits_left(gb) > 16; y += 4) { |
441 | for (x = 0; x < width; x += 4) { |
442 | for (j = 0; j < 4; j++) |
443 | for (i = 0; i < 4; i++) |
444 | Y[x + i + j * ystride] = decode_sym(gb, lru[0]); |
445 | U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; |
446 | V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; |
447 | } |
448 | |
449 | Y += ystride << 2; |
450 | U += ustride; |
451 | V += vstride; |
452 | } |
453 | |
454 | return y; |
455 | } |
456 | |
457 | |
458 | static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, |
459 | const uint8_t *src, int src_size) |
460 | { |
461 | return dxtory_decode_v2(avctx, pic, src, src_size, |
462 | dx2_decode_slice_410, |
463 | default_setup_lru, |
464 | AV_PIX_FMT_YUV410P); |
465 | } |
466 | |
467 | static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, |
468 | int line, int left, |
469 | uint8_t lru[3][8]) |
470 | { |
471 | int x, y; |
472 | |
473 | int width = frame->width; |
474 | |
475 | int ystride = frame->linesize[0]; |
476 | int ustride = frame->linesize[1]; |
477 | int vstride = frame->linesize[2]; |
478 | |
479 | uint8_t *Y = frame->data[0] + ystride * line; |
480 | uint8_t *U = frame->data[1] + (ustride >> 1) * line; |
481 | uint8_t *V = frame->data[2] + (vstride >> 1) * line; |
482 | |
483 | |
484 | for (y = 0; y < left - 1 && get_bits_left(gb) > 16; y += 2) { |
485 | for (x = 0; x < width; x += 2) { |
486 | Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); |
487 | Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); |
488 | Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]); |
489 | Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]); |
490 | U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; |
491 | V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; |
492 | } |
493 | |
494 | Y += ystride << 1; |
495 | U += ustride; |
496 | V += vstride; |
497 | } |
498 | |
499 | return y; |
500 | } |
501 | |
502 | static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, |
503 | const uint8_t *src, int src_size) |
504 | { |
505 | return dxtory_decode_v2(avctx, pic, src, src_size, |
506 | dx2_decode_slice_420, |
507 | default_setup_lru, |
508 | AV_PIX_FMT_YUV420P); |
509 | } |
510 | |
511 | static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, |
512 | int line, int left, |
513 | uint8_t lru[3][8]) |
514 | { |
515 | int x, y; |
516 | |
517 | int width = frame->width; |
518 | |
519 | int ystride = frame->linesize[0]; |
520 | int ustride = frame->linesize[1]; |
521 | int vstride = frame->linesize[2]; |
522 | |
523 | uint8_t *Y = frame->data[0] + ystride * line; |
524 | uint8_t *U = frame->data[1] + ustride * line; |
525 | uint8_t *V = frame->data[2] + vstride * line; |
526 | |
527 | for (y = 0; y < left && get_bits_left(gb) > 16; y++) { |
528 | for (x = 0; x < width; x++) { |
529 | Y[x] = decode_sym(gb, lru[0]); |
530 | U[x] = decode_sym(gb, lru[1]) ^ 0x80; |
531 | V[x] = decode_sym(gb, lru[2]) ^ 0x80; |
532 | } |
533 | |
534 | Y += ystride; |
535 | U += ustride; |
536 | V += vstride; |
537 | } |
538 | |
539 | return y; |
540 | } |
541 | |
542 | static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, |
543 | const uint8_t *src, int src_size) |
544 | { |
545 | return dxtory_decode_v2(avctx, pic, src, src_size, |
546 | dx2_decode_slice_444, |
547 | default_setup_lru, |
548 | AV_PIX_FMT_YUV444P); |
549 | } |
550 | |
551 | static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, |
552 | AVPacket *avpkt) |
553 | { |
554 | AVFrame *pic = data; |
555 | const uint8_t *src = avpkt->data; |
556 | int ret; |
557 | |
558 | if (avpkt->size < 16) { |
559 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
560 | return AVERROR_INVALIDDATA; |
561 | } |
562 | |
563 | switch (AV_RB32(src)) { |
564 | case 0x01000001: |
565 | ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, |
566 | AV_PIX_FMT_BGR24, 3); |
567 | break; |
568 | case 0x01000009: |
569 | ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16); |
570 | break; |
571 | case 0x02000001: |
572 | ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16); |
573 | break; |
574 | case 0x02000009: |
575 | ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16); |
576 | break; |
577 | case 0x03000001: |
578 | ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16); |
579 | break; |
580 | case 0x03000009: |
581 | ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16); |
582 | break; |
583 | case 0x04000001: |
584 | ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16); |
585 | break; |
586 | case 0x04000009: |
587 | ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16); |
588 | break; |
589 | case 0x17000001: |
590 | ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, |
591 | AV_PIX_FMT_RGB565LE, 2); |
592 | break; |
593 | case 0x17000009: |
594 | ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1); |
595 | break; |
596 | case 0x18000001: |
597 | case 0x19000001: |
598 | ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, |
599 | AV_PIX_FMT_RGB555LE, 2); |
600 | break; |
601 | case 0x18000009: |
602 | case 0x19000009: |
603 | ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0); |
604 | break; |
605 | default: |
606 | avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src)); |
607 | return AVERROR_PATCHWELCOME; |
608 | } |
609 | |
610 | if (ret) |
611 | return ret; |
612 | |
613 | pic->pict_type = AV_PICTURE_TYPE_I; |
614 | pic->key_frame = 1; |
615 | *got_frame = 1; |
616 | |
617 | return avpkt->size; |
618 | } |
619 | |
620 | AVCodec ff_dxtory_decoder = { |
621 | .name = "dxtory", |
622 | .long_name = NULL_IF_CONFIG_SMALL("Dxtory"), |
623 | .type = AVMEDIA_TYPE_VIDEO, |
624 | .id = AV_CODEC_ID_DXTORY, |
625 | .decode = decode_frame, |
626 | .capabilities = AV_CODEC_CAP_DR1, |
627 | }; |
628 |