Libav
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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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 inline unsigned make_16bit(unsigned value)
41 {
42  // mask away invalid bits
43  value &= 0xFFC0;
44  // correctly expand to 16 bits
45  return value + (value >> 10);
46 }
47 
48 static int decode_frame(AVCodecContext *avctx,
49  void *data,
50  int *got_frame,
51  AVPacket *avpkt)
52 {
53  const uint8_t *buf = avpkt->data;
54  const uint8_t *buf_end = avpkt->data + avpkt->size;
55  int buf_size = avpkt->size;
56  AVFrame *const p = data;
57  uint8_t *ptr;
58 
59  unsigned int offset;
60  int magic_num, endian;
61  int x, y, ret;
62  int w, h, stride, bits_per_color, descriptor, elements, target_packet_size, source_packet_size;
63 
64  unsigned int rgbBuffer;
65 
66  if (avpkt->size <= 1634) {
67  av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
68  return AVERROR_INVALIDDATA;
69  }
70 
71  magic_num = AV_RB32(buf);
72  buf += 4;
73 
74  /* Check if the files "magic number" is "SDPX" which means it uses
75  * big-endian or XPDS which is for little-endian files */
76  if (magic_num == AV_RL32("SDPX")) {
77  endian = 0;
78  } else if (magic_num == AV_RB32("SDPX")) {
79  endian = 1;
80  } else {
81  av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
82  return AVERROR_INVALIDDATA;
83  }
84 
85  offset = read32(&buf, endian);
86  if (avpkt->size <= offset) {
87  av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
88  return AVERROR_INVALIDDATA;
89  }
90  // Need to end in 0x304 offset from start of file
91  buf = avpkt->data + 0x304;
92  w = read32(&buf, endian);
93  h = read32(&buf, endian);
94 
95  // Need to end in 0x320 to read the descriptor
96  buf += 20;
97  descriptor = buf[0];
98 
99  // Need to end in 0x323 to read the bits per color
100  buf += 3;
101  avctx->bits_per_raw_sample =
102  bits_per_color = buf[0];
103 
104  buf += 825;
105  avctx->sample_aspect_ratio.num = read32(&buf, endian);
106  avctx->sample_aspect_ratio.den = read32(&buf, endian);
107 
108  switch (descriptor) {
109  case 51: // RGBA
110  elements = 4;
111  break;
112  case 50: // RGB
113  elements = 3;
114  break;
115  default:
116  av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
117  return AVERROR_INVALIDDATA;
118  }
119 
120  switch (bits_per_color) {
121  case 8:
122  if (elements == 4) {
123  avctx->pix_fmt = AV_PIX_FMT_RGBA;
124  } else {
125  avctx->pix_fmt = AV_PIX_FMT_RGB24;
126  }
127  source_packet_size = elements;
128  target_packet_size = elements;
129  break;
130  case 10:
131  avctx->pix_fmt = AV_PIX_FMT_RGB48;
132  target_packet_size = 6;
133  source_packet_size = 4;
134  break;
135  case 12:
136  case 16:
137  if (endian) {
138  avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
139  } else {
140  avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
141  }
142  target_packet_size = 6;
143  source_packet_size = elements * 2;
144  break;
145  default:
146  av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
147  return AVERROR_INVALIDDATA;
148  }
149 
150  if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
151  return ret;
152 
153  ff_set_sar(avctx, avctx->sample_aspect_ratio);
154 
155  if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
156  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
157  return ret;
158  }
159 
160  // Move pointer to offset from start of file
161  buf = avpkt->data + offset;
162 
163  ptr = p->data[0];
164  stride = p->linesize[0];
165 
166  if (source_packet_size*avctx->width*avctx->height > buf_end - buf) {
167  av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
168  return AVERROR_INVALIDDATA;
169  }
170  switch (bits_per_color) {
171  case 10:
172  for (x = 0; x < avctx->height; x++) {
173  uint16_t *dst = (uint16_t*)ptr;
174  for (y = 0; y < avctx->width; y++) {
175  rgbBuffer = read32(&buf, endian);
176  // Read out the 10-bit colors and convert to 16-bit
177  *dst++ = make_16bit(rgbBuffer >> 16);
178  *dst++ = make_16bit(rgbBuffer >> 6);
179  *dst++ = make_16bit(rgbBuffer << 4);
180  }
181  ptr += stride;
182  }
183  break;
184  case 8:
185  case 12: // Treat 12-bit as 16-bit
186  case 16:
187  if (source_packet_size == target_packet_size) {
188  for (x = 0; x < avctx->height; x++) {
189  memcpy(ptr, buf, target_packet_size*avctx->width);
190  ptr += stride;
191  buf += source_packet_size*avctx->width;
192  }
193  } else {
194  for (x = 0; x < avctx->height; x++) {
195  uint8_t *dst = ptr;
196  for (y = 0; y < avctx->width; y++) {
197  memcpy(dst, buf, target_packet_size);
198  dst += target_packet_size;
199  buf += source_packet_size;
200  }
201  ptr += stride;
202  }
203  }
204  break;
205  }
206 
207  *got_frame = 1;
208 
209  return buf_size;
210 }
211 
213  .name = "dpx",
214  .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
215  .type = AVMEDIA_TYPE_VIDEO,
216  .id = AV_CODEC_ID_DPX,
217  .decode = decode_frame,
218  .capabilities = CODEC_CAP_DR1,
219 };
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: dpx.c:48
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
This structure describes decoded (raw) audio or video data.
Definition: frame.h:135
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:67
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:133
int num
numerator
Definition: rational.h:44
int size
Definition: avcodec.h:974
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
Definition: avcodec.h:1429
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1254
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:2514
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:2796
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big...
Definition: pixfmt.h:112
uint8_t
AVCodec ff_dpx_decoder
Definition: dpx.c:212
const char * name
Name of the codec implementation.
Definition: avcodec.h:2803
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:684
const char data[16]
Definition: mxf.c:70
int ff_set_sar(AVCodecContext *avctx, AVRational sar)
Check that the provided sample aspect ratio is valid and set it on the codec context.
Definition: utils.c:145
static unsigned int read32(const uint8_t **ptr, int is_big)
Definition: dpx.c:28
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:150
static unsigned make_16bit(unsigned value)
Definition: dpx.c:40
Libavcodec external API header.
int width
picture width / height.
Definition: avcodec.h:1224
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as lit...
Definition: pixfmt.h:113
main external API structure.
Definition: avcodec.h:1050
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:612
uint8_t * data
Definition: avcodec.h:973
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:153
common internal api header.
int den
denominator
Definition: rational.h:45
#define AV_RB32(x)
Definition: intreadwrite.h:232
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:96
#define AV_RL32(x)
Definition: intreadwrite.h:248
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:229
This structure stores compressed data.
Definition: avcodec.h:950
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:141