]> git.sesse.net Git - vlc/blob - src/input/clock.c
Do not pre-buffer too much, it has side effects with the current es_out code.
[vlc] / src / input / clock.c
1 /*****************************************************************************
2  * clock.c: Clock/System date convertions, stream management
3  *****************************************************************************
4  * Copyright (C) 1999-2008 the VideoLAN team
5  * Copyright (C) 2008 Laurent Aimar
6  * $Id$
7  *
8  * Authors: Christophe Massiot <massiot@via.ecp.fr>
9  *          Laurent Aimar < fenrir _AT_ videolan _DOT_ org >
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
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 General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_input.h>
35 #include "clock.h"
36 #include <assert.h>
37
38 /* TODO:
39  * - clean up locking once clock code is stable
40  *
41  */
42
43 /*
44  * DISCUSSION : SYNCHRONIZATION METHOD
45  *
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 :
53  *
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.
58  *
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.
66  *
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.
69  */
70
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)
75  */
76
77
78 /*****************************************************************************
79  * Constants
80  *****************************************************************************/
81
82 /* Maximum gap allowed between two CRs. */
83 #define CR_MAX_GAP (INT64_C(2000000)*100/9)
84
85 /* Latency introduced on DVDs with CR == 0 on chapter change - this is from
86  * my dice --Meuuh */
87 #define CR_MEAN_PTS_GAP (300000)
88
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).
91  */
92 #define CR_BUFFERING_RATE (48)
93
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.
97  */
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)
101
102 /*****************************************************************************
103  * Structures
104  *****************************************************************************/
105
106 /**
107  * This structure holds long term average
108  */
109 typedef struct
110 {
111     mtime_t i_value;
112     int     i_residue;
113
114     int     i_count;
115     int     i_divider;
116 } average_t;
117 static void    AvgInit( average_t *, int i_divider );
118 static void    AvgClean( average_t * );
119
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 );
124
125 /* */
126 typedef struct
127 {
128     mtime_t i_stream;
129     mtime_t i_system;
130 } clock_point_t;
131
132 static inline clock_point_t clock_point_Create( mtime_t i_stream, mtime_t i_system )
133 {
134     clock_point_t p = { .i_stream = i_stream, .i_system = i_system };
135     return p;
136 }
137
138 /* */
139 #define INPUT_CLOCK_LATE_COUNT (3)
140
141 /* */
142 struct input_clock_t
143 {
144     /* */
145     vlc_mutex_t lock;
146
147     /* Reference point */
148     bool          b_has_reference;
149     clock_point_t ref;
150
151     /* Last point
152      * It is used to detect unexpected stream discontinuities */
153     clock_point_t last;
154
155     /* Maximal timestamp returned by input_clock_ConvertTS (in system unit) */
156     mtime_t i_ts_max;
157
158     /* Amount of extra buffering expressed in stream clock */
159     mtime_t i_buffering_duration;
160
161     /* Clock drift */
162     mtime_t i_next_drift_update;
163     average_t drift;
164
165     /* Late statistics */
166     struct
167     {
168         mtime_t  pi_value[INPUT_CLOCK_LATE_COUNT];
169         unsigned i_index;
170     } late;
171
172     /* Current modifiers */
173     int     i_rate;
174     mtime_t i_pts_delay;
175     bool    b_paused;
176     mtime_t i_pause_date;
177 };
178
179 static mtime_t ClockStreamToSystem( input_clock_t *, mtime_t i_stream );
180 static mtime_t ClockSystemToStream( input_clock_t *, mtime_t i_system );
181
182 static mtime_t ClockGetTsOffset( input_clock_t * );
183
184 /*****************************************************************************
185  * input_clock_New: create a new clock
186  *****************************************************************************/
187 input_clock_t *input_clock_New( int i_rate )
188 {
189     input_clock_t *cl = malloc( sizeof(*cl) );
190     if( !cl )
191         return NULL;
192
193     vlc_mutex_init( &cl->lock );
194     cl->b_has_reference = false;
195     cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
196
197     cl->last = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
198
199     cl->i_ts_max = VLC_TS_INVALID;
200
201     cl->i_buffering_duration = 0;
202
203     cl->i_next_drift_update = VLC_TS_INVALID;
204     AvgInit( &cl->drift, 10 );
205
206     cl->late.i_index = 0;
207     for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ )
208         cl->late.pi_value[i] = 0;
209
210     cl->i_rate = i_rate;
211     cl->i_pts_delay = 0;
212     cl->b_paused = false;
213     cl->i_pause_date = VLC_TS_INVALID;
214
215     return cl;
216 }
217
218 /*****************************************************************************
219  * input_clock_Delete: destroy a new clock
220  *****************************************************************************/
221 void input_clock_Delete( input_clock_t *cl )
222 {
223     AvgClean( &cl->drift );
224     vlc_mutex_destroy( &cl->lock );
225     free( cl );
226 }
227
228 /*****************************************************************************
229  * input_clock_Update: manages a clock reference
230  *
231  *  i_ck_stream: date in stream clock
232  *  i_ck_system: date in system clock
233  *****************************************************************************/
234 void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
235                          bool *pb_late,
236                          bool b_can_pace_control, bool b_buffering_allowed,
237                          mtime_t i_ck_stream, mtime_t i_ck_system )
238 {
239     bool b_reset_reference = false;
240
241     assert( i_ck_stream > VLC_TS_INVALID && i_ck_system > VLC_TS_INVALID );
242
243     vlc_mutex_lock( &cl->lock );
244
245     if( !cl->b_has_reference )
246     {
247         /* */
248         b_reset_reference= true;
249     }
250     else if( cl->last.i_stream > VLC_TS_INVALID &&
251              ( (cl->last.i_stream - i_ck_stream) > CR_MAX_GAP ||
252                (cl->last.i_stream - i_ck_stream) < -CR_MAX_GAP ) )
253     {
254         /* Stream discontinuity, for which we haven't received a
255          * warning from the stream control facilities (dd-edited
256          * stream ?). */
257         msg_Warn( p_log, "clock gap, unexpected stream discontinuity" );
258         cl->i_ts_max = VLC_TS_INVALID;
259
260         /* */
261         msg_Warn( p_log, "feeding synchro with a new reference point trying to recover from clock gap" );
262         b_reset_reference= true;
263     }
264
265     /* */
266     if( b_reset_reference )
267     {
268         cl->i_next_drift_update = VLC_TS_INVALID;
269         AvgReset( &cl->drift );
270
271         /* Feed synchro with a new reference point. */
272         cl->b_has_reference = true;
273         cl->ref = clock_point_Create( i_ck_stream,
274                                       __MAX( cl->i_ts_max + CR_MEAN_PTS_GAP, i_ck_system ) );
275     }
276
277     /* Compute the drift between the stream clock and the system clock
278      * when we don't control the source pace */
279     if( !b_can_pace_control && cl->i_next_drift_update < i_ck_system )
280     {
281         const mtime_t i_converted = ClockSystemToStream( cl, i_ck_system );
282
283         AvgUpdate( &cl->drift, i_converted - i_ck_stream );
284
285         cl->i_next_drift_update = i_ck_system + CLOCK_FREQ/5; /* FIXME why that */
286     }
287
288     /* Update the extra buffering value */
289     if( !b_can_pace_control || b_reset_reference )
290     {
291         cl->i_buffering_duration = 0;
292     }
293     else if( b_buffering_allowed )
294     {
295         /* Try to bufferize more than necessary by reading
296          * CR_BUFFERING_RATE/256 faster until we have CR_BUFFERING_TARGET.
297          */
298         const mtime_t i_duration = __MAX( i_ck_stream - cl->last.i_stream, 0 );
299
300         cl->i_buffering_duration += ( i_duration * CR_BUFFERING_RATE + 255 ) / 256;
301         if( cl->i_buffering_duration > CR_BUFFERING_TARGET )
302             cl->i_buffering_duration = CR_BUFFERING_TARGET;
303     }
304     //fprintf( stderr, "input_clock_Update: %d :: %lld\n", b_buffering_allowed, cl->i_buffering_duration/1000 );
305
306     /* */
307     cl->last = clock_point_Create( i_ck_stream, i_ck_system );
308
309     /* It does not take the decoder latency into account but it is not really
310      * the goal of the clock here */
311     const mtime_t i_system_expected = ClockStreamToSystem( cl, i_ck_stream + AvgGet( &cl->drift ) );
312     const mtime_t i_late = ( i_ck_system - cl->i_pts_delay ) - i_system_expected;
313     *pb_late = i_late > 0;
314     if( i_late > 0 )
315     {
316         cl->late.pi_value[cl->late.i_index] = i_late;
317         cl->late.i_index = ( cl->late.i_index + 1 ) % INPUT_CLOCK_LATE_COUNT;
318     }
319
320     vlc_mutex_unlock( &cl->lock );
321 }
322
323 /*****************************************************************************
324  * input_clock_Reset:
325  *****************************************************************************/
326 void input_clock_Reset( input_clock_t *cl )
327 {
328     vlc_mutex_lock( &cl->lock );
329
330     cl->b_has_reference = false;
331     cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
332     cl->i_ts_max = VLC_TS_INVALID;
333
334     vlc_mutex_unlock( &cl->lock );
335 }
336
337 /*****************************************************************************
338  * input_clock_ChangeRate:
339  *****************************************************************************/
340 void input_clock_ChangeRate( input_clock_t *cl, int i_rate )
341 {
342     vlc_mutex_lock( &cl->lock );
343
344     if( cl->b_has_reference )
345     {
346         /* Move the reference point (as if we were playing at the new rate
347          * from the start */
348         cl->ref.i_system = cl->last.i_system - (cl->last.i_system - cl->ref.i_system) * i_rate / cl->i_rate;
349     }
350     cl->i_rate = i_rate;
351
352     vlc_mutex_unlock( &cl->lock );
353 }
354
355 /*****************************************************************************
356  * input_clock_ChangePause:
357  *****************************************************************************/
358 void input_clock_ChangePause( input_clock_t *cl, bool b_paused, mtime_t i_date )
359 {
360     vlc_mutex_lock( &cl->lock );
361     assert( (!cl->b_paused) != (!b_paused) );
362
363     if( cl->b_paused )
364     {
365         const mtime_t i_duration = i_date - cl->i_pause_date;
366
367         if( cl->b_has_reference && i_duration > 0 )
368         {
369             cl->ref.i_system += i_duration;
370             cl->last.i_system += i_duration;
371         }
372     }
373     cl->i_pause_date = i_date;
374     cl->b_paused = b_paused;
375
376     vlc_mutex_unlock( &cl->lock );
377 }
378
379 /*****************************************************************************
380  * input_clock_GetWakeup
381  *****************************************************************************/
382 mtime_t input_clock_GetWakeup( input_clock_t *cl )
383 {
384     mtime_t i_wakeup = 0;
385
386     vlc_mutex_lock( &cl->lock );
387
388     /* Synchronized, we can wait */
389     if( cl->b_has_reference )
390         i_wakeup = ClockStreamToSystem( cl, cl->last.i_stream + AvgGet( &cl->drift ) - cl->i_buffering_duration );
391
392     vlc_mutex_unlock( &cl->lock );
393
394     return i_wakeup;
395 }
396
397 /*****************************************************************************
398  * input_clock_ConvertTS
399  *****************************************************************************/
400 int input_clock_ConvertTS( input_clock_t *cl,
401                            int *pi_rate, mtime_t *pi_ts0, mtime_t *pi_ts1,
402                            mtime_t i_ts_bound )
403 {
404     assert( pi_ts0 );
405     vlc_mutex_lock( &cl->lock );
406
407     if( pi_rate )
408         *pi_rate = cl->i_rate;
409
410     if( !cl->b_has_reference )
411     {
412         vlc_mutex_unlock( &cl->lock );
413         *pi_ts0 = VLC_TS_INVALID;
414         if( pi_ts1 )
415             *pi_ts1 = VLC_TS_INVALID;
416         return VLC_EGENERIC;
417     }
418
419     /* */
420     const mtime_t i_ts_buffering = cl->i_buffering_duration * cl->i_rate / INPUT_RATE_DEFAULT;
421     const mtime_t i_ts_delay = cl->i_pts_delay + ClockGetTsOffset( cl );
422
423     /* */
424     if( *pi_ts0 > VLC_TS_INVALID )
425     {
426         *pi_ts0 = ClockStreamToSystem( cl, *pi_ts0 + AvgGet( &cl->drift ) );
427         if( *pi_ts0 > cl->i_ts_max )
428             cl->i_ts_max = *pi_ts0;
429         *pi_ts0 += i_ts_delay;
430     }
431
432     /* XXX we do not ipdate i_ts_max on purpose */
433     if( pi_ts1 && *pi_ts1 > VLC_TS_INVALID )
434     {
435         *pi_ts1 = ClockStreamToSystem( cl, *pi_ts1 + AvgGet( &cl->drift ) ) +
436                   i_ts_delay;
437     }
438
439     vlc_mutex_unlock( &cl->lock );
440
441     /* Check ts validity */
442     if( i_ts_bound != INT64_MAX &&
443         *pi_ts0 > VLC_TS_INVALID && *pi_ts0 >= mdate() + i_ts_delay + i_ts_buffering + i_ts_bound )
444         return VLC_EGENERIC;
445
446     return VLC_SUCCESS;
447 }
448 /*****************************************************************************
449  * input_clock_GetRate: Return current rate
450  *****************************************************************************/
451 int input_clock_GetRate( input_clock_t *cl )
452 {
453     int i_rate;
454
455     vlc_mutex_lock( &cl->lock );
456     i_rate = cl->i_rate;
457     vlc_mutex_unlock( &cl->lock );
458
459     return i_rate;
460 }
461
462 int input_clock_GetState( input_clock_t *cl,
463                           mtime_t *pi_stream_start, mtime_t *pi_system_start,
464                           mtime_t *pi_stream_duration, mtime_t *pi_system_duration )
465 {
466     vlc_mutex_lock( &cl->lock );
467
468     if( !cl->b_has_reference )
469     {
470         vlc_mutex_unlock( &cl->lock );
471         return VLC_EGENERIC;
472     }
473
474     *pi_stream_start = cl->ref.i_stream;
475     *pi_system_start = cl->ref.i_system;
476
477     *pi_stream_duration = cl->last.i_stream - cl->ref.i_stream;
478     *pi_system_duration = cl->last.i_system - cl->ref.i_system;
479
480     vlc_mutex_unlock( &cl->lock );
481
482     return VLC_SUCCESS;
483 }
484
485 void input_clock_ChangeSystemOrigin( input_clock_t *cl, mtime_t i_system )
486 {
487     vlc_mutex_lock( &cl->lock );
488
489     assert( cl->b_has_reference );
490     const mtime_t i_offset = i_system - cl->ref.i_system - ClockGetTsOffset( cl );
491
492     cl->ref.i_system += i_offset;
493     cl->last.i_system += i_offset;
494
495     vlc_mutex_unlock( &cl->lock );
496 }
497
498 #warning "input_clock_SetJitter needs more work"
499 void input_clock_SetJitter( input_clock_t *cl,
500                             mtime_t i_pts_delay, int i_cr_average )
501 {
502     vlc_mutex_lock( &cl->lock );
503
504     /* Update late observations */
505     const mtime_t i_delay_delta = i_pts_delay - cl->i_pts_delay;
506     mtime_t pi_late[INPUT_CLOCK_LATE_COUNT];
507     for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ )
508         pi_late[i] = __MAX( cl->late.pi_value[(cl->late.i_index + 1 + i)%INPUT_CLOCK_LATE_COUNT] - i_delay_delta, 0 );
509
510     for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ )
511         cl->late.pi_value[i] = 0;
512     cl->late.i_index = 0;
513
514     for( int i = 0; i < INPUT_CLOCK_LATE_COUNT; i++ )
515     {
516         if( pi_late[i] <= 0 )
517             continue;
518         cl->late.pi_value[cl->late.i_index] = pi_late[i];
519         cl->late.i_index = ( cl->late.i_index + 1 ) % INPUT_CLOCK_LATE_COUNT;
520     }
521
522     /* TODO always save the value, and when rebuffering use the new one if smaller
523      * TODO when increasing -> force rebuffering
524      */
525     if( cl->i_pts_delay < i_pts_delay )
526         cl->i_pts_delay = i_pts_delay;
527
528     /* */
529     if( i_cr_average < 10 )
530         i_cr_average = 10;
531
532     if( cl->drift.i_divider != i_cr_average )
533         AvgRescale( &cl->drift, i_cr_average );
534
535     vlc_mutex_unlock( &cl->lock );
536 }
537
538 mtime_t input_clock_GetJitter( input_clock_t *cl )
539 {
540     vlc_mutex_lock( &cl->lock );
541
542 #if INPUT_CLOCK_LATE_COUNT != 3
543 #   error "unsupported INPUT_CLOCK_LATE_COUNT"
544 #endif
545     /* Find the median of the last late values
546      * It works pretty well at rejecting bad values
547      *
548      * XXX we only increase pts_delay over time, decreasing it is
549      * not that easy if we want to be robust.
550      */
551     const mtime_t *p = cl->late.pi_value;
552     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]);
553     mtime_t i_pts_delay = cl->i_pts_delay ;
554
555     vlc_mutex_unlock( &cl->lock );
556
557     return i_pts_delay + i_late_median;
558 }
559
560 /*****************************************************************************
561  * ClockStreamToSystem: converts a movie clock to system date
562  *****************************************************************************/
563 static mtime_t ClockStreamToSystem( input_clock_t *cl, mtime_t i_stream )
564 {
565     if( !cl->b_has_reference )
566         return VLC_TS_INVALID;
567
568     return ( i_stream - cl->ref.i_stream ) * cl->i_rate / INPUT_RATE_DEFAULT +
569            cl->ref.i_system;
570 }
571
572 /*****************************************************************************
573  * ClockSystemToStream: converts a system date to movie clock
574  *****************************************************************************
575  * Caution : a valid reference point is needed for this to operate.
576  *****************************************************************************/
577 static mtime_t ClockSystemToStream( input_clock_t *cl, mtime_t i_system )
578 {
579     assert( cl->b_has_reference );
580     return ( i_system - cl->ref.i_system ) * INPUT_RATE_DEFAULT / cl->i_rate +
581             cl->ref.i_stream;
582 }
583
584 /**
585  * It returns timestamp display offset due to ref/last modfied on rate changes
586  * It ensures that currently converted dates are not changed.
587  */
588 static mtime_t ClockGetTsOffset( input_clock_t *cl )
589 {
590     return cl->i_pts_delay * ( cl->i_rate - INPUT_RATE_DEFAULT ) / INPUT_RATE_DEFAULT;
591 }
592
593 /*****************************************************************************
594  * Long term average helpers
595  *****************************************************************************/
596 static void AvgInit( average_t *p_avg, int i_divider )
597 {
598     p_avg->i_divider = i_divider;
599     AvgReset( p_avg );
600 }
601 static void AvgClean( average_t *p_avg )
602 {
603     VLC_UNUSED(p_avg);
604 }
605 static void AvgReset( average_t *p_avg )
606 {
607     p_avg->i_value = 0;
608     p_avg->i_residue = 0;
609     p_avg->i_count = 0;
610 }
611 static void AvgUpdate( average_t *p_avg, mtime_t i_value )
612 {
613     const int i_f0 = __MIN( p_avg->i_divider - 1, p_avg->i_count );
614     const int i_f1 = p_avg->i_divider - i_f0;
615
616     const mtime_t i_tmp = i_f0 * p_avg->i_value + i_f1 * i_value + p_avg->i_residue;
617
618     p_avg->i_value   = i_tmp / p_avg->i_divider;
619     p_avg->i_residue = i_tmp % p_avg->i_divider;
620
621     p_avg->i_count++;
622 }
623 static mtime_t AvgGet( average_t *p_avg )
624 {
625     return p_avg->i_value;
626 }
627 static void AvgRescale( average_t *p_avg, int i_divider )
628 {
629     const mtime_t i_tmp = p_avg->i_value * p_avg->i_divider + p_avg->i_residue;
630
631     p_avg->i_divider = i_divider;
632     p_avg->i_value   = i_tmp / p_avg->i_divider;
633     p_avg->i_residue = i_tmp % p_avg->i_divider;
634 }