]> git.sesse.net Git - vlc/commitdiff
* Functional fast forward and slow motion API ;
authorChristophe Massiot <massiot@videolan.org>
Wed, 7 Feb 2001 17:44:52 +0000 (17:44 +0000)
committerChristophe Massiot <massiot@videolan.org>
Wed, 7 Feb 2001 17:44:52 +0000 (17:44 +0000)
* Dirty hack in the SDL intf to bind "a" (fAst forward), "s" (Slow motion)
and "p" (Play).

include/input_ext-intf.h
include/stream_control.h
plugins/sdl/intf_sdl.c
src/input/input.c
src/input/input.h
src/input/input_clock.c
src/input/input_ext-intf.c [new file with mode: 0644]
src/input/mpeg_system.c

index 9a76a5a6218fb47b4276fbcdf81710b1cf0aef40..0393e0ade9d126b2d9529e2e965a772370df663f 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.12 2001/02/07 15:32:25 massiot Exp $
+ * $Id: input_ext-intf.h,v 1.13 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors:
  *
@@ -277,13 +277,5 @@ struct input_thread_s * input_CreateThread( struct input_config_s *,
                                             int *pi_status );
 void                    input_DestroyThread( struct input_thread_s *,
                                              int *pi_status );
-void                    input_PauseProgram( struct input_thread_s *,
-                                            struct pgrm_descriptor_s * );
-void                    input_PlayProgram( struct input_thread_s *,
-                                           struct pgrm_descriptor_s * );
-void                    input_FFProgram( struct input_thread_s *,
-                                         struct pgrm_descriptor_s * );
-void                    input_SMProgram( struct input_thread_s *,
-                                           struct pgrm_descriptor_s * );
-void                    input_RewindProgram( struct input_thread_s *,
-                                             struct pgrm_descriptor_s * );
+void input_Play( struct input_thread_s * );
+void input_Forward( struct input_thread_s *, int );
index 5f2e5ad5a35d973958e20edb2b251eddab1cc124..607fb81a76347615bf517cda269ab2e22b4b3c81 100644 (file)
@@ -18,11 +18,12 @@ typedef struct stream_ctrl_s
 } stream_ctrl_t;
 
 /* Possible status : */
-#define PLAYING_S           0
-#define PAUSE_S             1
-#define FORWARD_S           2
-#define BACKWARD_S          3
-#define REWIND_S            4                /* Not supported for the moment */
+#define UNDEF_S             0
+#define PLAYING_S           1
+#define PAUSE_S             2
+#define FORWARD_S           3
+#define BACKWARD_S          4
+#define REWIND_S            5                /* Not supported for the moment */
 #define NOT_STARTED_S       10
 #define START_S             11
 
index 7c7919760f7e1b12edeb887854a17d2860d3e77f..f297412b6a036f386131bdffd373eabd5f0c0532 100644 (file)
@@ -2,7 +2,7 @@
  * intf_sdl.c: SDL interface plugin
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: intf_sdl.c,v 1.26 2001/02/06 00:56:55 nitrox Exp $
+ * $Id: intf_sdl.c,v 1.27 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors:
  *
@@ -136,12 +136,25 @@ void intf_SDLManage( intf_thread_t *p_intf )
                 vlc_mutex_unlock( &p_intf->p_vout->change_lock );
                 break;
                 
-           case SDLK_y:                                 /* switch to hard YUV */
+            case SDLK_y:                                /* switch to hard YUV */
                 vlc_mutex_lock( &p_intf->p_vout->change_lock );
                 p_intf->p_vout->i_changes |= VOUT_YUV_CHANGE;
                 vlc_mutex_unlock( &p_intf->p_vout->change_lock );
                 break; 
