yading@11
|
1 /*
|
yading@11
|
2 * xWMA demuxer
|
yading@11
|
3 * Copyright (c) 2011 Max Horn
|
yading@11
|
4 *
|
yading@11
|
5 * This file is part of FFmpeg.
|
yading@11
|
6 *
|
yading@11
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
9 * License as published by the Free Software Foundation; either
|
yading@11
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
11 *
|
yading@11
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
15 * Lesser General Public License for more details.
|
yading@11
|
16 *
|
yading@11
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
20 */
|
yading@11
|
21
|
yading@11
|
22 #include <inttypes.h>
|
yading@11
|
23
|
yading@11
|
24 #include "avformat.h"
|
yading@11
|
25 #include "internal.h"
|
yading@11
|
26 #include "riff.h"
|
yading@11
|
27
|
yading@11
|
28 /*
|
yading@11
|
29 * Demuxer for xWMA, a Microsoft audio container used by XAudio 2.
|
yading@11
|
30 */
|
yading@11
|
31
|
yading@11
|
32 typedef struct {
|
yading@11
|
33 int64_t data_end;
|
yading@11
|
34 } XWMAContext;
|
yading@11
|
35
|
yading@11
|
36 static int xwma_probe(AVProbeData *p)
|
yading@11
|
37 {
|
yading@11
|
38 if (!memcmp(p->buf, "RIFF", 4) && !memcmp(p->buf + 8, "XWMA", 4))
|
yading@11
|
39 return AVPROBE_SCORE_MAX;
|
yading@11
|
40 return 0;
|
yading@11
|
41 }
|
yading@11
|
42
|
yading@11
|
43 static int xwma_read_header(AVFormatContext *s)
|
yading@11
|
44 {
|
yading@11
|
45 int64_t size;
|
yading@11
|
46 int ret;
|
yading@11
|
47 uint32_t dpds_table_size = 0;
|
yading@11
|
48 uint32_t *dpds_table = 0;
|
yading@11
|
49 unsigned int tag;
|
yading@11
|
50 AVIOContext *pb = s->pb;
|
yading@11
|
51 AVStream *st;
|
yading@11
|
52 XWMAContext *xwma = s->priv_data;
|
yading@11
|
53 int i;
|
yading@11
|
54
|
yading@11
|
55 /* The following code is mostly copied from wav.c, with some
|
yading@11
|
56 * minor alterations.
|
yading@11
|
57 */
|
yading@11
|
58
|
yading@11
|
59 /* check RIFF header */
|
yading@11
|
60 tag = avio_rl32(pb);
|
yading@11
|
61 if (tag != MKTAG('R', 'I', 'F', 'F'))
|
yading@11
|
62 return -1;
|
yading@11
|
63 avio_rl32(pb); /* file size */
|
yading@11
|
64 tag = avio_rl32(pb);
|
yading@11
|
65 if (tag != MKTAG('X', 'W', 'M', 'A'))
|
yading@11
|
66 return -1;
|
yading@11
|
67
|
yading@11
|
68 /* parse fmt header */
|
yading@11
|
69 tag = avio_rl32(pb);
|
yading@11
|
70 if (tag != MKTAG('f', 'm', 't', ' '))
|
yading@11
|
71 return -1;
|
yading@11
|
72 size = avio_rl32(pb);
|
yading@11
|
73 st = avformat_new_stream(s, NULL);
|
yading@11
|
74 if (!st)
|
yading@11
|
75 return AVERROR(ENOMEM);
|
yading@11
|
76
|
yading@11
|
77 ret = ff_get_wav_header(pb, st->codec, size);
|
yading@11
|
78 if (ret < 0)
|
yading@11
|
79 return ret;
|
yading@11
|
80 st->need_parsing = AVSTREAM_PARSE_NONE;
|
yading@11
|
81
|
yading@11
|
82 /* All xWMA files I have seen contained WMAv2 data. If there are files
|
yading@11
|
83 * using WMA Pro or some other codec, then we need to figure out the right
|
yading@11
|
84 * extradata for that. Thus, ask the user for feedback, but try to go on
|
yading@11
|
85 * anyway.
|
yading@11
|
86 */
|
yading@11
|
87 if (st->codec->codec_id != AV_CODEC_ID_WMAV2) {
|
yading@11
|
88 avpriv_request_sample(s, "Unexpected codec (tag 0x04%x; id %d)",
|
yading@11
|
89 st->codec->codec_tag, st->codec->codec_id);
|
yading@11
|
90 } else {
|
yading@11
|
91 /* In all xWMA files I have seen, there is no extradata. But the WMA
|
yading@11
|
92 * codecs require extradata, so we provide our own fake extradata.
|
yading@11
|
93 *
|
yading@11
|
94 * First, check that there really was no extradata in the header. If
|
yading@11
|
95 * there was, then try to use it, after asking the user to provide a
|
yading@11
|
96 * sample of this unusual file.
|
yading@11
|
97 */
|
yading@11
|
98 if (st->codec->extradata_size != 0) {
|
yading@11
|
99 /* Surprise, surprise: We *did* get some extradata. No idea
|
yading@11
|
100 * if it will work, but just go on and try it, after asking
|
yading@11
|
101 * the user for a sample.
|
yading@11
|
102 */
|
yading@11
|
103 avpriv_request_sample(s, "Unexpected extradata (%d bytes)",
|
yading@11
|
104 st->codec->extradata_size);
|
yading@11
|
105 } else {
|
yading@11
|
106 st->codec->extradata_size = 6;
|
yading@11
|
107 st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE);
|
yading@11
|
108 if (!st->codec->extradata)
|
yading@11
|
109 return AVERROR(ENOMEM);
|
yading@11
|
110
|
yading@11
|
111 /* setup extradata with our experimentally obtained value */
|
yading@11
|
112 st->codec->extradata[4] = 31;
|
yading@11
|
113 }
|
yading@11
|
114 }
|
yading@11
|
115
|
yading@11
|
116 if (!st->codec->channels) {
|
yading@11
|
117 av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n",
|
yading@11
|
118 st->codec->channels);
|
yading@11
|
119 return AVERROR_INVALIDDATA;
|
yading@11
|
120 }
|
yading@11
|
121 if (!st->codec->bits_per_coded_sample) {
|
yading@11
|
122 av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n",
|
yading@11
|
123 st->codec->bits_per_coded_sample);
|
yading@11
|
124 return AVERROR_INVALIDDATA;
|
yading@11
|
125 }
|
yading@11
|
126
|
yading@11
|
127 /* set the sample rate */
|
yading@11
|
128 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
|
yading@11
|
129
|
yading@11
|
130 /* parse the remaining RIFF chunks */
|
yading@11
|
131 for (;;) {
|
yading@11
|
132 if (pb->eof_reached)
|
yading@11
|
133 return -1;
|
yading@11
|
134 /* read next chunk tag */
|
yading@11
|
135 tag = avio_rl32(pb);
|
yading@11
|
136 size = avio_rl32(pb);
|
yading@11
|
137 if (tag == MKTAG('d', 'a', 't', 'a')) {
|
yading@11
|
138 /* We assume that the data chunk comes last. */
|
yading@11
|
139 break;
|
yading@11
|
140 } else if (tag == MKTAG('d','p','d','s')) {
|
yading@11
|
141 /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the
|
yading@11
|
142 * decoded packet cumulative data size array, each element is the
|
yading@11
|
143 * number of bytes accumulated after the corresponding xWMA packet
|
yading@11
|
144 * is decoded in order."
|
yading@11
|
145 *
|
yading@11
|
146 * Each packet has size equal to st->codec->block_align, which in
|
yading@11
|
147 * all cases I saw so far was always 2230. Thus, we can use the
|
yading@11
|
148 * dpds data to compute a seeking index.
|
yading@11
|
149 */
|
yading@11
|
150
|
yading@11
|
151 /* Error out if there is more than one dpds chunk. */
|
yading@11
|
152 if (dpds_table) {
|
yading@11
|
153 av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
|
yading@11
|
154 return -1;
|
yading@11
|
155 }
|
yading@11
|
156
|
yading@11
|
157 /* Compute the number of entries in the dpds chunk. */
|
yading@11
|
158 if (size & 3) { /* Size should be divisible by four */
|
yading@11
|
159 av_log(s, AV_LOG_WARNING,
|
yading@11
|
160 "dpds chunk size %"PRId64" not divisible by 4\n", size);
|
yading@11
|
161 }
|
yading@11
|
162 dpds_table_size = size / 4;
|
yading@11
|
163 if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) {
|
yading@11
|
164 av_log(s, AV_LOG_ERROR,
|
yading@11
|
165 "dpds chunk size %"PRId64" invalid\n", size);
|
yading@11
|
166 return -1;
|
yading@11
|
167 }
|
yading@11
|
168
|
yading@11
|
169 /* Allocate some temporary storage to keep the dpds data around.
|
yading@11
|
170 * for processing later on.
|
yading@11
|
171 */
|
yading@11
|
172 dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t));
|
yading@11
|
173 if (!dpds_table) {
|
yading@11
|
174 return AVERROR(ENOMEM);
|
yading@11
|
175 }
|
yading@11
|
176
|
yading@11
|
177 for (i = 0; i < dpds_table_size; ++i) {
|
yading@11
|
178 dpds_table[i] = avio_rl32(pb);
|
yading@11
|
179 size -= 4;
|
yading@11
|
180 }
|
yading@11
|
181 }
|
yading@11
|
182 avio_skip(pb, size);
|
yading@11
|
183 }
|
yading@11
|
184
|
yading@11
|
185 /* Determine overall data length */
|
yading@11
|
186 if (size < 0)
|
yading@11
|
187 return -1;
|
yading@11
|
188 if (!size) {
|
yading@11
|
189 xwma->data_end = INT64_MAX;
|
yading@11
|
190 } else
|
yading@11
|
191 xwma->data_end = avio_tell(pb) + size;
|
yading@11
|
192
|
yading@11
|
193
|
yading@11
|
194 if (dpds_table && dpds_table_size) {
|
yading@11
|
195 int64_t cur_pos;
|
yading@11
|
196 const uint32_t bytes_per_sample
|
yading@11
|
197 = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3;
|
yading@11
|
198
|
yading@11
|
199 /* Estimate the duration from the total number of output bytes. */
|
yading@11
|
200 const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
|
yading@11
|
201
|
yading@11
|
202 if(!bytes_per_sample) {
|
yading@11
|
203 av_log(s, AV_LOG_ERROR, "bytes_per_sample is 0\n");
|
yading@11
|
204 return AVERROR_INVALIDDATA;
|
yading@11
|
205 }
|
yading@11
|
206
|
yading@11
|
207 st->duration = total_decoded_bytes / bytes_per_sample;
|
yading@11
|
208
|
yading@11
|
209 /* Use the dpds data to build a seek table. We can only do this after
|
yading@11
|
210 * we know the offset to the data chunk, as we need that to determine
|
yading@11
|
211 * the actual offset to each input block.
|
yading@11
|
212 * Note: If we allowed ourselves to assume that the data chunk always
|
yading@11
|
213 * follows immediately after the dpds block, we could of course guess
|
yading@11
|
214 * the data block's start offset already while reading the dpds chunk.
|
yading@11
|
215 * I decided against that, just in case other chunks ever are
|
yading@11
|
216 * discovered.
|
yading@11
|
217 */
|
yading@11
|
218 cur_pos = avio_tell(pb);
|
yading@11
|
219 for (i = 0; i < dpds_table_size; ++i) {
|
yading@11
|
220 /* From the number of output bytes that would accumulate in the
|
yading@11
|
221 * output buffer after decoding the first (i+1) packets, we compute
|
yading@11
|
222 * an offset / timestamp pair.
|
yading@11
|
223 */
|
yading@11
|
224 av_add_index_entry(st,
|
yading@11
|
225 cur_pos + (i+1) * st->codec->block_align, /* pos */
|
yading@11
|
226 dpds_table[i] / bytes_per_sample, /* timestamp */
|
yading@11
|
227 st->codec->block_align, /* size */
|
yading@11
|
228 0, /* duration */
|
yading@11
|
229 AVINDEX_KEYFRAME);
|
yading@11
|
230 }
|
yading@11
|
231 } else if (st->codec->bit_rate) {
|
yading@11
|
232 /* No dpds chunk was present (or only an empty one), so estimate
|
yading@11
|
233 * the total duration using the average bits per sample and the
|
yading@11
|
234 * total data length.
|
yading@11
|
235 */
|
yading@11
|
236 st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
|
yading@11
|
237 }
|
yading@11
|
238
|
yading@11
|
239 av_free(dpds_table);
|
yading@11
|
240
|
yading@11
|
241 return 0;
|
yading@11
|
242 }
|
yading@11
|
243
|
yading@11
|
244 static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@11
|
245 {
|
yading@11
|
246 int ret, size;
|
yading@11
|
247 int64_t left;
|
yading@11
|
248 AVStream *st;
|
yading@11
|
249 XWMAContext *xwma = s->priv_data;
|
yading@11
|
250
|
yading@11
|
251 st = s->streams[0];
|
yading@11
|
252
|
yading@11
|
253 left = xwma->data_end - avio_tell(s->pb);
|
yading@11
|
254 if (left <= 0) {
|
yading@11
|
255 return AVERROR_EOF;
|
yading@11
|
256 }
|
yading@11
|
257
|
yading@11
|
258 /* read a single block; the default block size is 2230. */
|
yading@11
|
259 size = (st->codec->block_align > 1) ? st->codec->block_align : 2230;
|
yading@11
|
260 size = FFMIN(size, left);
|
yading@11
|
261
|
yading@11
|
262 ret = av_get_packet(s->pb, pkt, size);
|
yading@11
|
263 if (ret < 0)
|
yading@11
|
264 return ret;
|
yading@11
|
265
|
yading@11
|
266 pkt->stream_index = 0;
|
yading@11
|
267 return ret;
|
yading@11
|
268 }
|
yading@11
|
269
|
yading@11
|
270 AVInputFormat ff_xwma_demuxer = {
|
yading@11
|
271 .name = "xwma",
|
yading@11
|
272 .long_name = NULL_IF_CONFIG_SMALL("Microsoft xWMA"),
|
yading@11
|
273 .priv_data_size = sizeof(XWMAContext),
|
yading@11
|
274 .read_probe = xwma_probe,
|
yading@11
|
275 .read_header = xwma_read_header,
|
yading@11
|
276 .read_packet = xwma_read_packet,
|
yading@11
|
277 };
|