[vlc-devel] Re: Kasenna pause and trickplay patch
Jean-Paul Saman
jean-paul.saman at planet.nl
Tue Nov 16 14:17:37 CET 2004
Dermot,
This is great functionality when commited. I only have some naming
comments they are inlined in the patch. Again good work!
Dermot McGahon wrote:
> Hi,
>
> Patch to implement pause/resume, fast forward and rewind for Kasenna
> Servers. There is a corresponding patch for this functionality against
> LIVE.COM which I will submit to the relevant list.
>
> This was implemented based on suggestions (mostly from fenrir) on irc
> and is work in progress. It works, but at this point I'm just hoping
> for a review, not a commit.
>
>
>
> Dermot.
> --
>
>------------------------------------------------------------------------
>
>Index: src/input/input.c
>===================================================================
>--- src/input/input.c (revision 9353)
>+++ src/input/input.c (working copy)
>@@ -515,7 +515,6 @@
> vlc_value_t val;
> double f_fps;
> vlc_meta_t *p_meta, *p_meta_tmp;
>- int i_es_out_mode;
> int i, i_delay;
>
> /* Initialize optional stream output. (before access/demuxer) */
>@@ -630,7 +629,6 @@
> if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) &&
> f_fps > 1.0 )
> {
>- vlc_value_t fps;
> float f_requested_fps;
>
> var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT );
>@@ -748,45 +746,20 @@
>
> /* Set up es_out */
> es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
>- i_es_out_mode = ES_OUT_MODE_AUTO;
>- val.p_list = NULL;
>+ val.b_bool = VLC_FALSE;
> if( p_input->p_sout )
> {
> var_Get( p_input, "sout-all", &val );
>- if ( val.b_bool )
>- {
>- i_es_out_mode = ES_OUT_MODE_ALL;
>- val.p_list = NULL;
>- }
>- else
>- {
>- var_Get( p_input, "programs", &val );
>- if ( val.p_list && val.p_list->i_count )
>- {
>- i_es_out_mode = ES_OUT_MODE_PARTIAL;
>- /* Note : we should remove the "program" callback. */
>- }
>- else
>- var_Change( p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
>- }
> }
>- es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, i_es_out_mode );
>+ es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE,
>+ val.b_bool ? ES_OUT_MODE_ALL : ES_OUT_MODE_AUTO );
>
> /* Inform the demuxer about waited group (needed only for DVB) */
>- if( i_es_out_mode == ES_OUT_MODE_ALL )
>- {
>- demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, NULL );
>- }
>- else if( i_es_out_mode == ES_OUT_MODE_PARTIAL )
>- {
>- demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1,
>- val.p_list );
>- }
>+ if( val.b_bool )
>+ demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1 );
> else
>- {
> demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP,
>- (int) var_GetInteger( p_input, "program" ), NULL );
>- }
>+ (int) var_GetInteger( p_input, "program" ) );
>
> if( p_input->p_sout )
> {
>@@ -1234,7 +1207,7 @@
> case INPUT_CONTROL_SET_RATE_SLOWER:
> case INPUT_CONTROL_SET_RATE_FASTER:
> {
>- int i_rate;
>+ int i_rate, i_ret;
>
> if( i_type == INPUT_CONTROL_SET_RATE_SLOWER )
> i_rate = p_input->i_rate * 2;
>@@ -1262,18 +1235,24 @@
> }
> if( i_rate != p_input->i_rate )
> {
>- p_input->i_rate = i_rate;
>+ //p_input->i_rate = i_rate;
> val.i_int = i_rate;
>- var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
>
>- /* We haven't send data to decoder when rate != default */
>- if( i_rate == INPUT_RATE_DEFAULT )
>- input_EsOutDiscontinuity( p_input->p_es_out, VLC_TRUE );
>+ i_ret = demux2_Control( p_input->input.p_demux, DEMUX_SET_RATE, i_rate, VLC_FALSE );
>
>- /* Reset clock */
>- es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
>+ if (i_ret)
>+ {
>+ var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
>
>- b_force_update = VLC_TRUE;
>+ /* We haven't send data to decoder when rate != default */
>+ if( i_rate == INPUT_RATE_DEFAULT )
>+ input_EsOutDiscontinuity( p_input->p_es_out, VLC_TRUE );
>+
>+ /* Reset clock */
>+ es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
>+
>+ b_force_update = VLC_TRUE;
>+ }
> }
> break;
> }
>@@ -1283,8 +1262,7 @@
> es_out_Control( p_input->p_es_out,
> ES_OUT_SET_GROUP, val.i_int );
>
>- demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, val.i_int,
>- NULL );
>+ demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, val.i_int );
> break;
>
> case INPUT_CONTROL_SET_ES:
>Index: modules/control/rc.c
>===================================================================
>--- modules/control/rc.c (revision 9353)
>+++ modules/control/rc.c (working copy)
>@@ -368,7 +368,12 @@
> var_AddCallback( p_intf, "chapter_n", Input, NULL );
> var_Create( p_intf, "chapter_p", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
> var_AddCallback( p_intf, "chapter_p", Input, NULL );
>+ var_Create( p_intf, "ff", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
>+ var_AddCallback( p_intf, "ff", Input, NULL );
>
>
Make this more human readible and call it "fforward" or "fastforward"
>+ var_Create( p_intf, "rw", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
>+ var_AddCallback( p_intf, "rw", Input, NULL );
>
>
>
Make this more human readible and call it "rewind"
>+
> var_Create( p_intf, "volume", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
> var_AddCallback( p_intf, "volume", Volume, NULL );
> var_Create( p_intf, "volup", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
>@@ -707,6 +712,22 @@
> vlc_object_release( p_input );
> return VLC_SUCCESS;
> }
>+ else if ( !strcmp( psz_cmd, "ff" ) )
>
>
this will become:
+ else if ( !strcmp( psz_cmd, "fforward" ) )
>+ {
>+ val.i_int = INPUT_RATE_MAX;
>+
>+ var_Set( p_input, "rate", val );
>+ vlc_object_release( p_input );
>+ return VLC_SUCCESS;
>+ }
>+ else if ( !strcmp( psz_cmd, "rw" ) )
>
>
and this
+ else if ( !strcmp( psz_cmd, "rewind" ) )
>+ {
>+ val.i_int = INPUT_RATE_MIN;
>+
>+ var_Set( p_input, "rate", val );
>+ vlc_object_release( p_input );
>+ return VLC_SUCCESS;
>+ }
>
> else if( !strcmp( psz_cmd, "chapter" ) ||
> !strcmp( psz_cmd, "chapter_n" ) ||
>Index: modules/demux/livedotcom.cpp
>===================================================================
>--- modules/demux/livedotcom.cpp (revision 9353)
>+++ modules/demux/livedotcom.cpp (working copy)
>@@ -149,6 +149,9 @@
> mtime_t i_length;
> mtime_t i_start;
>
>+ int i_rate;
>+ mtime_t i_running_duration;
>+
> char event;
> };
>
>@@ -157,11 +160,6 @@
>
> static int ParseASF( demux_t * );
>
>-static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int i_duration );
>-static void StreamClose( void *p_private );
>-static void TaskInterrupt( void *p_private );
>-
>-
> /*****************************************************************************
> * DemuxOpen:
> *****************************************************************************/
>@@ -215,6 +213,7 @@
> p_sys->i_pcr_start = 0;
> p_sys->i_length = 0;
> p_sys->i_start = 0;
>+ p_sys->i_running_duration = 0;
> p_sys->p_out_asf = NULL;
>
>
>@@ -245,6 +244,7 @@
> psz_options = p_sys->rtsp->sendOptionsCmd( psz_url );
> if( psz_options )
> delete [] psz_options;
>+ fprintf( stderr, "options=%s\n", psz_options);
>
>
use vlc functions here and do not use fprintf(), for instance:
msg_Info( p_intf, "options=%s\n", psz_options);
>
> p_sdp = (uint8_t*)p_sys->rtsp->describeURL( psz_url,
> NULL, var_CreateGetBool( p_demux, "rtsp-kasenna" ) );
>@@ -522,11 +522,6 @@
> tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
> }
>
>- if( sub->rtcpInstance() != NULL )
>- {
>- sub->rtcpInstance()->setByeHandler( StreamClose, tk );
>- }
>-
> if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf )
> {
> tk->readSource = sub->readSource();
>@@ -656,6 +651,11 @@
> free( p_sys );
> }
>
>+
>+static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int i_duration );
>+static void StreamClose( void *p_private );
>+static void TaskInterrupt( void *p_private );
>+
> /*****************************************************************************
> * Demux:
> *****************************************************************************/
>@@ -752,7 +752,7 @@
> int64_t *pi64;
> double *pf, f;
> vlc_bool_t *pb, b_bool;
>- int i;
>+ int i, i_rate;
>
> switch( i_query )
> {
>@@ -800,20 +800,22 @@
> p_sys->i_start = (mtime_t)(f * (double)p_sys->i_length);
> p_sys->i_pcr_start = 0;
> p_sys->i_pcr = 0;
>-
> for( i = 0; i < p_sys->i_track; i++ )
> {
> p_sys->track[i]->i_pts = 0;
>+
>+ if( p_sys->track[i]->b_muxed )
>+ es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
> }
> return VLC_SUCCESS;
> }
>- return VLC_SUCCESS;
>+ return VLC_EGENERIC;
> }
>
> /* Special for access_demux */
> case DEMUX_CAN_PAUSE:
> pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
>- if( p_sys->rtsp && p_sys->i_length )
>+ if( p_sys->rtsp )
> *pb = VLC_TRUE; /* Not always true, but will be handled in SET_PAUSE_STATE */
> else
> *pb = VLC_FALSE;
>@@ -821,16 +823,22 @@
>
> case DEMUX_CAN_CONTROL_PACE:
> pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
>- *pb = VLC_FALSE;
>+ *pb = VLC_TRUE;
> return VLC_SUCCESS;
>
> case DEMUX_SET_PAUSE_STATE:
>- double d_npt;
> MediaSubsessionIterator *iter;
> MediaSubsession *sub;
>
>- d_npt = ( (double)( p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start ) ) / 1000000.00;
>+ for( i = 0; i < p_sys->i_track; i++ )
>+ {
>+ if( !b_bool && p_sys->track[i]->b_muxed )
>+ es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
>+ }
>
>+ msg_Dbg(p_demux, "pcr values: %d %d %d %d", (int)p_sys->i_pcr, (int)p_sys->i_pcr_start,
>+ (int)p_sys->i_start, (int)p_sys->track[i]->i_pts);
>+
> b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t );
> if( p_sys->rtsp == NULL )
> return VLC_EGENERIC;
>@@ -839,22 +847,65 @@
> while( ( sub = iter->next() ) != NULL )
> {
> if( ( b_bool && !p_sys->rtsp->pauseMediaSubsession( *sub ) ) ||
>- ( !b_bool && !p_sys->rtsp->playMediaSubsession( *sub, d_npt > 0 ? d_npt : -1 ) ) )
>+ ( !b_bool && !p_sys->rtsp->playMediaSubsession( *sub, (int)p_sys->i_running_duration / 1000000 ) ) )
> {
> delete iter;
> return VLC_EGENERIC;
> }
> }
> delete iter;
>-#if 0
>- /* reset PCR and PCR start, mmh won't work well for multi-stream I fear */
>- for( i = 0; i < p_sys->i_track; i++ )
>+
>+ return VLC_SUCCESS;
>+
>+ case DEMUX_SET_RATE:
>+
>+ p_sys->i_rate = i_rate = (int)va_arg( args, int );
>+ msg_Dbg(p_demux, "i_rate: %d\n", i_rate);
>+
>+ if (i_rate == INPUT_RATE_MAX)
> {
>- p_sys->track[i]->i_pts = 0;
>- }
>- p_sys->i_pcr_start = 0; /* FIXME Wrong */
>- p_sys->i_pcr = 0;
>-#endif
>+ iter = new MediaSubsessionIterator( *p_sys->ms );
>+ while( ( sub = iter->next() ) != NULL )
>+ {
>+ if ( !p_sys->rtsp->pauseMediaSubsession( *sub ) )
>+ {
>+ delete iter;
>+ return VLC_EGENERIC;
>+ }
>+
>+ if ( !p_sys->rtsp->playMediaSubsession( *sub, p_sys->i_running_duration / 1000000,
>+ p_sys->i_length / 1000000, 0, 1 ) )
>+ {
>+ delete iter;
>+ return VLC_EGENERIC;
>+ }
>+ }
>+
>+ delete iter;
>+ }
>+
>+ if (i_rate == INPUT_RATE_MIN)
>+ {
>+ iter = new MediaSubsessionIterator( *p_sys->ms );
>+ while( ( sub = iter->next() ) != NULL )
>+ {
>+ if ( !p_sys->rtsp->pauseMediaSubsession( *sub ) )
>+ {
>+ delete iter;
>+ return VLC_EGENERIC;
>+ }
>+
>+ if ( !p_sys->rtsp->playMediaSubsession( *sub, p_sys->i_running_duration/1000000,
>+ p_sys->i_length / 1000000, 0, 2 ) )
>+ {
>+ delete iter;
>+ return VLC_EGENERIC;
>+ }
>+ }
>+
>+ delete iter;
>+ }
>+
> return VLC_SUCCESS;
>
> case DEMUX_GET_TITLE_INFO:
>@@ -882,6 +933,15 @@
> demux_sys_t *p_sys = p_demux->p_sys;
> block_t *p_block;
>
>+ if (p_sys->i_rate == INPUT_RATE_MAX)
>+ p_sys->i_running_duration += duration * 12;
>+ else if (p_sys->i_rate == INPUT_RATE_MIN)
>+ p_sys->i_running_duration -= duration * 12;
>+ else
>+ p_sys->i_running_duration += duration;
>+
>+ msg_Dbg(p_demux, "duration = %u", (unsigned int)p_sys->i_running_duration / 1000000);
>+
> mtime_t i_pts = (uint64_t)pts.tv_sec * UI64C(1000000) + (uint64_t)pts.tv_usec;
>
> /* XXX Beurk beurk beurk Avoid having negative value XXX */
>@@ -1142,4 +1202,3 @@
>
> return dest - dest_start;
> }
>-
>Index: include/vlc_demux.h
>===================================================================
>--- include/vlc_demux.h (revision 9353)
>+++ include/vlc_demux.h (working copy)
>@@ -105,7 +105,8 @@
> DEMUX_CAN_PAUSE, /* arg1= vlc_bool_t* cannot fail */
> DEMUX_CAN_CONTROL_PACE, /* arg1= vlc_bool_t* cannot fail */
> DEMUX_GET_PTS_DELAY, /* arg1= int64_t* cannot fail */
>- DEMUX_SET_PAUSE_STATE, /* arg1= vlc_bool_t can fail */
>+ DEMUX_SET_PAUSE_STATE, /* arg1= vlc_bool_t can fail */
>+ DEMUX_SET_RATE, /* arg1=int, arg2=vlc_bool_t *pb_recompute_pts */
> };
>
> /* stream_t *s could be null and then it mean a access+demux in one */
>
>
--
Many greetings,
Jean-Paul Saman
==========================================================================
VLC iPAQ maintainer (http://www.videolan.org)
RedHat Certified Engineer (RHCE: 807202745005548)
==========================================================================
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20041116/64520913/attachment.sig>
More information about the vlc-devel
mailing list