Mercurial > audlegacy
annotate Plugins/Input/aac/src/libmp4.c @ 345:9b19994a715c trunk
[svn] ditto for samplerate... we should have full plugin compatibility now
author | nenolod |
---|---|
date | Mon, 26 Dec 2005 13:01:04 -0800 |
parents | a98a7f2dfc84 |
children | 430658951e30 |
rev | line source |
---|---|
61 | 1 /* |
2 * MP4/AAC decoder for xmms | |
3 * | |
4 * This decoding source code is completly independent of the faad2 | |
5 * package. | |
6 * This package exist for people who don't want to install | |
7 * faad2 and mpeg4ip project files. | |
8 * | |
9 * OPTIONNAL need | |
10 * -------------- | |
11 * libid3 (3.8.x - www.id3.org) | |
12 */ | |
13 | |
339 | 14 #include <glib.h> |
61 | 15 #include <gtk/gtk.h> |
339 | 16 #include <string.h> |
17 #include <stdlib.h> | |
61 | 18 #include "faad.h" |
19 #include "mp4.h" | |
20 | |
21 #include <audacious/plugin.h> | |
22 #include <libaudacious/util.h> | |
23 #include <libaudacious/titlestring.h> | |
24 | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
25 #define MP4_VERSION "ver.- 15 December 2004" |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
26 #define LIBMP4V2_VERSION "1.2.0" |
61 | 27 #define MP4_ABOUT "Written by ciberfred" |
28 #define BUFFER_SIZE FAAD_MIN_STREAMSIZE*64 | |
29 | |
30 static void mp4_init(void); | |
31 static void mp4_about(void); | |
32 static void mp4_play(char *); | |
33 static void mp4_stop(void); | |
34 static void mp4_pause(short); | |
35 static void mp4_seek(int); | |
36 static int mp4_getTime(void); | |
37 static void mp4_cleanup(void); | |
342
320f0205ad45
[svn] Initial fileinfo box, loosely based around the mpg123-clone one.
nenolod
parents:
340
diff
changeset
|
38 static void audmp4_file_info_box(gchar *); |
61 | 39 static int mp4_isFile(char *); |
339 | 40 static void mp4_getSongTitle(char *filename, char **, int *); |
61 | 41 static void* mp4Decode(void *); |
42 | |
43 InputPlugin mp4_ip = | |
44 { | |
45 0, // handle | |
46 0, // filename | |
344
a98a7f2dfc84
[svn] Display the MP4/AAC+ bitrate, instead of "VBR".
nenolod
parents:
342
diff
changeset
|
47 "MP4 Audio Plugin", |
61 | 48 mp4_init, |
49 mp4_about, | |
50 0, // configuration | |
51 mp4_isFile, | |
52 0, //scandir | |
53 mp4_play, | |
54 mp4_stop, | |
55 mp4_pause, | |
56 mp4_seek, | |
57 0, // set equalizer | |
58 mp4_getTime, | |
59 0, // get volume | |
60 0, | |
61 mp4_cleanup, | |
62 0, // obsolete | |
63 0, // send visualisation data | |
64 0, // set player window info | |
65 0, // set song title text | |
339 | 66 mp4_getSongTitle, // get song title text |
342
320f0205ad45
[svn] Initial fileinfo box, loosely based around the mpg123-clone one.
nenolod
parents:
340
diff
changeset
|
67 audmp4_file_info_box, // info box |
61 | 68 0, // to output plugin |
69 }; | |
70 | |
71 typedef struct _mp4cfg{ | |
72 gshort file_type; | |
73 #define FILE_UNKNOW 0 | |
74 #define FILE_MP4 1 | |
75 #define FILE_AAC 2 | |
76 } Mp4Config; | |
77 | |
78 static Mp4Config mp4cfg; | |
79 static gboolean bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
80 static GThread *decodeThread; |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
81 GStaticMutex mutex = G_STATIC_MUTEX_INIT; |
61 | 82 static int seekPosition = -1; |
83 | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
84 void getMP4info(char*); |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
85 int getAACTrack(MP4FileHandle); |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
86 |
339 | 87 /* |
88 * Function extname (filename) | |
89 * | |
90 * Return pointer within filename to its extenstion, or NULL if | |
91 * filename has no extension. | |
92 * | |
93 */ | |
94 static gchar * | |
95 extname(const char *filename) | |
96 { | |
97 gchar *ext = strrchr(filename, '.'); | |
98 | |
99 if (ext != NULL) | |
100 ++ext; | |
101 | |
102 return ext; | |
103 } | |
61 | 104 |
105 InputPlugin *get_iplugin_info(void) | |
106 { | |
107 return(&mp4_ip); | |
108 } | |
109 | |
110 static void mp4_init(void) | |
111 { | |
112 mp4cfg.file_type = FILE_UNKNOW; | |
113 seekPosition = -1; | |
114 return; | |
115 } | |
116 | |
117 static void mp4_play(char *filename) | |
118 { | |
119 bPlaying = TRUE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
120 decodeThread = g_thread_create((GThreadFunc)mp4Decode, g_strdup(filename), TRUE, NULL); |
61 | 121 return; |
122 } | |
123 | |
124 static void mp4_stop(void) | |
125 { | |
126 if(bPlaying){ | |
127 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
128 g_thread_join(decodeThread); |
61 | 129 mp4_ip.output->close_audio(); |
130 } | |
131 } | |
132 | |
133 static int mp4_isFile(char *filename) | |
134 { | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
135 if(filename){ |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
136 gchar* extention; |
61 | 137 |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
138 extention = strrchr(filename, '.'); |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
139 if (extention &&( |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
140 !strcasecmp(extention, ".mp4") || // official extention |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
141 !strcasecmp(extention, ".m4a") || // Apple mp4 extention |
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
142 !strcasecmp(extention, ".aac") // old MPEG2/4-AAC extention |
61 | 143 )){ |
144 return (1); | |
145 } | |
146 } | |
147 return(0); | |
148 } | |
149 | |
150 static void mp4_about(void) | |
151 { | |
152 static GtkWidget *aboutbox; | |
153 | |
154 if(aboutbox!=NULL) | |
155 return; | |
156 aboutbox = xmms_show_message("About MP4 AAC player plugin", | |
157 "libfaad2-" FAAD2_VERSION "\n" | |
158 "libmp4v2-" LIBMP4V2_VERSION "\n" | |
159 "plugin version: " MP4_VERSION "\n" | |
160 MP4_ABOUT, | |
161 "Ok", FALSE, NULL, NULL); | |
162 gtk_signal_connect(GTK_OBJECT(aboutbox), "destroy", | |
163 GTK_SIGNAL_FUNC(gtk_widget_destroyed), | |
164 &aboutbox); | |
165 } | |
166 | |
167 static void mp4_pause(short flag) | |
168 { | |
169 mp4_ip.output->pause(flag); | |
170 } | |
171 | |
172 static void mp4_seek(int time) | |
173 { | |
174 seekPosition = time; | |
175 while(bPlaying && seekPosition!=-1) | |
176 xmms_usleep(10000); | |
177 } | |
178 | |
179 static int mp4_getTime(void) | |
180 { | |
181 if(!bPlaying) | |
182 return (-1); | |
183 else | |
184 return (mp4_ip.output->output_time()); | |
185 } | |
186 | |
187 static void mp4_cleanup(void) | |
188 { | |
189 } | |
190 | |
191 static void mp4_getSongInfo(char *filename) | |
192 { | |
193 if(mp4cfg.file_type == FILE_MP4) | |
194 getMP4info(filename); | |
195 else if(mp4cfg.file_type == FILE_AAC) | |
196 ; | |
197 } | |
198 | |
339 | 199 static gchar *mp4_get_song_title(char *filename) |
200 { | |
201 MP4FileHandle mp4file; | |
202 gchar *title = NULL; | |
203 | |
204 if (!(mp4file = MP4Read(filename, 0))) { | |
205 MP4Close(mp4file); | |
206 } else { | |
207 TitleInput *input; | |
208 gchar *tmpval; | |
209 | |
210 input = bmp_title_input_new(); | |
211 | |
212 MP4GetMetadataName(mp4file, &input->track_name); | |
213 MP4GetMetadataAlbum(mp4file, &input->album_name); | |
214 MP4GetMetadataArtist(mp4file, &input->performer); | |
215 MP4GetMetadataYear(mp4file, &tmpval); | |
216 MP4GetMetadataGenre(mp4file, &input->genre); | |
217 | |
340 | 218 if (tmpval) |
219 input->year = atoi(tmpval); | |
339 | 220 |
221 input->file_name = g_path_get_basename(filename); | |
222 input->file_path = g_path_get_dirname(filename); | |
223 input->file_ext = extname(filename); | |
224 | |
225 title = xmms_get_titlestring(xmms_get_gentitle_format(), input); | |
226 | |
227 free (input->file_name); | |
228 free (input->file_path); | |
229 free (input); | |
230 } | |
231 | |
232 if (!title) | |
233 { | |
234 title = g_path_get_basename(filename); | |
235 if (extname(title)) | |
236 *(extname(title) - 1) = '\0'; | |
237 } | |
238 | |
239 return title; | |
240 } | |
241 | |
242 static void mp4_getSongTitle(char *filename, char **title_real, int *len_real) | |
243 { | |
244 (*title_real) = mp4_get_song_title(filename); | |
245 (*len_real) = -1; | |
246 } | |
247 | |
61 | 248 static void *mp4Decode(void *args) |
249 { | |
250 MP4FileHandle mp4file; | |
251 | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
252 g_static_mutex_lock(&mutex); |
61 | 253 seekPosition = -1; |
254 bPlaying = TRUE; | |
255 if(!(mp4file = MP4Read(args, 0))){ | |
256 mp4cfg.file_type = FILE_AAC; | |
257 MP4Close(mp4file); | |
258 }else{ | |
259 mp4cfg.file_type = FILE_MP4; | |
260 } | |
261 | |
262 if(mp4cfg.file_type == FILE_MP4){ | |
263 // We are reading a MP4 file | |
264 gint mp4track; | |
265 | |
266 if((mp4track = getAACTrack(mp4file)) < 0){ | |
267 //TODO: check here for others Audio format..... | |
268 g_print("Unsupported Audio track type\n"); | |
269 g_free(args); | |
270 MP4Close(mp4file); | |
271 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
272 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
273 g_thread_exit(NULL); |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
274 return(NULL); |
61 | 275 }else{ |
276 faacDecHandle decoder; | |
277 unsigned char *buffer = NULL; | |
278 guint bufferSize = 0; | |
279 gulong samplerate; | |
280 guchar channels; | |
344
a98a7f2dfc84
[svn] Display the MP4/AAC+ bitrate, instead of "VBR".
nenolod
parents:
342
diff
changeset
|
281 guint avgBitrate; |
61 | 282 MP4Duration duration; |
283 gulong msDuration; | |
284 MP4SampleId numSamples; | |
285 MP4SampleId sampleID = 1; | |
339 | 286 gchar *title; |
61 | 287 |
288 decoder = faacDecOpen(); | |
289 MP4GetTrackESConfiguration(mp4file, mp4track, &buffer, &bufferSize); | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
290 if(!buffer) |
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
291 goto out; |
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
292 if(faacDecInit2(decoder, buffer, bufferSize, &samplerate, &channels)<0) |
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
293 goto out; |
61 | 294 g_free(buffer); |
295 if(channels == 0){ | |
296 g_print("Number of Channels not supported\n"); | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
297 goto out; |
61 | 298 } |
299 duration = MP4GetTrackDuration(mp4file, mp4track); | |
300 msDuration = MP4ConvertFromTrackDuration(mp4file, mp4track, duration, | |
301 MP4_MSECS_TIME_SCALE); | |
302 numSamples = MP4GetTrackNumberOfSamples(mp4file, mp4track); | |
345
9b19994a715c
[svn] ditto for samplerate... we should have full plugin compatibility now
nenolod
parents:
344
diff
changeset
|
303 samplerate = MP4GetTrackTimeScale(mp4file, mp4track); |
61 | 304 mp4_ip.output->open_audio(FMT_S16_NE, samplerate, channels); |
305 mp4_ip.output->flush(0); | |
339 | 306 title = mp4_get_song_title(args); |
344
a98a7f2dfc84
[svn] Display the MP4/AAC+ bitrate, instead of "VBR".
nenolod
parents:
342
diff
changeset
|
307 avgBitrate = MP4GetTrackBitRate(mp4file, mp4track); |
345
9b19994a715c
[svn] ditto for samplerate... we should have full plugin compatibility now
nenolod
parents:
344
diff
changeset
|
308 mp4_ip.set_info(title, msDuration, avgBitrate, samplerate, channels); |
61 | 309 |
310 while(bPlaying){ | |
311 void* sampleBuffer; | |
312 faacDecFrameInfo frameInfo; | |
313 gint rc; | |
314 | |
315 if(seekPosition!=-1){ | |
316 duration = MP4ConvertToTrackDuration(mp4file, | |
317 mp4track, | |
318 seekPosition*1000, | |
319 MP4_MSECS_TIME_SCALE); | |
320 sampleID = MP4GetSampleIdFromTime(mp4file, mp4track, duration, 0); | |
321 mp4_ip.output->flush(seekPosition*1000); | |
322 seekPosition = -1; | |
323 } | |
324 buffer=NULL; | |
325 bufferSize=0; | |
326 if(sampleID > numSamples){ | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
327 goto out; |
61 | 328 } |
329 rc = MP4ReadSample(mp4file, mp4track, sampleID++, &buffer, &bufferSize, | |
330 NULL, NULL, NULL, NULL); | |
331 if((rc==0) || (buffer== NULL)){ | |
332 g_print("MP4: read error\n"); | |
333 sampleBuffer = NULL; | |
334 sampleID=0; | |
335 mp4_ip.output->buffer_free(); | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
336 goto out; |
61 | 337 }else{ |
338 sampleBuffer = faacDecDecode(decoder, &frameInfo, buffer, bufferSize); | |
339 if(frameInfo.error > 0){ | |
340 g_print("MP4: %s\n", | |
341 faacDecGetErrorMessage(frameInfo.error)); | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
342 goto out; |
61 | 343 } |
344 if(buffer){ | |
345 g_free(buffer); buffer=NULL; bufferSize=0; | |
346 } | |
347 while(bPlaying && mp4_ip.output->buffer_free()<frameInfo.samples<<1) | |
348 xmms_usleep(30000); | |
349 } | |
350 mp4_ip.add_vis_pcm(mp4_ip.output->written_time(), | |
351 FMT_S16_NE, | |
352 channels, | |
353 frameInfo.samples<<1, | |
354 sampleBuffer); | |
355 mp4_ip.output->write_audio(sampleBuffer, frameInfo.samples<<1); | |
356 } | |
357 while(bPlaying && mp4_ip.output->buffer_free()){ | |
358 xmms_usleep(10000); | |
359 } | |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
360 out: |
61 | 361 mp4_ip.output->close_audio(); |
362 g_free(args); | |
363 faacDecClose(decoder); | |
364 MP4Close(mp4file); | |
365 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
366 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
367 g_thread_exit(NULL); |
250
b9e6cdce7219
[svn] Reduce code duplication and add a return statement.
chainsaw
parents:
200
diff
changeset
|
368 return(NULL); |
61 | 369 } |
370 } else{ | |
371 // WE ARE READING AN AAC FILE | |
372 FILE *file = NULL; | |
373 faacDecHandle decoder = 0; | |
374 guchar *buffer = 0; | |
375 gulong bufferconsumed = 0; | |
376 gulong samplerate = 0; | |
377 guchar channels; | |
378 gulong buffervalid = 0; | |
379 TitleInput* input; | |
380 gchar *temp = g_strdup(args); | |
381 gchar *ext = strrchr(temp, '.'); | |
382 gchar *xmmstitle = NULL; | |
383 faacDecConfigurationPtr config; | |
384 | |
385 if((file = fopen(args, "rb")) == 0){ | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
386 g_print("AAC: can't find file %s\n", (char*)args); |
61 | 387 bPlaying = FALSE; |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
388 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
389 g_thread_exit(NULL); |
61 | 390 } |
391 if((decoder = faacDecOpen()) == NULL){ | |
392 g_print("AAC: Open Decoder Error\n"); | |
393 fclose(file); | |
394 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
395 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
396 g_thread_exit(NULL); |
61 | 397 } |
398 config = faacDecGetCurrentConfiguration(decoder); | |
399 config->useOldADTSFormat = 0; | |
400 faacDecSetConfiguration(decoder, config); | |
401 if((buffer = g_malloc(BUFFER_SIZE)) == NULL){ | |
402 g_print("AAC: error g_malloc\n"); | |
403 fclose(file); | |
404 bPlaying = FALSE; | |
405 faacDecClose(decoder); | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
406 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
407 g_thread_exit(NULL); |
61 | 408 } |
409 if((buffervalid = fread(buffer, 1, BUFFER_SIZE, file))==0){ | |
410 g_print("AAC: Error reading file\n"); | |
411 g_free(buffer); | |
412 fclose(file); | |
413 bPlaying = FALSE; | |
414 faacDecClose(decoder); | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
415 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
416 g_thread_exit(NULL); |
61 | 417 } |
418 XMMS_NEW_TITLEINPUT(input); | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
419 input->file_name = (char*)g_basename(temp); |
61 | 420 input->file_ext = ext ? ext+1 : NULL; |
421 input->file_path = temp; | |
422 if(!strncmp(buffer, "ID3", 3)){ | |
423 gint size = 0; | |
424 | |
425 fseek(file, 0, SEEK_SET); | |
426 size = (buffer[6]<<21) | (buffer[7]<<14) | (buffer[8]<<7) | buffer[9]; | |
427 size+=10; | |
428 fread(buffer, 1, size, file); | |
429 buffervalid = fread(buffer, 1, BUFFER_SIZE, file); | |
430 } | |
431 xmmstitle = xmms_get_titlestring(xmms_get_gentitle_format(), input); | |
432 if(xmmstitle == NULL) | |
320
d8889f819081
[svn] Dereferencing type-punned pointer will break strict-aliasing rules squashed by Mark Loeser <halcy0n@gentoo.org>.
chainsaw
parents:
319
diff
changeset
|
433 xmmstitle = g_path_get_basename(input->file_name); |
61 | 434 if(temp) g_free(temp); |
435 if(input->performer) g_free(input->performer); | |
436 if(input->album_name) g_free(input->album_name); | |
437 if(input->track_name) g_free(input->track_name); | |
438 if(input->genre) g_free(input->genre); | |
439 g_free(input); | |
440 bufferconsumed = faacDecInit(decoder, | |
441 buffer, | |
442 buffervalid, | |
443 &samplerate, | |
444 &channels); | |
445 if(mp4_ip.output->open_audio(FMT_S16_NE,samplerate,channels) == FALSE){ | |
446 g_print("AAC: Output Error\n"); | |
447 g_free(buffer); buffer=0; | |
448 faacDecClose(decoder); | |
449 fclose(file); | |
450 mp4_ip.output->close_audio(); | |
451 /* | |
452 if(positionTable){ | |
453 g_free(positionTable); positionTable=0; | |
454 } | |
455 */ | |
456 g_free(xmmstitle); | |
457 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
458 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
459 g_thread_exit(NULL); |
61 | 460 } |
461 //if(bSeek){ | |
462 //mp4_ip.set_info(xmmstitle, lenght*1000, -1, samplerate, channels); | |
463 //}else{ | |
464 mp4_ip.set_info(xmmstitle, -1, -1, samplerate, channels); | |
465 //} | |
466 mp4_ip.output->flush(0); | |
467 | |
468 while(bPlaying && buffervalid > 0){ | |
469 faacDecFrameInfo finfo; | |
470 unsigned long samplesdecoded; | |
471 char* sample_buffer = NULL; | |
472 /* | |
473 if(bSeek && seekPosition!=-1){ | |
474 fseek(file, positionTable[seekPosition], SEEK_SET); | |
475 bufferconsumed=0; | |
476 buffervalid = fread(buffer, 1, BUFFER_SIZE, file); | |
477 aac_ip.output->flush(seekPosition*1000); | |
478 seekPosition=-1; | |
479 } | |
480 */ | |
481 if(bufferconsumed > 0){ | |
482 memmove(buffer, &buffer[bufferconsumed], buffervalid-bufferconsumed); | |
483 buffervalid -= bufferconsumed; | |
484 buffervalid += fread(&buffer[buffervalid], 1, | |
485 BUFFER_SIZE-buffervalid, file); | |
486 bufferconsumed = 0; | |
487 } | |
488 sample_buffer = faacDecDecode(decoder, &finfo, buffer, buffervalid); | |
489 if(finfo.error){ | |
490 config = faacDecGetCurrentConfiguration(decoder); | |
491 if(config->useOldADTSFormat != 1){ | |
492 faacDecClose(decoder); | |
493 decoder = faacDecOpen(); | |
494 config = faacDecGetCurrentConfiguration(decoder); | |
495 config->useOldADTSFormat = 1; | |
496 faacDecSetConfiguration(decoder, config); | |
497 finfo.bytesconsumed=0; | |
498 finfo.samples = 0; | |
499 faacDecInit(decoder, | |
500 buffer, | |
501 buffervalid, | |
502 &samplerate, | |
503 &channels); | |
504 }else{ | |
505 g_print("FAAD2 Warning %s\n", faacDecGetErrorMessage(finfo.error)); | |
506 buffervalid = 0; | |
507 } | |
508 } | |
509 bufferconsumed += finfo.bytesconsumed; | |
510 samplesdecoded = finfo.samples; | |
511 if((samplesdecoded<=0) && !sample_buffer){ | |
512 g_print("AAC: error sample decoding\n"); | |
513 continue; | |
514 } | |
515 while(bPlaying && mp4_ip.output->buffer_free() < (samplesdecoded<<1)){ | |
516 xmms_usleep(10000); | |
517 } | |
518 mp4_ip.add_vis_pcm(mp4_ip.output->written_time(), | |
519 FMT_S16_LE, channels, | |
520 samplesdecoded<<1, sample_buffer); | |
521 mp4_ip.output->write_audio(sample_buffer, samplesdecoded<<1); | |
522 } | |
523 while(bPlaying && mp4_ip.output->buffer_playing()){ | |
524 xmms_usleep(10000); | |
525 } | |
526 mp4_ip.output->buffer_free(); | |
527 mp4_ip.output->close_audio(); | |
528 bPlaying = FALSE; | |
529 g_free(buffer); | |
530 faacDecClose(decoder); | |
531 g_free(xmmstitle); | |
532 fclose(file); | |
533 seekPosition = -1; | |
534 /* | |
535 if(positionTable){ | |
536 g_free(positionTable); positionTable=0; | |
537 } | |
538 */ | |
539 bPlaying = FALSE; | |
200
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
540 g_static_mutex_unlock(&mutex); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
541 g_thread_exit(NULL); |
094ef8a0a9fd
[svn] GThreadify plugin. Adds a return statement and removes a pragma statement to please GCC.
chainsaw
parents:
199
diff
changeset
|
542 return(NULL); |
61 | 543 } |
544 } |