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 * @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
);
46 return AVERROR(ENOMEM
);
50 static int bfi_decode_frame(AVCodecContext
*avctx
, void *data
,
51 int *got_frame
, AVPacket
*avpkt
)
53 AVFrame
*frame
= data
;
55 int buf_size
= avpkt
->size
;
56 BFIContext
*bfi
= avctx
->priv_data
;
57 uint8_t *dst
= bfi
->dst
;
58 uint8_t *src
, *dst_offset
, colour1
, colour2
;
59 uint8_t *frame_end
= bfi
->dst
+ avctx
->width
* avctx
->height
;
61 int i
, j
, ret
, height
= avctx
->height
;
63 if ((ret
= ff_get_buffer(avctx
, frame
, 0)) < 0)
66 bytestream2_init(&g
, avpkt
->data
, buf_size
);
68 /* Set frame parameters and palette, if necessary */
69 if (!avctx
->frame_number
) {
70 frame
->pict_type
= AV_PICTURE_TYPE_I
;
72 /* Setting the palette */
73 if (avctx
->extradata_size
> 768) {
74 av_log(NULL
, AV_LOG_ERROR
, "Palette is too large.\n");
75 return AVERROR_INVALIDDATA
;
77 pal
= (uint32_t *)frame
->data
[1];
78 for (i
= 0; i
< avctx
->extradata_size
/ 3; i
++) {
81 for (j
= 0; j
< 3; j
++, shift
-= 8)
82 *pal
+= ((avctx
->extradata
[i
* 3 + j
] << 2) |
83 (avctx
->extradata
[i
* 3 + j
] >> 4)) << shift
;
86 memcpy(bfi
->pal
, frame
->data
[1], sizeof(bfi
->pal
));
87 frame
->palette_has_changed
= 1;
89 frame
->pict_type
= AV_PICTURE_TYPE_P
;
91 frame
->palette_has_changed
= 0;
92 memcpy(frame
->data
[1], bfi
->pal
, sizeof(bfi
->pal
));
95 bytestream2_skip(&g
, 4); // Unpacked size, not required.
97 while (dst
!= frame_end
) {
98 static const uint8_t lentab
[4] = { 0, 2, 0, 1 };
99 unsigned int byte
= bytestream2_get_byte(&g
), av_uninit(offset
);
100 unsigned int code
= byte
>> 6;
101 unsigned int length
= byte
& ~0xC0;
103 if (!bytestream2_get_bytes_left(&g
)) {
104 av_log(avctx
, AV_LOG_ERROR
,
105 "Input resolution larger than actual frame.\n");
106 return AVERROR_INVALIDDATA
;
109 /* Get length and offset (if required) */
112 length
= bytestream2_get_byte(&g
);
113 offset
= bytestream2_get_le16(&g
);
115 length
= bytestream2_get_le16(&g
);
116 if (code
== 2 && length
== 0)
121 offset
= bytestream2_get_byte(&g
);
124 /* Do boundary check */
125 if (dst
+ (length
<< lentab
[code
]) > frame_end
)
129 case 0: // normal chain
130 if (length
>= bytestream2_get_bytes_left(&g
)) {
131 av_log(avctx
, AV_LOG_ERROR
, "Frame larger than buffer.\n");
132 return AVERROR_INVALIDDATA
;
134 bytestream2_get_buffer(&g
, dst
, length
);
137 case 1: // back chain
138 dst_offset
= dst
- offset
;
139 length
*= 4; // Convert dwords to bytes.
140 if (dst_offset
< bfi
->dst
)
143 *dst
++ = *dst_offset
++;
145 case 2: // skip chain
148 case 3: // fill chain
149 colour1
= bytestream2_get_byte(&g
);
150 colour2
= bytestream2_get_byte(&g
);
160 dst
= frame
->data
[0];
162 memcpy(dst
, src
, avctx
->width
);
164 dst
+= frame
->linesize
[0];
171 static av_cold
int bfi_decode_close(AVCodecContext
*avctx
)
173 BFIContext
*bfi
= avctx
->priv_data
;
178 AVCodec ff_bfi_decoder
= {
180 .long_name
= NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),
181 .type
= AVMEDIA_TYPE_VIDEO
,
182 .id
= AV_CODEC_ID_BFI
,
183 .priv_data_size
= sizeof(BFIContext
),
184 .init
= bfi_decode_init
,
185 .close
= bfi_decode_close
,
186 .decode
= bfi_decode_frame
,
187 .capabilities
= CODEC_CAP_DR1
,