6c55863e7de87b8717714c41aa8453410927fcbc
3 * Copyright (c) 2006 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Karl Morton's Video Codec decoder
31 #include "bytestream.h"
33 #define KMVC_KEYFRAME 0x80
34 #define KMVC_PALETTE 0x40
35 #define KMVC_METHOD 0x0F
40 typedef struct KmvcContext
{
41 AVCodecContext
*avctx
;
51 typedef struct BitBuf
{
56 #define BLK(data, x, y) data[(x) + (y) * 320]
58 #define kmvc_init_getbits(bb, src) bb.bits = 7; bb.bitbuf = *src++;
60 #define kmvc_getbit(bb, src, src_end, res) {\
62 if (bb.bitbuf & (1 << bb.bits)) res = 1; \
65 if (src >= src_end) { \
66 av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); \
67 return AVERROR_INVALIDDATA; \
74 static int kmvc_decode_intra_8x8(KmvcContext
* ctx
, const uint8_t * src
, int src_size
, int w
, int h
)
80 int l0x
, l1x
, l0y
, l1y
;
82 const uint8_t *src_end
= src
+ src_size
;
84 kmvc_init_getbits(bb
, src
);
86 for (by
= 0; by
< h
; by
+= 8)
87 for (bx
= 0; bx
< w
; bx
+= 8) {
88 kmvc_getbit(bb
, src
, src_end
, res
);
89 if (!res
) { // fill whole 8x8 block
91 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
92 return AVERROR_INVALIDDATA
;
95 for (i
= 0; i
< 64; i
++)
96 BLK(ctx
->cur
, bx
+ (i
& 0x7), by
+ (i
>> 3)) = val
;
97 } else { // handle four 4x4 subblocks
98 for (i
= 0; i
< 4; i
++) {
99 l0x
= bx
+ (i
& 1) * 4;
100 l0y
= by
+ (i
& 2) * 2;
101 kmvc_getbit(bb
, src
, src_end
, res
);
103 kmvc_getbit(bb
, src
, src_end
, res
);
104 if (!res
) { // fill whole 4x4 block
105 if (src
>= src_end
) {
106 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
107 return AVERROR_INVALIDDATA
;
110 for (j
= 0; j
< 16; j
++)
111 BLK(ctx
->cur
, l0x
+ (j
& 3), l0y
+ (j
>> 2)) = val
;
112 } else { // copy block from already decoded place
113 if (src
>= src_end
) {
114 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
115 return AVERROR_INVALIDDATA
;
120 for (j
= 0; j
< 16; j
++)
121 BLK(ctx
->cur
, l0x
+ (j
& 3), l0y
+ (j
>> 2)) =
122 BLK(ctx
->cur
, l0x
+ (j
& 3) - mx
, l0y
+ (j
>> 2) - my
);
124 } else { // descend to 2x2 sub-sub-blocks
125 for (j
= 0; j
< 4; j
++) {
126 l1x
= l0x
+ (j
& 1) * 2;
128 kmvc_getbit(bb
, src
, src_end
, res
);
130 kmvc_getbit(bb
, src
, src_end
, res
);
131 if (!res
) { // fill whole 2x2 block
132 if (src
>= src_end
) {
133 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
134 return AVERROR_INVALIDDATA
;
137 BLK(ctx
->cur
, l1x
, l1y
) = val
;
138 BLK(ctx
->cur
, l1x
+ 1, l1y
) = val
;
139 BLK(ctx
->cur
, l1x
, l1y
+ 1) = val
;
140 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) = val
;
141 } else { // copy block from already decoded place
142 if (src
>= src_end
) {
143 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
144 return AVERROR_INVALIDDATA
;
149 BLK(ctx
->cur
, l1x
, l1y
) = BLK(ctx
->cur
, l1x
- mx
, l1y
- my
);
150 BLK(ctx
->cur
, l1x
+ 1, l1y
) =
151 BLK(ctx
->cur
, l1x
+ 1 - mx
, l1y
- my
);
152 BLK(ctx
->cur
, l1x
, l1y
+ 1) =
153 BLK(ctx
->cur
, l1x
- mx
, l1y
+ 1 - my
);
154 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) =
155 BLK(ctx
->cur
, l1x
+ 1 - mx
, l1y
+ 1 - my
);
157 } else { // read values for block
158 BLK(ctx
->cur
, l1x
, l1y
) = *src
++;
159 BLK(ctx
->cur
, l1x
+ 1, l1y
) = *src
++;
160 BLK(ctx
->cur
, l1x
, l1y
+ 1) = *src
++;
161 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) = *src
++;
172 static int kmvc_decode_inter_8x8(KmvcContext
* ctx
, const uint8_t * src
, int src_size
, int w
, int h
)
178 int l0x
, l1x
, l0y
, l1y
;
180 const uint8_t *src_end
= src
+ src_size
;
182 kmvc_init_getbits(bb
, src
);
184 for (by
= 0; by
< h
; by
+= 8)
185 for (bx
= 0; bx
< w
; bx
+= 8) {
186 kmvc_getbit(bb
, src
, src_end
, res
);
188 kmvc_getbit(bb
, src
, src_end
, res
);
189 if (!res
) { // fill whole 8x8 block
190 if (src
>= src_end
) {
191 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
192 return AVERROR_INVALIDDATA
;
195 for (i
= 0; i
< 64; i
++)
196 BLK(ctx
->cur
, bx
+ (i
& 0x7), by
+ (i
>> 3)) = val
;
197 } else { // copy block from previous frame
198 for (i
= 0; i
< 64; i
++)
199 BLK(ctx
->cur
, bx
+ (i
& 0x7), by
+ (i
>> 3)) =
200 BLK(ctx
->prev
, bx
+ (i
& 0x7), by
+ (i
>> 3));
202 } else { // handle four 4x4 subblocks
203 for (i
= 0; i
< 4; i
++) {
204 l0x
= bx
+ (i
& 1) * 4;
205 l0y
= by
+ (i
& 2) * 2;
206 kmvc_getbit(bb
, src
, src_end
, res
);
208 kmvc_getbit(bb
, src
, src_end
, res
);
209 if (!res
) { // fill whole 4x4 block
210 if (src
>= src_end
) {
211 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
212 return AVERROR_INVALIDDATA
;
215 for (j
= 0; j
< 16; j
++)
216 BLK(ctx
->cur
, l0x
+ (j
& 3), l0y
+ (j
>> 2)) = val
;
217 } else { // copy block
218 if (src
>= src_end
) {
219 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
220 return AVERROR_INVALIDDATA
;
223 mx
= (val
& 0xF) - 8;
225 for (j
= 0; j
< 16; j
++)
226 BLK(ctx
->cur
, l0x
+ (j
& 3), l0y
+ (j
>> 2)) =
227 BLK(ctx
->prev
, l0x
+ (j
& 3) + mx
, l0y
+ (j
>> 2) + my
);
229 } else { // descend to 2x2 sub-sub-blocks
230 for (j
= 0; j
< 4; j
++) {
231 l1x
= l0x
+ (j
& 1) * 2;
233 kmvc_getbit(bb
, src
, src_end
, res
);
235 kmvc_getbit(bb
, src
, src_end
, res
);
236 if (!res
) { // fill whole 2x2 block
237 if (src
>= src_end
) {
238 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
239 return AVERROR_INVALIDDATA
;
242 BLK(ctx
->cur
, l1x
, l1y
) = val
;
243 BLK(ctx
->cur
, l1x
+ 1, l1y
) = val
;
244 BLK(ctx
->cur
, l1x
, l1y
+ 1) = val
;
245 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) = val
;
246 } else { // copy block
247 if (src
>= src_end
) {
248 av_log(ctx
->avctx
, AV_LOG_ERROR
, "Data overrun\n");
249 return AVERROR_INVALIDDATA
;
252 mx
= (val
& 0xF) - 8;
254 BLK(ctx
->cur
, l1x
, l1y
) = BLK(ctx
->prev
, l1x
+ mx
, l1y
+ my
);
255 BLK(ctx
->cur
, l1x
+ 1, l1y
) =
256 BLK(ctx
->prev
, l1x
+ 1 + mx
, l1y
+ my
);
257 BLK(ctx
->cur
, l1x
, l1y
+ 1) =
258 BLK(ctx
->prev
, l1x
+ mx
, l1y
+ 1 + my
);
259 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) =
260 BLK(ctx
->prev
, l1x
+ 1 + mx
, l1y
+ 1 + my
);
262 } else { // read values for block
263 BLK(ctx
->cur
, l1x
, l1y
) = *src
++;
264 BLK(ctx
->cur
, l1x
+ 1, l1y
) = *src
++;
265 BLK(ctx
->cur
, l1x
, l1y
+ 1) = *src
++;
266 BLK(ctx
->cur
, l1x
+ 1, l1y
+ 1) = *src
++;
277 static int decode_frame(AVCodecContext
* avctx
, void *data
, int *data_size
, AVPacket
*avpkt
)
279 const uint8_t *buf
= avpkt
->data
;
280 int buf_size
= avpkt
->size
;
281 KmvcContext
*const ctx
= avctx
->priv_data
;
286 const uint8_t *pal
= av_packet_get_side_data(avpkt
, AV_PKT_DATA_PALETTE
, NULL
);
288 if (ctx
->pic
.data
[0])
289 avctx
->release_buffer(avctx
, &ctx
->pic
);
291 ctx
->pic
.reference
= 1;
292 ctx
->pic
.buffer_hints
= FF_BUFFER_HINTS_VALID
;
293 if (avctx
->get_buffer(avctx
, &ctx
->pic
) < 0) {
294 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
300 /* blocksize 127 is really palette change event */
303 for (i
= 0; i
< 127; i
++) {
304 ctx
->pal
[i
+ (header
& 0x81)] = AV_RB24(buf
);
310 if (header
& KMVC_KEYFRAME
) {
311 ctx
->pic
.key_frame
= 1;
312 ctx
->pic
.pict_type
= AV_PICTURE_TYPE_I
;
314 ctx
->pic
.key_frame
= 0;
315 ctx
->pic
.pict_type
= AV_PICTURE_TYPE_P
;
318 if (header
& KMVC_PALETTE
) {
319 ctx
->pic
.palette_has_changed
= 1;
320 // palette starts from index 1 and has 127 entries
321 for (i
= 1; i
<= ctx
->palsize
; i
++) {
322 ctx
->pal
[i
] = bytestream_get_be24(&buf
);
327 ctx
->pic
.palette_has_changed
= 1;
328 memcpy(ctx
->pal
, pal
, AVPALETTE_SIZE
);
333 ctx
->pic
.palette_has_changed
= 1;
336 /* make the palette available on the way out */
337 memcpy(ctx
->pic
.data
[1], ctx
->pal
, 1024);
341 if (blocksize
!= 8 && blocksize
!= 127) {
342 av_log(avctx
, AV_LOG_ERROR
, "Block size = %i\n", blocksize
);
345 memset(ctx
->cur
, 0, 320 * 200);
346 switch (header
& KMVC_METHOD
) {
348 case 1: // used in palette changed event
349 memcpy(ctx
->cur
, ctx
->prev
, 320 * 200);
352 kmvc_decode_intra_8x8(ctx
, buf
, buf_size
, avctx
->width
, avctx
->height
);
355 kmvc_decode_inter_8x8(ctx
, buf
, buf_size
, avctx
->width
, avctx
->height
);
358 av_log(avctx
, AV_LOG_ERROR
, "Unknown compression method %i\n", header
& KMVC_METHOD
);
362 out
= ctx
->pic
.data
[0];
364 for (i
= 0; i
< avctx
->height
; i
++) {
365 memcpy(out
, src
, avctx
->width
);
367 out
+= ctx
->pic
.linesize
[0];
371 if (ctx
->cur
== ctx
->frm0
) {
372 ctx
->cur
= ctx
->frm1
;
373 ctx
->prev
= ctx
->frm0
;
375 ctx
->cur
= ctx
->frm0
;
376 ctx
->prev
= ctx
->frm1
;
379 *data_size
= sizeof(AVFrame
);
380 *(AVFrame
*) data
= ctx
->pic
;
382 /* always report that the buffer was completely consumed */
391 static av_cold
int decode_init(AVCodecContext
* avctx
)
393 KmvcContext
*const c
= avctx
->priv_data
;
398 if (avctx
->width
> 320 || avctx
->height
> 200) {
399 av_log(avctx
, AV_LOG_ERROR
, "KMVC supports frames <= 320x200\n");
403 c
->frm0
= av_mallocz(320 * 200);
404 c
->frm1
= av_mallocz(320 * 200);
408 for (i
= 0; i
< 256; i
++) {
409 c
->pal
[i
] = i
* 0x10101;
412 if (avctx
->extradata_size
< 12) {
413 av_log(NULL
, 0, "Extradata missing, decoding may not work properly...\n");
416 c
->palsize
= AV_RL16(avctx
->extradata
+ 10);
419 if (avctx
->extradata_size
== 1036) { // palette in extradata
420 uint8_t *src
= avctx
->extradata
+ 12;
421 for (i
= 0; i
< 256; i
++) {
422 c
->pal
[i
] = AV_RL32(src
);
428 avctx
->pix_fmt
= PIX_FMT_PAL8
;
436 * Uninit kmvc decoder
438 static av_cold
int decode_end(AVCodecContext
* avctx
)
440 KmvcContext
*const c
= avctx
->priv_data
;
445 avctx
->release_buffer(avctx
, &c
->pic
);
450 AVCodec ff_kmvc_decoder
= {
452 .type
= AVMEDIA_TYPE_VIDEO
,
454 .priv_data_size
= sizeof(KmvcContext
),
457 .decode
= decode_frame
,
458 .capabilities
= CODEC_CAP_DR1
,
459 .long_name
= NULL_IF_CONFIG_SMALL("Karl Morton's video codec"),