summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/audio_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/audio_thread.c')
-rw-r--r--apps/plugins/mpegplayer/audio_thread.c721
1 files changed, 721 insertions, 0 deletions
diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c
new file mode 100644
index 0000000000..764ad111f2
--- /dev/null
+++ b/apps/plugins/mpegplayer/audio_thread.c
@@ -0,0 +1,721 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * mpegplayer audio thread implementation
11 *
12 * Copyright (c) 2007 Michael Sevakis
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "mpegplayer.h"
25#include "codecs/libmad/bit.h"
26#include "codecs/libmad/mad.h"
27
28/** Audio stream and thread **/
29struct pts_queue_slot;
30struct audio_thread_data
31{
32 struct queue_event ev; /* Our event queue to receive commands */
33 int state; /* Thread state */
34 int status; /* Media status (STREAM_PLAYING, etc.) */
35 int mad_errors; /* A count of the errors in each frame */
36 unsigned samplerate; /* Current stream sample rate */
37 int nchannels; /* Number of audio channels */
38 struct dsp_config *dsp; /* The DSP we're using */
39 struct dsp_buffer src; /* Current audio data for DSP processing */
40};
41
42/* The audio thread is stolen from the core codec thread */
43static struct event_queue audio_str_queue SHAREDBSS_ATTR;
44static struct queue_sender_list audio_str_queue_send SHAREDBSS_ATTR;
45struct stream audio_str IBSS_ATTR;
46
47/* libmad related definitions */
48static struct mad_stream stream IBSS_ATTR;
49static struct mad_frame frame IBSS_ATTR;
50static struct mad_synth synth IBSS_ATTR;
51
52/*sbsample buffer for mad_frame*/
53mad_fixed_t sbsample[2][36][32];
54
55/* 2567 bytes */
56static unsigned char mad_main_data[MAD_BUFFER_MDLEN];
57
58/* There isn't enough room for this in IRAM on PortalPlayer, but there
59 is for Coldfire. */
60
61/* 4608 bytes */
62#if defined(CPU_COLDFIRE) || defined(CPU_S5L870X)
63static mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR;
64#else
65static mad_fixed_t mad_frame_overlap[2][32][18];
66#endif
67
68/** A queue for saving needed information about MPEG audio packets **/
69#define AUDIODESC_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient -
70 if not, the case is handled */
71#define AUDIODESC_QUEUE_MASK (AUDIODESC_QUEUE_LEN-1)
72struct audio_frame_desc
73{
74 uint32_t time; /* Time stamp for packet in audio ticks */
75 ssize_t size; /* Number of unprocessed bytes left in packet */
76};
77
78 /* This starts out wr == rd but will never be emptied to zero during
79 streaming again in order to support initializing the first packet's
80 timestamp without a special case */
81struct
82{
83 /* Compressed audio data */
84 uint8_t *start; /* Start of encoded audio buffer */
85 uint8_t *ptr; /* Pointer to next encoded audio data */
86 ssize_t used; /* Number of bytes in MPEG audio buffer */
87 /* Compressed audio data descriptors */
88 unsigned read, write;
89 struct audio_frame_desc *curr; /* Current slot */
90 struct audio_frame_desc descs[AUDIODESC_QUEUE_LEN];
91} audio_queue;
92
93static inline int audiodesc_queue_count(void)
94{
95 return audio_queue.write - audio_queue.read;
96}
97
98static inline bool audiodesc_queue_full(void)
99{
100 return audio_queue.used >= MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD ||
101 audiodesc_queue_count() >= AUDIODESC_QUEUE_LEN;
102}
103
104/* Increments the queue tail postion - should be used to preincrement */
105static inline void audiodesc_queue_add_tail(void)
106{
107 if (audiodesc_queue_full())
108 {
109 DEBUGF("audiodesc_queue_add_tail: audiodesc queue full!\n");
110 return;
111 }
112
113 audio_queue.write++;
114}
115
116/* Increments the queue head position - leaves one slot as current */
117static inline bool audiodesc_queue_remove_head(void)
118{
119 if (audio_queue.write == audio_queue.read)
120 return false;
121
122 audio_queue.read++;
123 return true;
124}
125
126/* Returns the "tail" at the index just behind the write index */
127static inline struct audio_frame_desc * audiodesc_queue_tail(void)
128{
129 return &audio_queue.descs[(audio_queue.write - 1) & AUDIODESC_QUEUE_MASK];
130}
131
132/* Returns a pointer to the current head */
133static inline struct audio_frame_desc * audiodesc_queue_head(void)
134{
135 return &audio_queue.descs[audio_queue.read & AUDIODESC_QUEUE_MASK];
136}
137
138/* Resets the pts queue - call when starting and seeking */
139static void audio_queue_reset(void)
140{
141 audio_queue.ptr = audio_queue.start;
142 audio_queue.used = 0;
143 audio_queue.read = 0;
144 audio_queue.write = 0;
145 rb->memset(audio_queue.descs, 0, sizeof (audio_queue.descs));
146 audio_queue.curr = audiodesc_queue_head();
147}
148
149static void audio_queue_advance_pos(ssize_t len)
150{
151 audio_queue.ptr += len;
152 audio_queue.used -= len;
153 audio_queue.curr->size -= len;
154}
155
156static int audio_buffer(struct stream *str, enum stream_parse_mode type)
157{
158 int ret = STREAM_OK;
159
160 /* Carry any overshoot to the next size since we're technically
161 -size bytes into it already. If size is negative an audio
162 frame was split across packets. Old has to be saved before
163 moving the head. */
164 if (audio_queue.curr->size <= 0 && audiodesc_queue_remove_head())
165 {
166 struct audio_frame_desc *old = audio_queue.curr;
167 audio_queue.curr = audiodesc_queue_head();
168 audio_queue.curr->size += old->size;
169 old->size = 0;
170 }
171
172 /* Add packets to compressed audio buffer until it's full or the
173 * timestamp queue is full - whichever happens first */
174 while (!audiodesc_queue_full())
175 {
176 ret = parser_get_next_data(str, type);
177 struct audio_frame_desc *curr;
178 ssize_t len;
179
180 if (ret != STREAM_OK)
181 break;
182
183 /* Get data from next audio packet */
184 len = str->curr_packet_end - str->curr_packet;
185
186 if (str->pkt_flags & PKT_HAS_TS)
187 {
188 audiodesc_queue_add_tail();
189 curr = audiodesc_queue_tail();
190 curr->time = TS_TO_TICKS(str->pts);
191 /* pts->size should have been zeroed when slot was
192 freed */
193 }
194 else
195 {
196 /* Add to the one just behind the tail - this may be
197 * the head or the previouly added tail - whether or
198 * not we'll ever reach this is quite in question
199 * since audio always seems to have every packet
200 * timestamped */
201 curr = audiodesc_queue_tail();
202 }
203
204 curr->size += len;
205
206 /* Slide any remainder over to beginning */
207 if (audio_queue.ptr > audio_queue.start && audio_queue.used > 0)
208 {
209 rb->memmove(audio_queue.start, audio_queue.ptr,
210 audio_queue.used);
211 }
212
213 /* Splice this packet onto any remainder */
214 rb->memcpy(audio_queue.start + audio_queue.used,
215 str->curr_packet, len);
216
217 audio_queue.used += len;
218 audio_queue.ptr = audio_queue.start;
219
220 rb->yield();
221 }
222
223 return ret;
224}
225
226/* Initialise libmad */
227static void init_mad(void)
228{
229 /* init the sbsample buffer */
230 frame.sbsample_prev = &sbsample;
231 frame.sbsample = &sbsample;
232
233 /* We do this so libmad doesn't try to call codec_calloc(). This needs to
234 * be called before mad_stream_init(), mad_frame_inti() and
235 * mad_synth_init(). */
236 frame.overlap = &mad_frame_overlap;
237 stream.main_data = &mad_main_data;
238
239 /* Call mad initialization. Those will zero the arrays frame.overlap,
240 * frame.sbsample and frame.sbsample_prev. Therefore there is no need to
241 * zero them here. */
242 mad_stream_init(&stream);
243 mad_frame_init(&frame);
244 mad_synth_init(&synth);
245}
246
247/* Sync audio stream to a particular frame - see main decoder loop for
248 * detailed remarks */
249static int audio_sync(struct audio_thread_data *td,
250 struct str_sync_data *sd)
251{
252 int retval = STREAM_MATCH;
253 uint32_t sdtime = TS_TO_TICKS(clip_time(&audio_str, sd->time));
254 uint32_t time;
255 uint32_t duration = 0;
256 struct stream *str;
257 struct stream tmp_str;
258 struct mad_header header;
259 struct mad_stream stream;
260
261 if (td->ev.id == STREAM_SYNC)
262 {
263 /* Actually syncing for playback - use real stream */
264 time = 0;
265 str = &audio_str;
266 }
267 else
268 {
269 /* Probing - use temp stream */
270 time = INVALID_TIMESTAMP;
271 str = &tmp_str;
272 str->id = audio_str.id;
273 }
274
275 str->hdr.pos = sd->sk.pos;
276 str->hdr.limit = sd->sk.pos + sd->sk.len;
277
278 mad_stream_init(&stream);
279 mad_header_init(&header);
280
281 while (1)
282 {
283 if (audio_buffer(str, STREAM_PM_RANDOM_ACCESS) == STREAM_DATA_END)
284 {
285 DEBUGF("audio_sync:STR_DATA_END\n aqu:%ld swl:%ld swr:%ld\n",
286 (long)audio_queue.used, str->hdr.win_left, str->hdr.win_right);
287 if (audio_queue.used <= MAD_BUFFER_GUARD)
288 goto sync_data_end;
289 }
290
291 stream.error = 0;
292 mad_stream_buffer(&stream, audio_queue.ptr, audio_queue.used);
293
294 if (stream.sync && mad_stream_sync(&stream) < 0)
295 {
296 DEBUGF(" audio: mad_stream_sync failed\n");
297 audio_queue_advance_pos(MAX(audio_queue.curr->size - 1, 1));
298 continue;
299 }
300
301 stream.sync = 0;
302
303 if (mad_header_decode(&header, &stream) < 0)
304 {
305 DEBUGF(" audio: mad_header_decode failed:%s\n",
306 mad_stream_errorstr(&stream));
307 audio_queue_advance_pos(1);
308 continue;
309 }
310
311 duration = 32*MAD_NSBSAMPLES(&header);
312 time = audio_queue.curr->time;
313
314 DEBUGF(" audio: ft:%u t:%u fe:%u nsamp:%u sampr:%u\n",
315 (unsigned)TICKS_TO_TS(time), (unsigned)sd->time,
316 (unsigned)TICKS_TO_TS(time + duration),
317 (unsigned)duration, header.samplerate);
318
319 audio_queue_advance_pos(stream.this_frame - audio_queue.ptr);
320
321 if (time <= sdtime && sdtime < time + duration)
322 {
323 DEBUGF(" audio: ft<=t<fe\n");
324 retval = STREAM_PERFECT_MATCH;
325 break;
326 }
327 else if (time > sdtime)
328 {
329 DEBUGF(" audio: ft>t\n");
330 break;
331 }
332
333 audio_queue_advance_pos(stream.next_frame - audio_queue.ptr);
334 audio_queue.curr->time += duration;
335
336 rb->yield();
337 }
338
339sync_data_end:
340 if (td->ev.id == STREAM_FIND_END_TIME)
341 {
342 if (time != INVALID_TIMESTAMP)
343 {
344 time = TICKS_TO_TS(time);
345 duration = TICKS_TO_TS(duration);
346 sd->time = time + duration;
347 retval = STREAM_PERFECT_MATCH;
348 }
349 else
350 {
351 retval = STREAM_NOT_FOUND;
352 }
353 }
354
355 DEBUGF(" audio header: 0x%02X%02X%02X%02X\n",
356 (unsigned)audio_queue.ptr[0], (unsigned)audio_queue.ptr[1],
357 (unsigned)audio_queue.ptr[2], (unsigned)audio_queue.ptr[3]);
358
359 return retval;
360 (void)td;
361}
362
363static void audio_thread_msg(struct audio_thread_data *td)
364{
365 while (1)
366 {
367 intptr_t reply = 0;
368
369 switch (td->ev.id)
370 {
371 case STREAM_PLAY:
372 td->status = STREAM_PLAYING;
373
374 switch (td->state)
375 {
376 case TSTATE_INIT:
377 td->state = TSTATE_DECODE;
378 case TSTATE_DECODE:
379 case TSTATE_RENDER_WAIT:
380 break;
381
382 case TSTATE_EOS:
383 /* At end of stream - no playback possible so fire the
384 * completion event */
385 stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0);
386 break;
387 }
388
389 break;
390
391 case STREAM_PAUSE:
392 td->status = STREAM_PAUSED;
393 reply = td->state != TSTATE_EOS;
394 break;
395
396 case STREAM_STOP:
397 if (td->state == TSTATE_DATA)
398 stream_clear_notify(&audio_str, DISK_BUF_DATA_NOTIFY);
399
400 td->status = STREAM_STOPPED;
401 td->state = TSTATE_EOS;
402
403 reply = true;
404 break;
405
406 case STREAM_RESET:
407 if (td->state == TSTATE_DATA)
408 stream_clear_notify(&audio_str, DISK_BUF_DATA_NOTIFY);
409
410 td->status = STREAM_STOPPED;
411 td->state = TSTATE_INIT;
412 td->samplerate = 0;
413 td->nchannels = 0;
414
415 init_mad();
416 td->mad_errors = 0;
417
418 audio_queue_reset();
419
420 reply = true;
421 break;
422
423 case STREAM_NEEDS_SYNC:
424 reply = true; /* Audio always needs to */
425 break;
426
427 case STREAM_SYNC:
428 case STREAM_FIND_END_TIME:
429 if (td->state != TSTATE_INIT)
430 break;
431
432 reply = audio_sync(td, (struct str_sync_data *)td->ev.data);
433 break;
434
435 case DISK_BUF_DATA_NOTIFY:
436 /* Our bun is done */
437 if (td->state != TSTATE_DATA)
438 break;
439
440 td->state = TSTATE_DECODE;
441 str_data_notify_received(&audio_str);
442 break;
443
444 case STREAM_QUIT:
445 /* Time to go - make thread exit */
446 td->state = TSTATE_EOS;
447 return;
448 }
449
450 str_reply_msg(&audio_str, reply);
451
452 if (td->status == STREAM_PLAYING)
453 {
454 switch (td->state)
455 {
456 case TSTATE_DECODE:
457 case TSTATE_RENDER_WAIT:
458 /* These return when in playing state */
459 return;
460 }
461 }
462
463 str_get_msg(&audio_str, &td->ev);
464 }
465}
466
467static void audio_thread(void)
468{
469 struct audio_thread_data td;
470#ifdef HAVE_PRIORITY_SCHEDULING
471 /* Up the priority since the core DSP over-yields internally */
472 int old_priority = rb->thread_set_priority(rb->thread_self(),
473 PRIORITY_PLAYBACK-4);
474#endif
475
476 rb->memset(&td, 0, sizeof (td));
477 td.status = STREAM_STOPPED;
478 td.state = TSTATE_EOS;
479
480 /* We need this here to init the EMAC for Coldfire targets */
481 init_mad();
482
483 td.dsp = rb->dsp_get_config(CODEC_IDX_AUDIO);
484 rb->dsp_configure(td.dsp, DSP_SET_OUT_FREQUENCY, CLOCK_RATE);
485#ifdef HAVE_PITCHCONTROL
486 rb->sound_set_pitch(PITCH_SPEED_100);
487 rb->dsp_set_timestretch(PITCH_SPEED_100);
488#endif
489 rb->dsp_configure(td.dsp, DSP_RESET, 0);
490 rb->dsp_configure(td.dsp, DSP_FLUSH, 0);
491 rb->dsp_configure(td.dsp, DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
492
493 goto message_wait;
494
495 /* This is the decoding loop. */
496 while (1)
497 {
498 td.state = TSTATE_DECODE;
499
500 /* Check for any pending messages and process them */
501 if (str_have_msg(&audio_str))
502 {
503 message_wait:
504 /* Wait for a message to be queued */
505 str_get_msg(&audio_str, &td.ev);
506
507 message_process:
508 /* Process a message already dequeued */
509 audio_thread_msg(&td);
510
511 switch (td.state)
512 {
513 /* These states are the only ones that should return */
514 case TSTATE_DECODE: goto audio_decode;
515 case TSTATE_RENDER_WAIT: goto render_wait;
516 /* Anything else is interpreted as an exit */
517 default:
518 {
519#ifdef HAVE_PRIORITY_SCHEDULING
520 rb->thread_set_priority(rb->thread_self(), old_priority);
521#endif
522 return;
523 }
524 }
525 }
526
527 audio_decode:
528
529 /** Buffering **/
530 switch (audio_buffer(&audio_str, STREAM_PM_STREAMING))
531 {
532 case STREAM_DATA_NOT_READY:
533 {
534 td.state = TSTATE_DATA;
535 goto message_wait;
536 } /* STREAM_DATA_NOT_READY: */
537
538 case STREAM_DATA_END:
539 {
540 if (audio_queue.used > MAD_BUFFER_GUARD)
541 break; /* Still have frames to decode */
542
543 /* Used up remainder of compressed audio buffer. Wait for
544 * samples on PCM buffer to finish playing. */
545 audio_queue_reset();
546
547 while (1)
548 {
549 if (pcm_output_empty())
550 {
551 td.state = TSTATE_EOS;
552 stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0);
553 break;
554 }
555
556 pcm_output_drain();
557 str_get_msg_w_tmo(&audio_str, &td.ev, 1);
558
559 if (td.ev.id != SYS_TIMEOUT)
560 break;
561 }
562
563 goto message_wait;
564 } /* STREAM_DATA_END: */
565 }
566
567 /** Decoding **/
568 mad_stream_buffer(&stream, audio_queue.ptr, audio_queue.used);
569
570 int mad_stat = mad_frame_decode(&frame, &stream);
571
572 ssize_t len = stream.next_frame - audio_queue.ptr;
573
574 if (mad_stat != 0)
575 {
576 DEBUGF("audio: Stream error: %s\n",
577 mad_stream_errorstr(&stream));
578
579 /* If something's goofed - try to perform resync by moving
580 * at least one byte at a time */
581 audio_queue_advance_pos(MAX(len, 1));
582
583 if (stream.error == MAD_ERROR_BUFLEN)
584 {
585 /* This makes the codec support partially corrupted files */
586 if (++td.mad_errors <= MPA_MAX_FRAME_SIZE)
587 {
588 stream.error = 0;
589 rb->yield();
590 continue;
591 }
592 DEBUGF("audio: Too many errors\n");
593 }
594 else if (MAD_RECOVERABLE(stream.error))
595 {
596 /* libmad says it can recover - just keep on decoding */
597 rb->yield();
598 continue;
599 }
600 else
601 {
602 /* Some other unrecoverable error */
603 DEBUGF("audio: Unrecoverable error\n");
604 }
605
606 /* This is too hard - bail out */
607 td.state = TSTATE_EOS;
608 td.status = STREAM_ERROR;
609 stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0);
610
611 goto message_wait;
612 }
613
614 /* Adjust sizes by the frame size */
615 audio_queue_advance_pos(len);
616 td.mad_errors = 0; /* Clear errors */
617
618 /* Generate the pcm samples */
619 mad_synth_frame(&synth, &frame);
620
621 /** Output **/
622 if (frame.header.samplerate != td.samplerate)
623 {
624 td.samplerate = frame.header.samplerate;
625 rb->dsp_configure(td.dsp, DSP_SET_FREQUENCY,
626 td.samplerate);
627 }
628
629 if (MAD_NCHANNELS(&frame.header) != td.nchannels)
630 {
631 td.nchannels = MAD_NCHANNELS(&frame.header);
632 rb->dsp_configure(td.dsp, DSP_SET_STEREO_MODE,
633 td.nchannels == 1 ?
634 STEREO_MONO : STEREO_NONINTERLEAVED);
635 }
636
637 td.src.remcount = synth.pcm.length;
638 td.src.pin[0] = synth.pcm.samples[0];
639 td.src.pin[1] = synth.pcm.samples[1];
640 td.src.proc_mask = 0;
641
642 td.state = TSTATE_RENDER_WAIT;
643
644 /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */
645 render_wait:
646 rb->yield();
647
648 while (1)
649 {
650 struct dsp_buffer dst;
651 dst.remcount = 0;
652 dst.bufcount = MAX(td.src.remcount, 1024);
653
654 ssize_t size = dst.bufcount * 2 * sizeof(int16_t);
655
656 /* Wait for required amount of free buffer space */
657 while ((dst.p16out = pcm_output_get_buffer(&size)) == NULL)
658 {
659 /* Wait one frame */
660 int timeout = dst.bufcount*HZ / td.samplerate;
661 str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1));
662 if (td.ev.id != SYS_TIMEOUT)
663 goto message_process;
664 }
665
666 dst.bufcount = size / (2 * sizeof (int16_t));
667 rb->dsp_process(td.dsp, &td.src, &dst);
668
669 if (dst.remcount > 0)
670 {
671 /* Make this data available to DMA */
672 pcm_output_commit_data(dst.remcount * 2 * sizeof(int16_t),
673 audio_queue.curr->time);
674
675 /* As long as we're on this timestamp, the time is just
676 incremented by the number of samples */
677 audio_queue.curr->time += dst.remcount;
678 }
679 else if (td.src.remcount <= 0)
680 {
681 break;
682 }
683 }
684 } /* end decoding loop */
685}
686
687/* Initializes the audio thread resources and starts the thread */
688bool audio_thread_init(void)
689{
690 /* Initialise the encoded audio buffer and its descriptors */
691 audio_queue.start = mpeg_malloc(AUDIOBUF_ALLOC_SIZE,
692 MPEG_ALLOC_AUDIOBUF);
693 if (audio_queue.start == NULL)
694 return false;
695
696 /* Start the audio thread */
697 audio_str.hdr.q = &audio_str_queue;
698 rb->queue_init(audio_str.hdr.q, false);
699
700 /* We steal the codec thread for audio */
701 rb->codec_thread_do_callback(audio_thread, &audio_str.thread);
702
703 rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send,
704 audio_str.thread);
705
706 /* Wait for thread to initialize */
707 str_send_msg(&audio_str, STREAM_NULL, 0);
708
709 return true;
710}
711
712/* Stops the audio thread */
713void audio_thread_exit(void)
714{
715 if (audio_str.thread != 0)
716 {
717 str_post_msg(&audio_str, STREAM_QUIT, 0);
718 rb->codec_thread_do_callback(NULL, NULL);
719 audio_str.thread = 0;
720 }
721}