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