root/OpenSceneGraph/trunk/src/osgPlugins/ffmpeg/FFmpegClocks.cpp @ 13041

Revision 13041, 4.7 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1
2#include "FFmpegClocks.hpp"
3
4#include <cmath>
5#include <algorithm>
6
7// DEBUG
8//#include <iostream>
9
10
11namespace osgFFmpeg {
12
13
14
15namespace
16{
17
18    const double AV_SYNC_THRESHOLD = 0.01;
19    const double AV_NOSYNC_THRESHOLD = 10.0;
20
21    inline double clamp(const double value, const double min, const double max)
22    {
23        return (std::min)((std::max)(value, min), max);
24    }
25
26}
27
28
29
30FFmpegClocks::FFmpegClocks() :
31    m_video_clock(0),
32    m_start_time(0),
33    m_pause_time(0),
34    m_seek_time(0),
35    m_last_frame_delay(0.040),
36    m_last_frame_pts(0),
37    m_last_actual_delay(0),
38    m_frame_time(0),
39    m_audio_buffer_end_pts(0),
40    m_audio_delay(0.0),
41    m_audio_disabled(false),
42    m_paused(false),
43    m_last_current_time(0.0)
44{
45
46}
47
48
49
50void FFmpegClocks::reset(const double start_time)
51{
52    ScopedLock lock(m_mutex);
53
54    m_video_clock = start_time;
55
56    m_start_time = start_time;
57    m_last_frame_delay = 0.040;
58    m_last_frame_pts = start_time - m_last_frame_delay;
59    m_frame_time = start_time;
60
61    m_pause_time = 0;
62    m_seek_time = 0;
63
64    m_audio_buffer_end_pts = start_time;
65    m_audio_timer.setStartTick();
66}
67
68void FFmpegClocks::pause(bool pause)
69{
70    if(pause)
71        m_paused = true;
72    else
73    {
74        m_paused = false;
75        if(!m_audio_disabled) m_audio_timer.setStartTick();
76    }
77}
78
79
80
81void FFmpegClocks::rewind()
82{
83    ScopedLock lock(m_mutex);
84
85    m_pause_time = 0;
86    m_seek_time = 0;
87
88    m_audio_buffer_end_pts = m_start_time;
89    m_audio_timer.setStartTick();
90
91    m_last_frame_delay = 0.040;
92    m_frame_time = m_start_time;
93
94    if (m_audio_disabled)
95        return;
96
97    m_video_clock = m_start_time;
98}
99
100void FFmpegClocks::seek(double seek_time)
101{
102    ScopedLock lock(m_mutex);
103
104    m_video_clock = seek_time;
105    m_last_frame_delay = 0.040;
106    m_frame_time = seek_time;
107}
108
109
110void FFmpegClocks::audioSetBufferEndPts(const double pts)
111{
112    ScopedLock lock(m_mutex);
113
114    m_audio_buffer_end_pts = pts;
115    m_audio_timer.setStartTick();
116}
117
118
119
120void FFmpegClocks::audioAdjustBufferEndPts(double increment)
121{
122    ScopedLock lock(m_mutex);
123
124    m_audio_buffer_end_pts += increment;
125    m_audio_timer.setStartTick();
126}
127
128
129
130void FFmpegClocks::audioSetDelay(const double delay)
131{
132    m_audio_delay = delay;
133}
134
135
136
137void FFmpegClocks::audioDisable()
138{
139    ScopedLock lock(m_mutex);
140
141    m_audio_disabled = true;
142}
143
144
145
146double FFmpegClocks::videoSynchClock(const AVFrame * const frame, const double time_base, double pts)
147{
148    if (pts != 0)
149    {
150        // If we have a PTS, set the video clock to it.
151        m_video_clock = pts;
152    }
153    else
154    {
155        // Else, if we don't, use the video clock value.
156        pts = m_video_clock;
157    }
158
159    // Update the video clock to take into account the frame delay
160
161    double frame_delay = time_base;
162    frame_delay += frame->repeat_pict * (frame_delay * 0.5);
163
164    m_video_clock += frame_delay;
165
166    return pts;
167}
168
169
170
171double FFmpegClocks::videoRefreshSchedule(const double pts)
172{
173    ScopedLock lock(m_mutex);
174
175    // DEBUG
176    //std::cerr << "ftime / dpts / delay / audio_time / adelay:  ";
177
178    double delay = pts - m_last_frame_pts;
179
180
181    //std::cerr << m_frame_time << "  /  ";
182    //std::cerr << delay << "  /  ";
183
184
185    // If incorrect delay, use previous one
186
187    if (delay <= 0.0 || delay >= 1.0)
188    {
189        delay = m_last_frame_delay;
190        if(!m_audio_disabled) m_frame_time = pts - delay;
191    }
192
193
194    // Save for next time
195    m_last_frame_delay = delay;
196    m_last_frame_pts = pts;
197
198    // Update the delay to synch to the audio stream
199
200    // Ideally the frame time should be incremented after the actual delay is computed.
201    // But because of the sound latency, it seems better to keep some latency in the video too.
202    m_frame_time += delay;
203
204    const double audio_time = getAudioTime();
205    const double actual_delay = clamp(m_frame_time - audio_time, -0.5*delay, 2.5*delay);
206
207    //m_frame_time += delay;
208
209
210    // DEBUG
211    //std::cerr << delay << "  /  ";
212    //std::cerr << audio_time << "  /  ";
213    //std::cerr << actual_delay << std::endl;
214
215    m_last_actual_delay = actual_delay;
216
217    return actual_delay;
218}
219
220
221
222double FFmpegClocks::getStartTime() const
223{
224    return m_start_time;
225}
226
227void FFmpegClocks::setPauseTime(double pause_time)
228{
229    m_pause_time += pause_time;
230}
231
232void FFmpegClocks::setSeekTime(double seek_time)
233{
234    m_seek_time += getAudioTime() - seek_time;
235}
236
237
238
239double FFmpegClocks::getAudioTime() const
240{
241    if(m_audio_disabled)
242        return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_pause_time - m_audio_delay - m_seek_time;
243    else
244        return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_audio_delay;
245}
246
247
248double FFmpegClocks::getCurrentTime()
249{
250    if(!m_paused)
251        m_last_current_time = getAudioTime();
252
253    return m_last_current_time;
254}
255
256} // namespace osgFFmpeg
Note: See TracBrowser for help on using the browser.