Commit 68d21786 authored by Laurent Aimar's avatar Laurent Aimar

* all: rework of the input.

parent 7d01a7e7
...@@ -25,33 +25,7 @@ ...@@ -25,33 +25,7 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/input.h> #include <vlc/input.h>
#include "ninput.h" #include "input_internal.h"
int access_vaControl( input_thread_t *p_input, int i_query, va_list args )
{
if( p_input->pf_access_control )
{
return p_input->pf_access_control( p_input, i_query, args );
}
return VLC_EGENERIC;
}
int access_Control( input_thread_t *p_input, int i_query, ... )
{
va_list args;
int i_result;
va_start( args, i_query );
i_result = access_vaControl( p_input, i_query, args );
va_end( args );
return i_result;
}
int access_vaControlDefault( input_thread_t *p_input, int i_query, va_list args )
{
return VLC_EGENERIC;
}
/***************************************************************************** /*****************************************************************************
* access2_New: * access2_New:
......
...@@ -24,14 +24,11 @@ ...@@ -24,14 +24,11 @@
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
#include <string.h> /* memcpy(), memset() */ #include <stdlib.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include "stream_control.h" #include <vlc/input.h>
#include "input_ext-intf.h" #include "input_internal.h"
#include "input_ext-dec.h"
#include "input_ext-plugins.h"
/* /*
* DISCUSSION : SYNCHRONIZATION METHOD * DISCUSSION : SYNCHRONIZATION METHOD
...@@ -67,7 +64,8 @@ ...@@ -67,7 +64,8 @@
* new_average = (old_average * c_average + new_sample_value) / (c_average +1) * new_average = (old_average * c_average + new_sample_value) / (c_average +1)
*/ */
static void ClockNewRef( pgrm_descriptor_t * p_pgrm,
static void ClockNewRef( input_clock_t * p_pgrm,
mtime_t i_clock, mtime_t i_sysdate ); mtime_t i_clock, mtime_t i_sysdate );
/***************************************************************************** /*****************************************************************************
...@@ -84,19 +82,19 @@ static void ClockNewRef( pgrm_descriptor_t * p_pgrm, ...@@ -84,19 +82,19 @@ static void ClockNewRef( pgrm_descriptor_t * p_pgrm,
/***************************************************************************** /*****************************************************************************
* ClockToSysdate: converts a movie clock to system date * ClockToSysdate: converts a movie clock to system date
*****************************************************************************/ *****************************************************************************/
static mtime_t ClockToSysdate( input_thread_t * p_input, static mtime_t ClockToSysdate( input_thread_t *p_input,
pgrm_descriptor_t * p_pgrm, mtime_t i_clock ) input_clock_t *cl, mtime_t i_clock )
{ {
mtime_t i_sysdate = 0; mtime_t i_sysdate = 0;
if( p_pgrm->i_synchro_state == SYNCHRO_OK ) if( cl->i_synchro_state == SYNCHRO_OK )
{ {
i_sysdate = (mtime_t)(i_clock - p_pgrm->cr_ref) i_sysdate = (mtime_t)(i_clock - cl->cr_ref)
* (mtime_t)p_input->stream.control.i_rate * (mtime_t)p_input->i_rate
* (mtime_t)300; * (mtime_t)300;
i_sysdate /= 27; i_sysdate /= 27;
i_sysdate /= 1000; i_sysdate /= 1000;
i_sysdate += (mtime_t)p_pgrm->sysdate_ref; i_sysdate += (mtime_t)cl->sysdate_ref;
} }
return( i_sysdate ); return( i_sysdate );
...@@ -107,46 +105,54 @@ static mtime_t ClockToSysdate( input_thread_t * p_input, ...@@ -107,46 +105,54 @@ static mtime_t ClockToSysdate( input_thread_t * p_input,
***************************************************************************** *****************************************************************************
* Caution : the synchro state must be SYNCHRO_OK for this to operate. * Caution : the synchro state must be SYNCHRO_OK for this to operate.
*****************************************************************************/ *****************************************************************************/
static mtime_t ClockCurrent( input_thread_t * p_input, static mtime_t ClockCurrent( input_thread_t *p_input,
pgrm_descriptor_t * p_pgrm ) input_clock_t *cl )
{ {
return( (mdate() - p_pgrm->sysdate_ref) * 27 * DEFAULT_RATE return( (mdate() - cl->sysdate_ref) * 27 * INPUT_RATE_DEFAULT
/ p_input->stream.control.i_rate / 300 / p_input->i_rate / 300
+ p_pgrm->cr_ref ); + cl->cr_ref );
} }
/***************************************************************************** /*****************************************************************************
* ClockNewRef: writes a new clock reference * ClockNewRef: writes a new clock reference
*****************************************************************************/ *****************************************************************************/
static void ClockNewRef( pgrm_descriptor_t * p_pgrm, static void ClockNewRef( input_clock_t *cl,
mtime_t i_clock, mtime_t i_sysdate ) mtime_t i_clock, mtime_t i_sysdate )
{ {
p_pgrm->cr_ref = i_clock; cl->cr_ref = i_clock;
p_pgrm->sysdate_ref = i_sysdate ; cl->sysdate_ref = i_sysdate ;
} }
/***************************************************************************** /*****************************************************************************
* input_ClockInit: reinitializes the clock reference after a stream * input_ClockInit: reinitializes the clock reference after a stream
* discontinuity * discontinuity
*****************************************************************************/ *****************************************************************************/
void input_ClockInit( pgrm_descriptor_t * p_pgrm ) void input_ClockInit( input_clock_t *cl, vlc_bool_t b_master, int i_cr_average )
{ {
p_pgrm->last_cr = 0; cl->i_synchro_state = SYNCHRO_START;
p_pgrm->last_pts = 0;
p_pgrm->cr_ref = 0; cl->last_cr = 0;
p_pgrm->sysdate_ref = 0; cl->last_pts = 0;
p_pgrm->delta_cr = 0; cl->cr_ref = 0;
p_pgrm->c_average_count = 0; cl->sysdate_ref = 0;
cl->delta_cr = 0;
cl->c_average_count = 0;
cl->i_cr_average = i_cr_average;
cl->b_master = b_master;
} }
#if 0
/***************************************************************************** /*****************************************************************************
* input_ClockManageControl: handles the messages from the interface * input_ClockManageControl: handles the messages from the interface
***************************************************************************** *****************************************************************************
* Returns UNDEF_S if nothing happened, PAUSE_S if the stream was paused * Returns UNDEF_S if nothing happened, PAUSE_S if the stream was paused
*****************************************************************************/ *****************************************************************************/
int input_ClockManageControl( input_thread_t * p_input, int input_ClockManageControl( input_thread_t * p_input,
pgrm_descriptor_t * p_pgrm, mtime_t i_clock ) input_clock_t *cl, mtime_t i_clock )
{ {
#if 0
vlc_value_t val; vlc_value_t val;
int i_return_value = UNDEF_S; int i_return_value = UNDEF_S;
...@@ -221,36 +227,32 @@ int input_ClockManageControl( input_thread_t * p_input, ...@@ -221,36 +227,32 @@ int input_ClockManageControl( input_thread_t * p_input,
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
return( i_return_value ); return( i_return_value );
#endif
return UNDEF_S;
} }
#endif
/***************************************************************************** /*****************************************************************************
* input_ClockManageRef: manages a clock reference * input_ClockSetPCR: manages a clock reference
*****************************************************************************/ *****************************************************************************/
void input_ClockManageRef( input_thread_t * p_input, void input_ClockSetPCR( input_thread_t *p_input,
pgrm_descriptor_t * p_pgrm, mtime_t i_clock ) input_clock_t *cl, mtime_t i_clock )
{ {
/* take selected program if none specified */ if( ( cl->i_synchro_state != SYNCHRO_OK ) ||
if( !p_pgrm ) ( i_clock == 0 && cl->last_cr != 0 ) )
{
p_pgrm = p_input->stream.p_selected_program;
}
if( ( p_pgrm->i_synchro_state != SYNCHRO_OK ) ||
( i_clock == 0 && p_pgrm->last_cr != 0 ) )
{ {
/* Feed synchro with a new reference point. */ /* Feed synchro with a new reference point. */
ClockNewRef( p_pgrm, i_clock, ClockNewRef( cl, i_clock,
p_pgrm->last_pts + CR_MEAN_PTS_GAP > mdate() ? cl->last_pts + CR_MEAN_PTS_GAP > mdate() ?
p_pgrm->last_pts + CR_MEAN_PTS_GAP : mdate() ); cl->last_pts + CR_MEAN_PTS_GAP : mdate() );
p_pgrm->i_synchro_state = SYNCHRO_OK; cl->i_synchro_state = SYNCHRO_OK;
if( p_input->stream.b_pace_control if( p_input->b_can_pace_control && cl->b_master )
&& p_input->stream.p_selected_program == p_pgrm )
{ {
p_pgrm->last_cr = i_clock; cl->last_cr = i_clock;
if( !p_input->b_out_pace_control ) if( !p_input->b_out_pace_control )
{ {
mtime_t i_wakeup = ClockToSysdate( p_input, p_pgrm, i_clock ); mtime_t i_wakeup = ClockToSysdate( p_input, cl, i_clock );
while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 ) while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 )
{ {
msleep( CLOCK_FREQ ); msleep( CLOCK_FREQ );
...@@ -261,37 +263,38 @@ void input_ClockManageRef( input_thread_t * p_input, ...@@ -261,37 +263,38 @@ void input_ClockManageRef( input_thread_t * p_input,
} }
else else
{ {
p_pgrm->last_cr = 0; cl->last_cr = 0;
p_pgrm->delta_cr = 0; cl->delta_cr = 0;
p_pgrm->c_average_count = 0; cl->c_average_count = 0;
} }
} }
else else
{ {
if ( p_pgrm->last_cr != 0 && if ( cl->last_cr != 0 &&
( (p_pgrm->last_cr - i_clock) > CR_MAX_GAP ( (cl->last_cr - i_clock) > CR_MAX_GAP
|| (p_pgrm->last_cr - i_clock) < - CR_MAX_GAP ) ) || (cl->last_cr - i_clock) < - CR_MAX_GAP ) )
{ {
/* Stream discontinuity, for which we haven't received a /* Stream discontinuity, for which we haven't received a
* warning from the stream control facilities (dd-edited * warning from the stream control facilities (dd-edited
* stream ?). */ * stream ?). */
msg_Warn( p_input, "clock gap, unexpected stream discontinuity" ); msg_Warn( p_input, "clock gap, unexpected stream discontinuity" );
input_ClockInit( p_pgrm ); input_ClockInit( cl, cl->b_master, cl->i_cr_average );
p_pgrm->i_synchro_state = SYNCHRO_START; /* FIXME needed ? */
#if 0
input_EscapeDiscontinuity( p_input ); input_EscapeDiscontinuity( p_input );
#endif
} }
p_pgrm->last_cr = i_clock; cl->last_cr = i_clock;
if( p_input->stream.b_pace_control if( p_input->b_can_pace_control && cl->b_master )
&& p_input->stream.p_selected_program == p_pgrm )
{ {
/* Wait a while before delivering the packets to the decoder. /* Wait a while before delivering the packets to the decoder.
* In case of multiple programs, we arbitrarily follow the * In case of multiple programs, we arbitrarily follow the
* clock of the selected program. */ * clock of the selected program. */
if( !p_input->b_out_pace_control ) if( !p_input->b_out_pace_control )
{ {
mtime_t i_wakeup = ClockToSysdate( p_input, p_pgrm, i_clock ); mtime_t i_wakeup = ClockToSysdate( p_input, cl, i_clock );
while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 ) while( (i_wakeup - mdate()) / CLOCK_FREQ > 1 )
{ {
msleep( CLOCK_FREQ ); msleep( CLOCK_FREQ );
...@@ -299,30 +302,32 @@ void input_ClockManageRef( input_thread_t * p_input, ...@@ -299,30 +302,32 @@ void input_ClockManageRef( input_thread_t * p_input,
} }
mwait( i_wakeup ); mwait( i_wakeup );
} }
/* FIXME Not needed anymore ? */
#if 0
/* Now take into account interface changes. */ /* Now take into account interface changes. */
input_ClockManageControl( p_input, p_pgrm, i_clock ); input_ClockManageControl( p_input, cl, i_clock );
#endif
} }
else else
{ {
/* Smooth clock reference variations. */ /* Smooth clock reference variations. */
mtime_t i_extrapoled_clock = ClockCurrent( p_input, p_pgrm ); mtime_t i_extrapoled_clock = ClockCurrent( p_input, cl );
/* Bresenham algorithm to smooth variations. */ /* Bresenham algorithm to smooth variations. */
if( p_pgrm->c_average_count == p_input->i_cr_average ) if( cl->c_average_count == cl->i_cr_average )
{ {
p_pgrm->delta_cr = ( p_pgrm->delta_cr cl->delta_cr = ( cl->delta_cr
* (p_input->i_cr_average - 1) * (cl->i_cr_average - 1)
+ ( i_extrapoled_clock - i_clock ) ) + ( i_extrapoled_clock - i_clock ) )
/ p_input->i_cr_average; / cl->i_cr_average;
} }
else else
{ {
p_pgrm->delta_cr = ( p_pgrm->delta_cr cl->delta_cr = ( cl->delta_cr
* p_pgrm->c_average_count * cl->c_average_count
+ ( i_extrapoled_clock - i_clock ) ) + ( i_extrapoled_clock - i_clock ) )
/ (p_pgrm->c_average_count + 1); / (cl->c_average_count + 1);
p_pgrm->c_average_count++; cl->c_average_count++;
} }
} }
} }
...@@ -332,23 +337,12 @@ void input_ClockManageRef( input_thread_t * p_input, ...@@ -332,23 +337,12 @@ void input_ClockManageRef( input_thread_t * p_input,
* input_ClockGetTS: manages a PTS or DTS * input_ClockGetTS: manages a PTS or DTS
*****************************************************************************/ *****************************************************************************/
mtime_t input_ClockGetTS( input_thread_t * p_input, mtime_t input_ClockGetTS( input_thread_t * p_input,
pgrm_descriptor_t * p_pgrm, mtime_t i_ts ) input_clock_t *cl, mtime_t i_ts )
{ {
/* take selected program if none specified */ if( cl->i_synchro_state != SYNCHRO_OK )
if( !p_pgrm )
{
p_pgrm = p_input->stream.p_selected_program;
}
if( p_pgrm->i_synchro_state == SYNCHRO_OK )
{
p_pgrm->last_pts = ClockToSysdate( p_input, p_pgrm,
i_ts + p_pgrm->delta_cr );
return( p_pgrm->last_pts + p_input->i_pts_delay );
}
else
{
return 0; return 0;
}
cl->last_pts = ClockToSysdate( p_input, cl, i_ts + cl->delta_cr );
return cl->last_pts + p_input->i_pts_delay;
} }
...@@ -22,22 +22,12 @@ ...@@ -22,22 +22,12 @@
*****************************************************************************/ *****************************************************************************/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/input.h> #include <vlc/input.h>
#include "input_internal.h"
#include "vlc_playlist.h" #include "vlc_playlist.h"
#include "ninput.h"
#include "../../modules/demux/util/sub.h"
struct input_thread_sys_t
{
/* subtitles */
int i_sub;
subtitle_demux_t **sub;
int64_t i_stop_time;
};
static void UpdateBookmarksOption( input_thread_t * ); static void UpdateBookmarksOption( input_thread_t * );
...@@ -64,7 +54,6 @@ int input_Control( input_thread_t *p_input, int i_query, ... ) ...@@ -64,7 +54,6 @@ int input_Control( input_thread_t *p_input, int i_query, ... )
int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
{ {
int i_ret;
seekpoint_t *p_bkmk, ***ppp_bkmk; seekpoint_t *p_bkmk, ***ppp_bkmk;
int i_bkmk = 0; int i_bkmk = 0;
int *pi_bkmk; int *pi_bkmk;
...@@ -75,54 +64,50 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) ...@@ -75,54 +64,50 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
double f, *pf; double f, *pf;
int64_t i_64, *pi_64; int64_t i_64, *pi_64;
vlc_mutex_lock( &p_input->stream.stream_lock );
switch( i_query ) switch( i_query )
{ {
case INPUT_GET_POSITION: case INPUT_GET_POSITION:
pf = (double*)va_arg( args, double * ); pf = (double*)va_arg( args, double * );
*pf = var_GetFloat( p_input, "position" ); *pf = var_GetFloat( p_input, "position" );
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
case INPUT_SET_POSITION: case INPUT_SET_POSITION:
f = (double)va_arg( args, double ); f = (double)va_arg( args, double );
i_ret = var_SetFloat( p_input, "position", f ); return var_SetFloat( p_input, "position", f );
break;
case INPUT_GET_LENGTH: case INPUT_GET_LENGTH:
pi_64 = (int64_t*)va_arg( args, int64_t * ); pi_64 = (int64_t*)va_arg( args, int64_t * );
*pi_64 = var_GetTime( p_input, "length" ); *pi_64 = var_GetTime( p_input, "length" );
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
case INPUT_GET_TIME: case INPUT_GET_TIME:
pi_64 = (int64_t*)va_arg( args, int64_t * ); pi_64 = (int64_t*)va_arg( args, int64_t * );
*pi_64 = var_GetTime( p_input, "time" ); *pi_64 = var_GetTime( p_input, "time" );
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
case INPUT_SET_TIME: case INPUT_SET_TIME:
i_64 = (int64_t)va_arg( args, int64_t ); i_64 = (int64_t)va_arg( args, int64_t );
i_ret = var_SetTime( p_input, "time", i_64 ); return var_SetTime( p_input, "time", i_64 );
break;
case INPUT_GET_RATE: case INPUT_GET_RATE:
pi_int = (int*)va_arg( args, int * ); pi_int = (int*)va_arg( args, int * );
*pi_int = var_GetInteger( p_input, "rate" ); *pi_int = var_GetInteger( p_input, "rate" );
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
case INPUT_SET_RATE: case INPUT_SET_RATE:
i_int = (int)va_arg( args, int ); i_int = (int)va_arg( args, int );
i_ret = var_SetInteger( p_input, "rate", i_int ); return var_SetInteger( p_input, "rate", i_int );
break;
case INPUT_GET_STATE: case INPUT_GET_STATE:
pi_int = (int*)va_arg( args, int * ); pi_int = (int*)va_arg( args, int * );
*pi_int = var_GetInteger( p_input, "state" ); *pi_int = var_GetInteger( p_input, "state" );
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
case INPUT_SET_STATE: case INPUT_SET_STATE:
i_int = (int)va_arg( args, int ); i_int = (int)va_arg( args, int );
i_ret = var_SetInteger( p_input, "state", i_int ); return var_SetInteger( p_input, "state", i_int );
break;
#if 0
case INPUT_ADD_OPTION: case INPUT_ADD_OPTION:
{ {
psz_option = (char *)va_arg( args, char * ); psz_option = (char *)va_arg( args, char * );
...@@ -130,7 +115,7 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) ...@@ -130,7 +115,7 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
i_ret = VLC_EGENERIC; i_ret = VLC_EGENERIC;
vlc_mutex_lock( &p_input->p_item->lock ); vlc_mutex_lock( &p_input->p_item->lock );
/* Check if option already exists */ /* Check if option already exists */
for( i = 0; i < p_input->p_item->i_options; i++ ) for( i = 0; i < p_input->p_item->i_options; i++ )
{ {
if( !strncmp( p_input->p_item->ppsz_options[i], psz_option, if( !strncmp( p_input->p_item->ppsz_options[i], psz_option,
...@@ -500,22 +485,33 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) ...@@ -500,22 +485,33 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
i_ret = VLC_EGENERIC; i_ret = VLC_EGENERIC;
} }
break; break;
#endif
case INPUT_GET_BOOKMARKS:
case INPUT_CLEAR_BOOKMARKS:
case INPUT_ADD_BOOKMARK:
case INPUT_CHANGE_BOOKMARK:
case INPUT_DEL_BOOKMARK:
case INPUT_SET_BOOKMARK:
case INPUT_ADD_OPTION:
case INPUT_ADD_INFO:
case INPUT_GET_INFO:
case INPUT_SET_NAME:
case INPUT_GET_SUBDELAY:
case INPUT_SET_SUBDELAY:
/* FIXME */
msg_Err( p_input, "unimplemented query in input_vaControl" );
default: default:
msg_Err( p_input, "unknown query in input_vaControl" ); msg_Err( p_input, "unknown query in input_vaControl" );
i_ret = VLC_EGENERIC; return VLC_EGENERIC;
break;
} }
vlc_mutex_unlock( &p_input->stream.stream_lock );
return i_ret;
} }
static void UpdateBookmarksOption( input_thread_t *p_input ) static void UpdateBookmarksOption( input_thread_t *p_input )
{ {
int i, i_len = 0; int i, i_len = 0;
char *psz_value = NULL, *psz_next = NULL; char *psz_value = NULL, *psz_next = NULL;
/* FIXME */
#if 0
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
for( i = 0; i < p_input->i_bookmarks; i++ ) for( i = 0; i < p_input->i_bookmarks; i++ )
...@@ -546,4 +542,5 @@ static void UpdateBookmarksOption( input_thread_t *p_input ) ...@@ -546,4 +542,5 @@ static void UpdateBookmarksOption( input_thread_t *p_input )
psz_value ? psz_value : "" ); psz_value ? psz_value : "" );
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
#endif
} }
/***************************************************************************** /*****************************************************************************
* input_dec.c: Functions for the management of decoders * decoder.c: Functions for the management of decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2004 VideoLAN * Copyright (C) 1999-2004 VideoLAN