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 "decode.h"
38 #include "texturedsp.h"
39 
40 #define DDPF_FOURCC (1 << 2)
41 #define DDPF_PALETTE (1 << 5)
42 #define DDPF_NORMALMAP (1U << 31)
43 
45  DDS_NONE = 0,
58 };
59 
67 
74 
97 };
98 
99 typedef struct DDSContext {
102 
104  int paletted;
105  int bpp;
107 
109 } DDSContext;
110 
112 {
113  DDSContext *ctx = avctx->priv_data;
114  GetByteContext *gbc = &ctx->gbc;
115  uint32_t flags, fourcc, gimp_tag;
116  enum DDSDXGIFormat dxgi;
117  int size, bpp, r, g, b, a;
118  int alpha_exponent, ycocg_classic, ycocg_scaled, normal_map, array;
119 
120  /* Alternative DDS implementations use reserved1 as custom header. */
121  bytestream2_skip(gbc, 4 * 3);
122  gimp_tag = bytestream2_get_le32(gbc);
123  alpha_exponent = gimp_tag == MKTAG('A', 'E', 'X', 'P');
124  ycocg_classic = gimp_tag == MKTAG('Y', 'C', 'G', '1');
125  ycocg_scaled = gimp_tag == MKTAG('Y', 'C', 'G', '2');
126  bytestream2_skip(gbc, 4 * 7);
127 
128  /* Now the real DDPF starts. */
129  size = bytestream2_get_le32(gbc);
130  if (size != 32) {
131  av_log(avctx, AV_LOG_ERROR, "Invalid pixel format header %d.\n", size);
132  return AVERROR_INVALIDDATA;
133  }
134  flags = bytestream2_get_le32(gbc);
135  ctx->compressed = flags & DDPF_FOURCC;
136  ctx->paletted = flags & DDPF_PALETTE;
137  normal_map = flags & DDPF_NORMALMAP;
138  fourcc = bytestream2_get_le32(gbc);
139 
140  if (ctx->compressed && ctx->paletted) {
141  av_log(avctx, AV_LOG_WARNING,
142  "Disabling invalid palette flag for compressed dds.\n");
143  ctx->paletted = 0;
144  }
145 
146  bpp = ctx->bpp = bytestream2_get_le32(gbc); // rgbbitcount
147  r = bytestream2_get_le32(gbc); // rbitmask
148  g = bytestream2_get_le32(gbc); // gbitmask
149  b = bytestream2_get_le32(gbc); // bbitmask
150  a = bytestream2_get_le32(gbc); // abitmask
151 
152  bytestream2_skip(gbc, 4); // caps
153  bytestream2_skip(gbc, 4); // caps2
154  bytestream2_skip(gbc, 4); // caps3
155  bytestream2_skip(gbc, 4); // caps4
156  bytestream2_skip(gbc, 4); // reserved2
157 
158  av_log(avctx, AV_LOG_VERBOSE, "fourcc %s bpp %d "
159  "r 0x%x g 0x%x b 0x%x a 0x%x\n", av_fourcc2str(fourcc), bpp, r, g, b, a);
160  if (gimp_tag)
161  av_log(avctx, AV_LOG_VERBOSE, "and GIMP-DDS tag %s\n", av_fourcc2str(gimp_tag));
162 
163  if (ctx->compressed)
164  avctx->pix_fmt = AV_PIX_FMT_RGBA;
165 
166  if (ctx->compressed) {
167  ctx->dec.raw_ratio = 16;
168  switch (fourcc) {
169  case MKTAG('D', 'X', 'T', '1'):
170  ctx->dec.tex_ratio = 8;
171  ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
172  break;
173  case MKTAG('D', 'X', 'T', '2'):
174  ctx->dec.tex_ratio = 16;
175  ctx->dec.tex_funct = ctx->texdsp.dxt2_block;
176  break;
177  case MKTAG('D', 'X', 'T', '3'):
178  ctx->dec.tex_ratio = 16;
179  ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
180  break;
181  case MKTAG('D', 'X', 'T', '4'):
182  ctx->dec.tex_ratio = 16;
183  ctx->dec.tex_funct = ctx->texdsp.dxt4_block;
184  break;
185  case MKTAG('D', 'X', 'T', '5'):
186  ctx->dec.tex_ratio = 16;
187  if (ycocg_scaled)
188  ctx->dec.tex_funct = ctx->texdsp.dxt5ys_block;
189  else if (ycocg_classic)
190  ctx->dec.tex_funct = ctx->texdsp.dxt5y_block;
191  else
192  ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
193  break;
194  case MKTAG('R', 'X', 'G', 'B'):
195  ctx->dec.tex_ratio = 16;
196  ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
197  /* This format may be considered as a normal map,
198  * but it is handled differently in a separate postproc. */
199  ctx->postproc = DDS_SWIZZLE_RXGB;
200  normal_map = 0;
201  break;
202  case MKTAG('A', 'T', 'I', '1'):
203  case MKTAG('B', 'C', '4', 'U'):
204  ctx->dec.tex_ratio = 8;
205  ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
206  break;
207  case MKTAG('B', 'C', '4', 'S'):
208  ctx->dec.tex_ratio = 8;
209  ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
210  break;
211  case MKTAG('A', 'T', 'I', '2'):
212  /* RGT2 variant with swapped R and G (3Dc)*/
213  ctx->dec.tex_ratio = 16;
214  ctx->dec.tex_funct = ctx->texdsp.dxn3dc_block;
215  break;
216  case MKTAG('B', 'C', '5', 'U'):
217  ctx->dec.tex_ratio = 16;
218  ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
219  break;
220  case MKTAG('B', 'C', '5', 'S'):
221  ctx->dec.tex_ratio = 16;
222  ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
223  break;
224  case MKTAG('U', 'Y', 'V', 'Y'):
225  ctx->compressed = 0;
226  avctx->pix_fmt = AV_PIX_FMT_UYVY422;
227  break;
228  case MKTAG('Y', 'U', 'Y', '2'):
229  ctx->compressed = 0;
230  avctx->pix_fmt = AV_PIX_FMT_YUYV422;
231  break;
232  case MKTAG('P', '8', ' ', ' '):
233  /* ATI Palette8, same as normal palette */
234  ctx->compressed = 0;
235  ctx->paletted = 1;
236  avctx->pix_fmt = AV_PIX_FMT_PAL8;
237  break;
238  case MKTAG('G', '1', ' ', ' '):
239  ctx->compressed = 0;
240  avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
241  break;
242  case MKTAG('D', 'X', '1', '0'):
243  /* DirectX 10 extra header */
244  dxgi = bytestream2_get_le32(gbc);
245  bytestream2_skip(gbc, 4); // resourceDimension
246  bytestream2_skip(gbc, 4); // miscFlag
247  array = bytestream2_get_le32(gbc);
248  bytestream2_skip(gbc, 4); // miscFlag2
249 
250  if (array != 0)
251  av_log(avctx, AV_LOG_VERBOSE,
252  "Found array of size %d (ignored).\n", array);
253 
254  /* Only BC[1-5] are actually compressed. */
255  ctx->compressed = (dxgi >= 70) && (dxgi <= 84);
256 
257  av_log(avctx, AV_LOG_VERBOSE, "DXGI format %d.\n", dxgi);
258  switch (dxgi) {
259  /* RGB types. */
266  avctx->pix_fmt = AV_PIX_FMT_BGRA64;
267  break;
269  avctx->colorspace = AVCOL_SPC_RGB;
275  avctx->pix_fmt = AV_PIX_FMT_BGRA;
276  break;
278  avctx->colorspace = AVCOL_SPC_RGB;
281  avctx->pix_fmt = AV_PIX_FMT_RGBA;
282  break;
284  avctx->colorspace = AVCOL_SPC_RGB;
287  avctx->pix_fmt = AV_PIX_FMT_RGBA; // opaque
288  break;
290  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
291  break;
292  /* Texture types. */
294  avctx->colorspace = AVCOL_SPC_RGB;
297  ctx->dec.tex_ratio = 8;
298  ctx->dec.tex_funct = ctx->texdsp.dxt1a_block;
299  break;
301  avctx->colorspace = AVCOL_SPC_RGB;
304  ctx->dec.tex_ratio = 16;
305  ctx->dec.tex_funct = ctx->texdsp.dxt3_block;
306  break;
308  avctx->colorspace = AVCOL_SPC_RGB;
311  ctx->dec.tex_ratio = 16;
312  ctx->dec.tex_funct = ctx->texdsp.dxt5_block;
313  break;
316  ctx->dec.tex_ratio = 8;
317  ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block;
318  break;
320  ctx->dec.tex_ratio = 8;
321  ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block;
322  break;
325  ctx->dec.tex_ratio = 16;
326  ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block;
327  break;
329  ctx->dec.tex_ratio = 16;
330  ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block;
331  break;
332  default:
333  av_log(avctx, AV_LOG_ERROR,
334  "Unsupported DXGI format %d.\n", dxgi);
335  return AVERROR_INVALIDDATA;
336  }
337  break;
338  default:
339  av_log(avctx, AV_LOG_ERROR, "Unsupported %s fourcc.\n", av_fourcc2str(fourcc));
340  return AVERROR_INVALIDDATA;
341  }
342  } else if (ctx->paletted) {
343  if (bpp == 8) {
344  avctx->pix_fmt = AV_PIX_FMT_PAL8;
345  } else {
346  av_log(avctx, AV_LOG_ERROR, "Unsupported palette bpp %d.\n", bpp);
347  return AVERROR_INVALIDDATA;
348  }
349  } else {
350  /* 4 bpp */
351  if (bpp == 4 && r == 0 && g == 0 && b == 0 && a == 0)
352  avctx->pix_fmt = AV_PIX_FMT_PAL8;
353  /* 8 bpp */
354  else if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
355  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
356  else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
357  avctx->pix_fmt = AV_PIX_FMT_GRAY8;
358  /* 16 bpp */
359  else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
360  avctx->pix_fmt = AV_PIX_FMT_YA8;
361  else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
362  avctx->pix_fmt = AV_PIX_FMT_YA8;
363  ctx->postproc = DDS_SWAP_ALPHA;
364  }
365  else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
366  avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
367  else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
368  avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
369  else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
370  avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
371  else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
372  avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
373  /* 24 bpp */
374  else if (bpp == 24 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
375  avctx->pix_fmt = AV_PIX_FMT_BGR24;
376  /* 32 bpp */
377  else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0)
378  avctx->pix_fmt = AV_PIX_FMT_BGR0; // opaque
379  else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0)
380  avctx->pix_fmt = AV_PIX_FMT_RGB0; // opaque
381  else if (bpp == 32 && r == 0xff0000 && g == 0xff00 && b == 0xff && a == 0xff000000)
382  avctx->pix_fmt = AV_PIX_FMT_BGRA;
383  else if (bpp == 32 && r == 0xff && g == 0xff00 && b == 0xff0000 && a == 0xff000000)
384  avctx->pix_fmt = AV_PIX_FMT_RGBA;
385  /* give up */
386  else {
387  av_log(avctx, AV_LOG_ERROR, "Unknown pixel format "
388  "[bpp %d r 0x%x g 0x%x b 0x%x a 0x%x].\n", bpp, r, g, b, a);
389  return AVERROR_INVALIDDATA;
390  }
391  }
392 
393  /* Set any remaining post-proc that should happen before frame is ready. */
394  if (alpha_exponent)
395  ctx->postproc = DDS_ALPHA_EXP;
396  else if (normal_map)
397  ctx->postproc = DDS_NORMAL_MAP;
398  else if (ycocg_classic && !ctx->compressed)
399  ctx->postproc = DDS_RAW_YCOCG;
400 
401  /* ATI/NVidia variants sometimes add swizzling in bpp. */
402  switch (bpp) {
403  case MKTAG('A', '2', 'X', 'Y'):
404  ctx->postproc = DDS_SWIZZLE_A2XY;
405  break;
406  case MKTAG('x', 'G', 'B', 'R'):
407  ctx->postproc = DDS_SWIZZLE_XGBR;
408  break;
409  case MKTAG('x', 'R', 'B', 'G'):
410  ctx->postproc = DDS_SWIZZLE_XRBG;
411  break;
412  case MKTAG('R', 'B', 'x', 'G'):
413  ctx->postproc = DDS_SWIZZLE_RBXG;
414  break;
415  case MKTAG('R', 'G', 'x', 'B'):
416  ctx->postproc = DDS_SWIZZLE_RGXB;
417  break;
418  case MKTAG('R', 'x', 'B', 'G'):
419  ctx->postproc = DDS_SWIZZLE_RXBG;
420  break;
421  case MKTAG('x', 'G', 'x', 'R'):
422  ctx->postproc = DDS_SWIZZLE_XGXR;
423  break;
424  case MKTAG('A', '2', 'D', '5'):
425  ctx->postproc = DDS_NORMAL_MAP;
426  break;
427  }
428 
429  return 0;
430 }
431 
432 static void do_swizzle(AVFrame *frame, int x, int y)
433 {
434  int i;
435  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
436  uint8_t *src = frame->data[0] + i;
437  FFSWAP(uint8_t, src[x], src[y]);
438  }
439 }
440 
442 {
443  DDSContext *ctx = avctx->priv_data;
444  int i, x_off;
445 
446  switch (ctx->postproc) {
447  case DDS_ALPHA_EXP:
448  /* Alpha-exponential mode divides each channel by the maximum
449  * R, G or B value, and stores the multiplying factor in the
450  * alpha channel. */
451  av_log(avctx, AV_LOG_DEBUG, "Post-processing alpha exponent.\n");
452 
453  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
454  uint8_t *src = frame->data[0] + i;
455  int r = src[0];
456  int g = src[1];
457  int b = src[2];
458  int a = src[3];
459 
460  src[0] = r * a / 255;
461  src[1] = g * a / 255;
462  src[2] = b * a / 255;
463  src[3] = 255;
464  }
465  break;
466  case DDS_NORMAL_MAP:
467  /* Normal maps work in the XYZ color space and they encode
468  * X in R or in A, depending on the texture type, Y in G and
469  * derive Z with a square root of the distance.
470  *
471  * http://www.realtimecollisiondetection.net/blog/?p=28 */
472  av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n");
473 
474  x_off = ctx->dec.tex_ratio == 8 ? 0 : 3;
475  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
476  uint8_t *src = frame->data[0] + i;
477  int x = src[x_off];
478  int y = src[1];
479  int z = 127;
480 
481  int d = (255 * 255 - x * x - y * y) / 2;
482  if (d > 0)
483  z = lrint(sqrtf(d));
484 
485  src[0] = x;
486  src[1] = y;
487  src[2] = z;
488  src[3] = 255;
489  }
490  break;
491  case DDS_RAW_YCOCG:
492  /* Data is Y-Co-Cg-A and not RGBA, but they are represented
493  * with the same masks in the DDPF header. */
494  av_log(avctx, AV_LOG_DEBUG, "Post-processing raw YCoCg.\n");
495 
496  for (i = 0; i < frame->linesize[0] * frame->height; i += 4) {
497  uint8_t *src = frame->data[0] + i;
498  int a = src[0];
499  int cg = src[1] - 128;
500  int co = src[2] - 128;
501  int y = src[3];
502 
503  src[0] = av_clip_uint8(y + co - cg);
504  src[1] = av_clip_uint8(y + cg);
505  src[2] = av_clip_uint8(y - co - cg);
506  src[3] = a;
507  }
508  break;
509  case DDS_SWAP_ALPHA:
510  /* Alpha and Luma are stored swapped. */
511  av_log(avctx, AV_LOG_DEBUG, "Post-processing swapped Luma/Alpha.\n");
512 
513  for (i = 0; i < frame->linesize[0] * frame->height; i += 2) {
514  uint8_t *src = frame->data[0] + i;
515  FFSWAP(uint8_t, src[0], src[1]);
516  }
517  break;
518  case DDS_SWIZZLE_A2XY:
519  /* Swap R and G, often used to restore a standard RGTC2. */
520  av_log(avctx, AV_LOG_DEBUG, "Post-processing A2XY swizzle.\n");
521  do_swizzle(frame, 0, 1);
522  break;
523  case DDS_SWIZZLE_RBXG:
524  /* Swap G and A, then B and new A (G). */
525  av_log(avctx, AV_LOG_DEBUG, "Post-processing RBXG swizzle.\n");
526  do_swizzle(frame, 1, 3);
527  do_swizzle(frame, 2, 3);
528  break;
529  case DDS_SWIZZLE_RGXB:
530  /* Swap B and A. */
531  av_log(avctx, AV_LOG_DEBUG, "Post-processing RGXB swizzle.\n");
532  do_swizzle(frame, 2, 3);
533  break;
534  case DDS_SWIZZLE_RXBG:
535  /* Swap G and A. */
536  av_log(avctx, AV_LOG_DEBUG, "Post-processing RXBG swizzle.\n");
537  do_swizzle(frame, 1, 3);
538  break;
539  case DDS_SWIZZLE_RXGB:
540  /* Swap R and A (misleading name). */
541  av_log(avctx, AV_LOG_DEBUG, "Post-processing RXGB swizzle.\n");
542  do_swizzle(frame, 0, 3);
543  break;
544  case DDS_SWIZZLE_XGBR:
545  /* Swap B and A, then R and new A (B). */
546  av_log(avctx, AV_LOG_DEBUG, "Post-processing XGBR swizzle.\n");
547  do_swizzle(frame, 2, 3);
548  do_swizzle(frame, 0, 3);
549  break;
550  case DDS_SWIZZLE_XGXR:
551  /* Swap G and A, then R and new A (G), then new R (G) and new G (A).
552  * This variant does not store any B component. */
553  av_log(avctx, AV_LOG_DEBUG, "Post-processing XGXR swizzle.\n");
554  do_swizzle(frame, 1, 3);
555  do_swizzle(frame, 0, 3);
556  do_swizzle(frame, 0, 1);
557  break;
558  case DDS_SWIZZLE_XRBG:
559  /* Swap G and A, then R and new A (G). */
560  av_log(avctx, AV_LOG_DEBUG, "Post-processing XRBG swizzle.\n");
561  do_swizzle(frame, 1, 3);
562  do_swizzle(frame, 0, 3);
563  break;
564  }
565 }
566 
568  int *got_frame, AVPacket *avpkt)
569 {
570  DDSContext *ctx = avctx->priv_data;
571  GetByteContext *gbc = &ctx->gbc;
572  int mipmap;
573  int ret;
574  int width, height;
575 
576  ff_texturedsp_init(&ctx->texdsp);
577  bytestream2_init(gbc, avpkt->data, avpkt->size);
578 
579  if (bytestream2_get_bytes_left(gbc) < 128) {
580  av_log(avctx, AV_LOG_ERROR, "Frame is too small (%d).\n",
582  return AVERROR_INVALIDDATA;
583  }
584 
585  if (bytestream2_get_le32(gbc) != MKTAG('D', 'D', 'S', ' ') ||
586  bytestream2_get_le32(gbc) != 124) { // header size
587  av_log(avctx, AV_LOG_ERROR, "Invalid DDS header.\n");
588  return AVERROR_INVALIDDATA;
589  }
590 
591  bytestream2_skip(gbc, 4); // flags
592 
593  height = bytestream2_get_le32(gbc);
594  width = bytestream2_get_le32(gbc);
595  ret = ff_set_dimensions(avctx, width, height);
596  if (ret < 0) {
597  av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n",
598  avctx->width, avctx->height);
599  return ret;
600  }
601 
602  /* Since codec is based on 4x4 blocks, size is aligned to 4. */
603  avctx->coded_width = FFALIGN(avctx->width, TEXTURE_BLOCK_W);
604  avctx->coded_height = FFALIGN(avctx->height, TEXTURE_BLOCK_H);
605 
606  bytestream2_skip(gbc, 4); // pitch
607  bytestream2_skip(gbc, 4); // depth
608  mipmap = bytestream2_get_le32(gbc);
609  if (mipmap != 0)
610  av_log(avctx, AV_LOG_VERBOSE, "Found %d mipmaps (ignored).\n", mipmap);
611 
612  /* Extract pixel format information, considering additional elements
613  * in reserved1 and reserved2. */
614  ret = parse_pixel_format(avctx);
615  if (ret < 0)
616  return ret;
617 
618  ret = ff_get_buffer(avctx, frame, 0);
619  if (ret < 0)
620  return ret;
621 
622  if (ctx->compressed) {
623  int size = (avctx->coded_height / TEXTURE_BLOCK_H) *
624  (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->dec.tex_ratio;
625  ctx->dec.slice_count = av_clip(avctx->thread_count, 1,
626  avctx->coded_height / TEXTURE_BLOCK_H);
627 
628  if (bytestream2_get_bytes_left(gbc) < size) {
629  av_log(avctx, AV_LOG_ERROR,
630  "Compressed Buffer is too small (%d < %d).\n",
632  return AVERROR_INVALIDDATA;
633  }
634 
635  /* Use the decompress function on the texture, one block per thread. */
636  ctx->dec.tex_data.in = gbc->buffer;
637  ctx->dec.frame_data.out = frame->data[0];
638  ctx->dec.stride = frame->linesize[0];
639  avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec, NULL, ctx->dec.slice_count);
640  } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
641  uint8_t *dst = frame->data[0];
642  int x, y, i;
643 
644  /* Use the first 64 bytes as palette, then copy the rest. */
645  bytestream2_get_buffer(gbc, frame->data[1], 16 * 4);
646  for (i = 0; i < 16; i++) {
647  AV_WN32(frame->data[1] + i*4,
648  (frame->data[1][2+i*4]<<0)+
649  (frame->data[1][1+i*4]<<8)+
650  (frame->data[1][0+i*4]<<16)+
651  ((unsigned)frame->data[1][3+i*4]<<24)
652  );
653  }
654  frame->palette_has_changed = 1;
655 
656  if (bytestream2_get_bytes_left(gbc) < frame->height * frame->width / 2) {
657  av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
658  bytestream2_get_bytes_left(gbc), frame->height * frame->width / 2);
659  return AVERROR_INVALIDDATA;
660  }
661 
662  for (y = 0; y < frame->height; y++) {
663  for (x = 0; x < frame->width; x += 2) {
664  uint8_t val = bytestream2_get_byte(gbc);
665  dst[x ] = val & 0xF;
666  dst[x + 1] = val >> 4;
667  }
668  dst += frame->linesize[0];
669  }
670  } else {
671  int linesize = av_image_get_linesize(avctx->pix_fmt, frame->width, 0);
672 
673  if (ctx->paletted) {
674  int i;
675  /* Use the first 1024 bytes as palette, then copy the rest. */
676  bytestream2_get_buffer(gbc, frame->data[1], 256 * 4);
677  for (i = 0; i < 256; i++)
678  AV_WN32(frame->data[1] + i*4,
679  (frame->data[1][2+i*4]<<0)+
680  (frame->data[1][1+i*4]<<8)+
681  (frame->data[1][0+i*4]<<16)+
682  ((unsigned)frame->data[1][3+i*4]<<24)
683  );
684 
685  frame->palette_has_changed = 1;
686  }
687 
688  if (bytestream2_get_bytes_left(gbc) < frame->height * linesize) {
689  av_log(avctx, AV_LOG_ERROR, "Buffer is too small (%d < %d).\n",
690  bytestream2_get_bytes_left(gbc), frame->height * linesize);
691  return AVERROR_INVALIDDATA;
692  }
693 
694  av_image_copy_plane(frame->data[0], frame->linesize[0],
695  gbc->buffer, linesize,
696  linesize, frame->height);
697  }
698 
699  /* Run any post processing here if needed. */
700  if (ctx->postproc != DDS_NONE)
701  run_postproc(avctx, frame);
702 
703  /* Frame is ready to be output. */
704  frame->pict_type = AV_PICTURE_TYPE_I;
705  frame->key_frame = 1;
706  *got_frame = 1;
707 
708  return avpkt->size;
709 }
710 
712  .p.name = "dds",
713  CODEC_LONG_NAME("DirectDraw Surface image decoder"),
714  .p.type = AVMEDIA_TYPE_VIDEO,
715  .p.id = AV_CODEC_ID_DDS,
717  .priv_data_size = sizeof(DDSContext),
718  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
719 };
DXGI_FORMAT_BC4_SNORM
@ DXGI_FORMAT_BC4_SNORM
Definition: dds.c:86
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:49
DXGI_FORMAT_B8G8R8A8_TYPELESS
@ DXGI_FORMAT_B8G8R8A8_TYPELESS
Definition: dds.c:93
DXGI_FORMAT_BC2_UNORM_SRGB
@ DXGI_FORMAT_BC2_UNORM_SRGB
Definition: dds.c:80
DDS_RAW_YCOCG
@ DDS_RAW_YCOCG
Definition: dds.c:48
dds_decode
static int dds_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition: dds.c:567
av_clip
#define av_clip
Definition: common.h:95
r
const char * r
Definition: vf_curves.c:126
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:1002
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
@ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
Definition: dds.c:70
libm.h
DXGI_FORMAT_B8G8R8X8_UNORM
@ DXGI_FORMAT_B8G8R8X8_UNORM
Definition: dds.c:92
TEXTURE_BLOCK_H
#define TEXTURE_BLOCK_H
Definition: texturedsp.h:45
DXGI_FORMAT_B5G6R5_UNORM
@ DXGI_FORMAT_B5G6R5_UNORM
Definition: dds.c:90
GetByteContext
Definition: bytestream.h:33
DXGI_FORMAT_B8G8R8A8_UNORM
@ DXGI_FORMAT_B8G8R8A8_UNORM
Definition: dds.c:91
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
DDSContext::compressed
int compressed
Definition: dds.c:103
AVPacket::data
uint8_t * data
Definition: packet.h:374
DXGI_FORMAT_BC4_TYPELESS
@ DXGI_FORMAT_BC4_TYPELESS
Definition: dds.c:84
b
#define b
Definition: input.c:41
DDS_NONE
@ DDS_NONE
Definition: dds.c:45
DXGI_FORMAT_BC1_UNORM
@ DXGI_FORMAT_BC1_UNORM
Definition: dds.c:76
FFCodec
Definition: codec_internal.h:127
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:588
DXGI_FORMAT_R16G16B16A16_TYPELESS
@ DXGI_FORMAT_R16G16B16A16_TYPELESS
Definition: dds.c:61
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:96
ff_texturedsp_decompress_thread
int ff_texturedsp_decompress_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb)
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:104
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:75
texturedsp.h
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
DDSContext::bpp
int bpp
Definition: dds.c:105
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1502
DDPF_FOURCC
#define DDPF_FOURCC
Definition: dds.c:40
val
static double val(void *priv, double ch)
Definition: aeval.c:77
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:613
run_postproc
static void run_postproc(AVCodecContext *avctx, AVFrame *frame)
Definition: dds.c:441
DXGI_FORMAT_B8G8R8X8_TYPELESS
@ DXGI_FORMAT_B8G8R8X8_TYPELESS
Definition: dds.c:95
TextureDSPThreadContext
Definition: texturedsp.h:65
lrint
#define lrint
Definition: tablegen.h:53
DDSPostProc
DDSPostProc
Definition: dds.c:44
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:56
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:306
DDS_SWIZZLE_XGBR
@ DDS_SWIZZLE_XGBR
Definition: dds.c:55
DXGI_FORMAT_R16G16B16A16_SNORM
@ DXGI_FORMAT_R16G16B16A16_SNORM
Definition: dds.c:65
g
const char * g
Definition: vf_curves.c:127
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
decode.h
ff_texturedsp_init
av_cold void ff_texturedsp_init(TextureDSPContext *c)
Definition: texturedsp.c:637
DDS_SWIZZLE_RXBG
@ DDS_SWIZZLE_RXBG
Definition: dds.c:53
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
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:63
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:51
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:258
ff_dds_decoder
const FFCodec ff_dds_decoder
Definition: dds.c:711
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:85
DDPF_NORMALMAP
#define DDPF_NORMALMAP
Definition: dds.c:42
DDS_SWIZZLE_XGXR
@ DDS_SWIZZLE_XGXR
Definition: dds.c:57
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:1473
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
codec_internal.h
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
DDS_SWIZZLE_RXGB
@ DDS_SWIZZLE_RXGB
Definition: dds.c:54
DXGI_FORMAT_BC3_UNORM_SRGB
@ DXGI_FORMAT_BC3_UNORM_SRGB
Definition: dds.c:83
size
int size
Definition: twinvq_data.h:10344
DDSContext::texdsp
TextureDSPContext texdsp
Definition: dds.c:100
DXGI_FORMAT_R8G8B8A8_SNORM
@ DXGI_FORMAT_R8G8B8A8_SNORM
Definition: dds.c:72
DDSContext
Definition: dds.c:99
DXGI_FORMAT_BC5_SNORM
@ DXGI_FORMAT_BC5_SNORM
Definition: dds.c:89
DXGI_FORMAT_R8G8B8A8_TYPELESS
@ DXGI_FORMAT_R8G8B8A8_TYPELESS
Definition: dds.c:68
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:432
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:111
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:256
DXGI_FORMAT_R8G8B8A8_UINT
@ DXGI_FORMAT_R8G8B8A8_UINT
Definition: dds.c:71
DDSContext::postproc
enum DDSPostProc postproc
Definition: dds.c:106
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:62
AV_PIX_FMT_BGRA64
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:454
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:78
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:66
DDSDXGIFormat
DDSDXGIFormat
Definition: dds.c:60
parse_pixel_format
static int parse_pixel_format(AVCodecContext *avctx)
Definition: dds.c:111
TEXTURE_BLOCK_W
#define TEXTURE_BLOCK_W
Definition: texturedsp.h:44
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:191
AVCodecContext::height
int height
Definition: avcodec.h:598
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:635
DXGI_FORMAT_BC1_UNORM_SRGB
@ DXGI_FORMAT_BC1_UNORM_SRGB
Definition: dds.c:77
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:47
DXGI_FORMAT_BC5_TYPELESS
@ DXGI_FORMAT_BC5_TYPELESS
Definition: dds.c:87
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:41
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:82
AVCodecContext
main external API structure.
Definition: avcodec.h:426
DDSContext::dec
TextureDSPThreadContext dec
Definition: dds.c:108
DDSContext::gbc
GetByteContext gbc
Definition: dds.c:101
DXGI_FORMAT_BC2_UNORM
@ DXGI_FORMAT_BC2_UNORM
Definition: dds.c:79
DDS_SWIZZLE_RGXB
@ DDS_SWIZZLE_RGXB
Definition: dds.c:52
av_clip_uint8
#define av_clip_uint8
Definition: common.h:101
DXGI_FORMAT_R16G16B16A16_UINT
@ DXGI_FORMAT_R16G16B16A16_UINT
Definition: dds.c:64
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:613
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_CODEC_ID_DDS
@ AV_CODEC_ID_DDS
Definition: codec_id.h:242
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:98
DXGI_FORMAT_BC3_TYPELESS
@ DXGI_FORMAT_BC3_TYPELESS
Definition: dds.c:81
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:453
DDS_SWIZZLE_A2XY
@ DDS_SWIZZLE_A2XY
Definition: dds.c:50
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
d
d
Definition: ffmpeg_filter.c:156
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:598
bytestream.h
imgutils.h
DXGI_FORMAT_BC5_UNORM
@ DXGI_FORMAT_BC5_UNORM
Definition: dds.c:88
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:46
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:69
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:94
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:1551
DXGI_FORMAT_R8G8B8A8_SINT
@ DXGI_FORMAT_R8G8B8A8_SINT
Definition: dds.c:73
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:354