annotate vmdav.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents 7dd2a45249a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 /**
11644
7dd2a45249a9 Remove explicit filename from Doxygen @file commands.
diego
parents: 11560
diff changeset
23 * @file
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
24 * Sierra VMD audio & video decoders
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
25 * 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
26 * 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
27 * 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
28 *
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
29 * 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
30 * 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
31 * codec initialization. Each encoded frame that is sent to this decoder
2967
ef2149182f1c COSMETICS: Remove all trailing whitespace.
diego
parents: 2829
diff changeset
32 * 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
33 * 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
34 *
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
35 * 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
36 * 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
37 * 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
38 * 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
39 * normal libavcodec API means.
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
40 */
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 #include <stdio.h>
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
43 #include <stdlib.h>
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
44 #include <string.h>
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
45
8573
2acf0ae7b041 Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents: 7823
diff changeset
46 #include "libavutil/intreadwrite.h"
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
47 #include "avcodec.h"
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
48
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
49 #define VMD_HEADER_SIZE 0x330
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
50 #define PALETTE_COUNT 256
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 /*
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
53 * Video Decoder
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 typedef struct VmdVideoContext {
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 AVCodecContext *avctx;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
59 AVFrame frame;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
60 AVFrame prev_frame;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
61
6291
michael
parents: 5699
diff changeset
62 const unsigned char *buf;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
63 int size;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
64
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
65 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
66 unsigned char *unpack_buffer;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
67 int unpack_buffer_size;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
68
5699
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
69 int x_off, y_off;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
70 } VmdVideoContext;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
71
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
72 #define QUEUE_SIZE 0x1000
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
73 #define QUEUE_MASK 0x0FFF
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
74
6291
michael
parents: 5699
diff changeset
75 static void lz_unpack(const 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
76 {
6291
michael
parents: 5699
diff changeset
77 const unsigned char *s;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
78 unsigned char *d;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
79 unsigned char *d_end;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
80 unsigned char queue[QUEUE_SIZE];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
81 unsigned int qpos;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
82 unsigned int dataleft;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
83 unsigned int chainofs;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
84 unsigned int chainlen;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
85 unsigned int speclen;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
86 unsigned char tag;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
87 unsigned int i, j;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
88
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
89 s = src;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
90 d = dest;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
91 d_end = d + dest_len;
4364
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
92 dataleft = AV_RL32(s);
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
93 s += 4;
3562
432ac9dce673 Correct wrong memset invocation.
diego
parents: 3191
diff changeset
94 memset(queue, 0x20, QUEUE_SIZE);
4364
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
95 if (AV_RL32(s) == 0x56781234) {
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
96 s += 4;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
97 qpos = 0x111;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
98 speclen = 0xF + 3;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
99 } else {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
100 qpos = 0xFEE;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
101 speclen = 100; /* no speclen */
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
102 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
103
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
104 while (dataleft > 0) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
105 tag = *s++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
106 if ((tag == 0xFF) && (dataleft > 8)) {
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
107 if (d + 8 > d_end)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
108 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
109 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
110 queue[qpos++] = *d++ = *s++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
111 qpos &= QUEUE_MASK;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
112 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
113 dataleft -= 8;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
114 } else {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
115 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
116 if (dataleft == 0)
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
117 break;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
118 if (tag & 0x01) {
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
119 if (d + 1 > d_end)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
120 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
121 queue[qpos++] = *d++ = *s++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
122 qpos &= QUEUE_MASK;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
123 dataleft--;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
124 } else {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
125 chainofs = *s++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
126 chainofs |= ((*s & 0xF0) << 4);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
127 chainlen = (*s++ & 0x0F) + 3;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
128 if (chainlen == speclen)
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
129 chainlen = *s++ + 0xF + 3;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
130 if (d + chainlen > d_end)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
131 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
132 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
133 *d = queue[chainofs++ & QUEUE_MASK];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
134 queue[qpos++] = *d++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
135 qpos &= QUEUE_MASK;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
136 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
137 dataleft -= chainlen;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
138 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
139 tag >>= 1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
140 }
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 }
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
6291
michael
parents: 5699
diff changeset
145 static int rle_unpack(const unsigned char *src, unsigned char *dest,
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
146 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
147 {
6291
michael
parents: 5699
diff changeset
148 const unsigned char *ps;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
149 unsigned char *pd;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
150 int i, l;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
151 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
152
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
153 ps = src;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
154 pd = dest;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
155 if (src_len & 1)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
156 *pd++ = *ps++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
157
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
158 src_len >>= 1;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
159 i = 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
160 do {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
161 l = *ps++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
162 if (l & 0x80) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
163 l = (l & 0x7F) * 2;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
164 if (pd + l > dest_end)
6750
c93570aeb3eb Remove unnecessary parentheses from return calls.
diego
parents: 6712
diff changeset
165 return ps - src;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
166 memcpy(pd, ps, l);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
167 ps += l;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
168 pd += l;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
169 } else {
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
170 if (pd + i > dest_end)
6750
c93570aeb3eb Remove unnecessary parentheses from return calls.
diego
parents: 6712
diff changeset
171 return ps - src;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
172 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
173 *pd++ = ps[0];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
174 *pd++ = ps[1];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
175 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
176 ps += 2;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
177 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
178 i += l;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
179 } while (i < src_len);
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
180
6750
c93570aeb3eb Remove unnecessary parentheses from return calls.
diego
parents: 6712
diff changeset
181 return ps - src;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
182 }
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 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
185 {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
186 int i;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
187 unsigned int *palette32;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
188 unsigned char r, g, b;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
189
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
190 /* point to the start of the encoded data */
6291
michael
parents: 5699
diff changeset
191 const unsigned char *p = s->buf + 16;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
192
6291
michael
parents: 5699
diff changeset
193 const unsigned char *pb;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
194 unsigned char meth;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
195 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
196 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
197 unsigned char len;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
198 int ofs;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
199
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
200 int frame_x, frame_y;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
201 int frame_width, frame_height;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
202 int dp_size;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
203
4364
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
204 frame_x = AV_RL16(&s->buf[6]);
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
205 frame_y = AV_RL16(&s->buf[8]);
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
206 frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
207 frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
208
5699
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
209 if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
210 (frame_x || frame_y)) {
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
211
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
212 s->x_off = frame_x;
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
213 s->y_off = frame_y;
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
214 }
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
215 frame_x -= s->x_off;
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
216 frame_y -= s->y_off;
c5c356f38cc4 Fix decoding of VMDs representing sprites (Last Dynasty, Woodruff).
kostya
parents: 5523
diff changeset
217
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
218 /* 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
219 * frame before the decode */
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
220 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
221 (frame_height != s->avctx->height)) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
222
2967
ef2149182f1c COSMETICS: Remove all trailing whitespace.
diego
parents: 2829
diff changeset
223 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
224 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
225 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
226
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
227 /* 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
228 if (s->buf[15] & 0x02) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
229 p += 2;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
230 palette32 = (unsigned int *)s->palette;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
231 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
232 r = *p++ * 4;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
233 g = *p++ * 4;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
234 b = *p++ * 4;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
235 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
236 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
237 s->size -= (256 * 3 + 2);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
238 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
239 if (s->size >= 0) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
240 /* 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
241 pb = p;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
242 meth = *pb++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
243 if (meth & 0x80) {
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
244 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
245 meth &= 0x7F;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
246 pb = s->unpack_buffer;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
247 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
248
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
249 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
250 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
251 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
252 switch (meth) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
253 case 1:
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
254 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
255 ofs = 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
256 do {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
257 len = *pb++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
258 if (len & 0x80) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
259 len = (len & 0x7F) + 1;
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
260 if (ofs + len > frame_width)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
261 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
262 memcpy(&dp[ofs], pb, len);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
263 pb += len;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
264 ofs += len;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
265 } else {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
266 /* interframe pixel copy */
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
267 if (ofs + len + 1 > frame_width)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
268 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
269 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
270 ofs += len + 1;
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 } while (ofs < frame_width);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
273 if (ofs > frame_width) {
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
274 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
275 ofs, frame_width);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
276 break;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
277 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
278 dp += s->frame.linesize[0];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
279 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
280 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
281 break;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
282
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
283 case 2:
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
284 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
285 memcpy(dp, pb, frame_width);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
286 pb += frame_width;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
287 dp += s->frame.linesize[0];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
288 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
289 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
290 break;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
291
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
292 case 3:
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
293 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
294 ofs = 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
295 do {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
296 len = *pb++;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
297 if (len & 0x80) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
298 len = (len & 0x7F) + 1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
299 if (*pb++ == 0xFF)
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
300 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
301 else
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
302 memcpy(&dp[ofs], pb, len);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
303 pb += len;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
304 ofs += len;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
305 } else {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
306 /* interframe pixel copy */
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
307 if (ofs + len + 1 > frame_width)
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
308 return;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
309 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
310 ofs += len + 1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
311 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
312 } while (ofs < frame_width);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
313 if (ofs > frame_width) {
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
314 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
315 ofs, frame_width);
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 dp += s->frame.linesize[0];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
318 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
319 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
320 break;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
321 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
322 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
323 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
324
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6484
diff changeset
325 static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
326 {
4827
b3ee9a1526b0 Get rid of unnecessary pointer casts.
diego
parents: 4801
diff changeset
327 VmdVideoContext *s = avctx->priv_data;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
328 int i;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
329 unsigned int *palette32;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
330 int palette_index = 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
331 unsigned char r, g, b;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
332 unsigned char *vmd_header;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
333 unsigned char *raw_palette;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
334
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
335 s->avctx = avctx;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
336 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
337
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
338 /* 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
339 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
2967
ef2149182f1c COSMETICS: Remove all trailing whitespace.
diego
parents: 2829
diff changeset
340 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
341 VMD_HEADER_SIZE);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
342 return -1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
343 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
344 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
345
4364
05e932ddaaa9 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 4213
diff changeset
346 s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
2829
9ff4c2733422 tinfoil patch: be more diligent about checking array boundaries before
melanson
parents: 2274
diff changeset
347 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
348 if (!s->unpack_buffer)
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
349 return -1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
350
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
351 /* load up the initial palette */
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
352 raw_palette = &vmd_header[28];
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
353 palette32 = (unsigned int *)s->palette;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
354 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
355 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
356 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
357 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
358 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
359 }
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 return 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
362 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
363
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
364 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
365 void *data, int *data_size,
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
366 AVPacket *avpkt)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
367 {
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
368 const uint8_t *buf = avpkt->data;
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
369 int buf_size = avpkt->size;
4827
b3ee9a1526b0 Get rid of unnecessary pointer casts.
diego
parents: 4801
diff changeset
370 VmdVideoContext *s = avctx->priv_data;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
371
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
372 s->buf = buf;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
373 s->size = buf_size;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
374
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
375 if (buf_size < 16)
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
376 return buf_size;
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
377
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
378 s->frame.reference = 1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
379 if (avctx->get_buffer(avctx, &s->frame)) {
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
380 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
381 return -1;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
382 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
383
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
384 vmd_decode(s);
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
385
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
386 /* 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
387 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
388
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
389 /* shuffle frames */
5081
46c9abb46638 Do proper frame swapping so VMD video decoder works again
kostya
parents: 4962
diff changeset
390 FFSWAP(AVFrame, s->frame, s->prev_frame);
46c9abb46638 Do proper frame swapping so VMD video decoder works again
kostya
parents: 4962
diff changeset
391 if (s->frame.data[0])
46c9abb46638 Do proper frame swapping so VMD video decoder works again
kostya
parents: 4962
diff changeset
392 avctx->release_buffer(avctx, &s->frame);
1717
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 *data_size = sizeof(AVFrame);
5081
46c9abb46638 Do proper frame swapping so VMD video decoder works again
kostya
parents: 4962
diff changeset
395 *(AVFrame*)data = s->prev_frame;
1717
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 /* 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
398 return buf_size;
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
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6484
diff changeset
401 static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
402 {
4827
b3ee9a1526b0 Get rid of unnecessary pointer casts.
diego
parents: 4801
diff changeset
403 VmdVideoContext *s = avctx->priv_data;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
404
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
405 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
406 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
407 av_free(s->unpack_buffer);
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 return 0;
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
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 * Audio Decoder
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
415 */
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
416
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
417 typedef struct VmdAudioContext {
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
418 AVCodecContext *avctx;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
419 int channels;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
420 int bits;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
421 int block_align;
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
422 int predictors[2];
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
423 } VmdAudioContext;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
424
7129
322023e630a6 mark read-only data as const
stefang
parents: 7040
diff changeset
425 static const uint16_t vmdaudio_table[128] = {
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
426 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
427 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
428 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
429 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
430 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
431 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
432 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
433 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
434 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
435 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
436 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
437 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
438 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
439 };
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
440
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6484
diff changeset
441 static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
442 {
4827
b3ee9a1526b0 Get rid of unnecessary pointer casts.
diego
parents: 4801
diff changeset
443 VmdAudioContext *s = avctx->priv_data;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
444
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
445 s->avctx = avctx;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
446 s->channels = avctx->channels;
7823
4525dcd81357 Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 7451
diff changeset
447 s->bits = avctx->bits_per_coded_sample;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
448 s->block_align = avctx->block_align;
7451
85ab7655ad4d Modify all codecs to report their supported input and output sample format(s).
pross
parents: 7129
diff changeset
449 avctx->sample_fmt = SAMPLE_FMT_S16;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
450
1927
d7505fbe66cb conversion to av_log
alex
parents: 1882
diff changeset
451 av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
2979
bfabfdf9ce55 COSMETICS: tabs --> spaces, some prettyprinting
diego
parents: 2967
diff changeset
452 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
453
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
454 return 0;
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
455 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
456
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
457 static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
458 const uint8_t *buf, int buf_size, int stereo)
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
459 {
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
460 int i;
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
461 int chan = 0;
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
462 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
463
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
464 for(i = 0; i < buf_size; i++) {
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
465 if(buf[i] & 0x80)
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
466 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
467 else
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
468 s->predictors[chan] += vmdaudio_table[buf[i]];
5523
c2ab2ac31edb use av_clip_int16() where it makes sense
aurel
parents: 5215
diff changeset
469 s->predictors[chan] = av_clip_int16(s->predictors[chan]);
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
470 out[i] = s->predictors[chan];
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
471 chan ^= stereo;
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
472 }
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
473 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
474
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
475 static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
476 const uint8_t *buf, int silence, int data_size)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
477 {
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
478 int bytes_decoded = 0;
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
479 int i;
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
480
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
481 // if (silence)
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
482 // 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
483 if (s->channels == 2) {
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
484
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
485 /* stereo handling */
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
486 if (silence) {
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
487 memset(data, 0, data_size * 2);
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
488 } else {
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
489 if (s->bits == 16)
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
490 vmdaudio_decode_audio(s, data, buf, data_size, 1);
4182
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
491 else {
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
492 /* copy the data but convert it to signed */
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
493 for (i = 0; i < data_size; i++){
4182
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
494 *data++ = buf[i] + 0x80;
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
495 *data++ = buf[i] + 0x80;
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
496 }
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
497 }
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
498 }
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
499 } else {
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
500 bytes_decoded = data_size * 2;
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
501
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
502 /* mono handling */
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
503 if (silence) {
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
504 memset(data, 0, data_size * 2);
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
505 } else {
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
506 if (s->bits == 16) {
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
507 vmdaudio_decode_audio(s, data, buf, data_size, 0);
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
508 } else {
3191
7acb3ea20b4c 16-bit DPCM and stereo support for Sierra VMD
kostya
parents: 3036
diff changeset
509 /* copy the data but convert it to signed */
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
510 for (i = 0; i < data_size; i++){
4182
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
511 *data++ = buf[i] + 0x80;
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
512 *data++ = buf[i] + 0x80;
17d005bf07f2 Output proper 16-bit sound (fixes decoding on PPC)
kostya
parents: 3947
diff changeset
513 }
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
514 }
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
515 }
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
516 }
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
517
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
518 return data_size * 2;
1717
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
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
521 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
522 void *data, int *data_size,
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
523 AVPacket *avpkt)
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
524 {
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
525 const uint8_t *buf = avpkt->data;
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8718
diff changeset
526 int buf_size = avpkt->size;
4827
b3ee9a1526b0 Get rid of unnecessary pointer casts.
diego
parents: 4801
diff changeset
527 VmdAudioContext *s = avctx->priv_data;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
528 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
529
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
530 /* point to the start of the encoded data */
6291
michael
parents: 5699
diff changeset
531 const unsigned char *p = buf + 16;
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
532
1882
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
533 if (buf_size < 16)
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
534 return buf_size;
5456ab242388 minor VMD system update; still not perfect, but should not crash either
melanson
parents: 1823
diff changeset
535
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
536 if (buf[6] == 1) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
537 /* the chunk contains audio */
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
538 *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16);
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
539 } else if (buf[6] == 2) {
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
540 /* initial chunk, may contain audio and silence */
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
541 uint32_t flags = AV_RB32(p);
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
542 int raw_block_size = s->block_align * s->bits / 8;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
543 int silent_chunks;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
544 if(flags == 0xFFFFFFFF)
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
545 silent_chunks = 32;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
546 else
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
547 silent_chunks = av_log2(flags + 1);
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
548 if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2)
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
549 return -1;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
550 *data_size = 0;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
551 memset(output_samples, 0, raw_block_size * silent_chunks);
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
552 output_samples += raw_block_size * silent_chunks;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
553 *data_size = raw_block_size * silent_chunks;
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
554 *data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20);
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
555 } else if (buf[6] == 3) {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
556 /* silent chunk */
8634
33912b3ea952 VMD first chunk of audio is not coded as many separate chunks of block_align
kostya
parents: 8573
diff changeset
557 *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0);
1717
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
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
560 return buf_size;
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
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
563
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
564 /*
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
565 * Public Data Structures
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
566 */
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
567
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
568 AVCodec vmdvideo_decoder = {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
569 "vmdvideo",
11560
8a4984c5cacc Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 9981
diff changeset
570 AVMEDIA_TYPE_VIDEO,
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
571 CODEC_ID_VMDVIDEO,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
572 sizeof(VmdVideoContext),
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
573 vmdvideo_decode_init,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
574 NULL,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
575 vmdvideo_decode_end,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
576 vmdvideo_decode_frame,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
577 CODEC_CAP_DR1,
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6750
diff changeset
578 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
579 };
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
580
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
581 AVCodec vmdaudio_decoder = {
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
582 "vmdaudio",
11560
8a4984c5cacc Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 9981
diff changeset
583 AVMEDIA_TYPE_AUDIO,
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
584 CODEC_ID_VMDAUDIO,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
585 sizeof(VmdAudioContext),
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
586 vmdaudio_decode_init,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
587 NULL,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
588 NULL,
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
589 vmdaudio_decode_frame,
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6750
diff changeset
590 .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"),
1717
6a7e68899d8a first pass at Sierra VMD A/V decoders; video looks great, audio is not
melanson
parents:
diff changeset
591 };