2 * Brute Force & Ignorance (BFI) video decoder
3 * Copyright (c) 2008 Sisir Koppaka
5 * This file is part of FFmpeg.
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.
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.
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
23 * @file libavcodec/bfi.c
24 * @brief Brute Force & Ignorance (.bfi) video decoder
25 * @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
26 * @sa http://wiki.multimedia.cx/index.php?title=BFI
29 #include "libavutil/common.h"
31 #include "bytestream.h"
33 typedef struct BFIContext
{
34 AVCodecContext
*avctx
;
39 static av_cold
int bfi_decode_init(AVCodecContext
* avctx
)
41 BFIContext
*bfi
= avctx
->priv_data
;
42 avctx
->pix_fmt
= PIX_FMT_PAL8
;
43 bfi
->dst
= av_mallocz(avctx
->width
* avctx
->height
);
47 static int bfi_decode_frame(AVCodecContext
* avctx
, void *data
,
48 int *data_size
, AVPacket
*avpkt
)
50 const uint8_t *buf
= avpkt
->data
;
51 int buf_size
= avpkt
->size
;
52 BFIContext
*bfi
= avctx
->priv_data
;
53 uint8_t *dst
= bfi
->dst
;
54 uint8_t *src
, *dst_offset
, colour1
, colour2
;
55 uint8_t *frame_end
= bfi
->dst
+ avctx
->width
* avctx
->height
;
57 int i
, j
, height
= avctx
->height
;
59 if (bfi
->frame
.data
[0])
60 avctx
->release_buffer(avctx
, &bfi
->frame
);
62 bfi
->frame
.reference
= 1;
64 if (avctx
->get_buffer(avctx
, &bfi
->frame
) < 0) {
65 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
69 /* Set frame parameters and palette, if necessary */
70 if (!avctx
->frame_number
) {
71 bfi
->frame
.pict_type
= FF_I_TYPE
;
72 bfi
->frame
.key_frame
= 1;
73 /* Setting the palette */
74 if(avctx
->extradata_size
>768) {
75 av_log(NULL
, AV_LOG_ERROR
, "Palette is too large.\n");
78 pal
= (uint32_t *) bfi
->frame
.data
[1];
79 for (i
= 0; i
< avctx
->extradata_size
/ 3; i
++) {
82 for (j
= 0; j
< 3; j
++, shift
-= 8)
84 ((avctx
->extradata
[i
* 3 + j
] << 2) |
85 (avctx
->extradata
[i
* 3 + j
] >> 4)) << shift
;
88 bfi
->frame
.palette_has_changed
= 1;
90 bfi
->frame
.pict_type
= FF_P_TYPE
;
91 bfi
->frame
.key_frame
= 0;
94 buf
+= 4; //Unpacked size, not required.
96 while (dst
!= frame_end
) {
97 static const uint8_t lentab
[4]={0,2,0,1};
98 unsigned int byte
= *buf
++, av_uninit(offset
);
99 unsigned int code
= byte
>> 6;
100 unsigned int length
= byte
& ~0xC0;
102 /* Get length and offset(if required) */
105 length
= bytestream_get_byte(&buf
);
106 offset
= bytestream_get_le16(&buf
);
108 length
= bytestream_get_le16(&buf
);
109 if (code
== 2 && length
== 0)
114 offset
= bytestream_get_byte(&buf
);
117 /* Do boundary check */
118 if (dst
+ (length
<<lentab
[code
]) > frame_end
)
123 case 0: //Normal Chain
124 bytestream_get_buffer(&buf
, dst
, length
);
129 dst_offset
= dst
- offset
;
130 length
*= 4; //Convert dwords to bytes.
131 if (dst_offset
< bfi
->dst
)
134 *dst
++ = *dst_offset
++;
142 colour1
= bytestream_get_byte(&buf
);
143 colour2
= bytestream_get_byte(&buf
);
154 dst
= bfi
->frame
.data
[0];
156 memcpy(dst
, src
, avctx
->width
);
158 dst
+= bfi
->frame
.linesize
[0];
160 *data_size
= sizeof(AVFrame
);
161 *(AVFrame
*) data
= bfi
->frame
;
165 static av_cold
int bfi_decode_close(AVCodecContext
* avctx
)
167 BFIContext
*bfi
= avctx
->priv_data
;
168 if (bfi
->frame
.data
[0])
169 avctx
->release_buffer(avctx
, &bfi
->frame
);
174 AVCodec bfi_decoder
= {
176 .type
= CODEC_TYPE_VIDEO
,
178 .priv_data_size
= sizeof(BFIContext
),
179 .init
= bfi_decode_init
,
180 .close
= bfi_decode_close
,
181 .decode
= bfi_decode_frame
,
182 .capabilities
= CODEC_CAP_DR1
,
183 .long_name
= NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),