gstreamer_core/gst/gstpipeline.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    60  * The clock selection can be controlled with the gst_pipeline_use_clock()
    60  * The clock selection can be controlled with the gst_pipeline_use_clock()
    61  * method, which will enforce a given clock on the pipeline. With
    61  * method, which will enforce a given clock on the pipeline. With
    62  * gst_pipeline_auto_clock() the default clock selection algorithm can be
    62  * gst_pipeline_auto_clock() the default clock selection algorithm can be
    63  * restored.
    63  * restored.
    64  *
    64  *
    65  * A #GstPipeline maintains a running time for the elements. The running
    65  * A #GstPipeline maintains a stream time for the elements. The stream
    66  * time is defined as the difference between the current clock time and
    66  * time is defined as the difference between the current clock time and
    67  * the base time. When the pipeline goes to READY or a flushing seek is
    67  * the base time. When the pipeline goes to READY or a flushing seek is
    68  * performed on it, the running time is reset to 0. When the pipeline is
    68  * performed on it, the stream time is reset to 0. When the pipeline is
    69  * set from PLAYING to PAUSED, the current clock time is sampled and used to
    69  * set from PLAYING to PAUSED, the current clock time is sampled and used to
    70  * configure the base time for the elements when the pipeline is set
    70  * configure the base time for the elements when the pipeline is set
    71  * to PLAYING again. The effect is that the running time (as the difference
    71  * to PLAYING again. This default behaviour can be changed with the
    72  * between the clock time and the base time) will count how much time was spent
    72  * gst_pipeline_set_new_stream_time() method.
    73  * in the PLAYING state. This default behaviour can be changed with the
       
    74  * gst_element_set_start_time() method.
       
    75  *
    73  *
    76  * When sending a flushing seek event to a GstPipeline (see
    74  * When sending a flushing seek event to a GstPipeline (see
    77  * gst_element_seek()), it will make sure that the pipeline is properly
    75  * gst_element_seek()), it will make sure that the pipeline is properly
    78  * PAUSED and resumed as well as set the new running time to 0 when the
    76  * PAUSED and resumed as well as set the new stream time to 0 when the
    79  * seek succeeded.
    77  * seek succeeded.
    80  *
    78  *
    81  * Last reviewed on 2009-05-29 (0.10.24)
    79  * Last reviewed on 2006-03-12 (0.10.5)
    82  */
    80  */
    83 
    81 
    84 #include "gst_private.h"
    82 #include "gst_private.h"
    85 #include "gsterror.h"
    83 #include "gsterror.h"
    86 #include "gst-i18n-lib.h"
    84 #include "gst-i18n-lib.h"
    87 
    85 
    88 #include "gstpipeline.h"
    86 #include "gstpipeline.h"
    89 #include "gstinfo.h"
    87 #include "gstinfo.h"
    90 #include "gstsystemclock.h"
    88 #include "gstsystemclock.h"
    91 #include "gstutils.h"
    89 
    92 #ifdef __SYMBIAN32__
    90 #ifdef __SYMBIAN32__
    93 #include <glib_global.h>
    91 #include <glib_global.h>
    94 #endif
    92 #endif
    95 
    93 
    96 GST_DEBUG_CATEGORY_STATIC (pipeline_debug);
    94 GST_DEBUG_CATEGORY_STATIC (pipeline_debug);
   121   /* with LOCK */
   119   /* with LOCK */
   122   gboolean auto_flush_bus;
   120   gboolean auto_flush_bus;
   123 
   121 
   124   /* when we need to update stream_time or clock when going back to
   122   /* when we need to update stream_time or clock when going back to
   125    * PLAYING*/
   123    * PLAYING*/
   126   GstClockTime last_start_time;
   124   gboolean update_stream_time;
   127   gboolean update_clock;
   125   gboolean update_clock;
   128 };
   126 };
   129 
   127 
   130 
   128 
   131 static void gst_pipeline_base_init (gpointer g_class);
   129 static void gst_pipeline_base_init (gpointer g_class);
       
   130 static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
       
   131 static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
   132 
   132 
   133 static void gst_pipeline_dispose (GObject * object);
   133 static void gst_pipeline_dispose (GObject * object);
   134 static void gst_pipeline_set_property (GObject * object, guint prop_id,
   134 static void gst_pipeline_set_property (GObject * object, guint prop_id,
   135     const GValue * value, GParamSpec * pspec);
   135     const GValue * value, GParamSpec * pspec);
   136 static void gst_pipeline_get_property (GObject * object, guint prop_id,
   136 static void gst_pipeline_get_property (GObject * object, guint prop_id,
   140 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element,
   140 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element,
   141     GstStateChange transition);
   141     GstStateChange transition);
   142 
   142 
   143 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message);
   143 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message);
   144 
   144 
       
   145 static GstBinClass *parent_class = NULL;
       
   146 
   145 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
   147 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
   146 
   148 #ifdef __SYMBIAN32__
   147 #define _do_init(type) \
   149 EXPORT_C
   148 { \
   150 #endif
   149   GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, \
   151 
   150       "debugging info for the 'pipeline' container element"); \
   152 
   151 }
   153 GType
   152 
   154 gst_pipeline_get_type (void)
   153 GST_BOILERPLATE_FULL (GstPipeline, gst_pipeline, GstBin, GST_TYPE_BIN,
   155 {
   154     _do_init);
   156   static GType pipeline_type = 0;
       
   157 
       
   158   if (G_UNLIKELY (pipeline_type == 0)) {
       
   159     static const GTypeInfo pipeline_info = {
       
   160       sizeof (GstPipelineClass),
       
   161       gst_pipeline_base_init,
       
   162       NULL,
       
   163       (GClassInitFunc) gst_pipeline_class_init,
       
   164       NULL,
       
   165       NULL,
       
   166       sizeof (GstPipeline),
       
   167       0,
       
   168       gst_pipeline_init,
       
   169       NULL
       
   170     };
       
   171 
       
   172     pipeline_type =
       
   173         g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
       
   174 
       
   175     GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD,
       
   176         "debugging info for the 'pipeline' container element");
       
   177   }
       
   178   return pipeline_type;
       
   179 }
   155 
   180 
   156 static void
   181 static void
   157 gst_pipeline_base_init (gpointer g_class)
   182 gst_pipeline_base_init (gpointer g_class)
   158 {
   183 {
   159   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   184   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   163       "Complete pipeline object",
   188       "Complete pipeline object",
   164       "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
   189       "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
   165 }
   190 }
   166 
   191 
   167 static void
   192 static void
   168 gst_pipeline_class_init (GstPipelineClass * klass)
   193 gst_pipeline_class_init (gpointer g_class, gpointer class_data)
   169 {
   194 {
   170   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   195   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
   171   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
   196   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   172   GstBinClass *gstbin_class = GST_BIN_CLASS (klass);
   197   GstBinClass *gstbin_class = GST_BIN_CLASS (g_class);
       
   198   GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
   173 
   199 
   174   parent_class = g_type_class_peek_parent (klass);
   200   parent_class = g_type_class_peek_parent (klass);
   175 
   201 
   176   g_type_class_add_private (klass, sizeof (GstPipelinePrivate));
   202   g_type_class_add_private (klass, sizeof (GstPipelinePrivate));
   177 
   203 
   189    **/
   215    **/
   190   g_object_class_install_property (gobject_class, PROP_DELAY,
   216   g_object_class_install_property (gobject_class, PROP_DELAY,
   191       g_param_spec_uint64 ("delay", "Delay",
   217       g_param_spec_uint64 ("delay", "Delay",
   192           "Expected delay needed for elements "
   218           "Expected delay needed for elements "
   193           "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
   219           "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
   194           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   220           G_PARAM_READWRITE));
   195 
   221 
   196   /**
   222   /**
   197    * GstPipeline:auto-flush-bus:
   223    * GstPipeline:auto-flush-bus:
   198    *
   224    *
   199    * Whether or not to automatically flush all messages on the
   225    * Whether or not to automatically flush all messages on the
   204    **/
   230    **/
   205   g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS,
   231   g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS,
   206       g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus",
   232       g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus",
   207           "Whether to automatically flush the pipeline's bus when going "
   233           "Whether to automatically flush the pipeline's bus when going "
   208           "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS,
   234           "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS,
   209           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   235           G_PARAM_READWRITE));
   210 
   236 
   211   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
   237   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
   212 
   238 
   213   gstelement_class->change_state =
   239   gstelement_class->change_state =
   214       GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
   240       GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
   217   gstbin_class->handle_message =
   243   gstbin_class->handle_message =
   218       GST_DEBUG_FUNCPTR (gst_pipeline_handle_message);
   244       GST_DEBUG_FUNCPTR (gst_pipeline_handle_message);
   219 }
   245 }
   220 
   246 
   221 static void
   247 static void
   222 gst_pipeline_init (GstPipeline * pipeline, GstPipelineClass * klass)
   248 gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
   223 {
   249 {
       
   250   GstPipeline *pipeline = GST_PIPELINE (instance);
   224   GstBus *bus;
   251   GstBus *bus;
   225 
   252 
   226   pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline);
   253   pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline);
   227 
   254 
   228   /* set default property values */
   255   /* set default property values */
   293       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   320       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   294       break;
   321       break;
   295   }
   322   }
   296 }
   323 }
   297 
   324 
   298 /* set the start_time to 0, this will cause us to select a new base_time and
   325 /* set the stream time to 0 */
   299  * make the running_time start from 0 again. */
       
   300 static void
   326 static void
   301 reset_start_time (GstPipeline * pipeline)
   327 reset_stream_time (GstPipeline * pipeline)
   302 {
   328 {
   303   GST_OBJECT_LOCK (pipeline);
   329   GST_OBJECT_LOCK (pipeline);
   304   if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) {
   330   if (pipeline->stream_time != GST_CLOCK_TIME_NONE) {
   305     GST_DEBUG_OBJECT (pipeline, "reset start_time to 0");
   331     GST_DEBUG_OBJECT (pipeline, "reset stream_time to 0");
   306     GST_ELEMENT_START_TIME (pipeline) = 0;
   332     pipeline->stream_time = 0;
   307     pipeline->priv->last_start_time = -1;
   333     pipeline->priv->update_stream_time = TRUE;
   308   } else {
   334   } else {
   309     GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time");
   335     GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time");
   310   }
   336   }
   311   GST_OBJECT_UNLOCK (pipeline);
   337   GST_OBJECT_UNLOCK (pipeline);
   312 }
   338 }
   352       GST_OBJECT_UNLOCK (element);
   378       GST_OBJECT_UNLOCK (element);
   353       break;
   379       break;
   354     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
   380     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
   355     {
   381     {
   356       GstClockTime new_base_time;
   382       GstClockTime new_base_time;
   357       GstClockTime now, start_time, last_start_time, delay;
   383       GstClockTime start_time, stream_time, delay;
   358       gboolean update_clock;
   384       gboolean new_clock, update_stream_time, update_clock;
   359       GstClock *cur_clock;
   385       GstClock *cur_clock;
   360 
   386 
   361       GST_DEBUG_OBJECT (element, "selecting clock and base_time");
   387       GST_DEBUG_OBJECT (element, "selecting clock and base_time");
   362 
   388 
   363       GST_OBJECT_LOCK (element);
   389       GST_OBJECT_LOCK (element);
   364       cur_clock = element->clock;
   390       cur_clock = element->clock;
   365       if (cur_clock)
   391       if (cur_clock)
   366         gst_object_ref (cur_clock);
   392         gst_object_ref (cur_clock);
   367       /* get the desired running_time of the first buffer aka the start_time */
   393       stream_time = pipeline->stream_time;
   368       start_time = GST_ELEMENT_START_TIME (pipeline);
   394       update_stream_time = pipeline->priv->update_stream_time;
   369       last_start_time = pipeline->priv->last_start_time;
       
   370       pipeline->priv->last_start_time = start_time;
       
   371       /* see if we need to update the clock */
       
   372       update_clock = pipeline->priv->update_clock;
   395       update_clock = pipeline->priv->update_clock;
       
   396       pipeline->priv->update_stream_time = FALSE;
   373       pipeline->priv->update_clock = FALSE;
   397       pipeline->priv->update_clock = FALSE;
   374       delay = pipeline->delay;
   398       delay = pipeline->delay;
   375       GST_OBJECT_UNLOCK (element);
   399       GST_OBJECT_UNLOCK (element);
   376 
   400 
   377       /* running time changed, either with a PAUSED or a flush, we need to check
   401       /* stream time changed, either with a PAUSED or a flush, we need to check
   378        * if there is a new clock & update the base time */
   402        * if there is a new clock & update the base time */
   379       if (last_start_time != start_time) {
   403       if (update_stream_time) {
   380         GST_DEBUG_OBJECT (pipeline, "Need to update start_time");
   404         GST_DEBUG_OBJECT (pipeline, "Need to update stream_time");
   381 
   405 
   382         /* when going to PLAYING, select a clock when needed. If we just got
   406         /* when going to PLAYING, select a clock when needed. If we just got
   383          * flushed, we don't reselect the clock. */
   407          * flushed, we don't reselect the clock. */
   384         if (update_clock) {
   408         if (update_clock) {
   385           GST_DEBUG_OBJECT (pipeline, "Need to update clock.");
   409           GST_DEBUG_OBJECT (pipeline, "Need to update clock.");
   388           GST_DEBUG_OBJECT (pipeline,
   412           GST_DEBUG_OBJECT (pipeline,
   389               "Don't need to update clock, using old clock.");
   413               "Don't need to update clock, using old clock.");
   390           clock = gst_object_ref (cur_clock);
   414           clock = gst_object_ref (cur_clock);
   391         }
   415         }
   392 
   416 
       
   417         new_clock = (clock != cur_clock);
       
   418 
   393         if (clock) {
   419         if (clock) {
   394           now = gst_clock_get_time (clock);
   420           start_time = gst_clock_get_time (clock);
   395         } else {
   421         } else {
   396           GST_DEBUG ("no clock, using base time of NONE");
   422           GST_DEBUG ("no clock, using base time of NONE");
   397           now = GST_CLOCK_TIME_NONE;
   423           start_time = GST_CLOCK_TIME_NONE;
       
   424           new_base_time = GST_CLOCK_TIME_NONE;
   398         }
   425         }
   399 
   426 
   400         if (clock != cur_clock) {
   427         if (new_clock) {
   401           /* now distribute the clock (which could be NULL). If some
   428           /* now distribute the clock (which could be NULL). If some
   402            * element refuses the clock, this will return FALSE and
   429            * element refuses the clock, this will return FALSE and
   403            * we effectively fail the state change. */
   430            * we effectively fail the state change. */
   404           if (!gst_element_set_clock (element, clock))
   431           if (!gst_element_set_clock (element, clock))
   405             goto invalid_clock;
   432             goto invalid_clock;
   411         }
   438         }
   412 
   439 
   413         if (clock)
   440         if (clock)
   414           gst_object_unref (clock);
   441           gst_object_unref (clock);
   415 
   442 
   416         if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) {
   443         if (stream_time != GST_CLOCK_TIME_NONE
   417           new_base_time = now - start_time + delay;
   444             && start_time != GST_CLOCK_TIME_NONE) {
       
   445           new_base_time = start_time - stream_time + delay;
   418           GST_DEBUG_OBJECT (element,
   446           GST_DEBUG_OBJECT (element,
   419               "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
   447               "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
   420               ", base_time %" GST_TIME_FORMAT,
   448               ", base_time %" GST_TIME_FORMAT,
   421               GST_TIME_ARGS (start_time), GST_TIME_ARGS (now),
   449               GST_TIME_ARGS (stream_time), GST_TIME_ARGS (start_time),
   422               GST_TIME_ARGS (new_base_time));
   450               GST_TIME_ARGS (new_base_time));
   423         } else
   451         } else
   424           new_base_time = GST_CLOCK_TIME_NONE;
   452           new_base_time = GST_CLOCK_TIME_NONE;
   425 
   453 
   426         if (new_base_time != GST_CLOCK_TIME_NONE)
   454         if (new_base_time != GST_CLOCK_TIME_NONE)
   427           gst_element_set_base_time (element, new_base_time);
   455           gst_element_set_base_time (element, new_base_time);
   428         else
   456         else
   429           GST_DEBUG_OBJECT (pipeline,
   457           GST_DEBUG_OBJECT (pipeline,
   430               "NOT adjusting base_time because start_time is NONE");
   458               "NOT adjusting base_time because stream_time is NONE");
   431       } else {
   459       } else {
   432         GST_DEBUG_OBJECT (pipeline,
   460         GST_DEBUG_OBJECT (pipeline,
   433             "NOT adjusting base_time because we selected one before");
   461             "NOT adjusting base_time because we selected one before");
   434       }
   462       }
   435 
   463 
   436       if (cur_clock)
   464       if (cur_clock)
   437         gst_object_unref (cur_clock);
   465         gst_object_unref (cur_clock);
   438       break;
   466       break;
   439     }
   467     }
   440     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
   468     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
   469       break;
       
   470     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
   471     case GST_STATE_CHANGE_READY_TO_NULL:
       
   472       break;
       
   473   }
       
   474 
       
   475   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
   476 
       
   477   switch (transition) {
       
   478     case GST_STATE_CHANGE_NULL_TO_READY:
       
   479       break;
       
   480     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
   481     {
       
   482       reset_stream_time (pipeline);
       
   483       break;
       
   484     }
       
   485     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
   486       break;
       
   487     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
   441       GST_OBJECT_LOCK (element);
   488       GST_OBJECT_LOCK (element);
   442       if ((clock = element->clock)) {
   489       if ((clock = element->clock)) {
   443         GstClockTime now;
   490         GstClockTime now;
   444 
   491 
   445         gst_object_ref (clock);
   492         gst_object_ref (clock);
   448         /* calculate the time when we stopped */
   495         /* calculate the time when we stopped */
   449         now = gst_clock_get_time (clock);
   496         now = gst_clock_get_time (clock);
   450         gst_object_unref (clock);
   497         gst_object_unref (clock);
   451 
   498 
   452         GST_OBJECT_LOCK (element);
   499         GST_OBJECT_LOCK (element);
   453         /* store the current running time */
   500         /* store the current stream time */
   454         if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) {
   501         if (pipeline->stream_time != GST_CLOCK_TIME_NONE) {
   455           GST_ELEMENT_START_TIME (pipeline) = now - element->base_time;
   502           pipeline->stream_time = now - element->base_time;
   456           /* we went to PAUSED, when going to PLAYING select clock and new
   503           /* we went to PAUSED, when going to PLAYING select clock and new
   457            * base_time */
   504            * base_time */
       
   505           pipeline->priv->update_stream_time = TRUE;
   458           pipeline->priv->update_clock = TRUE;
   506           pipeline->priv->update_clock = TRUE;
   459         }
   507         }
       
   508 
   460         GST_DEBUG_OBJECT (element,
   509         GST_DEBUG_OBJECT (element,
   461             "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
   510             "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
   462             ", base_time %" GST_TIME_FORMAT,
   511             ", base_time %" GST_TIME_FORMAT,
   463             GST_TIME_ARGS (GST_ELEMENT_START_TIME (pipeline)),
   512             GST_TIME_ARGS (pipeline->stream_time), GST_TIME_ARGS (now),
   464             GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
   513             GST_TIME_ARGS (element->base_time));
   465       }
   514       }
   466       GST_OBJECT_UNLOCK (element);
   515       GST_OBJECT_UNLOCK (element);
   467       break;
   516       break;
   468       break;
       
   469     case GST_STATE_CHANGE_PAUSED_TO_READY:
   517     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
   518       break;
   470     case GST_STATE_CHANGE_READY_TO_NULL:
   519     case GST_STATE_CHANGE_READY_TO_NULL:
   471       break;
       
   472   }
       
   473 
       
   474   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
   475 
       
   476   switch (transition) {
       
   477     case GST_STATE_CHANGE_NULL_TO_READY:
       
   478       break;
       
   479     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
   480     {
       
   481       reset_start_time (pipeline);
       
   482       break;
       
   483     }
       
   484     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
   485       break;
       
   486     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
   487       break;
       
   488     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
   489       break;
       
   490     case GST_STATE_CHANGE_READY_TO_NULL:
       
   491     {
       
   492       GstBus *bus;
       
   493       gboolean auto_flush;
       
   494 
       
   495       /* grab some stuff before we release the lock to flush out the bus */
       
   496       GST_OBJECT_LOCK (element);
   520       GST_OBJECT_LOCK (element);
   497       if ((bus = element->bus))
   521       if (element->bus) {
   498         gst_object_ref (bus);
   522         if (pipeline->priv->auto_flush_bus) {
   499       auto_flush = pipeline->priv->auto_flush_bus;
   523           gst_bus_set_flushing (element->bus, TRUE);
   500       GST_OBJECT_UNLOCK (element);
       
   501 
       
   502       if (bus) {
       
   503         if (auto_flush) {
       
   504           gst_bus_set_flushing (bus, TRUE);
       
   505         } else {
   524         } else {
   506           GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled");
   525           GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled");
   507         }
   526         }
   508         gst_object_unref (bus);
       
   509       }
   527       }
   510       break;
   528       GST_OBJECT_UNLOCK (element);
   511     }
   529       break;
   512   }
   530   }
   513   return result;
   531   return result;
   514 
   532 
   515   /* ERRORS */
   533   /* ERRORS */
   516 invalid_clock:
   534 invalid_clock:
   526       gst_object_unref (clock);
   544       gst_object_unref (clock);
   527     return GST_STATE_CHANGE_FAILURE;
   545     return GST_STATE_CHANGE_FAILURE;
   528   }
   546   }
   529 }
   547 }
   530 
   548 
   531 /* intercept the bus messages from our children. We watch for the ASYNC_START
       
   532  * message with is posted by the elements (sinks) that require a reset of the
       
   533  * running_time after a flush. ASYNC_START also brings the pipeline back into
       
   534  * the PAUSED, pending PAUSED state. When the ASYNC_DONE message is received the
       
   535  * pipeline will redistribute the new base_time and will bring the elements back
       
   536  * to the desired state of the pipeline. */
       
   537 static void
   549 static void
   538 gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
   550 gst_pipeline_handle_message (GstBin * bin, GstMessage * message)
   539 {
   551 {
   540   GstPipeline *pipeline = GST_PIPELINE_CAST (bin);
   552   GstPipeline *pipeline = GST_PIPELINE_CAST (bin);
   541 
   553 
   544     {
   556     {
   545       gboolean new_base_time;
   557       gboolean new_base_time;
   546 
   558 
   547       gst_message_parse_async_start (message, &new_base_time);
   559       gst_message_parse_async_start (message, &new_base_time);
   548 
   560 
   549       /* reset our running time if we need to distribute a new base_time to the
   561       /* reset our stream time if we need to distribute a new base_time to the
   550        * children. */
   562        * children. */
   551       if (new_base_time)
   563       if (new_base_time)
   552         reset_start_time (pipeline);
   564         reset_stream_time (pipeline);
   553 
   565 
   554       break;
   566       break;
   555     }
   567     }
   556     default:
   568     default:
   557       break;
   569       break;
   561 
   573 
   562 /**
   574 /**
   563  * gst_pipeline_get_bus:
   575  * gst_pipeline_get_bus:
   564  * @pipeline: a #GstPipeline
   576  * @pipeline: a #GstPipeline
   565  *
   577  *
   566  * Gets the #GstBus of @pipeline. The bus allows applications to receive #GstMessages.
   578  * Gets the #GstBus of @pipeline.
   567  *
   579  *
   568  * Returns: a #GstBus, unref after usage.
   580  * Returns: a #GstBus, unref after usage.
   569  *
   581  *
   570  * MT safe.
   582  * MT safe.
   571  */
   583  */
   580 }
   592 }
   581 
   593 
   582 /**
   594 /**
   583  * gst_pipeline_set_new_stream_time:
   595  * gst_pipeline_set_new_stream_time:
   584  * @pipeline: a #GstPipeline
   596  * @pipeline: a #GstPipeline
   585  * @time: the new running time to set
   597  * @time: the new stream time to set
   586  *
   598  *
   587  * Set the new start time of @pipeline to @time. The start time is used to
   599  * Set the new stream time of @pipeline to @time. The stream time is used to
   588  * set the base time on the elements (see gst_element_set_base_time())
   600  * set the base time on the elements (see gst_element_set_base_time())
   589  * in the PAUSED->PLAYING state transition.
   601  * in the PAUSED->PLAYING state transition.
   590  *
   602  *
   591  * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management
   603  * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management
   592  * of element base time. The application will then be responsible for
   604  * of element base time. The application will then be responsible for
   593  * performing base time distribution. This is sometimes useful if you want to
   605  * performing base time distribution. This is sometimes useful if you want to
   594  * synchronize capture from multiple pipelines, and you can also ensure that the
   606  * synchronize capture from multiple pipelines, and you can also ensure that the
   595  * pipelines have the same clock.
   607  * pipelines have the same clock.
   596  *
   608  *
   597  * MT safe.
   609  * MT safe.
   598  *
   610  */
   599  * Deprecated: This function has the wrong name and is equivalent to
   611 #ifdef __SYMBIAN32__
   600  * gst_element_set_start_time(). 
   612 EXPORT_C
   601  */
   613 #endif
   602 #ifndef GST_REMOVE_DEPRECATED
   614 
   603 #ifdef __SYMBIAN32__
       
   604 EXPORT_C
       
   605 #endif
       
   606 void
   615 void
   607 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
   616 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
   608 {
   617 {
   609   g_return_if_fail (GST_IS_PIPELINE (pipeline));
   618   g_return_if_fail (GST_IS_PIPELINE (pipeline));
   610 
   619 
   611   gst_element_set_start_time (GST_ELEMENT_CAST (pipeline), time);
   620   GST_OBJECT_LOCK (pipeline);
       
   621   pipeline->stream_time = time;
       
   622   pipeline->priv->update_stream_time = TRUE;
       
   623   GST_OBJECT_UNLOCK (pipeline);
       
   624 
       
   625   GST_DEBUG_OBJECT (pipeline, "set new stream_time to %" GST_TIME_FORMAT,
       
   626       GST_TIME_ARGS (time));
   612 
   627 
   613   if (time == GST_CLOCK_TIME_NONE)
   628   if (time == GST_CLOCK_TIME_NONE)
   614     GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time");
   629     GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time");
   615 }
   630 }
   616 #endif /* GST_REMOVE_DEPRECATED */
       
   617 
   631 
   618 /**
   632 /**
   619  * gst_pipeline_get_last_stream_time:
   633  * gst_pipeline_get_last_stream_time:
   620  * @pipeline: a #GstPipeline
   634  * @pipeline: a #GstPipeline
   621  *
   635  *
   622  * Gets the last running time of @pipeline. If the pipeline is PLAYING,
   636  * Gets the last stream time of @pipeline. If the pipeline is PLAYING,
   623  * the returned time is the running time used to configure the element's
   637  * the returned time is the stream time used to configure the element's
   624  * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the
   638  * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the
   625  * returned time is the running time when the pipeline was paused.
   639  * returned time is the stream time when the pipeline was paused.
   626  *
   640  *
   627  * This function returns #GST_CLOCK_TIME_NONE if the pipeline was
   641  * This function returns #GST_CLOCK_TIME_NONE if the pipeline was
   628  * configured to not handle the management of the element's base time
   642  * configured to not handle the management of the element's base time
   629  * (see gst_pipeline_set_new_stream_time()).
   643  * (see gst_pipeline_set_new_stream_time()).
   630  *
   644  *
   631  * MT safe.
       
   632  *
       
   633  * Returns: a #GstClockTime.
   645  * Returns: a #GstClockTime.
   634  *
   646  *
   635  * Deprecated: This function has the wrong name and is equivalent to
   647  * MT safe.
   636  * gst_element_get_start_time(). 
   648  */
   637  */
   649 #ifdef __SYMBIAN32__
   638 #ifndef GST_REMOVE_DEPRECATED
   650 EXPORT_C
   639 #ifdef __SYMBIAN32__
   651 #endif
   640 EXPORT_C
   652 
   641 #endif
       
   642 GstClockTime
   653 GstClockTime
   643 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
   654 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
   644 {
   655 {
   645   GstClockTime result;
   656   GstClockTime result;
   646 
   657 
   647   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
   658   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
   648 
   659 
   649   result = gst_element_get_start_time (GST_ELEMENT_CAST (pipeline));
   660   GST_OBJECT_LOCK (pipeline);
       
   661   result = pipeline->stream_time;
       
   662   GST_OBJECT_UNLOCK (pipeline);
   650 
   663 
   651   return result;
   664   return result;
   652 }
   665 }
   653 #endif /* GST_REMOVE_DEPRECATED */
       
   654 
   666 
   655 static GstClock *
   667 static GstClock *
   656 gst_pipeline_provide_clock_func (GstElement * element)
   668 gst_pipeline_provide_clock_func (GstElement * element)
   657 {
   669 {
   658   GstClock *clock = NULL;
   670   GstClock *clock = NULL;
   670         clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
   682         clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
   671   } else {
   683   } else {
   672     GST_OBJECT_UNLOCK (pipeline);
   684     GST_OBJECT_UNLOCK (pipeline);
   673     /* let the parent bin select a clock */
   685     /* let the parent bin select a clock */
   674     clock =
   686     clock =
   675         GST_ELEMENT_CLASS (parent_class)->provide_clock (GST_ELEMENT
   687         GST_ELEMENT_CLASS (parent_class)->
   676         (pipeline));
   688         provide_clock (GST_ELEMENT (pipeline));
   677     /* no clock, use a system clock */
   689     /* no clock, use a system clock */
   678     if (!clock) {
   690     if (!clock) {
   679       clock = gst_system_clock_obtain ();
   691       clock = gst_system_clock_obtain ();
   680 
   692 
   681       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
   693       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",