From 9d822660324c2284d371f7560e8fdd4b4564861e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 15 Dec 2009 11:27:28 +0000 Subject: [PATCH] From Julen Garcia, "So here is the code with a proper audio sync (at least in my computer)" --- src/osgPlugins/ffmpeg/FFmpegClocks.cpp | 56 ++++++++++++-------- src/osgPlugins/ffmpeg/FFmpegClocks.hpp | 5 +- src/osgPlugins/ffmpeg/FFmpegDecoder.cpp | 2 + src/osgPlugins/ffmpeg/FFmpegDecoderAudio.cpp | 1 - src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp | 1 - 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/osgPlugins/ffmpeg/FFmpegClocks.cpp b/src/osgPlugins/ffmpeg/FFmpegClocks.cpp index 8ec87ceff..9a6d2cf2d 100644 --- a/src/osgPlugins/ffmpeg/FFmpegClocks.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegClocks.cpp @@ -39,7 +39,6 @@ FFmpegClocks::FFmpegClocks() : m_audio_buffer_end_pts(0), m_audio_delay(0.0), m_audio_disabled(false), - m_rewind(false), m_paused(false), m_last_current_time(0.0) { @@ -59,6 +58,9 @@ void FFmpegClocks::reset(const double start_time) m_last_frame_pts = start_time - m_last_frame_delay; m_frame_time = start_time; + m_pause_time = 0; + m_seek_time = 0; + m_audio_buffer_end_pts = start_time; m_audio_timer.setStartTick(); } @@ -68,39 +70,41 @@ void FFmpegClocks::pause(bool pause) if(pause) m_paused = true; else + { m_paused = false; + if(!m_audio_disabled) m_audio_timer.setStartTick(); + } } -void FFmpegClocks::rewindAudio() +void FFmpegClocks::rewind() { ScopedLock lock(m_mutex); + m_pause_time = 0; + m_seek_time = 0; + m_audio_buffer_end_pts = m_start_time; m_audio_timer.setStartTick(); - m_rewind = ! m_rewind; -} - - - -void FFmpegClocks::rewindVideo() -{ - ScopedLock lock(m_mutex); + m_last_frame_delay = 0.040; + m_frame_time = m_start_time; if (m_audio_disabled) return; - m_video_clock = m_start_time; - - m_last_frame_delay = 0.040; - m_last_frame_pts = m_start_time - m_last_frame_delay; - m_frame_time = m_start_time; - - m_rewind = ! m_rewind; + m_video_clock = m_start_time; } +void FFmpegClocks::seek(double seek_time) +{ + ScopedLock lock(m_mutex); + + m_video_clock = seek_time; + m_last_frame_delay = 0.040; + m_frame_time = seek_time; +} void FFmpegClocks::audioSetBufferEndPts(const double pts) @@ -179,8 +183,13 @@ double FFmpegClocks::videoRefreshSchedule(const double pts) // If incorrect delay, use previous one + if (delay <= 0.0 || delay >= 1.0) + { delay = m_last_frame_delay; + if(!m_audio_disabled) m_frame_time = pts - delay; + } + // Save for next time m_last_frame_delay = delay; @@ -193,9 +202,7 @@ double FFmpegClocks::videoRefreshSchedule(const double pts) m_frame_time += delay; const double audio_time = getAudioTime(); - const double actual_delay = (! m_rewind) ? - clamp(m_frame_time - audio_time, -0.5*delay, 2.5*delay) : - m_last_actual_delay; // when rewinding audio or video (but the other has yet to be), get the last used delay + const double actual_delay = clamp(m_frame_time - audio_time, -0.5*delay, 2.5*delay); //m_frame_time += delay; @@ -224,21 +231,24 @@ void FFmpegClocks::setPauseTime(double pause_time) void FFmpegClocks::setSeekTime(double seek_time) { - m_seek_time = getAudioTime() - seek_time; + m_seek_time += getAudioTime() - seek_time; } double FFmpegClocks::getAudioTime() const { - return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_pause_time - m_audio_delay; + if(m_audio_disabled) + return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_pause_time - m_audio_delay - m_seek_time; + else + return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_audio_delay; } double FFmpegClocks::getCurrentTime() { if(!m_paused) - m_last_current_time = getAudioTime() - m_seek_time; // synced with audio + m_last_current_time = getAudioTime(); return m_last_current_time; } diff --git a/src/osgPlugins/ffmpeg/FFmpegClocks.hpp b/src/osgPlugins/ffmpeg/FFmpegClocks.hpp index 5fa165228..1fc7a1b91 100644 --- a/src/osgPlugins/ffmpeg/FFmpegClocks.hpp +++ b/src/osgPlugins/ffmpeg/FFmpegClocks.hpp @@ -23,8 +23,8 @@ public: void reset(double start_time); void pause(bool pause); - void rewindAudio(); - void rewindVideo(); + void seek(double seek_time); + void rewind(); void audioSetBufferEndPts(double pts); void audioAdjustBufferEndPts(double increment); @@ -63,7 +63,6 @@ private: double m_audio_delay; Timer m_audio_timer; bool m_audio_disabled; - bool m_rewind; bool m_paused; double m_last_current_time; diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp b/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp index 796d642d7..460d1b77a 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp @@ -367,6 +367,7 @@ void FFmpegDecoder::rewindButDontFlushQueues() if (av_seek_frame(m_format_context.get(), m_video_index, seek_target, 0/*AVSEEK_FLAG_BYTE |*/ /*AVSEEK_FLAG_BACKWARD*/) < 0) throw std::runtime_error("av_seek_frame failed()"); + m_clocks.rewind(); m_state = REWINDING; } @@ -392,6 +393,7 @@ void FFmpegDecoder::seekButDontFlushQueues(double time) if (av_seek_frame(m_format_context.get(), m_video_index, seek_target, 0/*AVSEEK_FLAG_BYTE |*/ /*AVSEEK_FLAG_BACKWARD*/) < 0) throw std::runtime_error("av_seek_frame failed()"); + m_clocks.seek(time); m_state = SEEKING; } diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoderAudio.cpp b/src/osgPlugins/ffmpeg/FFmpegDecoderAudio.cpp index 86c1503d2..7579b5854 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoderAudio.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoderAudio.cpp @@ -322,7 +322,6 @@ size_t FFmpegDecoderAudio::decodeFrame(void * const buffer, const size_t size) else if (m_packet.type == FFmpegPacket::PACKET_FLUSH) { avcodec_flush_buffers(m_context); - m_clocks.rewindAudio(); } // just output silence when we reached the end of stream diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp index 8b2e69d7d..3099d76ca 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoderVideo.cpp @@ -227,7 +227,6 @@ void FFmpegDecoderVideo::decodeLoop() else if (packet.type == FFmpegPacket::PACKET_FLUSH) { avcodec_flush_buffers(m_context); - m_clocks.rewindVideo(); } } }