1 | /*
|
---|
2 | * KMVC decoder
|
---|
3 | * Copyright (c) 2006 Konstantin Shishkov
|
---|
4 | *
|
---|
5 | * This library is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU Lesser General Public
|
---|
7 | * License as published by the Free Software Foundation; either
|
---|
8 | * version 2 of the License, or (at your option) any later version.
|
---|
9 | *
|
---|
10 | * This library is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
13 | * Lesser General Public License for more details.
|
---|
14 | *
|
---|
15 | * You should have received a copy of the GNU Lesser General Public
|
---|
16 | * License along with this library; if not, write to the Free Software
|
---|
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
18 | *
|
---|
19 | */
|
---|
20 |
|
---|
21 | /**
|
---|
22 | * @file kmvc.c
|
---|
23 | * Karl Morton's Video Codec decoder
|
---|
24 | */
|
---|
25 |
|
---|
26 | #include <stdio.h>
|
---|
27 | #include <stdlib.h>
|
---|
28 |
|
---|
29 | #include "common.h"
|
---|
30 | #include "avcodec.h"
|
---|
31 |
|
---|
32 | #define KMVC_KEYFRAME 0x80
|
---|
33 | #define KMVC_PALETTE 0x40
|
---|
34 | #define KMVC_METHOD 0x0F
|
---|
35 |
|
---|
36 | /*
|
---|
37 | * Decoder context
|
---|
38 | */
|
---|
39 | typedef struct KmvcContext {
|
---|
40 | AVCodecContext *avctx;
|
---|
41 | AVFrame pic;
|
---|
42 |
|
---|
43 | int setpal;
|
---|
44 | int palsize;
|
---|
45 | uint32_t pal[256];
|
---|
46 | uint8_t *cur, *prev;
|
---|
47 | uint8_t *frm0, *frm1;
|
---|
48 | } KmvcContext;
|
---|
49 |
|
---|
50 | typedef struct BitBuf {
|
---|
51 | int bits;
|
---|
52 | int bitbuf;
|
---|
53 | } BitBuf;
|
---|
54 |
|
---|
55 | #define BLK(data, x, y) data[(x) + (y) * 320]
|
---|
56 |
|
---|
57 | #define kmvc_init_getbits(bb, src) bb.bits = 7; bb.bitbuf = *src++;
|
---|
58 |
|
---|
59 | #define kmvc_getbit(bb, src, res) {\
|
---|
60 | res = 0; \
|
---|
61 | if (bb.bitbuf & (1 << bb.bits)) res = 1; \
|
---|
62 | bb.bits--; \
|
---|
63 | if(bb.bits == -1) { \
|
---|
64 | bb.bitbuf = *src++; \
|
---|
65 | bb.bits = 7; \
|
---|
66 | } \
|
---|
67 | }
|
---|
68 |
|
---|
69 | static void kmvc_decode_intra_8x8(KmvcContext * ctx, uint8_t * src, int w, int h)
|
---|
70 | {
|
---|
71 | BitBuf bb;
|
---|
72 | int res, val;
|
---|
73 | int i, j;
|
---|
74 | int bx, by;
|
---|
75 | int l0x, l1x, l0y, l1y;
|
---|
76 | int mx, my;
|
---|
77 |
|
---|
78 | kmvc_init_getbits(bb, src);
|
---|
79 |
|
---|
80 | for (by = 0; by < h; by += 8)
|
---|
81 | for (bx = 0; bx < w; bx += 8) {
|
---|
82 | kmvc_getbit(bb, src, res);
|
---|
83 | if (!res) { // fill whole 8x8 block
|
---|
84 | val = *src++;
|
---|
85 | for (i = 0; i < 64; i++)
|
---|
86 | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val;
|
---|
87 | } else { // handle four 4x4 subblocks
|
---|
88 | for (i = 0; i < 4; i++) {
|
---|
89 | l0x = bx + (i & 1) * 4;
|
---|
90 | l0y = by + (i & 2) * 2;
|
---|
91 | kmvc_getbit(bb, src, res);
|
---|
92 | if (!res) {
|
---|
93 | kmvc_getbit(bb, src, res);
|
---|
94 | if (!res) { // fill whole 4x4 block
|
---|
95 | val = *src++;
|
---|
96 | for (j = 0; j < 16; j++)
|
---|
97 | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
|
---|
98 | } else { // copy block from already decoded place
|
---|
99 | val = *src++;
|
---|
100 | mx = val & 0xF;
|
---|
101 | my = val >> 4;
|
---|
102 | for (j = 0; j < 16; j++)
|
---|
103 | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) =
|
---|
104 | BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my);
|
---|
105 | }
|
---|
106 | } else { // descend to 2x2 sub-sub-blocks
|
---|
107 | for (j = 0; j < 4; j++) {
|
---|
108 | l1x = l0x + (j & 1) * 2;
|
---|
109 | l1y = l0y + (j & 2);
|
---|
110 | kmvc_getbit(bb, src, res);
|
---|
111 | if (!res) {
|
---|
112 | kmvc_getbit(bb, src, res);
|
---|
113 | if (!res) { // fill whole 2x2 block
|
---|
114 | val = *src++;
|
---|
115 | BLK(ctx->cur, l1x, l1y) = val;
|
---|
116 | BLK(ctx->cur, l1x + 1, l1y) = val;
|
---|
117 | BLK(ctx->cur, l1x, l1y + 1) = val;
|
---|
118 | BLK(ctx->cur, l1x + 1, l1y + 1) = val;
|
---|
119 | } else { // copy block from already decoded place
|
---|
120 | val = *src++;
|
---|
121 | mx = val & 0xF;
|
---|
122 | my = val >> 4;
|
---|
123 | BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my);
|
---|
124 | BLK(ctx->cur, l1x + 1, l1y) =
|
---|
125 | BLK(ctx->cur, l1x + 1 - mx, l1y - my);
|
---|
126 | BLK(ctx->cur, l1x, l1y + 1) =
|
---|
127 | BLK(ctx->cur, l1x - mx, l1y + 1 - my);
|
---|
128 | BLK(ctx->cur, l1x + 1, l1y + 1) =
|
---|
129 | BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my);
|
---|
130 | }
|
---|
131 | } else { // read values for block
|
---|
132 | BLK(ctx->cur, l1x, l1y) = *src++;
|
---|
133 | BLK(ctx->cur, l1x + 1, l1y) = *src++;
|
---|
134 | BLK(ctx->cur, l1x, l1y + 1) = *src++;
|
---|
135 | BLK(ctx->cur, l1x + 1, l1y + 1) = *src++;
|
---|
136 | }
|
---|
137 | }
|
---|
138 | }
|
---|
139 | }
|
---|
140 | }
|
---|
141 | }
|
---|
142 | }
|
---|
143 |
|
---|
144 | static void kmvc_decode_inter_8x8(KmvcContext * ctx, uint8_t * src, int w, int h)
|
---|
145 | {
|
---|
146 | BitBuf bb;
|
---|
147 | int res, val;
|
---|
148 | int i, j;
|
---|
149 | int bx, by;
|
---|
150 | int l0x, l1x, l0y, l1y;
|
---|
151 | int mx, my;
|
---|
152 |
|
---|
153 | kmvc_init_getbits(bb, src);
|
---|
154 |
|
---|
155 | for (by = 0; by < h; by += 8)
|
---|
156 | for (bx = 0; bx < w; bx += 8) {
|
---|
157 | kmvc_getbit(bb, src, res);
|
---|
158 | if (!res) {
|
---|
159 | kmvc_getbit(bb, src, res);
|
---|
160 | if (!res) { // fill whole 8x8 block
|
---|
161 | val = *src++;
|
---|
162 | for (i = 0; i < 64; i++)
|
---|
163 | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val;
|
---|
164 | } else { // copy block from previous frame
|
---|
165 | for (i = 0; i < 64; i++)
|
---|
166 | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) =
|
---|
167 | BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3));
|
---|
168 | }
|
---|
169 | } else { // handle four 4x4 subblocks
|
---|
170 | for (i = 0; i < 4; i++) {
|
---|
171 | l0x = bx + (i & 1) * 4;
|
---|
172 | l0y = by + (i & 2) * 2;
|
---|
173 | kmvc_getbit(bb, src, res);
|
---|
174 | if (!res) {
|
---|
175 | kmvc_getbit(bb, src, res);
|
---|
176 | if (!res) { // fill whole 4x4 block
|
---|
177 | val = *src++;
|
---|
178 | for (j = 0; j < 16; j++)
|
---|
179 | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
|
---|
180 | } else { // copy block
|
---|
181 | val = *src++;
|
---|
182 | mx = (val & 0xF) - 8;
|
---|
183 | my = (val >> 4) - 8;
|
---|
184 | for (j = 0; j < 16; j++)
|
---|
185 | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) =
|
---|
186 | BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my);
|
---|
187 | }
|
---|
188 | } else { // descend to 2x2 sub-sub-blocks
|
---|
189 | for (j = 0; j < 4; j++) {
|
---|
190 | l1x = l0x + (j & 1) * 2;
|
---|
191 | l1y = l0y + (j & 2);
|
---|
192 | kmvc_getbit(bb, src, res);
|
---|
193 | if (!res) {
|
---|
194 | kmvc_getbit(bb, src, res);
|
---|
195 | if (!res) { // fill whole 2x2 block
|
---|
196 | val = *src++;
|
---|
197 | BLK(ctx->cur, l1x, l1y) = val;
|
---|
198 | BLK(ctx->cur, l1x + 1, l1y) = val;
|
---|
199 | BLK(ctx->cur, l1x, l1y + 1) = val;
|
---|
200 | BLK(ctx->cur, l1x + 1, l1y + 1) = val;
|
---|
201 | } else { // copy block
|
---|
202 | val = *src++;
|
---|
203 | mx = (val & 0xF) - 8;
|
---|
204 | my = (val >> 4) - 8;
|
---|
205 | BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my);
|
---|
206 | BLK(ctx->cur, l1x + 1, l1y) =
|
---|
207 | BLK(ctx->prev, l1x + 1 + mx, l1y + my);
|
---|
208 | BLK(ctx->cur, l1x, l1y + 1) =
|
---|
209 | BLK(ctx->prev, l1x + mx, l1y + 1 + my);
|
---|
210 | BLK(ctx->cur, l1x + 1, l1y + 1) =
|
---|
211 | BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my);
|
---|
212 | }
|
---|
213 | } else { // read values for block
|
---|
214 | BLK(ctx->cur, l1x, l1y) = *src++;
|
---|
215 | BLK(ctx->cur, l1x + 1, l1y) = *src++;
|
---|
216 | BLK(ctx->cur, l1x, l1y + 1) = *src++;
|
---|
217 | BLK(ctx->cur, l1x + 1, l1y + 1) = *src++;
|
---|
218 | }
|
---|
219 | }
|
---|
220 | }
|
---|
221 | }
|
---|
222 | }
|
---|
223 | }
|
---|
224 | }
|
---|
225 |
|
---|
226 | static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t * buf,
|
---|
227 | int buf_size)
|
---|
228 | {
|
---|
229 | KmvcContext *const ctx = (KmvcContext *) avctx->priv_data;
|
---|
230 | uint8_t *out, *src;
|
---|
231 | int i;
|
---|
232 | int header;
|
---|
233 | int blocksize;
|
---|
234 |
|
---|
235 | if (ctx->pic.data[0])
|
---|
236 | avctx->release_buffer(avctx, &ctx->pic);
|
---|
237 |
|
---|
238 | ctx->pic.reference = 1;
|
---|
239 | ctx->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
|
---|
240 | if (avctx->get_buffer(avctx, &ctx->pic) < 0) {
|
---|
241 | av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
---|
242 | return -1;
|
---|
243 | }
|
---|
244 |
|
---|
245 | header = *buf++;
|
---|
246 |
|
---|
247 | /* blocksize 127 is really palette change event */
|
---|
248 | if (buf[0] == 127) {
|
---|
249 | buf += 3;
|
---|
250 | for (i = 0; i < 127; i++) {
|
---|
251 | ctx->pal[i + (header & 0x81)] = (buf[0] << 16) | (buf[1] << 8) | buf[2];
|
---|
252 | buf += 4;
|
---|
253 | }
|
---|
254 | buf -= 127 * 4 + 3;
|
---|
255 | }
|
---|
256 |
|
---|
257 | if (header & KMVC_KEYFRAME) {
|
---|
258 | ctx->pic.key_frame = 1;
|
---|
259 | ctx->pic.pict_type = FF_I_TYPE;
|
---|
260 | } else {
|
---|
261 | ctx->pic.key_frame = 0;
|
---|
262 | ctx->pic.pict_type = FF_P_TYPE;
|
---|
263 | }
|
---|
264 |
|
---|
265 | /* if palette has been changed, copy it from palctrl */
|
---|
266 | if (ctx->avctx->palctrl && ctx->avctx->palctrl->palette_changed) {
|
---|
267 | memcpy(ctx->pal, ctx->avctx->palctrl->palette, AVPALETTE_SIZE);
|
---|
268 | ctx->setpal = 1;
|
---|
269 | ctx->avctx->palctrl->palette_changed = 0;
|
---|
270 | }
|
---|
271 |
|
---|
272 | if (header & KMVC_PALETTE) {
|
---|
273 | ctx->pic.palette_has_changed = 1;
|
---|
274 | // palette starts from index 1 and has 127 entries
|
---|
275 | for (i = 1; i <= ctx->palsize; i++) {
|
---|
276 | ctx->pal[i] = (buf[0] << 16) | (buf[1] << 8) | buf[2];
|
---|
277 | buf += 3;
|
---|
278 | }
|
---|
279 | }
|
---|
280 |
|
---|
281 | if (ctx->setpal) {
|
---|
282 | ctx->setpal = 0;
|
---|
283 | ctx->pic.palette_has_changed = 1;
|
---|
284 | }
|
---|
285 |
|
---|
286 | /* make the palette available on the way out */
|
---|
287 | memcpy(ctx->pic.data[1], ctx->pal, 1024);
|
---|
288 |
|
---|
289 | blocksize = *buf++;
|
---|
290 |
|
---|
291 | if (blocksize != 8 && blocksize != 127) {
|
---|
292 | av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize);
|
---|
293 | return -1;
|
---|
294 | }
|
---|
295 | memset(ctx->cur, 0, 320 * 200);
|
---|
296 | switch (header & KMVC_METHOD) {
|
---|
297 | case 0:
|
---|
298 | case 1: // used in palette changed event
|
---|
299 | memcpy(ctx->cur, ctx->prev, 320 * 200);
|
---|
300 | break;
|
---|
301 | case 3:
|
---|
302 | kmvc_decode_intra_8x8(ctx, buf, avctx->width, avctx->height);
|
---|
303 | break;
|
---|
304 | case 4:
|
---|
305 | kmvc_decode_inter_8x8(ctx, buf, avctx->width, avctx->height);
|
---|
306 | break;
|
---|
307 | default:
|
---|
308 | av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD);
|
---|
309 | return -1;
|
---|
310 | }
|
---|
311 |
|
---|
312 | out = ctx->pic.data[0];
|
---|
313 | src = ctx->cur;
|
---|
314 | for (i = 0; i < avctx->height; i++) {
|
---|
315 | memcpy(out, src, avctx->width);
|
---|
316 | src += 320;
|
---|
317 | out += ctx->pic.linesize[0];
|
---|
318 | }
|
---|
319 |
|
---|
320 | /* flip buffers */
|
---|
321 | if (ctx->cur == ctx->frm0) {
|
---|
322 | ctx->cur = ctx->frm1;
|
---|
323 | ctx->prev = ctx->frm0;
|
---|
324 | } else {
|
---|
325 | ctx->cur = ctx->frm0;
|
---|
326 | ctx->prev = ctx->frm1;
|
---|
327 | }
|
---|
328 |
|
---|
329 | *data_size = sizeof(AVFrame);
|
---|
330 | *(AVFrame *) data = ctx->pic;
|
---|
331 |
|
---|
332 | /* always report that the buffer was completely consumed */
|
---|
333 | return buf_size;
|
---|
334 | }
|
---|
335 |
|
---|
336 |
|
---|
337 |
|
---|
338 | /*
|
---|
339 | * Init kmvc decoder
|
---|
340 | */
|
---|
341 | static int decode_init(AVCodecContext * avctx)
|
---|
342 | {
|
---|
343 | KmvcContext *const c = (KmvcContext *) avctx->priv_data;
|
---|
344 | int i;
|
---|
345 |
|
---|
346 | c->avctx = avctx;
|
---|
347 | avctx->has_b_frames = 0;
|
---|
348 |
|
---|
349 | c->pic.data[0] = NULL;
|
---|
350 |
|
---|
351 | if (avctx->width > 320 || avctx->height > 200) {
|
---|
352 | av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n");
|
---|
353 | return -1;
|
---|
354 | }
|
---|
355 |
|
---|
356 | c->frm0 = av_mallocz(320 * 200);
|
---|
357 | c->frm1 = av_mallocz(320 * 200);
|
---|
358 | c->cur = c->frm0;
|
---|
359 | c->prev = c->frm1;
|
---|
360 |
|
---|
361 | for (i = 0; i < 256; i++) {
|
---|
362 | c->pal[i] = i * 0x10101;
|
---|
363 | }
|
---|
364 |
|
---|
365 | if (avctx->extradata_size < 12) {
|
---|
366 | av_log(NULL, 0, "Extradata missing, decoding may not work properly...\n");
|
---|
367 | c->palsize = 127;
|
---|
368 | } else {
|
---|
369 | c->palsize = LE_16(avctx->extradata + 10);
|
---|
370 | }
|
---|
371 |
|
---|
372 | if (avctx->extradata_size == 1036) { // palette in extradata
|
---|
373 | uint8_t *src = avctx->extradata + 12;
|
---|
374 | for (i = 0; i < 256; i++) {
|
---|
375 | c->pal[i] = LE_32(src);
|
---|
376 | src += 4;
|
---|
377 | }
|
---|
378 | c->setpal = 1;
|
---|
379 | if (c->avctx->palctrl) {
|
---|
380 | c->avctx->palctrl->palette_changed = 0;
|
---|
381 | }
|
---|
382 | }
|
---|
383 |
|
---|
384 | avctx->pix_fmt = PIX_FMT_PAL8;
|
---|
385 |
|
---|
386 | return 0;
|
---|
387 | }
|
---|
388 |
|
---|
389 |
|
---|
390 |
|
---|
391 | /*
|
---|
392 | * Uninit kmvc decoder
|
---|
393 | */
|
---|
394 | static int decode_end(AVCodecContext * avctx)
|
---|
395 | {
|
---|
396 | KmvcContext *const c = (KmvcContext *) avctx->priv_data;
|
---|
397 |
|
---|
398 | if (c->frm0)
|
---|
399 | av_free(c->frm0);
|
---|
400 | if (c->frm1)
|
---|
401 | av_free(c->frm1);
|
---|
402 | if (c->pic.data[0])
|
---|
403 | avctx->release_buffer(avctx, &c->pic);
|
---|
404 |
|
---|
405 | return 0;
|
---|
406 | }
|
---|
407 |
|
---|
408 | AVCodec kmvc_decoder = {
|
---|
409 | "kmvc",
|
---|
410 | CODEC_TYPE_VIDEO,
|
---|
411 | CODEC_ID_KMVC,
|
---|
412 | sizeof(KmvcContext),
|
---|
413 | decode_init,
|
---|
414 | NULL,
|
---|
415 | decode_end,
|
---|
416 | decode_frame
|
---|
417 | };
|
---|