FFmpeg
Loading...
Searching...
No Matches
dds.c
Go to the documentation of this file.
1/*
2 * DirectDraw Surface image decoder
3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * DDS decoder
25 *
26 * https://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx
27 */
28
29#include <stdint.h>
30
32#include "libavutil/libm.h"
33#include "libavutil/imgutils.h"
34
35#include "avcodec.h"
36#include "bytestream.h"
37#include "codec_internal.h"
38#include "decode.h"
39#include "texturedsp.h"
40
41#define DDPF_FOURCC (1 << 2)
42#define DDPF_PALETTE (1 << 5)
43#define DDPF_NORMALMAP (1U << 31)
44
60
99
111
113{
114 DDSContext *ctx = avctx->priv_data;
115 GetByteContext *gbc = &ctx->gbc;
116 uint32_t flags, fourcc, gimp_tag;
117 enum DDSDXGIFormat dxgi;
118 int size, bpp, r, g, b, a;
119 int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;
120
121 /* Alternative DDS implementations use reserved1 as custom header. */
122 bytestream2_skip(gbc, 4 * 3);
123 gimp_tag = bytestream2_get_le32(gbc);
124 alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');
125 ycocg_classic = gimp_tag == MKTAG('Y', 'C', 'G', '1');
126 ycocg_scaled = gimp_tag == MKTAG('Y', 'C', 'G', '2');
127 bytestream2_skip(gbc, 4 * 7);
128
129 /* Now the real DDPF starts. */
130 size = bytestream2_get_le32(gbc);
131 if (size != 32) {
132 av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);
133 return AVERROR_INVALIDDATA;
134 }
135 flags = bytestream2_get_le32(gbc);
136 ctx->compressed = flags & DDPF_FOURCC;
137 ctx->paletted = flags & DDPF_PALETTE;
138 normal_map = flags & DDPF_NORMALMAP;
139 fourcc = bytestream2_get_le32(gbc);
140
141 if (ctx->compressed && ctx->paletted) {
142 av_log(avctx, AV_LOG_WARNING,
143 "Disabling invalid palette flag for compressed dds.\n");
144 ctx->paletted = 0;
145 }
146
147 bpp = ctx->bpp = bytestream2_get_le32(gbc); // rgbbitcount
148 r = bytestream2_get_le32(gbc); // rbitmask
149 g = bytestream2_get_le32(gbc); // gbitmask
150 b = bytestream2_get_le32(gbc); // bbitmask
151 a = bytestream2_get_le32(gbc); // abitmask
152
153 bytestream2_skip(gbc, 4); // caps
154 bytestream2_skip(gbc, 4); // caps2
155 bytestream2_skip(gbc, 4); // caps3
156 bytestream2_skip(gbc, 4); // caps4
157 bytestream2_skip(gbc, 4); // reserved2
158
159 av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "
160 "r 0x%x g 0x%x b 0x%x a 0x%x\n", av_fourcc2str(fourcc), bpp, r, g, b, a);
161 if (gimp_tag)
162 av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", av_fourcc2str(gimp_tag));
163
164 if (ctx->compressed)
165 avctx->pix_fmt = AV_PIX_FMT_RGBA;
166
167 if (ctx->compressed) {
168 ctx->dec.raw_ratio = 16;
169 switch (fourcc) {
170 case MKTAG('D', 'X', 'T', '1'):
171 ctx->dec.tex_ratio = 8;
172 ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
173 break;
174 case MKTAG('D', 'X', 'T', '2'):
175 ctx->dec.tex_ratio = 16;
176 ctx->dec.tex_funct = ctx->texdsp.dxt2_block;
177 break;
178 case MKTAG('D', 'X', 'T', '3'):
179 ctx->dec.tex_ratio = 16;
180 ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
181 break;
182 case MKTAG('D', 'X', 'T', '4'):
183 ctx->dec.tex_ratio = 16;
184 ctx->dec.tex_funct = ctx->texdsp.dxt4_block;
185 break;
186 case MKTAG('D', 'X', 'T', '5'):
187 ctx->dec.tex_ratio = 16;
188 if (ycocg_scaled)
189 ctx->dec.tex_funct = ctx->texdsp.dxt5ys_block;
190 else if (ycocg_classic)
191 ctx->dec.tex_funct = ctx->texdsp.dxt5y_block;
192 else
193 ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
194 break;
195 case MKTAG('R', 'X', 'G', 'B'):
196 ctx->dec.tex_ratio = 16;
197 ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
198 /* This format may be considered as a normal map,
199 * but it is handled differently in a separate postproc. */
200 ctx->postproc = DDS_SWIZZLE_RXGB;
201 normal_map = 0;
202 break;
203 case MKTAG('A', 'T', 'I', '1'):
204 case MKTAG('B', 'C', '4', 'U'):
205 ctx->dec.tex_ratio = 8;
206 ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
207 break;
208 case MKTAG('B', 'C', '4', 'S'):
209 ctx->dec.tex_ratio = 8;
210 ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
211 break;
212 case MKTAG('A', 'T', 'I', '2'):
213 /* RGT2 variant with swapped R and G (3Dc)*/
214 ctx->dec.tex_ratio = 16;
215 ctx->dec.tex_funct = ctx->texdsp.dxn3dc_block;
216 break;
217 case MKTAG('B', 'C', '5', 'U'):
218 ctx->dec.tex_ratio = 16;
219 ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
220 break;
221 case MKTAG('B', 'C', '5', 'S'):
222 ctx->dec.tex_ratio = 16;
223 ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
224 break;
225 case MKTAG('U', 'Y', 'V', 'Y'):
226 ctx->compressed = 0;
228 break;
229 case MKTAG('Y', 'U', 'Y', '2'):
230 ctx->compressed = 0;
232 break;
233 case MKTAG('P', '8', ' ', ' '):
234 /* ATI Palette8, same as normal palette */
235 ctx->compressed = 0;
236 ctx->paletted = 1;
237 avctx->pix_fmt = AV_PIX_FMT_PAL8;
238 break;
239 case MKTAG('G', '1', ' ', ' '):
240 ctx->compressed = 0;
242 break;
243 case MKTAG('D', 'X', '1', '0'):
244 /* DirectX 10 extra header */
245 dxgi = bytestream2_get_le32(gbc);
246 bytestream2_skip(gbc, 4); // resourceDimension
247 bytestream2_skip(gbc, 4); // miscFlag
248 array = bytestream2_get_le32(gbc);
249 bytestream2_skip(gbc, 4); // miscFlag2
250
251 if (array != 0)
252 av_log(avctx, AV_LOG_VERBOSE,
253 "Found array of size %d (ignored).\n", array);
254
255 /* Only BC[1-5] are actually compressed. */
256 ctx->compressed = (dxgi >= 70) && (dxgi <= 84);
257
258 av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);
259 switch (dxgi) {
260 /* RGB types. */
267 avctx->pix_fmt = AV_PIX_FMT_BGRA64;
268 break;
270 avctx->colorspace = AVCOL_SPC_RGB;
277 avctx->pix_fmt = AV_PIX_FMT_BGRA;
278 break;
280 avctx->colorspace = AVCOL_SPC_RGB;
284 avctx->pix_fmt = AV_PIX_FMT_RGBA;
285 break;
287 avctx->colorspace = AVCOL_SPC_RGB;
291 avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
292 break;
295 break;
296 /* Texture types. */
298 avctx->colorspace = AVCOL_SPC_RGB;
302 ctx->dec.tex_ratio = 8;
303 ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
304 break;
306 avctx->colorspace = AVCOL_SPC_RGB;
310 ctx->dec.tex_ratio = 16;
311 ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
312 break;
314 avctx->colorspace = AVCOL_SPC_RGB;
318 ctx->dec.tex_ratio = 16;
319 ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
320 break;
323 ctx->dec.tex_ratio = 8;
324 ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
325 break;
327 ctx->dec.tex_ratio = 8;
328 ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
329 break;
332 ctx->dec.tex_ratio = 16;
333 ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
334 break;
336 ctx->dec.tex_ratio = 16;
337 ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
338 break;
339 default:
340 av_log(avctx, AV_LOG_ERROR,
341 "Unsupported DXGI format %d.\n", dxgi);
342 return AVERROR_INVALIDDATA;
343 }
344 break;
345 default:
346 av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", av_fourcc2str(fourcc));
347 return AVERROR_INVALIDDATA;
348 }
349 } else if (ctx->paletted) {
350 if (bpp == 8) {
351 avctx->pix_fmt = AV_PIX_FMT_PAL8;
352 } else {
353 av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
354 return AVERROR_INVALIDDATA;
355 }
356 } else {
357 /* 4 bpp */
358 if (bpp == 4 && r == 0 && g == 0 && b == 0 && a == 0)
359 avctx->pix_fmt = AV_PIX_FMT_PAL8;
360 /* 8 bpp */
361 else if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
362 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
363 else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
364 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
365 /* 16 bpp */
366 else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
367 avctx->pix_fmt = AV_PIX_FMT_YA8;
368 else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
369 avctx->pix_fmt = AV_PIX_FMT_YA8;
370 ctx->postproc = DDS_SWAP_ALPHA;
371 }
372 else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
374 else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
376 else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
377 avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
378 else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
380 /* 24 bpp */
381 else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
382 avctx->pix_fmt = AV_PIX_FMT_BGR24;
383 /* 32 bpp */
384 else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
385 avctx->pix_fmt = AV_PIX_FMT_BGR0; // opaque
386 else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
387 avctx->pix_fmt = AV_PIX_FMT_RGB0; // opaque
388 else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
389 avctx->pix_fmt = AV_PIX_FMT_BGRA;
390 else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
391 avctx->pix_fmt = AV_PIX_FMT_RGBA;
392 /* give up */
393 else {
394 av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
395 "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
396 return AVERROR_INVALIDDATA;
397 }
398 }
399
400 /* Set any remaining post-proc that should happen before frame is ready. */
401 if (alpha_exponent)
402 ctx->postproc = DDS_ALPHA_EXP;
403 else if (normal_map)
404 ctx->postproc = DDS_NORMAL_MAP;
405 else if (ycocg_classic && !ctx->compressed)
406 ctx->postproc = DDS_RAW_YCOCG;
407
408 /* ATI/NVidia variants sometimes add swizzling in bpp. */
409 switch (bpp) {
410 case MKTAG('A', '2', 'X', 'Y'):
411 ctx->postproc = DDS_SWIZZLE_A2XY;
412 break;
413 case MKTAG('x', 'G', 'B', 'R'):
414 ctx->postproc = DDS_SWIZZLE_XGBR;
415 break;
416 case MKTAG('x', 'R', 'B', 'G'):
417 ctx->postproc = DDS_SWIZZLE_XRBG;
418 break;
419 case MKTAG('R', 'B', 'x', 'G'):
420 ctx->postproc = DDS_SWIZZLE_RBXG;
421 break;
422 case MKTAG('R', 'G', 'x', 'B'):
423 ctx->postproc = DDS_SWIZZLE_RGXB;
424 break;
425 case MKTAG('R', 'x', 'B', 'G'):
426 ctx->postproc = DDS_SWIZZLE_RXBG;
427 break;
428 case MKTAG('x', 'G', 'x', 'R'):
429 ctx->postproc = DDS_SWIZZLE_XGXR;
430 break;
431 case MKTAG('A', '2', 'D', '5'):
432 ctx->postproc = DDS_NORMAL_MAP;
433 break;
434 }
435
436 return 0;
437}
438
439static void do_swizzle(AVFrame *frame, int x, int y)
440{
441 int i;
442 for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
443 uint8_t *src = frame->data[0] + i;
444 FFSWAP(uint8_t, src[x], src[y]);
445 }
446}
447
449{
450 DDSContext *ctx = avctx->priv_data;
451 int i, x_off;
452
453 switch (ctx->postproc) {
454 case DDS_ALPHA_EXP:
455 /* Alpha-exponential mode divides each channel by the maximum
456 * R, G or B value, and stores the multiplying factor in the
457 * alpha channel. */
458 av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
459
460 for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
461 uint8_t *src = frame->data[0] + i;
462 int r = src[0];
463 int g = src[1];
464 int b = src[2];
465 int a = src[3];
466
467 src[0] = r * a / 255;
468 src[1] = g * a / 255;
469 src[2] = b * a / 255;
470 src[3] = 255;
471 }
472 break;
473 case DDS_NORMAL_MAP:
474 /* Normal maps work in the XYZ color space and they encode
475 * X in R or in A, depending on the texture type, Y in G and
476 * derive Z with a square root of the distance.
477 *
478 * http://www.realtimecollisiondetection.net/blog/?p=28 */
479 av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
480
481 x_off = ctx->dec.tex_ratio == 8 ? 0 : 3;
482 for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
483 uint8_t *src = frame->data[0] + i;
484 int x = src[x_off];
485 int y = src[1];
486 int z = 127;
487
488 int d = (255 * 255 - x * x - y * y) / 2;
489 if (d > 0)
490 z = lrint(sqrtf(d));
491
492 src[0] = x;
493 src[1] = y;
494 src[2] = z;
495 src[3] = 255;
496 }
497 break;
498 case DDS_RAW_YCOCG:
499 /* Data is Y-Co-Cg-A and not RGBA, but they are represented
500 * with the same masks in the DDPF header. */
501 av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
502
503 for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
504 uint8_t *src = frame->data[0] + i;
505 int a = src[0];
506 int cg = src[1] - 128;
507 int co = src[2] - 128;
508 int y = src[3];
509
510 src[0] = av_clip_uint8(y + co - cg);
511 src[1] = av_clip_uint8(y + cg);
512 src[2] = av_clip_uint8(y - co - cg);
513 src[3] = a;
514 }
515 break;
516 case DDS_SWAP_ALPHA:
517 /* Alpha and Luma are stored swapped. */
518 av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
519
520 for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
521 uint8_t *src = frame->data[0] + i;
522 FFSWAP(uint8_t, src[0], src[1]);
523 }
524 break;
525 case DDS_SWIZZLE_A2XY:
526 /* Swap R and G, often used to restore a standard RGTC2. */
527 av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
528 do_swizzle(frame, 0, 1);
529 break;
530 case DDS_SWIZZLE_RBXG:
531 /* Swap G and A, then B and new A (G). */
532 av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
533 do_swizzle(frame, 1, 3);
534 do_swizzle(frame, 2, 3);
535 break;
536 case DDS_SWIZZLE_RGXB:
537 /* Swap B and A. */
538 av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
539 do_swizzle(frame, 2, 3);
540 break;
541 case DDS_SWIZZLE_RXBG:
542 /* Swap G and A. */
543 av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
544 do_swizzle(frame, 1, 3);
545 break;
546 case DDS_SWIZZLE_RXGB:
547 /* Swap R and A (misleading name). */
548 av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
549 do_swizzle(frame, 0, 3);
550 break;
551 case DDS_SWIZZLE_XGBR:
552 /* Swap B and A, then R and new A (B). */
553 av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
554 do_swizzle(frame, 2, 3);
555 do_swizzle(frame, 0, 3);
556 break;
557 case DDS_SWIZZLE_XGXR:
558 /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
559 * This variant does not store any B component. */
560 av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
561 do_swizzle(frame, 1, 3);
562 do_swizzle(frame, 0, 3);
563 do_swizzle(frame, 0, 1);
564 break;
565 case DDS_SWIZZLE_XRBG:
566 /* Swap G and A, then R and new A (G). */
567 av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
568 do_swizzle(frame, 1, 3);
569 do_swizzle(frame, 0, 3);
570 break;
571 }
572}
573
575 int *got_frame, AVPacket *avpkt)
576{
577 DDSContext *ctx = avctx->priv_data;
578 GetByteContext *gbc = &ctx->gbc;
579 int mipmap;
580 int ret;
581 int width, height;
582
583 ff_texturedsp_init(&ctx->texdsp);
584 bytestream2_init(gbc, avpkt->data, avpkt->size);
585
586 if (bytestream2_get_bytes_left(gbc) < 128) {
587 av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n",
589 return AVERROR_INVALIDDATA;
590 }
591
592 if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
593 bytestream2_get_le32(gbc) != 124) { // header size
594 av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n");
595 return AVERROR_INVALIDDATA;
596 }
597
598 bytestream2_skip(gbc, 4); // flags
599
600 height = bytestream2_get_le32(gbc);
601 width = bytestream2_get_le32(gbc);
602 ret = ff_set_dimensions(avctx, width, height);
603 if (ret < 0) {
604 av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
605 avctx->width, avctx->height);
606 return ret;
607 }
608
609 /* Since codec is based on 4x4 blocks, size is aligned to 4. */
610 avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
611 avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
612
613 bytestream2_skip(gbc, 4); // pitch
614 bytestream2_skip(gbc, 4); // depth
615 mipmap = bytestream2_get_le32(gbc);
616 if (mipmap != 0)
617 av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
618
619 /* Extract pixel format information, considering additional elements
620 * in reserved1 and reserved2. */
621 ret = parse_pixel_format(avctx);
622 if (ret < 0)
623 return ret;
624
625 ret = ff_get_buffer(avctx, frame, 0);
626 if (ret < 0)
627 return ret;
628
629 if (ctx->compressed) {
630 int size = (avctx->coded_height / TEXTURE_BLOCK_H) *
631 (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->dec.tex_ratio;
632 ctx->dec.slice_count = av_clip(avctx->thread_count, 1,
634
635 if (bytestream2_get_bytes_left(gbc) < size) {
636 av_log(avctx, AV_LOG_ERROR,
637 "Compressed Buffer is too small (%d < %d).\n",
639 return AVERROR_INVALIDDATA;
640 }
641
642 /* Use the decompress function on the texture, one block per thread. */
643 ctx->dec.tex_data.in = gbc->buffer;
644 ctx->dec.frame_data.out = frame->data[0];
645 ctx->dec.stride = frame->linesize[0];
646 ctx->dec.width = avctx->coded_width;
647 ctx->dec.height = avctx->coded_height;
649 } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
650 uint8_t *dst = frame->data[0];
651 int x, y, i;
652
653 /* Use the first 64 bytes as palette, then copy the rest. */
654 bytestream2_get_buffer(gbc, frame->data[1], 16 * 4);
655 for (i = 0; i < 16; i++) {
656 AV_WN32(frame->data[1] + i*4,
657 (frame->data[1][2+i*4]<<0)+
658 (frame->data[1][1+i*4]<<8)+
659 (frame->data[1][0+i*4]<<16)+
660 ((unsigned)frame->data[1][3+i*4]<<24)
661 );
662 }
663
664 if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) {
665 av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
666 bytestream2_get_bytes_left(gbc), frame->height * frame->width / 2);
667 return AVERROR_INVALIDDATA;
668 }
669
670 for (y = 0; y < frame->height; y++) {
671 for (x = 0; x < frame->width; x += 2) {
672 uint8_t val = bytestream2_get_byte(gbc);
673 dst[x ] = val & 0xF;
674 dst[x + 1] = val >> 4;
675 }
676 dst += frame->linesize[0];
677 }
678 } else {
679 int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
680
681 if (ctx->paletted) {
682 int i;
683 /* Use the first 1024 bytes as palette, then copy the rest. */
684 bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
685 for (i = 0; i < 256; i++)
686 AV_WN32(frame->data[1] + i*4,
687 (frame->data[1][2+i*4]<<0)+
688 (frame->data[1][1+i*4]<<8)+
689 (frame->data[1][0+i*4]<<16)+
690 ((unsigned)frame->data[1][3+i*4]<<24)
691 );
692 }
693
694 if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) {
695 av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
696 bytestream2_get_bytes_left(gbc), frame->height * linesize);
697 return AVERROR_INVALIDDATA;
698 }
699
700 av_image_copy_plane(frame->data[0], frame->linesize[0],
701 gbc->buffer, linesize,
702 linesize, frame->height);
703 }
704
705 /* Run any post processing here if needed. */
706 if (ctx->postproc != DDS_NONE)
707 run_postproc(avctx, frame);
708
709 /* Frame is ready to be output. */
710 *got_frame = 1;
711
712 return avpkt->size;
713}
714
716 .p.name = "dds",
717 CODEC_LONG_NAME("DirectDraw Surface image decoder"),
718 .p.type = AVMEDIA_TYPE_VIDEO,
719 .p.id = AV_CODEC_ID_DDS,
721 .priv_data_size = sizeof(DDSContext),
723};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double val(void *priv, double ch)
Definition aeval.c:77
const FFCodec ff_dds_decoder
Definition dds.c:715
Libavcodec external API header.
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition bytestream.h:267
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define av_clip
Definition common.h:100
#define av_clip_uint8
Definition common.h:106
static __device__ float sqrtf(float a)
DDSDXGIFormat
Definition dds.c:61
@ DXGI_FORMAT_B8G8R8A8_UNORM
Definition dds.c:92
@ DXGI_FORMAT_BC3_UNORM_SRGB
Definition dds.c:84
@ DXGI_FORMAT_BC3_TYPELESS
Definition dds.c:82
@ DXGI_FORMAT_BC5_UNORM
Definition dds.c:89
@ DXGI_FORMAT_BC1_UNORM
Definition dds.c:77
@ DXGI_FORMAT_R16G16B16A16_SNORM
Definition dds.c:66
@ DXGI_FORMAT_R16G16B16A16_UNORM
Definition dds.c:64
@ DXGI_FORMAT_BC1_UNORM_SRGB
Definition dds.c:78
@ DXGI_FORMAT_R8G8B8A8_TYPELESS
Definition dds.c:69
@ DXGI_FORMAT_BC2_TYPELESS
Definition dds.c:79
@ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
Definition dds.c:95
@ DXGI_FORMAT_B8G8R8X8_TYPELESS
Definition dds.c:96
@ DXGI_FORMAT_B8G8R8A8_TYPELESS
Definition dds.c:94
@ DXGI_FORMAT_R16G16B16A16_UINT
Definition dds.c:65
@ DXGI_FORMAT_R8G8B8A8_SINT
Definition dds.c:74
@ DXGI_FORMAT_R8G8B8A8_SNORM
Definition dds.c:73
@ DXGI_FORMAT_R8G8B8A8_UINT
Definition dds.c:72
@ DXGI_FORMAT_R16G16B16A16_TYPELESS
Definition dds.c:62
@ DXGI_FORMAT_R16G16B16A16_FLOAT
Definition dds.c:63
@ DXGI_FORMAT_R8G8B8A8_UNORM
Definition dds.c:70
@ DXGI_FORMAT_BC5_TYPELESS
Definition dds.c:88
@ DXGI_FORMAT_BC2_UNORM_SRGB
Definition dds.c:81
@ DXGI_FORMAT_BC5_SNORM
Definition dds.c:90
@ DXGI_FORMAT_BC4_TYPELESS
Definition dds.c:85
@ DXGI_FORMAT_BC3_UNORM
Definition dds.c:83
@ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
Definition dds.c:71
@ DXGI_FORMAT_R16G16B16A16_SINT
Definition dds.c:67
@ DXGI_FORMAT_BC1_TYPELESS
Definition dds.c:76
@ DXGI_FORMAT_BC2_UNORM
Definition dds.c:80
@ DXGI_FORMAT_B5G6R5_UNORM
Definition dds.c:91
@ DXGI_FORMAT_BC4_UNORM
Definition dds.c:86
@ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
Definition dds.c:97
@ DXGI_FORMAT_BC4_SNORM
Definition dds.c:87
@ DXGI_FORMAT_B8G8R8X8_UNORM
Definition dds.c:93
static int dds_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition dds.c:574
#define DDPF_PALETTE
Definition dds.c:42
static void do_swizzle(AVFrame *frame, int x, int y)
Definition dds.c:439
#define DDPF_FOURCC
Definition dds.c:41
#define DDPF_NORMALMAP
Definition dds.c:43
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
Definition dds.c:448
DDSPostProc
Definition dds.c:45
@ DDS_SWIZZLE_RGXB
Definition dds.c:53
@ DDS_SWIZZLE_RBXG
Definition dds.c:52
@ DDS_SWIZZLE_RXGB
Definition dds.c:55
@ DDS_SWIZZLE_XGXR
Definition dds.c:58
@ DDS_RAW_YCOCG
Definition dds.c:49
@ DDS_SWIZZLE_XRBG
Definition dds.c:57
@ DDS_NONE
Definition dds.c:46
@ DDS_ALPHA_EXP
Definition dds.c:47
@ DDS_NORMAL_MAP
Definition dds.c:48
@ DDS_SWAP_ALPHA
Definition dds.c:50
@ DDS_SWIZZLE_RXBG
Definition dds.c:54
@ DDS_SWIZZLE_A2XY
Definition dds.c:51
@ DDS_SWIZZLE_XGBR
Definition dds.c:56
static int parse_pixel_format(AVCodecContext *avctx)
Definition dds.c:112
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
static AVFrame * frame
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition codec.h:102
@ AV_CODEC_ID_DDS
Definition codec_id.h:239
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define av_fourcc2str(fourcc)
Definition avutil.h:323
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition imgutils.c:374
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane.
Definition imgutils.c:76
int a
misc image utilities
#define r
Definition input.c:42
#define b
Definition input.c:43
#define AV_WN32(p, v)
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
Replacements for frequently missing libm functions.
#define FFSWAP(type, a, b)
Definition macros.h:52
#define MKTAG(a, b, c, d)
Definition macros.h:55
#define FFALIGN(x, a)
Definition macros.h:78
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition pixfmt.h:83
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition pixfmt.h:265
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition pixfmt.h:113
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:115
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition pixfmt.h:263
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition pixfmt.h:105
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
Definition pixfmt.h:140
#define AV_PIX_FMT_BGRA64
Definition pixfmt.h:540
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition pixfmt.h:707
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
enum AVColorSpace colorspace
YUV colorspace type.
Definition avcodec.h:671
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition avcodec.h:1579
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition avcodec.h:619
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
enum DDSPostProc postproc
Definition dds.c:107
TextureDSPContext texdsp
Definition dds.c:101
int paletted
Definition dds.c:105
int bpp
Definition dds.c:106
TextureDSPThreadContext dec
Definition dds.c:109
GetByteContext gbc
Definition dds.c:102
int compressed
Definition dds.c:104
const uint8_t * buffer
Definition bytestream.h:34
#define lrint
Definition tablegen.h:53
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static int array[MAX_W *MAX_W]
static AVFormatContext * ctx
Definition movenc.c:49
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition texturedsp.c:640
Texture block (4x4) module.
int ff_texturedsp_exec_decompress_threads(struct AVCodecContext *avctx, TextureDSPThreadContext *ctx)
#define TEXTURE_BLOCK_W
Definition texturedsp.h:42
#define TEXTURE_BLOCK_H
Definition texturedsp.h:43
int size
uint32_t fourcc
const char * g
Definition vf_curves.c:128