1 /*****************************************************************************
2 * clock.c: Clock/System date convertions, stream management
3 *****************************************************************************
4 * Copyright (C) 1999-2008 VLC authors and VideoLAN
5 * Copyright (C) 2008 Laurent Aimar
8 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * Laurent Aimar < fenrir _AT_ videolan _DOT_ org >
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_input.h>
39 * - clean up locking once clock code is stable
44 * DISCUSSION : SYNCHRONIZATION METHOD
46 * In some cases we can impose the pace of reading (when reading from a
47 * file or a pipe), and for the synchronization we simply sleep() until
48 * it is time to deliver the packet to the decoders. When reading from
49 * the network, we must be read at the same pace as the server writes,
50 * otherwise the kernel's buffer will trash packets. The risk is now to
51 * overflow the input buffers in case the server goes too fast, that is
52 * why we do these calculations :
54 * We compute a mean for the pcr because we want to eliminate the
55 * network jitter and keep the low frequency variations. The mean is
56 * in fact a low pass filter and the jitter is a high frequency signal
57 * that is why it is eliminated by the filter/average.
59 * The low frequency variations enable us to synchronize the client clock
60 * with the server clock because they represent the time variation between
61 * the 2 clocks. Those variations (ie the filtered pcr) are used to compute
62 * the presentation dates for the audio and video frames. With those dates
63 * we can decode (or trash) the MPEG2 stream at "exactly" the same rate
64 * as it is sent by the server and so we keep the synchronization between
65 * the server and the client.
67 * It is a very important matter if you want to avoid underflow or overflow
68 * in all the FIFOs, but it may be not enough.
71 /* i_cr_average : Maximum number of samples used to compute the
72 * dynamic average value.
73 * We use the following formula :
74 * new_average = (old_average * c_average + new_sample_value) / (c_average +1)
78 /*****************************************************************************
80 *****************************************************************************/
82 /* Maximum gap allowed between two CRs. */
83 #define CR_MAX_GAP (INT64_C(2000000)*100/9)
85 /* Latency introduced on DVDs with CR == 0 on chapter change - this is from
87 #define CR_MEAN_PTS_GAP (300000)
89 /* Rate (in 1/256) at which we will read faster to try to increase our
90 * internal buffer (if we control the pace of the source).
92 #define CR_BUFFERING_RATE (48)
94 /* Extra internal buffer value (in CLOCK_FREQ)
95 * It is 60s max, remember as it is limited by the size it takes by es_out.c
96 * it can be really large.
98 //#define CR_BUFFERING_TARGET (60000000)
99 /* Due to some problems in es_out, we cannot use a large value yet */
100 #define CR_BUFFERING_TARGET (100000)
102 /*****************************************************************************
104 *****************************************************************************/
107 * This structure holds long term average
117 static void AvgInit( average_t
*, int i_divider
);
118 static void AvgClean( average_t
* );
120 static void AvgReset( average_t
* );
121 static void AvgUpdate( average_t
*, mtime_t i_value
);
122 static mtime_t
AvgGet( average_t
* );
123 static void AvgRescale( average_t
*, int i_divider
);
132 static inline clock_point_t
clock_point_Create( mtime_t i_stream
, mtime_t i_system
)
134 clock_point_t p
= { .i_stream
= i_stream
, .i_system
= i_system
};
139 #define INPUT_CLOCK_LATE_COUNT (3)
148 * It is used to detect unexpected stream discontinuities */
151 /* Maximal timestamp returned by input_clock_ConvertTS (in system unit) */
154 /* Amount of extra buffering expressed in stream clock */
155 mtime_t i_buffering_duration
;
158 mtime_t i_next_drift_update
;
161 /* Late statistics */
164 mtime_t pi_value
[INPUT_CLOCK_LATE_COUNT
];
168 /* Reference point */
170 bool b_has_reference
;
172 /* External clock drift */
173 mtime_t i_external_clock
;
174 bool b_has_external_clock
;
176 /* Current modifiers */
180 mtime_t i_pause_date
;
183 static mtime_t
ClockStreamToSystem( input_clock_t
*, mtime_t i_stream
);
184 static mtime_t
ClockSystemToStream( input_clock_t
*, mtime_t i_system
);
186 static mtime_t
ClockGetTsOffset( input_clock_t
* );
188 /*****************************************************************************
189 * input_clock_New: create a new clock
190 *****************************************************************************/
191 input_clock_t
*input_clock_New( int i_rate
)
193 input_clock_t
*cl
= malloc( sizeof(*cl
) );
197 vlc_mutex_init( &cl
->lock
);
198 cl
->b_has_reference
= false;
199 cl
->ref
= clock_point_Create( VLC_TS_INVALID
, VLC_TS_INVALID
);
200 cl
->b_has_external_clock
= false;
202 cl
->last
= clock_point_Create( VLC_TS_INVALID
, VLC_TS_INVALID
);
204 cl
->i_ts_max
= VLC_TS_INVALID
;
206 cl
->i_buffering_duration
= 0;
208 cl
->i_next_drift_update
= VLC_TS_INVALID
;
209 AvgInit( &cl
->drift
, 10 );
211 cl
->late
.i_index
= 0;
212 for( int i
= 0; i
< INPUT_CLOCK_LATE_COUNT
; i
++ )
213 cl
->late
.pi_value
[i
] = 0;
217 cl
->b_paused
= false;
218 cl
->i_pause_date
= VLC_TS_INVALID
;
223 /*****************************************************************************
224 * input_clock_Delete: destroy a new clock
225 *****************************************************************************/
226 void input_clock_Delete( input_clock_t
*cl
)
228 AvgClean( &cl
->drift
);
229 vlc_mutex_destroy( &cl
->lock
);
233 /*****************************************************************************
234 * input_clock_Update: manages a clock reference
236 * i_ck_stream: date in stream clock
237 * i_ck_system: date in system clock
238 *****************************************************************************/
239 void input_clock_Update( input_clock_t
*cl
, vlc_object_t
*p_log
,
241 bool b_can_pace_control
, bool b_buffering_allowed
,
242 mtime_t i_ck_stream
, mtime_t i_ck_system
)
244 bool b_reset_reference
= false;
246 assert( i_ck_stream
> VLC_TS_INVALID
&& i_ck_system
> VLC_TS_INVALID
);
248 vlc_mutex_lock( &cl
->lock
);
250 if( !cl
->b_has_reference
)
253 b_reset_reference
= true;
255 else if( cl
->last
.i_stream
> VLC_TS_INVALID
&&
256 ( (cl
->last
.i_stream
- i_ck_stream
) > CR_MAX_GAP
||
257 (cl
->last
.i_stream
- i_ck_stream
) < -CR_MAX_GAP
) )
259 /* Stream discontinuity, for which we haven't received a
260 * warning from the stream control facilities (dd-edited
262 msg_Warn( p_log
, "clock gap, unexpected stream discontinuity" );
263 cl
->i_ts_max
= VLC_TS_INVALID
;
266 msg_Warn( p_log
, "feeding synchro with a new reference point trying to recover from clock gap" );
267 b_reset_reference
= true;
271 if( b_reset_reference
)
273 cl
->i_next_drift_update
= VLC_TS_INVALID
;
274 AvgReset( &cl
->drift
);
276 /* Feed synchro with a new reference point. */
277 cl
->b_has_reference
= true;
278 cl
->ref
= clock_point_Create( i_ck_stream
,
279 __MAX( cl
->i_ts_max
+ CR_MEAN_PTS_GAP
, i_ck_system
) );
280 cl
->b_has_external_clock
= false;
283 /* Compute the drift between the stream clock and the system clock
284 * when we don't control the source pace */
285 if( !b_can_pace_control
&& cl
->i_next_drift_update
< i_ck_system
)
287 const mtime_t i_converted
= ClockSystemToStream( cl
, i_ck_system
);
289 AvgUpdate( &cl
->drift
, i_converted
- i_ck_stream
);
291 cl
->i_next_drift_update
= i_ck_system
+ CLOCK_FREQ
/5; /* FIXME why that */
294 /* Update the extra buffering value */
295 if( !b_can_pace_control
|| b_reset_reference
)
297 cl
->i_buffering_duration
= 0;
299 else if( b_buffering_allowed
)
301 /* Try to bufferize more than necessary by reading
302 * CR_BUFFERING_RATE/256 faster until we have CR_BUFFERING_TARGET.
304 const mtime_t i_duration
= __MAX( i_ck_stream
- cl
->last
.i_stream
, 0 );
306 cl
->i_buffering_duration
+= ( i_duration
* CR_BUFFERING_RATE
+ 255 ) / 256;
307 if( cl
->i_buffering_duration
> CR_BUFFERING_TARGET
)
308 cl
->i_buffering_duration
= CR_BUFFERING_TARGET
;
310 //fprintf( stderr, "input_clock_Update: %d :: %lld\n", b_buffering_allowed, cl->i_buffering_duration/1000 );
313 cl
->last
= clock_point_Create( i_ck_stream
, i_ck_system
);
315 /* It does not take the decoder latency into account but it is not really
316 * the goal of the clock here */
317 const mtime_t i_system_expected
= ClockStreamToSystem( cl
, i_ck_stream
+ AvgGet( &cl
->drift
) );
318 const mtime_t i_late
= ( i_ck_system
- cl
->i_pts_delay
) - i_system_expected
;
319 *pb_late
= i_late
> 0;
322 cl
->late
.pi_value
[cl
->late
.i_index
] = i_late
;
323 cl
->late
.i_index
= ( cl
->late
.i_index
+ 1 ) % INPUT_CLOCK_LATE_COUNT
;
326 vlc_mutex_unlock( &cl
->lock
);
329 /*****************************************************************************
331 *****************************************************************************/
332 void input_clock_Reset( input_clock_t
*cl
)
334 vlc_mutex_lock( &cl
->lock
);
336 cl
->b_has_reference
= false;
337 cl
->ref
= clock_point_Create( VLC_TS_INVALID
, VLC_TS_INVALID
);
338 cl
->b_has_external_clock
= false;
339 cl
->i_ts_max
= VLC_TS_INVALID
;
341 vlc_mutex_unlock( &cl
->lock
);
344 /*****************************************************************************
345 * input_clock_ChangeRate:
346 *****************************************************************************/
347 void input_clock_ChangeRate( input_clock_t
*cl
, int i_rate
)
349 vlc_mutex_lock( &cl
->lock
);
351 if( cl
->b_has_reference
)
353 /* Move the reference point (as if we were playing at the new rate
355 cl
->ref
.i_system
= cl
->last
.i_system
- (cl
->last
.i_system
- cl
->ref
.i_system
) * i_rate
/ cl
->i_rate
;
359 vlc_mutex_unlock( &cl
->lock
);
362 /*****************************************************************************
363 * input_clock_ChangePause:
364 *****************************************************************************/
365 void input_clock_ChangePause( input_clock_t
*cl
, bool b_paused
, mtime_t i_date
)
367 vlc_mutex_lock( &cl
->lock
);
368 assert( (!cl
->b_paused
) != (!b_paused
) );
372 const mtime_t i_duration
= i_date
- cl
->i_pause_date
;
374 if( cl
->b_has_reference
&& i_duration
> 0 )
376 cl
->ref
.i_system
+= i_duration
;
377 cl
->last
.i_system
+= i_duration
;
380 cl
->i_pause_date
= i_date
;
381 cl
->b_paused
= b_paused
;
383 vlc_mutex_unlock( &cl
->lock
);
386 /*****************************************************************************
387 * input_clock_GetWakeup
388 *****************************************************************************/
389 mtime_t
input_clock_GetWakeup( input_clock_t
*cl
)
391 mtime_t i_wakeup
= 0;
393 vlc_mutex_lock( &cl
->lock
);
395 /* Synchronized, we can wait */
396 if( cl
->b_has_reference
)
397 i_wakeup
= ClockStreamToSystem( cl
, cl
->last
.i_stream
+ AvgGet( &cl
->drift
) - cl
->i_buffering_duration
);
399 vlc_mutex_unlock( &cl
->lock
);
404 /*****************************************************************************
405 * input_clock_ConvertTS
406 *****************************************************************************/
407 int input_clock_ConvertTS( input_clock_t
*cl
,
408 int *pi_rate
, mtime_t
*pi_ts0
, mtime_t
*pi_ts1
,
412 vlc_mutex_lock( &cl
->lock
);
415 *pi_rate
= cl
->i_rate
;
417 if( !cl
->b_has_reference
)
419 vlc_mutex_unlock( &cl
->lock
);
420 *pi_ts0
= VLC_TS_INVALID
;
422 *pi_ts1
= VLC_TS_INVALID
;
427 const mtime_t i_ts_buffering
= cl
->i_buffering_duration
* cl
->i_rate
/ INPUT_RATE_DEFAULT
;
428 const mtime_t i_ts_delay
= cl
->i_pts_delay
+ ClockGetTsOffset( cl
);
431 if( *pi_ts0
> VLC_TS_INVALID
)
433 *pi_ts0
= ClockStreamToSystem( cl
, *pi_ts0
+ AvgGet( &cl
->drift
) );
434 if( *pi_ts0
> cl
->i_ts_max
)
435 cl
->i_ts_max
= *pi_ts0
;
436 *pi_ts0
+= i_ts_delay
;
439 /* XXX we do not ipdate i_ts_max on purpose */
440 if( pi_ts1
&& *pi_ts1
> VLC_TS_INVALID
)
442 *pi_ts1
= ClockStreamToSystem( cl
, *pi_ts1
+ AvgGet( &cl
->drift
) ) +
446 vlc_mutex_unlock( &cl
->lock
);
448 /* Check ts validity */
449 if( i_ts_bound
!= INT64_MAX
&&
450 *pi_ts0
> VLC_TS_INVALID
&& *pi_ts0
>= mdate() + i_ts_delay
+ i_ts_buffering
+ i_ts_bound
)
455 /*****************************************************************************
456 * input_clock_GetRate: Return current rate
457 *****************************************************************************/
458 int input_clock_GetRate( input_clock_t
*cl
)
462 vlc_mutex_lock( &cl
->lock
);
464 vlc_mutex_unlock( &cl
->lock
);
469 int input_clock_GetState( input_clock_t
*cl
,
470 mtime_t
*pi_stream_start
, mtime_t
*pi_system_start
,
471 mtime_t
*pi_stream_duration
, mtime_t
*pi_system_duration
)
473 vlc_mutex_lock( &cl
->lock
);
475 if( !cl
->b_has_reference
)
477 vlc_mutex_unlock( &cl
->lock
);
481 *pi_stream_start
= cl
->ref
.i_stream
;
482 *pi_system_start
= cl
->ref
.i_system
;
484 *pi_stream_duration
= cl
->last
.i_stream
- cl
->ref
.i_stream
;
485 *pi_system_duration
= cl
->last
.i_system
- cl
->ref
.i_system
;
487 vlc_mutex_unlock( &cl
->lock
);
492 void input_clock_ChangeSystemOrigin( input_clock_t
*cl
, bool b_absolute
, mtime_t i_system
)
494 vlc_mutex_lock( &cl
->lock
);
496 assert( cl
->b_has_reference
);
500 i_offset
= i_system
- cl
->ref
.i_system
- ClockGetTsOffset( cl
);
504 if( !cl
->b_has_external_clock
)
506 cl
->b_has_external_clock
= true;
507 cl
->i_external_clock
= i_system
;
509 i_offset
= i_system
- cl
->i_external_clock
;
512 cl
->ref
.i_system
+= i_offset
;
513 cl
->last
.i_system
+= i_offset
;
515 vlc_mutex_unlock( &cl
->lock
);
518 void input_clock_GetSystemOrigin( input_clock_t
*cl
, mtime_t
*pi_system
, mtime_t
*pi_delay
)
520 vlc_mutex_lock( &cl
->lock
);
522 assert( cl
->b_has_reference
);
524 *pi_system
= cl
->ref
.i_system
;
526 *pi_delay
= cl
->i_pts_delay
;
528 vlc_mutex_unlock( &cl
->lock
);
531 #warning "input_clock_SetJitter needs more work"
532 void input_clock_SetJitter( input_clock_t
*cl
,
533 mtime_t i_pts_delay
, int i_cr_average
)
535 vlc_mutex_lock( &cl
->lock
);
537 /* Update late observations */
538 const mtime_t i_delay_delta
= i_pts_delay
- cl
->i_pts_delay
;
539 mtime_t pi_late
[INPUT_CLOCK_LATE_COUNT
];
540 for( int i
= 0; i
< INPUT_CLOCK_LATE_COUNT
; i
++ )
541 pi_late
[i
] = __MAX( cl
->late
.pi_value
[(cl
->late
.i_index
+ 1 + i
)%INPUT_CLOCK_LATE_COUNT
] - i_delay_delta
, 0 );
543 for( int i
= 0; i
< INPUT_CLOCK_LATE_COUNT
; i
++ )
544 cl
->late
.pi_value
[i
] = 0;
545 cl
->late
.i_index
= 0;
547 for( int i
= 0; i
< INPUT_CLOCK_LATE_COUNT
; i
++ )
549 if( pi_late
[i
] <= 0 )
551 cl
->late
.pi_value
[cl
->late
.i_index
] = pi_late
[i
];
552 cl
->late
.i_index
= ( cl
->late
.i_index
+ 1 ) % INPUT_CLOCK_LATE_COUNT
;
555 /* TODO always save the value, and when rebuffering use the new one if smaller
556 * TODO when increasing -> force rebuffering
558 if( cl
->i_pts_delay
< i_pts_delay
)
559 cl
->i_pts_delay
= i_pts_delay
;
562 if( i_cr_average
< 10 )
565 if( cl
->drift
.i_divider
!= i_cr_average
)
566 AvgRescale( &cl
->drift
, i_cr_average
);
568 vlc_mutex_unlock( &cl
->lock
);
571 mtime_t
input_clock_GetJitter( input_clock_t
*cl
)
573 vlc_mutex_lock( &cl
->lock
);
575 #if INPUT_CLOCK_LATE_COUNT != 3
576 # error "unsupported INPUT_CLOCK_LATE_COUNT"
578 /* Find the median of the last late values
579 * It works pretty well at rejecting bad values
581 * XXX we only increase pts_delay over time, decreasing it is
582 * not that easy if we want to be robust.
584 const mtime_t
*p
= cl
->late
.pi_value
;
585 mtime_t i_late_median
= p
[0] + p
[1] + p
[2] - __MIN(__MIN(p
[0],p
[1]),p
[2]) - __MAX(__MAX(p
[0],p
[1]),p
[2]);
586 mtime_t i_pts_delay
= cl
->i_pts_delay
;
588 vlc_mutex_unlock( &cl
->lock
);
590 return i_pts_delay
+ i_late_median
;
593 /*****************************************************************************
594 * ClockStreamToSystem: converts a movie clock to system date
595 *****************************************************************************/
596 static mtime_t
ClockStreamToSystem( input_clock_t
*cl
, mtime_t i_stream
)
598 if( !cl
->b_has_reference
)
599 return VLC_TS_INVALID
;
601 return ( i_stream
- cl
->ref
.i_stream
) * cl
->i_rate
/ INPUT_RATE_DEFAULT
+
605 /*****************************************************************************
606 * ClockSystemToStream: converts a system date to movie clock
607 *****************************************************************************
608 * Caution : a valid reference point is needed for this to operate.
609 *****************************************************************************/
610 static mtime_t
ClockSystemToStream( input_clock_t
*cl
, mtime_t i_system
)
612 assert( cl
->b_has_reference
);
613 return ( i_system
- cl
->ref
.i_system
) * INPUT_RATE_DEFAULT
/ cl
->i_rate
+
618 * It returns timestamp display offset due to ref/last modfied on rate changes
619 * It ensures that currently converted dates are not changed.
621 static mtime_t
ClockGetTsOffset( input_clock_t
*cl
)
623 return cl
->i_pts_delay
* ( cl
->i_rate
- INPUT_RATE_DEFAULT
) / INPUT_RATE_DEFAULT
;
626 /*****************************************************************************
627 * Long term average helpers
628 *****************************************************************************/
629 static void AvgInit( average_t
*p_avg
, int i_divider
)
631 p_avg
->i_divider
= i_divider
;
634 static void AvgClean( average_t
*p_avg
)
638 static void AvgReset( average_t
*p_avg
)
641 p_avg
->i_residue
= 0;
644 static void AvgUpdate( average_t
*p_avg
, mtime_t i_value
)
646 const int i_f0
= __MIN( p_avg
->i_divider
- 1, p_avg
->i_count
);
647 const int i_f1
= p_avg
->i_divider
- i_f0
;
649 const mtime_t i_tmp
= i_f0
* p_avg
->i_value
+ i_f1
* i_value
+ p_avg
->i_residue
;
651 p_avg
->i_value
= i_tmp
/ p_avg
->i_divider
;
652 p_avg
->i_residue
= i_tmp
% p_avg
->i_divider
;
656 static mtime_t
AvgGet( average_t
*p_avg
)
658 return p_avg
->i_value
;
660 static void AvgRescale( average_t
*p_avg
, int i_divider
)
662 const mtime_t i_tmp
= p_avg
->i_value
* p_avg
->i_divider
+ p_avg
->i_residue
;
664 p_avg
->i_divider
= i_divider
;
665 p_avg
->i_value
= i_tmp
/ p_avg
->i_divider
;
666 p_avg
->i_residue
= i_tmp
% p_avg
->i_divider
;