FFmpeg
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 
31 #include "libavutil/attributes.h"
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 
46  DDS_NONE = 0,
59 };
60 
68 
75 
98 };
99 
100 typedef struct DDSContext {
103 
105  int paletted;
106  int bpp;
108 
110 } DDSContext;
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;
227  avctx->pix_fmt = AV_PIX_FMT_UYVY422;
228  break;
229  case MKTAG('Y', 'U', 'Y', '2'):
230  ctx->compressed = 0;
231  avctx->pix_fmt = AV_PIX_FMT_YUYV422;
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;
241  avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
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;
294  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
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)
373  avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
374  else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
375  avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
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)
379  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
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 
439 static 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,
633  avctx->coded_height / TEXTURE_BLOCK_H);
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 };
flags
const SwsFlags flags[]
Definition: swscale.c:72
DXGI_FORMAT_BC4_SNORM
@ DXGI_FORMAT_BC4_SNORM
Definition: dds.c:87
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
DDS_SWAP_ALPHA
@ DDS_SWAP_ALPHA
Definition: dds.c:50
DXGI_FORMAT_B8G8R8A8_TYPELESS
@ DXGI_FORMAT_B8G8R8A8_TYPELESS
Definition: dds.c:94
DXGI_FORMAT_BC2_UNORM_SRGB
@ DXGI_FORMAT_BC2_UNORM_SRGB
Definition: dds.c:81
DDS_RAW_YCOCG
@ DDS_RAW_YCOCG
Definition: dds.c:49
dds_decode
static int dds_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: dds.c:574
av_clip
#define av_clip
Definition: common.h:100
r
const char * r
Definition: vf_curves.c:127
AV_PIX_FMT_YA8
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
Definition: pixfmt.h:140
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:667
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
@ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
Definition: dds.c:71
libm.h
DXGI_FORMAT_B8G8R8X8_UNORM
@ DXGI_FORMAT_B8G8R8X8_UNORM
Definition: dds.c:93
TEXTURE_BLOCK_H
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:43
DXGI_FORMAT_B5G6R5_UNORM
@ DXGI_FORMAT_B5G6R5_UNORM
Definition: dds.c:91
GetByteContext
Definition: bytestream.h:33
DXGI_FORMAT_B8G8R8A8_UNORM
@ DXGI_FORMAT_B8G8R8A8_UNORM
Definition: dds.c:92
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:435
DDSContext::compressed
int compressed
Definition: dds.c:104
AVPacket::data
uint8_t * data
Definition: packet.h:595
DXGI_FORMAT_BC4_TYPELESS
@ DXGI_FORMAT_BC4_TYPELESS
Definition: dds.c:85
b
#define b
Definition: input.c:43
DDS_NONE
@ DDS_NONE
Definition: dds.c:46
DXGI_FORMAT_BC1_UNORM
@ DXGI_FORMAT_BC1_UNORM
Definition: dds.c:77
FFCodec
Definition: codec_internal.h:127
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:701
DXGI_FORMAT_R16G16B16A16_TYPELESS
@ DXGI_FORMAT_R16G16B16A16_TYPELESS
Definition: dds.c:62
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
TextureDSPContext
Definition: texturedsp.h:45
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
@ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
Definition: dds.c:97
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:91
DDSContext::paletted
int paletted
Definition: dds.c:105
av_image_copy_plane
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
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
DXGI_FORMAT_BC1_TYPELESS
@ DXGI_FORMAT_BC1_TYPELESS
Definition: dds.c:76
texturedsp.h
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
DDSContext::bpp
int bpp
Definition: dds.c:106
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1573
DDPF_FOURCC
#define DDPF_FOURCC
Definition: dds.c:41
val
static double val(void *priv, double ch)
Definition: aeval.c:77
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:615
run_postproc
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
Definition: dds.c:448
DXGI_FORMAT_B8G8R8X8_TYPELESS
@ DXGI_FORMAT_B8G8R8X8_TYPELESS
Definition: dds.c:96
TextureDSPThreadContext
Definition: texturedsp.h:69
lrint
#define lrint
Definition: tablegen.h:53
DDSPostProc
DDSPostProc
Definition: dds.c:45
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
DDS_SWIZZLE_XRBG
@ DDS_SWIZZLE_XRBG
Definition: dds.c:57
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:347
DDS_SWIZZLE_XGBR
@ DDS_SWIZZLE_XGBR
Definition: dds.c:56
DXGI_FORMAT_R16G16B16A16_SNORM
@ DXGI_FORMAT_R16G16B16A16_SNORM
Definition: dds.c:66
g
const char * g
Definition: vf_curves.c:128
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
decode.h
ff_texturedsp_init
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:640
av_fallthrough
#define av_fallthrough
Definition: attributes.h:67
DDS_SWIZZLE_RXBG
@ DDS_SWIZZLE_RXBG
Definition: dds.c:54
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:332
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:113
DXGI_FORMAT_R16G16B16A16_UNORM
@ DXGI_FORMAT_R16G16B16A16_UNORM
Definition: dds.c:64
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
AV_PIX_FMT_MONOBLACK
@ 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
DDS_SWIZZLE_RBXG
@ DDS_SWIZZLE_RBXG
Definition: dds.c:52
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
sqrtf
static __device__ float sqrtf(float a)
Definition: cuda_runtime.h:184
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
ff_dds_decoder
const FFCodec ff_dds_decoder
Definition: dds.c:715
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
DXGI_FORMAT_BC4_UNORM
@ DXGI_FORMAT_BC4_UNORM
Definition: dds.c:86
DDPF_NORMALMAP
#define DDPF_NORMALMAP
Definition: dds.c:43
DDS_SWIZZLE_XGXR
@ DDS_SWIZZLE_XGXR
Definition: dds.c:58
ff_texturedsp_exec_decompress_threads
int ff_texturedsp_exec_decompress_threads(struct AVCodecContext *avctx, TextureDSPThreadContext *ctx)
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1765
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:596
height
#define height
Definition: dsp.h:89
codec_internal.h
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:372
DDS_SWIZZLE_RXGB
@ DDS_SWIZZLE_RXGB
Definition: dds.c:55
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
DXGI_FORMAT_BC3_UNORM_SRGB
@ DXGI_FORMAT_BC3_UNORM_SRGB
Definition: dds.c:84
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
size
int size
Definition: twinvq_data.h:10344
DDSContext::texdsp
TextureDSPContext texdsp
Definition: dds.c:101
DXGI_FORMAT_R8G8B8A8_SNORM
@ DXGI_FORMAT_R8G8B8A8_SNORM
Definition: dds.c:73
DDSContext
Definition: dds.c:100
DXGI_FORMAT_BC5_SNORM
@ DXGI_FORMAT_BC5_SNORM
Definition: dds.c:90
DXGI_FORMAT_R8G8B8A8_TYPELESS
@ DXGI_FORMAT_R8G8B8A8_TYPELESS
Definition: dds.c:69
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
do_swizzle
static void do_swizzle(AVFrame *frame, int x, int y)
Definition: dds.c:439
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:99
attributes.h
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
DXGI_FORMAT_R8G8B8A8_UINT
@ DXGI_FORMAT_R8G8B8A8_UINT
Definition: dds.c:72
DDSContext::postproc
enum DDSPostProc postproc
Definition: dds.c:107
av_image_get_linesize
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
DXGI_FORMAT_R16G16B16A16_FLOAT
@ DXGI_FORMAT_R16G16B16A16_FLOAT
Definition: dds.c:63
AV_PIX_FMT_BGRA64
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:534
AV_PIX_FMT_RGB555LE
@ 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
DXGI_FORMAT_BC2_TYPELESS
@ DXGI_FORMAT_BC2_TYPELESS
Definition: dds.c:79
DXGI_FORMAT_R16G16B16A16_SINT
@ DXGI_FORMAT_R16G16B16A16_SINT
Definition: dds.c:67
DDSDXGIFormat
DDSDXGIFormat
Definition: dds.c:61
parse_pixel_format
static int parse_pixel_format(AVCodecContext *avctx)
Definition: dds.c:112
TEXTURE_BLOCK_W
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:42
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
AVCodecContext::height
int height
Definition: avcodec.h:600
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:639
DXGI_FORMAT_BC1_UNORM_SRGB
@ DXGI_FORMAT_BC1_UNORM_SRGB
Definition: dds.c:78
avcodec.h
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
array
static int array[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:116
ret
ret
Definition: filter_design.txt:187
DDS_NORMAL_MAP
@ DDS_NORMAL_MAP
Definition: dds.c:48
DXGI_FORMAT_BC5_TYPELESS
@ DXGI_FORMAT_BC5_TYPELESS
Definition: dds.c:88
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
DDPF_PALETTE
#define DDPF_PALETTE
Definition: dds.c:42
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
DXGI_FORMAT_BC3_UNORM
@ DXGI_FORMAT_BC3_UNORM
Definition: dds.c:83
AVCodecContext
main external API structure.
Definition: avcodec.h:439
DDSContext::dec
TextureDSPThreadContext dec
Definition: dds.c:109
DDSContext::gbc
GetByteContext gbc
Definition: dds.c:102
DXGI_FORMAT_BC2_UNORM
@ DXGI_FORMAT_BC2_UNORM
Definition: dds.c:80
DDS_SWIZZLE_RGXB
@ DDS_SWIZZLE_RGXB
Definition: dds.c:53
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
DXGI_FORMAT_R16G16B16A16_UINT
@ DXGI_FORMAT_R16G16B16A16_UINT
Definition: dds.c:65
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:615
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
AV_CODEC_ID_DDS
@ AV_CODEC_ID_DDS
Definition: codec_id.h:244
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:105
DXGI_FORMAT_BC3_TYPELESS
@ DXGI_FORMAT_BC3_TYPELESS
Definition: dds.c:82
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:572
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:466
DDS_SWIZZLE_A2XY
@ DDS_SWIZZLE_A2XY
Definition: dds.c:51
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:600
bytestream.h
imgutils.h
DXGI_FORMAT_BC5_UNORM
@ DXGI_FORMAT_BC5_UNORM
Definition: dds.c:89
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
DDS_ALPHA_EXP
@ DDS_ALPHA_EXP
Definition: dds.c:47
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
DXGI_FORMAT_R8G8B8A8_UNORM
@ DXGI_FORMAT_R8G8B8A8_UNORM
Definition: dds.c:70
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
width
#define width
Definition: dsp.h:89
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:263
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
@ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
Definition: dds.c:95
DXGI_FORMAT_R8G8B8A8_SINT
@ DXGI_FORMAT_R8G8B8A8_SINT
Definition: dds.c:74
src
#define src
Definition: vp8dsp.c:248
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:347