460b9539 |
1 | /* This file is a subset of the debian source tarball of mpg321-0.2.10.3/mad.c |
2 | - see http://mpg321.sourceforge.net/ */ |
3 | |
4 | /* |
5 | mpg321 - a fully free clone of mpg123. |
6 | Copyright (C) 2001 Joe Drew |
7 | |
8 | Originally based heavily upon: |
9 | plaympeg - Sample MPEG player using the SMPEG library |
10 | Copyright (C) 1999 Loki Entertainment Software |
11 | |
12 | Also uses some code from |
13 | mad - MPEG audio decoder |
14 | Copyright (C) 2000-2001 Robert Leslie |
15 | |
16 | Original playlist code contributed by Tobias Bengtsson <tobbe@tobbe.nu> |
17 | |
18 | This program is free software; you can redistribute it and/or modify |
19 | it under the terms of the GNU General Public License as published by |
20 | the Free Software Foundation; either version 2 of the License, or |
21 | (at your option) any later version. |
22 | |
23 | This program is distributed in the hope that it will be useful, |
24 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 | GNU General Public License for more details. |
27 | |
28 | You should have received a copy of the GNU General Public License |
29 | along with this program; if not, write to the Free Software |
30 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
31 | */ |
32 | |
33 | #include <sys/types.h> |
34 | #include <string.h> |
35 | |
36 | #include <mad.h> |
37 | |
38 | #include "madshim.h" |
39 | |
40 | /* XING parsing is from the MAD winamp input plugin */ |
41 | |
42 | struct xing { |
43 | int flags; |
44 | unsigned long frames; |
45 | unsigned long bytes; |
46 | unsigned char toc[100]; |
47 | long scale; |
48 | }; |
49 | |
50 | enum { |
51 | XING_FRAMES = 0x0001, |
52 | XING_BYTES = 0x0002, |
53 | XING_TOC = 0x0004, |
54 | XING_SCALE = 0x0008 |
55 | }; |
56 | |
57 | # define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g') |
58 | |
59 | static |
60 | int parse_xing(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen) |
61 | { |
62 | if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC) |
63 | goto fail; |
64 | |
65 | xing->flags = mad_bit_read(&ptr, 32); |
66 | bitlen -= 64; |
67 | |
68 | if (xing->flags & XING_FRAMES) { |
69 | if (bitlen < 32) |
70 | goto fail; |
71 | |
72 | xing->frames = mad_bit_read(&ptr, 32); |
73 | bitlen -= 32; |
74 | } |
75 | |
76 | if (xing->flags & XING_BYTES) { |
77 | if (bitlen < 32) |
78 | goto fail; |
79 | |
80 | xing->bytes = mad_bit_read(&ptr, 32); |
81 | bitlen -= 32; |
82 | } |
83 | |
84 | if (xing->flags & XING_TOC) { |
85 | int i; |
86 | |
87 | if (bitlen < 800) |
88 | goto fail; |
89 | |
90 | for (i = 0; i < 100; ++i) |
91 | xing->toc[i] = mad_bit_read(&ptr, 8); |
92 | |
93 | bitlen -= 800; |
94 | } |
95 | |
96 | if (xing->flags & XING_SCALE) { |
97 | if (bitlen < 32) |
98 | goto fail; |
99 | |
100 | xing->scale = mad_bit_read(&ptr, 32); |
101 | bitlen -= 32; |
102 | } |
103 | |
104 | return 1; |
105 | |
106 | fail: |
107 | xing->flags = 0; |
108 | return 0; |
109 | } |
110 | |
111 | /* Following two functions are adapted from mad_timer, from the |
112 | libmad distribution */ |
113 | void scan_mp3(void const *ptr, ssize_t len, buffer *buf) |
114 | { |
115 | struct mad_stream stream; |
116 | struct mad_header header; |
117 | struct xing xing; |
118 | |
119 | unsigned long bitrate = 0; |
120 | int has_xing = 0; |
121 | int is_vbr = 0; |
122 | |
123 | memset(&xing, 0, sizeof xing); |
124 | |
125 | mad_stream_init(&stream); |
126 | mad_header_init(&header); |
127 | |
128 | mad_stream_buffer(&stream, ptr, len); |
129 | |
130 | buf->num_frames = 0; |
131 | |
132 | /* There are three ways of calculating the length of an mp3: |
133 | 1) Constant bitrate: One frame can provide the information |
134 | needed: # of frames and duration. Just see how long it |
135 | is and do the division. |
136 | 2) Variable bitrate: Xing tag. It provides the number of |
137 | frames. Each frame has the same number of samples, so |
138 | just use that. |
139 | 3) All: Count up the frames and duration of each frames |
140 | by decoding each one. We do this if we've no other |
141 | choice, i.e. if it's a VBR file with no Xing tag. |
142 | */ |
143 | |
144 | while (1) |
145 | { |
146 | if (mad_header_decode(&header, &stream) == -1) |
147 | { |
148 | if (MAD_RECOVERABLE(stream.error)) |
149 | continue; |
150 | else |
151 | break; |
152 | } |
153 | |
154 | /* Limit xing testing to the first frame header */ |
155 | if (!buf->num_frames++) |
156 | { |
157 | if(parse_xing(&xing, stream.anc_ptr, stream.anc_bitlen)) |
158 | { |
159 | is_vbr = 1; |
160 | |
161 | if (xing.flags & XING_FRAMES) |
162 | { |
163 | /* We use the Xing tag only for frames. If it doesn't have that |
164 | information, it's useless to us and we have to treat it as a |
165 | normal VBR file */ |
166 | has_xing = 1; |
167 | buf->num_frames = xing.frames; |
168 | break; |
169 | } |
170 | } |
171 | } |
172 | |
173 | /* Test the first n frames to see if this is a VBR file */ |
174 | if (!is_vbr && !(buf->num_frames > 20)) |
175 | { |
176 | if (bitrate && header.bitrate != bitrate) |
177 | { |
178 | is_vbr = 1; |
179 | } |
180 | |
181 | else |
182 | { |
183 | bitrate = header.bitrate; |
184 | } |
185 | } |
186 | |
187 | /* We have to assume it's not a VBR file if it hasn't already been |
188 | marked as one and we've checked n frames for different bitrates */ |
189 | else if (!is_vbr) |
190 | { |
191 | break; |
192 | } |
193 | |
194 | mad_timer_add(&buf->duration, header.duration); |
195 | } |
196 | |
197 | if (!is_vbr) |
198 | { |
199 | double time = (len * 8.0) / (header.bitrate); /* time in seconds */ |
200 | double timefrac = (double)time - ((long)(time)); |
201 | long nsamples = 32 * MAD_NSBSAMPLES(&header); /* samples per frame */ |
202 | |
203 | /* samplerate is a constant */ |
204 | buf->num_frames = (long) (time * header.samplerate / nsamples); |
205 | |
206 | mad_timer_set(&buf->duration, (long)time, (long)(timefrac*100), 100); |
207 | } |
208 | |
209 | else if (has_xing) |
210 | { |
211 | /* modify header.duration since we don't need it anymore */ |
212 | mad_timer_multiply(&header.duration, buf->num_frames); |
213 | buf->duration = header.duration; |
214 | } |
215 | |
216 | else |
217 | { |
218 | /* the durations have been added up, and the number of frames |
219 | counted. We do nothing here. */ |
220 | } |
221 | |
222 | mad_header_finish(&header); |
223 | mad_stream_finish(&stream); |
224 | } |
225 | |
226 | /* |
227 | Local Variables: |
228 | c-basic-offset:2 |
229 | comment-column:40 |
230 | End: |
231 | */ |