diff options
Diffstat (limited to 'apps/plugins/mpegplayer/audio_thread.c')
-rw-r--r-- | apps/plugins/mpegplayer/audio_thread.c | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c index 9e3968007f..ecb8b1ffae 100644 --- a/apps/plugins/mpegplayer/audio_thread.c +++ b/apps/plugins/mpegplayer/audio_thread.c | |||
@@ -112,7 +112,7 @@ static inline void audiodesc_queue_add_tail(void) | |||
112 | audio_queue.write++; | 112 | audio_queue.write++; |
113 | } | 113 | } |
114 | 114 | ||
115 | /* Increments the queue tail position - leaves one slot as current */ | 115 | /* Increments the queue head position - leaves one slot as current */ |
116 | static inline bool audiodesc_queue_remove_head(void) | 116 | static inline bool audiodesc_queue_remove_head(void) |
117 | { | 117 | { |
118 | if (audio_queue.write == audio_queue.read) | 118 | if (audio_queue.write == audio_queue.read) |
@@ -375,8 +375,6 @@ static void audio_thread_msg(struct audio_thread_data *td) | |||
375 | case TSTATE_INIT: | 375 | case TSTATE_INIT: |
376 | td->state = TSTATE_DECODE; | 376 | td->state = TSTATE_DECODE; |
377 | case TSTATE_DECODE: | 377 | case TSTATE_DECODE: |
378 | case TSTATE_RENDER_WAIT: | ||
379 | case TSTATE_RENDER_WAIT_END: | ||
380 | break; | 378 | break; |
381 | 379 | ||
382 | case TSTATE_EOS: | 380 | case TSTATE_EOS: |
@@ -455,7 +453,6 @@ static void audio_thread_msg(struct audio_thread_data *td) | |||
455 | { | 453 | { |
456 | case TSTATE_DECODE: | 454 | case TSTATE_DECODE: |
457 | case TSTATE_RENDER_WAIT: | 455 | case TSTATE_RENDER_WAIT: |
458 | case TSTATE_RENDER_WAIT_END: | ||
459 | /* These return when in playing state */ | 456 | /* These return when in playing state */ |
460 | return; | 457 | return; |
461 | } | 458 | } |
@@ -512,7 +509,6 @@ static void audio_thread(void) | |||
512 | /* These states are the only ones that should return */ | 509 | /* These states are the only ones that should return */ |
513 | case TSTATE_DECODE: goto audio_decode; | 510 | case TSTATE_DECODE: goto audio_decode; |
514 | case TSTATE_RENDER_WAIT: goto render_wait; | 511 | case TSTATE_RENDER_WAIT: goto render_wait; |
515 | case TSTATE_RENDER_WAIT_END: goto render_wait_end; | ||
516 | /* Anything else is interpreted as an exit */ | 512 | /* Anything else is interpreted as an exit */ |
517 | default: | 513 | default: |
518 | { | 514 | { |
@@ -538,29 +534,28 @@ static void audio_thread(void) | |||
538 | case STREAM_DATA_END: | 534 | case STREAM_DATA_END: |
539 | { | 535 | { |
540 | if (audio_queue.used > MAD_BUFFER_GUARD) | 536 | if (audio_queue.used > MAD_BUFFER_GUARD) |
541 | break; | 537 | break; /* Still have frames to decode */ |
542 | 538 | ||
543 | /* Used up remainder of compressed audio buffer. | 539 | /* Used up remainder of compressed audio buffer. Wait for |
544 | * Force any residue to play if audio ended before | 540 | * samples on PCM buffer to finish playing. */ |
545 | * reaching the threshold */ | ||
546 | td.state = TSTATE_RENDER_WAIT_END; | ||
547 | audio_queue_reset(); | 541 | audio_queue_reset(); |
548 | 542 | ||
549 | render_wait_end: | 543 | while (1) |
550 | pcm_output_drain(); | ||
551 | |||
552 | while (pcm_output_used() > (ssize_t)PCMOUT_LOW_WM) | ||
553 | { | 544 | { |
545 | if (pcm_output_empty()) | ||
546 | { | ||
547 | td.state = TSTATE_EOS; | ||
548 | stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | pcm_output_drain(); | ||
554 | str_get_msg_w_tmo(&audio_str, &td.ev, 1); | 553 | str_get_msg_w_tmo(&audio_str, &td.ev, 1); |
554 | |||
555 | if (td.ev.id != SYS_TIMEOUT) | 555 | if (td.ev.id != SYS_TIMEOUT) |
556 | goto message_process; | 556 | break; |
557 | } | 557 | } |
558 | 558 | ||
559 | td.state = TSTATE_EOS; | ||
560 | if (td.status == STREAM_PLAYING) | ||
561 | stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); | ||
562 | |||
563 | rb->yield(); | ||
564 | goto message_wait; | 559 | goto message_wait; |
565 | } /* STREAM_DATA_END: */ | 560 | } /* STREAM_DATA_END: */ |
566 | } | 561 | } |
@@ -606,11 +601,9 @@ static void audio_thread(void) | |||
606 | 601 | ||
607 | /* This is too hard - bail out */ | 602 | /* This is too hard - bail out */ |
608 | td.state = TSTATE_EOS; | 603 | td.state = TSTATE_EOS; |
609 | |||
610 | if (td.status == STREAM_PLAYING) | ||
611 | stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); | ||
612 | |||
613 | td.status = STREAM_ERROR; | 604 | td.status = STREAM_ERROR; |
605 | stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); | ||
606 | |||
614 | goto message_wait; | 607 | goto message_wait; |
615 | } | 608 | } |
616 | 609 | ||
@@ -643,15 +636,15 @@ static void audio_thread(void) | |||
643 | render_wait: | 636 | render_wait: |
644 | if (synth.pcm.length > 0) | 637 | if (synth.pcm.length > 0) |
645 | { | 638 | { |
646 | struct pcm_frame_header *dst_hdr = pcm_output_get_buffer(); | ||
647 | const char *src[2] = | 639 | const char *src[2] = |
648 | { (char *)synth.pcm.samples[0], (char *)synth.pcm.samples[1] }; | 640 | { (char *)synth.pcm.samples[0], (char *)synth.pcm.samples[1] }; |
649 | int out_count = (synth.pcm.length * CLOCK_RATE | 641 | int out_count = (synth.pcm.length * CLOCK_RATE |
650 | + (td.samplerate - 1)) / td.samplerate; | 642 | + (td.samplerate - 1)) / td.samplerate; |
651 | ssize_t size = sizeof(*dst_hdr) + out_count*4; | 643 | unsigned char *out_buf; |
644 | ssize_t size = out_count*4; | ||
652 | 645 | ||
653 | /* Wait for required amount of free buffer space */ | 646 | /* Wait for required amount of free buffer space */ |
654 | while (pcm_output_free() < size) | 647 | while ((out_buf = pcm_output_get_buffer(&size)) == NULL) |
655 | { | 648 | { |
656 | /* Wait one frame */ | 649 | /* Wait one frame */ |
657 | int timeout = out_count*HZ / td.samplerate; | 650 | int timeout = out_count*HZ / td.samplerate; |
@@ -660,21 +653,17 @@ static void audio_thread(void) | |||
660 | goto message_process; | 653 | goto message_process; |
661 | } | 654 | } |
662 | 655 | ||
663 | out_count = rb->dsp_process(td.dsp, dst_hdr->data, src, | 656 | out_count = rb->dsp_process(td.dsp, out_buf, src, synth.pcm.length); |
664 | synth.pcm.length); | ||
665 | 657 | ||
666 | if (out_count <= 0) | 658 | if (out_count <= 0) |
667 | break; | 659 | break; |
668 | 660 | ||
669 | dst_hdr->size = sizeof(*dst_hdr) + out_count*4; | 661 | /* Make this data available to DMA */ |
670 | dst_hdr->time = audio_queue.curr->time; | 662 | pcm_output_commit_data(out_count*4, audio_queue.curr->time); |
671 | 663 | ||
672 | /* As long as we're on this timestamp, the time is just | 664 | /* As long as we're on this timestamp, the time is just |
673 | incremented by the number of samples */ | 665 | incremented by the number of samples */ |
674 | audio_queue.curr->time += out_count; | 666 | audio_queue.curr->time += out_count; |
675 | |||
676 | /* Make this data available to DMA */ | ||
677 | pcm_output_add_data(); | ||
678 | } | 667 | } |
679 | 668 | ||
680 | rb->yield(); | 669 | rb->yield(); |