1 /**
2  *   (c) 2001-2006 Nathan Hjelm <hjelmn@users.sourceforge.net>
3  *   v1.5.0 mp3.c
4  *
5  *   MPEG file parser
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program 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
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  **/
21 
22 #include <string.h>
23 #include <errno.h>
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 
29 #include <sys/ioctl.h>
30 #include <sys/types.h>
31 #include <sys/uio.h>
32 #include <sys/stat.h>
33 
34 #include <time.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 
38 #include "rioi.h"
39 
40 #ifdef HAVE_LIBGEN_H
41 #include <libgen.h>
42 #endif
43 
44 
45 #define MP3_DEBUG 0
46 
47 #define MP3_PROTECTION_BIT 0x00010000
48 #define MP3_PADDING_BIT    0x00000200
49 
mp3_debug(char * format,...)50 void mp3_debug (char *format, ...) {
51 #if MP3_DEBUG==1
52   va_list arg;
53   va_start (arg, format);
54   vfprintf (stderr, format, arg);
55   va_end (arg);
56 #endif
57 }
58 
59 struct mp3_file {
60   FILE *fh;
61 
62   int file_size;  /* Bytes */
63   int tagv2_size; /* Bytes */
64   int skippage;   /* Bytes */
65   int data_size;  /* Bytes */
66 
67   int vbr;
68   int bitrate;    /* bps */
69 
70   int initial_header;
71 
72   int frames;
73   int xdata_size;
74 
75   int layer;
76   int version;
77 
78   int samplerate; /* Hz */
79 
80   int length;     /* ms */
81   int mod_date;
82 };
83 
84 /* [version][layer][bitrate] */
85 int bitrate_table[4][4][16] = {
86   /* v2.5 */
87   {{-1, -1, -1, -1, -1. -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
88    {-1,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160, -1},
89    {-1,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160, -1},
90    {-1, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1}},
91 
92   /* NOTUSED */
93   {{-1, -1, -1, -1, -1. -1, -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
94    {-1, -1, -1, -1, -1. -1, -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
95    {-1, -1, -1, -1, -1. -1, -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
96    {-1, -1, -1, -1, -1. -1, -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1}},
97 
98   /* v2 */
99   {{-1, -1, -1, -1, -1. -1, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
100    {-1,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160, -1},
101    {-1,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160, -1},
102    {-1, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1}},
103 
104   /* v1 */
105   {{-1, -1, -1, -1,  -1.  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -1},
106    {-1, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1},
107    {-1, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, -1},
108    {-1, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1}},
109 
110 };
111 
112 int samplerate_table[4][4] = {
113   {11025, 12000,  8000, -1},
114   {   -1,    -1,    -1, -1},
115   {22050, 24000, 16000, -1},
116   {44100, 48000, 32000, -1}
117 };
118 
119 double version_table[] = {
120   2.5, -1.0, 2.0, 1.0
121 };
122 
123 size_t layer_table[] = {
124   -1, 3, 2, 1
125 };
126 
127 #define MPEG_VERSION(header) ((header & 0x00180000) >> 19)
128 #define MPEG_LAYER(header) ((header & 0x00060000) >> 17)
129 #define MPEG_BITRATEI(header) ((header & 0x0000f000) >> 12)
130 #define MPEG_SAMPLERATEI(header) ((header & 0x00000c00) >> 10)
131 #define MPEG_PADDING(header) ((header & 0x00000200) >> 9)
132 
133 #define BITRATE(header) bitrate_table[MPEG_VERSION(header)][MPEG_LAYER(header)][MPEG_BITRATEI(header)]
134 #define SAMPLERATE(header) samplerate_table[MPEG_VERSION(header)][MPEG_SAMPLERATEI(header)]
135 #define PADDING(header) ((MPEG_LAYER(header) == 0x3) ? 4 : 1)
136 
mpeg_frame_length(int header)137 static size_t mpeg_frame_length (int header) {
138   double bitrate = (double)BITRATE(header) * 1000.0;
139   double samplerate = (double)SAMPLERATE(header);
140   double padding = (double)MPEG_PADDING(header);
141   char layer = MPEG_LAYER(header);
142   size_t frame_length;
143 
144   if (layer == 0x11)
145     frame_length = 144.0 * bitrate/samplerate + padding;
146   else
147     frame_length = (12 * bitrate/samplerate + padding) * 4.0;
148 
149   return (size_t)((layer != 0x11) ? (144.0 * bitrate/samplerate + padding)
150 	  : (12 * bitrate/samplerate + padding) * 4.0);
151 }
152 
153 /* check_mp3_header: returns 0 on success */
check_mp3_header(int header)154 static int check_mp3_header (int header) {
155   if (((header & 0xffe00000) == 0xffe00000) &&
156       (MPEG_VERSION(header) > 0.0) && (BITRATE(header) > 0)
157       && (SAMPLERATE(header) > 0))
158     return 0;
159   else if (header == 0x4d4c4c54) /* MLLT */
160     return 2;
161   else
162     return 1;
163 }
164 
find_first_frame(struct mp3_file * mp3)165 static int find_first_frame (struct mp3_file *mp3) {
166   int header;
167   int buffer;
168   int ret;
169   mp3->skippage = 0;
170 
171   while (fread (&header, 4, 1, mp3->fh)) {
172     header = big32_2_arch32(header);
173 
174     /* MPEG-1 Layer III */
175     if ((ret = check_mp3_header (header)) == 0) {
176       /* Check for Xing frame and skip it */
177       fseek (mp3->fh, 32, SEEK_CUR);
178       fread (&buffer, 4, 1, mp3->fh);
179 
180       buffer = big32_2_arch32(buffer);
181 
182       if (buffer == ('X' << 24 | 'i' << 16 | 'n' << 8 | 'g') ) {
183 	int xstart = ftell (mp3->fh);
184 	int xflags;
185 
186 	/* an mp3 with an Xing header is ALWAYS vbr */
187 	mp3->vbr = 1;
188 
189 	fread (&xflags, 4, 1, mp3->fh);
190 
191 	mp3_debug ("Xing flags = %08x\n", xflags);
192 
193 	if (xflags & 0x00000001) {
194 	  fread (&buffer, 4, 1, mp3->fh);
195 	  mp3->frames = buffer;
196 
197 	  mp3_debug ("MPEG file has %i frames\n", mp3->frames);
198 	}
199 
200 	if (xflags & 0x00000002) {
201 	  fread (&buffer, 4, 1, mp3->fh);
202 	  mp3->xdata_size = buffer;
203 
204 	  mp3_debug ("MPEG file has %i bytes of data\n", mp3->xdata_size);
205 	}
206 
207 	fseek (mp3->fh, xstart, SEEK_SET);
208       }
209 
210       mp3->initial_header = header;
211 
212       mp3->samplerate = SAMPLERATE(header);
213 
214       mp3_debug ("Inital bitrate = %i\n", BITRATE(header));
215 
216       fseek (mp3->fh, -40, SEEK_CUR);
217       return 0;
218     } else if (ret == 2)
219       return -2;
220 
221     fseek (mp3->fh, -3, SEEK_CUR);
222     mp3->skippage++;
223   }
224 
225   return -1;
226 }
227 
228 
mp3_open(char * file_name,struct mp3_file * mp3)229 static int mp3_open (char *file_name, struct mp3_file *mp3) {
230   struct stat statinfo;
231 
232   char buffer[14];
233   int has_v1 = 0;
234 
235   mp3_debug ("mp3_open: Entering...\n");
236 
237   memset (mp3, 0 , sizeof (struct mp3_file));
238 
239   if (stat (file_name, &statinfo) < 0)
240     return -errno;
241 
242   mp3->file_size = mp3->data_size = statinfo.st_size;
243   mp3->mod_date  = statinfo.st_mtime;
244 
245   mp3->fh = fopen (file_name, "r");
246   if (mp3->fh == NULL)
247     return -errno;
248 
249   /* Adjust total_size if an id3v1 tag exists */
250   fseek (mp3->fh, -128, SEEK_END);
251   memset (buffer, 0, 5);
252 
253   fread (buffer, 1, 3, mp3->fh);
254   if (strncmp (buffer, "TAG", 3) == 0) {
255     mp3->data_size -= 128;
256 
257     has_v1 = 1;
258 
259     mp3_debug ("mp3_open: Found id3v1 tag.\n");
260   }
261   /*                                          */
262 
263   /* Check for Lyrics v2.00 */
264   fseek (mp3->fh, -9 - (has_v1 ? 128 : 0), SEEK_END);
265   memset (buffer, 0, 10);
266   fread (buffer, 1, 9, mp3->fh);
267 
268   if (strncmp (buffer, "LYRICS200", 9) == 0) {
269     int lyrics_size;
270     mp3_debug ("mp3_open: Found Lyrics v2.00\n");
271 
272     /* Get the size of the Lyrics */
273     fseek (mp3->fh, -15, SEEK_CUR);
274     memset (buffer, 0, 7);
275     fread (buffer, 1, 6, mp3->fh);
276 
277     /* Include the size if LYRICS200 (9) and the size field (6) */
278     lyrics_size = strtol (buffer, NULL, 10) + 15;
279     mp3->data_size -= lyrics_size;
280 
281     mp3_debug ("mp3_open: Lyrics are 0x%x Bytes in length.\n", lyrics_size);
282   }
283 
284   /* find and skip id3v2 tag if it exists */
285   fseek (mp3->fh, 0, SEEK_SET);
286   fread (buffer, 1, 14, mp3->fh);
287   mp3->tagv2_size = id3v2_size (buffer);
288 
289   fseek (mp3->fh, mp3->tagv2_size, SEEK_SET);
290 
291   mp3_debug ("mp3_open: id3v2 size: 0x%08x\n", mp3->tagv2_size);
292   /****************************************/
293 
294   mp3->vbr = 0;
295 
296   mp3_debug ("mp3_open: Complete\n");
297 
298   return find_first_frame (mp3);
299 }
300 
301 #define FRAME_COUNT 30
302 
mp3_scan(struct mp3_file * mp3)303 static int mp3_scan (struct mp3_file *mp3) {
304   int header;
305   int ret;
306   int frames = 0;
307   int last_bitrate = -1;
308   int total_framesize = 0;
309 
310   size_t bitrate;
311   int frame_size;
312 
313   mp3_debug ("mp3_scan: Entering...\n");
314 
315   if (mp3->frames == 0 || mp3->xdata_size == 0) {
316     while (ftell (mp3->fh) < mp3->data_size && (frames < FRAME_COUNT || mp3->vbr)) {
317       fread (&header, 4, 1, mp3->fh);
318 
319       header = big32_2_arch32 (header);
320 
321       if (check_mp3_header (header) != 0) {
322 	fseek (mp3->fh, -4, SEEK_CUR);
323 
324 	mp3_debug ("mp3_scan: Invalid header %08x %08x Bytes into the file.\n", header, ftell(mp3->fh));
325 
326 	if ((ret = find_first_frame (mp3)) == -1) {
327 	  mp3_debug ("mp3_scan: An error occured at line: %i\n", __LINE__);
328 
329 	  /* This is hack-ish, but there might be junk at the end of the file. */
330 
331 	  break;
332 	} else if (ret == -2) {
333 	  mp3_debug ("mp3_scan: Ran into MLLT frame.\n");
334 
335 	  mp3->data_size -= (mp3->file_size) - ftell (mp3->fh);
336 
337 	  break;
338 	}
339 
340 	continue;
341       }
342 
343       bitrate = BITRATE(header);
344 
345       if (!mp3->vbr && (last_bitrate != -1) && (bitrate != last_bitrate))
346 	mp3->vbr = 1;
347       else
348 	last_bitrate = bitrate;
349 
350       frame_size = mpeg_frame_length (header);
351       total_framesize += frame_size;
352       fseek (mp3->fh, frame_size - 4, SEEK_CUR);
353       frames++;
354     }
355 
356     if (frames == FRAME_COUNT) {
357       frames = (int)((double)((mp3->data_size - mp3->tagv2_size) * FRAME_COUNT) / (double)total_framesize);
358       total_framesize = mp3->data_size - mp3->tagv2_size;
359     }
360 
361     if (mp3->frames == 0)
362       mp3->frames = frames;
363 
364     if (mp3->xdata_size == 0)
365       mp3->xdata_size = total_framesize;
366   }
367 
368   mp3->length     = (int)((double)mp3->frames * 26.12245); /* each mpeg frame represents 26.12245ms */
369   mp3->bitrate    = (int)(((float)mp3->xdata_size * 8.0)/(float)mp3->length);
370 
371   mp3_debug ("mp3_scan: Finished scan. SampleRate: %i, BitRate: %i, Length: %i, Frames: %i.\n",
372 	     mp3->samplerate, mp3->bitrate, mp3->length, mp3->frames);
373 
374   if (mp3->samplerate <= 0 || mp3->bitrate <= 0 || mp3->length <= 0)
375     return -1;
376 
377   return 0;
378 }
379 
mp3_close(struct mp3_file * mp3)380 static void mp3_close (struct mp3_file *mp3) {
381   fclose (mp3->fh);
382 }
383 
get_mp3_info(char * file_name,rio_file_t * mp3_file)384 static int get_mp3_info (char *file_name, rio_file_t *mp3_file) {
385   struct mp3_file mp3;
386 
387   if (mp3_open (file_name, &mp3) < 0)
388     return -1;
389 
390   mp3_scan (&mp3);
391   mp3_close (&mp3);
392 
393   mp3_file->bit_rate    = mp3.bitrate << 7;
394   mp3_file->sample_rate = mp3.samplerate;
395   mp3_file->time        = mp3.length/1000;
396   mp3_file->size        = mp3.file_size;
397 
398   return mp3.skippage;
399 }
400 
401 
402 /*
403   mp3_info:
404     Function takes in a file name (MP3) and returns a
405   Info structure containing the amount of junk (in bytes)
406   and a compete Rio header struct.
407 */
mp3_info(info_page_t * newInfo,char * file_name)408 int mp3_info (info_page_t *newInfo, char *file_name){
409   rio_file_t *mp3_file = newInfo->data;
410 
411   int id3_version;
412   int mp3_header_offset;
413 
414   if ((mp3_header_offset = get_mp3_info(file_name, mp3_file)) < 0) {
415     free(mp3_file);
416     newInfo->data = NULL;
417     return -1;
418   }
419 
420   if ((id3_version = get_id3_info(file_name, mp3_file)) < 0) {
421     free(mp3_file);
422     newInfo->data = NULL;
423     return -1;
424   }
425 
426   /* the file that will be uploaded is smaller if there is junk */
427   if (mp3_header_offset > 0 && !(id3_version >= 2)) {
428       mp3_file->size -= mp3_header_offset;
429       newInfo->skip = mp3_header_offset;
430   } else
431     /* dont want to not copy the id3v2 tags */
432     newInfo->skip = 0;
433 
434   /* it is an mp3 all right, finish up the INFO structure */
435   mp3_file->bits     = 0x10000b11;
436   mp3_file->type     = TYPE_MP3;
437   mp3_file->foo4     = 0x00020000;
438 
439   return URIO_SUCCESS;
440 }
441