Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 304 lines (269 sloc) 9.09 kb
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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 /**
bad5537 @DonDiego Use full internal pathname in doxygen @file directives.
DonDiego authored
23 * @file libavcodec/vb.c
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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;
46 uint32_t pal[256];
7993df6 @michaelni consts
michaelni authored
47 const uint8_t *stream;
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
61 static void vb_decode_palette(VBDecContext *c, int data_size)
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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 }
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
71 if(size*3+2 > data_size){
72 av_log(c->avctx, AV_LOG_ERROR, "Palette data runs beyond chunk size\n");
73 return;
74 }
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
89 static int vb_decode_framedata(VBDecContext *c, const uint8_t *buf, int data_size, int offset)
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
90 {
91 uint8_t *prev, *cur;
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
92 const uint8_t* data_end = buf + data_size;
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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++){
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
107 if(!(blk & 3)) {
108 if(buf >= data_end){
109 av_log(c->avctx, AV_LOG_ERROR, "Data pointer out of bounds\n");
110 return -1;
111 }
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
112 blocktypes = bytestream_get_byte(&buf);
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
113 }
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
125 if(buf + 16 > data_end){
126 av_log(c->avctx, AV_LOG_ERROR, "Insufficient data\n");
127 return -1;
128 }
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
149 if(buf + 2 > data_end){
150 av_log(c->avctx, AV_LOG_ERROR, "Insufficient data\n");
151 return -1;
152 }
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
7a00bba Implement avcodec_decode_video2(), _audio3() and _subtitle2() which take...
Thilo Borgmann authored
194 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
195 {
7a00bba Implement avcodec_decode_video2(), _audio3() and _subtitle2() which take...
Thilo Borgmann authored
196 const uint8_t *buf = avpkt->data;
197 int buf_size = avpkt->size;
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
10ae4bb Get new buffer during frame decoding in VB video decoder, not only once
Kostya Shishkov authored
206 if(c->pic.data[0])
207 avctx->release_buffer(avctx, &c->pic);
208 c->pic.reference = 1;
209 if(avctx->get_buffer(avctx, &c->pic) < 0){
210 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
211 return -1;
212 }
213
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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 }
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
230 vb_decode_framedata(c, c->stream, size, offset);
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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 }
57835fc Check for chunk boundaries when decoding VB codec data
Kostya Shishkov authored
240 vb_decode_palette(c, size);
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
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
98a6fff @zuxy Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy authored
265 static av_cold int decode_init(AVCodecContext *avctx)
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
266 {
267 VBDecContext * const c = avctx->priv_data;
268
269 c->avctx = avctx;
270 avctx->pix_fmt = PIX_FMT_PAL8;
271
272 c->frame = av_malloc( avctx->width * avctx->height);
273 c->prev_frame = av_malloc( avctx->width * avctx->height);
274
2727649 Zero palette in case not all entries are initialized later
Kostya Shishkov authored
275 memset(c->pal, 0, sizeof(c->pal));
276
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
277 return 0;
278 }
279
98a6fff @zuxy Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy authored
280 static av_cold int decode_end(AVCodecContext *avctx)
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
281 {
282 VBDecContext *c = avctx->priv_data;
283
284 av_freep(&c->frame);
285 av_freep(&c->prev_frame);
286 if(c->pic.data[0])
287 avctx->release_buffer(avctx, &c->pic);
288
289 return 0;
290 }
291
292 AVCodec vb_decoder = {
293 "vb",
294 CODEC_TYPE_VIDEO,
295 CODEC_ID_VB,
296 sizeof(VBDecContext),
297 decode_init,
298 NULL,
299 decode_end,
d5202e4 Add long names to many AVCodec declarations.
Stefano Sabatini authored
300 decode_frame,
fe4bf37 Make AVCodec long_names definition conditional depending on CONFIG_SMALL...
Stefano Sabatini authored
301 .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"),
66f7679 Beam Software SIFF demuxer and video decoder
Kostya Shishkov authored
302 };
303
Something went wrong with that request. Please try again.