-                        
+
+            /* FIXME : this is temporary */
+            case SDLK_p:
+                input_Play( p_intf->p_input );
+                break;
+
+            case SDLK_a:
+                input_Forward( p_intf->p_input, DEFAULT_RATE/2 );
+                break;
+
+            case SDLK_s:
+                input_Forward( p_intf->p_input, DEFAULT_RATE*2 );
+                break;
+
             default:
                 if( intf_ProcessKey( p_intf, (char )i_key ) )
                 {
index de3dc8aa683a86cff6ef9574bc64af1612ba621a..cfca95f8deaa248bb55c54da250f5555e5273769 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input.c,v 1.73 2001/01/24 19:05:55 massiot Exp $
+ * $Id: input.c,v 1.74 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors: 
  *
@@ -99,6 +99,8 @@ input_thread_t *input_CreateThread ( input_config_t * p_config, int *pi_status )
     p_input->stream.i_es_number = 0;
     p_input->stream.i_selected_es_number = 0;
     p_input->stream.i_pgrm_number = 0;
+    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
+    p_input->stream.i_seek = 0;
 
     /* Initialize stream control properties. */
     p_input->stream.control.i_status = PLAYING_S;
index e4bd1be0ed24688a22551f872e60fabc6fae64b8..409c8e8dfb8efb5f4f8a5544e316533d0d274b7e 100644 (file)
@@ -2,7 +2,7 @@
  * input.h: structures of the input not exported to other modules
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input.h,v 1.13 2001/02/07 15:32:25 massiot Exp $
+ * $Id: input.h,v 1.14 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors:
  *
@@ -104,9 +104,7 @@ void input_DecodePES( struct decoder_fifo_s *, struct pes_packet_s * );
  * Prototypes from input_clock.c
  *****************************************************************************/
 void input_ClockNewRef( struct input_thread_s *,
-                        struct pgrm_descriptor_s *, mtime_t );
-void input_EscapeDiscontinuity( struct input_thread_s *,
-                                struct pgrm_descriptor_s * );
+                        struct pgrm_descriptor_s *, mtime_t, mtime_t );
 void input_ClockInit( struct pgrm_descriptor_s * );
 void input_ClockManageRef( struct input_thread_s *,
                            struct pgrm_descriptor_s *, mtime_t );
index 25cef639cc30651b58bbd92bd56867a0d50b958d..0c78cac15769fd115cf8c41dbde439b091e2fad3 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * input_clock.c: Clock/System date conversions, stream management
+ * input_clock.c: Clock/System date convertions, stream management
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_clock.c,v 1.2 2001/02/07 15:32:26 massiot Exp $
+ * $Id: input_clock.c,v 1.3 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
 #include "input.h"
 
 /*
- *   DISCUSSION : SYNCHRONIZATION METHOD
+ * DISCUSSION : SYNCHRONIZATION METHOD
  *
- *   In some cases we can impose the pace of reading (when reading from a
- *   file or a pipe), and for the synchronization we simply sleep() until
- *   it is time to deliver the packet to the decoders. When reading from
- *   the network, we must be read at the same pace as the server writes,
- *   otherwise the kernel's buffer will trash packets. The risk is now to
- *   overflow the input buffers in case the server goes too fast, that is
- *   why we do these calculations :
+ * In some cases we can impose the pace of reading (when reading from a
+ * file or a pipe), and for the synchronization we simply sleep() until
+ * it is time to deliver the packet to the decoders. When reading from
+ * the network, we must be read at the same pace as the server writes,
+ * otherwise the kernel's buffer will trash packets. The risk is now to
+ * overflow the input buffers in case the server goes too fast, that is
+ * why we do these calculations :
  *
- *   We compute a mean for the pcr because we want to eliminate the
- *   network jitter and keep the low frequency variations. The mean is
- *   in fact a low pass filter and the jitter is a high frequency signal
- *   that is why it is eliminated by the filter/average.
+ * We compute a mean for the pcr because we want to eliminate the
+ * network jitter and keep the low frequency variations. The mean is
+ * in fact a low pass filter and the jitter is a high frequency signal
+ * that is why it is eliminated by the filter/average.
  *
- *   The low frequency variations enable us to synchronize the client clock
- *   with the server clock because they represent the time variation between
- *   the 2 clocks. Those variations (ie the filtered pcr) are used to compute
- *   the presentation dates for the audio and video frames. With those dates
- *   we can decode (or trash) the MPEG2 stream at "exactly" the same rate
- *   as it is sent by the server and so we keep the synchronization between
- *   the server and the client.
+ * The low frequency variations enable us to synchronize the client clock
+ * with the server clock because they represent the time variation between
+ * the 2 clocks. Those variations (ie the filtered pcr) are used to compute
+ * the presentation dates for the audio and video frames. With those dates
+ * we can decode (or trash) the MPEG2 stream at "exactly" the same rate
+ * as it is sent by the server and so we keep the synchronization between
+ * the server and the client.
  *
- *   It is a very important matter if you want to avoid underflow or overflow
- *   in all the FIFOs, but it may be not enough.
+ * It is a very important matter if you want to avoid underflow or overflow
+ * in all the FIFOs, but it may be not enough.
  */
 
 /*****************************************************************************
@@ -72,7 +72,8 @@
 
 /* Maximum number of samples used to compute the dynamic average value.
  * We use the following formula :
- * new_average = (old_average * c_average + new_sample_value) / (c_average +1) */
+ * new_average = (old_average * c_average + new_sample_value) / (c_average +1)
+ */
 #define CR_MAX_AVERAGE_COUNTER 40
 
 /* Maximum gap allowed between two CRs. */
