00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <vlc/vlc.h>
00029
00030 #include <vlc/input.h>
00031 #include "input_internal.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static void ClockNewRef( input_clock_t * p_pgrm,
00069 mtime_t i_clock, mtime_t i_sysdate );
00070
00071
00072
00073
00074
00075
00076 #define CR_MAX_GAP 2000000
00077
00078
00079
00080 #define CR_MEAN_PTS_GAP 300000
00081
00082
00083
00084
00085 static mtime_t ClockToSysdate( input_thread_t *p_input,
00086 input_clock_t *cl, mtime_t i_clock )
00087 {
00088 mtime_t i_sysdate = 0;
00089
00090 if( cl->i_synchro_state == SYNCHRO_OK )
00091 {
00092 i_sysdate = (mtime_t)(i_clock - cl->cr_ref)
00093 * (mtime_t)p_input->i_rate
00094 * (mtime_t)300;
00095 i_sysdate /= 27;
00096 i_sysdate /= 1000;
00097 i_sysdate += (mtime_t)cl->sysdate_ref;
00098 }
00099
00100 return( i_sysdate );
00101 }
00102
00103
00104
00105
00106
00107
00108 static mtime_t ClockCurrent( input_thread_t *p_input,
00109 input_clock_t *cl )
00110 {
00111 return( (mdate() - cl->sysdate_ref) * 27 * INPUT_RATE_DEFAULT
00112 / p_input->i_rate / 300
00113 + cl->cr_ref );
00114 }
00115
00116
00117
00118
00119 static void ClockNewRef( input_clock_t *cl,
00120 mtime_t i_clock, mtime_t i_sysdate )
00121 {
00122 cl->cr_ref = i_clock;
00123 cl->sysdate_ref = i_sysdate ;
00124 }
00125
00126
00127
00128
00129
00130 void input_ClockInit( input_clock_t *cl, vlc_bool_t b_master, int i_cr_average )
00131 {
00132 cl->i_synchro_state = SYNCHRO_START;
00133
00134 cl->last_cr = 0;
00135 cl->last_pts = 0;
00136 cl->last_sysdate = 0;
00137 cl->cr_ref = 0;
00138 cl->sysdate_ref = 0;
00139 cl->delta_cr = 0;
00140 cl->i_delta_cr_residue = 0;
00141
00142 cl->i_cr_average = i_cr_average;
00143
00144 cl->b_master = b_master;
00145 }
00146
00147 #if 0
00148
00149
00150
00151
00152
00153 int input_ClockManageControl( input_thread_t * p_input,
00154 input_clock_t *cl, mtime_t i_clock )
00155 {
00156 #if 0
00157 vlc_value_t val;
00158 int i_return_value = UNDEF_S;
00159
00160 vlc_mutex_lock( &p_input->stream.stream_lock );
00161
00162 if( p_input->stream.i_new_status == PAUSE_S )
00163 {
00164 int i_old_status;
00165
00166 vlc_mutex_lock( &p_input->stream.control.control_lock );
00167 i_old_status = p_input->stream.control.i_status;
00168 p_input->stream.control.i_status = PAUSE_S;
00169 vlc_mutex_unlock( &p_input->stream.control.control_lock );
00170
00171 vlc_cond_wait( &p_input->stream.stream_wait,
00172 &p_input->stream.stream_lock );
00173 ClockNewRef( p_pgrm, i_clock, p_pgrm->last_pts > mdate() ?
00174 p_pgrm->last_pts : mdate() );
00175
00176 if( p_input->stream.i_new_status == PAUSE_S )
00177 {
00178
00179 vlc_mutex_lock( &p_input->stream.control.control_lock );
00180 p_input->stream.control.i_status = i_old_status;
00181 vlc_mutex_unlock( &p_input->stream.control.control_lock );
00182
00183 p_input->stream.i_new_status = UNDEF_S;
00184 p_input->stream.i_new_rate = UNDEF_S;
00185 }
00186
00187
00188
00189 i_return_value = PAUSE_S;
00190 }
00191
00192 if( p_input->stream.i_new_status != UNDEF_S )
00193 {
00194 vlc_mutex_lock( &p_input->stream.control.control_lock );
00195
00196 p_input->stream.control.i_status = p_input->stream.i_new_status;
00197
00198 ClockNewRef( p_pgrm, i_clock,
00199 ClockToSysdate( p_input, p_pgrm, i_clock ) );
00200
00201 if( p_input->stream.control.i_status == PLAYING_S )
00202 {
00203 p_input->stream.control.i_rate = DEFAULT_RATE;
00204 p_input->stream.control.b_mute = 0;
00205 }
00206 else
00207 {
00208 p_input->stream.control.i_rate = p_input->stream.i_new_rate;
00209 p_input->stream.control.b_mute = 1;
00210
00211
00212
00213 input_EscapeAudioDiscontinuity( p_input );
00214 }
00215
00216 val.i_int = p_input->stream.control.i_rate;
00217 var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
00218
00219 val.i_int = p_input->stream.control.i_status;
00220 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
00221
00222 p_input->stream.i_new_status = UNDEF_S;
00223 p_input->stream.i_new_rate = UNDEF_S;
00224
00225 vlc_mutex_unlock( &p_input->stream.control.control_lock );
00226 }
00227
00228 vlc_mutex_unlock( &p_input->stream.stream_lock );
00229
00230 return( i_return_value );
00231 #endif
00232 return UNDEF_S;
00233 }
00234 #endif
00235
00236
00237
00238
00239 void input_ClockSetPCR( input_thread_t *p_input,
00240 input_clock_t *cl, mtime_t i_clock )
00241 {
00242 if( ( cl->i_synchro_state != SYNCHRO_OK ) ||
00243 ( i_clock == 0 && cl->last_cr != 0 ) )
00244 {
00245
00246 ClockNewRef( cl, i_clock,
00247 cl->last_pts + CR_MEAN_PTS_GAP > mdate() ?
00248 cl->last_pts + CR_MEAN_PTS_GAP : mdate() );
00249 cl->i_synchro_state = SYNCHRO_OK;
00250
00251 if( p_input->b_can_pace_control && cl->b_master )
00252 {
00253 cl->last_cr = i_clock;
00254 if( !p_input->b_out_pace_control )
00255 {
00256 mtime_t i_wakeup = ClockToSysdate( p_input, cl, i_clock );
00257 while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 )
00258 {
00259 msleep( CLOCK_FREQ );
00260 if( p_input->b_die ) i_wakeup = mdate();
00261 }
00262 mwait( i_wakeup );
00263 }
00264 }
00265 else
00266 {
00267 cl->last_cr = 0;
00268 cl->last_sysdate = 0;
00269 cl->delta_cr = 0;
00270 cl->i_delta_cr_residue = 0;
00271 }
00272 }
00273 else
00274 {
00275 if ( cl->last_cr != 0 &&
00276 ( (cl->last_cr - i_clock) > CR_MAX_GAP
00277 || (cl->last_cr - i_clock) < - CR_MAX_GAP ) )
00278 {
00279
00280
00281
00282 msg_Warn( p_input, "clock gap, unexpected stream discontinuity" );
00283 input_ClockInit( cl, cl->b_master, cl->i_cr_average );
00284
00285 #if 0
00286 input_EscapeDiscontinuity( p_input );
00287 #endif
00288 }
00289
00290 cl->last_cr = i_clock;
00291
00292 if( p_input->b_can_pace_control && cl->b_master )
00293 {
00294
00295
00296
00297 if( !p_input->b_out_pace_control )
00298 {
00299 mtime_t i_wakeup = ClockToSysdate( p_input, cl, i_clock );
00300 while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 )
00301 {
00302 msleep( CLOCK_FREQ );
00303 if( p_input->b_die ) i_wakeup = mdate();
00304 }
00305 mwait( i_wakeup );
00306 }
00307
00308 #if 0
00309
00310 input_ClockManageControl( p_input, cl, i_clock );
00311 #endif
00312 }
00313 else if ( mdate() - cl->last_sysdate > 200000 )
00314 {
00315
00316 mtime_t i_extrapoled_clock = ClockCurrent( p_input, cl );
00317 mtime_t delta_cr;
00318
00319
00320 delta_cr = ( cl->delta_cr * (cl->i_cr_average - 1)
00321 + ( i_extrapoled_clock - i_clock )
00322 + cl->i_delta_cr_residue )
00323 / cl->i_cr_average;
00324 cl->i_delta_cr_residue = ( cl->delta_cr * (cl->i_cr_average - 1)
00325 + ( i_extrapoled_clock - i_clock )
00326 + cl->i_delta_cr_residue )
00327 % cl->i_cr_average;
00328 cl->delta_cr = delta_cr;
00329 cl->last_sysdate = mdate();
00330 }
00331 }
00332 }
00333
00334
00335
00336
00337 mtime_t input_ClockGetTS( input_thread_t * p_input,
00338 input_clock_t *cl, mtime_t i_ts )
00339 {
00340 if( cl->i_synchro_state != SYNCHRO_OK )
00341 return 0;
00342
00343 cl->last_pts = ClockToSysdate( p_input, cl, i_ts + cl->delta_cr );
00344 return cl->last_pts + p_input->i_pts_delay;
00345 }
00346