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