@@ -116,17 +117,19 @@ static mtime_t ClockCurrent( input_thread_t * p_input,
  * input_ClockNewRef: writes a new clock reference
  *****************************************************************************/
 void input_ClockNewRef( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm,
-                        mtime_t i_clock )
+                        mtime_t i_clock, mtime_t i_sysdate )
 {
+    intf_WarnMsg( 1, "Old ref: %lld/%lld, New ref: %lld/%lld", p_pgrm->cr_ref,
+              p_pgrm->sysdate_ref, i_clock, i_sysdate );
     p_pgrm->cr_ref = i_clock;
-    p_pgrm->sysdate_ref = mdate();
+    p_pgrm->sysdate_ref = i_sysdate;
 }
 
 /*****************************************************************************
- * input_EscapeDiscontinuity: send a NULL packet to the decoders
+ * EscapeDiscontinuity: send a NULL packet to the decoders
  *****************************************************************************/
-void input_EscapeDiscontinuity( input_thread_t * p_input,
-                                pgrm_descriptor_t * p_pgrm )
+static void EscapeDiscontinuity( input_thread_t * p_input,
+                                 pgrm_descriptor_t * p_pgrm )
 {
     int     i_es;
 
@@ -141,6 +144,25 @@ void input_EscapeDiscontinuity( input_thread_t * p_input,
     }
 }
 
+/*****************************************************************************
+ * EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
+ *****************************************************************************/
+static void EscapeAudioDiscontinuity( input_thread_t * p_input,
+                                      pgrm_descriptor_t * p_pgrm )
+{
+    int     i_es;
+
+    for( i_es = 0; i_es < p_pgrm->i_es_number; i_es++ )
+    {
+        es_descriptor_t * p_es = p_pgrm->pp_es[i_es];
+
+        if( p_es->p_decoder_fifo != NULL && p_es->b_audio )
+        {
+            input_NullPacket( p_input, p_es );
+        }
+    }
+}
+
 /*****************************************************************************
  * input_ClockInit: reinitializes the clock reference after a stream
  *                  discontinuity
@@ -163,7 +185,7 @@ void input_ClockManageRef( input_thread_t * p_input,
     if( p_pgrm->i_synchro_state != SYNCHRO_OK )
     {
         /* Feed synchro with a new reference point. */
-        input_ClockNewRef( p_input, p_pgrm, i_clock );
+        input_ClockNewRef( p_input, p_pgrm, i_clock, mdate() );
         p_pgrm->i_synchro_state = SYNCHRO_OK;
     }
     else
