/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 | 884k | #define KMVC_KEYFRAME 0x80 |
36 | 884k | #define KMVC_PALETTE 0x40 |
37 | 112k | #define KMVC_METHOD 0x0F |
38 | 81 | #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 | 23.6M | #define BLK(data, x, y) data[av_clip((x) + (y) * 320, 0, 320 * 200 -1)] |
60 | | |
61 | 110k | #define kmvc_init_getbits(bb, g) bb.bits = 7; bb.bitbuf = bytestream2_get_byte(g); |
62 | | |
63 | 1.74M | #define kmvc_getbit(bb, g, res) {\ |
64 | 1.74M | res = 0; \ |
65 | 1.74M | if (bb.bitbuf & (1 << bb.bits)) res = 1; \ |
66 | 1.74M | bb.bits--; \ |
67 | 1.74M | if(bb.bits == -1) { \ |
68 | 212k | bb.bitbuf = bytestream2_get_byte(g); \ |
69 | 212k | bb.bits = 7; \ |
70 | 212k | } \ |
71 | 1.74M | } |
72 | | |
73 | | static int kmvc_decode_intra_8x8(KmvcContext * ctx, int w, int h) |
74 | 100k | { |
75 | 100k | BitBuf bb; |
76 | 100k | int res, val; |
77 | 100k | int i, j; |
78 | 100k | int bx, by; |
79 | 100k | int l0x, l1x, l0y, l1y; |
80 | 100k | int mx, my; |
81 | | |
82 | 100k | kmvc_init_getbits(bb, &ctx->g); |
83 | | |
84 | 126k | for (by = 0; by < h; by += 8) |
85 | 276k | for (bx = 0; bx < w; bx += 8) { |
86 | 250k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
87 | 99.1k | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
88 | 99.1k | return AVERROR_INVALIDDATA; |
89 | 99.1k | } |
90 | 151k | kmvc_getbit(bb, &ctx->g, res); |
91 | 151k | if (!res) { // fill whole 8x8 block |
92 | 113k | val = bytestream2_get_byte(&ctx->g); |
93 | 7.37M | for (i = 0; i < 64; i++) |
94 | 7.26M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; |
95 | 113k | } else { // handle four 4x4 subblocks |
96 | 184k | for (i = 0; i < 4; i++) { |
97 | 148k | l0x = bx + (i & 1) * 4; |
98 | 148k | l0y = by + (i & 2) * 2; |
99 | 148k | kmvc_getbit(bb, &ctx->g, res); |
100 | 148k | if (!res) { |
101 | 69.0k | kmvc_getbit(bb, &ctx->g, res); |
102 | 69.0k | if (!res) { // fill whole 4x4 block |
103 | 30.5k | val = bytestream2_get_byte(&ctx->g); |
104 | 519k | for (j = 0; j < 16; j++) |
105 | 489k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; |
106 | 38.5k | } else { // copy block from already decoded place |
107 | 38.5k | val = bytestream2_get_byte(&ctx->g); |
108 | 38.5k | mx = val & 0xF; |
109 | 38.5k | my = val >> 4; |
110 | 38.5k | if ((l0x-mx) + 320*(l0y-my) < 0 || (l0x-mx) + 320*(l0y-my) > 320*197 - 4) { |
111 | 829 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
112 | 829 | return AVERROR_INVALIDDATA; |
113 | 829 | } |
114 | 640k | for (j = 0; j < 16; j++) |
115 | 602k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = |
116 | 602k | BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my); |
117 | 37.6k | } |
118 | 78.9k | } else { // descend to 2x2 sub-sub-blocks |
119 | 393k | for (j = 0; j < 4; j++) { |
120 | 315k | l1x = l0x + (j & 1) * 2; |
121 | 315k | l1y = l0y + (j & 2); |
122 | 315k | kmvc_getbit(bb, &ctx->g, res); |
123 | 315k | if (!res) { |
124 | 208k | kmvc_getbit(bb, &ctx->g, res); |
125 | 208k | if (!res) { // fill whole 2x2 block |
126 | 92.9k | val = bytestream2_get_byte(&ctx->g); |
127 | 92.9k | BLK(ctx->cur, l1x, l1y) = val; |
128 | 92.9k | BLK(ctx->cur, l1x + 1, l1y) = val; |
129 | 92.9k | BLK(ctx->cur, l1x, l1y + 1) = val; |
130 | 92.9k | BLK(ctx->cur, l1x + 1, l1y + 1) = val; |
131 | 115k | } else { // copy block from already decoded place |
132 | 115k | val = bytestream2_get_byte(&ctx->g); |
133 | 115k | mx = val & 0xF; |
134 | 115k | my = val >> 4; |
135 | 115k | if ((l1x-mx) + 320*(l1y-my) < 0 || (l1x-mx) + 320*(l1y-my) > 320*199 - 2) { |
136 | 348 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
137 | 348 | return AVERROR_INVALIDDATA; |
138 | 348 | } |
139 | 114k | BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my); |
140 | 114k | BLK(ctx->cur, l1x + 1, l1y) = |
141 | 114k | BLK(ctx->cur, l1x + 1 - mx, l1y - my); |
142 | 114k | BLK(ctx->cur, l1x, l1y + 1) = |
143 | 114k | BLK(ctx->cur, l1x - mx, l1y + 1 - my); |
144 | 114k | BLK(ctx->cur, l1x + 1, l1y + 1) = |
145 | 114k | BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my); |
146 | 114k | } |
147 | 208k | } else { // read values for block |
148 | 106k | BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); |
149 | 106k | BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); |
150 | 106k | BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); |
151 | 106k | BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); |
152 | 106k | } |
153 | 315k | } |
154 | 78.9k | } |
155 | 148k | } |
156 | 37.6k | } |
157 | 151k | } |
158 | | |
159 | 381 | return 0; |
160 | 100k | } |
161 | | |
162 | | static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h) |
163 | 9.97k | { |
164 | 9.97k | BitBuf bb; |
165 | 9.97k | int res, val; |
166 | 9.97k | int i, j; |
167 | 9.97k | int bx, by; |
168 | 9.97k | int l0x, l1x, l0y, l1y; |
169 | 9.97k | int mx, my; |
170 | | |
171 | 9.97k | kmvc_init_getbits(bb, &ctx->g); |
172 | | |
173 | 33.0k | for (by = 0; by < h; by += 8) |
174 | 189k | for (bx = 0; bx < w; bx += 8) { |
175 | 166k | kmvc_getbit(bb, &ctx->g, res); |
176 | 166k | if (!res) { |
177 | 137k | kmvc_getbit(bb, &ctx->g, res); |
178 | 137k | if (!res) { // fill whole 8x8 block |
179 | 103k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
180 | 7.82k | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
181 | 7.82k | return AVERROR_INVALIDDATA; |
182 | 7.82k | } |
183 | 95.6k | val = bytestream2_get_byte(&ctx->g); |
184 | 6.21M | for (i = 0; i < 64; i++) |
185 | 6.12M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; |
186 | 95.6k | } else { // copy block from previous frame |
187 | 2.22M | for (i = 0; i < 64; i++) |
188 | 2.19M | BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = |
189 | 2.19M | BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3)); |
190 | 34.2k | } |
191 | 137k | } else { // handle four 4x4 subblocks |
192 | 28.9k | if (!bytestream2_get_bytes_left(&ctx->g)) { |
193 | 513 | av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); |
194 | 513 | return AVERROR_INVALIDDATA; |
195 | 513 | } |
196 | 138k | for (i = 0; i < 4; i++) { |
197 | 111k | l0x = bx + (i & 1) * 4; |
198 | 111k | l0y = by + (i & 2) * 2; |
199 | 111k | kmvc_getbit(bb, &ctx->g, res); |
200 | 111k | if (!res) { |
201 | 50.3k | kmvc_getbit(bb, &ctx->g, res); |
202 | 50.3k | if (!res) { // fill whole 4x4 block |
203 | 28.6k | val = bytestream2_get_byte(&ctx->g); |
204 | 486k | for (j = 0; j < 16; j++) |
205 | 457k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; |
206 | 28.6k | } else { // copy block |
207 | 21.7k | val = bytestream2_get_byte(&ctx->g); |
208 | 21.7k | mx = (val & 0xF) - 8; |
209 | 21.7k | my = (val >> 4) - 8; |
210 | 21.7k | if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 320*197 - 4) { |
211 | 595 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
212 | 595 | return AVERROR_INVALIDDATA; |
213 | 595 | } |
214 | 359k | for (j = 0; j < 16; j++) |
215 | 338k | BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = |
216 | 338k | BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my); |
217 | 21.1k | } |
218 | 61.0k | } else { // descend to 2x2 sub-sub-blocks |
219 | 303k | for (j = 0; j < 4; j++) { |
220 | 243k | l1x = l0x + (j & 1) * 2; |
221 | 243k | l1y = l0y + (j & 2); |
222 | 243k | kmvc_getbit(bb, &ctx->g, res); |
223 | 243k | if (!res) { |
224 | 143k | kmvc_getbit(bb, &ctx->g, res); |
225 | 143k | if (!res) { // fill whole 2x2 block |
226 | 64.9k | val = bytestream2_get_byte(&ctx->g); |
227 | 64.9k | BLK(ctx->cur, l1x, l1y) = val; |
228 | 64.9k | BLK(ctx->cur, l1x + 1, l1y) = val; |
229 | 64.9k | BLK(ctx->cur, l1x, l1y + 1) = val; |
230 | 64.9k | BLK(ctx->cur, l1x + 1, l1y + 1) = val; |
231 | 78.0k | } else { // copy block |
232 | 78.0k | val = bytestream2_get_byte(&ctx->g); |
233 | 78.0k | mx = (val & 0xF) - 8; |
234 | 78.0k | my = (val >> 4) - 8; |
235 | 78.0k | if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 320*199 - 2) { |
236 | 599 | av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); |
237 | 599 | return AVERROR_INVALIDDATA; |
238 | 599 | } |
239 | 77.4k | BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my); |
240 | 77.4k | BLK(ctx->cur, l1x + 1, l1y) = |
241 | 77.4k | BLK(ctx->prev, l1x + 1 + mx, l1y + my); |
242 | 77.4k | BLK(ctx->cur, l1x, l1y + 1) = |
243 | 77.4k | BLK(ctx->prev, l1x + mx, l1y + 1 + my); |
244 | 77.4k | BLK(ctx->cur, l1x + 1, l1y + 1) = |
245 | 77.4k | BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my); |
246 | 77.4k | } |
247 | 143k | } else { // read values for block |
248 | 100k | BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); |
249 | 100k | BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); |
250 | 100k | BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); |
251 | 100k | BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); |
252 | 100k | } |
253 | 243k | } |
254 | 61.0k | } |
255 | 111k | } |
256 | 28.4k | } |
257 | 166k | } |
258 | | |
259 | 440 | return 0; |
260 | 9.97k | } |
261 | | |
262 | | static int decode_frame(AVCodecContext * avctx, AVFrame *frame, |
263 | | int *got_frame, AVPacket *avpkt) |
264 | 921k | { |
265 | 921k | KmvcContext *const ctx = avctx->priv_data; |
266 | 921k | uint8_t *out, *src; |
267 | 921k | int i, ret; |
268 | 921k | int header; |
269 | 921k | int blocksize; |
270 | | |
271 | 921k | bytestream2_init(&ctx->g, avpkt->data, avpkt->size); |
272 | | |
273 | 921k | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
274 | 37.3k | return ret; |
275 | | |
276 | 884k | ff_copy_palette(ctx->pal, avpkt, avctx); |
277 | | |
278 | 884k | header = bytestream2_get_byte(&ctx->g); |
279 | | |
280 | | /* blocksize 127 is really palette change event */ |
281 | 884k | if (bytestream2_peek_byte(&ctx->g) == 127) { |
282 | 1.76k | bytestream2_skip(&ctx->g, 3); |
283 | 225k | for (i = 0; i < 127; i++) { |
284 | 223k | ctx->pal[i + (header & 0x81)] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); |
285 | 223k | bytestream2_skip(&ctx->g, 1); |
286 | 223k | } |
287 | 1.76k | bytestream2_seek(&ctx->g, -127 * 4 - 3, SEEK_CUR); |
288 | 1.76k | } |
289 | | |
290 | 884k | if (header & KMVC_KEYFRAME) { |
291 | 719k | frame->flags |= AV_FRAME_FLAG_KEY; |
292 | 719k | frame->pict_type = AV_PICTURE_TYPE_I; |
293 | 719k | } else { |
294 | 165k | frame->flags &= ~AV_FRAME_FLAG_KEY; |
295 | 165k | frame->pict_type = AV_PICTURE_TYPE_P; |
296 | 165k | } |
297 | | |
298 | 884k | if (header & KMVC_PALETTE) { |
299 | | // palette starts from index 1 and has 127 entries |
300 | 86.2M | for (i = 1; i <= ctx->palsize; i++) { |
301 | 85.5M | ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); |
302 | 85.5M | } |
303 | 749k | } |
304 | | |
305 | 884k | if (ctx->setpal) { |
306 | 1 | ctx->setpal = 0; |
307 | 1 | } |
308 | | |
309 | | /* make the palette available on the way out */ |
310 | 884k | memcpy(frame->data[1], ctx->pal, 1024); |
311 | | |
312 | 884k | blocksize = bytestream2_get_byte(&ctx->g); |
313 | | |
314 | 884k | if (blocksize != 8 && blocksize != 127) { |
315 | 772k | av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize); |
316 | 772k | return AVERROR_INVALIDDATA; |
317 | 772k | } |
318 | 111k | memset(ctx->cur, 0, 320 * 200); |
319 | 111k | switch (header & KMVC_METHOD) { |
320 | 465 | case 0: |
321 | 724 | case 1: // used in palette changed event |
322 | 724 | memcpy(ctx->cur, ctx->prev, 320 * 200); |
323 | 724 | break; |
324 | 100k | case 3: |
325 | 100k | kmvc_decode_intra_8x8(ctx, avctx->width, avctx->height); |
326 | 100k | break; |
327 | 9.97k | case 4: |
328 | 9.97k | kmvc_decode_inter_8x8(ctx, avctx->width, avctx->height); |
329 | 9.97k | break; |
330 | 371 | default: |
331 | 371 | av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD); |
332 | 371 | return AVERROR_INVALIDDATA; |
333 | 111k | } |
334 | | |
335 | 111k | out = frame->data[0]; |
336 | 111k | src = ctx->cur; |
337 | 16.3M | for (i = 0; i < avctx->height; i++) { |
338 | 16.2M | memcpy(out, src, avctx->width); |
339 | 16.2M | src += 320; |
340 | 16.2M | out += frame->linesize[0]; |
341 | 16.2M | } |
342 | | |
343 | | /* flip buffers */ |
344 | 111k | FFSWAP(uint8_t *, ctx->cur, ctx->prev); |
345 | | |
346 | 111k | *got_frame = 1; |
347 | | |
348 | | /* always report that the buffer was completely consumed */ |
349 | 111k | return avpkt->size; |
350 | 111k | } |
351 | | |
352 | | |
353 | | |
354 | | /* |
355 | | * Init kmvc decoder |
356 | | */ |
357 | | static av_cold int decode_init(AVCodecContext * avctx) |
358 | 1.19k | { |
359 | 1.19k | KmvcContext *const c = avctx->priv_data; |
360 | 1.19k | int i; |
361 | | |
362 | 1.19k | c->avctx = avctx; |
363 | | |
364 | 1.19k | if (avctx->width > 320 || avctx->height > 200) { |
365 | 33 | av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n"); |
366 | 33 | return AVERROR(EINVAL); |
367 | 33 | } |
368 | | |
369 | 1.15k | c->cur = c->frm0; |
370 | 1.15k | c->prev = c->frm1; |
371 | | |
372 | 297k | for (i = 0; i < 256; i++) { |
373 | 296k | c->pal[i] = 0xFFU << 24 | i * 0x10101; |
374 | 296k | } |
375 | | |
376 | 1.15k | if (avctx->extradata_size < 12) { |
377 | 1.07k | av_log(avctx, AV_LOG_WARNING, |
378 | 1.07k | "Extradata missing, decoding may not work properly...\n"); |
379 | 1.07k | c->palsize = 127; |
380 | 1.07k | } else { |
381 | 81 | c->palsize = AV_RL16(avctx->extradata + 10); |
382 | 81 | if (c->palsize >= (unsigned)MAX_PALSIZE) { |
383 | 17 | c->palsize = 127; |
384 | 17 | av_log(avctx, AV_LOG_ERROR, "KMVC palette too large\n"); |
385 | 17 | return AVERROR_INVALIDDATA; |
386 | 17 | } |
387 | 81 | } |
388 | | |
389 | 1.14k | 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.14k | avctx->pix_fmt = AV_PIX_FMT_PAL8; |
399 | | |
400 | 1.14k | return 0; |
401 | 1.15k | } |
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 | | }; |