1//=========================================================================
2// FILENAME	: tagutils-mp3.c
3// DESCRIPTION	: MP3 metadata reader
4//=========================================================================
5// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
6//=========================================================================
7
8/*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * This file is derived from mt-daap project.
25 */
26
27static int
28_get_mp3tags(char *file, struct song_metadata *psong)
29{
30	struct id3_file *pid3file;
31	struct id3_tag *pid3tag;
32	struct id3_frame *pid3frame;
33	int err;
34	int index;
35	int used;
36	unsigned char *utf8_text;
37	int genre = WINAMP_GENRE_UNKNOWN;
38	int have_utf8;
39	int have_text;
40	id3_ucs4_t const *native_text;
41	char *tmp;
42	int got_numeric_genre;
43	id3_byte_t const *image;
44	id3_length_t image_size = 0;
45
46	pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY);
47	if(!pid3file)
48	{
49		DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file);
50		return -1;
51	}
52
53	pid3tag = id3_file_tag(pid3file);
54
55	if(!pid3tag)
56	{
57		err = errno;
58		id3_file_close(pid3file);
59		errno = err;
60		DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file);
61		return -1;
62	}
63
64	index = 0;
65	while((pid3frame = id3_tag_findframe(pid3tag, "", index)))
66	{
67		used = 0;
68		utf8_text = NULL;
69		native_text = NULL;
70		have_utf8 = 0;
71		have_text = 0;
72
73		if(!strcmp(pid3frame->id, "YTCP"))   /* for id3v2.2 */
74		{
75			psong->compilation = 1;
76			DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file));
77		}
78		else if(!strcmp(pid3frame->id, "APIC") && !image_size)
79		{
80			if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) ||
81			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 0) ||
82			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) )
83			{
84				image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size);
85				if( image_size )
86				{
87					psong->image = malloc(image_size);
88					memcpy(psong->image, image, image_size);
89					psong->image_size = image_size;
90					//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size);
91				}
92			}
93		}
94
95		if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) &&
96		   (id3_field_getnstrings(&pid3frame->fields[1])))
97			have_text = 1;
98
99		if(have_text)
100		{
101			native_text = id3_field_getstrings(&pid3frame->fields[1], 0);
102
103			if(native_text)
104			{
105				have_utf8 = 1;
106				if(lang_index >= 0)
107					utf8_text = _get_utf8_text(native_text); // through iconv
108				else
109					utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
110
111				if(!strcmp(pid3frame->id, "TIT2"))
112				{
113					used = 1;
114					psong->title = (char*)utf8_text;
115				}
116				else if(!strcmp(pid3frame->id, "TPE1"))
117				{
118					used = 1;
119					psong->contributor[ROLE_ARTIST] = (char*)utf8_text;
120				}
121				else if(!strcmp(pid3frame->id, "TALB"))
122				{
123					used = 1;
124					psong->album = (char*)utf8_text;
125				}
126				else if(!strcmp(pid3frame->id, "TCOM"))
127				{
128					used = 1;
129					psong->contributor[ROLE_COMPOSER] = (char*)utf8_text;
130				}
131				else if(!strcmp(pid3frame->id, "TIT1"))
132				{
133					used = 1;
134					psong->grouping = (char*)utf8_text;
135				}
136				else if(!strcmp(pid3frame->id, "TPE2"))
137				{
138					used = 1;
139					psong->contributor[ROLE_BAND] = (char*)utf8_text;
140				}
141				else if(!strcmp(pid3frame->id, "TPE3"))
142				{
143					used = 1;
144					psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text;
145				}
146				else if(!strcmp(pid3frame->id, "TCON"))
147				{
148					used = 1;
149					psong->genre = (char*)utf8_text;
150					got_numeric_genre = 0;
151					if(psong->genre)
152					{
153						if(!strlen(psong->genre))
154						{
155							genre = WINAMP_GENRE_UNKNOWN;
156							got_numeric_genre = 1;
157						}
158						else if(isdigit(psong->genre[0]))
159						{
160							genre = atoi(psong->genre);
161							got_numeric_genre = 1;
162						}
163						else if((psong->genre[0] == '(') && (isdigit(psong->genre[1])))
164						{
165							genre = atoi((char*)&psong->genre[1]);
166							got_numeric_genre = 1;
167						}
168
169						if(got_numeric_genre)
170						{
171							if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
172								genre = WINAMP_GENRE_UNKNOWN;
173							free(psong->genre);
174							psong->genre = strdup(winamp_genre[genre]);
175						}
176					}
177				}
178				else if(!strcmp(pid3frame->id, "COMM"))
179				{
180					used = 1;
181					psong->comment = (char*)utf8_text;
182				}
183				else if(!strcmp(pid3frame->id, "TPOS"))
184				{
185					tmp = (char*)utf8_text;
186					strsep(&tmp, "/");
187					if(tmp)
188					{
189						psong->total_discs = atoi(tmp);
190					}
191					psong->disc = atoi((char*)utf8_text);
192				}
193				else if(!strcmp(pid3frame->id, "TRCK"))
194				{
195					tmp = (char*)utf8_text;
196					strsep(&tmp, "/");
197					if(tmp)
198					{
199						psong->total_tracks = atoi(tmp);
200					}
201					psong->track = atoi((char*)utf8_text);
202				}
203				else if(!strcmp(pid3frame->id, "TDRC"))
204				{
205					psong->year = atoi((char*)utf8_text);
206				}
207				else if(!strcmp(pid3frame->id, "TLEN"))
208				{
209					psong->song_length = atoi((char*)utf8_text);
210				}
211				else if(!strcmp(pid3frame->id, "TBPM"))
212				{
213					psong->bpm = atoi((char*)utf8_text);
214				}
215				else if(!strcmp(pid3frame->id, "TCMP"))
216				{
217					psong->compilation = (char)atoi((char*)utf8_text);
218				}
219			}
220		}
221
222		// check if text tag
223		if((!used) && (have_utf8) && (utf8_text))
224			free(utf8_text);
225
226		// v2 COMM
227		if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4))
228		{
229			native_text = id3_field_getstring(&pid3frame->fields[2]);
230			if(native_text)
231			{
232				utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
233				if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0))
234				{
235					// read comment
236					free(utf8_text);
237
238					native_text = id3_field_getfullstring(&pid3frame->fields[3]);
239					if(native_text)
240					{
241						utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
242						if(utf8_text)
243						{
244							free(psong->comment);
245							psong->comment = (char*)utf8_text;
246						}
247					}
248				}
249				else
250				{
251					free(utf8_text);
252				}
253			}
254		}
255
256		index++;
257	}
258
259	id3_file_close(pid3file);
260	//DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file);
261	return 0;
262}
263
264// _decode_mp3_frame
265static int
266_decode_mp3_frame(unsigned char *frame, struct mp3_frameinfo *pfi)
267{
268	int ver;
269	int layer_index;
270	int sample_index;
271	int bitrate_index;
272	int samplerate_index;
273
274	if((frame[0] != 0xFF) || (frame[1] < 224))
275	{
276		pfi->is_valid = 0;
277		return -1;
278	}
279
280	ver = (frame[1] & 0x18) >> 3;
281	pfi->layer = 4 - ((frame[1] & 0x6) >> 1);
282
283	layer_index = sample_index = -1;
284
285	switch(ver)
286	{
287	case 0:
288		pfi->mpeg_version = 0x25;       // 2.5
289		sample_index = 2;
290		if(pfi->layer == 1)
291			layer_index = 3;
292		if((pfi->layer == 2) || (pfi->layer == 3))
293			layer_index = 4;
294		break;
295	case 2:
296		pfi->mpeg_version = 0x20;       // 2.0
297		sample_index = 1;
298		if(pfi->layer == 1)
299			layer_index = 3;
300		if((pfi->layer == 2) || (pfi->layer == 3))
301			layer_index = 4;
302		break;
303	case 3:
304		pfi->mpeg_version = 0x10;       // 1.0
305		sample_index = 0;
306		if(pfi->layer == 1)
307			layer_index = 0;
308		if(pfi->layer == 2)
309			layer_index = 1;
310		if(pfi->layer == 3)
311			layer_index = 2;
312		break;
313	}
314
315	if((layer_index < 0) || (layer_index > 4))
316	{
317		pfi->is_valid = 0;
318		return -1;
319	}
320
321	if((sample_index < 0) || (sample_index >= 2))
322	{
323		pfi->is_valid = 0;
324		return -1;
325	}
326
327	if(pfi->layer == 1) pfi->samples_per_frame = 384;
328	if(pfi->layer == 2) pfi->samples_per_frame = 1152;
329	if(pfi->layer == 3)
330	{
331		if(pfi->mpeg_version == 0x10)
332			pfi->samples_per_frame = 1152;
333		else
334			pfi->samples_per_frame = 576;
335	}
336
337	bitrate_index = (frame[2] & 0xF0) >> 4;
338	samplerate_index = (frame[2] & 0x0C) >> 2;
339
340	if((bitrate_index == 0xF) || (bitrate_index == 0x0))
341	{
342		pfi->is_valid = 0;
343		return -1;
344	}
345
346	if(samplerate_index == 3)
347	{
348		pfi->is_valid = 0;
349		return -1;
350	}
351
352
353	pfi->bitrate = bitrate_tbl[layer_index][bitrate_index];
354	pfi->samplerate = sample_rate_tbl[sample_index][samplerate_index];
355
356	if((frame[3] & 0xC0 >> 6) == 3)
357		pfi->stereo = 0;
358	else
359		pfi->stereo = 1;
360
361	if(frame[2] & 0x02)
362		pfi->padding = 1;
363	else
364		pfi->padding = 0;
365
366	if(pfi->mpeg_version == 0x10)
367	{
368		if(pfi->stereo)
369			pfi->xing_offset = 32;
370		else
371			pfi->xing_offset = 17;
372	}
373	else
374	{
375		if(pfi->stereo)
376			pfi->xing_offset = 17;
377		else
378			pfi->xing_offset = 9;
379	}
380
381	pfi->crc_protected = frame[1] & 0xFE;
382
383	if(pfi->layer == 1)
384		pfi->frame_length = (12 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding) * 4;
385	else
386		pfi->frame_length = 144 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding;
387
388	if((pfi->frame_length > 2880) || (pfi->frame_length <= 0))
389	{
390		pfi->is_valid = 0;
391		return -1;
392	}
393
394	pfi->is_valid = 1;
395	return 0;
396}
397
398// _mp3_get_average_bitrate
399//    read from midle of file, and estimate
400static void _mp3_get_average_bitrate(FILE *infile, struct mp3_frameinfo *pfi, const char *fname)
401{
402	off_t file_size;
403	unsigned char frame_buffer[2900];
404	unsigned char header[4];
405	int index = 0;
406	int found = 0;
407	off_t pos;
408	struct mp3_frameinfo fi;
409	int frame_count = 0;
410	int bitrate_total = 0;
411
412	fseek(infile, 0, SEEK_END);
413	file_size = ftell(infile);
414
415	pos = file_size >> 1;
416
417	/* now, find the first frame */
418	fseek(infile, pos, SEEK_SET);
419	if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) != sizeof(frame_buffer))
420		return;
421
422	while(!found)
423	{
424		while((frame_buffer[index] != 0xFF) && (index < (sizeof(frame_buffer) - 4)))
425			index++;
426
427		if(index >= (sizeof(frame_buffer) - 4))   // max mp3 framesize = 2880
428		{
429			DPRINTF(E_DEBUG, L_SCANNER, "Could not find frame for %s\n", basename((char *)fname));
430			return;
431		}
432
433		if(!_decode_mp3_frame(&frame_buffer[index], &fi))
434		{
435			/* see if next frame is valid */
436			fseek(infile, pos + index + fi.frame_length, SEEK_SET);
437			if(fread(header, 1, sizeof(header), infile) != sizeof(header))
438			{
439				DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname));
440				return;
441			}
442
443			if(!_decode_mp3_frame(header, &fi))
444				found = 1;
445		}
446
447		if(!found)
448			index++;
449	}
450
451	pos += index;
452
453	// got first frame
454	while(frame_count < 10)
455	{
456		fseek(infile, pos, SEEK_SET);
457		if(fread(header, 1, sizeof(header), infile) != sizeof(header))
458		{
459			DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname));
460			return;
461		}
462		if(_decode_mp3_frame(header, &fi))
463		{
464			DPRINTF(E_DEBUG, L_SCANNER, "Invalid frame header while averaging %s\n", basename((char *)fname));
465			return;
466		}
467
468		bitrate_total += fi.bitrate;
469		frame_count++;
470		pos += fi.frame_length;
471	}
472
473	pfi->bitrate = bitrate_total / frame_count;
474
475	return;
476}
477
478// _mp3_get_frame_count
479//   do brute scan
480static void __attribute__((unused))
481_mp3_get_frame_count(FILE *infile, struct mp3_frameinfo *pfi)
482{
483	int pos;
484	int frames = 0;
485	unsigned char frame_buffer[4];
486	struct mp3_frameinfo fi;
487	off_t file_size;
488	int err = 0;
489	int cbr = 1;
490	int last_bitrate = 0;
491
492	fseek(infile, 0, SEEK_END);
493	file_size = ftell(infile);
494
495	pos = pfi->frame_offset;
496
497	while(1)
498	{
499		err = 1;
500
501		fseek(infile, pos, SEEK_SET);
502		if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer))
503		{
504			// valid frame?
505			if(!_decode_mp3_frame(frame_buffer, &fi))
506			{
507				frames++;
508				pos += fi.frame_length;
509				err = 0;
510
511				if((last_bitrate) && (fi.bitrate != last_bitrate))
512					cbr = 0;
513				last_bitrate = fi.bitrate;
514
515				// no sense to scan cbr
516				if(cbr && (frames > 100))
517				{
518					DPRINTF(E_DEBUG, L_SCANNER, "File appears to be CBR... quitting frame _mp3_get_frame_count()\n");
519					return;
520				}
521			}
522		}
523
524		if(err)
525		{
526			if(pos > (file_size - 4096))
527			{
528				pfi->number_of_frames = frames;
529				return;
530			}
531			else
532			{
533				DPRINTF(E_ERROR, L_SCANNER, "Frame count aborted on error.  Pos=%d, Count=%d\n",
534					pos, frames);
535				return;
536			}
537		}
538	}
539}
540
541// _get_mp3fileinfo
542static int
543_get_mp3fileinfo(char *file, struct song_metadata *psong)
544{
545	FILE *infile;
546	struct id3header *pid3;
547	struct mp3_frameinfo fi;
548	unsigned int size = 0;
549	unsigned int n_read;
550	off_t fp_size = 0;
551	off_t file_size;
552	unsigned char buffer[1024];
553	int index;
554
555	int xing_flags;
556	int found;
557
558	int first_check = 0;
559	char frame_buffer[4];
560
561	char id3v1taghdr[4];
562
563	if(!(infile = fopen(file, "rb")))
564	{
565		DPRINTF(E_ERROR, L_SCANNER, "Could not open %s for reading\n", file);
566		return -1;
567	}
568
569	memset((void*)&fi, 0, sizeof(fi));
570
571	fseek(infile, 0, SEEK_END);
572	file_size = ftell(infile);
573	fseek(infile, 0, SEEK_SET);
574
575	if(fread(buffer, 1, sizeof(buffer), infile) != sizeof(buffer))
576	{
577		if(ferror(infile))
578		{
579			DPRINTF(E_ERROR, L_SCANNER, "Error reading: %s [%s]\n", strerror(errno), file);
580		}
581		else
582		{
583			DPRINTF(E_WARN, L_SCANNER, "File too small. Probably corrupted. [%s]\n", file);
584		}
585		fclose(infile);
586		return -1;
587	}
588
589	pid3 = (struct id3header*)buffer;
590
591	found = 0;
592	fp_size = 0;
593
594	if(strncmp((char*)pid3->id, "ID3", 3) == 0)
595	{
596		char tagversion[16];
597
598		/* found an ID3 header... */
599		size = (pid3->size[0] << 21 | pid3->size[1] << 14 |
600			pid3->size[2] << 7 | pid3->size[3]);
601		fp_size = size + sizeof(struct id3header);
602		first_check = 1;
603
604		snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d",
605			 pid3->version[0], pid3->version[1]);
606		psong->tagversion = strdup(tagversion);
607	}
608
609	index = 0;
610
611	/* Here we start the brute-force header seeking.  Sure wish there
612	 * weren't so many crappy mp3 files out there
613	 */
614
615	while(!found)
616	{
617		fseek(infile, fp_size, SEEK_SET);
618		if((n_read = fread(buffer, 1, sizeof(buffer), infile)) < 4)   // at least mp3 frame header size (i.e. 4 bytes)
619		{
620			fclose(infile);
621			return 0;
622		}
623
624		index = 0;
625		while(!found)
626		{
627			while((buffer[index] != 0xFF) && (index < (n_read - 50)))
628				index++;
629
630			if((first_check) && (index))
631			{
632				fp_size = 0;
633				first_check = 0;
634				if(n_read < sizeof(buffer))
635				{
636					fclose(infile);
637					return 0;
638				}
639				break;
640			}
641
642			if(index > (n_read - 50))
643			{
644				fp_size += index;
645				if(n_read < sizeof(buffer))
646				{
647					fclose(infile);
648					return 0;
649				}
650				break;
651			}
652
653			if(!_decode_mp3_frame(&buffer[index], &fi))
654			{
655				if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4))
656				{
657					/* no need to check further... if there is a xing header there,
658					 * this is definately a valid frame */
659					found = 1;
660					fp_size += index;
661				}
662				else
663				{
664					/* No Xing... check for next frame to validate current fram is correct */
665					fseek(infile, fp_size + index + fi.frame_length, SEEK_SET);
666					if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer))
667					{
668						if(!_decode_mp3_frame((unsigned char*)frame_buffer, &fi))
669						{
670							found = 1;
671							fp_size += index;
672						}
673					}
674					else
675					{
676						DPRINTF(E_ERROR, L_SCANNER, "Could not read frame header: %s\n", file);
677						fclose(infile);
678						return 0;
679					}
680
681					if(!found)
682					{
683						// cannot find second frame. Song may be too short. So assume first frame is valid.
684						found = 1;
685						fp_size += index;
686					}
687				}
688			}
689
690			if(!found)
691			{
692				index++;
693				if(first_check)
694				{
695					DPRINTF(E_INFO, L_SCANNER, "Bad header... dropping back for full frame search [%s]\n", psong->path);
696					first_check = 0;
697					fp_size = 0;
698					break;
699				}
700			}
701		}
702	}
703
704	fi.frame_offset = fp_size;
705
706	psong->audio_offset = fp_size;
707	psong->audio_size = file_size - fp_size;
708	// check if last 128 bytes is ID3v1.0 ID3v1.1 tag
709	fseek(infile, file_size - 128, SEEK_SET);
710	if(fread(id3v1taghdr, 1, 4, infile) == 4)
711	{
712		if(id3v1taghdr[0] == 'T' && id3v1taghdr[1] == 'A' && id3v1taghdr[2] == 'G')
713		{
714			psong->audio_size -= 128;
715		}
716	}
717
718	if(_decode_mp3_frame(&buffer[index], &fi))
719	{
720		fclose(infile);
721		DPRINTF(E_ERROR, L_SCANNER, "Could not find sync frame: %s\n", file);
722		return 0;
723	}
724
725	/* now check for an XING header */
726	psong->vbr_scale = -1;
727	if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4))
728	{
729		xing_flags = buffer[index+fi.xing_offset+4+4] << 24 |
730		             buffer[index+fi.xing_offset+4+5] << 16 |
731		             buffer[index+fi.xing_offset+4+6] << 8 |
732		             buffer[index+fi.xing_offset+4+7];
733		psong->vbr_scale = 78;
734
735		if(xing_flags & 0x1)
736		{
737			/* Frames field is valid... */
738			fi.number_of_frames = buffer[index+fi.xing_offset+4+8] << 24 |
739			                      buffer[index+fi.xing_offset+4+9] << 16 |
740			                      buffer[index+fi.xing_offset+4+10] << 8 |
741			                      buffer[index+fi.xing_offset+4+11];
742		}
743	}
744
745	if((fi.number_of_frames == 0) && (!psong->song_length))
746	{
747		_mp3_get_average_bitrate(infile, &fi, file);
748	}
749
750	psong->bitrate = fi.bitrate * 1000;
751	psong->samplerate = fi.samplerate;
752
753	if(!psong->song_length)
754	{
755		if(fi.number_of_frames)
756		{
757			psong->song_length = (int)((double)(fi.number_of_frames * fi.samples_per_frame * 1000.) /
758						   (double)fi.samplerate);
759			psong->vbr_scale = 78;
760		}
761		else
762		{
763			psong->song_length = (int)((double)(file_size - fp_size) * 8. /
764						   (double)fi.bitrate);
765		}
766	}
767	psong->channels = fi.stereo ? 2 : 1;
768
769	fclose(infile);
770	//DEBUG DPRINTF(E_INFO, L_SCANNER, "Got fileinfo successfully for file=%s song_length=%d\n", file, psong->song_length);
771
772	psong->blockalignment = 1;
773	xasprintf(&(psong->dlna_pn), "MP3");
774
775	return 0;
776}
777