Libav 0.7.1
|
00001 /* 00002 * Brute Force & Ignorance (BFI) demuxer 00003 * Copyright (c) 2008 Sisir Koppaka 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00029 #include "libavutil/intreadwrite.h" 00030 #include "avformat.h" 00031 00032 typedef struct BFIContext { 00033 int nframes; 00034 int audio_frame; 00035 int video_frame; 00036 int video_size; 00037 int avflag; 00038 } BFIContext; 00039 00040 static int bfi_probe(AVProbeData * p) 00041 { 00042 /* Check file header */ 00043 if (AV_RL32(p->buf) == MKTAG('B', 'F', '&', 'I')) 00044 return AVPROBE_SCORE_MAX; 00045 else 00046 return 0; 00047 } 00048 00049 static int bfi_read_header(AVFormatContext * s, AVFormatParameters * ap) 00050 { 00051 BFIContext *bfi = s->priv_data; 00052 AVIOContext *pb = s->pb; 00053 AVStream *vstream; 00054 AVStream *astream; 00055 int fps, chunk_header; 00056 00057 /* Initialize the video codec... */ 00058 vstream = av_new_stream(s, 0); 00059 if (!vstream) 00060 return AVERROR(ENOMEM); 00061 00062 /* Initialize the audio codec... */ 00063 astream = av_new_stream(s, 0); 00064 if (!astream) 00065 return AVERROR(ENOMEM); 00066 00067 /* Set the total number of frames. */ 00068 avio_skip(pb, 8); 00069 chunk_header = avio_rl32(pb); 00070 bfi->nframes = avio_rl32(pb); 00071 avio_rl32(pb); 00072 avio_rl32(pb); 00073 avio_rl32(pb); 00074 fps = avio_rl32(pb); 00075 avio_skip(pb, 12); 00076 vstream->codec->width = avio_rl32(pb); 00077 vstream->codec->height = avio_rl32(pb); 00078 00079 /*Load the palette to extradata */ 00080 avio_skip(pb, 8); 00081 vstream->codec->extradata = av_malloc(768); 00082 vstream->codec->extradata_size = 768; 00083 avio_read(pb, vstream->codec->extradata, 00084 vstream->codec->extradata_size); 00085 00086 astream->codec->sample_rate = avio_rl32(pb); 00087 00088 /* Set up the video codec... */ 00089 av_set_pts_info(vstream, 32, 1, fps); 00090 vstream->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00091 vstream->codec->codec_id = CODEC_ID_BFI; 00092 vstream->codec->pix_fmt = PIX_FMT_PAL8; 00093 00094 /* Set up the audio codec now... */ 00095 astream->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00096 astream->codec->codec_id = CODEC_ID_PCM_U8; 00097 astream->codec->channels = 1; 00098 astream->codec->bits_per_coded_sample = 8; 00099 astream->codec->bit_rate = 00100 astream->codec->sample_rate * astream->codec->bits_per_coded_sample; 00101 avio_seek(pb, chunk_header - 3, SEEK_SET); 00102 av_set_pts_info(astream, 64, 1, astream->codec->sample_rate); 00103 return 0; 00104 } 00105 00106 00107 static int bfi_read_packet(AVFormatContext * s, AVPacket * pkt) 00108 { 00109 BFIContext *bfi = s->priv_data; 00110 AVIOContext *pb = s->pb; 00111 int ret, audio_offset, video_offset, chunk_size, audio_size = 0; 00112 if (bfi->nframes == 0 || pb->eof_reached) { 00113 return AVERROR(EIO); 00114 } 00115 00116 /* If all previous chunks were completely read, then find a new one... */ 00117 if (!bfi->avflag) { 00118 uint32_t state = 0; 00119 while(state != MKTAG('S','A','V','I')){ 00120 if (pb->eof_reached) 00121 return AVERROR(EIO); 00122 state = 256*state + avio_r8(pb); 00123 } 00124 /* Now that the chunk's location is confirmed, we proceed... */ 00125 chunk_size = avio_rl32(pb); 00126 avio_rl32(pb); 00127 audio_offset = avio_rl32(pb); 00128 avio_rl32(pb); 00129 video_offset = avio_rl32(pb); 00130 audio_size = video_offset - audio_offset; 00131 bfi->video_size = chunk_size - video_offset; 00132 00133 //Tossing an audio packet at the audio decoder. 00134 ret = av_get_packet(pb, pkt, audio_size); 00135 if (ret < 0) 00136 return ret; 00137 00138 pkt->pts = bfi->audio_frame; 00139 bfi->audio_frame += ret; 00140 } 00141 00142 else { 00143 00144 //Tossing a video packet at the video decoder. 00145 ret = av_get_packet(pb, pkt, bfi->video_size); 00146 if (ret < 0) 00147 return ret; 00148 00149 pkt->pts = bfi->video_frame; 00150 bfi->video_frame += ret / bfi->video_size; 00151 00152 /* One less frame to read. A cursory decrement. */ 00153 bfi->nframes--; 00154 } 00155 00156 bfi->avflag = !bfi->avflag; 00157 pkt->stream_index = bfi->avflag; 00158 return ret; 00159 } 00160 00161 AVInputFormat ff_bfi_demuxer = { 00162 "bfi", 00163 NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"), 00164 sizeof(BFIContext), 00165 bfi_probe, 00166 bfi_read_header, 00167 bfi_read_packet, 00168 };