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

Revision 10851, 4.6 kB (checked in by robert, 5 years ago)

From Julen Garcia,"I've been lately working also with the ffmpeg plugin and I implemented pause(), seek() and getReferenceTime(). I think that I have solved the internal clock issues (maybe not in the most elegant way :?"

RevLine 
[9816]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),
[10851]33    m_pause_time(0),
34    m_seek_time(0),
[9816]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),
[10851]42    m_rewind(false),
43    m_paused(false),
44    m_last_current_time(0.0)
[9816]45{
46
47}
48
49
50
51void FFmpegClocks::reset(const double start_time)
52{
53    ScopedLock lock(m_mutex);
54
55    m_video_clock = start_time;
56
57    m_start_time = start_time;
58    m_last_frame_delay = 0.040;
59    m_last_frame_pts = start_time - m_last_frame_delay;
60    m_frame_time = start_time;
61
62    m_audio_buffer_end_pts = start_time;
63    m_audio_timer.setStartTick();
64}
65
[10851]66void FFmpegClocks::pause(bool pause)
67{
68    if(pause)
69        m_paused = true;
70    else
71        m_paused = false;
72}
[9816]73
74
[10851]75
[9816]76void FFmpegClocks::rewindAudio()
77{
78    ScopedLock lock(m_mutex);
79
80    m_audio_buffer_end_pts = m_start_time;
81    m_audio_timer.setStartTick();
82
83    m_rewind = ! m_rewind;
84}
85
86
87
88void FFmpegClocks::rewindVideo()
89{
90    ScopedLock lock(m_mutex);
91
92    if (m_audio_disabled)
93        return;
94
95    m_video_clock = m_start_time;
96
97    m_last_frame_delay = 0.040;
98    m_last_frame_pts = m_start_time - m_last_frame_delay;
99    m_frame_time = m_start_time;
100
101    m_rewind = ! m_rewind;
102}
103
104
105
106void FFmpegClocks::audioSetBufferEndPts(const double pts)
107{
108    ScopedLock lock(m_mutex);
109
110    m_audio_buffer_end_pts = pts;
111    m_audio_timer.setStartTick();
112}
113
114
115
116void FFmpegClocks::audioAdjustBufferEndPts(double increment)
117{
118    ScopedLock lock(m_mutex);
119
120    m_audio_buffer_end_pts += increment;
121    m_audio_timer.setStartTick();
122}
123
124
125
126void FFmpegClocks::audioSetDelay(const double delay)
127{
128    m_audio_delay = delay;
129}
130
131
132
133void FFmpegClocks::audioDisable()
134{
135    ScopedLock lock(m_mutex);
136
137    m_audio_disabled = true;
138}
139
140
141
142double FFmpegClocks::videoSynchClock(const AVFrame * const frame, const double time_base, double pts)
143{
144    if (pts != 0)
145    {
146        // If we have a PTS, set the video clock to it.
147        m_video_clock = pts;
148    }
149    else
150    {
151        // Else, if we don't, use the video clock value.
152        pts = m_video_clock;
153    }
154
155    // Update the video clock to take into account the frame delay
156
157    double frame_delay = time_base;
158    frame_delay += frame->repeat_pict * (frame_delay * 0.5);
159
160    m_video_clock += frame_delay;
161
162    return pts;
163}
164
165
166
167double FFmpegClocks::videoRefreshSchedule(const double pts)
168{
169    ScopedLock lock(m_mutex);
170
171    // DEBUG
172    //std::cerr << "ftime / dpts / delay / audio_time / adelay:  ";
173
174    double delay = pts - m_last_frame_pts;
175
176
177    //std::cerr << m_frame_time << "  /  ";
178    //std::cerr << delay << "  /  ";
179
180
181    // If incorrect delay, use previous one
182    if (delay <= 0.0 || delay >= 1.0)
183        delay = m_last_frame_delay;
184
185    // Save for next time
186    m_last_frame_delay = delay;
187    m_last_frame_pts = pts;
188
189    // Update the delay to synch to the audio stream
190
191    // Ideally the frame time should be incremented after the actual delay is computed.
192    // But because of the sound latency, it seems better to keep some latency in the video too.
193    m_frame_time += delay;
194
195    const double audio_time = getAudioTime();
196    const double actual_delay = (! m_rewind) ?
197        clamp(m_frame_time - audio_time, -0.5*delay, 2.5*delay) :
198        m_last_actual_delay; // when rewinding audio or video (but the other has yet to be), get the last used delay
199
200    //m_frame_time += delay;
201
202
203    // DEBUG
204    //std::cerr << delay << "  /  ";
205    //std::cerr << audio_time << "  /  ";
206    //std::cerr << actual_delay << std::endl;
207
208    m_last_actual_delay = actual_delay;
209
210    return actual_delay;
211}
212
213
214
215double FFmpegClocks::getStartTime() const
216{
217    return m_start_time;
218}
219
[10851]220void FFmpegClocks::setPauseTime(double pause_time)
221{
222    m_pause_time += pause_time;
223}
[9816]224
[10851]225void FFmpegClocks::setSeekTime(double seek_time)
226{
227    m_seek_time = getAudioTime() - seek_time;
228}
[9816]229
[10851]230
231
[9816]232double FFmpegClocks::getAudioTime() const
233{
[10851]234    return m_audio_buffer_end_pts + m_audio_timer.time_s() - m_pause_time - m_audio_delay;
[9816]235}
236
237
[10851]238double FFmpegClocks::getCurrentTime()
239{
240    if(!m_paused)
241        m_last_current_time = getAudioTime() - m_seek_time; // synced with audio
242   
243    return m_last_current_time; 
244}
[9816]245
246} // namespace osgFFmpeg
Note: See TracBrowser for help on using the browser.