Mercurial > libavcodec.hg
annotate vb.c @ 11557:53822d92c3f7 libavcodec
Make sure the EC code does not attempt to use inter based concealment if there
is no reference frame available. (this can happen because the EC code will attempt
to use reference frames even for I/IDR frames)
author | michael |
---|---|
date | Tue, 30 Mar 2010 20:46:46 +0000 |
parents | 3dd1cb77cc60 |
children | 8a4984c5cacc |
rev | line source |
---|---|
5847 | 1 /* |
2 * Beam Software VB 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:
7040
diff
changeset
|
23 * @file libavcodec/vb.c |
5847 | 24 * VB Video decoder |
25 */ | |
26 | |
27 #include <stdio.h> | |
28 #include <stdlib.h> | |
29 | |
30 #include "avcodec.h" | |
31 #include "bytestream.h" | |
32 | |
33 enum VBFlags{ | |
34 VB_HAS_GMC = 0x01, | |
35 VB_HAS_AUDIO = 0x04, | |
36 VB_HAS_VIDEO = 0x08, | |
37 VB_HAS_PALETTE = 0x10, | |
38 VB_HAS_LENGTH = 0x20 | |
39 }; | |
40 | |
41 typedef struct VBDecContext { | |
42 AVCodecContext *avctx; | |
43 AVFrame pic; | |
44 | |
45 uint8_t *frame, *prev_frame; | |
10972 | 46 uint32_t pal[AVPALETTE_COUNT]; |
6218 | 47 const uint8_t *stream; |
5847 | 48 } VBDecContext; |
49 | |
50 static const uint16_t vb_patterns[64] = { | |
51 0x0660, 0xFF00, 0xCCCC, 0xF000, 0x8888, 0x000F, 0x1111, 0xFEC8, | |
52 0x8CEF, 0x137F, 0xF731, 0xC800, 0x008C, 0x0013, 0x3100, 0xCC00, | |
53 0x00CC, 0x0033, 0x3300, 0x0FF0, 0x6666, 0x00F0, 0x0F00, 0x2222, | |
54 0x4444, 0xF600, 0x8CC8, 0x006F, 0x1331, 0x318C, 0xC813, 0x33CC, | |
55 0x6600, 0x0CC0, 0x0066, 0x0330, 0xF900, 0xC88C, 0x009F, 0x3113, | |
56 0x6000, 0x0880, 0x0006, 0x0110, 0xCC88, 0xFC00, 0x00CF, 0x88CC, | |
57 0x003F, 0x1133, 0x3311, 0xF300, 0x6FF6, 0x0603, 0x08C6, 0x8C63, | |
58 0xC631, 0x6310, 0xC060, 0x0136, 0x136C, 0x36C8, 0x6C80, 0x324C | |
59 }; | |
60 | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
61 static void vb_decode_palette(VBDecContext *c, int data_size) |
5847 | 62 { |
63 int start, size, i; | |
64 | |
65 start = bytestream_get_byte(&c->stream); | |
66 size = (bytestream_get_byte(&c->stream) - 1) & 0xFF; | |
67 if(start + size > 255){ | |
68 av_log(c->avctx, AV_LOG_ERROR, "Palette change runs beyond entry 256\n"); | |
69 return; | |
70 } | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
71 if(size*3+2 > data_size){ |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
72 av_log(c->avctx, AV_LOG_ERROR, "Palette data runs beyond chunk size\n"); |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
73 return; |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
74 } |
5847 | 75 for(i = start; i <= start + size; i++) |
76 c->pal[i] = bytestream_get_be24(&c->stream); | |
77 } | |
78 | |
79 static inline int check_pixel(uint8_t *buf, uint8_t *start, uint8_t *end) | |
80 { | |
81 return buf >= start && buf < end; | |
82 } | |
83 | |
84 static inline int check_line(uint8_t *buf, uint8_t *start, uint8_t *end) | |
85 { | |
86 return buf >= start && (buf + 4) <= end; | |
87 } | |
88 | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
89 static int vb_decode_framedata(VBDecContext *c, const uint8_t *buf, int data_size, int offset) |
5847 | 90 { |
91 uint8_t *prev, *cur; | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
92 const uint8_t* data_end = buf + data_size; |
5847 | 93 int blk, blocks, t, blk2; |
94 int blocktypes = 0; | |
95 int x, y, a, b; | |
96 int pattype, pattern; | |
97 const int width = c->avctx->width; | |
98 uint8_t *pstart = c->prev_frame; | |
99 uint8_t *pend = c->prev_frame + width*c->avctx->height; | |
100 | |
101 prev = c->prev_frame + offset; | |
102 cur = c->frame; | |
103 | |
104 blocks = (c->avctx->width >> 2) * (c->avctx->height >> 2); | |
105 blk2 = 0; | |
106 for(blk = 0; blk < blocks; blk++){ | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
107 if(!(blk & 3)) { |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
108 if(buf >= data_end){ |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
109 av_log(c->avctx, AV_LOG_ERROR, "Data pointer out of bounds\n"); |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
110 return -1; |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
111 } |
5847 | 112 blocktypes = bytestream_get_byte(&buf); |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
113 } |
5847 | 114 switch(blocktypes & 0xC0){ |
115 case 0x00: //skip | |
116 for(y = 0; y < 4; y++) | |
117 if(check_line(prev + y*width, pstart, pend)) | |
118 memcpy(cur + y*width, prev + y*width, 4); | |
119 else | |
120 memset(cur + y*width, 0, 4); | |
121 break; | |
122 case 0x40: | |
123 t = bytestream_get_byte(&buf); | |
124 if(!t){ //raw block | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
125 if(buf + 16 > data_end){ |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
126 av_log(c->avctx, AV_LOG_ERROR, "Insufficient data\n"); |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
127 return -1; |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
128 } |
5847 | 129 for(y = 0; y < 4; y++) |
130 memcpy(cur + y*width, buf + y*4, 4); | |
131 buf += 16; | |
132 }else{ // motion compensation | |
133 x = ((t & 0xF)^8) - 8; | |
134 y = ((t >> 4) ^8) - 8; | |
135 t = x + y*width; | |
136 for(y = 0; y < 4; y++) | |
137 if(check_line(prev + t + y*width, pstart, pend)) | |
138 memcpy(cur + y*width, prev + t + y*width, 4); | |
139 else | |
140 memset(cur + y*width, 0, 4); | |
141 } | |
142 break; | |
143 case 0x80: // fill | |
144 t = bytestream_get_byte(&buf); | |
145 for(y = 0; y < 4; y++) | |
146 memset(cur + y*width, t, 4); | |
147 break; | |
148 case 0xC0: // pattern fill | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
149 if(buf + 2 > data_end){ |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
150 av_log(c->avctx, AV_LOG_ERROR, "Insufficient data\n"); |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
151 return -1; |
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
152 } |
5847 | 153 t = bytestream_get_byte(&buf); |
154 pattype = t >> 6; | |
155 pattern = vb_patterns[t & 0x3F]; | |
156 switch(pattype){ | |
157 case 0: | |
158 a = bytestream_get_byte(&buf); | |
159 b = bytestream_get_byte(&buf); | |
160 for(y = 0; y < 4; y++) | |
161 for(x = 0; x < 4; x++, pattern >>= 1) | |
162 cur[x + y*width] = (pattern & 1) ? b : a; | |
163 break; | |
164 case 1: | |
165 pattern = ~pattern; | |
166 case 2: | |
167 a = bytestream_get_byte(&buf); | |
168 for(y = 0; y < 4; y++) | |
169 for(x = 0; x < 4; x++, pattern >>= 1) | |
170 if(pattern & 1 && check_pixel(prev + x + y*width, pstart, pend)) | |
171 cur[x + y*width] = prev[x + y*width]; | |
172 else | |
173 cur[x + y*width] = a; | |
174 break; | |
175 case 3: | |
176 av_log(c->avctx, AV_LOG_ERROR, "Invalid opcode seen @%d\n",blk); | |
177 return -1; | |
178 } | |
179 break; | |
180 } | |
181 blocktypes <<= 2; | |
182 cur += 4; | |
183 prev += 4; | |
184 blk2++; | |
185 if(blk2 == (width >> 2)){ | |
186 blk2 = 0; | |
187 cur += width * 3; | |
188 prev += width * 3; | |
189 } | |
190 } | |
191 return 0; | |
192 } | |
193 | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
194 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
5847 | 195 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
196 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
197 int buf_size = avpkt->size; |
5847 | 198 VBDecContext * const c = avctx->priv_data; |
199 uint8_t *outptr, *srcptr; | |
200 int i, j; | |
201 int flags; | |
202 uint32_t size; | |
203 int rest = buf_size; | |
204 int offset = 0; | |
205 | |
9821
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
206 if(c->pic.data[0]) |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
207 avctx->release_buffer(avctx, &c->pic); |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
208 c->pic.reference = 1; |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
209 if(avctx->get_buffer(avctx, &c->pic) < 0){ |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
210 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
211 return -1; |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
212 } |
0813b30e7db9
Get new buffer during frame decoding in VB video decoder, not only once
kostya
parents:
9355
diff
changeset
|
213 |
5847 | 214 c->stream = buf; |
215 flags = bytestream_get_le16(&c->stream); | |
216 rest -= 2; | |
217 | |
218 if(flags & VB_HAS_GMC){ | |
219 i = (int16_t)bytestream_get_le16(&c->stream); | |
220 j = (int16_t)bytestream_get_le16(&c->stream); | |
221 offset = i + j * avctx->width; | |
222 rest -= 4; | |
223 } | |
224 if(flags & VB_HAS_VIDEO){ | |
225 size = bytestream_get_le32(&c->stream); | |
226 if(size > rest){ | |
227 av_log(avctx, AV_LOG_ERROR, "Frame size is too big\n"); | |
228 return -1; | |
229 } | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
230 vb_decode_framedata(c, c->stream, size, offset); |
5847 | 231 c->stream += size - 4; |
232 rest -= size; | |
233 } | |
234 if(flags & VB_HAS_PALETTE){ | |
235 size = bytestream_get_le32(&c->stream); | |
236 if(size > rest){ | |
237 av_log(avctx, AV_LOG_ERROR, "Palette size is too big\n"); | |
238 return -1; | |
239 } | |
10963
81033a080136
Check for chunk boundaries when decoding VB codec data
kostya
parents:
10962
diff
changeset
|
240 vb_decode_palette(c, size); |
5847 | 241 rest -= size; |
242 } | |
243 | |
244 memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE); | |
245 c->pic.palette_has_changed = flags & VB_HAS_PALETTE; | |
246 | |
247 outptr = c->pic.data[0]; | |
248 srcptr = c->frame; | |
249 | |
250 for(i = 0; i < avctx->height; i++){ | |
251 memcpy(outptr, srcptr, avctx->width); | |
252 srcptr += avctx->width; | |
253 outptr += c->pic.linesize[0]; | |
254 } | |
255 | |
256 FFSWAP(uint8_t*, c->frame, c->prev_frame); | |
257 | |
258 *data_size = sizeof(AVFrame); | |
259 *(AVFrame*)data = c->pic; | |
260 | |
261 /* always report that the buffer was completely consumed */ | |
262 return buf_size; | |
263 } | |
264 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
265 static av_cold int decode_init(AVCodecContext *avctx) |
5847 | 266 { |
267 VBDecContext * const c = avctx->priv_data; | |
268 | |
269 c->avctx = avctx; | |
270 avctx->pix_fmt = PIX_FMT_PAL8; | |
271 | |
10967
1c3a10f94570
Zero the frame data on allocation for VB codec, e.g. the FATE sample seems to
reimar
parents:
10963
diff
changeset
|
272 c->frame = av_mallocz(avctx->width * avctx->height); |
1c3a10f94570
Zero the frame data on allocation for VB codec, e.g. the FATE sample seems to
reimar
parents:
10963
diff
changeset
|
273 c->prev_frame = av_mallocz(avctx->width * avctx->height); |
5847 | 274 |
275 return 0; | |
276 } | |
277 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
278 static av_cold int decode_end(AVCodecContext *avctx) |
5847 | 279 { |
280 VBDecContext *c = avctx->priv_data; | |
281 | |
282 av_freep(&c->frame); | |
283 av_freep(&c->prev_frame); | |
284 if(c->pic.data[0]) | |
285 avctx->release_buffer(avctx, &c->pic); | |
286 | |
287 return 0; | |
288 } | |
289 | |
290 AVCodec vb_decoder = { | |
291 "vb", | |
292 CODEC_TYPE_VIDEO, | |
293 CODEC_ID_VB, | |
294 sizeof(VBDecContext), | |
295 decode_init, | |
296 NULL, | |
297 decode_end, | |
6710 | 298 decode_frame, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
299 .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), |
5847 | 300 }; |
301 |