| 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 | */ |