Mercurial > libavcodec.hg
annotate sgidec.c @ 12454:f4355cd85faa libavcodec
Port latest x264 deblock asm (before they moved to using NV12 as internal
format), LGPL'ed with permission from Jason and Loren. This includes mmx2
code, so remove inline asm from h264dsp_mmx.c accordingly.
author | rbultje |
---|---|
date | Fri, 03 Sep 2010 16:52:46 +0000 |
parents | 914f484bb476 |
children | ffb3668ff7af |
rev | line source |
---|---|
4790 | 1 /* |
2 * SGI image decoder | |
3 * Todd Kirby <doubleshot@pacbell.net> | |
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 | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11560
diff
changeset
|
22 #include "libavcore/imgutils.h" |
4790 | 23 #include "avcodec.h" |
24 #include "bytestream.h" | |
25 #include "sgi.h" | |
26 | |
27 typedef struct SgiState { | |
28 AVFrame picture; | |
29 unsigned int width; | |
30 unsigned int height; | |
31 unsigned int depth; | |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
32 unsigned int bytes_per_channel; |
4790 | 33 int linesize; |
34 } SgiState; | |
35 | |
36 /** | |
37 * Expand an RLE row into a channel. | |
38 * @param in_buf input buffer | |
39 * @param in_end end of input buffer | |
40 * @param out_buf Points to one line after the output buffer. | |
41 * @param out_end end of line in output buffer | |
42 * @param pixelstride pixel stride of input buffer | |
43 * @return size of output in bytes, -1 if buffer overflows | |
44 */ | |
6218 | 45 static int expand_rle_row(const uint8_t *in_buf, const uint8_t* in_end, |
4790 | 46 unsigned char *out_buf, uint8_t* out_end, int pixelstride) |
47 { | |
48 unsigned char pixel, count; | |
49 unsigned char *orig = out_buf; | |
50 | |
51 while (1) { | |
52 if(in_buf + 1 > in_end) return -1; | |
53 pixel = bytestream_get_byte(&in_buf); | |
54 if (!(count = (pixel & 0x7f))) { | |
55 return (out_buf - orig) / pixelstride; | |
56 } | |
57 | |
58 /* Check for buffer overflow. */ | |
59 if(out_buf + pixelstride * count >= out_end) return -1; | |
60 | |
61 if (pixel & 0x80) { | |
62 while (count--) { | |
63 *out_buf = bytestream_get_byte(&in_buf); | |
64 out_buf += pixelstride; | |
65 } | |
66 } else { | |
67 pixel = bytestream_get_byte(&in_buf); | |
68 | |
69 while (count--) { | |
70 *out_buf = pixel; | |
71 out_buf += pixelstride; | |
72 } | |
73 } | |
74 } | |
75 } | |
76 | |
77 /** | |
78 * Read a run length encoded SGI image. | |
79 * @param out_buf output buffer | |
80 * @param in_buf input buffer | |
81 * @param in_end end of input buffer | |
82 * @param s the current image state | |
83 * @return 0 if no error, else return error number. | |
84 */ | |
6218 | 85 static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, |
86 const uint8_t *in_end, SgiState* s) | |
4790 | 87 { |
88 uint8_t *dest_row; | |
89 unsigned int len = s->height * s->depth * 4; | |
6218 | 90 const uint8_t *start_table = in_buf; |
4790 | 91 unsigned int y, z; |
92 unsigned int start_offset; | |
93 | |
94 /* size of RLE offset and length tables */ | |
95 if(len * 2 > in_end - in_buf) { | |
96 return AVERROR_INVALIDDATA; | |
97 } | |
98 | |
99 in_buf -= SGI_HEADER_SIZE; | |
100 for (z = 0; z < s->depth; z++) { | |
101 dest_row = out_buf; | |
102 for (y = 0; y < s->height; y++) { | |
103 dest_row -= s->linesize; | |
104 start_offset = bytestream_get_be32(&start_table); | |
105 if(start_offset > in_end - in_buf) { | |
106 return AVERROR_INVALIDDATA; | |
107 } | |
108 if (expand_rle_row(in_buf + start_offset, in_end, dest_row + z, | |
109 dest_row + FFABS(s->linesize), s->depth) != s->width) | |
110 return AVERROR_INVALIDDATA; | |
111 } | |
112 } | |
113 return 0; | |
114 } | |
115 | |
116 /** | |
117 * Read an uncompressed SGI image. | |
118 * @param out_buf output buffer | |
119 * @param out_end end ofoutput buffer | |
120 * @param in_buf input buffer | |
121 * @param in_end end of input buffer | |
122 * @param s the current image state | |
123 * @return 0 if read success, otherwise return -1. | |
124 */ | |
125 static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, | |
6218 | 126 const uint8_t *in_buf, const uint8_t *in_end, SgiState* s) |
4790 | 127 { |
128 int x, y, z; | |
6218 | 129 const uint8_t *ptr; |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
130 unsigned int offset = s->height * s->width * s->bytes_per_channel; |
4790 | 131 |
132 /* Test buffer size. */ | |
133 if (offset * s->depth > in_end - in_buf) { | |
134 return -1; | |
135 } | |
136 | |
137 for (y = s->height - 1; y >= 0; y--) { | |
138 out_end = out_buf + (y * s->linesize); | |
139 for (x = s->width; x > 0; x--) { | |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
140 ptr = in_buf += s->bytes_per_channel; |
4790 | 141 for(z = 0; z < s->depth; z ++) { |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
142 memcpy(out_end, ptr, s->bytes_per_channel); |
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
143 out_end += s->bytes_per_channel; |
4790 | 144 ptr += offset; |
145 } | |
146 } | |
147 } | |
148 return 0; | |
149 } | |
150 | |
151 static int decode_frame(AVCodecContext *avctx, | |
152 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
153 AVPacket *avpkt) |
4790 | 154 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
155 const uint8_t *in_buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
156 int buf_size = avpkt->size; |
4790 | 157 SgiState *s = avctx->priv_data; |
158 AVFrame *picture = data; | |
159 AVFrame *p = &s->picture; | |
6218 | 160 const uint8_t *in_end = in_buf + buf_size; |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
161 unsigned int dimension, rle; |
4790 | 162 int ret = 0; |
163 uint8_t *out_buf, *out_end; | |
164 | |
165 if (buf_size < SGI_HEADER_SIZE){ | |
166 av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size); | |
167 return -1; | |
168 } | |
169 | |
170 /* Test for SGI magic. */ | |
171 if (bytestream_get_be16(&in_buf) != SGI_MAGIC) { | |
172 av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); | |
173 return -1; | |
174 } | |
175 | |
176 rle = bytestream_get_byte(&in_buf); | |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
177 s->bytes_per_channel = bytestream_get_byte(&in_buf); |
4790 | 178 dimension = bytestream_get_be16(&in_buf); |
179 s->width = bytestream_get_be16(&in_buf); | |
180 s->height = bytestream_get_be16(&in_buf); | |
181 s->depth = bytestream_get_be16(&in_buf); | |
182 | |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
183 if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) { |
4790 | 184 av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); |
185 return -1; | |
186 } | |
187 | |
188 /* Check for supported image dimensions. */ | |
189 if (dimension != 2 && dimension != 3) { | |
190 av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); | |
191 return -1; | |
192 } | |
193 | |
194 if (s->depth == SGI_GRAYSCALE) { | |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
195 avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_GRAY16BE : PIX_FMT_GRAY8; |
4790 | 196 } else if (s->depth == SGI_RGB) { |
10194
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
197 avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_RGB48BE : PIX_FMT_RGB24; |
5b05416fcb6b
Support uncompressed 16 bit sgi image format, as e.g. used by the files at
reimar
parents:
9355
diff
changeset
|
198 } else if (s->depth == SGI_RGBA && s->bytes_per_channel == 1) { |
4790 | 199 avctx->pix_fmt = PIX_FMT_RGBA; |
200 } else { | |
201 av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); | |
202 return -1; | |
203 } | |
204 | |
12372
914f484bb476
Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents:
11560
diff
changeset
|
205 if (av_check_image_size(s->width, s->height, 0, avctx)) |
4790 | 206 return -1; |
207 avcodec_set_dimensions(avctx, s->width, s->height); | |
208 | |
209 if (p->data[0]) | |
210 avctx->release_buffer(avctx, p); | |
211 | |
212 p->reference = 0; | |
213 if (avctx->get_buffer(avctx, p) < 0) { | |
214 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); | |
215 return -1; | |
216 } | |
217 | |
218 p->pict_type = FF_I_TYPE; | |
219 p->key_frame = 1; | |
220 out_buf = p->data[0]; | |
221 | |
222 out_end = out_buf + p->linesize[0] * s->height; | |
223 | |
224 s->linesize = p->linesize[0]; | |
225 | |
226 /* Skip header. */ | |
227 in_buf += SGI_HEADER_SIZE - 12; | |
228 if (rle) { | |
229 ret = read_rle_sgi(out_end, in_buf, in_end, s); | |
230 } else { | |
231 ret = read_uncompressed_sgi(out_buf, out_end, in_buf, in_end, s); | |
232 } | |
233 | |
234 if (ret == 0) { | |
235 *picture = s->picture; | |
236 *data_size = sizeof(AVPicture); | |
237 return buf_size; | |
238 } else { | |
239 return -1; | |
240 } | |
241 } | |
242 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
243 static av_cold int sgi_init(AVCodecContext *avctx){ |
4790 | 244 SgiState *s = avctx->priv_data; |
245 | |
246 avcodec_get_frame_defaults(&s->picture); | |
247 avctx->coded_frame = &s->picture; | |
248 | |
249 return 0; | |
250 } | |
251 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
252 static av_cold int sgi_end(AVCodecContext *avctx) |
4790 | 253 { |
254 SgiState * const s = avctx->priv_data; | |
255 | |
256 if (s->picture.data[0]) | |
257 avctx->release_buffer(avctx, &s->picture); | |
258 | |
259 return 0; | |
260 } | |
261 | |
262 AVCodec sgi_decoder = { | |
263 "sgi", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10194
diff
changeset
|
264 AVMEDIA_TYPE_VIDEO, |
4790 | 265 CODEC_ID_SGI, |
266 sizeof(SgiState), | |
267 sgi_init, | |
268 NULL, | |
269 sgi_end, | |
270 decode_frame, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6722
diff
changeset
|
271 .long_name = NULL_IF_CONFIG_SMALL("SGI image"), |
4790 | 272 }; |
273 |