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

Revision 9816, 4.0 kB (checked in by robert, 5 years ago)

From Tanguy Fautre (Aris Technologies), ffmpeg plugin

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