Browse code

BFI video decoder. Patch by Sisir Koppaka sisir koppaka gmail Original thread: [FFmpeg-devel] BFI video decoder Date: 04/17/2008 04:25 PM

Originally committed as revision 12890 to svn://svn.ffmpeg.org/ffmpeg/trunk

Sisir Koppaka authored on 2008/04/18 17:43:11
Showing 5 changed files
... ...
@@ -120,6 +120,7 @@ version <next>
120 120
 - 8SVX audio decoder
121 121
 - BFI demuxer
122 122
 - MAXIS EA XA (.xa) demuxer / decoder
123
+- BFI video decoder
123 124
 
124 125
 version 0.4.9-pre1:
125 126
 
... ...
@@ -137,7 +137,7 @@ different game cutscenes repacked for use with ScummVM.
137 137
 @tab Audio and video format used in some games by Entertainment Software Partners
138 138
 @item IFF @tab    @tab X
139 139
 @tab Interchange File Format
140
-@item BFI @tab    @tab
140
+@item BFI @tab    @tab X
141 141
 @tab Brute Force & Ignorance, used in Flash Traffic: City of Angels
142 142
 @end multitable
143 143
 
... ...
@@ -42,6 +42,7 @@ OBJS-$(CONFIG_ASV2_ENCODER)            += asv1.o mpeg12data.o
42 42
 OBJS-$(CONFIG_ATRAC3_DECODER)          += atrac3.o mdct.o fft.o
43 43
 OBJS-$(CONFIG_AVS_DECODER)             += avs.o
44 44
 OBJS-$(CONFIG_BETHSOFTVID_DECODER)     += bethsoftvideo.o
45
+OBJS-$(CONFIG_BFI_DECODER)             += bfi.o
45 46
 OBJS-$(CONFIG_BMP_DECODER)             += bmp.o
46 47
 OBJS-$(CONFIG_BMP_ENCODER)             += bmpenc.o
47 48
 OBJS-$(CONFIG_C93_DECODER)             += c93.o
... ...
@@ -66,6 +66,7 @@ void avcodec_register_all(void)
66 66
     REGISTER_ENCDEC  (ASV2, asv2);
67 67
     REGISTER_DECODER (AVS, avs);
68 68
     REGISTER_DECODER (BETHSOFTVID, bethsoftvid);
69
+    REGISTER_DECODER (BFI, bfi);
69 70
     REGISTER_ENCDEC  (BMP, bmp);
70 71
     REGISTER_DECODER (C93, c93);
71 72
     REGISTER_DECODER (CAVS, cavs);
