/src/ffmpeg/libavcodec/kmvc.c
Line | Count | Source |
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 | | |
29 | | #include "avcodec.h" |
30 | | #include "bytestream.h" |
31 | | #include "codec_internal.h" |
32 | | #include "decode.h" |
33 | | #include "libavutil/common.h" |
34 | | |
35 | 1.49M | #define KMVC_KEYFRAME 0x80 |
36 | 1.49M | #define KMVC_PALETTE 0x40 |
37 | 116k | #define KMVC_METHOD 0x0F |
38 | 61 | #define MAX_PALSIZE 256 |
39 | | |
40 | | /* |
41 | | * Decoder context |
42 | | */ |
43 | | typedef struct KmvcContext { |
44 | | AVCodecContext *avctx; |
45 | | |
46 | | GetByteContext g; |
47 | | uint8_t *cur, *prev; |
48 | | int setpal; |
49 | | int palsize; |
50 | | uint32_t pal[MAX_PALSIZE]; |
51 | | uint8_t frm0[320 * 200], frm1[320 * 200]; |
52 | | } KmvcContext; |
53 | | |
54 | | typedef struct BitBuf { |
55 | | int bits; |
56 | | int bitbuf; |
57 | | } BitBuf; |
58 | | |
59 | 21.5M | #define BLK(data, x, y) data[av_clip((x) + (y) * 320, 0, 320 * 200 -1)] |
60 | | |
61 | 114k | #define kmvc_init_getbits(bb, g) bb.bits = 7; bb.bitbuf = bytestream2_get_byte(g); |
62 | | |
63 | 1.57M | #define kmvc_getbit(bb, g, res) {\ |
64 | 1.57M | res = 0; \ |
65 | 1.57M | if (bb.bitbuf & (1 << bb.bits)) res = 1; \ |
66 | 1.57M | bb.bits--; \ |
67 | 1.57M | if(bb.bits == -1) { \ |
68 | 192k | bb.bitbuf = bytestream2_get_byte(g); \ |
69 | 192k | bb.bits = 7; \ |
70 | 192k | } \ |
71 | 1.57M | } |
72 | | |
73 | | static int kmvc_decode_intra_8x8(KmvcContext * ctx, int w, int h) |
74 | 109k | { |
75 | 109k | BitBuf bb; |
76 | 109k | int res, val; |
77 | 109k | int i, j; |
78 | 109k | int bx, by; |
79 | 109k | int l0x, l1x, l0y, l1y; |
80 | 109k | int mx, my; |
81 | | |
82 | 109k | kmvc_init_getbits(bb, &ctx->g); |
83 | | |
84 | 135k | for (by = 0; by < h; by += 8) |
85 | 279k | for (bx = 0; bx < w; bx += 8) { |
86 | 252k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
87 | 107k | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
88 | 107k | return AVERROR_INVALIDDATA; |
89 | 107k | } |
90 | 145k | kmvc_getbit(bb, &ctx->g, res); |
91 | 145k | if (!res) { // fill whole 8x8 block |
92 | 109k | val = bytestream2_get_byte(&ctx->g); |
93 | 7.14M | for (i = 0; i < 64; i++) |
94 | 7.03M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; |
95 | 109k | } else { // handle four 4x4 subblocks |
96 | 172k | for (i = 0; i < 4; i++) { |
97 | 138k | l0x = bx + (i & 1) * 4; |
98 | 138k | l0y = by + (i & 2) * 2; |
99 | 138k | kmvc_getbit(bb, &ctx->g, res); |
100 | 138k | if (!res) { |
101 | 65.8k | kmvc_getbit(bb, &ctx->g, res); |
102 | 65.8k | if (!res) { // fill whole 4x4 block |
103 | 29.1k | val = bytestream2_get_byte(&ctx->g); |
104 | 495k | for (j = 0; j < 16; j++) |
105 | 466k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; |
106 | 36.6k | } else { // copy block from already decoded place |
107 | 36.6k | val = bytestream2_get_byte(&ctx->g); |
108 | 36.6k | mx = val & 0xF; |
109 | 36.6k | my = val >> 4; |
110 | 36.6k | if ((l0x-mx) + 320*(l0y-my) < 0 || (l0x-mx) + 320*(l0y-my) > 320*197 - 4) { |
111 | 694 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
112 | 694 | return AVERROR_INVALIDDATA; |
113 | 694 | } |
114 | 612k | for (j = 0; j < 16; j++) |
115 | 576k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = |
116 | 576k | BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my); |
117 | 36.0k | } |
118 | 72.4k | } else { // descend to 2x2 sub-sub-blocks |
119 | 361k | for (j = 0; j < 4; j++) { |
120 | 289k | l1x = l0x + (j & 1) * 2; |
121 | 289k | l1y = l0y + (j & 2); |
122 | 289k | kmvc_getbit(bb, &ctx->g, res); |
123 | 289k | if (!res) { |
124 | 191k | kmvc_getbit(bb, &ctx->g, res); |
125 | 191k | if (!res) { // fill whole 2x2 block |
126 | 85.7k | val = bytestream2_get_byte(&ctx->g); |
127 | 85.7k | BLK(ctx->cur, l1x, l1y) = val; |
128 | 85.7k | BLK(ctx->cur, l1x + 1, l1y) = val; |
129 | 85.7k | BLK(ctx->cur, l1x, l1y + 1) = val; |
130 | 85.7k | BLK(ctx->cur, l1x + 1, l1y + 1) = val; |
131 | 105k | } else { // copy block from already decoded place |
132 | 105k | val = bytestream2_get_byte(&ctx->g); |
133 | 105k | mx = val & 0xF; |
134 | 105k | my = val >> 4; |
135 | 105k | if ((l1x-mx) + 320*(l1y-my) < 0 || (l1x-mx) + 320*(l1y-my) > 320*199 - 2) { |
136 | 387 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
137 | 387 | return AVERROR_INVALIDDATA; |
138 | 387 | } |
139 | 104k | BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my); |
140 | 104k | BLK(ctx->cur, l1x + 1, l1y) = |
141 | 104k | BLK(ctx->cur, l1x + 1 - mx, l1y - my); |
142 | 104k | BLK(ctx->cur, l1x, l1y + 1) = |
143 | 104k | BLK(ctx->cur, l1x - mx, l1y + 1 - my); |
144 | 104k | BLK(ctx->cur, l1x + 1, l1y + 1) = |
145 | 104k | BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my); |
146 | 104k | } |
147 | 191k | } else { // read values for block |
148 | 98.0k | BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); |
149 | 98.0k | BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); |
150 | 98.0k | BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); |
151 | 98.0k | BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); |
152 | 98.0k | } |
153 | 289k | } |
154 | 72.4k | } |
155 | 138k | } |
156 | 35.1k | } |
157 | 145k | } |
158 | | |
159 | 365 | return 0; |
160 | 109k | } |
161 | | |
162 | | static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h) |
163 | 5.68k | { |
164 | 5.68k | BitBuf bb; |
165 | 5.68k | int res, val; |
166 | 5.68k | int i, j; |
167 | 5.68k | int bx, by; |
168 | 5.68k | int l0x, l1x, l0y, l1y; |
169 | 5.68k | int mx, my; |
170 | | |
171 | 5.68k | kmvc_init_getbits(bb, &ctx->g); |
172 | | |
173 | 26.1k | for (by = 0; by < h; by += 8) |
174 | 161k | for (bx = 0; bx < w; bx += 8) { |
175 | 141k | kmvc_getbit(bb, &ctx->g, res); |
176 | 141k | if (!res) { |
177 | 115k | kmvc_getbit(bb, &ctx->g, res); |
178 | 115k | if (!res) { // fill whole 8x8 block |
179 | 84.4k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
180 | 3.34k | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
181 | 3.34k | return AVERROR_INVALIDDATA; |
182 | 3.34k | } |
183 | 81.0k | val = bytestream2_get_byte(&ctx->g); |
184 | 5.26M | for (i = 0; i < 64; i++) |
185 | 5.18M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; |
186 | 81.0k | } else { // copy block from previous frame |
187 | 2.01M | for (i = 0; i < 64; i++) |
188 | 1.98M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = |
189 | 1.98M | BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3)); |
190 | 31.0k | } |
191 | 115k | } else { // handle four 4x4 subblocks |
192 | 25.8k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
193 | 402 | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
194 | 402 | return AVERROR_INVALIDDATA; |
195 | 402 | } |
196 | 122k | for (i = 0; i < 4; i++) { |
197 | 98.4k | l0x = bx + (i & 1) * 4; |
198 | 98.4k | l0y = by + (i & 2) * 2; |
199 | 98.4k | kmvc_getbit(bb, &ctx->g, res); |
200 | 98.4k | if (!res) { |
201 | 44.5k | kmvc_getbit(bb, &ctx->g, res); |
202 | 44.5k | if (!res) { // fill whole 4x4 block |
203 | 25.0k | val = bytestream2_get_byte(&ctx->g); |
204 | 426k | for (j = 0; j < 16; j++) |
205 | 401k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; |
206 | 25.0k | } else { // copy block |
207 | 19.4k | val = bytestream2_get_byte(&ctx->g); |
208 | 19.4k | mx = (val & 0xF) - 8; |
209 | 19.4k | my = (val >> 4) - 8; |
210 | 19.4k | if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 320*197 - 4) { |
211 | 653 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
212 | 653 | return AVERROR_INVALIDDATA; |
213 | 653 | } |
214 | 319k | for (j = 0; j < 16; j++) |
215 | 300k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = |
216 | 300k | BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my); |
217 | 18.7k | } |
218 | 53.9k | } else { // descend to 2x2 sub-sub-blocks |
219 | 267k | for (j = 0; j < 4; j++) { |
220 | 214k | l1x = l0x + (j & 1) * 2; |
221 | 214k | l1y = l0y + (j & 2); |
222 | 214k | kmvc_getbit(bb, &ctx->g, res); |
223 | 214k | if (!res) { |
224 | 131k | kmvc_getbit(bb, &ctx->g, res); |
225 | 131k | if (!res) { // fill whole 2x2 block |
226 | 59.0k | val = bytestream2_get_byte(&ctx->g); |
227 | 59.0k | BLK(ctx->cur, l1x, l1y) = val; |
228 | 59.0k | BLK(ctx->cur, l1x + 1, l1y) = val; |
229 | 59.0k | BLK(ctx->cur, l1x, l1y + 1) = val; |
230 | 59.0k | BLK(ctx->cur, l1x + 1, l1y + 1) = val; |
231 | 72.0k | } else { // copy block |
232 | 72.0k | val = bytestream2_get_byte(&ctx->g); |
233 | 72.0k | mx = (val & 0xF) - 8; |
234 | 72.0k | my = (val >> 4) - 8; |
235 | 72.0k | if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 320*199 - 2) { |
236 | 886 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
237 | 886 | return AVERROR_INVALIDDATA; |
238 | 886 | } |
239 | 71.1k | BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my); |
240 | 71.1k | BLK(ctx->cur, l1x + 1, l1y) = |
241 | 71.1k | BLK(ctx->prev, l1x + 1 + mx, l1y + my); |
242 | 71.1k | BLK(ctx->cur, l1x, l1y + 1) = |
243 | 71.1k | BLK(ctx->prev, l1x + mx, l1y + 1 + my); |
244 | 71.1k | BLK(ctx->cur, l1x + 1, l1y + 1) = |
245 | 71.1k | BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my); |
246 | 71.1k | } |
247 | 131k | } else { // read values for block |
248 | 82.9k | BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); |
249 | 82.9k | BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); |
250 | 82.9k | BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); |
251 | 82.9k | BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); |
252 | 82.9k | } |
253 | 214k | } |
254 | 53.9k | } |
255 | 98.4k | } |
256 | 25.4k | } |
257 | 141k | } |
258 | | |
259 | 391 | return 0; |
260 | 5.68k | } |
261 | | |
262 | | static int decode_frame(AVCodecContext * avctx, AVFrame *frame, |
263 | | int *got_frame, AVPacket *avpkt) |
264 | 1.51M | { |
265 | 1.51M | KmvcContext *const ctx = avctx->priv_data; |
266 | 1.51M | uint8_t *out, *src; |
267 | 1.51M | int i, ret; |
268 | 1.51M | int header; |
269 | 1.51M | int blocksize; |
270 | | |
271 | 1.51M | bytestream2_init(&ctx->g, avpkt->data, avpkt->size); |
272 | | |
273 | 1.51M | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
274 | 20.0k | return ret; |
275 | | |
276 | 1.49M | ff_copy_palette(ctx->pal, avpkt, avctx); |
277 | | |
278 | 1.49M | header = bytestream2_get_byte(&ctx->g); |
279 | | |
280 | | /* blocksize 127 is really palette change event */ |
281 | 1.49M | if (bytestream2_peek_byte(&ctx->g) == 127) { |
282 | 2.01k | bytestream2_skip(&ctx->g, 3); |
283 | 258k | for (i = 0; i < 127; i++) { |
284 | 256k | ctx->pal[i + (header & 0x81)] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); |
285 | 256k | bytestream2_skip(&ctx->g, 1); |
286 | 256k | } |
287 | 2.01k | bytestream2_seek(&ctx->g, -127 * 4 - 3, SEEK_CUR); |
288 | 2.01k | } |
289 | | |
290 | 1.49M | if (header & KMVC_KEYFRAME) { |
291 | 1.28M | frame->flags |= AV_FRAME_FLAG_KEY; |
292 | 1.28M | frame->pict_type = AV_PICTURE_TYPE_I; |
293 | 1.28M | } else { |
294 | 208k | frame->flags &= ~AV_FRAME_FLAG_KEY; |
295 | 208k | frame->pict_type = AV_PICTURE_TYPE_P; |
296 | 208k | } |
297 | | |
298 | 1.49M | if (header & KMVC_PALETTE) { |
299 | | // palette starts from index 1 and has 127 entries |
300 | 170M | for (i = 1; i <= ctx->palsize; i++) { |
301 | 169M | ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); |
302 | 169M | } |
303 | 1.33M | } |
304 | | |
305 | 1.49M | if (ctx->setpal) { |
306 | 1 | ctx->setpal = 0; |
307 | 1 | } |
308 | | |
309 | | /* make the palette available on the way out */ |
310 | 1.49M | memcpy(frame->data[1], ctx->pal, 1024); |
311 | | |
312 | 1.49M | blocksize = bytestream2_get_byte(&ctx->g); |
313 | | |
314 | 1.49M | if (blocksize != 8 && blocksize != 127) { |
315 | 1.38M | av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize); |
316 | 1.38M | return AVERROR_INVALIDDATA; |
317 | 1.38M | } |
318 | 115k | memset(ctx->cur, 0, 320 * 200); |
319 | 115k | switch (header & KMVC_METHOD) { |
320 | 359 | case 0: |
321 | 618 | case 1: // used in palette changed event |
322 | 618 | memcpy(ctx->cur, ctx->prev, 320 * 200); |
323 | 618 | break; |
324 | 109k | case 3: |
325 | 109k | kmvc_decode_intra_8x8(ctx, avctx->width, avctx->height); |
326 | 109k | break; |
327 | 5.68k | case 4: |
328 | 5.68k | kmvc_decode_inter_8x8(ctx, avctx->width, avctx->height); |
329 | 5.68k | break; |
330 | 329 | default: |
331 | 329 | av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD); |
332 | 329 | return AVERROR_INVALIDDATA; |
333 | 115k | } |
334 | | |
335 | 115k | out = frame->data[0]; |
336 | 115k | src = ctx->cur; |
337 | 17.0M | for (i = 0; i < avctx->height; i++) { |
338 | 16.8M | memcpy(out, src, avctx->width); |
339 | 16.8M | src += 320; |
340 | 16.8M | out += frame->linesize[0]; |
341 | 16.8M | } |
342 | | |
343 | | /* flip buffers */ |
344 | 115k | FFSWAP(uint8_t *, ctx->cur, ctx->prev); |
345 | | |
346 | 115k | *got_frame = 1; |
347 | | |
348 | | /* always report that the buffer was completely consumed */ |
349 | 115k | return avpkt->size; |
350 | 115k | } |
351 | | |
352 | | |
353 | | |
354 | | /* |
355 | | * Init kmvc decoder |
356 | | */ |
357 | | static av_cold int decode_init(AVCodecContext * avctx) |
358 | 1.14k | { |
359 | 1.14k | KmvcContext *const c = avctx->priv_data; |
360 | 1.14k | int i; |
361 | | |
362 | 1.14k | c->avctx = avctx; |
363 | | |
364 | 1.14k | if (avctx->width > 320 || avctx->height > 200) { |
365 | 31 | av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n"); |
366 | 31 | return AVERROR(EINVAL); |
367 | 31 | } |
368 | | |
369 | 1.11k | c->cur = c->frm0; |
370 | 1.11k | c->prev = c->frm1; |
371 | | |
372 | 285k | for (i = 0; i < 256; i++) { |
373 | 284k | c->pal[i] = 0xFFU << 24 | i * 0x10101; |
374 | 284k | } |
375 | | |
376 | 1.11k | if (avctx->extradata_size < 12) { |
377 | 1.04k | av_log(avctx, AV_LOG_WARNING, |
378 | 1.04k | "Extradata missing, decoding may not work properly...\n"); |
379 | 1.04k | c->palsize = 127; |
380 | 1.04k | } else { |
381 | 61 | c->palsize = AV_RL16(avctx->extradata + 10); |
382 | 61 | if (c->palsize >= (unsigned)MAX_PALSIZE) { |
383 | 12 | c->palsize = 127; |
384 | 12 | av_log(avctx, AV_LOG_ERROR, "KMVC palette too large\n"); |
385 | 12 | return AVERROR_INVALIDDATA; |
386 | 12 | } |
387 | 61 | } |
388 | | |
389 | 1.09k | if (avctx->extradata_size == 1036) { // palette in extradata |
390 | 1 | uint8_t *src = avctx->extradata + 12; |
391 | 257 | for (i = 0; i < 256; i++) { |
392 | 256 | c->pal[i] = AV_RL32(src); |
393 | 256 | src += 4; |
394 | 256 | } |
395 | 1 | c->setpal = 1; |
396 | 1 | } |
397 | | |
398 | 1.09k | avctx->pix_fmt = AV_PIX_FMT_PAL8; |
399 | | |
400 | 1.09k | return 0; |
401 | 1.11k | } |
402 | | |
403 | | const FFCodec ff_kmvc_decoder = { |
404 | | .p.name = "kmvc", |
405 | | CODEC_LONG_NAME("Karl Morton's video codec"), |
406 | | .p.type = AVMEDIA_TYPE_VIDEO, |
407 | | .p.id = AV_CODEC_ID_KMVC, |
408 | | .priv_data_size = sizeof(KmvcContext), |
409 | | .init = decode_init, |
410 | | FF_CODEC_DECODE_CB(decode_frame), |
411 | | .p.capabilities = AV_CODEC_CAP_DR1, |
412 | | }; |