2 * Brute Force & Ignorance (BFI) video decoder
3 * Copyright (c) 2008 Sisir Koppaka
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 * @brief Brute Force & Ignorance (.bfi) video decoder
25 * @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
26 * @see http://wiki.multimedia.cx/index.php?title=BFI
29 #include "libavutil/common.h"
31 #include "bytestream.h"
34 typedef struct BFIContext
{
35 AVCodecContext
*avctx
;
40 static av_cold
int bfi_decode_init(AVCodecContext
*avctx
)
42 BFIContext
*bfi
= avctx
->priv_data
;
43 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
44 bfi
->dst
= av_mallocz(avctx
->width
* avctx
->height
);
48 static int bfi_decode_frame(AVCodecContext
*avctx
, void *data
,
49 int *got_frame
, AVPacket
*avpkt
)
52 int buf_size
= avpkt
->size
;
53 BFIContext
*bfi
= avctx
->priv_data
;
54 uint8_t *dst
= bfi
->dst
;
55 uint8_t *src
, *dst_offset
, colour1
, colour2
;
56 uint8_t *frame_end
= bfi
->dst
+ avctx
->width
* avctx
->height
;
58 int i
, j
, ret
, height
= avctx
->height
;
60 if (bfi
->frame
.data
[0])
61 avctx
->release_buffer(avctx
, &bfi
->frame
);
63 bfi
->frame
.reference
= 1;
65 if ((ret
= ff_get_buffer(avctx
, &bfi
->frame
)) < 0) {
66 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
70 bytestream2_init(&g
, avpkt
->data
, buf_size
);
72 /* Set frame parameters and palette, if necessary */
73 if (!avctx
->frame_number
) {
74 bfi
->frame
.pict_type
= AV_PICTURE_TYPE_I
;
75 bfi
->frame
.key_frame
= 1;
76 /* Setting the palette */
77 if (avctx
->extradata_size
> 768) {
78 av_log(NULL
, AV_LOG_ERROR
, "Palette is too large.\n");
79 return AVERROR_INVALIDDATA
;
81 pal
= (uint32_t *)bfi
->frame
.data
[1];
82 for (i
= 0; i
< avctx
->extradata_size
/ 3; i
++) {
85 for (j
= 0; j
< 3; j
++, shift
-= 8)
86 *pal
+= ((avctx
->extradata
[i
* 3 + j
] << 2) |
87 (avctx
->extradata
[i
* 3 + j
] >> 4)) << shift
;
90 bfi
->frame
.palette_has_changed
= 1;
92 bfi
->frame
.pict_type
= AV_PICTURE_TYPE_P
;
93 bfi
->frame
.key_frame
= 0;
96 bytestream2_skip(&g
, 4); // Unpacked size, not required.
98 while (dst
!= frame_end
) {
99 static const uint8_t lentab
[4] = { 0, 2, 0, 1 };
100 unsigned int byte
= bytestream2_get_byte(&g
), av_uninit(offset
);
101 unsigned int code
= byte
>> 6;
102 unsigned int length
= byte
& ~0xC0;
104 if (!bytestream2_get_bytes_left(&g
)) {
105 av_log(avctx
, AV_LOG_ERROR
,
106 "Input resolution larger than actual frame.\n");
107 return AVERROR_INVALIDDATA
;
110 /* Get length and offset (if required) */
113 length
= bytestream2_get_byte(&g
);
114 offset
= bytestream2_get_le16(&g
);
116 length
= bytestream2_get_le16(&g
);
117 if (code
== 2 && length
== 0)
122 offset
= bytestream2_get_byte(&g
);
125 /* Do boundary check */
126 if (dst
+ (length
<< lentab
[code
]) > frame_end
)
130 case 0: // normal chain
131 if (length
>= bytestream2_get_bytes_left(&g
)) {
132 av_log(avctx
, AV_LOG_ERROR
, "Frame larger than buffer.\n");
133 return AVERROR_INVALIDDATA
;
135 bytestream2_get_buffer(&g
, dst
, length
);
138 case 1: // back chain
139 dst_offset
= dst
- offset
;
140 length
*= 4; // Convert dwords to bytes.
141 if (dst_offset
< bfi
->dst
)
144 *dst
++ = *dst_offset
++;
146 case 2: // skip chain
149 case 3: // fill chain
150 colour1
= bytestream2_get_byte(&g
);
151 colour2
= bytestream2_get_byte(&g
);
161 dst
= bfi
->frame
.data
[0];
163 memcpy(dst
, src
, avctx
->width
);
165 dst
+= bfi
->frame
.linesize
[0];
168 *(AVFrame
*)data
= bfi
->frame
;
172 static av_cold
int bfi_decode_close(AVCodecContext
*avctx
)
174 BFIContext
*bfi
= avctx
->priv_data
;
175 if (bfi
->frame
.data
[0])
176 avctx
->release_buffer(avctx
, &bfi
->frame
);
181 AVCodec ff_bfi_decoder
= {
183 .type
= AVMEDIA_TYPE_VIDEO
,
184 .id
= AV_CODEC_ID_BFI
,
185 .priv_data_size
= sizeof(BFIContext
),
186 .init
= bfi_decode_init
,
187 .close
= bfi_decode_close
,
188 .decode
= bfi_decode_frame
,
189 .capabilities
= CODEC_CAP_DR1
,
190 .long_name
= NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),