72 73
new file mode 100644
... ...
@@ -0,0 +1,181 @@
0
+/*
1
+ * Brute Force & Ignorance (BFI) video decoder
2
+ * Copyright (c) 2008 Sisir Koppaka
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file bfi.c
23
+ * @brief Brute Force & Ignorance (.bfi) video decoder
24
+ * @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
25
+ * @sa http://wiki.multimedia.cx/index.php?title=BFI
26
+ */
27
+
28
+#include "avcodec.h"
29
+#include "common.h"
30
+#include "bytestream.h"
31
+
32
+typedef struct BFIContext {
33
+    AVCodecContext *avctx;
34
+    AVFrame frame;
35
+    uint8_t *dst;
36
+} BFIContext;
37
+
38
+static int bfi_decode_init(AVCodecContext * avctx)
39
+{
40
+    BFIContext *bfi = avctx->priv_data;
41
+    avctx->pix_fmt = PIX_FMT_PAL8;
42
+    bfi->dst = av_mallocz(avctx->width * avctx->height);
43
+    return 0;
44
+}
45
+
46
+static int bfi_decode_frame(AVCodecContext * avctx, void *data,
47
+                            int *data_size, const uint8_t * buf,
48
+                            int buf_size)
49
+{
50
+    BFIContext *bfi = avctx->priv_data;
51
+    uint8_t *dst = bfi->dst;
52
+    uint8_t *src, *dst_offset, colour1, colour2;
53
+    uint8_t *frame_end = bfi->dst + avctx->width * avctx->height;
54
+    uint32_t *pal;
55
+    int i, j, height = avctx->height;
56
+
57
+    if (bfi->frame.data[0])
58
+        avctx->release_buffer(avctx, &bfi->frame);
59
+
60
+    bfi->frame.reference = 1;
61
+
62
+    if (avctx->get_buffer(avctx, &bfi->frame) < 0) {
63
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
64
+        return -1;
65
+    }
66
+
67
+    /* Set frame parameters and palette, if necessary */
68
+    if (!avctx->frame_number) {
69
+        bfi->frame.pict_type = FF_I_TYPE;
70
+        bfi->frame.key_frame = 1;
71
+        /* Setting the palette */
72
+        if(avctx->extradata_size>768) {
73
+            av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");
74
+            return -1;
75
+        }
76
+        pal = (uint32_t *) bfi->frame.data[1];
77
+        for (i = 0; i < avctx->extradata_size / 3; i++) {
78
+            int shift = 16;
79
+            *pal = 0;
80
+            for (j = 0; j < 3; j++, shift -= 8)
81
+                *pal +=
82
+                    ((avctx->extradata[i * 3 + j] << 2) |
83
+                    (avctx->extradata[i * 3 + j] >> 4)) << shift;
84
+            pal++;
85
+        }
86
+        bfi->frame.palette_has_changed = 1;
87
+    } else {
88
+        bfi->frame.pict_type = FF_P_TYPE;
89
+        bfi->frame.key_frame = 0;
90
+    }
91
+
92
+    buf += 4; //Unpacked size, not required.
93
+
94
+    while (dst != frame_end) {
95
+        static const uint8_t lentab[4]={0,2,0,1};
96
+        unsigned int byte = *buf++, offset;
97
+        unsigned int code = byte >> 6;
98
+        unsigned int length = byte & ~0xC0;
99
+
100
+        /* Get length and offset(if required) */
101
+        if (length == 0) {
102
+            if (code == 1) {
103
+                length = bytestream_get_byte(&buf);
104
+                offset = bytestream_get_le16(&buf);
105
+            } else {
106
+                length = bytestream_get_le16(&buf);
107
+                if (code == 2 && length == 0)
108
+                    break;
109
+            }
110
+        } else {
111
+            if (code == 1)
112
+                offset = bytestream_get_byte(&buf);
113
+        }
114
+
115
+        /* Do boundary check */
116
+        if (dst + (length<<lentab[code]) > frame_end)
117
+            break;
118
+
119
+        switch (code) {
120
+
121
+        case 0:                //Normal Chain
122
+            bytestream_get_buffer(&buf, dst, length);
123
+            dst += length;
124
+            break;
125
+
126
+        case 1:                //Back Chain
127
+            dst_offset = dst - offset;
128
+            length *= 4;        //Convert dwords to bytes.
129
+            if (dst_offset < bfi->dst)
130
+                break;
131
+            while (length--)
132
+                *dst++ = *dst_offset++;
133
+            break;
134
+
135
+        case 2:                //Skip Chain
136
+            dst += length;
137
+            break;
138
+
139
+        case 3:                //Fill Chain
140
+            colour1 = bytestream_get_byte(&buf);
141
+            colour2 = bytestream_get_byte(&buf);
142
+            while (length--) {
143
+                *dst++ = colour1;
144
+                *dst++ = colour2;
145
+            }
146
+            break;
147
+
148
+        }
149
+    }
150
+
151
+    src = bfi->dst;
152
+    dst = bfi->frame.data[0];
153
+    while (height--) {
154
+        memcpy(dst, src, avctx->width);
155
+        src += avctx->width;
156
+        dst += bfi->frame.linesize[0];
157
+    }
158
+    *data_size = sizeof(AVFrame);
159
+    *(AVFrame *) data = bfi->frame;
160
+    return buf_size;
161
+}
162
+
163
+static int bfi_decode_close(AVCodecContext * avctx)
164
+{
165
+    BFIContext *bfi = avctx->priv_data;
166
+    if (bfi->frame.data[0])
167
+        avctx->release_buffer(avctx, &bfi->frame);
168
+    av_free(bfi->dst);
169
+    return 0;
170
+}
171
+
172
+AVCodec bfi_decoder = {
173
+    .name = "bfi",
174
+    .type = CODEC_TYPE_VIDEO,
175
+    .id = CODEC_ID_BFI,
176
+    .priv_data_size = sizeof(BFIContext),
177
+    .init = bfi_decode_init,
178
+    .close = bfi_decode_close,
179
+    .decode = bfi_decode_frame,
180
+};