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/intfloat.h" 24#include "libavutil/imgutils.h" 25#include "bytestream.h" 26#include "avcodec.h" 27#include "internal.h" 28 29static unsigned int read16(const uint8_t **ptr, int is_big) 30{ 31 unsigned int temp; 32 if (is_big) { 33 temp = AV_RB16(*ptr); 34 } else { 35 temp = AV_RL16(*ptr); 36 } 37 *ptr += 2; 38 return temp; 39} 40 41static unsigned int read32(const uint8_t **ptr, int is_big) 42{ 43 unsigned int temp; 44 if (is_big) { 45 temp = AV_RB32(*ptr); 46 } else { 47 temp = AV_RL32(*ptr); 48 } 49 *ptr += 4; 50 return temp; 51} 52 53static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf, 54 int * n_datum, int is_big) 55{ 56 if (*n_datum) 57 (*n_datum)--; 58 else { 59 *lbuf = read32(ptr, is_big); 60 *n_datum = 2; 61 } 62 63 *lbuf = (*lbuf << 10) | (*lbuf >> 22); 64 65 return *lbuf & 0x3FF; 66} 67 68static int decode_frame(AVCodecContext *avctx, 69 void *data, 70 int *got_frame, 71 AVPacket *avpkt) 72{ 73 const uint8_t *buf = avpkt->data; 74 int buf_size = avpkt->size; 75 AVFrame *const p = data; 76 uint8_t *ptr[AV_NUM_DATA_POINTERS]; 77 78 unsigned int offset; 79 int magic_num, endian; 80 int x, y, i, ret; 81 int w, h, bits_per_color, descriptor, elements, packing, total_size; 82 int encoding; 83 84 unsigned int rgbBuffer = 0; 85 int n_datum = 0; 86 87 if (avpkt->size <= 1634) { 88 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n"); 89 return AVERROR_INVALIDDATA; 90 } 91 92 magic_num = AV_RB32(buf); 93 buf += 4; 94 95 /* Check if the files "magic number" is "SDPX" which means it uses 96 * big-endian or XPDS which is for little-endian files */ 97 if (magic_num == AV_RL32("SDPX")) { 98 endian = 0; 99 } else if (magic_num == AV_RB32("SDPX")) { 100 endian = 1; 101 } else { 102 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n"); 103 return AVERROR_INVALIDDATA; 104 } 105 106 offset = read32(&buf, endian); 107 if (avpkt->size <= offset) { 108 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n"); 109 return AVERROR_INVALIDDATA; 110 } 111 // Need to end in 0x304 offset from start of file 112 buf = avpkt->data + 0x304; 113 w = read32(&buf, endian); 114 h = read32(&buf, endian); 115 116 if ((ret = ff_set_dimensions(avctx, w, h)) < 0) 117 return ret; 118 119 // Need to end in 0x320 to read the descriptor 120 buf += 20; 121 descriptor = buf[0]; 122 123 // Need to end in 0x323 to read the bits per color 124 buf += 3; 125 avctx->bits_per_raw_sample = 126 bits_per_color = buf[0]; 127 buf++; 128 packing = read16(&buf, endian); 129 encoding = read16(&buf, endian); 130 131 if (packing > 1) { 132 avpriv_report_missing_feature(avctx, "Packing %d", packing); 133 return AVERROR_PATCHWELCOME; 134 } 135 if (encoding) { 136 avpriv_report_missing_feature(avctx, "Encoding %d", encoding); 137 return AVERROR_PATCHWELCOME; 138 } 139 140 buf += 820; 141 avctx->sample_aspect_ratio.num = read32(&buf, endian); 142 avctx->sample_aspect_ratio.den = read32(&buf, endian); 143 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) 144 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, 145 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 146 0x10000); 147 else 148 avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; 149 150 if (offset >= 1724 + 4) { 151 buf = avpkt->data + 1724; 152 i = read32(&buf, endian); 153 if(i) { 154 AVRational q = av_d2q(av_int2float(i), 4096); 155 if (q.num > 0 && q.den > 0) 156 avctx->time_base = av_inv_q(q); 157 } 158 } 159 160 switch (descriptor) { 161 case 6: // Y 162 elements = 1; 163 break; 164 case 52: // ABGR 165 case 51: // RGBA 166 elements = 4; 167 break; 168 case 50: // RGB 169 elements = 3; 170 break; 171 default: 172 avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor); 173 return AVERROR_PATCHWELCOME; 174 } 175 176 switch (bits_per_color) { 177 case 8: 178 total_size = avctx->width * avctx->height * elements; 179 break; 180 case 10: 181 if (!packing) { 182 av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n"); 183 return -1; 184 } 185 total_size = (avctx->width * elements + 2) / 3 * 4 * avctx->height; 186 break; 187 case 12: 188 if (!packing) { 189 av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n"); 190 return -1; 191 } 192 total_size = 2 * avctx->width * avctx->height * elements; 193 break; 194 case 16: 195 total_size = 2 * avctx->width * avctx->height * elements; 196 break; 197 case 1: 198 case 32: 199 case 64: 200 avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color); 201 return AVERROR_PATCHWELCOME; 202 default: 203 return AVERROR_INVALIDDATA; 204 } 205 206 switch (1000 * descriptor + 10 * bits_per_color + endian) { 207 case 6081: 208 case 6080: 209 avctx->pix_fmt = AV_PIX_FMT_GRAY8; 210 break; 211 case 50081: 212 case 50080: 213 avctx->pix_fmt = AV_PIX_FMT_RGB24; 214 break; 215 case 52081: 216 case 52080: 217 avctx->pix_fmt = AV_PIX_FMT_ABGR; 218 break; 219 case 51081: 220 case 51080: 221 avctx->pix_fmt = AV_PIX_FMT_RGBA; 222 break; 223 case 50100: 224 case 51100: 225 case 50101: 226 case 51101: 227 avctx->pix_fmt = AV_PIX_FMT_GBRP10; 228 break; 229 case 50120: 230 case 51120: 231 case 50121: 232 case 51121: 233 avctx->pix_fmt = AV_PIX_FMT_GBRP12; 234 break; 235 case 6161: 236 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE; 237 break; 238 case 6160: 239 avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; 240 break; 241 case 50161: 242 avctx->pix_fmt = AV_PIX_FMT_RGB48BE; 243 break; 244 case 50160: 245 avctx->pix_fmt = AV_PIX_FMT_RGB48LE; 246 break; 247 case 51161: 248 avctx->pix_fmt = AV_PIX_FMT_RGBA64BE; 249 break; 250 case 51160: 251 avctx->pix_fmt = AV_PIX_FMT_RGBA64LE; 252 break; 253 default: 254 av_log(avctx, AV_LOG_ERROR, "Unsupported format\n"); 255 return AVERROR_PATCHWELCOME; 256 } 257 258 ff_set_sar(avctx, avctx->sample_aspect_ratio); 259 260 if ((ret = ff_get_buffer(avctx, p, 0)) < 0) 261 return ret; 262 263 // Move pointer to offset from start of file 264 buf = avpkt->data + offset; 265 266 for (i=0; i<AV_NUM_DATA_POINTERS; i++) 267 ptr[i] = p->data[i]; 268 269 if (total_size + (int64_t)offset > avpkt->size) { 270 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n"); 271 return AVERROR_INVALIDDATA; 272 } 273 switch (bits_per_color) { 274 case 10: 275 for (x = 0; x < avctx->height; x++) { 276 uint16_t *dst[3] = {(uint16_t*)ptr[0], 277 (uint16_t*)ptr[1], 278 (uint16_t*)ptr[2]}; 279 for (y = 0; y < avctx->width; y++) { 280 *dst[2]++ = read10in32(&buf, &rgbBuffer, 281 &n_datum, endian); 282 *dst[0]++ = read10in32(&buf, &rgbBuffer, 283 &n_datum, endian); 284 *dst[1]++ = read10in32(&buf, &rgbBuffer, 285 &n_datum, endian); 286 // For 10 bit, ignore alpha 287 if (elements == 4) 288 read10in32(&buf, &rgbBuffer, 289 &n_datum, endian); 290 } 291 n_datum = 0; 292 for (i = 0; i < 3; i++) 293 ptr[i] += p->linesize[i]; 294 } 295 break; 296 case 12: 297 for (x = 0; x < avctx->height; x++) { 298 uint16_t *dst[3] = {(uint16_t*)ptr[0], 299 (uint16_t*)ptr[1], 300 (uint16_t*)ptr[2]}; 301 for (y = 0; y < avctx->width; y++) { 302 *dst[2] = read16(&buf, endian) >> 4; 303 dst[2]++; 304 *dst[0] = read16(&buf, endian) >> 4; 305 dst[0]++; 306 *dst[1] = read16(&buf, endian) >> 4; 307 dst[1]++; 308 // For 12 bit, ignore alpha 309 if (elements == 4) 310 buf += 2; 311 } 312 for (i = 0; i < 3; i++) 313 ptr[i] += p->linesize[i]; 314 } 315 break; 316 case 16: 317 elements *= 2; 318 case 8: 319 av_image_copy_plane(ptr[0], p->linesize[0], 320 buf, elements * avctx->width, 321 elements * avctx->width, avctx->height); 322 break; 323 } 324 325 *got_frame = 1; 326 327 return buf_size; 328} 329 330AVCodec ff_dpx_decoder = { 331 .name = "dpx", 332 .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), 333 .type = AVMEDIA_TYPE_VIDEO, 334 .id = AV_CODEC_ID_DPX, 335 .decode = decode_frame, 336 .capabilities = CODEC_CAP_DR1, 337}; 338