Mercurial > libavcodec.hg
annotate dpx.c @ 12391:4be72e19ab0e libavcodec
imc: fix undefined float to int conversion
Conversion of an out of range float to int is undefined. Clipping to
the final range first avoids such problems. This fixes decoding on
MIPS, which handles these conversions differently from many other CPUs.
author | mru |
---|---|
date | Thu, 19 Aug 2010 16:51:26 +0000 |
parents | 914f484bb476 |
children | ffb3668ff7af |
rev | line source |
---|---|
9839 | 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" | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11560
diff
changeset
|
23 #include "libavcore/imgutils.h" |
9839 | 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 inline unsigned make_16bit(unsigned value) | |
45 { | |
46 // mask away invalid bits | |
47 value &= 0xFFC0; | |
48 // correctly expand to 16 bits | |
49 return value + (value >> 10); | |
50 } | |
51 | |
52 static int decode_frame(AVCodecContext *avctx, | |
53 void *data, | |
54 int *data_size, | |
55 AVPacket *avpkt) | |
56 { | |
57 const uint8_t *buf = avpkt->data; | |
58 int buf_size = avpkt->size; | |
59 DPXContext *const s = avctx->priv_data; | |
60 AVFrame *picture = data; | |
61 AVFrame *const p = &s->picture; | |
62 uint8_t *ptr; | |
63 | |
64 int magic_num, offset, endian; | |
65 int x, y; | |
66 int w, h, stride, bits_per_color, descriptor, elements, target_packet_size, source_packet_size; | |
67 | |
68 unsigned int rgbBuffer; | |
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 // Need to end in 0x304 offset from start of file | |
86 buf = avpkt->data + 0x304; | |
87 w = read32(&buf, endian); | |
88 h = read32(&buf, endian); | |
89 | |
90 // Need to end in 0x320 to read the descriptor | |
91 buf += 20; | |
92 descriptor = buf[0]; | |
93 | |
94 // Need to end in 0x323 to read the bits per color | |
95 buf += 3; | |
10691
d54e52670962
Set bits_per_raw_sample appropriately in dpx decoder.
reimar
parents:
9839
diff
changeset
|
96 avctx->bits_per_raw_sample = |
9839 | 97 bits_per_color = buf[0]; |
98 | |
99 switch (descriptor) { | |
100 case 51: // RGBA | |
101 elements = 4; | |
102 break; | |
103 case 50: // RGB | |
104 elements = 3; | |
105 break; | |
106 default: | |
107 av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor); | |
108 return -1; | |
109 } | |
110 | |
111 switch (bits_per_color) { | |
112 case 8: | |
113 if (elements == 4) { | |
114 avctx->pix_fmt = PIX_FMT_RGBA; | |
115 } else { | |
116 avctx->pix_fmt = PIX_FMT_RGB24; | |
117 } | |
118 source_packet_size = elements; | |
119 target_packet_size = elements; | |
120 break; | |
121 case 10: | |
122 avctx->pix_fmt = PIX_FMT_RGB48; | |
123 target_packet_size = 6; | |
124 source_packet_size = elements * 2; | |
125 break; | |
126 case 12: | |
127 case 16: | |
128 if (endian) { | |
129 avctx->pix_fmt = PIX_FMT_RGB48BE; | |
130 } else { | |
131 avctx->pix_fmt = PIX_FMT_RGB48LE; | |
132 } | |
133 target_packet_size = 6; | |
134 source_packet_size = elements * 2; | |
135 break; | |
136 default: | |
137 av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color); | |
138 return -1; | |
139 } | |
140 | |
141 if (s->picture.data[0]) | |
142 avctx->release_buffer(avctx, &s->picture); | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11560
diff
changeset
|
143 if (av_check_image_size(w, h, 0, avctx)) |
9839 | 144 return -1; |
145 if (w != avctx->width || h != avctx->height) | |
146 avcodec_set_dimensions(avctx, w, h); | |
147 if (avctx->get_buffer(avctx, p) < 0) { | |
148 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
149 return -1; | |
150 } | |
151 | |
152 // Move pointer to offset from start of file | |
153 buf = avpkt->data + offset; | |
154 | |
155 ptr = p->data[0]; | |
156 stride = p->linesize[0]; | |
157 | |
158 switch (bits_per_color) { | |
159 case 10: | |
160 for (x = 0; x < avctx->height; x++) { | |
161 uint16_t *dst = (uint16_t*)ptr; | |
162 for (y = 0; y < avctx->width; y++) { | |
163 rgbBuffer = read32(&buf, endian); | |
164 // Read out the 10-bit colors and convert to 16-bit | |
165 *dst++ = make_16bit(rgbBuffer >> 16); | |
166 *dst++ = make_16bit(rgbBuffer >> 6); | |
167 *dst++ = make_16bit(rgbBuffer << 4); | |
168 } | |
169 ptr += stride; | |
170 } | |
171 break; | |
172 case 8: | |
173 case 12: // Treat 12-bit as 16-bit | |
174 case 16: | |
175 if (source_packet_size == target_packet_size) { | |
176 for (x = 0; x < avctx->height; x++) { | |
177 memcpy(ptr, buf, target_packet_size*avctx->width); | |
178 ptr += stride; | |
179 buf += source_packet_size*avctx->width; | |
180 } | |
181 } else { | |
182 for (x = 0; x < avctx->height; x++) { | |
183 uint8_t *dst = ptr; | |
184 for (y = 0; y < avctx->width; y++) { | |
185 memcpy(dst, buf, target_packet_size); | |
186 dst += target_packet_size; | |
187 buf += source_packet_size; | |
188 } | |
189 ptr += stride; | |
190 } | |
191 } | |
192 break; | |
193 } | |
194 | |
195 *picture = s->picture; | |
196 *data_size = sizeof(AVPicture); | |
197 | |
198 return buf_size; | |
199 } | |
200 | |
201 static av_cold int decode_init(AVCodecContext *avctx) | |
202 { | |
203 DPXContext *s = avctx->priv_data; | |
204 avcodec_get_frame_defaults(&s->picture); | |
205 avctx->coded_frame = &s->picture; | |
206 return 0; | |
207 } | |
208 | |
209 static av_cold int decode_end(AVCodecContext *avctx) | |
210 { | |
211 DPXContext *s = avctx->priv_data; | |
212 if (s->picture.data[0]) | |
213 avctx->release_buffer(avctx, &s->picture); | |
214 | |
215 return 0; | |
216 } | |
217 | |
218 AVCodec dpx_decoder = { | |
219 "dpx", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10691
diff
changeset
|
220 AVMEDIA_TYPE_VIDEO, |
9839 | 221 CODEC_ID_DPX, |
222 sizeof(DPXContext), | |
223 decode_init, | |
224 NULL, | |
225 decode_end, | |
226 decode_frame, | |
227 0, | |
228 NULL, | |
229 .long_name = NULL_IF_CONFIG_SMALL("DPX image"), | |
230 }; |