@@ -190,6 +212,39 @@ void input_ClockManageRef( input_thread_t * p_input,
              * In case of multiple programs, we arbitrarily follow the
              * clock of the first program. */
             mwait( ClockToSysdate( p_input, p_pgrm, i_clock ) );
+
+            /* Now take into account interface changes. */
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            if( p_input->stream.i_new_status != UNDEF_S )
+            {
+                /* For the moment, only PLAYING_S and FORWARD_S are
+                 * supported. */
+                input_ClockNewRef( p_input, p_pgrm, i_clock,
+                                   ClockToSysdate( p_input, p_pgrm, i_clock ) );
+
+                vlc_mutex_lock( &p_input->stream.control.control_lock );
+                p_input->stream.control.i_status = p_input->stream.i_new_status;
+
+                if( p_input->stream.control.i_status != PLAYING_S )
+                {
+                    p_input->stream.control.i_rate = p_input->stream.i_new_rate;
+                    p_input->stream.control.b_mute = 1;
+
+                    /* Feed the audio decoders with a NULL packet to avoid
+                     * discontinuities. */
+                    EscapeAudioDiscontinuity( p_input, p_pgrm );
+                }
+                else
+                {
+                    p_input->stream.control.i_rate = DEFAULT_RATE;
+                    p_input->stream.control.b_mute = 0;
+                }
+                vlc_mutex_unlock( &p_input->stream.control.control_lock );
+
+                p_input->stream.i_new_status = UNDEF_S;
+                p_input->stream.i_new_rate = UNDEF_S;
+            }
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
         }
         else
         {
diff --git a/src/input/input_ext-intf.c b/src/input/input_ext-intf.c
new file mode 100644 (file)
index 0000000..dad03ab
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * input_ext-intf.c: services to the interface
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ *
+ * Authors: 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h"
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+#include "input_ext-intf.h"
+
+#include "input.h"
+
+/*****************************************************************************
+ * input_Play: comes back to the normal pace of reading
+ *****************************************************************************/
+void input_Play( input_thread_t * p_input )
+{
+    intf_Msg( "Playing normally" );
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.i_new_status = PLAYING_S;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+}
+
+/*****************************************************************************
+ * input_Forward: manages fast forward and slow motion
+ *****************************************************************************
+ * Note that if i_rate > DEFAULT_RATE, the pace is slower.
+ *****************************************************************************/
+void input_Forward( input_thread_t * p_input, int i_rate )
+{
+    intf_Msg( "Forward enabled" );
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.i_new_status = FORWARD_S;
+    p_input->stream.i_new_rate = i_rate;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+}
index d2e37992ad137d788121d107d13281abffea8d79..188023d5bd878a08b04388813cf131c76aa8d2a8 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_system.c: TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: mpeg_system.c,v 1.29 2001/02/07 15:32:26 massiot Exp $
+ * $Id: mpeg_system.c,v 1.30 2001/02/07 17:44:52 massiot Exp $
  *
  * Authors: 
  *
@@ -838,8 +838,11 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
     {
         p_es = input_ParsePS( p_input, p_data );
 
-        if( p_es != NULL && p_es->p_decoder_fifo != NULL )
+        vlc_mutex_lock( &p_input->stream.control.control_lock );
+        if( p_es != NULL && p_es->p_decoder_fifo != NULL
+             && (!p_es->b_audio || !p_input->stream.control.b_mute) )
         {
+            vlc_mutex_unlock( &p_input->stream.control.control_lock );
 #ifdef STATS
             p_es->c_packets++;
 #endif
@@ -847,6 +850,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
         }
         else
         {
+            vlc_mutex_unlock( &p_input->stream.control.control_lock );
             b_trash = 1;
         }
     }
@@ -895,13 +899,16 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
     /* Find out the elementary stream. */
     vlc_mutex_lock( &p_input->stream.stream_lock );
     p_es = input_FindES( p_input, i_pid );
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-    if( p_es == NULL || p_es->p_decoder_fifo == NULL )
+    vlc_mutex_lock( &p_input->stream.control.control_lock );
+    if( p_es == NULL || p_es->p_decoder_fifo == NULL
+         || (p_es->b_audio && p_input->stream.control.b_mute) )
     {
         /* Not selected. Just read the adaptation field for a PCR. */
         b_trash = 1;
     }
+    vlc_mutex_unlock( &p_input->stream.control.control_lock );
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     if( (p_es->p_decoder_fifo != NULL) || (p_pgrm_demux->i_pcr_pid == i_pid) )
     {