Mercurial > libavcodec.hg
annotate vmdav.c @ 4166:eced83504436 libavcodec
mp3 header (de)compression bitstream filter
this will make mp3 frames 4 bytes smaller, it will not give you binary identical mp3 files, but it will give you mp3 files which decode to binary identical output
this will only work in containers providing at least packet size, sample_rate and number of channels
bugreports about mp3 files for which this fails are welcome
and this is experimental (dont expect compatibility and dont even expect to be able to decompress what you compressed, hell dont even expect this to work without editing the source a little)
author | michael |
---|---|
date | Fri, 10 Nov 2006 01:41:53 +0000 |
parents | c8c591fe26f8 |
children | 17d005bf07f2 |
rev | line source |
---|---|
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
1 /* |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
2 * Sierra VMD Audio & Video Decoders |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
3 * Copyright (C) 2004 the ffmpeg project |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
8 * modify it under the terms of the GNU Lesser General Public |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
9 * License as published by the Free Software Foundation; either |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
15 * Lesser General Public License for more details. |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
16 * |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
17 * You should have received a copy of the GNU Lesser General Public |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3562
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
20 * |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
21 */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
22 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
23 /** |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
24 * @file vmdvideo.c |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
25 * Sierra VMD audio & video decoders |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
26 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru) |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
27 * for more information on the Sierra VMD format, visit: |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
28 * http://www.pcisys.net/~melanson/codecs/ |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
29 * |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
30 * The video decoder outputs PAL8 colorspace data. The decoder expects |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
31 * a 0x330-byte VMD file header to be transmitted via extradata during |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
32 * codec initialization. Each encoded frame that is sent to this decoder |
2967 | 33 * is expected to be prepended with the appropriate 16-byte frame |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
34 * information record from the VMD file. |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
35 * |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
36 * The audio decoder, like the video decoder, expects each encoded data |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
37 * chunk to be prepended with the appropriate 16-byte frame information |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
38 * record from the VMD file. It does not require the 0x330-byte VMD file |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
39 * header, but it does need the audio setup parameters passed in through |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
40 * normal libavcodec API means. |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
41 */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
42 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
43 #include <stdio.h> |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
44 #include <stdlib.h> |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
45 #include <string.h> |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
46 #include <unistd.h> |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
47 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
48 #include "common.h" |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
49 #include "avcodec.h" |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
50 #include "dsputil.h" |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
51 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
52 #define VMD_HEADER_SIZE 0x330 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
53 #define PALETTE_COUNT 256 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
54 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
55 /* |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
56 * Video Decoder |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
57 */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
58 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
59 typedef struct VmdVideoContext { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
60 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
61 AVCodecContext *avctx; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
62 DSPContext dsp; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
63 AVFrame frame; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
64 AVFrame prev_frame; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
65 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
66 unsigned char *buf; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
67 int size; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
68 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
69 unsigned char palette[PALETTE_COUNT * 4]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
70 unsigned char *unpack_buffer; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
71 int unpack_buffer_size; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
72 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
73 } VmdVideoContext; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
74 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
75 #define QUEUE_SIZE 0x1000 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
76 #define QUEUE_MASK 0x0FFF |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
77 |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
78 static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len) |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
79 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
80 unsigned char *s; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
81 unsigned char *d; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
82 unsigned char *d_end; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
83 unsigned char queue[QUEUE_SIZE]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
84 unsigned int qpos; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
85 unsigned int dataleft; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
86 unsigned int chainofs; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
87 unsigned int chainlen; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
88 unsigned int speclen; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
89 unsigned char tag; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
90 unsigned int i, j; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
91 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
92 s = src; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
93 d = dest; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
94 d_end = d + dest_len; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
95 dataleft = LE_32(s); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
96 s += 4; |
3562 | 97 memset(queue, 0x20, QUEUE_SIZE); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
98 if (LE_32(s) == 0x56781234) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
99 s += 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
100 qpos = 0x111; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
101 speclen = 0xF + 3; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
102 } else { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
103 qpos = 0xFEE; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
104 speclen = 100; /* no speclen */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
105 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
106 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
107 while (dataleft > 0) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
108 tag = *s++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
109 if ((tag == 0xFF) && (dataleft > 8)) { |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
110 if (d + 8 > d_end) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
111 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
112 for (i = 0; i < 8; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
113 queue[qpos++] = *d++ = *s++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
114 qpos &= QUEUE_MASK; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
115 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
116 dataleft -= 8; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
117 } else { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
118 for (i = 0; i < 8; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
119 if (dataleft == 0) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
120 break; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
121 if (tag & 0x01) { |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
122 if (d + 1 > d_end) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
123 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
124 queue[qpos++] = *d++ = *s++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
125 qpos &= QUEUE_MASK; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
126 dataleft--; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
127 } else { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
128 chainofs = *s++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
129 chainofs |= ((*s & 0xF0) << 4); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
130 chainlen = (*s++ & 0x0F) + 3; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
131 if (chainlen == speclen) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
132 chainlen = *s++ + 0xF + 3; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
133 if (d + chainlen > d_end) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
134 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
135 for (j = 0; j < chainlen; j++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
136 *d = queue[chainofs++ & QUEUE_MASK]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
137 queue[qpos++] = *d++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
138 qpos &= QUEUE_MASK; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
139 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
140 dataleft -= chainlen; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
141 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
142 tag >>= 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
143 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
144 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
145 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
146 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
147 |
2967 | 148 static int rle_unpack(unsigned char *src, unsigned char *dest, |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
149 int src_len, int dest_len) |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
150 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
151 unsigned char *ps; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
152 unsigned char *pd; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
153 int i, l; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
154 unsigned char *dest_end = dest + dest_len; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
155 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
156 ps = src; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
157 pd = dest; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
158 if (src_len & 1) |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
159 *pd++ = *ps++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
160 |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
161 src_len >>= 1; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
162 i = 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
163 do { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
164 l = *ps++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
165 if (l & 0x80) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
166 l = (l & 0x7F) * 2; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
167 if (pd + l > dest_end) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
168 return (ps - src); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
169 memcpy(pd, ps, l); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
170 ps += l; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
171 pd += l; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
172 } else { |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
173 if (pd + i > dest_end) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
174 return (ps - src); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
175 for (i = 0; i < l; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
176 *pd++ = ps[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
177 *pd++ = ps[1]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
178 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
179 ps += 2; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
180 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
181 i += l; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
182 } while (i < src_len); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
183 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
184 return (ps - src); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
185 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
186 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
187 static void vmd_decode(VmdVideoContext *s) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
188 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
189 int i; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
190 unsigned int *palette32; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
191 unsigned char r, g, b; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
192 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
193 /* point to the start of the encoded data */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
194 unsigned char *p = s->buf + 16; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
195 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
196 unsigned char *pb; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
197 unsigned char meth; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
198 unsigned char *dp; /* pointer to current frame */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
199 unsigned char *pp; /* pointer to previous frame */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
200 unsigned char len; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
201 int ofs; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
202 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
203 int frame_x, frame_y; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
204 int frame_width, frame_height; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
205 int dp_size; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
206 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
207 frame_x = LE_16(&s->buf[6]); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
208 frame_y = LE_16(&s->buf[8]); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
209 frame_width = LE_16(&s->buf[10]) - frame_x + 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
210 frame_height = LE_16(&s->buf[12]) - frame_y + 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
211 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
212 /* if only a certain region will be updated, copy the entire previous |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
213 * frame before the decode */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
214 if (frame_x || frame_y || (frame_width != s->avctx->width) || |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
215 (frame_height != s->avctx->height)) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
216 |
2967 | 217 memcpy(s->frame.data[0], s->prev_frame.data[0], |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
218 s->avctx->height * s->frame.linesize[0]); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
219 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
220 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
221 /* check if there is a new palette */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
222 if (s->buf[15] & 0x02) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
223 p += 2; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
224 palette32 = (unsigned int *)s->palette; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
225 for (i = 0; i < PALETTE_COUNT; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
226 r = *p++ * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
227 g = *p++ * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
228 b = *p++ * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
229 palette32[i] = (r << 16) | (g << 8) | (b); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
230 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
231 s->size -= (256 * 3 + 2); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
232 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
233 if (s->size >= 0) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
234 /* originally UnpackFrame in VAG's code */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
235 pb = p; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
236 meth = *pb++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
237 if (meth & 0x80) { |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
238 lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
239 meth &= 0x7F; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
240 pb = s->unpack_buffer; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
241 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
242 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
243 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x]; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
244 dp_size = s->frame.linesize[0] * s->avctx->height; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
245 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
246 switch (meth) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
247 case 1: |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
248 for (i = 0; i < frame_height; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
249 ofs = 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
250 do { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
251 len = *pb++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
252 if (len & 0x80) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
253 len = (len & 0x7F) + 1; |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
254 if (ofs + len > frame_width) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
255 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
256 memcpy(&dp[ofs], pb, len); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
257 pb += len; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
258 ofs += len; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
259 } else { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
260 /* interframe pixel copy */ |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
261 if (ofs + len + 1 > frame_width) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
262 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
263 memcpy(&dp[ofs], &pp[ofs], len + 1); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
264 ofs += len + 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
265 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
266 } while (ofs < frame_width); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
267 if (ofs > frame_width) { |
1927 | 268 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n", |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
269 ofs, frame_width); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
270 break; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
271 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
272 dp += s->frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
273 pp += s->prev_frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
274 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
275 break; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
276 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
277 case 2: |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
278 for (i = 0; i < frame_height; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
279 memcpy(dp, pb, frame_width); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
280 pb += frame_width; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
281 dp += s->frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
282 pp += s->prev_frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
283 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
284 break; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
285 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
286 case 3: |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
287 for (i = 0; i < frame_height; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
288 ofs = 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
289 do { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
290 len = *pb++; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
291 if (len & 0x80) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
292 len = (len & 0x7F) + 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
293 if (*pb++ == 0xFF) |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
294 len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
295 else |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
296 memcpy(&dp[ofs], pb, len); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
297 pb += len; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
298 ofs += len; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
299 } else { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
300 /* interframe pixel copy */ |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
301 if (ofs + len + 1 > frame_width) |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
302 return; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
303 memcpy(&dp[ofs], &pp[ofs], len + 1); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
304 ofs += len + 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
305 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
306 } while (ofs < frame_width); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
307 if (ofs > frame_width) { |
1927 | 308 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n", |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
309 ofs, frame_width); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
310 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
311 dp += s->frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
312 pp += s->prev_frame.linesize[0]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
313 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
314 break; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
315 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
316 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
317 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
318 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
319 static int vmdvideo_decode_init(AVCodecContext *avctx) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
320 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
321 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
322 int i; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
323 unsigned int *palette32; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
324 int palette_index = 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
325 unsigned char r, g, b; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
326 unsigned char *vmd_header; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
327 unsigned char *raw_palette; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
328 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
329 s->avctx = avctx; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
330 avctx->pix_fmt = PIX_FMT_PAL8; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
331 avctx->has_b_frames = 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
332 dsputil_init(&s->dsp, avctx); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
333 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
334 /* make sure the VMD header made it */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
335 if (s->avctx->extradata_size != VMD_HEADER_SIZE) { |
2967 | 336 av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n", |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
337 VMD_HEADER_SIZE); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
338 return -1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
339 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
340 vmd_header = (unsigned char *)avctx->extradata; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
341 |
2829
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
342 s->unpack_buffer_size = LE_32(&vmd_header[800]); |
9ff4c2733422
tinfoil patch: be more diligent about checking array boundaries before
melanson
parents:
2274
diff
changeset
|
343 s->unpack_buffer = av_malloc(s->unpack_buffer_size); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
344 if (!s->unpack_buffer) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
345 return -1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
346 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
347 /* load up the initial palette */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
348 raw_palette = &vmd_header[28]; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
349 palette32 = (unsigned int *)s->palette; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
350 for (i = 0; i < PALETTE_COUNT; i++) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
351 r = raw_palette[palette_index++] * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
352 g = raw_palette[palette_index++] * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
353 b = raw_palette[palette_index++] * 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
354 palette32[i] = (r << 16) | (g << 8) | (b); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
355 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
356 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
357 s->frame.data[0] = s->prev_frame.data[0] = NULL; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
358 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
359 return 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
360 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
361 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
362 static int vmdvideo_decode_frame(AVCodecContext *avctx, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
363 void *data, int *data_size, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
364 uint8_t *buf, int buf_size) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
365 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
366 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
367 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
368 s->buf = buf; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
369 s->size = buf_size; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
370 |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
371 if (buf_size < 16) |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
372 return buf_size; |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
373 |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
374 s->frame.reference = 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
375 if (avctx->get_buffer(avctx, &s->frame)) { |
1927 | 376 av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n"); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
377 return -1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
378 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
379 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
380 vmd_decode(s); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
381 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
382 /* make the palette available on the way out */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
383 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
384 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
385 if (s->prev_frame.data[0]) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
386 avctx->release_buffer(avctx, &s->prev_frame); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
387 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
388 /* shuffle frames */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
389 s->prev_frame = s->frame; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
390 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
391 *data_size = sizeof(AVFrame); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
392 *(AVFrame*)data = s->frame; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
393 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
394 /* report that the buffer was completely consumed */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
395 return buf_size; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
396 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
397 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
398 static int vmdvideo_decode_end(AVCodecContext *avctx) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
399 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
400 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
401 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
402 if (s->prev_frame.data[0]) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
403 avctx->release_buffer(avctx, &s->prev_frame); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
404 av_free(s->unpack_buffer); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
405 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
406 return 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
407 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
408 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
409 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
410 /* |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
411 * Audio Decoder |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
412 */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
413 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
414 typedef struct VmdAudioContext { |
1927 | 415 AVCodecContext *avctx; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
416 int channels; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
417 int bits; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
418 int block_align; |
3191 | 419 int predictors[2]; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
420 } VmdAudioContext; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
421 |
3191 | 422 static uint16_t vmdaudio_table[128] = { |
423 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, | |
424 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120, | |
425 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, | |
426 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, | |
427 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280, | |
428 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, | |
429 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, | |
430 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, | |
431 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0, | |
432 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480, | |
433 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, | |
434 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, | |
435 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 | |
436 }; | |
437 | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
438 static int vmdaudio_decode_init(AVCodecContext *avctx) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
439 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
440 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
441 |
1927 | 442 s->avctx = avctx; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
443 s->channels = avctx->channels; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
444 s->bits = avctx->bits_per_sample; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
445 s->block_align = avctx->block_align; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
446 |
1927 | 447 av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n", |
2979 | 448 s->channels, s->bits, s->block_align, avctx->sample_rate); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
449 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
450 return 0; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
451 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
452 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
453 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, |
3191 | 454 uint8_t *buf, int stereo) |
455 { | |
456 int i; | |
457 int chan = 0; | |
458 int16_t *out = (int16_t*)data; | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
459 |
3191 | 460 for(i = 0; i < s->block_align; i++) { |
461 if(buf[i] & 0x80) | |
462 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; | |
463 else | |
464 s->predictors[chan] += vmdaudio_table[buf[i]]; | |
465 s->predictors[chan] = clip(s->predictors[chan], -32768, 32767); | |
466 out[i] = s->predictors[chan]; | |
467 chan ^= stereo; | |
468 } | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
469 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
470 |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
471 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
472 uint8_t *buf, int silence) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
473 { |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
474 int bytes_decoded = 0; |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
475 int i; |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
476 |
3191 | 477 // if (silence) |
478 // av_log(s->avctx, AV_LOG_INFO, "silent block!\n"); | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
479 if (s->channels == 2) { |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
480 |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
481 /* stereo handling */ |
3191 | 482 if (silence) { |
483 memset(data, 0, s->block_align * 2); | |
484 } else { | |
485 if (s->bits == 16) | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
486 vmdaudio_decode_audio(s, data, buf, 1); |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
487 else |
3191 | 488 /* copy the data but convert it to signed */ |
489 for (i = 0; i < s->block_align; i++) | |
490 data[i * 2 + 1] = buf[i] + 0x80; | |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
491 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
492 } else { |
3191 | 493 bytes_decoded = s->block_align * 2; |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
494 |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
495 /* mono handling */ |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
496 if (silence) { |
3191 | 497 memset(data, 0, s->block_align * 2); |
498 } else { | |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
499 if (s->bits == 16) { |
3191 | 500 vmdaudio_decode_audio(s, data, buf, 0); |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
501 } else { |
3191 | 502 /* copy the data but convert it to signed */ |
503 for (i = 0; i < s->block_align; i++) | |
504 data[i * 2 + 1] = buf[i] + 0x80; | |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
505 } |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
506 } |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
507 } |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
508 |
3191 | 509 return s->block_align * 2; |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
510 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
511 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
512 static int vmdaudio_decode_frame(AVCodecContext *avctx, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
513 void *data, int *data_size, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
514 uint8_t *buf, int buf_size) |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
515 { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
516 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
517 unsigned int sound_flags; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
518 unsigned char *output_samples = (unsigned char *)data; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
519 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
520 /* point to the start of the encoded data */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
521 unsigned char *p = buf + 16; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
522 unsigned char *p_end = buf + buf_size; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
523 |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
524 if (buf_size < 16) |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
525 return buf_size; |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
526 |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
527 if (buf[6] == 1) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
528 /* the chunk contains audio */ |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
529 *data_size = vmdaudio_loadsound(s, output_samples, p, 0); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
530 } else if (buf[6] == 2) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
531 /* the chunk contains audio and silence mixed together */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
532 sound_flags = LE_32(p); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
533 p += 4; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
534 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
535 /* do something with extrabufs here? */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
536 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
537 while (p < p_end) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
538 if (sound_flags & 0x01) |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
539 /* silence */ |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
540 *data_size += vmdaudio_loadsound(s, output_samples, p, 1); |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
541 else { |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
542 /* audio */ |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
543 *data_size += vmdaudio_loadsound(s, output_samples, p, 0); |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
544 p += s->block_align; |
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
545 } |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
546 output_samples += (s->block_align * s->bits / 8); |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
547 sound_flags >>= 1; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
548 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
549 } else if (buf[6] == 3) { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
550 /* silent chunk */ |
1882
5456ab242388
minor VMD system update; still not perfect, but should not crash either
melanson
parents:
1823
diff
changeset
|
551 *data_size = vmdaudio_loadsound(s, output_samples, p, 1); |
1717
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
552 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
553 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
554 return buf_size; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
555 } |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
556 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
557 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
558 /* |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
559 * Public Data Structures |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
560 */ |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
561 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
562 AVCodec vmdvideo_decoder = { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
563 "vmdvideo", |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
564 CODEC_TYPE_VIDEO, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
565 CODEC_ID_VMDVIDEO, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
566 sizeof(VmdVideoContext), |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
567 vmdvideo_decode_init, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
568 NULL, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
569 vmdvideo_decode_end, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
570 vmdvideo_decode_frame, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
571 CODEC_CAP_DR1, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
572 }; |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
573 |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
574 AVCodec vmdaudio_decoder = { |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
575 "vmdaudio", |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
576 CODEC_TYPE_AUDIO, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
577 CODEC_ID_VMDAUDIO, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
578 sizeof(VmdAudioContext), |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
579 vmdaudio_decode_init, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
580 NULL, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
581 NULL, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
582 vmdaudio_decode_frame, |
6a7e68899d8a
first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff
changeset
|
583 }; |