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