comparison src/aac/libmp4.c @ 1882:eed7c270e8dd

Fix MILLIONS of Makefiles.
author Jonathan Schleifer <js@h3c.de>
date Wed, 26 Sep 2007 14:53:37 +0200
parents src/aac/src/libmp4.c@f35f9d6fcb6d
children 2ebeb7816c5e
comparison
equal deleted inserted replaced
1881:8bdede3414cd 1882:eed7c270e8dd
1 #include <glib.h>
2 #include <gtk/gtk.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "faad.h"
6 #include "mp4ff.h"
7 #include "tagging.h"
8
9 #include "audacious/plugin.h"
10 #include "audacious/output.h"
11 #include "audacious/util.h"
12 #include "audacious/vfs.h"
13 #include "audacious/i18n.h"
14 #include "audacious/strings.h"
15 #include "audacious/main.h"
16 #include "audacious/tuple.h"
17 #include "audacious/tuple_formatter.h"
18
19 #define MP4_VERSION VERSION
20
21 #define SBR_DEC
22
23 extern VFSFile *vfs_buffered_file_new_from_uri(gchar *uri);
24
25 /*
26 * BUFFER_SIZE is the highest amount of memory that can be pulled.
27 * We use this for sanity checks, among other things, as mp4ff needs
28 * a labotomy sometimes.
29 */
30 #define BUFFER_SIZE FAAD_MIN_STREAMSIZE*64
31
32 /*
33 * AAC_MAGIC is the pattern that marks the beginning of an MP4 container.
34 */
35 #define AAC_MAGIC (unsigned char [4]) { 0xFF, 0xF9, 0x5C, 0x80 }
36
37 static void mp4_init(void);
38 static void mp4_about(void);
39 static int mp4_is_our_file(char *);
40 static void mp4_play(InputPlayback *);
41 static void mp4_stop(InputPlayback *);
42 static void mp4_pause(InputPlayback *, short);
43 static void mp4_seek(InputPlayback *, int);
44 static void mp4_cleanup(void);
45 static void mp4_get_song_title_len(char *filename, char **, int *);
46 static Tuple* mp4_get_song_tuple(char *);
47 static int mp4_is_our_fd(char *, VFSFile *);
48
49 static gchar *fmts[] = { "m4a", "mp4", "aac", NULL };
50
51 static void * mp4_decode(void *);
52 static gchar * mp4_get_song_title(char *filename);
53 gboolean buffer_playing;
54
55 InputPlugin mp4_ip =
56 {
57 .description = "MP4 Audio Plugin",
58 .init = mp4_init,
59 .about = mp4_about,
60 .is_our_file = mp4_is_our_file,
61 .play_file = mp4_play,
62 .stop = mp4_stop,
63 .pause = mp4_pause,
64 .seek = mp4_seek,
65 .cleanup = mp4_cleanup,
66 .get_song_info = mp4_get_song_title_len,
67 .get_song_tuple = mp4_get_song_tuple,
68 .is_our_file_from_vfs = mp4_is_our_fd,
69 .vfs_extensions = fmts,
70 };
71
72 InputPlugin *mp4_iplist[] = { &mp4_ip, NULL };
73
74 DECLARE_PLUGIN(mp4, NULL, NULL, mp4_iplist, NULL, NULL, NULL, NULL, NULL);
75
76 typedef struct _mp4cfg
77 {
78 #define FILE_UNKNOWN 0
79 #define FILE_MP4 1
80 #define FILE_AAC 2
81 gshort file_type;
82 } Mp4Config;
83
84 static Mp4Config mp4cfg;
85 static GThread *decodeThread;
86 GStaticMutex mutex = G_STATIC_MUTEX_INIT;
87 static int seekPosition = -1;
88
89 void getMP4info(char*);
90 int getAACTrack(mp4ff_t *);
91
92 static guint32 mp4_read_callback(void *data, void *buffer, guint32 len)
93 {
94 if (data == NULL || buffer == NULL)
95 return -1;
96
97 return vfs_fread(buffer, 1, len, (VFSFile *) data);
98 }
99
100 static guint32 mp4_seek_callback(void *data, guint64 pos)
101 {
102 if (data == NULL)
103 return -1;
104
105 return vfs_fseek((VFSFile *) data, pos, SEEK_SET);
106 }
107
108 static void mp4_init(void)
109 {
110 mp4cfg.file_type = FILE_UNKNOWN;
111 seekPosition = -1;
112 return;
113 }
114
115 static void mp4_play(InputPlayback *playback)
116 {
117 buffer_playing = TRUE;
118 playback->playing = 1; //XXX should acquire lock?
119 decodeThread = g_thread_self();
120 playback->set_pb_ready(playback);
121 mp4_decode(playback);
122 }
123
124 static void mp4_stop(InputPlayback *playback)
125 {
126 if (buffer_playing)
127 {
128 buffer_playing = FALSE;
129 playback->playing = 0; //XXX should acquire lock?
130 g_thread_join(decodeThread);
131 playback->output->close_audio();
132 }
133 }
134
135 /*
136 * These routines are derived from MPlayer.
137 */
138
139 /// \param srate (out) sample rate
140 /// \param num (out) number of audio frames in this ADTS frame
141 /// \return size of the ADTS frame in bytes
142 /// aac_parse_frames needs a buffer at least 8 bytes long
143 int aac_parse_frame(guchar *buf, int *srate, int *num)
144 {
145 int i = 0, sr, fl = 0, id;
146 static int srates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0};
147
148 if((buf[i] != 0xFF) || ((buf[i+1] & 0xF6) != 0xF0))
149 return 0;
150
151 id = (buf[i+1] >> 3) & 0x01; //id=1 mpeg2, 0: mpeg4
152 sr = (buf[i+2] >> 2) & 0x0F;
153 if(sr > 11)
154 return 0;
155 *srate = srates[sr];
156
157 fl = ((buf[i+3] & 0x03) << 11) | (buf[i+4] << 3) | ((buf[i+5] >> 5) & 0x07);
158 *num = (buf[i+6] & 0x02) + 1;
159
160 return fl;
161 }
162
163 static gboolean parse_aac_stream(VFSFile *stream)
164 {
165 int cnt = 0, c, len, srate, num;
166 off_t init, probed;
167 static guchar buf[8];
168
169 init = probed = vfs_ftell(stream);
170 while(probed-init <= 32768 && cnt < 8)
171 {
172 c = 0;
173 while(probed-init <= 32768 && c != 0xFF)
174 {
175 c = vfs_getc(stream);
176 if(c < 0)
177 return FALSE;
178 probed = vfs_ftell(stream);
179 }
180 buf[0] = 0xFF;
181 if(vfs_fread(&(buf[1]), 1, 7, stream) < 7)
182 return FALSE;
183
184 len = aac_parse_frame(buf, &srate, &num);
185 if(len > 0)
186 {
187 cnt++;
188 vfs_fseek(stream, len - 8, SEEK_CUR);
189 }
190 probed = vfs_ftell(stream);
191 }
192
193 if(cnt < 8)
194 return FALSE;
195
196 return TRUE;
197 }
198
199 static int aac_probe(unsigned char *buffer, int len)
200 {
201 int i = 0, pos = 0;
202 #ifdef DEBUG
203 g_print("\nAAC_PROBE: %d bytes\n", len);
204 #endif
205 while(i <= len-4) {
206 if(
207 ((buffer[i] == 0xff) && ((buffer[i+1] & 0xf6) == 0xf0)) ||
208 (buffer[i] == 'A' && buffer[i+1] == 'D' && buffer[i+2] == 'I' && buffer[i+3] == 'F')
209 ) {
210 pos = i;
211 break;
212 }
213 #ifdef DEBUG
214 g_print("AUDIO PAYLOAD: %x %x %x %x\n",
215 buffer[i], buffer[i+1], buffer[i+2], buffer[i+3]);
216 #endif
217 i++;
218 }
219 #ifdef DEBUG
220 g_print("\nAAC_PROBE: ret %d\n", pos);
221 #endif
222 return pos;
223 }
224
225 static int mp4_is_our_file(char *filename)
226 {
227 VFSFile *file;
228 gchar* extension;
229 gchar magic[8];
230
231 memset(magic, '\0', 8);
232
233 extension = strrchr(filename, '.');
234 if ((file = vfs_fopen(filename, "rb"))) {
235 vfs_fread(magic, 1, 8, file);
236 vfs_rewind(file);
237 if (parse_aac_stream(file) == TRUE) {
238 vfs_fclose(file);
239 return TRUE;
240 }
241 if (!memcmp(magic, "ID3", 3)) { // ID3 tag bolted to the front, obfuscated magic bytes
242 vfs_fclose(file);
243 if (extension &&(
244 !strcasecmp(extension, ".mp4") || // official extension
245 !strcasecmp(extension, ".m4a") || // Apple mp4 extension
246 !strcasecmp(extension, ".aac") // old MPEG2/4-AAC extension
247 ))
248 return 1;
249 else
250 return 0;
251 }
252 if (!memcmp(&magic[4], "ftyp", 4)) {
253 vfs_fclose(file);
254 return 1;
255 }
256 vfs_fclose(file);
257 }
258 return 0;
259 }
260
261 static int mp4_is_our_fd(char *filename, VFSFile* file)
262 {
263 gchar* extension;
264 gchar magic[8];
265
266 extension = strrchr(filename, '.');
267 vfs_fread(magic, 1, 8, file);
268 vfs_rewind(file);
269 if (parse_aac_stream(file) == TRUE)
270 return 1;
271 if (!memcmp(&magic[4], "ftyp", 4))
272 return 1;
273 if (!memcmp(magic, "ID3", 3)) { // ID3 tag bolted to the front, obfuscated magic bytes
274 if (extension &&(
275 !strcasecmp(extension, ".mp4") || // official extension
276 !strcasecmp(extension, ".m4a") || // Apple mp4 extension
277 !strcasecmp(extension, ".aac") // old MPEG2/4-AAC extension
278 ))
279 return 1;
280 else
281 return 0;
282 }
283 return 0;
284 }
285
286 static void mp4_about(void)
287 {
288 static GtkWidget *aboutbox = NULL;
289 gchar *about_text;
290
291 about_text = g_strjoin ("", _("Using libfaad2-"), FAAD2_VERSION,
292 _(" for decoding.\n"
293 "FAAD2 AAC/HE-AAC/HE-AACv2/DRM decoder (c) Nero AG, www.nero.com\n"
294 "Copyright (c) 2005-2006 Audacious team"), NULL);
295
296 aboutbox = audacious_info_dialog(_("About MP4 AAC player plugin"),
297 about_text,
298 _("Ok"), FALSE, NULL, NULL);
299
300 g_signal_connect(G_OBJECT(aboutbox), "destroy",
301 G_CALLBACK(gtk_widget_destroyed), &aboutbox);
302 g_free(about_text);
303 }
304
305 static void mp4_pause(InputPlayback *playback, short flag)
306 {
307 playback->output->pause(flag);
308 }
309
310 static void mp4_seek(InputPlayback *data, int time)
311 {
312 seekPosition = time;
313 while(buffer_playing && seekPosition != -1)
314 g_usleep(10000);
315 }
316
317 static void mp4_cleanup(void)
318 {
319 }
320
321 static Tuple *mp4_get_song_tuple_base(char *filename, VFSFile *mp4fh)
322 {
323 mp4ff_callback_t *mp4cb = g_malloc0(sizeof(mp4ff_callback_t));
324 mp4ff_t *mp4file;
325 Tuple *ti = tuple_new_from_filename(filename);
326
327 /* check if this file is an ADTS stream, if so return a blank tuple */
328 if (parse_aac_stream(mp4fh))
329 {
330 g_free(mp4cb);
331
332 tuple_associate_string(ti, FIELD_TITLE, NULL, vfs_get_metadata(mp4fh, "track-name"));
333 tuple_associate_string(ti, FIELD_ALBUM, NULL, vfs_get_metadata(mp4fh, "stream-name"));
334
335 tuple_associate_string(ti, FIELD_CODEC, NULL, "Advanced Audio Coding (AAC)");
336 tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossy");
337
338 vfs_fclose(mp4fh);
339 return ti;
340 }
341
342 vfs_rewind(mp4fh);
343
344 mp4cb->read = mp4_read_callback;
345 mp4cb->seek = mp4_seek_callback;
346 mp4cb->user_data = mp4fh;
347
348 if (!(mp4file = mp4ff_open_read(mp4cb))) {
349 g_free(mp4cb);
350 vfs_fclose(mp4fh);
351 } else {
352 gint mp4track= getAACTrack(mp4file);
353 gint numSamples = mp4ff_num_samples(mp4file, mp4track);
354 guint framesize = 1024;
355 guint samplerate = 0;
356 guchar channels = 0;
357 gint msDuration;
358 mp4AudioSpecificConfig mp4ASC;
359 gchar *tmpval;
360 guchar *buffer = NULL;
361 guint bufferSize = 0;
362 faacDecHandle decoder;
363
364 if (mp4track == -1)
365 return NULL;
366
367 decoder = faacDecOpen();
368 mp4ff_get_decoder_config(mp4file, mp4track, &buffer, &bufferSize);
369
370 if ( !buffer ) {
371 faacDecClose(decoder);
372 return FALSE;
373 }
374 if ( faacDecInit2(decoder, buffer, bufferSize,
375 &samplerate, &channels) < 0 ) {
376 faacDecClose(decoder);
377
378 return FALSE;
379 }
380
381 /* Add some hacks for SBR profile */
382 if (AudioSpecificConfig(buffer, bufferSize, &mp4ASC) >= 0) {
383 if (mp4ASC.frameLengthFlag == 1) framesize = 960;
384 if (mp4ASC.sbr_present_flag == 1) framesize *= 2;
385 }
386
387 g_free(buffer);
388
389 faacDecClose(decoder);
390
391 msDuration = ((float)numSamples * (float)(framesize - 1.0)/(float)samplerate) * 1000;
392 tuple_associate_int(ti, FIELD_LENGTH, NULL, msDuration);
393
394 mp4ff_meta_get_title(mp4file, &tmpval);
395 if (tmpval)
396 {
397 tuple_associate_string(ti, FIELD_TITLE, NULL, tmpval);
398 free(tmpval);
399 }
400
401 mp4ff_meta_get_album(mp4file, &tmpval);
402 if (tmpval)
403 {
404 tuple_associate_string(ti, FIELD_ALBUM, NULL, tmpval);
405 free(tmpval);
406 }
407
408 mp4ff_meta_get_artist(mp4file, &tmpval);
409 if (tmpval)
410 {
411 tuple_associate_string(ti, FIELD_ARTIST, NULL, tmpval);
412 free(tmpval);
413 }
414
415 mp4ff_meta_get_genre(mp4file, &tmpval);
416 if (tmpval)
417 {
418 tuple_associate_string(ti, FIELD_GENRE, NULL, tmpval);
419 free(tmpval);
420 }
421
422 mp4ff_meta_get_date(mp4file, &tmpval);
423 if (tmpval)
424 {
425 tuple_associate_int(ti, FIELD_YEAR, NULL, atoi(tmpval));
426 free(tmpval);
427 }
428
429 tuple_associate_string(ti, FIELD_CODEC, NULL, "Advanced Audio Coding (AAC)");
430 tuple_associate_string(ti, FIELD_QUALITY, NULL, "lossy");
431
432 free (mp4cb);
433 vfs_fclose(mp4fh);
434 }
435
436 return ti;
437 }
438
439 static Tuple *mp4_get_song_tuple(char *filename)
440 {
441 Tuple *tuple;
442 VFSFile *mp4fh;
443 gboolean remote = str_has_prefix_nocase(filename, "http:") ||
444 str_has_prefix_nocase(filename, "https:");
445
446 mp4fh = remote ? vfs_buffered_file_new_from_uri(filename) : vfs_fopen(filename, "rb");
447
448 tuple = mp4_get_song_tuple_base(filename, mp4fh);
449
450 return tuple;
451 }
452
453 static void mp4_get_song_title_len(char *filename, char **title, int *len)
454 {
455 (*title) = mp4_get_song_title(filename);
456 (*len) = -1;
457 }
458
459 static gchar *mp4_get_song_title(char *filename)
460 {
461 gchar *title;
462 Tuple *tuple = mp4_get_song_tuple(filename);
463
464 title = tuple_formatter_make_title_string(tuple, get_gentitle_format());
465
466 tuple_free(tuple);
467
468 return title;
469 }
470
471 static int my_decode_mp4( InputPlayback *playback, char *filename, mp4ff_t *mp4file )
472 {
473 // We are reading an MP4 file
474 gint mp4track= getAACTrack(mp4file);
475 faacDecHandle decoder;
476 mp4AudioSpecificConfig mp4ASC;
477 guchar *buffer = NULL;
478 guint bufferSize = 0;
479 guint samplerate = 0;
480 guchar channels = 0;
481 gulong msDuration;
482 guint numSamples;
483 gulong sampleID = 1;
484 guint framesize = 1024;
485
486 if (mp4track < 0)
487 {
488 g_print("Unsupported Audio track type\n");
489 return TRUE;
490 }
491
492 gchar *xmmstitle = NULL;
493 xmmstitle = mp4_get_song_title(filename);
494 if(xmmstitle == NULL)
495 xmmstitle = g_strdup(filename);
496
497 decoder = faacDecOpen();
498 mp4ff_get_decoder_config(mp4file, mp4track, &buffer, &bufferSize);
499 if ( !buffer ) {
500 faacDecClose(decoder);
501 return FALSE;
502 }
503 if ( faacDecInit2(decoder, buffer, bufferSize,
504 &samplerate, &channels) < 0 ) {
505 faacDecClose(decoder);
506
507 return FALSE;
508 }
509
510 /* Add some hacks for SBR profile */
511 if (AudioSpecificConfig(buffer, bufferSize, &mp4ASC) >= 0) {
512 if (mp4ASC.frameLengthFlag == 1) framesize = 960;
513 if (mp4ASC.sbr_present_flag == 1) framesize *= 2;
514 }
515
516 g_free(buffer);
517 if( !channels ) {
518 faacDecClose(decoder);
519
520 return FALSE;
521 }
522 numSamples = mp4ff_num_samples(mp4file, mp4track);
523 msDuration = ((float)numSamples * (float)(framesize - 1.0)/(float)samplerate) * 1000;
524 playback->output->open_audio(FMT_S16_NE, samplerate, channels);
525 playback->output->flush(0);
526
527 mp4_ip.set_info(xmmstitle, msDuration,
528 mp4ff_get_avg_bitrate( mp4file, mp4track ),
529 samplerate,channels);
530
531 while ( buffer_playing ) {
532 void* sampleBuffer;
533 faacDecFrameInfo frameInfo;
534 gint rc;
535
536 /* Seek if seek position has changed */
537 if ( seekPosition!=-1 ) {
538 sampleID = (float)seekPosition*(float)samplerate/(float)(framesize - 1.0);
539 playback->output->flush(seekPosition*1000);
540 seekPosition = -1;
541 }
542
543 /* Otherwise continue playing */
544 buffer=NULL;
545 bufferSize=0;
546
547 /* If we've run to the end of the file, we're done. */
548 if(sampleID >= numSamples){
549 /* Finish playing before we close the
550 output. */
551 while ( playback->output->buffer_playing() ) {
552 g_usleep(10000);
553 }
554
555 playback->output->flush(seekPosition*1000);
556 playback->output->close_audio();
557 faacDecClose(decoder);
558
559 g_static_mutex_lock(&mutex);
560 buffer_playing = FALSE;
561 playback->playing = 0;
562 g_static_mutex_unlock(&mutex);
563 return FALSE;
564 }
565 rc= mp4ff_read_sample(mp4file, mp4track,
566 sampleID++, &buffer, &bufferSize);
567
568 /*g_print(":: %d/%d\n", sampleID-1, numSamples);*/
569
570 /* If we can't read the file, we're done. */
571 if((rc == 0) || (buffer== NULL) || (bufferSize == 0) || (bufferSize > BUFFER_SIZE)){
572 g_print("MP4: read error\n");
573 sampleBuffer = NULL;
574 sampleID=0;
575 playback->output->buffer_free();
576 playback->output->close_audio();
577
578 faacDecClose(decoder);
579
580 return FALSE;
581 }
582
583 /* g_print(" :: %d/%d\n", bufferSize, BUFFER_SIZE); */
584
585 sampleBuffer= faacDecDecode(decoder,
586 &frameInfo,
587 buffer,
588 bufferSize);
589
590 /* If there was an error decoding, we're done. */
591 if(frameInfo.error > 0){
592 g_print("MP4: %s\n",
593 faacDecGetErrorMessage(frameInfo.error));
594 playback->output->close_audio();
595 faacDecClose(decoder);
596
597 return FALSE;
598 }
599 if(buffer){
600 g_free(buffer);
601 buffer=NULL;
602 bufferSize=0;
603 }
604 if (buffer_playing == FALSE)
605 {
606 playback->output->close_audio();
607 return FALSE;
608 }
609 produce_audio(playback->output->written_time(),
610 FMT_S16_NE,
611 channels,
612 frameInfo.samples<<1,
613 sampleBuffer, &buffer_playing);
614 }
615
616 playback->output->close_audio();
617 faacDecClose(decoder);
618
619 return TRUE;
620 }
621
622 void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file )
623 {
624 faacDecHandle decoder = 0;
625 guchar streambuffer[BUFFER_SIZE];
626 gulong bufferconsumed = 0;
627 gulong samplerate = 0;
628 guchar channels = 0;
629 gulong buffervalid = 0;
630 gchar *ttemp = NULL, *stemp = NULL;
631 gchar *temp = g_strdup(filename);
632 gchar *xmmstitle = NULL;
633 gboolean remote = str_has_prefix_nocase(filename, "http:") ||
634 str_has_prefix_nocase(filename, "https:");
635
636 vfs_rewind(file);
637 if((decoder = faacDecOpen()) == NULL){
638 g_print("AAC: Open Decoder Error\n");
639 vfs_fclose(file);
640 buffer_playing = FALSE;
641 playback->playing = 0;
642 g_static_mutex_unlock(&mutex);
643 return;
644 }
645 if((buffervalid = vfs_fread(streambuffer, 1, BUFFER_SIZE, file))==0){
646 g_print("AAC: Error reading file\n");
647 vfs_fclose(file);
648 buffer_playing = FALSE;
649 playback->playing = 0;
650 faacDecClose(decoder);
651 g_static_mutex_unlock(&mutex);
652 return;
653 }
654 if(!strncmp((char*)streambuffer, "ID3", 3)){
655 gint size = 0;
656
657 vfs_fseek(file, 0, SEEK_SET);
658 size = (streambuffer[6]<<21) | (streambuffer[7]<<14) |
659 (streambuffer[8]<<7) | streambuffer[9];
660 size+=10;
661 vfs_fread(streambuffer, 1, size, file);
662 buffervalid = vfs_fread(streambuffer, 1, BUFFER_SIZE, file);
663 }
664
665 ttemp = vfs_get_metadata(file, "stream-name");
666
667 if (ttemp != NULL)
668 {
669 xmmstitle = g_strdup(ttemp);
670 g_free(ttemp);
671 }
672 else
673 xmmstitle = g_strdup(g_basename(temp));
674
675 bufferconsumed = aac_probe(streambuffer, buffervalid);
676 if(bufferconsumed) {
677 buffervalid -= bufferconsumed;
678 memmove(streambuffer, &streambuffer[bufferconsumed], buffervalid);
679 buffervalid += vfs_fread(&streambuffer[buffervalid], 1,
680 BUFFER_SIZE-buffervalid, file);
681 bufferconsumed = 0;
682 }
683
684 bufferconsumed = faacDecInit(decoder,
685 streambuffer,
686 buffervalid,
687 &samplerate,
688 &channels);
689 #ifdef DEBUG
690 g_print("samplerate: %d, channels: %d\n", samplerate, channels);
691 #endif
692 if(playback->output->open_audio(FMT_S16_NE,samplerate,channels) == FALSE){
693 g_print("AAC: Output Error\n");
694 faacDecClose(decoder);
695 vfs_fclose(file);
696 playback->output->close_audio();
697 g_free(xmmstitle);
698 buffer_playing = FALSE;
699 playback->playing = 0;
700 g_static_mutex_unlock(&mutex);
701 return;
702 }
703
704 mp4_ip.set_info(xmmstitle, -1, -1, samplerate, channels);
705 playback->output->flush(0);
706
707 while(buffer_playing && buffervalid > 0 && streambuffer != NULL)
708 {
709 faacDecFrameInfo finfo;
710 unsigned long samplesdecoded;
711 char* sample_buffer = NULL;
712
713 if(bufferconsumed > 0)
714 {
715 buffervalid -= bufferconsumed;
716 memmove(streambuffer, &streambuffer[bufferconsumed], buffervalid);
717 buffervalid += vfs_fread(&streambuffer[buffervalid], 1,
718 BUFFER_SIZE-buffervalid, file);
719 bufferconsumed = 0;
720
721 ttemp = vfs_get_metadata(file, "stream-name");
722
723 if (ttemp != NULL)
724 stemp = vfs_get_metadata(file, "track-name");
725
726 if (stemp != NULL)
727 {
728 static gchar *ostmp = NULL;
729
730 if (ostmp == NULL || g_ascii_strcasecmp(stemp, ostmp))
731 {
732 if (xmmstitle != NULL)
733 g_free(xmmstitle);
734
735 xmmstitle = g_strdup_printf("%s (%s)", stemp, ttemp);
736
737 if (ostmp != NULL)
738 g_free(ostmp);
739
740 ostmp = stemp;
741
742 mp4_ip.set_info(xmmstitle, -1, -1, samplerate, channels);
743 }
744 }
745
746 g_free(ttemp);
747 ttemp = NULL;
748 }
749
750 sample_buffer = faacDecDecode(decoder, &finfo, streambuffer, buffervalid);
751
752 bufferconsumed += finfo.bytesconsumed;
753 samplesdecoded = finfo.samples;
754
755 if(finfo.error > 0 && remote != FALSE)
756 {
757 buffervalid--;
758 memmove(streambuffer, &streambuffer[1], buffervalid);
759 if(buffervalid < BUFFER_SIZE) {
760 buffervalid +=
761 vfs_fread(&streambuffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file);
762 }
763 bufferconsumed = aac_probe(streambuffer, buffervalid);
764 if(bufferconsumed) {
765 buffervalid -= bufferconsumed;
766 memmove(streambuffer, &streambuffer[bufferconsumed], buffervalid);
767 bufferconsumed = 0;
768 }
769 continue;
770 }
771
772 if((samplesdecoded <= 0) && !sample_buffer){
773 #ifdef DEBUG
774 g_print("AAC: decoded %d samples!\n", samplesdecoded);
775 #endif
776 continue;
777 }
778
779 produce_audio(playback->output->written_time(),
780 FMT_S16_LE, channels,
781 samplesdecoded<<1, sample_buffer, &buffer_playing);
782 }
783 playback->output->buffer_free();
784 playback->output->close_audio();
785 buffer_playing = FALSE;
786 playback->playing = 0;
787 faacDecClose(decoder);
788 g_free(xmmstitle);
789 vfs_fclose(file);
790 seekPosition = -1;
791
792 buffer_playing = FALSE;
793 playback->playing = 0;
794 g_static_mutex_unlock(&mutex);
795 }
796
797 static void *mp4_decode( void *args )
798 {
799 mp4ff_callback_t *mp4cb = g_malloc0(sizeof(mp4ff_callback_t));
800 VFSFile *mp4fh;
801 mp4ff_t *mp4file;
802 gboolean ret;
803
804 InputPlayback *playback = args;
805 char *filename = playback->filename;
806
807 mp4fh = vfs_buffered_file_new_from_uri(filename);
808
809 g_static_mutex_lock(&mutex);
810 seekPosition= -1;
811 buffer_playing= TRUE;
812 g_static_mutex_unlock(&mutex);
813
814 if (mp4fh == NULL)
815 return NULL;
816
817 ret = parse_aac_stream(mp4fh);
818
819 if( ret == TRUE )
820 vfs_fseek(mp4fh, 0, SEEK_SET);
821 else {
822 vfs_fclose(mp4fh);
823 mp4fh = vfs_fopen(filename, "rb");
824 }
825
826 mp4cb->read = mp4_read_callback;
827 mp4cb->seek = mp4_seek_callback;
828 mp4cb->user_data = mp4fh;
829
830 mp4file= mp4ff_open_read(mp4cb);
831
832 if( ret == TRUE ) {
833 g_free(mp4cb);
834 my_decode_aac( playback, filename, mp4fh );
835 }
836 else
837 my_decode_mp4( playback, filename, mp4file );
838
839 return NULL;
840 }