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
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 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
, const uint8_t * buf
,
51 BFIContext
*bfi
= avctx
->priv_data
;
52 uint8_t *dst
= bfi
->dst
;
53 uint8_t *src
, *dst_offset
, colour1
, colour2
;
54 uint8_t *frame_end
= bfi
->dst
+ avctx
->width
* avctx
->height
;
56 int i
, j
, height
= avctx
->height
;
58 if (bfi
->frame
.data
[0])
59 avctx
->release_buffer(avctx
, &bfi
->frame
);
61 bfi
->frame
.reference
= 1;
63 if (avctx
->get_buffer(avctx
, &bfi
->frame
) < 0) {
64 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
68 /* Set frame parameters and palette, if necessary */
69 if (!avctx
->frame_number
) {
70 bfi
->frame
.pict_type
= FF_I_TYPE
;
71 bfi
->frame
.key_frame
= 1;
72 /* Setting the palette */
73 if(avctx
->extradata_size
>768) {
74 av_log(NULL
, AV_LOG_ERROR
, "Palette is too large.\n");
77 pal
= (uint32_t *) bfi
->frame
.data
[1];
78 for (i
= 0; i
< avctx
->extradata_size
/ 3; i
++) {
81 for (j
= 0; j
< 3; j
++, shift
-= 8)
83 ((avctx
->extradata
[i
* 3 + j
] << 2) |
84 (avctx
->extradata
[i
* 3 + j
] >> 4)) << shift
;
87 bfi
->frame
.palette_has_changed
= 1;
89 bfi
->frame
.pict_type
= FF_P_TYPE
;
90 bfi
->frame
.key_frame
= 0;
93 buf
+= 4; //Unpacked size, not required.
95 while (dst
!= frame_end
) {
96 static const uint8_t lentab
[4]={0,2,0,1};
97 unsigned int byte
= *buf
++, offset
;
98 unsigned int code
= byte
>> 6;
99 unsigned int length
= byte
& ~0xC0;
101 /* Get length and offset(if required) */
104 length
= bytestream_get_byte(&buf
);
105 offset
= bytestream_get_le16(&buf
);
107 length
= bytestream_get_le16(&buf
);
108 if (code
== 2 && length
== 0)
113 offset
= bytestream_get_byte(&buf
);
116 /* Do boundary check */
117 if (dst
+ (length
<<lentab
[code
]) > frame_end
)
122 case 0: //Normal Chain
123 bytestream_get_buffer(&buf
, dst
, length
);
128 dst_offset
= dst
- offset
;
129 length
*= 4; //Convert dwords to bytes.
130 if (dst_offset
< bfi
->dst
)
133 *dst
++ = *dst_offset
++;
141 colour1
= bytestream_get_byte(&buf
);
142 colour2
= bytestream_get_byte(&buf
);
153 dst
= bfi
->frame
.data
[0];
155 memcpy(dst
, src
, avctx
->width
);
157 dst
+= bfi
->frame
.linesize
[0];
159 *data_size
= sizeof(AVFrame
);
160 *(AVFrame
*) data
= bfi
->frame
;
164 static int bfi_decode_close(AVCodecContext
* avctx
)
166 BFIContext
*bfi
= avctx
->priv_data
;
167 if (bfi
->frame
.data
[0])
168 avctx
->release_buffer(avctx
, &bfi
->frame
);
173 AVCodec bfi_decoder
= {
175 .type
= CODEC_TYPE_VIDEO
,
177 .priv_data_size
= sizeof(BFIContext
),
178 .init
= bfi_decode_init
,
179 .close
= bfi_decode_close
,
180 .decode
= bfi_decode_frame
,
181 .long_name
= "Brute Force & Ignorance",