diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 49346e36d9e..482fe001f93 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -504,28 +504,32 @@ void VideoStreamPlaybackTheora::update(double p_delta) { ogg_packet op; while (!audio_ready && !audio_done) { + // Send remaining frames + if (!send_audio()) { + audio_ready = true; + break; + } + float **pcm; int ret = vorbis_synthesis_pcmout(&vd, &pcm); if (ret > 0) { - const int AUXBUF_LEN = 4096; - int to_read = ret; - float aux_buffer[AUXBUF_LEN]; - while (to_read) { - int m = MIN(AUXBUF_LEN / vi.channels, to_read); + int frames_read = 0; + while (frames_read < ret) { + int m = MIN(AUXBUF_LEN / vi.channels, ret - frames_read); int count = 0; for (int j = 0; j < m; j++) { for (int i = 0; i < vi.channels; i++) { - aux_buffer[count++] = pcm[i][j]; + audio_buffer[count++] = pcm[i][frames_read + j]; } } - int mixed = mix_callback(mix_udata, aux_buffer, m); - to_read -= mixed; - if (mixed != m) { //could mix no more + frames_read += m; + audio_ptr_end = m; + if (!send_audio()) { audio_ready = true; break; } } - vorbis_synthesis_read(&vd, ret - to_read); + vorbis_synthesis_read(&vd, frames_read); } else { /* no pending audio; is there a pending packet to decode? */ if (ogg_stream_packetout(&vo, &op) > 0) { @@ -649,6 +653,8 @@ void VideoStreamPlaybackTheora::seek(double p_time) { audio_done = !has_audio; theora_eos = false; vorbis_eos = false; + audio_ptr_start = 0; + audio_ptr_end = 0; ogg_stream_reset(&to); if (has_audio) { diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 89257ff59b4..97893c27a97 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -52,6 +52,11 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { Point2i size; Rect2i region; + const static int AUXBUF_LEN = 4096; + float audio_buffer[AUXBUF_LEN]; + int audio_ptr_start; + int audio_ptr_end; + int buffer_data(); int queue_page(ogg_page *page); int read_page(ogg_page *page); @@ -108,6 +113,20 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { protected: void clear(); + _FORCE_INLINE_ bool send_audio() { + if (audio_ptr_end > 0) { + int mixed = mix_callback(mix_udata, &audio_buffer[audio_ptr_start * vi.channels], audio_ptr_end - audio_ptr_start); + audio_ptr_start += mixed; + if (audio_ptr_start == audio_ptr_end) { + audio_ptr_start = 0; + audio_ptr_end = 0; + } else { + return false; + } + } + return true; + } + public: virtual void play() override; virtual void stop() override;