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;
114 int magic_num, endian;
115 int x, y, stride, i, ret;
116 int w, h, bits_per_color, descriptor, elements, packing;
117 int encoding, need_align = 0;
119 unsigned int rgbBuffer = 0;
122 if (avpkt->size <= 1634) {
123 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
124 return AVERROR_INVALIDDATA;
127 magic_num = AV_RB32(buf);
130 /* Check if the files "magic number" is "SDPX" which means it uses
131 * big-endian or XPDS which is for little-endian files */
132 if (magic_num == AV_RL32("SDPX")) {
134 } else if (magic_num == AV_RB32("SDPX")) {
137 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
138 return AVERROR_INVALIDDATA;
141 offset = read32(&buf, endian);
142 if (avpkt->size <= offset) {
143 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
144 return AVERROR_INVALIDDATA;
147 header_version = read32(&buf, 0);
148 if (header_version == MKTAG('V','1','.','0'))
150 if (header_version == MKTAG('V','2','.','0'))
153 av_log(avctx, AV_LOG_WARNING, "Unknown header format version %s.\n",
154 av_fourcc2str(header_version));
157 buf = avpkt->data + 660;
158 ret = read32(&buf, endian);
159 if (ret != 0xFFFFFFFF) {
160 avpriv_report_missing_feature(avctx, "Encryption");
161 av_log(avctx, AV_LOG_WARNING, "The image is encrypted and may "
162 "not properly decode.\n");
165 // Need to end in 0x304 offset from start of file
166 buf = avpkt->data + 0x304;
167 w = read32(&buf, endian);
168 h = read32(&buf, endian);
170 if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
173 // Need to end in 0x320 to read the descriptor
177 // Need to end in 0x323 to read the bits per color
179 avctx->bits_per_raw_sample =
180 bits_per_color = buf[0];
182 packing = read16(&buf, endian);
183 encoding = read16(&buf, endian);
186 avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
187 return AVERROR_PATCHWELCOME;
191 avctx->sample_aspect_ratio.num = read32(&buf, endian);
192 avctx->sample_aspect_ratio.den = read32(&buf, endian);
193 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
194 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
195 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den,
198 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
200 if (offset >= 1724 + 4) {
201 buf = avpkt->data + 1724;
202 i = read32(&buf, endian);
204 AVRational q = av_d2q(av_int2float(i), 4096);
205 if (q.num > 0 && q.den > 0)
206 avctx->framerate = q;
210 switch (descriptor) {
216 case 103: // UYVA4444
227 avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
228 return AVERROR_PATCHWELCOME;
231 switch (bits_per_color) {
233 stride = avctx->width * elements;
237 av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
240 stride = (avctx->width * elements + 2) / 3 * 4;
243 stride = avctx->width * elements;
257 stride = 2 * avctx->width * elements;
262 avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
263 return AVERROR_PATCHWELCOME;
265 return AVERROR_INVALIDDATA;
268 // Table 3c: Runs will always break at scan line boundaries. Packing
269 // will always break to the next 32-bit word at scan-line boundaries.
270 // Unfortunately, the encoder produced invalid files, so attempt
272 need_align = FFALIGN(stride, 4);
273 if (need_align*avctx->height + (int64_t)offset > avpkt->size) {
274 // Alignment seems unappliable, try without
275 if (stride*avctx->height + (int64_t)offset > avpkt->size) {
276 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
277 return AVERROR_INVALIDDATA;
279 av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
284 need_align -= stride;
285 stride = FFALIGN(stride, 4);
288 switch (1000 * descriptor + 10 * bits_per_color + endian) {
291 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
295 avctx->pix_fmt = AV_PIX_FMT_GRAY12;
299 avctx->pix_fmt = AV_PIX_FMT_RGB24;
303 avctx->pix_fmt = AV_PIX_FMT_ABGR;
307 avctx->pix_fmt = AV_PIX_FMT_RGBA;
311 avctx->pix_fmt = AV_PIX_FMT_GBRP10;
315 avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
319 avctx->pix_fmt = AV_PIX_FMT_GBRP12;
323 avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
326 avctx->pix_fmt = AV_PIX_FMT_GRAY10;
329 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
332 avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
335 avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
338 avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
341 avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
344 avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
347 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
350 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
353 avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
356 av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
357 return AVERROR_PATCHWELCOME;
360 ff_set_sar(avctx, avctx->sample_aspect_ratio);
362 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
365 av_strlcpy(creator, avpkt->data + 160, 100);
367 av_dict_set(&p->metadata, "Creator", creator, 0);
369 // Move pointer to offset from start of file
370 buf = avpkt->data + offset;
372 for (i=0; i<AV_NUM_DATA_POINTERS; i++)
375 switch (bits_per_color) {
377 for (x = 0; x < avctx->height; x++) {
378 uint16_t *dst[4] = {(uint16_t*)ptr[0],
382 int shift = packing == 1 ? 22 : 20;
383 for (y = 0; y < avctx->width; y++) {
385 *dst[2]++ = read10in32(&buf, &rgbBuffer,
386 &n_datum, endian, shift);
387 *dst[0]++ = read10in32(&buf, &rgbBuffer,
388 &n_datum, endian, shift);
390 *dst[1]++ = read10in32(&buf, &rgbBuffer,
391 &n_datum, endian, shift);
394 read10in32(&buf, &rgbBuffer,
395 &n_datum, endian, shift);
398 for (i = 0; i < elements; i++)
399 ptr[i] += p->linesize[i];
403 for (x = 0; x < avctx->height; x++) {
404 uint16_t *dst[4] = {(uint16_t*)ptr[0],
408 int shift = packing == 1 ? 4 : 0;
409 for (y = 0; y < avctx->width; y++) {
412 *dst[2]++ = read16(&buf, endian) >> shift & 0xFFF;
413 *dst[0]++ = read16(&buf, endian) >> shift & 0xFFF;
415 *dst[1]++ = read16(&buf, endian) >> shift & 0xFFF;
417 *dst[3]++ = read16(&buf, endian) >> shift & 0xFFF;
420 *dst[2]++ = read12in32(&buf, &rgbBuffer,
422 *dst[0]++ = read12in32(&buf, &rgbBuffer,
425 *dst[1]++ = read12in32(&buf, &rgbBuffer,
428 *dst[3]++ = read12in32(&buf, &rgbBuffer,
433 for (i = 0; i < elements; i++)
434 ptr[i] += p->linesize[i];
435 // Jump to next aligned position
442 if ( avctx->pix_fmt == AV_PIX_FMT_YUVA444P
443 || avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
444 for (x = 0; x < avctx->height; x++) {
445 ptr[0] = p->data[0] + x * p->linesize[0];
446 ptr[1] = p->data[1] + x * p->linesize[1];
447 ptr[2] = p->data[2] + x * p->linesize[2];
448 ptr[3] = p->data[3] + x * p->linesize[3];
449 for (y = 0; y < avctx->width; y++) {
453 if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
458 av_image_copy_plane(ptr[0], p->linesize[0],
460 elements * avctx->width, avctx->height);
470 AVCodec ff_dpx_decoder = {
472 .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
473 .type = AVMEDIA_TYPE_VIDEO,
474 .id = AV_CODEC_ID_DPX,
475 .decode = decode_frame,
476 .capabilities = AV_CODEC_CAP_DR1,