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