[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