1 /*
2 * Kega Game Video (KGV1) decoder
3 * Copyright (c) 2010 Daniel Verkamp
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Kega Game Video decoder
25 */
26
32
37
39 {
41
44 }
45
48 {
53 int offsets[8];
55 int outcnt = 0, maxcnt;
56 int w, h, i, res;
57
60
61 w = (buf[0] + 1) * 8;
62 h = (buf[1] + 1) * 8;
63 buf += 2;
64
69 return res;
70 }
71
78 }
79 }
80
81 maxcnt = w * h;
82
84 return res;
87
88 for (i = 0; i < 8; i++)
89 offsets[i] = -1;
90
91 while (outcnt < maxcnt && buf_end - 2 >= buf) {
93 buf += 2;
94
95 if (!(code & 0x8000)) {
96 AV_WN16A(&out[2 * outcnt], code);
// rgb555 pixel coded directly
97 outcnt++;
98 } else {
100
101 if ((code & 0x6000) == 0x6000) {
102 // copy from previous frame
103 int oidx = (code >> 10) & 7;
105
106 count = (code & 0x3FF) + 3;
107
108 if (offsets[oidx] < 0) {
109 if (buf_end - 3 < buf)
110 break;
112 buf += 3;
113 }
114
115 start = (outcnt + offsets[oidx]) % maxcnt;
116
117 if (maxcnt - start < count || maxcnt - outcnt < count)
118 break;
119
120 if (!prev) {
122 "Frame reference does not exist\n");
123 break;
124 }
125
126 memcpy(out + 2 * outcnt, prev + 2 * start, 2 * count);
127 } else {
128 // copy from earlier in this frame
129 int offset = (code & 0x1FFF) + 1;
130
131 if (!(code & 0x6000)) {
132 count = 2;
133 } else if ((code & 0x6000) == 0x2000) {
134 count = 3;
135 } else {
136 if (buf_end - 1 < buf)
137 break;
138 count = 4 + *buf++;
139 }
140
141 if (outcnt < offset || maxcnt - outcnt < count)
142 break;
143
145 }
147 }
148 }
149
150 if (outcnt - maxcnt)
152
157
158 *got_frame = 1;
159
161 }
162
164 {
166
167 return 0;
168 }
169
171 {
173 return 0;
174 }
175
187 };