yading@10
|
1 /*
|
yading@10
|
2 * DPX (.dpx) image decoder
|
yading@10
|
3 * Copyright (c) 2009 Jimmy Christensen
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 #include "libavutil/intreadwrite.h"
|
yading@10
|
23 #include "libavutil/imgutils.h"
|
yading@10
|
24 #include "bytestream.h"
|
yading@10
|
25 #include "avcodec.h"
|
yading@10
|
26 #include "internal.h"
|
yading@10
|
27
|
yading@10
|
28 static unsigned int read32(const uint8_t **ptr, int is_big)
|
yading@10
|
29 {
|
yading@10
|
30 unsigned int temp;
|
yading@10
|
31 if (is_big) {
|
yading@10
|
32 temp = AV_RB32(*ptr);
|
yading@10
|
33 } else {
|
yading@10
|
34 temp = AV_RL32(*ptr);
|
yading@10
|
35 }
|
yading@10
|
36 *ptr += 4;
|
yading@10
|
37 return temp;
|
yading@10
|
38 }
|
yading@10
|
39
|
yading@10
|
40 static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
|
yading@10
|
41 int * n_datum, int is_big)
|
yading@10
|
42 {
|
yading@10
|
43 if (*n_datum)
|
yading@10
|
44 (*n_datum)--;
|
yading@10
|
45 else {
|
yading@10
|
46 *lbuf = read32(ptr, is_big);
|
yading@10
|
47 *n_datum = 2;
|
yading@10
|
48 }
|
yading@10
|
49
|
yading@10
|
50 *lbuf = (*lbuf << 10) | (*lbuf >> 22);
|
yading@10
|
51
|
yading@10
|
52 return *lbuf & 0x3FF;
|
yading@10
|
53 }
|
yading@10
|
54
|
yading@10
|
55 static int decode_frame(AVCodecContext *avctx,
|
yading@10
|
56 void *data,
|
yading@10
|
57 int *got_frame,
|
yading@10
|
58 AVPacket *avpkt)
|
yading@10
|
59 {
|
yading@10
|
60 const uint8_t *buf = avpkt->data;
|
yading@10
|
61 int buf_size = avpkt->size;
|
yading@10
|
62 AVFrame *const p = data;
|
yading@10
|
63 uint8_t *ptr[AV_NUM_DATA_POINTERS];
|
yading@10
|
64
|
yading@10
|
65 unsigned int offset;
|
yading@10
|
66 int magic_num, endian;
|
yading@10
|
67 int x, y, i, ret;
|
yading@10
|
68 int w, h, bits_per_color, descriptor, elements, packing, total_size;
|
yading@10
|
69
|
yading@10
|
70 unsigned int rgbBuffer = 0;
|
yading@10
|
71 int n_datum = 0;
|
yading@10
|
72
|
yading@10
|
73 if (avpkt->size <= 1634) {
|
yading@10
|
74 av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
|
yading@10
|
75 return AVERROR_INVALIDDATA;
|
yading@10
|
76 }
|
yading@10
|
77
|
yading@10
|
78 magic_num = AV_RB32(buf);
|
yading@10
|
79 buf += 4;
|
yading@10
|
80
|
yading@10
|
81 /* Check if the files "magic number" is "SDPX" which means it uses
|
yading@10
|
82 * big-endian or XPDS which is for little-endian files */
|
yading@10
|
83 if (magic_num == AV_RL32("SDPX")) {
|
yading@10
|
84 endian = 0;
|
yading@10
|
85 } else if (magic_num == AV_RB32("SDPX")) {
|
yading@10
|
86 endian = 1;
|
yading@10
|
87 } else {
|
yading@10
|
88 av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
|
yading@10
|
89 return AVERROR_INVALIDDATA;
|
yading@10
|
90 }
|
yading@10
|
91
|
yading@10
|
92 offset = read32(&buf, endian);
|
yading@10
|
93 if (avpkt->size <= offset) {
|
yading@10
|
94 av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n");
|
yading@10
|
95 return AVERROR_INVALIDDATA;
|
yading@10
|
96 }
|
yading@10
|
97 // Need to end in 0x304 offset from start of file
|
yading@10
|
98 buf = avpkt->data + 0x304;
|
yading@10
|
99 w = read32(&buf, endian);
|
yading@10
|
100 h = read32(&buf, endian);
|
yading@10
|
101 if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
|
yading@10
|
102 return ret;
|
yading@10
|
103
|
yading@10
|
104 if (w != avctx->width || h != avctx->height)
|
yading@10
|
105 avcodec_set_dimensions(avctx, w, h);
|
yading@10
|
106
|
yading@10
|
107 // Need to end in 0x320 to read the descriptor
|
yading@10
|
108 buf += 20;
|
yading@10
|
109 descriptor = buf[0];
|
yading@10
|
110
|
yading@10
|
111 // Need to end in 0x323 to read the bits per color
|
yading@10
|
112 buf += 3;
|
yading@10
|
113 avctx->bits_per_raw_sample =
|
yading@10
|
114 bits_per_color = buf[0];
|
yading@10
|
115 buf++;
|
yading@10
|
116 packing = *((uint16_t*)buf);
|
yading@10
|
117
|
yading@10
|
118 buf += 824;
|
yading@10
|
119 avctx->sample_aspect_ratio.num = read32(&buf, endian);
|
yading@10
|
120 avctx->sample_aspect_ratio.den = read32(&buf, endian);
|
yading@10
|
121 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0)
|
yading@10
|
122 av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
|
yading@10
|
123 avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den,
|
yading@10
|
124 0x10000);
|
yading@10
|
125 else
|
yading@10
|
126 avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
|
yading@10
|
127
|
yading@10
|
128 switch (descriptor) {
|
yading@10
|
129 case 51: // RGBA
|
yading@10
|
130 elements = 4;
|
yading@10
|
131 break;
|
yading@10
|
132 case 50: // RGB
|
yading@10
|
133 elements = 3;
|
yading@10
|
134 break;
|
yading@10
|
135 default:
|
yading@10
|
136 av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor);
|
yading@10
|
137 return AVERROR_INVALIDDATA;
|
yading@10
|
138 }
|
yading@10
|
139
|
yading@10
|
140 switch (bits_per_color) {
|
yading@10
|
141 case 8:
|
yading@10
|
142 if (elements == 4) {
|
yading@10
|
143 avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
yading@10
|
144 } else {
|
yading@10
|
145 avctx->pix_fmt = AV_PIX_FMT_RGB24;
|
yading@10
|
146 }
|
yading@10
|
147 total_size = avctx->width * avctx->height * elements;
|
yading@10
|
148 break;
|
yading@10
|
149 case 10:
|
yading@10
|
150 if (!packing) {
|
yading@10
|
151 av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
|
yading@10
|
152 return -1;
|
yading@10
|
153 }
|
yading@10
|
154 avctx->pix_fmt = AV_PIX_FMT_GBRP10;
|
yading@10
|
155 total_size = (avctx->width * elements + 2) / 3 * 4 * avctx->height;
|
yading@10
|
156 break;
|
yading@10
|
157 case 12:
|
yading@10
|
158 if (!packing) {
|
yading@10
|
159 av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
|
yading@10
|
160 return -1;
|
yading@10
|
161 }
|
yading@10
|
162 if (endian) {
|
yading@10
|
163 avctx->pix_fmt = AV_PIX_FMT_GBRP12BE;
|
yading@10
|
164 } else {
|
yading@10
|
165 avctx->pix_fmt = AV_PIX_FMT_GBRP12LE;
|
yading@10
|
166 }
|
yading@10
|
167 total_size = 2 * avctx->width * avctx->height * elements;
|
yading@10
|
168 break;
|
yading@10
|
169 case 16:
|
yading@10
|
170 if (endian) {
|
yading@10
|
171 avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGB48BE;
|
yading@10
|
172 } else {
|
yading@10
|
173 avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGB48LE;
|
yading@10
|
174 }
|
yading@10
|
175 total_size = 2 * avctx->width * avctx->height * elements;
|
yading@10
|
176 break;
|
yading@10
|
177 default:
|
yading@10
|
178 av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color);
|
yading@10
|
179 return AVERROR_INVALIDDATA;
|
yading@10
|
180 }
|
yading@10
|
181
|
yading@10
|
182 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
|
yading@10
|
183 return ret;
|
yading@10
|
184
|
yading@10
|
185 // Move pointer to offset from start of file
|
yading@10
|
186 buf = avpkt->data + offset;
|
yading@10
|
187
|
yading@10
|
188 for (i=0; i<AV_NUM_DATA_POINTERS; i++)
|
yading@10
|
189 ptr[i] = p->data[i];
|
yading@10
|
190
|
yading@10
|
191 if (total_size + (int64_t)offset > avpkt->size) {
|
yading@10
|
192 av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n");
|
yading@10
|
193 return AVERROR_INVALIDDATA;
|
yading@10
|
194 }
|
yading@10
|
195 switch (bits_per_color) {
|
yading@10
|
196 case 10:
|
yading@10
|
197 for (x = 0; x < avctx->height; x++) {
|
yading@10
|
198 uint16_t *dst[3] = {(uint16_t*)ptr[0],
|
yading@10
|
199 (uint16_t*)ptr[1],
|
yading@10
|
200 (uint16_t*)ptr[2]};
|
yading@10
|
201 for (y = 0; y < avctx->width; y++) {
|
yading@10
|
202 *dst[2]++ = read10in32(&buf, &rgbBuffer,
|
yading@10
|
203 &n_datum, endian);
|
yading@10
|
204 *dst[0]++ = read10in32(&buf, &rgbBuffer,
|
yading@10
|
205 &n_datum, endian);
|
yading@10
|
206 *dst[1]++ = read10in32(&buf, &rgbBuffer,
|
yading@10
|
207 &n_datum, endian);
|
yading@10
|
208 // For 10 bit, ignore alpha
|
yading@10
|
209 if (elements == 4)
|
yading@10
|
210 read10in32(&buf, &rgbBuffer,
|
yading@10
|
211 &n_datum, endian);
|
yading@10
|
212 }
|
yading@10
|
213 n_datum = 0;
|
yading@10
|
214 for (i = 0; i < 3; i++)
|
yading@10
|
215 ptr[i] += p->linesize[i];
|
yading@10
|
216 }
|
yading@10
|
217 break;
|
yading@10
|
218 case 12:
|
yading@10
|
219 for (x = 0; x < avctx->height; x++) {
|
yading@10
|
220 uint16_t *dst[3] = {(uint16_t*)ptr[0],
|
yading@10
|
221 (uint16_t*)ptr[1],
|
yading@10
|
222 (uint16_t*)ptr[2]};
|
yading@10
|
223 for (y = 0; y < avctx->width; y++) {
|
yading@10
|
224 *dst[2] = *((uint16_t*)buf);
|
yading@10
|
225 *dst[2] = (*dst[2] >> 4) | (*dst[2] << 12);
|
yading@10
|
226 dst[2]++;
|
yading@10
|
227 buf += 2;
|
yading@10
|
228 *dst[0] = *((uint16_t*)buf);
|
yading@10
|
229 *dst[0] = (*dst[0] >> 4) | (*dst[0] << 12);
|
yading@10
|
230 dst[0]++;
|
yading@10
|
231 buf += 2;
|
yading@10
|
232 *dst[1] = *((uint16_t*)buf);
|
yading@10
|
233 *dst[1] = (*dst[1] >> 4) | (*dst[1] << 12);
|
yading@10
|
234 dst[1]++;
|
yading@10
|
235 buf += 2;
|
yading@10
|
236 // For 12 bit, ignore alpha
|
yading@10
|
237 if (elements == 4)
|
yading@10
|
238 buf += 2;
|
yading@10
|
239 }
|
yading@10
|
240 for (i = 0; i < 3; i++)
|
yading@10
|
241 ptr[i] += p->linesize[i];
|
yading@10
|
242 }
|
yading@10
|
243 break;
|
yading@10
|
244 case 16:
|
yading@10
|
245 elements *= 2;
|
yading@10
|
246 case 8:
|
yading@10
|
247 for (x = 0; x < avctx->height; x++) {
|
yading@10
|
248 memcpy(ptr[0], buf, elements*avctx->width);
|
yading@10
|
249 ptr[0] += p->linesize[0];
|
yading@10
|
250 buf += elements*avctx->width;
|
yading@10
|
251 }
|
yading@10
|
252 break;
|
yading@10
|
253 }
|
yading@10
|
254
|
yading@10
|
255 *got_frame = 1;
|
yading@10
|
256
|
yading@10
|
257 return buf_size;
|
yading@10
|
258 }
|
yading@10
|
259
|
yading@10
|
260 AVCodec ff_dpx_decoder = {
|
yading@10
|
261 .name = "dpx",
|
yading@10
|
262 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
263 .id = AV_CODEC_ID_DPX,
|
yading@10
|
264 .decode = decode_frame,
|
yading@10
|
265 .long_name = NULL_IF_CONFIG_SMALL("DPX image"),
|
yading@10
|
266 .capabilities = CODEC_CAP_DR1,
|
yading@10
|
267 };
|