]> git.sesse.net Git - ffmpeg/blob - libavcodec/dpx.c
avcodec/dpx: add support for another gray10 variant
[ffmpeg] / libavcodec / dpx.c
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/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/intfloat.h"
25 #include "libavutil/imgutils.h"
26 #include "bytestream.h"
27 #include "avcodec.h"
28 #include "internal.h"
29
30 static unsigned int read16(const uint8_t **ptr, int is_big)
31 {
32     unsigned int temp;
33     if (is_big) {
34         temp = AV_RB16(*ptr);
35     } else {
36         temp = AV_RL16(*ptr);
37     }
38     *ptr += 2;
39     return temp;
40 }
41
42 static unsigned int read32(const uint8_t **ptr, int is_big)
43 {
44     unsigned int temp;
45     if (is_big) {
46         temp = AV_RB32(*ptr);
47     } else {
48         temp = AV_RL32(*ptr);
49     }
50     *ptr += 4;
51     return temp;
52 }
53
54 static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf,
55                                   int * n_datum, int is_big, int shift)
56 {
57     if (*n_datum)
58         (*n_datum)--;
59     else {
60         *lbuf = read32(ptr, is_big);
61         *n_datum = 2;
62     }
63
64     *lbuf = *lbuf << 10 | *lbuf >> shift & 0x3FFFFF;
65
66     return *lbuf & 0x3FF;
67 }
68
69 static uint16_t read12in32(const uint8_t **ptr, uint32_t * lbuf,
70                                   int * n_datum, int is_big)
71 {
72     if (*n_datum)
73         (*n_datum)--;
74     else {
75         *lbuf = read32(ptr, is_big);
76         *n_datum = 7;
77     }
78
79     switch (*n_datum){
80     case 7: return *lbuf & 0xFFF;
81     case 6: return (*lbuf >> 12) & 0xFFF;
82     case 5: {
83             uint32_t c = *lbuf >> 24;
84             *lbuf = read32(ptr, is_big);
85             c |= *lbuf << 8;
86             return c & 0xFFF;
87             }
88     case 4: return (*lbuf >> 4) & 0xFFF;
89     case 3: return (*lbuf >> 16) & 0xFFF;
90     case 2: {
91             uint32_t c = *lbuf >> 28;
92             *lbuf = read32(ptr, is_big);
93             c |= *lbuf << 4;
94             return c & 0xFFF;
95             }
96     case 1: return (*lbuf >> 8) & 0xFFF;
97     default: return *lbuf >> 20;
98     }
99 }
100
101 static int decode_frame(AVCodecContext *avctx,
102                         void *data,
103                         int *got_frame,
104                         AVPacket *avpkt)
105 {
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;
111     char creator[101];
112     char input_device[33];
113
114     unsigned int offset;
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;
119
120     unsigned int rgbBuffer = 0;
121     int n_datum = 0;
122
123     if (avpkt->size <= 1634) {
124         av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n");
125         return AVERROR_INVALIDDATA;
126     }
127
128     magic_num = AV_RB32(buf);
129     buf += 4;
130
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")) {
134         endian = 0;
135     } else if (magic_num == AV_RB32("SDPX")) {
136         endian = 1;
137     } else {
138         av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n");
139         return AVERROR_INVALIDDATA;
140     }
141
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;
146     }
147
148     header_version = read32(&buf, 0);
149     if (header_version == MKTAG('V','1','.','0'))
150         version = 1;
151     if (header_version == MKTAG('V','2','.','0'))
152         version = 2;
153     if (!version)
154         av_log(avctx, AV_LOG_WARNING, "Unknown header format version %s.\n",
155                av_fourcc2str(header_version));
156
157     // Check encryption
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");
164     }
165
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);
170
171     if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
172         return ret;
173
174     // Need to end in 0x320 to read the descriptor
175     buf += 20;
176     descriptor = buf[0];
177
178     // Need to end in 0x323 to read the bits per color
179     buf += 3;
180     avctx->bits_per_raw_sample =
181     bits_per_color = buf[0];
182     buf++;
183     packing = read16(&buf, endian);
184     encoding = read16(&buf, endian);
185
186     if (encoding) {
187         avpriv_report_missing_feature(avctx, "Encoding %d", encoding);
188         return AVERROR_PATCHWELCOME;
189     }
190
191     buf += 820;
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,
197                   0x10000);
198     else
199         avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
200
201     if (offset >= 1724 + 4) {
202         buf = avpkt->data + 1724;
203         i = read32(&buf, endian);
204         if(i) {
205             AVRational q = av_d2q(av_int2float(i), 4096);
206             if (q.num > 0 && q.den > 0)
207                 avctx->framerate = q;
208         }
209     }
210
211     switch (descriptor) {
212     case 6:  // Y
213         elements = 1;
214         break;
215     case 52: // ABGR
216     case 51: // RGBA
217     case 103: // UYVA4444
218         elements = 4;
219         break;
220     case 50: // RGB
221     case 102: // UYV444
222         elements = 3;
223         break;
224     case 100: // UYVY422
225         elements = 2;
226         break;
227     default:
228         avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor);
229         return AVERROR_PATCHWELCOME;
230     }
231
232     switch (bits_per_color) {
233     case 8:
234         stride = avctx->width * elements;
235         break;
236     case 10:
237         if (!packing) {
238             av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n");
239             return -1;
240         }
241         stride = (avctx->width * elements + 2) / 3 * 4;
242         break;
243     case 12:
244         stride = avctx->width * elements;
245         if (packing) {
246             stride *= 2;
247         } else {
248             stride *= 3;
249             if (stride % 8) {
250                 stride /= 8;
251                 stride++;
252                 stride *= 8;
253             }
254             stride /= 2;
255         }
256         break;
257     case 16:
258         stride = 2 * avctx->width * elements;
259         break;
260     case 1:
261     case 32:
262     case 64:
263         avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color);
264         return AVERROR_PATCHWELCOME;
265     default:
266         return AVERROR_INVALIDDATA;
267     }
268
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
272     // to detect it
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;
279         } else {
280             av_log(avctx, AV_LOG_INFO, "Decoding DPX without scanline "
281                    "alignment.\n");
282             need_align = 0;
283         }
284     } else {
285         need_align -= stride;
286         stride = FFALIGN(stride, 4);
287     }
288
289     switch (1000 * descriptor + 10 * bits_per_color + endian) {
290     case 6081:
291     case 6080:
292         avctx->pix_fmt = AV_PIX_FMT_GRAY8;
293         break;
294     case 6121:
295     case 6120:
296         avctx->pix_fmt = AV_PIX_FMT_GRAY12;
297         break;
298     case 50081:
299     case 50080:
300         avctx->pix_fmt = AV_PIX_FMT_RGB24;
301         break;
302     case 52081:
303     case 52080:
304         avctx->pix_fmt = AV_PIX_FMT_ABGR;
305         break;
306     case 51081:
307     case 51080:
308         avctx->pix_fmt = AV_PIX_FMT_RGBA;
309         break;
310     case 50100:
311     case 50101:
312         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
313         break;
314     case 51100:
315     case 51101:
316         avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
317         break;
318     case 50120:
319     case 50121:
320         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
321         break;
322     case 51120:
323     case 51121:
324         avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
325         break;
326     case 6100:
327     case 6101:
328         avctx->pix_fmt = AV_PIX_FMT_GRAY10;
329         break;
330     case 6161:
331         avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
332         break;
333     case 6160:
334         avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
335         break;
336     case 50161:
337         avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
338         break;
339     case 50160:
340         avctx->pix_fmt = AV_PIX_FMT_RGB48LE;
341         break;
342     case 51161:
343         avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
344         break;
345     case 51160:
346         avctx->pix_fmt = AV_PIX_FMT_RGBA64LE;
347         break;
348     case 100081:
349         avctx->pix_fmt = AV_PIX_FMT_UYVY422;
350         break;
351     case 102081:
352         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
353         break;
354     case 103081:
355         avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
356         break;
357     default:
358         av_log(avctx, AV_LOG_ERROR, "Unsupported format\n");
359         return AVERROR_PATCHWELCOME;
360     }
361
362     ff_set_sar(avctx, avctx->sample_aspect_ratio);
363
364     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
365         return ret;
366
367     av_strlcpy(creator, avpkt->data + 160, 100);
368     creator[100] = '\0';
369     av_dict_set(&p->metadata, "Creator", creator, 0);
370
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);
374
375     // Move pointer to offset from start of file
376     buf =  avpkt->data + offset;
377
378     for (i=0; i<AV_NUM_DATA_POINTERS; i++)
379         ptr[i] = p->data[i];
380
381     switch (bits_per_color) {
382     case 10:
383         for (x = 0; x < avctx->height; x++) {
384             uint16_t *dst[4] = {(uint16_t*)ptr[0],
385                                 (uint16_t*)ptr[1],
386                                 (uint16_t*)ptr[2],
387                                 (uint16_t*)ptr[3]};
388             int shift = packing == 1 ? 22 : 20;
389             for (y = 0; y < avctx->width; y++) {
390                 if (elements >= 3)
391                     *dst[2]++ = read10in32(&buf, &rgbBuffer,
392                                            &n_datum, endian, shift);
393                 *dst[0]++ = read10in32(&buf, &rgbBuffer,
394                                        &n_datum, endian, shift);
395                 if (elements >= 2)
396                     *dst[1]++ = read10in32(&buf, &rgbBuffer,
397                                            &n_datum, endian, shift);
398                 if (elements == 4)
399                     *dst[3]++ =
400                     read10in32(&buf, &rgbBuffer,
401                                &n_datum, endian, shift);
402             }
403             n_datum = 0;
404             for (i = 0; i < elements; i++)
405                 ptr[i] += p->linesize[i];
406         }
407         break;
408     case 12:
409         for (x = 0; x < avctx->height; x++) {
410             uint16_t *dst[4] = {(uint16_t*)ptr[0],
411                                 (uint16_t*)ptr[1],
412                                 (uint16_t*)ptr[2],
413                                 (uint16_t*)ptr[3]};
414             int shift = packing == 1 ? 4 : 0;
415             for (y = 0; y < avctx->width; y++) {
416                 if (packing) {
417                     if (elements >= 3)
418                         *dst[2]++ = read16(&buf, endian) >> shift & 0xFFF;
419                     *dst[0]++ = read16(&buf, endian) >> shift & 0xFFF;
420                     if (elements >= 2)
421                         *dst[1]++ = read16(&buf, endian) >> shift & 0xFFF;
422                     if (elements == 4)
423                         *dst[3]++ = read16(&buf, endian) >> shift & 0xFFF;
424                 } else {
425                     if (elements >= 3)
426                         *dst[2]++ = read12in32(&buf, &rgbBuffer,
427                                                &n_datum, endian);
428                     *dst[0]++ = read12in32(&buf, &rgbBuffer,
429                                            &n_datum, endian);
430                     if (elements >= 2)
431                         *dst[1]++ = read12in32(&buf, &rgbBuffer,
432                                                &n_datum, endian);
433                     if (elements == 4)
434                         *dst[3]++ = read12in32(&buf, &rgbBuffer,
435                                                &n_datum, endian);
436                 }
437             }
438             n_datum = 0;
439             for (i = 0; i < elements; i++)
440                 ptr[i] += p->linesize[i];
441             // Jump to next aligned position
442             buf += need_align;
443         }
444         break;
445     case 16:
446         elements *= 2;
447     case 8:
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++) {
456                     *ptr[1]++ = *buf++;
457                     *ptr[0]++ = *buf++;
458                     *ptr[2]++ = *buf++;
459                     if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P)
460                         *ptr[3]++ = *buf++;
461                 }
462             }
463         } else {
464         av_image_copy_plane(ptr[0], p->linesize[0],
465                             buf, stride,
466                             elements * avctx->width, avctx->height);
467         }
468         break;
469     }
470
471     *got_frame = 1;
472
473     return buf_size;
474 }
475
476 AVCodec ff_dpx_decoder = {
477     .name           = "dpx",
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,
483 };