Mercurial > libavcodec.hg
annotate dxa.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Fri, 20 Feb 2009 16:20:01 +0000 |
parents | e9d9d946f213 |
children | 54bc8a2727b0 |
rev | line source |
---|---|
4671 | 1 /* |
2 * Feeble Files/ScummVM DXA decoder | |
3 * Copyright (c) 2007 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 */ | |
21 | |
22 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8573
diff
changeset
|
23 * @file libavcodec/dxa.c |
4671 | 24 * DXA Video decoder |
25 */ | |
26 | |
27 #include <stdio.h> | |
28 #include <stdlib.h> | |
29 | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
30 #include "libavutil/intreadwrite.h" |
4671 | 31 #include "avcodec.h" |
32 | |
33 #include <zlib.h> | |
34 | |
35 /* | |
36 * Decoder context | |
37 */ | |
38 typedef struct DxaDecContext { | |
39 AVCodecContext *avctx; | |
40 AVFrame pic, prev; | |
41 | |
42 int dsize; | |
43 uint8_t *decomp_buf; | |
44 uint32_t pal[256]; | |
45 } DxaDecContext; | |
46 | |
47 static const int shift1[6] = { 0, 8, 8, 8, 4, 4 }; | |
48 static const int shift2[6] = { 0, 0, 8, 4, 0, 4 }; | |
49 | |
50 static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, uint8_t *src, uint8_t *ref) | |
51 { | |
52 uint8_t *code, *data, *mv, *msk, *tmp, *tmp2; | |
53 int i, j, k; | |
54 int type, x, y, d, d2; | |
55 int stride = c->pic.linesize[0]; | |
56 uint32_t mask; | |
57 | |
58 code = src + 12; | |
59 data = code + ((avctx->width * avctx->height) >> 4); | |
60 mv = data + AV_RB32(src + 0); | |
61 msk = mv + AV_RB32(src + 4); | |
62 | |
63 for(j = 0; j < avctx->height; j += 4){ | |
64 for(i = 0; i < avctx->width; i += 4){ | |
65 tmp = dst + i; | |
66 tmp2 = ref + i; | |
67 type = *code++; | |
68 switch(type){ | |
69 case 4: // motion compensation | |
70 x = (*mv) >> 4; if(x & 8) x = 8 - x; | |
71 y = (*mv++) & 0xF; if(y & 8) y = 8 - y; | |
72 tmp2 += x + y*stride; | |
73 case 0: // skip | |
74 case 5: // skip in method 12 | |
75 for(y = 0; y < 4; y++){ | |
76 memcpy(tmp, tmp2, 4); | |
77 tmp += stride; | |
78 tmp2 += stride; | |
79 } | |
80 break; | |
81 case 1: // masked change | |
82 case 10: // masked change with only half of pixels changed | |
83 case 11: // cases 10-15 are for method 12 only | |
84 case 12: | |
85 case 13: | |
86 case 14: | |
87 case 15: | |
88 if(type == 1){ | |
89 mask = AV_RB16(msk); | |
90 msk += 2; | |
91 }else{ | |
92 type -= 10; | |
93 mask = ((msk[0] & 0xF0) << shift1[type]) | ((msk[0] & 0xF) << shift2[type]); | |
94 msk++; | |
95 } | |
96 for(y = 0; y < 4; y++){ | |
97 for(x = 0; x < 4; x++){ | |
98 tmp[x] = (mask & 0x8000) ? *data++ : tmp2[x]; | |
99 mask <<= 1; | |
100 } | |
101 tmp += stride; | |
102 tmp2 += stride; | |
103 } | |
104 break; | |
105 case 2: // fill block | |
106 for(y = 0; y < 4; y++){ | |
107 memset(tmp, data[0], 4); | |
108 tmp += stride; | |
109 } | |
110 data++; | |
111 break; | |
112 case 3: // raw block | |
113 for(y = 0; y < 4; y++){ | |
114 memcpy(tmp, data, 4); | |
115 data += 4; | |
116 tmp += stride; | |
117 } | |
118 break; | |
119 case 8: // subblocks - method 13 only | |
120 mask = *msk++; | |
121 for(k = 0; k < 4; k++){ | |
122 d = ((k & 1) << 1) + ((k & 2) * stride); | |
123 d2 = ((k & 1) << 1) + ((k & 2) * stride); | |
124 tmp2 = ref + i + d2; | |
125 switch(mask & 0xC0){ | |
126 case 0x80: // motion compensation | |
127 x = (*mv) >> 4; if(x & 8) x = 8 - x; | |
128 y = (*mv++) & 0xF; if(y & 8) y = 8 - y; | |
129 tmp2 += x + y*stride; | |
130 case 0x00: // skip | |
131 tmp[d + 0 ] = tmp2[0]; | |
132 tmp[d + 1 ] = tmp2[1]; | |
133 tmp[d + 0 + stride] = tmp2[0 + stride]; | |
134 tmp[d + 1 + stride] = tmp2[1 + stride]; | |
135 break; | |
136 case 0x40: // fill | |
137 tmp[d + 0 ] = data[0]; | |
138 tmp[d + 1 ] = data[0]; | |
139 tmp[d + 0 + stride] = data[0]; | |
140 tmp[d + 1 + stride] = data[0]; | |
141 data++; | |
142 break; | |
143 case 0xC0: // raw | |
144 tmp[d + 0 ] = *data++; | |
145 tmp[d + 1 ] = *data++; | |
146 tmp[d + 0 + stride] = *data++; | |
147 tmp[d + 1 + stride] = *data++; | |
148 break; | |
149 } | |
150 mask <<= 2; | |
151 } | |
152 break; | |
153 case 32: // vector quantization - 2 colors | |
154 mask = AV_RB16(msk); | |
155 msk += 2; | |
156 for(y = 0; y < 4; y++){ | |
157 for(x = 0; x < 4; x++){ | |
158 tmp[x] = data[mask & 1]; | |
159 mask >>= 1; | |
160 } | |
161 tmp += stride; | |
162 tmp2 += stride; | |
163 } | |
164 data += 2; | |
165 break; | |
166 case 33: // vector quantization - 3 or 4 colors | |
167 case 34: | |
168 mask = AV_RB32(msk); | |
169 msk += 4; | |
170 for(y = 0; y < 4; y++){ | |
171 for(x = 0; x < 4; x++){ | |
172 tmp[x] = data[mask & 3]; | |
173 mask >>= 2; | |
174 } | |
175 tmp += stride; | |
176 tmp2 += stride; | |
177 } | |
178 data += type - 30; | |
179 break; | |
180 default: | |
181 av_log(avctx, AV_LOG_ERROR, "Unknown opcode %d\n", type); | |
182 return -1; | |
183 } | |
184 } | |
185 dst += stride * 4; | |
186 ref += stride * 4; | |
187 } | |
188 return 0; | |
189 } | |
190 | |
6267 | 191 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) |
4671 | 192 { |
4827 | 193 DxaDecContext * const c = avctx->priv_data; |
4671 | 194 uint8_t *outptr, *srcptr, *tmpptr; |
195 unsigned long dsize; | |
196 int i, j, compr; | |
197 int stride; | |
198 int orig_buf_size = buf_size; | |
199 int pc = 0; | |
200 | |
201 /* make the palette available on the way out */ | |
202 if(buf[0]=='C' && buf[1]=='M' && buf[2]=='A' && buf[3]=='P'){ | |
203 int r, g, b; | |
204 | |
205 buf += 4; | |
206 for(i = 0; i < 256; i++){ | |
207 r = *buf++; | |
208 g = *buf++; | |
209 b = *buf++; | |
210 c->pal[i] = (r << 16) | (g << 8) | b; | |
211 } | |
212 pc = 1; | |
213 buf_size -= 768+4; | |
214 } | |
215 | |
216 if(avctx->get_buffer(avctx, &c->pic) < 0){ | |
217 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
218 return -1; | |
219 } | |
220 memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE); | |
221 c->pic.palette_has_changed = pc; | |
222 | |
223 outptr = c->pic.data[0]; | |
224 srcptr = c->decomp_buf; | |
225 tmpptr = c->prev.data[0]; | |
226 stride = c->pic.linesize[0]; | |
227 | |
228 if(buf[0]=='N' && buf[1]=='U' && buf[2]=='L' && buf[3]=='L') | |
229 compr = -1; | |
230 else | |
231 compr = buf[4]; | |
232 | |
233 dsize = c->dsize; | |
234 if((compr != 4 && compr != -1) && uncompress(c->decomp_buf, &dsize, buf + 9, buf_size - 9) != Z_OK){ | |
235 av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n"); | |
236 return -1; | |
237 } | |
238 switch(compr){ | |
239 case -1: | |
240 c->pic.key_frame = 0; | |
241 c->pic.pict_type = FF_P_TYPE; | |
242 if(c->prev.data[0]) | |
243 memcpy(c->pic.data[0], c->prev.data[0], c->pic.linesize[0] * avctx->height); | |
244 else{ // Should happen only when first frame is 'NULL' | |
245 memset(c->pic.data[0], 0, c->pic.linesize[0] * avctx->height); | |
246 c->pic.key_frame = 1; | |
247 c->pic.pict_type = FF_I_TYPE; | |
248 } | |
249 break; | |
250 case 2: | |
251 case 3: | |
252 case 4: | |
253 case 5: | |
254 c->pic.key_frame = !(compr & 1); | |
255 c->pic.pict_type = (compr & 1) ? FF_P_TYPE : FF_I_TYPE; | |
256 for(j = 0; j < avctx->height; j++){ | |
257 if(compr & 1){ | |
258 for(i = 0; i < avctx->width; i++) | |
259 outptr[i] = srcptr[i] ^ tmpptr[i]; | |
260 tmpptr += stride; | |
261 }else | |
262 memcpy(outptr, srcptr, avctx->width); | |
263 outptr += stride; | |
264 srcptr += avctx->width; | |
265 } | |
266 break; | |
267 case 12: // ScummVM coding | |
268 case 13: | |
269 c->pic.key_frame = 0; | |
270 c->pic.pict_type = FF_P_TYPE; | |
271 decode_13(avctx, c, c->pic.data[0], srcptr, c->prev.data[0]); | |
272 break; | |
273 default: | |
274 av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", buf[4]); | |
275 return -1; | |
276 } | |
277 | |
278 FFSWAP(AVFrame, c->pic, c->prev); | |
279 if(c->pic.data[0]) | |
280 avctx->release_buffer(avctx, &c->pic); | |
281 | |
282 *data_size = sizeof(AVFrame); | |
283 *(AVFrame*)data = c->prev; | |
284 | |
285 /* always report that the buffer was completely consumed */ | |
286 return orig_buf_size; | |
287 } | |
288 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6267
diff
changeset
|
289 static av_cold int decode_init(AVCodecContext *avctx) |
4671 | 290 { |
4827 | 291 DxaDecContext * const c = avctx->priv_data; |
4671 | 292 |
293 c->avctx = avctx; | |
294 avctx->pix_fmt = PIX_FMT_PAL8; | |
295 | |
296 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { | |
297 return -1; | |
298 } | |
299 | |
300 c->dsize = avctx->width * avctx->height * 2; | |
301 if((c->decomp_buf = av_malloc(c->dsize)) == NULL) { | |
302 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); | |
303 return -1; | |
304 } | |
305 | |
306 return 0; | |
307 } | |
308 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6267
diff
changeset
|
309 static av_cold int decode_end(AVCodecContext *avctx) |
4671 | 310 { |
4827 | 311 DxaDecContext * const c = avctx->priv_data; |
4671 | 312 |
313 av_freep(&c->decomp_buf); | |
314 if(c->prev.data[0]) | |
315 avctx->release_buffer(avctx, &c->prev); | |
316 if(c->pic.data[0]) | |
317 avctx->release_buffer(avctx, &c->pic); | |
318 | |
319 return 0; | |
320 } | |
321 | |
322 AVCodec dxa_decoder = { | |
323 "dxa", | |
324 CODEC_TYPE_VIDEO, | |
325 CODEC_ID_DXA, | |
326 sizeof(DxaDecContext), | |
327 decode_init, | |
328 NULL, | |
329 decode_end, | |
6712 | 330 decode_frame, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
331 .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), |
4671 | 332 }; |
333 |