FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dpx.c
Go to the documentation of this file.
1 /*
2  * DPX (.dpx) image decoder
3  * Copyright (c) 2009 Jimmy Christensen
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 #include "libavutil/intreadwrite.h"
23 #include "libavutil/imgutils.h"
24 #include "bytestream.h"
25 #include "avcodec.h"
26 #include "internal.h"
27 
28 static unsigned int read32(const uint8_t **ptr, int is_big)
29 {
30  unsigned int temp;
31  if (is_big) {
32  temp = AV_RB32(*ptr);
33  } else {
34  temp = AV_RL32(*ptr);
35  }
36  *ptr += 4;
37  return temp;
38 }
39 
40 static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
41  int * n_datum, int is_big)
42 {
43  if (*n_datum)
44  (*n_datum)--;
45  else {
46  *lbuf = read32(ptr, is_big);
47  *n_datum = 2;
48  }
49 
50  *lbuf = (*lbuf << 10) | (*lbuf >> 22);
51 
52  return *lbuf & 0x3FF;
53 }
54 
55 static int decode_frame(AVCodecContext *avctx,
56  void *data,
57  int *got_frame,
58  AVPacket *avpkt)
59 {
60  const uint8_t *buf = avpkt->data;
61  int buf_size = avpkt->size;
62  AVFrame *const p = data;
64 
65  unsigned int offset;
66  int magic_num, endian;
67  int x, y, i, ret;
68  int w, h, bits_per_color, descriptor, elements, packing, total_size;
69 
70  unsigned int rgbBuffer = 0;
71  int n_datum = 0;
72 
73  if (avpkt->size <= 1634) {
74  av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
75  return AVERROR_INVALIDDATA;
76  }
77 
78  magic_num = AV_RB32(buf);
79  buf += 4;
80 
81  /* Check if the files "magic number" is "SDPX" which means it uses
82  * big-endian or XPDS which is for little-endian files */
83  if (magic_num == AV_RL32("SDPX")) {
84  endian = 0;
85  } else if (magic_num == AV_RB32("SDPX")) {
86  endian = 1;
87  } else {
88  av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
89  return AVERROR_INVALIDDATA;
90  }
91 
92  offset = read32(&buf, endian);
93  if (avpkt->size <= offset) {
94  av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
95  return AVERROR_INVALIDDATA;
96  }
97  // Need to end in 0x304 offset from start of file
98  buf = avpkt->data + 0x304;
99  w = read32(&buf, endian);
100  h = read32(&buf, endian);
101  if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
102  return ret;
103 
104  if (w != avctx->width || h != avctx->height)
105  avcodec_set_dimensions(avctx, w, h);
106 
107  // Need to end in 0x320 to read the descriptor
108  buf += 20;
109  descriptor = buf[0];
110 
111  // Need to end in 0x323 to read the bits per color
112  buf += 3;
113  avctx->bits_per_raw_sample =
114  bits_per_color = buf[0];
115  buf++;
116  packing = *((uint16_t*)buf);
117 
118  buf += 824;
119  avctx->sample_aspect_ratio.num = read32(&buf, endian);
120  avctx->sample_aspect_ratio.den = read32(&buf, endian);
121  if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
124  0x10000);
125  else
126  avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
127 
128  switch (descriptor) {
129  case 51: // RGBA
130  elements = 4;
131  break;
132  case 50: // RGB
133  elements = 3;
134  break;
135  default:
136  av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
137  return AVERROR_INVALIDDATA;
138  }
139 
140  switch (bits_per_color) {
141  case 8:
142  if (elements == 4) {
143  avctx->pix_fmt = AV_PIX_FMT_RGBA;
144  } else {
145  avctx->pix_fmt = AV_PIX_FMT_RGB24;
146  }
147  total_size = avctx->width * avctx->height * elements;
148  break;
149  case 10:
150  if (!packing) {
151  av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
152  return -1;
153  }
154  avctx->pix_fmt = AV_PIX_FMT_GBRP10;
155  total_size = (avctx->width * elements + 2) / 3 * 4 * avctx->height;
156  break;
157  case 12:
158  if (!packing) {
159  av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
160  return -1;
161  }
162  if (endian) {
163  avctx->pix_fmt = AV_PIX_FMT_GBRP12BE;
164  } else {
165  avctx->pix_fmt = AV_PIX_FMT_GBRP12LE;
166  }
167  total_size = 2 * avctx->width * avctx->height * elements;
168  break;
169  case 16:
170  if (endian) {
171  avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGB48BE;
172  } else {
173  avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGB48LE;
174  }
175  total_size = 2 * avctx->width * avctx->height * elements;
176  break;
177  default:
178  av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
179  return AVERROR_INVALIDDATA;
180  }
181 
182  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
183  return ret;
184 
185  // Move pointer to offset from start of file
186  buf = avpkt->data + offset;
187 
188  for (i=0; i<AV_NUM_DATA_POINTERS; i++)
189  ptr[i] = p->data[i];
190 
191  if (total_size + (int64_t)offset > avpkt->size) {
192  av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
193  return AVERROR_INVALIDDATA;
194  }
195  switch (bits_per_color) {
196  case 10:
197  for (x = 0; x < avctx->height; x++) {
198  uint16_t *dst[3] = {(uint16_t*)ptr[0],
199  (uint16_t*)ptr[1],
200  (uint16_t*)ptr[2]};
201  for (y = 0; y < avctx->width; y++) {
202  *dst[2]++ = read10in32(&buf, &rgbBuffer,
203  &n_datum, endian);
204  *dst[0]++ = read10in32(&buf, &rgbBuffer,
205  &n_datum, endian);
206  *dst[1]++ = read10in32(&buf, &rgbBuffer,
207  &n_datum, endian);
208  // For 10 bit, ignore alpha
209  if (elements == 4)
210  read10in32(&buf, &rgbBuffer,
211  &n_datum, endian);
212  }
213  n_datum = 0;
214  for (i = 0; i < 3; i++)
215  ptr[i] += p->linesize[i];
216  }
217  break;
218  case 12:
219  for (x = 0; x < avctx->height; x++) {
220  uint16_t *dst[3] = {(uint16_t*)ptr[0],
221  (uint16_t*)ptr[1],
222  (uint16_t*)ptr[2]};
223  for (y = 0; y < avctx->width; y++) {
224  *dst[2] = *((uint16_t*)buf);
225  *dst[2] = (*dst[2] >> 4) | (*dst[2] << 12);
226  dst[2]++;
227  buf += 2;
228  *dst[0] = *((uint16_t*)buf);
229  *dst[0] = (*dst[0] >> 4) | (*dst[0] << 12);
230  dst[0]++;
231  buf += 2;
232  *dst[1] = *((uint16_t*)buf);
233  *dst[1] = (*dst[1] >> 4) | (*dst[1] << 12);
234  dst[1]++;
235  buf += 2;
236  // For 12 bit, ignore alpha
237  if (elements == 4)
238  buf += 2;
239  }
240  for (i = 0; i < 3; i++)
241  ptr[i] += p->linesize[i];
242  }
243  break;
244  case 16:
245  elements *= 2;
246  case 8:
247  for (x = 0; x < avctx->height; x++) {
248  memcpy(ptr[0], buf, elements*avctx->width);
249  ptr[0] += p->linesize[0];
250  buf += elements*avctx->width;
251  }
252  break;
253  }
254 
255  *got_frame = 1;
256 
257  return buf_size;
258 }
259 
261  .name = "dpx",
262  .type = AVMEDIA_TYPE_VIDEO,
263  .id = AV_CODEC_ID_DPX,
264  .decode = decode_frame,
265  .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
266  .capabilities = CODEC_CAP_DR1,
267 };