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 
fsb_probe(const AVProbeData * p)28 static 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 
fsb_read_header(AVFormatContext * s)37 static 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->channels    = avio_rl16(pb);
72         if (!par->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->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->channels;
82         } else if (format & 0x00800000) {
83             par->codec_id    = AV_CODEC_ID_ADPCM_PSX;
84             par->block_align = 16 * par->channels;
85         } else if (format & 0x02000000) {
86             par->codec_id    = AV_CODEC_ID_ADPCM_THP;
87             par->block_align = 8 * par->channels;
88             if (par->channels > INT_MAX / 32)
89                 return AVERROR_INVALIDDATA;
90             ret = ff_alloc_extradata(par, 32 * par->channels);
91             if (ret < 0)
92                 return ret;
93             avio_seek(pb, 0x68, SEEK_SET);
94             for (c = 0; c < par->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->channels    = avio_rl16(pb);
129         if (!par->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->channels > INT_MAX / 32)
142                 return AVERROR_INVALIDDATA;
143             ret = ff_alloc_extradata(par, 32 * par->channels);
144             if (ret < 0)
145                 return ret;
146             avio_seek(pb, 0x80, SEEK_SET);
147             for (c = 0; c < par->channels; c++) {
148                 avio_read(pb, par->extradata + 32 * c, 32);
149                 avio_skip(pb, 14);
150             }
151             par->block_align = 8 * par->channels;
152             break;
153         }
154     } else {
155         av_assert0(0);
156     }
157 
158     avio_skip(pb, offset - avio_tell(pb));
159     s->internal->data_offset = avio_tell(pb);
160 
161     avpriv_set_pts_info(st, 64, 1, par->sample_rate);
162 
163     return 0;
164 }
165 
fsb_read_packet(AVFormatContext * s,AVPacket * pkt)166 static 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->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->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 
203 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