2 * Brute Force & Ignorance (BFI) demuxer
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) file demuxer
25 * @author Sisir Koppaka ( sisir.koppaka at gmail dot com )
26 * @see http://wiki.multimedia.cx/index.php?title=BFI
29 #include "libavutil/channel_layout.h"
30 #include "libavutil/intreadwrite.h"
34 typedef struct BFIContext
{
42 static int bfi_probe(AVProbeData
* p
)
44 /* Check file header */
45 if (AV_RL32(p
->buf
) == MKTAG('B', 'F', '&', 'I'))
46 return AVPROBE_SCORE_MAX
;
51 static int bfi_read_header(AVFormatContext
* s
)
53 BFIContext
*bfi
= s
->priv_data
;
54 AVIOContext
*pb
= s
->pb
;
57 int fps
, chunk_header
;
59 /* Initialize the video codec... */
60 vstream
= avformat_new_stream(s
, NULL
);
62 return AVERROR(ENOMEM
);
64 /* Initialize the audio codec... */
65 astream
= avformat_new_stream(s
, NULL
);
67 return AVERROR(ENOMEM
);
69 /* Set the total number of frames. */
71 chunk_header
= avio_rl32(pb
);
72 bfi
->nframes
= avio_rl32(pb
);
78 vstream
->codec
->width
= avio_rl32(pb
);
79 vstream
->codec
->height
= avio_rl32(pb
);
81 /*Load the palette to extradata */
83 vstream
->codec
->extradata
= av_malloc(768);
84 if (!vstream
->codec
->extradata
)
85 return AVERROR(ENOMEM
);
86 vstream
->codec
->extradata_size
= 768;
87 avio_read(pb
, vstream
->codec
->extradata
,
88 vstream
->codec
->extradata_size
);
90 astream
->codec
->sample_rate
= avio_rl32(pb
);
92 /* Set up the video codec... */
93 avpriv_set_pts_info(vstream
, 32, 1, fps
);
94 vstream
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
95 vstream
->codec
->codec_id
= AV_CODEC_ID_BFI
;
96 vstream
->codec
->pix_fmt
= AV_PIX_FMT_PAL8
;
98 vstream
->duration
= bfi
->nframes
;
100 /* Set up the audio codec now... */
101 astream
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
102 astream
->codec
->codec_id
= AV_CODEC_ID_PCM_U8
;
103 astream
->codec
->channels
= 1;
104 astream
->codec
->channel_layout
= AV_CH_LAYOUT_MONO
;
105 astream
->codec
->bits_per_coded_sample
= 8;
106 astream
->codec
->bit_rate
=
107 astream
->codec
->sample_rate
* astream
->codec
->bits_per_coded_sample
;
108 avio_seek(pb
, chunk_header
- 3, SEEK_SET
);
109 avpriv_set_pts_info(astream
, 64, 1, astream
->codec
->sample_rate
);
114 static int bfi_read_packet(AVFormatContext
* s
, AVPacket
* pkt
)
116 BFIContext
*bfi
= s
->priv_data
;
117 AVIOContext
*pb
= s
->pb
;
118 int ret
, audio_offset
, video_offset
, chunk_size
, audio_size
= 0;
119 if (bfi
->nframes
== 0 || avio_feof(pb
)) {
123 /* If all previous chunks were completely read, then find a new one... */
126 while(state
!= MKTAG('S','A','V','I')){
129 state
= 256*state
+ avio_r8(pb
);
131 /* Now that the chunk's location is confirmed, we proceed... */
132 chunk_size
= avio_rl32(pb
);
134 audio_offset
= avio_rl32(pb
);
136 video_offset
= avio_rl32(pb
);
137 audio_size
= video_offset
- audio_offset
;
138 bfi
->video_size
= chunk_size
- video_offset
;
139 if (audio_size
< 0 || bfi
->video_size
< 0) {
140 av_log(s
, AV_LOG_ERROR
, "Invalid audio/video offsets or chunk size\n");
141 return AVERROR_INVALIDDATA
;
144 //Tossing an audio packet at the audio decoder.
145 ret
= av_get_packet(pb
, pkt
, audio_size
);
149 pkt
->pts
= bfi
->audio_frame
;
150 bfi
->audio_frame
+= ret
;
151 } else if (bfi
->video_size
> 0) {
153 //Tossing a video packet at the video decoder.
154 ret
= av_get_packet(pb
, pkt
, bfi
->video_size
);
158 pkt
->pts
= bfi
->video_frame
;
159 bfi
->video_frame
+= ret
/ bfi
->video_size
;
161 /* One less frame to read. A cursory decrement. */
164 /* Empty video packet */
165 ret
= AVERROR(EAGAIN
);
168 bfi
->avflag
= !bfi
->avflag
;
169 pkt
->stream_index
= bfi
->avflag
;
173 AVInputFormat ff_bfi_demuxer
= {
175 .long_name
= NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"),
176 .priv_data_size
= sizeof(BFIContext
),
177 .read_probe
= bfi_probe
,
178 .read_header
= bfi_read_header
,
179 .read_packet
= bfi_read_packet
,