2 * DPX (.dpx) image decoder
3 * Copyright (c) 2009 Jimmy Christensen
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/intfloat.h"
25 #include "libavutil/imgutils.h"
26 #include "bytestream.h"
30 static unsigned int read16(const uint8_t **ptr, int is_big)
42 static unsigned int read32(const uint8_t **ptr, int is_big)
54 static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
55 int * n_datum, int is_big, int shift)
60 *lbuf = read32(ptr, is_big);
64 *lbuf = *lbuf << 10 | *lbuf >> shift & 0x3FFFFF;
69 static uint16_t read12in32(const uint8_t **ptr, uint32_t * lbuf,
70 int * n_datum, int is_big)
75 *lbuf = read32(ptr, is_big);
80 case 7: return *lbuf & 0xFFF;
81 case 6: return (*lbuf >> 12) & 0xFFF;
83 uint32_t c = *lbuf >> 24;
84 *lbuf = read32(ptr, is_big);
88 case 4: return (*lbuf >> 4) & 0xFFF;
89 case 3: return (*lbuf >> 16) & 0xFFF;
91 uint32_t c = *lbuf >> 28;
92 *lbuf = read32(ptr, is_big);
96 case 1: return (*lbuf >> 8) & 0xFFF;
97 default: return *lbuf >> 20;
101 static int decode_frame(AVCodecContext *avctx,
106 const uint8_t *buf = avpkt->data;
107 int buf_size = avpkt->size;
108 AVFrame *const p = data;
109 uint8_t *ptr[AV_NUM_DATA_POINTERS];
110 uint32_t header_version, version = 0;
112 char input_device[33];
115 int magic_num, endian;
116 int x, y, stride, i, ret;
117 int w, h, bits_per_color, descriptor, elements, packing;
118 int encoding, need_align = 0;
120 unsigned int rgbBuffer = 0;
123 if (avpkt->size <= 1634) {
124 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
125 return AVERROR_INVALIDDATA;
128 magic_num = AV_RB32(buf);
131 /* Check if the files "magic number" is "SDPX" which means it uses
132 * big-endian or XPDS which is for little-endian files */
133 if (magic_num == AV_RL32("SDPX")) {
135 } else if (magic_num == AV_RB32("SDPX")) {
138 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
139 return AVERROR_INVALIDDATA;
142 offset = read32(&buf, endian);
143 if (avpkt->size <= offset) {
144 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
145 return AVERROR_INVALIDDATA;
148 header_version = read32(&buf, 0);
149 if (header_version == MKTAG('V','1','.','0'))
151 if (header_version == MKTAG('V','2','.','0'))
154 av_log(avctx, AV_LOG_WARNING, "Unknown header format version %s.\n",
155 av_fourcc2str(header_version));
158 buf = avpkt->data + 660;
159 ret = read32(&buf, endian);
160 if (ret != 0xFFFFFFFF) {
161 avpriv_report_missing_feature(avctx, "Encryption");
162 av_log(avctx, AV_LOG_WARNING, "The image is encrypted and may "
163 "not properly decode.\n");
166 // Need to end in 0x304 offset from start of file
167 buf = avpkt->data + 0x304;
168 w = read32(&buf, endian);
169 h = read32(&buf, endian);
171 if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
174 // Need to end in 0x320 to read the descriptor
178 // Need to end in 0x323 to read the bits per color
180 avctx->bits_per_raw_sample =
181 bits_per_color = buf[0];
183 packing = read16(&buf, endian);
184 encoding = read16(&buf, endian);
187 avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
188 return AVERROR_PATCHWELCOME;
192 avctx->sample_aspect_ratio.num = read32(&buf, endian);
193 avctx->sample_aspect_ratio.den = read32(&buf, endian);
194 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
195 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
196 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den,
199 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
201 if (offset >= 1724 + 4) {
202 buf = avpkt->data + 1724;
203 i = read32(&buf, endian);
205 AVRational q = av_d2q(av_int2float(i), 4096);
206 if (q.num > 0 && q.den > 0)
207 avctx->framerate = q;
211 switch (descriptor) {
217 case 103: // UYVA4444
228 avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
229 return AVERROR_PATCHWELCOME;
232 switch (bits_per_color) {
234 stride = avctx->width * elements;
238 av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
241 stride = (avctx->width * elements + 2) / 3 * 4;
244 stride = avctx->width * elements;
258 stride = 2 * avctx->width * elements;
263 avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
264 return AVERROR_PATCHWELCOME;
266 return AVERROR_INVALIDDATA;
269 // Table 3c: Runs will always break at scan line boundaries. Packing
270 // will always break to the next 32-bit word at scan-line boundaries.
271 // Unfortunately, the encoder produced invalid files, so attempt
273 need_align = FFALIGN(stride, 4);
274 if (need_align*avctx->height + (int64_t)offset > avpkt->size) {
275 // Alignment seems unappliable, try without
276 if (stride*avctx->height + (int64_t)offset > avpkt->size) {
277 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
278 return AVERROR_INVALIDDATA;
280 av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
285 need_align -= stride;
286 stride = FFALIGN(stride, 4);
289 switch (1000 * descriptor + 10 * bits_per_color + endian) {
292 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
296 avctx->pix_fmt = AV_PIX_FMT_GRAY12;
300 avctx->pix_fmt = AV_PIX_FMT_RGB24;
304 avctx->pix_fmt = AV_PIX_FMT_ABGR;
308 avctx->pix_fmt = AV_PIX_FMT_RGBA;
312 avctx->pix_fmt = AV_PIX_FMT_GBRP10;
316 avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
320 avctx->pix_fmt = AV_PIX_FMT_GBRP12;
324 avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
328 avctx->pix_fmt = AV_PIX_FMT_GRAY10;
331 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
334 avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
337 avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
340 avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
343 avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
346 avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
349 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
352 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
355 avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
358 av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
359 return AVERROR_PATCHWELCOME;
362 ff_set_sar(avctx, avctx->sample_aspect_ratio);
364 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
367 av_strlcpy(creator, avpkt->data + 160, 100);
369 av_dict_set(&p->metadata, "Creator", creator, 0);
371 av_strlcpy(input_device, avpkt->data + 1556, 32);
372 input_device[32] = '\0';
373 av_dict_set(&p->metadata, "Input Device", input_device, 0);
375 // Move pointer to offset from start of file
376 buf = avpkt->data + offset;
378 for (i=0; i<AV_NUM_DATA_POINTERS; i++)
381 switch (bits_per_color) {
383 for (x = 0; x < avctx->height; x++) {
384 uint16_t *dst[4] = {(uint16_t*)ptr[0],
388 int shift = packing == 1 ? 22 : 20;
389 for (y = 0; y < avctx->width; y++) {
391 *dst[2]++ = read10in32(&buf, &rgbBuffer,
392 &n_datum, endian, shift);
393 *dst[0]++ = read10in32(&buf, &rgbBuffer,
394 &n_datum, endian, shift);
396 *dst[1]++ = read10in32(&buf, &rgbBuffer,
397 &n_datum, endian, shift);
400 read10in32(&buf, &rgbBuffer,
401 &n_datum, endian, shift);
404 for (i = 0; i < elements; i++)
405 ptr[i] += p->linesize[i];
409 for (x = 0; x < avctx->height; x++) {
410 uint16_t *dst[4] = {(uint16_t*)ptr[0],
414 int shift = packing == 1 ? 4 : 0;
415 for (y = 0; y < avctx->width; y++) {
418 *dst[2]++ = read16(&buf, endian) >> shift & 0xFFF;
419 *dst[0]++ = read16(&buf, endian) >> shift & 0xFFF;
421 *dst[1]++ = read16(&buf, endian) >> shift & 0xFFF;
423 *dst[3]++ = read16(&buf, endian) >> shift & 0xFFF;
426 *dst[2]++ = read12in32(&buf, &rgbBuffer,
428 *dst[0]++ = read12in32(&buf, &rgbBuffer,
431 *dst[1]++ = read12in32(&buf, &rgbBuffer,
434 *dst[3]++ = read12in32(&buf, &rgbBuffer,
439 for (i = 0; i < elements; i++)
440 ptr[i] += p->linesize[i];
441 // Jump to next aligned position
448 if ( avctx->pix_fmt == AV_PIX_FMT_YUVA444P
449 || avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
450 for (x = 0; x < avctx->height; x++) {
451 ptr[0] = p->data[0] + x * p->linesize[0];
452 ptr[1] = p->data[1] + x * p->linesize[1];
453 ptr[2] = p->data[2] + x * p->linesize[2];
454 ptr[3] = p->data[3] + x * p->linesize[3];
455 for (y = 0; y < avctx->width; y++) {
459 if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
464 av_image_copy_plane(ptr[0], p->linesize[0],
466 elements * avctx->width, avctx->height);
476 AVCodec ff_dpx_decoder = {
478 .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
479 .type = AVMEDIA_TYPE_VIDEO,
480 .id = AV_CODEC_ID_DPX,
481 .decode = decode_frame,
482 .capabilities = AV_CODEC_CAP_DR1,