1/* 2 * FSB demuxer 3 * Copyright (c) 2015 Paul B Mahol 4 * 5 * This file is part of FFmpeg. 6 * 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. 11 * 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. 16 * 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 20 */ 21 22#include "libavutil/avassert.h" 23#include "libavutil/intreadwrite.h" 24#include "avformat.h" 25#include "avio.h" 26#include "internal.h" 27 28static int fsb_probe(const AVProbeData *p) 29{ 30 if (memcmp(p->buf, "FSB", 3) || p->buf[3] - '0' < 1 || p->buf[3] - '0' > 5) 31 return 0; 32 if (AV_RL32(p->buf + 4) != 1) 33 return 0; 34 return AVPROBE_SCORE_MAX; 35} 36 37static int fsb_read_header(AVFormatContext *s) 38{ 39 AVIOContext *pb = s->pb; 40 unsigned format, version, c; 41 int64_t offset; 42 AVCodecParameters *par; 43 AVStream *st = avformat_new_stream(s, NULL); 44 int ret; 45 46 avio_skip(pb, 3); // "FSB" 47 version = avio_r8(pb) - '0'; 48 if (version != 4 && version != 3) { 49 avpriv_request_sample(s, "version %d", version); 50 return AVERROR_PATCHWELCOME; 51 } 52 53 avio_skip(pb, 4); 54 55 if (!st) 56 return AVERROR(ENOMEM); 57 par = st->codecpar; 58 par->codec_type = AVMEDIA_TYPE_AUDIO; 59 par->codec_tag = 0; 60 61 if (version == 3) { 62 offset = avio_rl32(pb) + 0x18; 63 avio_skip(pb, 44); 64 st->duration = avio_rl32(pb); 65 avio_skip(pb, 12); 66 format = avio_rl32(pb); 67 par->sample_rate = avio_rl32(pb); 68 if (par->sample_rate <= 0) 69 return AVERROR_INVALIDDATA; 70 avio_skip(pb, 6); 71 par->ch_layout.nb_channels = avio_rl16(pb); 72 if (!par->ch_layout.nb_channels) 73 return AVERROR_INVALIDDATA; 74 75 if (format & 0x00000100) { 76 par->codec_id = AV_CODEC_ID_PCM_S16LE; 77 par->block_align = 4096 * par->ch_layout.nb_channels; 78 } else if (format & 0x00400000) { 79 par->bits_per_coded_sample = 4; 80 par->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV; 81 par->block_align = 36 * par->ch_layout.nb_channels; 82 } else if (format & 0x00800000) { 83 par->codec_id = AV_CODEC_ID_ADPCM_PSX; 84 par->block_align = 16 * par->ch_layout.nb_channels; 85 } else if (format & 0x02000000) { 86 par->codec_id = AV_CODEC_ID_ADPCM_THP; 87 par->block_align = 8 * par->ch_layout.nb_channels; 88 if (par->ch_layout.nb_channels > INT_MAX / 32) 89 return AVERROR_INVALIDDATA; 90 ret = ff_alloc_extradata(par, 32 * par->ch_layout.nb_channels); 91 if (ret < 0) 92 return ret; 93 avio_seek(pb, 0x68, SEEK_SET); 94 for (c = 0; c < par->ch_layout.nb_channels; c++) { 95 avio_read(pb, par->extradata + 32 * c, 32); 96 avio_skip(pb, 14); 97 } 98 } else { 99 avpriv_request_sample(s, "format 0x%X", format); 100 return AVERROR_PATCHWELCOME; 101 } 102 } else if (version == 4) { 103 offset = avio_rl32(pb) + 0x30; 104 avio_skip(pb, 80); 105 st->duration = avio_rl32(pb); 106 107 format = avio_rb32(pb); 108 switch(format) { 109 case 0x40001001: 110 case 0x00001005: 111 case 0x40001081: 112 case 0x40200001: 113 par->codec_id = AV_CODEC_ID_XMA2; 114 break; 115 case 0x40000802: 116 par->codec_id = AV_CODEC_ID_ADPCM_THP; 117 break; 118 default: 119 avpriv_request_sample(s, "format 0x%X", format); 120 return AVERROR_PATCHWELCOME; 121 } 122 123 par->sample_rate = avio_rl32(pb); 124 if (par->sample_rate <= 0) 125 return AVERROR_INVALIDDATA; 126 avio_skip(pb, 6); 127 128 par->ch_layout.nb_channels = avio_rl16(pb); 129 if (!par->ch_layout.nb_channels) 130 return AVERROR_INVALIDDATA; 131 132 switch (par->codec_id) { 133 case AV_CODEC_ID_XMA2: 134 ret = ff_alloc_extradata(par, 34); 135 if (ret < 0) 136 return ret; 137 memset(par->extradata, 0, 34); 138 par->block_align = 2048; 139 break; 140 case AV_CODEC_ID_ADPCM_THP: 141 if (par->ch_layout.nb_channels > INT_MAX / 32) 142 return AVERROR_INVALIDDATA; 143 ret = ff_alloc_extradata(par, 32 * par->ch_layout.nb_channels); 144 if (ret < 0) 145 return ret; 146 avio_seek(pb, 0x80, SEEK_SET); 147 for (c = 0; c < par->ch_layout.nb_channels; c++) { 148 avio_read(pb, par->extradata + 32 * c, 32); 149 avio_skip(pb, 14); 150 } 151 par->block_align = 8 * par->ch_layout.nb_channels; 152 break; 153 } 154 } else { 155 av_assert0(0); 156 } 157 158 avio_skip(pb, offset - avio_tell(pb)); 159 ffformatcontext(s)->data_offset = avio_tell(pb); 160 161 avpriv_set_pts_info(st, 64, 1, par->sample_rate); 162 163 return 0; 164} 165 166static int fsb_read_packet(AVFormatContext *s, AVPacket *pkt) 167{ 168 AVCodecParameters *par = s->streams[0]->codecpar; 169 int64_t pos; 170 int ret; 171 172 if (avio_feof(s->pb)) 173 return AVERROR_EOF; 174 175 pos = avio_tell(s->pb); 176 if (par->codec_id == AV_CODEC_ID_ADPCM_THP && 177 par->ch_layout.nb_channels > 1) { 178 int i, ch; 179 180 ret = av_new_packet(pkt, par->block_align); 181 if (ret < 0) 182 return ret; 183 for (i = 0; i < 4; i++) { 184 for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { 185 pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb); 186 pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb); 187 } 188 } 189 ret = 0; 190 } else { 191 ret = av_get_packet(s->pb, pkt, par->block_align); 192 } 193 194 if (par->codec_id == AV_CODEC_ID_XMA2 && pkt->size >= 1) 195 pkt->duration = (pkt->data[0] >> 2) * 512; 196 197 pkt->pos = pos; 198 pkt->stream_index = 0; 199 200 return ret; 201} 202 203const AVInputFormat ff_fsb_demuxer = { 204 .name = "fsb", 205 .long_name = NULL_IF_CONFIG_SMALL("FMOD Sample Bank"), 206 .read_probe = fsb_probe, 207 .read_header = fsb_read_header, 208 .read_packet = fsb_read_packet, 209 .extensions = "fsb", 210 .flags = AVFMT_GENERIC_INDEX, 211}; 212