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/libm.h"
32 #include "libavutil/imgutils.h"
33 
34 #include "avcodec.h"
35 #include "bytestream.h"
36 #include "codec_internal.h"
37 #include "internal.h"
38 #include "texturedsp.h"
39 #include "thread.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;
276  avctx->pix_fmt = AV_PIX_FMT_BGRA;
277  break;
279  avctx->colorspace = AVCOL_SPC_RGB;
282  avctx->pix_fmt = AV_PIX_FMT_RGBA;
283  break;
285  avctx->colorspace = AVCOL_SPC_RGB;
288  avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
289  break;
291  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
292  break;
293  /* Texture types. */
295  avctx->colorspace = AVCOL_SPC_RGB;
298  ctx->dec.tex_ratio = 8;
299  ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
300  break;
302  avctx->colorspace = AVCOL_SPC_RGB;
305  ctx->dec.tex_ratio = 16;
306  ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
307  break;
309  avctx->colorspace = AVCOL_SPC_RGB;
312  ctx->dec.tex_ratio = 16;
313  ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
314  break;
317  ctx->dec.tex_ratio = 8;
318  ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
319  break;
321  ctx->dec.tex_ratio = 8;
322  ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
323  break;
326  ctx->dec.tex_ratio = 16;
327  ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
328  break;
330  ctx->dec.tex_ratio = 16;
331  ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
332  break;
333  default:
334  av_log(avctx, AV_LOG_ERROR,
335  "Unsupported DXGI format %d.\n", dxgi);
336  return AVERROR_INVALIDDATA;
337  }
338  break;
339  default:
340  av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", av_fourcc2str(fourcc));
341  return AVERROR_INVALIDDATA;
342  }
343  } else if (ctx->paletted) {
344  if (bpp == 8) {
345  avctx->pix_fmt = AV_PIX_FMT_PAL8;
346  } else {
347  av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
348  return AVERROR_INVALIDDATA;
349  }
350  } else {
351  /* 4 bpp */
352  if (bpp == 4 && r == 0 && g == 0 && b == 0 && a == 0)
353  avctx->pix_fmt = AV_PIX_FMT_PAL8;
354  /* 8 bpp */
355  else if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
356  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
357  else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
358  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
359  /* 16 bpp */
360  else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
361  avctx->pix_fmt = AV_PIX_FMT_YA8;
362  else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
363  avctx->pix_fmt = AV_PIX_FMT_YA8;
364  ctx->postproc = DDS_SWAP_ALPHA;
365  }
366  else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
367  avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
368  else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
369  avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
370  else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
371  avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
372  else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
373  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
374  /* 24 bpp */
375  else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
376  avctx->pix_fmt = AV_PIX_FMT_BGR24;
377  /* 32 bpp */
378  else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
379  avctx->pix_fmt = AV_PIX_FMT_BGR0; // opaque
380  else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
381  avctx->pix_fmt = AV_PIX_FMT_RGB0; // opaque
382  else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
383  avctx->pix_fmt = AV_PIX_FMT_BGRA;
384  else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
385  avctx->pix_fmt = AV_PIX_FMT_RGBA;
386  /* give up */
387  else {
388  av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
389  "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
390  return AVERROR_INVALIDDATA;
391  }
392  }
393 
394  /* Set any remaining post-proc that should happen before frame is ready. */
395  if (alpha_exponent)
396  ctx->postproc = DDS_ALPHA_EXP;
397  else if (normal_map)
398  ctx->postproc = DDS_NORMAL_MAP;
399  else if (ycocg_classic && !ctx->compressed)
400  ctx->postproc = DDS_RAW_YCOCG;
401 
402  /* ATI/NVidia variants sometimes add swizzling in bpp. */
403  switch (bpp) {
404  case MKTAG('A', '2', 'X', 'Y'):
405  ctx->postproc = DDS_SWIZZLE_A2XY;
406  break;
407  case MKTAG('x', 'G', 'B', 'R'):
408  ctx->postproc = DDS_SWIZZLE_XGBR;
409  break;
410  case MKTAG('x', 'R', 'B', 'G'):
411  ctx->postproc = DDS_SWIZZLE_XRBG;
412  break;
413  case MKTAG('R', 'B', 'x', 'G'):
414  ctx->postproc = DDS_SWIZZLE_RBXG;
415  break;
416  case MKTAG('R', 'G', 'x', 'B'):
417  ctx->postproc = DDS_SWIZZLE_RGXB;
418  break;
419  case MKTAG('R', 'x', 'B', 'G'):
420  ctx->postproc = DDS_SWIZZLE_RXBG;
421  break;
422  case MKTAG('x', 'G', 'x', 'R'):
423  ctx->postproc = DDS_SWIZZLE_XGXR;
424  break;
425  case MKTAG('A', '2', 'D', '5'):
426  ctx->postproc = DDS_NORMAL_MAP;
427  break;
428  }
429 
430  return 0;
431 }
432 
433 static void do_swizzle(AVFrame *frame, int x, int y)
434 {
435  int i;
436  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
437  uint8_t *src = frame->data[0] + i;
438  FFSWAP(uint8_t, src[x], src[y]);
439  }
440 }
441 
443 {
444  DDSContext *ctx = avctx->priv_data;
445  int i, x_off;
446 
447  switch (ctx->postproc) {
448  case DDS_ALPHA_EXP:
449  /* Alpha-exponential mode divides each channel by the maximum
450  * R, G or B value, and stores the multiplying factor in the
451  * alpha channel. */
452  av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
453 
454  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
455  uint8_t *src = frame->data[0] + i;
456  int r = src[0];
457  int g = src[1];
458  int b = src[2];
459  int a = src[3];
460 
461  src[0] = r * a / 255;
462  src[1] = g * a / 255;
463  src[2] = b * a / 255;
464  src[3] = 255;
465  }
466  break;
467  case DDS_NORMAL_MAP:
468  /* Normal maps work in the XYZ color space and they encode
469  * X in R or in A, depending on the texture type, Y in G and
470  * derive Z with a square root of the distance.
471  *
472  * http://www.realtimecollisiondetection.net/blog/?p=28 */
473  av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
474 
475  x_off = ctx->dec.tex_ratio == 8 ? 0 : 3;
476  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
477  uint8_t *src = frame->data[0] + i;
478  int x = src[x_off];
479  int y = src[1];
480  int z = 127;
481 
482  int d = (255 * 255 - x * x - y * y) / 2;
483  if (d > 0)
484  z = lrint(sqrtf(d));
485 
486  src[0] = x;
487  src[1] = y;
488  src[2] = z;
489  src[3] = 255;
490  }
491  break;
492  case DDS_RAW_YCOCG:
493  /* Data is Y-Co-Cg-A and not RGBA, but they are represented
494  * with the same masks in the DDPF header. */
495  av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
496 
497  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
498  uint8_t *src = frame->data[0] + i;
499  int a = src[0];
500  int cg = src[1] - 128;
501  int co = src[2] - 128;
502  int y = src[3];
503 
504  src[0] = av_clip_uint8(y + co - cg);
505  src[1] = av_clip_uint8(y + cg);
506  src[2] = av_clip_uint8(y - co - cg);
507  src[3] = a;
508  }
509  break;
510  case DDS_SWAP_ALPHA:
511  /* Alpha and Luma are stored swapped. */
512  av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
513 
514  for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
515  uint8_t *src = frame->data[0] + i;
516  FFSWAP(uint8_t, src[0], src[1]);
517  }
518  break;
519  case DDS_SWIZZLE_A2XY:
520  /* Swap R and G, often used to restore a standard RGTC2. */
521  av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
522  do_swizzle(frame, 0, 1);
523  break;
524  case DDS_SWIZZLE_RBXG:
525  /* Swap G and A, then B and new A (G). */
526  av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
527  do_swizzle(frame, 1, 3);
528  do_swizzle(frame, 2, 3);
529  break;
530  case DDS_SWIZZLE_RGXB:
531  /* Swap B and A. */
532  av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
533  do_swizzle(frame, 2, 3);
534  break;
535  case DDS_SWIZZLE_RXBG:
536  /* Swap G and A. */
537  av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
538  do_swizzle(frame, 1, 3);
539  break;
540  case DDS_SWIZZLE_RXGB:
541  /* Swap R and A (misleading name). */
542  av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
543  do_swizzle(frame, 0, 3);
544  break;
545  case DDS_SWIZZLE_XGBR:
546  /* Swap B and A, then R and new A (B). */
547  av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
548  do_swizzle(frame, 2, 3);
549  do_swizzle(frame, 0, 3);
550  break;
551  case DDS_SWIZZLE_XGXR:
552  /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
553  * This variant does not store any B component. */
554  av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
555  do_swizzle(frame, 1, 3);
556  do_swizzle(frame, 0, 3);
557  do_swizzle(frame, 0, 1);
558  break;
559  case DDS_SWIZZLE_XRBG:
560  /* Swap G and A, then R and new A (G). */
561  av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
562  do_swizzle(frame, 1, 3);
563  do_swizzle(frame, 0, 3);
564  break;
565  }
566 }
567 
569  int *got_frame, AVPacket *avpkt)
570 {
571  DDSContext *ctx = avctx->priv_data;
572  GetByteContext *gbc = &ctx->gbc;
573  int mipmap;
574  int ret;
575  int width, height;
576 
577  ff_texturedsp_init(&ctx->texdsp);
578  bytestream2_init(gbc, avpkt->data, avpkt->size);
579 
580  if (bytestream2_get_bytes_left(gbc) < 128) {
581  av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n",
583  return AVERROR_INVALIDDATA;
584  }
585 
586  if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
587  bytestream2_get_le32(gbc) != 124) { // header size
588  av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n");
589  return AVERROR_INVALIDDATA;
590  }
591 
592  bytestream2_skip(gbc, 4); // flags
593 
594  height = bytestream2_get_le32(gbc);
595  width = bytestream2_get_le32(gbc);
596  ret = ff_set_dimensions(avctx, width, height);
597  if (ret < 0) {
598  av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
599  avctx->width, avctx->height);
600  return ret;
601  }
602 
603  /* Since codec is based on 4x4 blocks, size is aligned to 4. */
604  avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
605  avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
606 
607  bytestream2_skip(gbc, 4); // pitch
608  bytestream2_skip(gbc, 4); // depth
609  mipmap = bytestream2_get_le32(gbc);
610  if (mipmap != 0)
611  av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
612 
613  /* Extract pixel format information, considering additional elements
614  * in reserved1 and reserved2. */
615  ret = parse_pixel_format(avctx);
616  if (ret < 0)
617  return ret;
618 
619  ret = ff_get_buffer(avctx, frame, 0);
620  if (ret < 0)
621  return ret;
622 
623  if (ctx->compressed) {
624  int size = (avctx->coded_height / TEXTURE_BLOCK_H) *
625  (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->dec.tex_ratio;
626  ctx->dec.slice_count = av_clip(avctx->thread_count, 1,
627  avctx->coded_height / TEXTURE_BLOCK_H);
628 
629  if (bytestream2_get_bytes_left(gbc) < size) {
630  av_log(avctx, AV_LOG_ERROR,
631  "Compressed Buffer is too small (%d < %d).\n",
633  return AVERROR_INVALIDDATA;
634  }
635 
636  /* Use the decompress function on the texture, one block per thread. */
637  ctx->dec.tex_data.in = gbc->buffer;
638  ctx->dec.frame_data.out = frame->data[0];
639  ctx->dec.stride = frame->linesize[0];
640  avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec, NULL, ctx->dec.slice_count);
641  } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
642  uint8_t *dst = frame->data[0];
643  int x, y, i;
644 
645  /* Use the first 64 bytes as palette, then copy the rest. */
646  bytestream2_get_buffer(gbc, frame->data[1], 16 * 4);
647  for (i = 0; i < 16; i++) {
648  AV_WN32(frame->data[1] + i*4,
649  (frame->data[1][2+i*4]<<0)+
650  (frame->data[1][1+i*4]<<8)+
651  (frame->data[1][0+i*4]<<16)+
652  ((unsigned)frame->data[1][3+i*4]<<24)
653  );
654  }
655  frame->palette_has_changed = 1;
656 
657  if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) {
658  av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
659  bytestream2_get_bytes_left(gbc), frame->height * frame->width / 2);
660  return AVERROR_INVALIDDATA;
661  }
662 
663  for (y = 0; y < frame->height; y++) {
664  for (x = 0; x < frame->width; x += 2) {
665  uint8_t val = bytestream2_get_byte(gbc);
666  dst[x ] = val & 0xF;
667  dst[x + 1] = val >> 4;
668  }
669  dst += frame->linesize[0];
670  }
671  } else {
672  int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
673 
674  if (ctx->paletted) {
675  int i;
676  /* Use the first 1024 bytes as palette, then copy the rest. */
677  bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
678  for (i = 0; i < 256; i++)
679  AV_WN32(frame->data[1] + i*4,
680  (frame->data[1][2+i*4]<<0)+
681  (frame->data[1][1+i*4]<<8)+
682  (frame->data[1][0+i*4]<<16)+
683  ((unsigned)frame->data[1][3+i*4]<<24)
684  );
685 
686  frame->palette_has_changed = 1;
687  }
688 
689  if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) {
690  av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
691  bytestream2_get_bytes_left(gbc), frame->height * linesize);
692  return AVERROR_INVALIDDATA;
693  }
694 
695  av_image_copy_plane(frame->data[0], frame->linesize[0],
696  gbc->buffer, linesize,
697  linesize, frame->height);
698  }
699 
700  /* Run any post processing here if needed. */
701  if (ctx->postproc != DDS_NONE)
702  run_postproc(avctx, frame);
703 
704  /* Frame is ready to be output. */
705  frame->pict_type = AV_PICTURE_TYPE_I;
706  frame->key_frame = 1;
707  *got_frame = 1;
708 
709  return avpkt->size;
710 }
711 
713  .p.name = "dds",
714  .p.long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"),
715  .p.type = AVMEDIA_TYPE_VIDEO,
716  .p.id = AV_CODEC_ID_DDS,
718  .priv_data_size = sizeof(DDSContext),
719  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
720  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE
721 };
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:186
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:568
av_clip
#define av_clip
Definition: common.h:95
r
const char * r
Definition: vf_curves.c:116
AV_PIX_FMT_YA8
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
Definition: pixfmt.h:133
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:966
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:45
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:325
DDSContext::compressed
int compressed
Definition: dds.c:104
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:374
DXGI_FORMAT_BC4_TYPELESS
@ DXGI_FORMAT_BC4_TYPELESS
Definition: dds.c:85
b
#define b
Definition: input.c:34
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:112
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
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:526
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:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
TextureDSPContext
Definition: texturedsp.h:47
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
@ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
Definition: dds.c:97
ff_texturedsp_decompress_thread
int ff_texturedsp_decompress_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
DDSContext::paletted
int paletted
Definition: dds.c:105
thread.h
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:116
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:1463
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:577
run_postproc
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
Definition: dds.c:442
DXGI_FORMAT_B8G8R8X8_TYPELESS
@ DXGI_FORMAT_B8G8R8X8_TYPELESS
Definition: dds.c:96
TextureDSPThreadContext
Definition: texturedsp.h:65
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:180
width
#define width
DDS_SWIZZLE_XRBG
@ DDS_SWIZZLE_XRBG
Definition: dds.c:57
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:254
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:117
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:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ff_texturedsp_init
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:637
DDS_SWIZZLE_RXBG
@ DDS_SWIZZLE_RXBG
Definition: dds.c:54
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:106
DXGI_FORMAT_R16G16B16A16_UNORM
@ DXGI_FORMAT_R16G16B16A16_UNORM
Definition: dds.c:64
NULL
#define NULL
Definition: coverity.c:32
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
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:76
DDS_SWIZZLE_RBXG
@ DDS_SWIZZLE_RBXG
Definition: dds.c:52
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:274
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:230
ff_dds_decoder
const FFCodec ff_dds_decoder
Definition: dds.c:712
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
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
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1403
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:375
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
codec_internal.h
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
DDS_SWIZZLE_RXGB
@ DDS_SWIZZLE_RXGB
Definition: dds.c:55
DXGI_FORMAT_BC3_UNORM_SRGB
@ DXGI_FORMAT_BC3_UNORM_SRGB
Definition: dds.c:84
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
height
#define height
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:433
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:117
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:228
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:401
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:108
DXGI_FORMAT_BC2_TYPELESS
@ DXGI_FORMAT_BC2_TYPELESS
Definition: dds.c:79
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
DXGI_FORMAT_R16G16B16A16_SINT
@ DXGI_FORMAT_R16G16B16A16_SINT
Definition: dds.c:67
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: codec_internal.h:31
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:44
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:203
AVCodecContext::height
int height
Definition: avcodec.h:562
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:599
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:77
array
static int array[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:111
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:264
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:81
DXGI_FORMAT_BC3_UNORM
@ DXGI_FORMAT_BC3_UNORM
Definition: dds.c:83
AVCodecContext
main external API structure.
Definition: avcodec.h:389
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
av_clip_uint8
#define av_clip_uint8
Definition: common.h:101
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:577
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_CODEC_ID_DDS
@ AV_CODEC_ID_DDS
Definition: codec_id.h:240
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:98
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:90
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:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:416
DDS_SWIZZLE_A2XY
@ DDS_SWIZZLE_A2XY
Definition: dds.c:51
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
d
d
Definition: ffmpeg_filter.c:153
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:562
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
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:241
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
@ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
Definition: dds.c:95
AVCodecContext::execute2
int(* execute2)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count)
The codec may call this to execute several independent things.
Definition: avcodec.h:1533
DXGI_FORMAT_R8G8B8A8_SINT
@ DXGI_FORMAT_R8G8B8A8_SINT
Definition: dds.c:74
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:354