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