1 /*
2 * Sierra VMD video decoder
3 * Copyright (c) 2004 The FFmpeg Project
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 /**
23 * @file
24 * Sierra VMD video decoder
25 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
26 * for more information on the Sierra VMD format, visit:
27 * http://www.pcisys.net/~melanson/codecs/
28 *
29 * The video decoder outputs PAL8 colorspace data. The decoder expects
30 * a 0x330-byte VMD file header to be transmitted via extradata during
31 * codec initialization. Each encoded frame that is sent to this decoder
32 * is expected to be prepended with the appropriate 16-byte frame
33 * information record from the VMD file.
34 */
35
36 #include <string.h>
37
40
44
45 #define VMD_HEADER_SIZE 0x330
46 #define PALETTE_COUNT 256
47
49
52
53 const unsigned char *
buf;
55
59
62
63 #define QUEUE_SIZE 0x1000
64 #define QUEUE_MASK 0x0FFF
65
67 unsigned char *dest, int dest_len)
68 {
69 unsigned char *d;
70 unsigned char *d_end;
72 unsigned int qpos;
73 unsigned int dataleft;
74 unsigned int chainofs;
75 unsigned int chainlen;
76 unsigned int speclen;
78 unsigned int i, j;
80
82 d = dest;
83 d_end = d + dest_len;
84 dataleft = bytestream2_get_le32(&gb);
88 if (bytestream2_peek_le32(&gb) == 0x56781234) {
90 qpos = 0x111;
91 speclen = 0xF + 3;
92 } else {
93 qpos = 0xFEE;
94 speclen = 100; /* no speclen */
95 }
96
98 tag = bytestream2_get_byteu(&gb);
99 if ((tag == 0xFF) && (dataleft > 8)) {
102 for (i = 0; i < 8; i++) {
103 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
105 }
106 dataleft -= 8;
107 } else {
108 for (i = 0; i < 8; i++) {
109 if (dataleft == 0)
110 break;
111 if (tag & 0x01) {
114 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
116 dataleft--;
117 } else {
118 chainofs = bytestream2_get_byte(&gb);
119 chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4);
120 chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3;
121 if (chainlen == speclen) {
122 chainlen = bytestream2_get_byte(&gb) + 0xF + 3;
123 }
124 if (d_end - d < chainlen)
126 for (j = 0; j < chainlen; j++) {
128 queue[qpos++] = *d++;
130 }
131 dataleft -= chainlen;
132 }
133 tag >>= 1;
134 }
135 }
136 }
137 return d - dest;
138 }
140 int src_count, int src_size, int dest_len)
141 {
142 unsigned char *pd;
143 int i, l, used = 0;
144 unsigned char *dest_end = dest + dest_len;
146 uint16_t run_val;
147
149 pd = dest;
150 if (src_count & 1) {
152 return 0;
153 *pd++ = bytestream2_get_byteu(&gb);
154 used++;
155 }
156
157 do {
159 break;
160 l = bytestream2_get_byteu(&gb);
161 if (l & 0x80) {
162 l = (l & 0x7F) * 2;
166 pd += l;
167 } else {
171 for (i = 0; i < l; i++) {
173 pd += 2;
174 }
175 l *= 2;
176 }
177 used += l;
178 } while (used < src_count);
179
181 }
182
184 {
185 int i;
186 unsigned int *palette32;
187 unsigned char r,
g,
b;
188
190
191 unsigned char meth;
192 unsigned char *dp; /* pointer to current frame */
193 unsigned char *pp; /* pointer to previous frame */
195 int ofs;
196
197 int frame_x, frame_y;
198 int frame_width, frame_height;
199
202 frame_width =
AV_RL16(&s->
buf[10]) - frame_x + 1;
203 frame_height =
AV_RL16(&s->
buf[12]) - frame_y + 1;
204
206 (frame_x || frame_y)) {
207
210 }
213
214 if (frame_x < 0 || frame_width < 0 ||
219 "Invalid horizontal range %d-%d\n",
220 frame_x, frame_width);
222 }
223 if (frame_y < 0 || frame_height < 0 ||
228 "Invalid vertical range %d-%d\n",
229 frame_x, frame_width);
231 }
232
233 /* if only a certain region will be updated, copy the entire previous
234 * frame before the decode */
236 (frame_x || frame_y || (frame_width != s->
avctx->
width) ||
238
241 }
242
243 /* check if there is a new palette */
245 if (s->
buf[15] & 0x02) {
247 palette32 = (
unsigned int *)s->
palette;
250 r = bytestream2_get_byteu(&gb) * 4;
251 g = bytestream2_get_byteu(&gb) * 4;
252 b = bytestream2_get_byteu(&gb) * 4;
253 palette32[i] = 0xFF
U << 24 | (r << 16) | (g << 8) | (
b);
254 palette32[i] |= palette32[i] >> 6 & 0x30303;
255 }
256 } else {
259 }
260 }
261
263 return 0;
264
265 /* originally UnpackFrame in VAG's code */
268 meth = bytestream2_get_byteu(&gb);
269 if (meth & 0x80) {
273 "Trying to unpack LZ-compressed frame with no LZ buffer\n");
275 }
278 if (size < 0)
280 meth &= 0x7F;
282 }
283
284 dp = &frame->
data[0][frame_y * frame->
linesize[0] + frame_x];
286 switch (meth) {
287 case 1:
288 for (i = 0; i < frame_height; i++) {
289 ofs = 0;
290 do {
291 len = bytestream2_get_byte(&gb);
292 if (len & 0x80) {
293 len = (len & 0x7F) + 1;
294 if (ofs + len > frame_width ||
299 } else {
300 /* interframe pixel copy */
303 memcpy(&dp[ofs], &pp[ofs], len + 1);
304 ofs += len + 1;
305 }
306 } while (ofs < frame_width);
307 if (ofs > frame_width) {
309 "offset > width (%d > %d)\n",
310 ofs, frame_width);
312 }
315 }
316 break;
317
318 case 2:
319 for (i = 0; i < frame_height; i++) {
323 }
324 break;
325
326 case 3:
327 for (i = 0; i < frame_height; i++) {
328 ofs = 0;
329 do {
330 len = bytestream2_get_byte(&gb);
331 if (len & 0x80) {
332 len = (len & 0x7F) + 1;
333 if (bytestream2_peek_byte(&gb) == 0xFF) {
335 bytestream2_get_byte(&gb);
338 frame_width - ofs);
339 ofs += slen;
341 } else {
342 if (ofs + len > frame_width ||
347 }
348 } else {
349 /* interframe pixel copy */
352 memcpy(&dp[ofs], &pp[ofs], len + 1);
353 ofs += len + 1;
354 }
355 } while (ofs < frame_width);
356 if (ofs > frame_width) {
358 "offset > width (%d > %d)\n",
359 ofs, frame_width);
361 }
364 }
365 break;
366 }
367 return 0;
368 }
369
371 {
373
377
378 return 0;
379 }
380
382 {
384 int i;
385 unsigned int *palette32;
386 int palette_index = 0;
387 unsigned char r,
g,
b;
388 unsigned char *vmd_header;
389 unsigned char *raw_palette;
390
393
394 /* make sure the VMD header made it */
399 }
400 vmd_header = (
unsigned char *)avctx->
extradata;
401
407 }
408
409 /* load up the initial palette */
410 raw_palette = &vmd_header[28];
411 palette32 = (
unsigned int *)s->
palette;
413 r = raw_palette[palette_index++] * 4;
414 g = raw_palette[palette_index++] * 4;
415 b = raw_palette[palette_index++] * 4;
416 palette32[i] = 0xFF
U << 24 | (r << 16) | (g << 8) | (
b);
417 palette32[i] |= palette32[i] >> 6 & 0x30303;
418 }
419
424 }
425
426 return 0;
427 }
428
430 void *
data,
int *got_frame,
432 {
434 int buf_size = avpkt->
size;
438
441
442 if (buf_size < 16)
444
447
450
451 /* make the palette available on the way out */
453
454 /* shuffle frames */
458
459 *got_frame = 1;
460
461 /* report that the buffer was completely consumed */
462 return buf_size;
463 }
464
475 };