From Julen Garcia, "So here is the code with a proper audio sync (at least in my computer)"
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -227,7 +227,6 @@ void FFmpegDecoderVideo::decodeLoop()
|
||||
else if (packet.type == FFmpegPacket::PACKET_FLUSH)
|
||||
{
|
||||
avcodec_flush_buffers(m_context);
|
||||
m_clocks.rewindVideo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user