Mercurial > libavcodec.hg
annotate targa.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | 9a577b684548 |
children | 8a4984c5cacc |
rev | line source |
---|---|
3986 | 1 /* |
2 * Targa (.tga) image decoder | |
3 * Copyright (c) 2006 Konstantin Shishkov | |
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 */ | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
21 |
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
3986 | 23 #include "avcodec.h" |
24 | |
25 enum TargaCompr{ | |
26 TGA_NODATA = 0, // no image data | |
27 TGA_PAL = 1, // palettized | |
28 TGA_RGB = 2, // true-color | |
29 TGA_BW = 3, // black & white or grayscale | |
30 TGA_RLE = 8, // flag pointing that data is RLE-coded | |
31 }; | |
32 | |
33 typedef struct TargaContext { | |
34 AVFrame picture; | |
35 | |
36 int width, height; | |
37 int bpp; | |
38 int color_type; | |
39 int compression_type; | |
40 } TargaContext; | |
41 | |
6281 | 42 static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp) |
3986 | 43 { |
44 int i, x, y; | |
45 int depth = (bpp + 1) >> 3; | |
46 int type, count; | |
47 int diff; | |
48 | |
49 diff = stride - w * depth; | |
50 x = y = 0; | |
51 while(y < h){ | |
52 type = *src++; | |
53 count = (type & 0x7F) + 1; | |
54 type &= 0x80; | |
55 if((x + count > w) && (x + count + 1 > (h - y) * w)){ | |
56 av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count); | |
57 return; | |
58 } | |
59 for(i = 0; i < count; i++){ | |
60 switch(depth){ | |
61 case 1: | |
62 *dst = *src; | |
63 break; | |
64 case 2: | |
4364 | 65 *((uint16_t*)dst) = AV_RL16(src); |
3986 | 66 break; |
67 case 3: | |
68 dst[0] = src[0]; | |
69 dst[1] = src[1]; | |
70 dst[2] = src[2]; | |
71 break; | |
4132 | 72 case 4: |
4364 | 73 *((uint32_t*)dst) = AV_RL32(src); |
4132 | 74 break; |
3986 | 75 } |
76 dst += depth; | |
77 if(!type) | |
78 src += depth; | |
79 | |
80 x++; | |
81 if(x == w){ | |
82 x = 0; | |
83 y++; | |
84 dst += diff; | |
85 } | |
86 } | |
87 if(type) | |
88 src += depth; | |
89 } | |
90 } | |
91 | |
92 static int decode_frame(AVCodecContext *avctx, | |
93 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
94 AVPacket *avpkt) |
3986 | 95 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
96 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8573
diff
changeset
|
97 int buf_size = avpkt->size; |
3986 | 98 TargaContext * const s = avctx->priv_data; |
99 AVFrame *picture = data; | |
100 AVFrame * const p= (AVFrame*)&s->picture; | |
101 uint8_t *dst; | |
102 int stride; | |
103 int idlen, pal, compr, x, y, w, h, bpp, flags; | |
104 int first_clr, colors, csize; | |
105 | |
106 /* parse image header */ | |
107 idlen = *buf++; | |
108 pal = *buf++; | |
109 compr = *buf++; | |
4364 | 110 first_clr = AV_RL16(buf); buf += 2; |
111 colors = AV_RL16(buf); buf += 2; | |
3986 | 112 csize = *buf++; |
4364 | 113 x = AV_RL16(buf); buf += 2; |
114 y = AV_RL16(buf); buf += 2; | |
115 w = AV_RL16(buf); buf += 2; | |
116 h = AV_RL16(buf); buf += 2; | |
3986 | 117 bpp = *buf++; |
118 flags = *buf++; | |
119 //skip identifier if any | |
120 buf += idlen; | |
121 s->bpp = bpp; | |
122 s->width = w; | |
123 s->height = h; | |
124 switch(s->bpp){ | |
125 case 8: | |
126 avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8; | |
127 break; | |
128 case 15: | |
129 avctx->pix_fmt = PIX_FMT_RGB555; | |
130 break; | |
131 case 16: | |
132 avctx->pix_fmt = PIX_FMT_RGB555; | |
133 break; | |
134 case 24: | |
135 avctx->pix_fmt = PIX_FMT_BGR24; | |
136 break; | |
4132 | 137 case 32: |
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4364
diff
changeset
|
138 avctx->pix_fmt = PIX_FMT_RGB32; |
4132 | 139 break; |
3986 | 140 default: |
4128 | 141 av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", s->bpp); |
3986 | 142 return -1; |
143 } | |
144 | |
145 if(s->picture.data[0]) | |
146 avctx->release_buffer(avctx, &s->picture); | |
147 | |
148 if(avcodec_check_dimensions(avctx, w, h)) | |
149 return -1; | |
150 if(w != avctx->width || h != avctx->height) | |
151 avcodec_set_dimensions(avctx, w, h); | |
152 if(avctx->get_buffer(avctx, p) < 0){ | |
153 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
154 return -1; | |
155 } | |
156 if(flags & 0x20){ | |
157 dst = p->data[0]; | |
158 stride = p->linesize[0]; | |
159 }else{ //image is upside-down | |
160 dst = p->data[0] + p->linesize[0] * (h - 1); | |
161 stride = -p->linesize[0]; | |
162 } | |
163 | |
164 if(avctx->pix_fmt == PIX_FMT_PAL8 && avctx->palctrl){ | |
165 memcpy(p->data[1], avctx->palctrl->palette, AVPALETTE_SIZE); | |
166 if(avctx->palctrl->palette_changed){ | |
167 p->palette_has_changed = 1; | |
168 avctx->palctrl->palette_changed = 0; | |
169 } | |
170 } | |
171 if(colors){ | |
172 if((colors + first_clr) > 256){ | |
173 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr); | |
174 return -1; | |
175 } | |
176 if(csize != 24){ | |
177 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize); | |
178 return -1; | |
179 } | |
180 if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway | |
181 buf += colors * ((csize + 1) >> 3); | |
182 else{ | |
183 int r, g, b, t; | |
184 int32_t *pal = ((int32_t*)p->data[1]) + first_clr; | |
185 for(t = 0; t < colors; t++){ | |
186 r = *buf++; | |
187 g = *buf++; | |
188 b = *buf++; | |
189 *pal++ = (b << 16) | (g << 8) | r; | |
190 } | |
191 p->palette_has_changed = 1; | |
192 } | |
193 } | |
194 if((compr & (~TGA_RLE)) == TGA_NODATA) | |
195 memset(p->data[0], 0, p->linesize[0] * s->height); | |
196 else{ | |
197 if(compr & TGA_RLE) | |
198 targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp); | |
199 else{ | |
200 for(y = 0; y < s->height; y++){ | |
9985 | 201 #if HAVE_BIGENDIAN |
3986 | 202 if((s->bpp + 1) >> 3 == 2){ |
203 uint16_t *dst16 = (uint16_t*)dst; | |
204 for(x = 0; x < s->width; x++) | |
4364 | 205 dst16[x] = AV_RL16(buf + x * 2); |
4132 | 206 }else if((s->bpp + 1) >> 3 == 4){ |
207 uint32_t *dst32 = (uint32_t*)dst; | |
208 for(x = 0; x < s->width; x++) | |
4364 | 209 dst32[x] = AV_RL32(buf + x * 4); |
3986 | 210 }else |
211 #endif | |
212 memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3)); | |
213 | |
214 dst += stride; | |
215 buf += s->width * ((s->bpp + 1) >> 3); | |
216 } | |
217 } | |
218 } | |
219 | |
220 *picture= *(AVFrame*)&s->picture; | |
221 *data_size = sizeof(AVPicture); | |
222 | |
223 return buf_size; | |
224 } | |
225 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6281
diff
changeset
|
226 static av_cold int targa_init(AVCodecContext *avctx){ |
3986 | 227 TargaContext *s = avctx->priv_data; |
228 | |
229 avcodec_get_frame_defaults((AVFrame*)&s->picture); | |
230 avctx->coded_frame= (AVFrame*)&s->picture; | |
231 | |
232 return 0; | |
233 } | |
234 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6281
diff
changeset
|
235 static av_cold int targa_end(AVCodecContext *avctx){ |
3986 | 236 TargaContext *s = avctx->priv_data; |
237 | |
238 if(s->picture.data[0]) | |
239 avctx->release_buffer(avctx, &s->picture); | |
240 | |
241 return 0; | |
242 } | |
243 | |
244 AVCodec targa_decoder = { | |
245 "targa", | |
246 CODEC_TYPE_VIDEO, | |
247 CODEC_ID_TARGA, | |
248 sizeof(TargaContext), | |
249 targa_init, | |
250 NULL, | |
251 targa_end, | |
252 decode_frame, | |
9810
8f56bd47d2c8
targa image decoder uses get_buffer, set CODEC_CAP_DR1
bcoudurier
parents:
9553
diff
changeset
|
253 CODEC_CAP_DR1, |
6722 | 254 NULL, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6722
diff
changeset
|
255 .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), |
3986 | 256 }; |