LCOV - code coverage report
Current view: top level - libs/gst/base - gstbasesrc.c (source / functions) Hit Total Coverage
Test: GStreamer 0.10.32.1 Lines: 769 1172 65.6 %
Date: 2011-03-25 Functions: 41 51 80.4 %
Branches: 357 977 36.5 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer
       2                 :            :  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       3                 :            :  *               2000,2005 Wim Taymans <wim@fluendo.com>
       4                 :            :  *
       5                 :            :  * gstbasesrc.c:
       6                 :            :  *
       7                 :            :  * This library is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU Library General Public
       9                 :            :  * License as published by the Free Software Foundation; either
      10                 :            :  * version 2 of the License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This library is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :            :  * Library General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU Library General Public
      18                 :            :  * License along with this library; if not, write to the
      19                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      20                 :            :  * Boston, MA 02111-1307, USA.
      21                 :            :  */
      22                 :            : 
      23                 :            : /**
      24                 :            :  * SECTION:gstbasesrc
      25                 :            :  * @short_description: Base class for getrange based source elements
      26                 :            :  * @see_also: #GstPushSrc, #GstBaseTransform, #GstBaseSink
      27                 :            :  *
      28                 :            :  * This is a generice base class for source elements. The following
      29                 :            :  * types of sources are supported:
      30                 :            :  * <itemizedlist>
      31                 :            :  *   <listitem><para>random access sources like files</para></listitem>
      32                 :            :  *   <listitem><para>seekable sources</para></listitem>
      33                 :            :  *   <listitem><para>live sources</para></listitem>
      34                 :            :  * </itemizedlist>
      35                 :            :  *
      36                 :            :  * The source can be configured to operate in any #GstFormat with the
      37                 :            :  * gst_base_src_set_format() method. The currently set format determines
      38                 :            :  * the format of the internal #GstSegment and any #GST_EVENT_NEWSEGMENT
      39                 :            :  * events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES.
      40                 :            :  *
      41                 :            :  * #GstBaseSrc always supports push mode scheduling. If the following
      42                 :            :  * conditions are met, it also supports pull mode scheduling:
      43                 :            :  * <itemizedlist>
      44                 :            :  *   <listitem><para>The format is set to #GST_FORMAT_BYTES (default).</para>
      45                 :            :  *   </listitem>
      46                 :            :  *   <listitem><para>#GstBaseSrcClass.is_seekable() returns %TRUE.</para>
      47                 :            :  *   </listitem>
      48                 :            :  * </itemizedlist>
      49                 :            :  *
      50                 :            :  * Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any time
      51                 :            :  * by overriding #GstBaseSrcClass.check_get_range() so that it returns %TRUE.
      52                 :            :  *
      53                 :            :  * If all the conditions are met for operating in pull mode, #GstBaseSrc is
      54                 :            :  * automatically seekable in push mode as well. The following conditions must
      55                 :            :  * be met to make the element seekable in push mode when the format is not
      56                 :            :  * #GST_FORMAT_BYTES:
      57                 :            :  * <itemizedlist>
      58                 :            :  *   <listitem><para>
      59                 :            :  *     #GstBaseSrcClass.is_seekable() returns %TRUE.
      60                 :            :  *   </para></listitem>
      61                 :            :  *   <listitem><para>
      62                 :            :  *     #GstBaseSrcClass.query() can convert all supported seek formats to the
      63                 :            :  *     internal format as set with gst_base_src_set_format().
      64                 :            :  *   </para></listitem>
      65                 :            :  *   <listitem><para>
      66                 :            :  *     #GstBaseSrcClass.do_seek() is implemented, performs the seek and returns
      67                 :            :  *      %TRUE.
      68                 :            :  *   </para></listitem>
      69                 :            :  * </itemizedlist>
      70                 :            :  *
      71                 :            :  * When the element does not meet the requirements to operate in pull mode, the
      72                 :            :  * offset and length in the #GstBaseSrcClass.create() method should be ignored.
      73                 :            :  * It is recommended to subclass #GstPushSrc instead, in this situation. If the
      74                 :            :  * element can operate in pull mode but only with specific offsets and
      75                 :            :  * lengths, it is allowed to generate an error when the wrong values are passed
      76                 :            :  * to the #GstBaseSrcClass.create() function.
      77                 :            :  *
      78                 :            :  * #GstBaseSrc has support for live sources. Live sources are sources that when
      79                 :            :  * paused discard data, such as audio or video capture devices. A typical live
      80                 :            :  * source also produces data at a fixed rate and thus provides a clock to publish
      81                 :            :  * this rate.
      82                 :            :  * Use gst_base_src_set_live() to activate the live source mode.
      83                 :            :  *
      84                 :            :  * A live source does not produce data in the PAUSED state. This means that the
      85                 :            :  * #GstBaseSrcClass.create() method will not be called in PAUSED but only in
      86                 :            :  * PLAYING. To signal the pipeline that the element will not produce data, the
      87                 :            :  * return value from the READY to PAUSED state will be
      88                 :            :  * #GST_STATE_CHANGE_NO_PREROLL.
      89                 :            :  *
      90                 :            :  * A typical live source will timestamp the buffers it creates with the
      91                 :            :  * current running time of the pipeline. This is one reason why a live source
      92                 :            :  * can only produce data in the PLAYING state, when the clock is actually
      93                 :            :  * distributed and running.
      94                 :            :  *
      95                 :            :  * Live sources that synchronize and block on the clock (an audio source, for
      96                 :            :  * example) can since 0.10.12 use gst_base_src_wait_playing() when the
      97                 :            :  * #GstBaseSrcClass.create() function was interrupted by a state change to
      98                 :            :  * PAUSED.
      99                 :            :  *
     100                 :            :  * The #GstBaseSrcClass.get_times() method can be used to implement pseudo-live
     101                 :            :  * sources. It only makes sense to implement the #GstBaseSrcClass.get_times()
     102                 :            :  * function if the source is a live source. The #GstBaseSrcClass.get_times()
     103                 :            :  * function should return timestamps starting from 0, as if it were a non-live
     104                 :            :  * source. The base class will make sure that the timestamps are transformed
     105                 :            :  * into the current running_time. The base source will then wait for the
     106                 :            :  * calculated running_time before pushing out the buffer.
     107                 :            :  *
     108                 :            :  * For live sources, the base class will by default report a latency of 0.
     109                 :            :  * For pseudo live sources, the base class will by default measure the difference
     110                 :            :  * between the first buffer timestamp and the start time of get_times and will
     111                 :            :  * report this value as the latency.
     112                 :            :  * Subclasses should override the query function when this behaviour is not
     113                 :            :  * acceptable.
     114                 :            :  *
     115                 :            :  * There is only support in #GstBaseSrc for exactly one source pad, which
     116                 :            :  * should be named "src". A source implementation (subclass of #GstBaseSrc)
     117                 :            :  * should install a pad template in its class_init function, like so:
     118                 :            :  * |[
     119                 :            :  * static void
     120                 :            :  * my_element_class_init (GstMyElementClass *klass)
     121                 :            :  * {
     122                 :            :  *   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
     123                 :            :  *   // srctemplate should be a #GstStaticPadTemplate with direction
     124                 :            :  *   // #GST_PAD_SRC and name "src"
     125                 :            :  *   gst_element_class_add_pad_template (gstelement_class,
     126                 :            :  *       gst_static_pad_template_get (&amp;srctemplate));
     127                 :            :  *   // see #GstElementDetails
     128                 :            :  *   gst_element_class_set_details (gstelement_class, &amp;details);
     129                 :            :  * }
     130                 :            :  * ]|
     131                 :            :  *
     132                 :            :  * <refsect2>
     133                 :            :  * <title>Controlled shutdown of live sources in applications</title>
     134                 :            :  * <para>
     135                 :            :  * Applications that record from a live source may want to stop recording
     136                 :            :  * in a controlled way, so that the recording is stopped, but the data
     137                 :            :  * already in the pipeline is processed to the end (remember that many live
     138                 :            :  * sources would go on recording forever otherwise). For that to happen the
     139                 :            :  * application needs to make the source stop recording and send an EOS
     140                 :            :  * event down the pipeline. The application would then wait for an
     141                 :            :  * EOS message posted on the pipeline's bus to know when all data has
     142                 :            :  * been processed and the pipeline can safely be stopped.
     143                 :            :  *
     144                 :            :  * Since GStreamer 0.10.16 an application may send an EOS event to a source
     145                 :            :  * element to make it perform the EOS logic (send EOS event downstream or post a
     146                 :            :  * #GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
     147                 :            :  * with the gst_element_send_event() function on the element or its parent bin.
     148                 :            :  *
     149                 :            :  * After the EOS has been sent to the element, the application should wait for
     150                 :            :  * an EOS message to be posted on the pipeline's bus. Once this EOS message is
     151                 :            :  * received, it may safely shut down the entire pipeline.
     152                 :            :  *
     153                 :            :  * The old behaviour for controlled shutdown introduced since GStreamer 0.10.3
     154                 :            :  * is still available but deprecated as it is dangerous and less flexible.
     155                 :            :  *
     156                 :            :  * Last reviewed on 2007-12-19 (0.10.16)
     157                 :            :  * </para>
     158                 :            :  * </refsect2>
     159                 :            :  */
     160                 :            : 
     161                 :            : #ifdef HAVE_CONFIG_H
     162                 :            : #  include "config.h"
     163                 :            : #endif
     164                 :            : 
     165                 :            : #include <stdlib.h>
     166                 :            : #include <string.h>
     167                 :            : 
     168                 :            : #include <gst/gst_private.h>
     169                 :            : 
     170                 :            : #include "gstbasesrc.h"
     171                 :            : #include "gsttypefindhelper.h"
     172                 :            : #include <gst/gstmarshal.h>
     173                 :            : #include <gst/gst-i18n-lib.h>
     174                 :            : 
     175                 :            : GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
     176                 :            : #define GST_CAT_DEFAULT gst_base_src_debug
     177                 :            : 
     178                 :            : #define GST_LIVE_GET_LOCK(elem)               (GST_BASE_SRC_CAST(elem)->live_lock)
     179                 :            : #define GST_LIVE_LOCK(elem)                   g_mutex_lock(GST_LIVE_GET_LOCK(elem))
     180                 :            : #define GST_LIVE_TRYLOCK(elem)                g_mutex_trylock(GST_LIVE_GET_LOCK(elem))
     181                 :            : #define GST_LIVE_UNLOCK(elem)                 g_mutex_unlock(GST_LIVE_GET_LOCK(elem))
     182                 :            : #define GST_LIVE_GET_COND(elem)               (GST_BASE_SRC_CAST(elem)->live_cond)
     183                 :            : #define GST_LIVE_WAIT(elem)                   g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))
     184                 :            : #define GST_LIVE_TIMED_WAIT(elem, timeval)    g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem),\
     185                 :            :                                                                                 timeval)
     186                 :            : #define GST_LIVE_SIGNAL(elem)                 g_cond_signal (GST_LIVE_GET_COND (elem));
     187                 :            : #define GST_LIVE_BROADCAST(elem)              g_cond_broadcast (GST_LIVE_GET_COND (elem));
     188                 :            : 
     189                 :            : /* BaseSrc signals and args */
     190                 :            : enum
     191                 :            : {
     192                 :            :   /* FILL ME */
     193                 :            :   LAST_SIGNAL
     194                 :            : };
     195                 :            : 
     196                 :            : #define DEFAULT_BLOCKSIZE       4096
     197                 :            : #define DEFAULT_NUM_BUFFERS     -1
     198                 :            : #define DEFAULT_TYPEFIND        FALSE
     199                 :            : #define DEFAULT_DO_TIMESTAMP    FALSE
     200                 :            : 
     201                 :            : enum
     202                 :            : {
     203                 :            :   PROP_0,
     204                 :            :   PROP_BLOCKSIZE,
     205                 :            :   PROP_NUM_BUFFERS,
     206                 :            :   PROP_TYPEFIND,
     207                 :            :   PROP_DO_TIMESTAMP
     208                 :            : };
     209                 :            : 
     210                 :            : #define GST_BASE_SRC_GET_PRIVATE(obj)  \
     211                 :            :    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SRC, GstBaseSrcPrivate))
     212                 :            : 
     213                 :            : struct _GstBaseSrcPrivate
     214                 :            : {
     215                 :            :   gboolean last_sent_eos;       /* last thing we did was send an EOS (we set this
     216                 :            :                                  * to avoid the sending of two EOS in some cases) */
     217                 :            :   gboolean discont;
     218                 :            :   gboolean flushing;
     219                 :            : 
     220                 :            :   /* two segments to be sent in the streaming thread with STREAM_LOCK */
     221                 :            :   GstEvent *close_segment;
     222                 :            :   GstEvent *start_segment;
     223                 :            :   gboolean newsegment_pending;
     224                 :            : 
     225                 :            :   /* if EOS is pending (atomic) */
     226                 :            :   gint pending_eos;
     227                 :            : 
     228                 :            :   /* startup latency is the time it takes between going to PLAYING and producing
     229                 :            :    * the first BUFFER with running_time 0. This value is included in the latency
     230                 :            :    * reporting. */
     231                 :            :   GstClockTime latency;
     232                 :            :   /* timestamp offset, this is the offset add to the values of gst_times for
     233                 :            :    * pseudo live sources */
     234                 :            :   GstClockTimeDiff ts_offset;
     235                 :            : 
     236                 :            :   gboolean do_timestamp;
     237                 :            : 
     238                 :            :   /* stream sequence number */
     239                 :            :   guint32 seqnum;
     240                 :            : 
     241                 :            :   /* pending tags to be pushed in the data stream */
     242                 :            :   GList *pending_tags;
     243                 :            :   volatile gint have_tags;
     244                 :            : 
     245                 :            :   /* QoS *//* with LOCK */
     246                 :            :   gboolean qos_enabled;
     247                 :            :   gdouble proportion;
     248                 :            :   GstClockTime earliest_time;
     249                 :            : };
     250                 :            : 
     251                 :            : static GstElementClass *parent_class = NULL;
     252                 :            : 
     253                 :            : static void gst_base_src_base_init (gpointer g_class);
     254                 :            : static void gst_base_src_class_init (GstBaseSrcClass * klass);
     255                 :            : static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
     256                 :            : static void gst_base_src_finalize (GObject * object);
     257                 :            : 
     258                 :            : 
     259                 :            : GType
     260                 :    1188303 : gst_base_src_get_type (void)
     261                 :            : {
     262                 :            :   static volatile gsize base_src_type = 0;
     263                 :            : 
     264         [ +  + ]:    1188303 :   if (g_once_init_enter (&base_src_type)) {
     265                 :            :     GType _type;
     266                 :            :     static const GTypeInfo base_src_info = {
     267                 :            :       sizeof (GstBaseSrcClass),
     268                 :            :       (GBaseInitFunc) gst_base_src_base_init,
     269                 :            :       NULL,
     270                 :            :       (GClassInitFunc) gst_base_src_class_init,
     271                 :            :       NULL,
     272                 :            :       NULL,
     273                 :            :       sizeof (GstBaseSrc),
     274                 :            :       0,
     275                 :            :       (GInstanceInitFunc) gst_base_src_init,
     276                 :            :     };
     277                 :            : 
     278                 :        153 :     _type = g_type_register_static (GST_TYPE_ELEMENT,
     279                 :            :         "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
     280                 :        153 :     g_once_init_leave (&base_src_type, _type);
     281                 :            :   }
     282                 :    1188304 :   return base_src_type;
     283                 :            : }
     284                 :            : 
     285                 :            : static GstCaps *gst_base_src_getcaps (GstPad * pad);
     286                 :            : static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
     287                 :            : static void gst_base_src_fixate (GstPad * pad, GstCaps * caps);
     288                 :            : 
     289                 :            : static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
     290                 :            : static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
     291                 :            : static void gst_base_src_set_property (GObject * object, guint prop_id,
     292                 :            :     const GValue * value, GParamSpec * pspec);
     293                 :            : static void gst_base_src_get_property (GObject * object, guint prop_id,
     294                 :            :     GValue * value, GParamSpec * pspec);
     295                 :            : static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);
     296                 :            : static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);
     297                 :            : static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event);
     298                 :            : static const GstQueryType *gst_base_src_get_query_types (GstElement * element);
     299                 :            : 
     300                 :            : static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
     301                 :            : 
     302                 :            : static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
     303                 :            : static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,
     304                 :            :     GstSegment * segment);
     305                 :            : static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);
     306                 :            : static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src,
     307                 :            :     GstEvent * event, GstSegment * segment);
     308                 :            : 
     309                 :            : static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc,
     310                 :            :     gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing);
     311                 :            : static gboolean gst_base_src_start (GstBaseSrc * basesrc);
     312                 :            : static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
     313                 :            : 
     314                 :            : static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
     315                 :            :     GstStateChange transition);
     316                 :            : 
     317                 :            : static void gst_base_src_loop (GstPad * pad);
     318                 :            : static gboolean gst_base_src_pad_check_get_range (GstPad * pad);
     319                 :            : static gboolean gst_base_src_default_check_get_range (GstBaseSrc * bsrc);
     320                 :            : static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,
     321                 :            :     guint length, GstBuffer ** buf);
     322                 :            : static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
     323                 :            :     guint length, GstBuffer ** buf);
     324                 :            : static gboolean gst_base_src_seekable (GstBaseSrc * src);
     325                 :            : 
     326                 :            : static void
     327                 :        253 : gst_base_src_base_init (gpointer g_class)
     328                 :            : {
     329         [ +  + ]:        253 :   GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
     330                 :        253 : }
     331                 :            : 
     332                 :            : static void
     333                 :        111 : gst_base_src_class_init (GstBaseSrcClass * klass)
     334                 :            : {
     335                 :            :   GObjectClass *gobject_class;
     336                 :            :   GstElementClass *gstelement_class;
     337                 :            : 
     338                 :        111 :   gobject_class = G_OBJECT_CLASS (klass);
     339                 :        111 :   gstelement_class = GST_ELEMENT_CLASS (klass);
     340                 :            : 
     341                 :        111 :   g_type_class_add_private (klass, sizeof (GstBaseSrcPrivate));
     342                 :            : 
     343                 :        111 :   parent_class = g_type_class_peek_parent (klass);
     344                 :            : 
     345                 :        111 :   gobject_class->finalize = gst_base_src_finalize;
     346                 :        111 :   gobject_class->set_property = gst_base_src_set_property;
     347                 :        111 :   gobject_class->get_property = gst_base_src_get_property;
     348                 :            : 
     349                 :            : /* FIXME 0.11: blocksize property should be int, not ulong (min is >max here) */
     350                 :        111 :   g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
     351                 :            :       g_param_spec_ulong ("blocksize", "Block size",
     352                 :            :           "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
     353                 :            :           DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     354                 :        111 :   g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
     355                 :            :       g_param_spec_int ("num-buffers", "num-buffers",
     356                 :            :           "Number of buffers to output before sending EOS (-1 = unlimited)",
     357                 :            :           -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE |
     358                 :            :           G_PARAM_STATIC_STRINGS));
     359                 :        111 :   g_object_class_install_property (gobject_class, PROP_TYPEFIND,
     360                 :            :       g_param_spec_boolean ("typefind", "Typefind",
     361                 :            :           "Run typefind before negotiating", DEFAULT_TYPEFIND,
     362                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     363                 :        111 :   g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP,
     364                 :            :       g_param_spec_boolean ("do-timestamp", "Do timestamp",
     365                 :            :           "Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP,
     366                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     367                 :            : 
     368                 :        111 :   gstelement_class->change_state =
     369                 :        111 :       GST_DEBUG_FUNCPTR (gst_base_src_change_state);
     370                 :        111 :   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);
     371                 :        111 :   gstelement_class->get_query_types =
     372                 :        111 :       GST_DEBUG_FUNCPTR (gst_base_src_get_query_types);
     373                 :            : 
     374                 :        111 :   klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate);
     375                 :        111 :   klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);
     376                 :        111 :   klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);
     377                 :        111 :   klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);
     378                 :        111 :   klass->check_get_range =
     379                 :        111 :       GST_DEBUG_FUNCPTR (gst_base_src_default_check_get_range);
     380                 :        111 :   klass->prepare_seek_segment =
     381                 :        111 :       GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment);
     382                 :            : 
     383                 :            :   /* Registering debug symbols for function pointers */
     384                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_push);
     385                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_pull);
     386                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event_handler);
     387                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query);
     388                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_get_range);
     389                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_check_get_range);
     390                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getcaps);
     391                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_setcaps);
     392                 :        111 :   GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate);
     393                 :        111 : }
     394                 :            : 
     395                 :            : static void
     396                 :        164 : gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
     397                 :            : {
     398                 :            :   GstPad *pad;
     399                 :            :   GstPadTemplate *pad_template;
     400                 :            : 
     401                 :        164 :   basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc);
     402                 :            : 
     403                 :        164 :   basesrc->is_live = FALSE;
     404                 :        164 :   basesrc->live_lock = g_mutex_new ();
     405                 :        164 :   basesrc->live_cond = g_cond_new ();
     406                 :        164 :   basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
     407                 :        164 :   basesrc->num_buffers_left = -1;
     408                 :            : 
     409                 :        164 :   basesrc->can_activate_push = TRUE;
     410                 :        164 :   basesrc->pad_mode = GST_ACTIVATE_NONE;
     411                 :            : 
     412                 :        164 :   pad_template =
     413                 :        164 :       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
     414         [ -  + ]:        328 :   g_return_if_fail (pad_template != NULL);
     415                 :            : 
     416         [ -  + ]:        164 :   GST_DEBUG_OBJECT (basesrc, "creating src pad");
     417                 :        164 :   pad = gst_pad_new_from_template (pad_template, "src");
     418                 :            : 
     419         [ -  + ]:        164 :   GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
     420                 :        164 :   gst_pad_set_activatepush_function (pad, gst_base_src_activate_push);
     421                 :        164 :   gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
     422                 :        164 :   gst_pad_set_event_function (pad, gst_base_src_event_handler);
     423                 :        164 :   gst_pad_set_query_function (pad, gst_base_src_query);
     424                 :        164 :   gst_pad_set_checkgetrange_function (pad, gst_base_src_pad_check_get_range);
     425                 :        164 :   gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range);
     426                 :        164 :   gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
     427                 :        164 :   gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
     428                 :        164 :   gst_pad_set_fixatecaps_function (pad, gst_base_src_fixate);
     429                 :            : 
     430                 :            :   /* hold pointer to pad */
     431                 :        164 :   basesrc->srcpad = pad;
     432         [ -  + ]:        164 :   GST_DEBUG_OBJECT (basesrc, "adding src pad");
     433                 :        164 :   gst_element_add_pad (GST_ELEMENT (basesrc), pad);
     434                 :            : 
     435                 :        164 :   basesrc->blocksize = DEFAULT_BLOCKSIZE;
     436                 :        164 :   basesrc->clock_id = NULL;
     437                 :            :   /* we operate in BYTES by default */
     438                 :        164 :   gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
     439                 :        164 :   basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
     440                 :        164 :   basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
     441                 :        164 :   g_atomic_int_set (&basesrc->priv->have_tags, FALSE);
     442                 :            : 
     443                 :        164 :   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
     444                 :        164 :   GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_IS_SOURCE);
     445                 :            : 
     446         [ -  + ]:        164 :   GST_DEBUG_OBJECT (basesrc, "init done");
     447                 :            : }
     448                 :            : 
     449                 :            : static void
     450                 :        156 : gst_base_src_finalize (GObject * object)
     451                 :            : {
     452                 :            :   GstBaseSrc *basesrc;
     453                 :            :   GstEvent **event_p;
     454                 :            : 
     455                 :        156 :   basesrc = GST_BASE_SRC (object);
     456                 :            : 
     457                 :        156 :   g_mutex_free (basesrc->live_lock);
     458                 :        156 :   g_cond_free (basesrc->live_cond);
     459                 :            : 
     460                 :        156 :   event_p = &basesrc->data.ABI.pending_seek;
     461                 :        156 :   gst_event_replace (event_p, NULL);
     462                 :            : 
     463         [ -  + ]:        156 :   if (basesrc->priv->pending_tags) {
     464                 :          0 :     g_list_foreach (basesrc->priv->pending_tags, (GFunc) gst_event_unref, NULL);
     465                 :          0 :     g_list_free (basesrc->priv->pending_tags);
     466                 :            :   }
     467                 :            : 
     468                 :        156 :   G_OBJECT_CLASS (parent_class)->finalize (object);
     469                 :        156 : }
     470                 :            : 
     471                 :            : /**
     472                 :            :  * gst_base_src_wait_playing:
     473                 :            :  * @src: the src
     474                 :            :  *
     475                 :            :  * If the #GstBaseSrcClass.create() method performs its own synchronisation
     476                 :            :  * against the clock it must unblock when going from PLAYING to the PAUSED state
     477                 :            :  * and call this method before continuing to produce the remaining data.
     478                 :            :  *
     479                 :            :  * This function will block until a state change to PLAYING happens (in which
     480                 :            :  * case this function returns #GST_FLOW_OK) or the processing must be stopped due
     481                 :            :  * to a state change to READY or a FLUSH event (in which case this function
     482                 :            :  * returns #GST_FLOW_WRONG_STATE).
     483                 :            :  *
     484                 :            :  * Since: 0.10.12
     485                 :            :  *
     486                 :            :  * Returns: #GST_FLOW_OK if @src is PLAYING and processing can
     487                 :            :  * continue. Any other return value should be returned from the create vmethod.
     488                 :            :  */
     489                 :            : GstFlowReturn
     490                 :          0 : gst_base_src_wait_playing (GstBaseSrc * src)
     491                 :            : {
     492 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_BASE_SRC (src), GST_FLOW_ERROR);
         [ #  # ][ #  # ]
     493                 :            : 
     494                 :            :   do {
     495                 :            :     /* block until the state changes, or we get a flush, or something */
     496         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "live source waiting for running state");
     497                 :          0 :     GST_LIVE_WAIT (src);
     498         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "live source unlocked");
     499         [ #  # ]:          0 :     if (src->priv->flushing)
     500                 :          0 :       goto flushing;
     501         [ #  # ]:          0 :   } while (G_UNLIKELY (!src->live_running));
     502                 :            : 
     503                 :          0 :   return GST_FLOW_OK;
     504                 :            : 
     505                 :            :   /* ERRORS */
     506                 :            : flushing:
     507                 :            :   {
     508         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "we are flushing");
     509                 :          0 :     return GST_FLOW_WRONG_STATE;
     510                 :            :   }
     511                 :            : }
     512                 :            : 
     513                 :            : /**
     514                 :            :  * gst_base_src_set_live:
     515                 :            :  * @src: base source instance
     516                 :            :  * @live: new live-mode
     517                 :            :  *
     518                 :            :  * If the element listens to a live source, @live should
     519                 :            :  * be set to %TRUE.
     520                 :            :  *
     521                 :            :  * A live source will not produce data in the PAUSED state and
     522                 :            :  * will therefore not be able to participate in the PREROLL phase
     523                 :            :  * of a pipeline. To signal this fact to the application and the
     524                 :            :  * pipeline, the state change return value of the live source will
     525                 :            :  * be GST_STATE_CHANGE_NO_PREROLL.
     526                 :            :  */
     527                 :            : void
     528                 :        137 : gst_base_src_set_live (GstBaseSrc * src, gboolean live)
     529                 :            : {
     530 [ -  + ][ +  - ]:        274 :   g_return_if_fail (GST_IS_BASE_SRC (src));
         [ -  + ][ -  + ]
     531                 :            : 
     532                 :        137 :   GST_OBJECT_LOCK (src);
     533                 :        137 :   src->is_live = live;
     534                 :        137 :   GST_OBJECT_UNLOCK (src);
     535                 :            : }
     536                 :            : 
     537                 :            : /**
     538                 :            :  * gst_base_src_is_live:
     539                 :            :  * @src: base source instance
     540                 :            :  *
     541                 :            :  * Check if an element is in live mode.
     542                 :            :  *
     543                 :            :  * Returns: %TRUE if element is in live mode.
     544                 :            :  */
     545                 :            : gboolean
     546                 :     534553 : gst_base_src_is_live (GstBaseSrc * src)
     547                 :            : {
     548                 :            :   gboolean result;
     549                 :            : 
     550 [ -  + ][ +  - ]:     534553 :   g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
         [ -  + ][ -  + ]
     551                 :            : 
     552                 :     534553 :   GST_OBJECT_LOCK (src);
     553                 :     534553 :   result = src->is_live;
     554                 :     534553 :   GST_OBJECT_UNLOCK (src);
     555                 :            : 
     556                 :     534553 :   return result;
     557                 :            : }
     558                 :            : 
     559                 :            : /**
     560                 :            :  * gst_base_src_set_format:
     561                 :            :  * @src: base source instance
     562                 :            :  * @format: the format to use
     563                 :            :  *
     564                 :            :  * Sets the default format of the source. This will be the format used
     565                 :            :  * for sending NEW_SEGMENT events and for performing seeks.
     566                 :            :  *
     567                 :            :  * If a format of GST_FORMAT_BYTES is set, the element will be able to
     568                 :            :  * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns TRUE.
     569                 :            :  *
     570                 :            :  * This function must only be called in states < %GST_STATE_PAUSED.
     571                 :            :  *
     572                 :            :  * Since: 0.10.1
     573                 :            :  */
     574                 :            : void
     575                 :        558 : gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
     576                 :            : {
     577 [ -  + ][ +  - ]:        558 :   g_return_if_fail (GST_IS_BASE_SRC (src));
         [ +  + ][ -  + ]
     578         [ -  + ]:        558 :   g_return_if_fail (GST_STATE (src) <= GST_STATE_READY);
     579                 :            : 
     580                 :        558 :   GST_OBJECT_LOCK (src);
     581                 :        558 :   gst_segment_init (&src->segment, format);
     582                 :        558 :   GST_OBJECT_UNLOCK (src);
     583                 :            : }
     584                 :            : 
     585                 :            : /**
     586                 :            :  * gst_base_src_query_latency:
     587                 :            :  * @src: the source
     588                 :            :  * @live: (out) (allow-none): if the source is live
     589                 :            :  * @min_latency: (out) (allow-none): the min latency of the source
     590                 :            :  * @max_latency: (out) (allow-none): the max latency of the source
     591                 :            :  *
     592                 :            :  * Query the source for the latency parameters. @live will be TRUE when @src is
     593                 :            :  * configured as a live source. @min_latency will be set to the difference
     594                 :            :  * between the running time and the timestamp of the first buffer.
     595                 :            :  * @max_latency is always the undefined value of -1.
     596                 :            :  *
     597                 :            :  * This function is mostly used by subclasses.
     598                 :            :  *
     599                 :            :  * Returns: TRUE if the query succeeded.
     600                 :            :  *
     601                 :            :  * Since: 0.10.13
     602                 :            :  */
     603                 :            : gboolean
     604                 :        102 : gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
     605                 :            :     GstClockTime * min_latency, GstClockTime * max_latency)
     606                 :            : {
     607                 :            :   GstClockTime min;
     608                 :            : 
     609 [ -  + ][ +  - ]:        102 :   g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
         [ -  + ][ -  + ]
     610                 :            : 
     611                 :        102 :   GST_OBJECT_LOCK (src);
     612         [ +  - ]:        102 :   if (live)
     613                 :        102 :     *live = src->is_live;
     614                 :            : 
     615                 :            :   /* if we have a startup latency, report this one, else report 0. Subclasses
     616                 :            :    * are supposed to override the query function if they want something
     617                 :            :    * else. */
     618         [ +  - ]:        102 :   if (src->priv->latency != -1)
     619                 :        102 :     min = src->priv->latency;
     620                 :            :   else
     621                 :          0 :     min = 0;
     622                 :            : 
     623         [ +  - ]:        102 :   if (min_latency)
     624                 :        102 :     *min_latency = min;
     625         [ +  - ]:        102 :   if (max_latency)
     626                 :        102 :     *max_latency = -1;
     627                 :            : 
     628 [ -  + ][ #  # ]:        102 :   GST_LOG_OBJECT (src, "latency: live %d, min %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
     629                 :            :       ", max %" GST_TIME_FORMAT, src->is_live, GST_TIME_ARGS (min),
     630                 :            :       GST_TIME_ARGS (-1));
     631                 :        102 :   GST_OBJECT_UNLOCK (src);
     632                 :            : 
     633                 :        102 :   return TRUE;
     634                 :            : }
     635                 :            : 
     636                 :            : /**
     637                 :            :  * gst_base_src_set_blocksize:
     638                 :            :  * @src: the source
     639                 :            :  * @blocksize: the new blocksize in bytes
     640                 :            :  *
     641                 :            :  * Set the number of bytes that @src will push out with each buffer. When
     642                 :            :  * @blocksize is set to -1, a default length will be used.
     643                 :            :  *
     644                 :            :  * Since: 0.10.22
     645                 :            :  */
     646                 :            : /* FIXME 0.11: blocksize property should be int, not ulong */
     647                 :            : void
     648                 :          1 : gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize)
     649                 :            : {
     650 [ -  + ][ +  - ]:          2 :   g_return_if_fail (GST_IS_BASE_SRC (src));
         [ -  + ][ -  + ]
     651                 :            : 
     652                 :          1 :   GST_OBJECT_LOCK (src);
     653                 :          1 :   src->blocksize = blocksize;
     654                 :          1 :   GST_OBJECT_UNLOCK (src);
     655                 :            : }
     656                 :            : 
     657                 :            : /**
     658                 :            :  * gst_base_src_get_blocksize:
     659                 :            :  * @src: the source
     660                 :            :  *
     661                 :            :  * Get the number of bytes that @src will push out with each buffer.
     662                 :            :  *
     663                 :            :  * Returns: the number of bytes pushed with each buffer.
     664                 :            :  *
     665                 :            :  * Since: 0.10.22
     666                 :            :  */
     667                 :            : /* FIXME 0.11: blocksize property should be int, not ulong */
     668                 :            : gulong
     669                 :          0 : gst_base_src_get_blocksize (GstBaseSrc * src)
     670                 :            : {
     671                 :            :   gulong res;
     672                 :            : 
     673 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_BASE_SRC (src), 0);
         [ #  # ][ #  # ]
     674                 :            : 
     675                 :          0 :   GST_OBJECT_LOCK (src);
     676                 :          0 :   res = src->blocksize;
     677                 :          0 :   GST_OBJECT_UNLOCK (src);
     678                 :            : 
     679                 :          0 :   return res;
     680                 :            : }
     681                 :            : 
     682                 :            : 
     683                 :            : /**
     684                 :            :  * gst_base_src_set_do_timestamp:
     685                 :            :  * @src: the source
     686                 :            :  * @timestamp: enable or disable timestamping
     687                 :            :  *
     688                 :            :  * Configure @src to automatically timestamp outgoing buffers based on the
     689                 :            :  * current running_time of the pipeline. This property is mostly useful for live
     690                 :            :  * sources.
     691                 :            :  *
     692                 :            :  * Since: 0.10.15
     693                 :            :  */
     694                 :            : void
     695                 :          0 : gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
     696                 :            : {
     697 [ #  # ][ #  # ]:          0 :   g_return_if_fail (GST_IS_BASE_SRC (src));
         [ #  # ][ #  # ]
     698                 :            : 
     699                 :          0 :   GST_OBJECT_LOCK (src);
     700                 :          0 :   src->priv->do_timestamp = timestamp;
     701                 :          0 :   GST_OBJECT_UNLOCK (src);
     702                 :            : }
     703                 :            : 
     704                 :            : /**
     705                 :            :  * gst_base_src_get_do_timestamp:
     706                 :            :  * @src: the source
     707                 :            :  *
     708                 :            :  * Query if @src timestamps outgoing buffers based on the current running_time.
     709                 :            :  *
     710                 :            :  * Returns: %TRUE if the base class will automatically timestamp outgoing buffers.
     711                 :            :  *
     712                 :            :  * Since: 0.10.15
     713                 :            :  */
     714                 :            : gboolean
     715                 :          0 : gst_base_src_get_do_timestamp (GstBaseSrc * src)
     716                 :            : {
     717                 :            :   gboolean res;
     718                 :            : 
     719 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
         [ #  # ][ #  # ]
     720                 :            : 
     721                 :          0 :   GST_OBJECT_LOCK (src);
     722                 :          0 :   res = src->priv->do_timestamp;
     723                 :          0 :   GST_OBJECT_UNLOCK (src);
     724                 :            : 
     725                 :          0 :   return res;
     726                 :            : }
     727                 :            : 
     728                 :            : /**
     729                 :            :  * gst_base_src_new_seamless_segment:
     730                 :            :  * @src: The source
     731                 :            :  * @start: The new start value for the segment
     732                 :            :  * @stop: Stop value for the new segment
     733                 :            :  * @position: The position value for the new segent
     734                 :            :  *
     735                 :            :  * Prepare a new seamless segment for emission downstream. This function must
     736                 :            :  * only be called by derived sub-classes, and only from the create() function,
     737                 :            :  * as the stream-lock needs to be held.
     738                 :            :  *
     739                 :            :  * The format for the new segment will be the current format of the source, as
     740                 :            :  * configured with gst_base_src_set_format()
     741                 :            :  *
     742                 :            :  * Returns: %TRUE if preparation of the seamless segment succeeded.
     743                 :            :  *
     744                 :            :  * Since: 0.10.26
     745                 :            :  */
     746                 :            : gboolean
     747                 :          0 : gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
     748                 :            :     gint64 position)
     749                 :            : {
     750                 :          0 :   gboolean res = TRUE;
     751                 :            : 
     752 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (src,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     753                 :            :       "Starting new seamless segment. Start %" GST_TIME_FORMAT " stop %"
     754                 :            :       GST_TIME_FORMAT " position %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
     755                 :            :       GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
     756                 :            : 
     757                 :          0 :   GST_OBJECT_LOCK (src);
     758 [ #  # ][ #  # ]:          0 :   if (src->data.ABI.running && !src->priv->newsegment_pending) {
     759         [ #  # ]:          0 :     if (src->priv->close_segment)
     760                 :          0 :       gst_event_unref (src->priv->close_segment);
     761                 :          0 :     src->priv->close_segment =
     762                 :          0 :         gst_event_new_new_segment_full (TRUE,
     763                 :            :         src->segment.rate, src->segment.applied_rate, src->segment.format,
     764                 :            :         src->segment.start, src->segment.last_stop, src->segment.time);
     765                 :            :   }
     766                 :            : 
     767                 :          0 :   gst_segment_set_newsegment_full (&src->segment, FALSE, src->segment.rate,
     768                 :            :       src->segment.applied_rate, src->segment.format, start, stop, position);
     769                 :            : 
     770         [ #  # ]:          0 :   if (src->priv->start_segment)
     771                 :          0 :     gst_event_unref (src->priv->start_segment);
     772         [ #  # ]:          0 :   if (src->segment.rate >= 0.0) {
     773                 :            :     /* forward, we send data from last_stop to stop */
     774                 :          0 :     src->priv->start_segment =
     775                 :          0 :         gst_event_new_new_segment_full (FALSE,
     776                 :            :         src->segment.rate, src->segment.applied_rate, src->segment.format,
     777                 :            :         src->segment.last_stop, stop, src->segment.time);
     778                 :            :   } else {
     779                 :            :     /* reverse, we send data from last_stop to start */
     780                 :          0 :     src->priv->start_segment =
     781                 :          0 :         gst_event_new_new_segment_full (FALSE,
     782                 :            :         src->segment.rate, src->segment.applied_rate, src->segment.format,
     783                 :            :         src->segment.start, src->segment.last_stop, src->segment.time);
     784                 :            :   }
     785                 :          0 :   GST_OBJECT_UNLOCK (src);
     786                 :            : 
     787                 :          0 :   src->priv->discont = TRUE;
     788                 :          0 :   src->data.ABI.running = TRUE;
     789                 :            : 
     790                 :          0 :   return res;
     791                 :            : }
     792                 :            : 
     793                 :            : static gboolean
     794                 :          0 : gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
     795                 :            : {
     796                 :            :   GstBaseSrcClass *bclass;
     797                 :            :   GstBaseSrc *bsrc;
     798                 :          0 :   gboolean res = TRUE;
     799                 :            : 
     800                 :          0 :   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
     801                 :          0 :   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
     802                 :            : 
     803         [ #  # ]:          0 :   if (bclass->set_caps)
     804                 :          0 :     res = bclass->set_caps (bsrc, caps);
     805                 :            : 
     806                 :          0 :   return res;
     807                 :            : }
     808                 :            : 
     809                 :            : static GstCaps *
     810                 :        742 : gst_base_src_getcaps (GstPad * pad)
     811                 :            : {
     812                 :            :   GstBaseSrcClass *bclass;
     813                 :            :   GstBaseSrc *bsrc;
     814                 :        742 :   GstCaps *caps = NULL;
     815                 :            : 
     816                 :        742 :   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
     817                 :        742 :   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
     818         [ -  + ]:        742 :   if (bclass->get_caps)
     819                 :          0 :     caps = bclass->get_caps (bsrc);
     820                 :            : 
     821         [ +  - ]:        742 :   if (caps == NULL) {
     822                 :            :     GstPadTemplate *pad_template;
     823                 :            : 
     824                 :        742 :     pad_template =
     825                 :        742 :         gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
     826         [ +  - ]:        742 :     if (pad_template != NULL) {
     827                 :        742 :       caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
     828                 :            :     }
     829                 :            :   }
     830                 :        742 :   return caps;
     831                 :            : }
     832                 :            : 
     833                 :            : static void
     834                 :          0 : gst_base_src_fixate (GstPad * pad, GstCaps * caps)
     835                 :            : {
     836                 :            :   GstBaseSrcClass *bclass;
     837                 :            :   GstBaseSrc *bsrc;
     838                 :            : 
     839                 :          0 :   bsrc = GST_BASE_SRC (gst_pad_get_parent (pad));
     840                 :          0 :   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
     841                 :            : 
     842         [ #  # ]:          0 :   if (bclass->fixate)
     843                 :          0 :     bclass->fixate (bsrc, caps);
     844                 :            : 
     845                 :          0 :   gst_object_unref (bsrc);
     846                 :          0 : }
     847                 :            : 
     848                 :            : static gboolean
     849                 :        120 : gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
     850                 :            : {
     851                 :            :   gboolean res;
     852                 :            : 
     853   [ +  +  +  -  :        120 :   switch (GST_QUERY_TYPE (query)) {
          -  -  +  -  -  
                      - ]
     854                 :            :     case GST_QUERY_POSITION:
     855                 :            :     {
     856                 :            :       GstFormat format;
     857                 :            : 
     858                 :          6 :       gst_query_parse_position (query, &format, NULL);
     859                 :            : 
     860         [ -  + ]:          6 :       GST_DEBUG_OBJECT (src, "position query in format %s",
     861                 :            :           gst_format_get_name (format));
     862                 :            : 
     863         [ -  + ]:          6 :       switch (format) {
     864                 :            :         case GST_FORMAT_PERCENT:
     865                 :            :         {
     866                 :            :           gint64 percent;
     867                 :            :           gint64 position;
     868                 :            :           gint64 duration;
     869                 :            : 
     870                 :          0 :           GST_OBJECT_LOCK (src);
     871                 :          0 :           position = src->segment.last_stop;
     872                 :          0 :           duration = src->segment.duration;
     873                 :          0 :           GST_OBJECT_UNLOCK (src);
     874                 :            : 
     875 [ #  # ][ #  # ]:          0 :           if (position != -1 && duration != -1) {
     876         [ #  # ]:          0 :             if (position < duration)
     877                 :          0 :               percent = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, position,
     878                 :            :                   duration);
     879                 :            :             else
     880                 :          0 :               percent = GST_FORMAT_PERCENT_MAX;
     881                 :            :           } else
     882                 :          0 :             percent = -1;
     883                 :            : 
     884                 :          0 :           gst_query_set_position (query, GST_FORMAT_PERCENT, percent);
     885                 :          0 :           res = TRUE;
     886                 :          0 :           break;
     887                 :            :         }
     888                 :            :         default:
     889                 :            :         {
     890                 :            :           gint64 position;
     891                 :            :           GstFormat seg_format;
     892                 :            : 
     893                 :          6 :           GST_OBJECT_LOCK (src);
     894                 :          6 :           position =
     895                 :          6 :               gst_segment_to_stream_time (&src->segment, src->segment.format,
     896                 :            :               src->segment.last_stop);
     897                 :          6 :           seg_format = src->segment.format;
     898                 :          6 :           GST_OBJECT_UNLOCK (src);
     899                 :            : 
     900         [ +  - ]:          6 :           if (position != -1) {
     901                 :            :             /* convert to requested format */
     902                 :          6 :             res =
     903                 :          6 :                 gst_pad_query_convert (src->srcpad, seg_format,
     904                 :            :                 position, &format, &position);
     905                 :            :           } else
     906                 :          0 :             res = TRUE;
     907                 :            : 
     908                 :          6 :           gst_query_set_position (query, format, position);
     909                 :          6 :           break;
     910                 :            :         }
     911                 :            :       }
     912                 :          6 :       break;
     913                 :            :     }
     914                 :            :     case GST_QUERY_DURATION:
     915                 :            :     {
     916                 :            :       GstFormat format;
     917                 :            : 
     918                 :          8 :       gst_query_parse_duration (query, &format, NULL);
     919                 :            : 
     920         [ -  + ]:          8 :       GST_DEBUG_OBJECT (src, "duration query in format %s",
     921                 :            :           gst_format_get_name (format));
     922                 :            : 
     923         [ -  + ]:          8 :       switch (format) {
     924                 :            :         case GST_FORMAT_PERCENT:
     925                 :          0 :           gst_query_set_duration (query, GST_FORMAT_PERCENT,
     926                 :            :               GST_FORMAT_PERCENT_MAX);
     927                 :          0 :           res = TRUE;
     928                 :          0 :           break;
     929                 :            :         default:
     930                 :            :         {
     931                 :            :           gint64 duration;
     932                 :            :           GstFormat seg_format;
     933                 :            : 
     934                 :          8 :           GST_OBJECT_LOCK (src);
     935                 :            :           /* this is the duration as configured by the subclass. */
     936                 :          8 :           duration = src->segment.duration;
     937                 :          8 :           seg_format = src->segment.format;
     938                 :          8 :           GST_OBJECT_UNLOCK (src);
     939                 :            : 
     940         [ -  + ]:          8 :           GST_LOG_OBJECT (src, "duration %" G_GINT64_FORMAT ", format %s",
     941                 :            :               duration, gst_format_get_name (seg_format));
     942                 :            : 
     943         [ -  + ]:          8 :           if (duration != -1) {
     944                 :            :             /* convert to requested format, if this fails, we have a duration
     945                 :            :              * but we cannot answer the query, we must return FALSE. */
     946                 :          0 :             res =
     947                 :          0 :                 gst_pad_query_convert (src->srcpad, seg_format,
     948                 :            :                 duration, &format, &duration);
     949                 :            :           } else {
     950                 :            :             /* The subclass did not configure a duration, we assume that the
     951                 :            :              * media has an unknown duration then and we return TRUE to report
     952                 :            :              * this. Note that this is not the same as returning FALSE, which
     953                 :            :              * means that we cannot report the duration at all. */
     954                 :          8 :             res = TRUE;
     955                 :            :           }
     956                 :          8 :           gst_query_set_duration (query, format, duration);
     957                 :          8 :           break;
     958                 :            :         }
     959                 :            :       }
     960                 :          8 :       break;
     961                 :            :     }
     962                 :            : 
     963                 :            :     case GST_QUERY_SEEKING:
     964                 :            :     {
     965                 :            :       GstFormat format, seg_format;
     966                 :            :       gint64 duration;
     967                 :            : 
     968                 :          4 :       GST_OBJECT_LOCK (src);
     969                 :          4 :       duration = src->segment.duration;
     970                 :          4 :       seg_format = src->segment.format;
     971                 :          4 :       GST_OBJECT_UNLOCK (src);
     972                 :            : 
     973                 :          4 :       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
     974         [ +  - ]:          4 :       if (format == seg_format) {
     975                 :          4 :         gst_query_set_seeking (query, seg_format,
     976                 :            :             gst_base_src_seekable (src), 0, duration);
     977                 :          4 :         res = TRUE;
     978                 :            :       } else {
     979                 :            :         /* FIXME 0.11: return TRUE + seekable=FALSE for SEEKING query here */
     980                 :            :         /* Don't reply to the query to make up for demuxers which don't
     981                 :            :          * handle the SEEKING query yet. Players like Totem will fall back
     982                 :            :          * to the duration when the SEEKING query isn't answered. */
     983                 :          0 :         res = FALSE;
     984                 :            :       }
     985                 :          4 :       break;
     986                 :            :     }
     987                 :            :     case GST_QUERY_SEGMENT:
     988                 :            :     {
     989                 :            :       gint64 start, stop;
     990                 :            : 
     991                 :          0 :       GST_OBJECT_LOCK (src);
     992                 :            :       /* no end segment configured, current duration then */
     993         [ #  # ]:          0 :       if ((stop = src->segment.stop) == -1)
     994                 :          0 :         stop = src->segment.duration;
     995                 :          0 :       start = src->segment.start;
     996                 :            : 
     997                 :            :       /* adjust to stream time */
     998         [ #  # ]:          0 :       if (src->segment.time != -1) {
     999                 :          0 :         start -= src->segment.time;
    1000         [ #  # ]:          0 :         if (stop != -1)
    1001                 :          0 :           stop -= src->segment.time;
    1002                 :            :       }
    1003                 :            : 
    1004                 :          0 :       gst_query_set_segment (query, src->segment.rate, src->segment.format,
    1005                 :            :           start, stop);
    1006                 :          0 :       GST_OBJECT_UNLOCK (src);
    1007                 :          0 :       res = TRUE;
    1008                 :          0 :       break;
    1009                 :            :     }
    1010                 :            : 
    1011                 :            :     case GST_QUERY_FORMATS:
    1012                 :            :     {
    1013                 :          0 :       gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
    1014                 :            :           GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
    1015                 :          0 :       res = TRUE;
    1016                 :          0 :       break;
    1017                 :            :     }
    1018                 :            :     case GST_QUERY_CONVERT:
    1019                 :            :     {
    1020                 :            :       GstFormat src_fmt, dest_fmt;
    1021                 :            :       gint64 src_val, dest_val;
    1022                 :            : 
    1023                 :          0 :       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
    1024                 :            : 
    1025                 :            :       /* we can only convert between equal formats... */
    1026         [ #  # ]:          0 :       if (src_fmt == dest_fmt) {
    1027                 :          0 :         dest_val = src_val;
    1028                 :          0 :         res = TRUE;
    1029                 :            :       } else
    1030                 :          0 :         res = FALSE;
    1031                 :            : 
    1032                 :          0 :       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
    1033                 :          0 :       break;
    1034                 :            :     }
    1035                 :            :     case GST_QUERY_LATENCY:
    1036                 :            :     {
    1037                 :            :       GstClockTime min, max;
    1038                 :            :       gboolean live;
    1039                 :            : 
    1040                 :            :       /* Subclasses should override and implement something usefull */
    1041                 :        102 :       res = gst_base_src_query_latency (src, &live, &min, &max);
    1042                 :            : 
    1043 [ -  + ][ #  # ]:        102 :       GST_LOG_OBJECT (src, "report latency: live %d, min %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1044                 :            :           ", max %" GST_TIME_FORMAT, live, GST_TIME_ARGS (min),
    1045                 :            :           GST_TIME_ARGS (max));
    1046                 :            : 
    1047                 :        102 :       gst_query_set_latency (query, live, min, max);
    1048                 :        102 :       break;
    1049                 :            :     }
    1050                 :            :     case GST_QUERY_JITTER:
    1051                 :            :     case GST_QUERY_RATE:
    1052                 :          0 :       res = FALSE;
    1053                 :          0 :       break;
    1054                 :            :     case GST_QUERY_BUFFERING:
    1055                 :            :     {
    1056                 :            :       GstFormat format, seg_format;
    1057                 :            :       gint64 start, stop, estimated;
    1058                 :            : 
    1059                 :          0 :       gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL);
    1060                 :            : 
    1061         [ #  # ]:          0 :       GST_DEBUG_OBJECT (src, "buffering query in format %s",
    1062                 :            :           gst_format_get_name (format));
    1063                 :            : 
    1064                 :          0 :       GST_OBJECT_LOCK (src);
    1065         [ #  # ]:          0 :       if (src->random_access) {
    1066                 :          0 :         estimated = 0;
    1067                 :          0 :         start = 0;
    1068         [ #  # ]:          0 :         if (format == GST_FORMAT_PERCENT)
    1069                 :          0 :           stop = GST_FORMAT_PERCENT_MAX;
    1070                 :            :         else
    1071                 :          0 :           stop = src->segment.duration;
    1072                 :            :       } else {
    1073                 :          0 :         estimated = -1;
    1074                 :          0 :         start = -1;
    1075                 :          0 :         stop = -1;
    1076                 :            :       }
    1077                 :          0 :       seg_format = src->segment.format;
    1078                 :          0 :       GST_OBJECT_UNLOCK (src);
    1079                 :            : 
    1080                 :            :       /* convert to required format. When the conversion fails, we can't answer
    1081                 :            :        * the query. When the value is unknown, we can don't perform conversion
    1082                 :            :        * but report TRUE. */
    1083 [ #  # ][ #  # ]:          0 :       if (format != GST_FORMAT_PERCENT && stop != -1) {
    1084                 :          0 :         res = gst_pad_query_convert (src->srcpad, seg_format,
    1085                 :            :             stop, &format, &stop);
    1086                 :            :       } else {
    1087                 :          0 :         res = TRUE;
    1088                 :            :       }
    1089 [ #  # ][ #  # ]:          0 :       if (res && format != GST_FORMAT_PERCENT && start != -1)
                 [ #  # ]
    1090                 :          0 :         res = gst_pad_query_convert (src->srcpad, seg_format,
    1091                 :            :             start, &format, &start);
    1092                 :            : 
    1093                 :          0 :       gst_query_set_buffering_range (query, format, start, stop, estimated);
    1094                 :          0 :       break;
    1095                 :            :     }
    1096                 :            :     default:
    1097                 :          0 :       res = FALSE;
    1098                 :          0 :       break;
    1099                 :            :   }
    1100         [ -  + ]:        120 :   GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),
    1101                 :            :       res);
    1102                 :        120 :   return res;
    1103                 :            : }
    1104                 :            : 
    1105                 :            : static gboolean
    1106                 :        134 : gst_base_src_query (GstPad * pad, GstQuery * query)
    1107                 :            : {
    1108                 :            :   GstBaseSrc *src;
    1109                 :            :   GstBaseSrcClass *bclass;
    1110                 :        134 :   gboolean result = FALSE;
    1111                 :            : 
    1112                 :        134 :   src = GST_BASE_SRC (gst_pad_get_parent (pad));
    1113                 :            : 
    1114                 :        134 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    1115                 :            : 
    1116         [ +  - ]:        134 :   if (bclass->query)
    1117                 :        134 :     result = bclass->query (src, query);
    1118                 :            :   else
    1119                 :          0 :     result = gst_pad_query_default (pad, query);
    1120                 :            : 
    1121                 :        134 :   gst_object_unref (src);
    1122                 :            : 
    1123                 :        134 :   return result;
    1124                 :            : }
    1125                 :            : 
    1126                 :            : static gboolean
    1127                 :        397 : gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment)
    1128                 :            : {
    1129                 :        397 :   gboolean res = TRUE;
    1130                 :            : 
    1131                 :            :   /* update our offset if the start/stop position was updated */
    1132         [ +  - ]:        397 :   if (segment->format == GST_FORMAT_BYTES) {
    1133                 :        397 :     segment->time = segment->start;
    1134         [ #  # ]:          0 :   } else if (segment->start == 0) {
    1135                 :            :     /* seek to start, we can implement a default for this. */
    1136                 :          0 :     segment->time = 0;
    1137                 :            :   } else {
    1138                 :          0 :     res = FALSE;
    1139         [ #  # ]:          0 :     GST_INFO_OBJECT (src, "Can't do a default seek");
    1140                 :            :   }
    1141                 :            : 
    1142                 :        397 :   return res;
    1143                 :            : }
    1144                 :            : 
    1145                 :            : static gboolean
    1146                 :        407 : gst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment)
    1147                 :            : {
    1148                 :            :   GstBaseSrcClass *bclass;
    1149                 :        407 :   gboolean result = FALSE;
    1150                 :            : 
    1151                 :        407 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    1152                 :            : 
    1153         [ +  - ]:        407 :   if (bclass->do_seek)
    1154                 :        407 :     result = bclass->do_seek (src, segment);
    1155                 :            : 
    1156                 :        407 :   return result;
    1157                 :            : }
    1158                 :            : 
    1159                 :            : #define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))
    1160                 :            : 
    1161                 :            : static gboolean
    1162                 :          1 : gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
    1163                 :            :     GstSegment * segment)
    1164                 :            : {
    1165                 :            :   /* By default, we try one of 2 things:
    1166                 :            :    *   - For absolute seek positions, convert the requested position to our
    1167                 :            :    *     configured processing format and place it in the output segment \
    1168                 :            :    *   - For relative seek positions, convert our current (input) values to the
    1169                 :            :    *     seek format, adjust by the relative seek offset and then convert back to
    1170                 :            :    *     the processing format
    1171                 :            :    */
    1172                 :            :   GstSeekType cur_type, stop_type;
    1173                 :            :   gint64 cur, stop;
    1174                 :            :   GstSeekFlags flags;
    1175                 :            :   GstFormat seek_format, dest_format;
    1176                 :            :   gdouble rate;
    1177                 :            :   gboolean update;
    1178                 :          1 :   gboolean res = TRUE;
    1179                 :            : 
    1180                 :          1 :   gst_event_parse_seek (event, &rate, &seek_format, &flags,
    1181                 :            :       &cur_type, &cur, &stop_type, &stop);
    1182                 :          1 :   dest_format = segment->format;
    1183                 :            : 
    1184         [ -  + ]:          1 :   if (seek_format == dest_format) {
    1185                 :          0 :     gst_segment_set_seek (segment, rate, seek_format, flags,
    1186                 :            :         cur_type, cur, stop_type, stop, &update);
    1187                 :          0 :     return TRUE;
    1188                 :            :   }
    1189                 :            : 
    1190         [ -  + ]:          1 :   if (cur_type != GST_SEEK_TYPE_NONE) {
    1191                 :            :     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
    1192                 :          0 :     res =
    1193                 :          0 :         gst_pad_query_convert (src->srcpad, seek_format, cur, &dest_format,
    1194                 :            :         &cur);
    1195                 :          0 :     cur_type = GST_SEEK_TYPE_SET;
    1196                 :            :   }
    1197                 :            : 
    1198 [ +  - ][ -  + ]:          1 :   if (res && stop_type != GST_SEEK_TYPE_NONE) {
    1199                 :            :     /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
    1200                 :          0 :     res =
    1201                 :          0 :         gst_pad_query_convert (src->srcpad, seek_format, stop, &dest_format,
    1202                 :            :         &stop);
    1203                 :          0 :     stop_type = GST_SEEK_TYPE_SET;
    1204                 :            :   }
    1205                 :            : 
    1206                 :            :   /* And finally, configure our output segment in the desired format */
    1207                 :          1 :   gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,
    1208                 :            :       stop_type, stop, &update);
    1209                 :            : 
    1210         [ -  + ]:          1 :   if (!res)
    1211                 :          0 :     goto no_format;
    1212                 :            : 
    1213                 :          1 :   return res;
    1214                 :            : 
    1215                 :            : no_format:
    1216                 :            :   {
    1217         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "undefined format given, seek aborted.");
    1218                 :          1 :     return FALSE;
    1219                 :            :   }
    1220                 :            : }
    1221                 :            : 
    1222                 :            : static gboolean
    1223                 :          1 : gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
    1224                 :            :     GstSegment * seeksegment)
    1225                 :            : {
    1226                 :            :   GstBaseSrcClass *bclass;
    1227                 :          1 :   gboolean result = FALSE;
    1228                 :            : 
    1229                 :          1 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    1230                 :            : 
    1231         [ +  - ]:          1 :   if (bclass->prepare_seek_segment)
    1232                 :          1 :     result = bclass->prepare_seek_segment (src, event, seeksegment);
    1233                 :            : 
    1234                 :          1 :   return result;
    1235                 :            : }
    1236                 :            : 
    1237                 :            : /* this code implements the seeking. It is a good example
    1238                 :            :  * handling all cases.
    1239                 :            :  *
    1240                 :            :  * A seek updates the currently configured segment.start
    1241                 :            :  * and segment.stop values based on the SEEK_TYPE. If the
    1242                 :            :  * segment.start value is updated, a seek to this new position
    1243                 :            :  * should be performed.
    1244                 :            :  *
    1245                 :            :  * The seek can only be executed when we are not currently
    1246                 :            :  * streaming any data, to make sure that this is the case, we
    1247                 :            :  * acquire the STREAM_LOCK which is taken when we are in the
    1248                 :            :  * _loop() function or when a getrange() is called. Normally
    1249                 :            :  * we will not receive a seek if we are operating in pull mode
    1250                 :            :  * though. When we operate as a live source we might block on the live
    1251                 :            :  * cond, which does not release the STREAM_LOCK. Therefore we will try
    1252                 :            :  * to grab the LIVE_LOCK instead of the STREAM_LOCK to make sure it is
    1253                 :            :  * safe to perform the seek.
    1254                 :            :  *
    1255                 :            :  * When we are in the loop() function, we might be in the middle
    1256                 :            :  * of pushing a buffer, which might block in a sink. To make sure
    1257                 :            :  * that the push gets unblocked we push out a FLUSH_START event.
    1258                 :            :  * Our loop function will get a WRONG_STATE return value from
    1259                 :            :  * the push and will pause, effectively releasing the STREAM_LOCK.
    1260                 :            :  *
    1261                 :            :  * For a non-flushing seek, we pause the task, which might eventually
    1262                 :            :  * release the STREAM_LOCK. We say eventually because when the sink
    1263                 :            :  * blocks on the sample we might wait a very long time until the sink
    1264                 :            :  * unblocks the sample. In any case we acquire the STREAM_LOCK and
    1265                 :            :  * can continue the seek. A non-flushing seek is normally done in a
    1266                 :            :  * running pipeline to perform seamless playback, this means that the sink is
    1267                 :            :  * PLAYING and will return from its chain function.
    1268                 :            :  * In the case of a non-flushing seek we need to make sure that the
    1269                 :            :  * data we output after the seek is continuous with the previous data,
    1270                 :            :  * this is because a non-flushing seek does not reset the running-time
    1271                 :            :  * to 0. We do this by closing the currently running segment, ie. sending
    1272                 :            :  * a new_segment event with the stop position set to the last processed
    1273                 :            :  * position.
    1274                 :            :  *
    1275                 :            :  * After updating the segment.start/stop values, we prepare for
    1276                 :            :  * streaming again. We push out a FLUSH_STOP to make the peer pad
    1277                 :            :  * accept data again and we start our task again.
    1278                 :            :  *
    1279                 :            :  * A segment seek posts a message on the bus saying that the playback
    1280                 :            :  * of the segment started. We store the segment flag internally because
    1281                 :            :  * when we reach the segment.stop we have to post a segment.done
    1282                 :            :  * instead of EOS when doing a segment seek.
    1283                 :            :  */
    1284                 :            : /* FIXME (0.11), we have the unlock gboolean here because most current
    1285                 :            :  * implementations (fdsrc, -base/gst/tcp/, ...) unconditionally unlock, even when
    1286                 :            :  * the streaming thread isn't running, resulting in bogus unlocks later when it
    1287                 :            :  * starts. This is fixed by adding unlock_stop, but we should still avoid unlocking
    1288                 :            :  * unnecessarily for backwards compatibility. Ergo, the unlock variable stays
    1289                 :            :  * until 0.11
    1290                 :            :  */
    1291                 :            : static gboolean
    1292                 :        407 : gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
    1293                 :            : {
    1294                 :        407 :   gboolean res = TRUE, tres;
    1295                 :            :   gdouble rate;
    1296                 :            :   GstFormat seek_format, dest_format;
    1297                 :            :   GstSeekFlags flags;
    1298                 :            :   GstSeekType cur_type, stop_type;
    1299                 :            :   gint64 cur, stop;
    1300                 :            :   gboolean flush, playing;
    1301                 :            :   gboolean update;
    1302                 :        407 :   gboolean relative_seek = FALSE;
    1303                 :        407 :   gboolean seekseg_configured = FALSE;
    1304                 :            :   GstSegment seeksegment;
    1305                 :            :   guint32 seqnum;
    1306                 :            :   GstEvent *tevent;
    1307                 :            : 
    1308         [ -  + ]:        407 :   GST_DEBUG_OBJECT (src, "doing seek: %" GST_PTR_FORMAT, event);
    1309                 :            : 
    1310                 :        407 :   GST_OBJECT_LOCK (src);
    1311                 :        407 :   dest_format = src->segment.format;
    1312                 :        407 :   GST_OBJECT_UNLOCK (src);
    1313                 :            : 
    1314         [ +  + ]:        407 :   if (event) {
    1315                 :          4 :     gst_event_parse_seek (event, &rate, &seek_format, &flags,
    1316                 :            :         &cur_type, &cur, &stop_type, &stop);
    1317                 :            : 
    1318 [ +  + ][ +  - ]:          7 :     relative_seek = SEEK_TYPE_IS_RELATIVE (cur_type) ||
                 [ +  + ]
    1319         [ -  + ]:          3 :         SEEK_TYPE_IS_RELATIVE (stop_type);
    1320                 :            : 
    1321 [ +  + ][ +  - ]:          4 :     if (dest_format != seek_format && !relative_seek) {
    1322                 :            :       /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it
    1323                 :            :        * here before taking the stream lock, otherwise we must convert it later,
    1324                 :            :        * once we have the stream lock and can read the last configures segment
    1325                 :            :        * start and stop positions */
    1326                 :          1 :       gst_segment_init (&seeksegment, dest_format);
    1327                 :            : 
    1328         [ -  + ]:          1 :       if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment))
    1329                 :          0 :         goto prepare_failed;
    1330                 :            : 
    1331                 :          1 :       seekseg_configured = TRUE;
    1332                 :            :     }
    1333                 :            : 
    1334                 :          4 :     flush = flags & GST_SEEK_FLAG_FLUSH;
    1335                 :          4 :     seqnum = gst_event_get_seqnum (event);
    1336                 :            :   } else {
    1337                 :        403 :     flush = FALSE;
    1338                 :            :     /* get next seqnum */
    1339                 :        403 :     seqnum = gst_util_seqnum_next ();
    1340                 :            :   }
    1341                 :            : 
    1342                 :            :   /* send flush start */
    1343         [ +  + ]:        407 :   if (flush) {
    1344                 :          2 :     tevent = gst_event_new_flush_start ();
    1345                 :          2 :     gst_event_set_seqnum (tevent, seqnum);
    1346                 :          2 :     gst_pad_push_event (src->srcpad, tevent);
    1347                 :            :   } else
    1348                 :        405 :     gst_pad_pause_task (src->srcpad);
    1349                 :            : 
    1350                 :            :   /* unblock streaming thread. */
    1351                 :        407 :   gst_base_src_set_flushing (src, TRUE, FALSE, unlock, &playing);
    1352                 :            : 
    1353                 :            :   /* grab streaming lock, this should eventually be possible, either
    1354                 :            :    * because the task is paused, our streaming thread stopped
    1355                 :            :    * or because our peer is flushing. */
    1356                 :        407 :   GST_PAD_STREAM_LOCK (src->srcpad);
    1357         [ -  + ]:        407 :   if (G_UNLIKELY (src->priv->seqnum == seqnum)) {
    1358                 :            :     /* we have seen this event before, issue a warning for now */
    1359         [ #  # ]:          0 :     GST_WARNING_OBJECT (src, "duplicate event found %" G_GUINT32_FORMAT,
    1360                 :            :         seqnum);
    1361                 :            :   } else {
    1362                 :        407 :     src->priv->seqnum = seqnum;
    1363         [ -  + ]:        407 :     GST_DEBUG_OBJECT (src, "seek with seqnum %" G_GUINT32_FORMAT, seqnum);
    1364                 :            :   }
    1365                 :            : 
    1366                 :        407 :   gst_base_src_set_flushing (src, FALSE, playing, unlock, NULL);
    1367                 :            : 
    1368                 :            :   /* If we configured the seeksegment above, don't overwrite it now. Otherwise
    1369                 :            :    * copy the current segment info into the temp segment that we can actually
    1370                 :            :    * attempt the seek with. We only update the real segment if the seek suceeds. */
    1371         [ +  + ]:        407 :   if (!seekseg_configured) {
    1372                 :        406 :     memcpy (&seeksegment, &src->segment, sizeof (GstSegment));
    1373                 :            : 
    1374                 :            :     /* now configure the final seek segment */
    1375         [ +  + ]:        406 :     if (event) {
    1376         [ -  + ]:          3 :       if (seeksegment.format != seek_format) {
    1377                 :            :         /* OK, here's where we give the subclass a chance to convert the relative
    1378                 :            :          * seek into an absolute one in the processing format. We set up any
    1379                 :            :          * absolute seek above, before taking the stream lock. */
    1380         [ #  # ]:          0 :         if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) {
    1381         [ #  # ]:          0 :           GST_DEBUG_OBJECT (src, "Preparing the seek failed after flushing. "
    1382                 :            :               "Aborting seek");
    1383                 :          0 :           res = FALSE;
    1384                 :            :         }
    1385                 :            :       } else {
    1386                 :            :         /* The seek format matches our processing format, no need to ask the
    1387                 :            :          * the subclass to configure the segment. */
    1388                 :          3 :         gst_segment_set_seek (&seeksegment, rate, seek_format, flags,
    1389                 :            :             cur_type, cur, stop_type, stop, &update);
    1390                 :            :       }
    1391                 :            :     }
    1392                 :            :     /* Else, no seek event passed, so we're just (re)starting the
    1393                 :            :        current segment. */
    1394                 :            :   }
    1395                 :            : 
    1396         [ +  - ]:        407 :   if (res) {
    1397         [ -  + ]:        407 :     GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
    1398                 :            :         " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
    1399                 :            :         seeksegment.start, seeksegment.stop, seeksegment.last_stop);
    1400                 :            : 
    1401                 :            :     /* do the seek, segment.last_stop contains the new position. */
    1402                 :        407 :     res = gst_base_src_do_seek (src, &seeksegment);
    1403                 :            :   }
    1404                 :            : 
    1405                 :            :   /* and prepare to continue streaming */
    1406         [ +  + ]:        407 :   if (flush) {
    1407                 :          2 :     tevent = gst_event_new_flush_stop ();
    1408                 :          2 :     gst_event_set_seqnum (tevent, seqnum);
    1409                 :            :     /* send flush stop, peer will accept data and events again. We
    1410                 :            :      * are not yet providing data as we still have the STREAM_LOCK. */
    1411                 :          2 :     gst_pad_push_event (src->srcpad, tevent);
    1412 [ +  - ][ +  + ]:        405 :   } else if (res && src->data.ABI.running) {
    1413                 :            :     /* we are running the current segment and doing a non-flushing seek,
    1414                 :            :      * close the segment first based on the last_stop. */
    1415         [ -  + ]:          1 :     GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT
    1416                 :            :         " to %" G_GINT64_FORMAT, src->segment.start, src->segment.last_stop);
    1417                 :            : 
    1418                 :            :     /* queue the segment for sending in the stream thread */
    1419         [ -  + ]:          1 :     if (src->priv->close_segment)
    1420                 :          0 :       gst_event_unref (src->priv->close_segment);
    1421                 :          2 :     src->priv->close_segment =
    1422                 :          1 :         gst_event_new_new_segment_full (TRUE,
    1423                 :            :         src->segment.rate, src->segment.applied_rate, src->segment.format,
    1424                 :            :         src->segment.start, src->segment.last_stop, src->segment.time);
    1425                 :          1 :     gst_event_set_seqnum (src->priv->close_segment, seqnum);
    1426                 :            :   }
    1427                 :            : 
    1428                 :            :   /* The subclass must have converted the segment to the processing format
    1429                 :            :    * by now */
    1430 [ +  - ][ -  + ]:        407 :   if (res && seeksegment.format != dest_format) {
    1431         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "Subclass failed to prepare a seek segment "
    1432                 :            :         "in the correct format. Aborting seek.");
    1433                 :          0 :     res = FALSE;
    1434                 :            :   }
    1435                 :            : 
    1436                 :            :   /* if the seek was successful, we update our real segment and push
    1437                 :            :    * out the new segment. */
    1438         [ +  - ]:        407 :   if (res) {
    1439                 :        407 :     GST_OBJECT_LOCK (src);
    1440                 :        407 :     memcpy (&src->segment, &seeksegment, sizeof (GstSegment));
    1441                 :        407 :     GST_OBJECT_UNLOCK (src);
    1442                 :            : 
    1443         [ -  + ]:        407 :     if (seeksegment.flags & GST_SEEK_FLAG_SEGMENT) {
    1444                 :            :       GstMessage *message;
    1445                 :            : 
    1446                 :          0 :       message = gst_message_new_segment_start (GST_OBJECT (src),
    1447                 :            :           seeksegment.format, seeksegment.last_stop);
    1448                 :          0 :       gst_message_set_seqnum (message, seqnum);
    1449                 :            : 
    1450                 :          0 :       gst_element_post_message (GST_ELEMENT (src), message);
    1451                 :            :     }
    1452                 :            : 
    1453                 :            :     /* for deriving a stop position for the playback segment from the seek
    1454                 :            :      * segment, we must take the duration when the stop is not set */
    1455         [ +  - ]:        407 :     if ((stop = seeksegment.stop) == -1)
    1456                 :        407 :       stop = seeksegment.duration;
    1457                 :            : 
    1458         [ -  + ]:        407 :     GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
    1459                 :            :         " to %" G_GINT64_FORMAT, seeksegment.start, stop);
    1460                 :            : 
    1461                 :            :     /* now replace the old segment so that we send it in the stream thread the
    1462                 :            :      * next time it is scheduled. */
    1463         [ -  + ]:        407 :     if (src->priv->start_segment)
    1464                 :          0 :       gst_event_unref (src->priv->start_segment);
    1465         [ +  + ]:        407 :     if (seeksegment.rate >= 0.0) {
    1466                 :            :       /* forward, we send data from last_stop to stop */
    1467                 :        406 :       src->priv->start_segment =
    1468                 :        406 :           gst_event_new_new_segment_full (FALSE,
    1469                 :            :           seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
    1470                 :            :           seeksegment.last_stop, stop, seeksegment.time);
    1471                 :            :     } else {
    1472                 :            :       /* reverse, we send data from last_stop to start */
    1473                 :          1 :       src->priv->start_segment =
    1474                 :          1 :           gst_event_new_new_segment_full (FALSE,
    1475                 :            :           seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
    1476                 :            :           seeksegment.start, seeksegment.last_stop, seeksegment.time);
    1477                 :            :     }
    1478                 :        407 :     gst_event_set_seqnum (src->priv->start_segment, seqnum);
    1479                 :        407 :     src->priv->newsegment_pending = TRUE;
    1480                 :            :   }
    1481                 :            : 
    1482                 :        407 :   src->priv->discont = TRUE;
    1483                 :        407 :   src->data.ABI.running = TRUE;
    1484                 :            :   /* and restart the task in case it got paused explicitly or by
    1485                 :            :    * the FLUSH_START event we pushed out. */
    1486                 :        407 :   tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
    1487                 :        407 :       src->srcpad);
    1488 [ +  - ][ -  + ]:        407 :   if (res && !tres)
    1489                 :          0 :     res = FALSE;
    1490                 :            : 
    1491                 :            :   /* and release the lock again so we can continue streaming */
    1492                 :        407 :   GST_PAD_STREAM_UNLOCK (src->srcpad);
    1493                 :            : 
    1494                 :        407 :   return res;
    1495                 :            : 
    1496                 :            :   /* ERROR */
    1497                 :            : prepare_failed:
    1498         [ #  # ]:          0 :   GST_DEBUG_OBJECT (src, "Preparing the seek failed before flushing. "
    1499                 :            :       "Aborting seek");
    1500                 :        407 :   return FALSE;
    1501                 :            : }
    1502                 :            : 
    1503                 :            : static const GstQueryType *
    1504                 :          0 : gst_base_src_get_query_types (GstElement * element)
    1505                 :            : {
    1506                 :            :   static const GstQueryType query_types[] = {
    1507                 :            :     GST_QUERY_DURATION,
    1508                 :            :     GST_QUERY_POSITION,
    1509                 :            :     GST_QUERY_SEEKING,
    1510                 :            :     GST_QUERY_SEGMENT,
    1511                 :            :     GST_QUERY_FORMATS,
    1512                 :            :     GST_QUERY_LATENCY,
    1513                 :            :     GST_QUERY_JITTER,
    1514                 :            :     GST_QUERY_RATE,
    1515                 :            :     GST_QUERY_CONVERT,
    1516                 :            :     0
    1517                 :            :   };
    1518                 :            : 
    1519                 :          0 :   return query_types;
    1520                 :            : }
    1521                 :            : 
    1522                 :            : /* all events send to this element directly. This is mainly done from the
    1523                 :            :  * application.
    1524                 :            :  */
    1525                 :            : static gboolean
    1526                 :          4 : gst_base_src_send_event (GstElement * element, GstEvent * event)
    1527                 :            : {
    1528                 :            :   GstBaseSrc *src;
    1529                 :          4 :   gboolean result = FALSE;
    1530                 :            : 
    1531                 :          4 :   src = GST_BASE_SRC (element);
    1532                 :            : 
    1533         [ -  + ]:          4 :   GST_DEBUG_OBJECT (src, "handling event %p %" GST_PTR_FORMAT, event, event);
    1534                 :            : 
    1535   [ -  +  -  -  :          4 :   switch (GST_EVENT_TYPE (event)) {
          -  -  +  -  -  
             -  -  -  - ]
    1536                 :            :       /* bidirectional events */
    1537                 :            :     case GST_EVENT_FLUSH_START:
    1538                 :            :     case GST_EVENT_FLUSH_STOP:
    1539                 :            :       /* sending random flushes downstream can break stuff,
    1540                 :            :        * especially sync since all segment info will get flushed */
    1541                 :          0 :       break;
    1542                 :            : 
    1543                 :            :       /* downstream serialized events */
    1544                 :            :     case GST_EVENT_EOS:
    1545                 :            :     {
    1546                 :            :       GstBaseSrcClass *bclass;
    1547                 :            : 
    1548                 :          2 :       bclass = GST_BASE_SRC_GET_CLASS (src);
    1549                 :            : 
    1550                 :            :       /* queue EOS and make sure the task or pull function performs the EOS
    1551                 :            :        * actions.
    1552                 :            :        *
    1553                 :            :        * We have two possibilities:
    1554                 :            :        *
    1555                 :            :        *  - Before we are to enter the _create function, we check the pending_eos
    1556                 :            :        *    first and do EOS instead of entering it.
    1557                 :            :        *  - If we are in the _create function or we did not manage to set the
    1558                 :            :        *    flag fast enough and we are about to enter the _create function,
    1559                 :            :        *    we unlock it so that we exit with WRONG_STATE immediatly. We then
    1560                 :            :        *    check the EOS flag and do the EOS logic.
    1561                 :            :        */
    1562                 :          2 :       g_atomic_int_set (&src->priv->pending_eos, TRUE);
    1563         [ -  + ]:          2 :       GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
    1564                 :            : 
    1565                 :            :       /* unlock the _create function so that we can check the pending_eos flag
    1566                 :            :        * and we can do EOS. This will eventually release the LIVE_LOCK again so
    1567                 :            :        * that we can grab it and stop the unlock again. We don't take the stream
    1568                 :            :        * lock so that this operation is guaranteed to never block. */
    1569         [ -  + ]:          2 :       if (bclass->unlock)
    1570                 :          0 :         bclass->unlock (src);
    1571                 :            : 
    1572         [ -  + ]:          2 :       GST_DEBUG_OBJECT (src, "unlock called, waiting for LIVE_LOCK");
    1573                 :            : 
    1574                 :          2 :       GST_LIVE_LOCK (src);
    1575         [ -  + ]:          2 :       GST_DEBUG_OBJECT (src, "LIVE_LOCK acquired, calling unlock_stop");
    1576                 :            :       /* now stop the unlock of the streaming thread again. Grabbing the live
    1577                 :            :        * lock is enough because that protects the create function. */
    1578         [ -  + ]:          2 :       if (bclass->unlock_stop)
    1579                 :          0 :         bclass->unlock_stop (src);
    1580                 :          2 :       GST_LIVE_UNLOCK (src);
    1581                 :            : 
    1582                 :          2 :       result = TRUE;
    1583                 :          2 :       break;
    1584                 :            :     }
    1585                 :            :     case GST_EVENT_NEWSEGMENT:
    1586                 :            :       /* sending random NEWSEGMENT downstream can break sync. */
    1587                 :          0 :       break;
    1588                 :            :     case GST_EVENT_TAG:
    1589                 :            :       /* Insert tag in the dataflow */
    1590                 :          0 :       GST_OBJECT_LOCK (src);
    1591                 :          0 :       src->priv->pending_tags = g_list_append (src->priv->pending_tags, event);
    1592                 :          0 :       g_atomic_int_set (&src->priv->have_tags, TRUE);
    1593                 :          0 :       GST_OBJECT_UNLOCK (src);
    1594                 :          0 :       event = NULL;
    1595                 :          0 :       result = TRUE;
    1596                 :          0 :       break;
    1597                 :            :     case GST_EVENT_BUFFERSIZE:
    1598                 :            :       /* does not seem to make much sense currently */
    1599                 :          0 :       break;
    1600                 :            : 
    1601                 :            :       /* upstream events */
    1602                 :            :     case GST_EVENT_QOS:
    1603                 :            :       /* elements should override send_event and do something */
    1604                 :          0 :       break;
    1605                 :            :     case GST_EVENT_SEEK:
    1606                 :            :     {
    1607                 :            :       gboolean started;
    1608                 :            : 
    1609                 :          2 :       GST_OBJECT_LOCK (src->srcpad);
    1610         [ -  + ]:          2 :       if (GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PULL)
    1611                 :          0 :         goto wrong_mode;
    1612                 :          2 :       started = GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PUSH;
    1613                 :          2 :       GST_OBJECT_UNLOCK (src->srcpad);
    1614                 :            : 
    1615         [ +  + ]:          2 :       if (started) {
    1616         [ -  + ]:          1 :         GST_DEBUG_OBJECT (src, "performing seek");
    1617                 :            :         /* when we are running in push mode, we can execute the
    1618                 :            :          * seek right now, we need to unlock. */
    1619                 :          1 :         result = gst_base_src_perform_seek (src, event, TRUE);
    1620                 :            :       } else {
    1621                 :            :         GstEvent **event_p;
    1622                 :            : 
    1623                 :            :         /* else we store the event and execute the seek when we
    1624                 :            :          * get activated */
    1625                 :          1 :         GST_OBJECT_LOCK (src);
    1626         [ -  + ]:          1 :         GST_DEBUG_OBJECT (src, "queueing seek");
    1627                 :          1 :         event_p = &src->data.ABI.pending_seek;
    1628                 :          1 :         gst_event_replace ((GstEvent **) event_p, event);
    1629                 :          1 :         GST_OBJECT_UNLOCK (src);
    1630                 :            :         /* assume the seek will work */
    1631                 :          1 :         result = TRUE;
    1632                 :            :       }
    1633                 :          2 :       break;
    1634                 :            :     }
    1635                 :            :     case GST_EVENT_NAVIGATION:
    1636                 :            :       /* could make sense for elements that do something with navigation events
    1637                 :            :        * but then they would need to override the send_event function */
    1638                 :          0 :       break;
    1639                 :            :     case GST_EVENT_LATENCY:
    1640                 :            :       /* does not seem to make sense currently */
    1641                 :          0 :       break;
    1642                 :            : 
    1643                 :            :       /* custom events */
    1644                 :            :     case GST_EVENT_CUSTOM_UPSTREAM:
    1645                 :            :       /* override send_event if you want this */
    1646                 :          0 :       break;
    1647                 :            :     case GST_EVENT_CUSTOM_DOWNSTREAM:
    1648                 :            :     case GST_EVENT_CUSTOM_BOTH:
    1649                 :            :       /* FIXME, insert event in the dataflow */
    1650                 :          0 :       break;
    1651                 :            :     case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
    1652                 :            :     case GST_EVENT_CUSTOM_BOTH_OOB:
    1653                 :            :       /* insert a random custom event into the pipeline */
    1654         [ #  # ]:          0 :       GST_DEBUG_OBJECT (src, "pushing custom OOB event downstream");
    1655                 :          0 :       result = gst_pad_push_event (src->srcpad, event);
    1656                 :            :       /* we gave away the ref to the event in the push */
    1657                 :          0 :       event = NULL;
    1658                 :          0 :       break;
    1659                 :            :     default:
    1660                 :          0 :       break;
    1661                 :            :   }
    1662                 :            : done:
    1663                 :            :   /* if we still have a ref to the event, unref it now */
    1664         [ +  - ]:          4 :   if (event)
    1665                 :          4 :     gst_event_unref (event);
    1666                 :            : 
    1667                 :          4 :   return result;
    1668                 :            : 
    1669                 :            :   /* ERRORS */
    1670                 :            : wrong_mode:
    1671                 :            :   {
    1672         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "cannot perform seek when operating in pull mode");
    1673                 :          0 :     GST_OBJECT_UNLOCK (src->srcpad);
    1674                 :          0 :     result = FALSE;
    1675                 :          0 :     goto done;
    1676                 :            :   }
    1677                 :            : }
    1678                 :            : 
    1679                 :            : static gboolean
    1680                 :        423 : gst_base_src_seekable (GstBaseSrc * src)
    1681                 :            : {
    1682                 :            :   GstBaseSrcClass *bclass;
    1683                 :        423 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    1684         [ +  + ]:        423 :   if (bclass->is_seekable)
    1685                 :        413 :     return bclass->is_seekable (src);
    1686                 :            :   else
    1687                 :        423 :     return FALSE;
    1688                 :            : }
    1689                 :            : 
    1690                 :            : static void
    1691                 :          0 : gst_base_src_update_qos (GstBaseSrc * src,
    1692                 :            :     gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
    1693                 :            : {
    1694 [ #  # ][ #  # ]:          0 :   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, src,
         [ #  # ][ #  # ]
                 [ #  # ]
    1695                 :            :       "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
    1696                 :            :       GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
    1697                 :            : 
    1698                 :          0 :   GST_OBJECT_LOCK (src);
    1699                 :          0 :   src->priv->proportion = proportion;
    1700                 :          0 :   src->priv->earliest_time = timestamp + diff;
    1701                 :          0 :   GST_OBJECT_UNLOCK (src);
    1702                 :          0 : }
    1703                 :            : 
    1704                 :            : 
    1705                 :            : static gboolean
    1706                 :        107 : gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
    1707                 :            : {
    1708                 :            :   gboolean result;
    1709                 :            : 
    1710         [ -  + ]:        107 :   GST_DEBUG_OBJECT (src, "handle event %" GST_PTR_FORMAT, event);
    1711                 :            : 
    1712   [ +  -  -  -  :        107 :   switch (GST_EVENT_TYPE (event)) {
                      + ]
    1713                 :            :     case GST_EVENT_SEEK:
    1714                 :            :       /* is normally called when in push mode */
    1715         [ -  + ]:          2 :       if (!gst_base_src_seekable (src))
    1716                 :          0 :         goto not_seekable;
    1717                 :            : 
    1718                 :          2 :       result = gst_base_src_perform_seek (src, event, TRUE);
    1719                 :          2 :       break;
    1720                 :            :     case GST_EVENT_FLUSH_START:
    1721                 :            :       /* cancel any blocking getrange, is normally called
    1722                 :            :        * when in pull mode. */
    1723                 :          0 :       result = gst_base_src_set_flushing (src, TRUE, FALSE, TRUE, NULL);
    1724                 :          0 :       break;
    1725                 :            :     case GST_EVENT_FLUSH_STOP:
    1726                 :          0 :       result = gst_base_src_set_flushing (src, FALSE, TRUE, TRUE, NULL);
    1727                 :          0 :       break;
    1728                 :            :     case GST_EVENT_QOS:
    1729                 :            :     {
    1730                 :            :       gdouble proportion;
    1731                 :            :       GstClockTimeDiff diff;
    1732                 :            :       GstClockTime timestamp;
    1733                 :            : 
    1734                 :          0 :       gst_event_parse_qos (event, &proportion, &diff, &timestamp);
    1735                 :          0 :       gst_base_src_update_qos (src, proportion, diff, timestamp);
    1736                 :          0 :       result = TRUE;
    1737                 :          0 :       break;
    1738                 :            :     }
    1739                 :            :     default:
    1740                 :        105 :       result = TRUE;
    1741                 :        105 :       break;
    1742                 :            :   }
    1743                 :        107 :   return result;
    1744                 :            : 
    1745                 :            :   /* ERRORS */
    1746                 :            : not_seekable:
    1747                 :            :   {
    1748         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "is not seekable");
    1749                 :        107 :     return FALSE;
    1750                 :            :   }
    1751                 :            : }
    1752                 :            : 
    1753                 :            : static gboolean
    1754                 :        107 : gst_base_src_event_handler (GstPad * pad, GstEvent * event)
    1755                 :            : {
    1756                 :            :   GstBaseSrc *src;
    1757                 :            :   GstBaseSrcClass *bclass;
    1758                 :        107 :   gboolean result = FALSE;
    1759                 :            : 
    1760                 :        107 :   src = GST_BASE_SRC (gst_pad_get_parent (pad));
    1761                 :        107 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    1762                 :            : 
    1763         [ +  - ]:        107 :   if (bclass->event) {
    1764         [ -  + ]:        107 :     if (!(result = bclass->event (src, event)))
    1765                 :          0 :       goto subclass_failed;
    1766                 :            :   }
    1767                 :            : 
    1768                 :            : done:
    1769                 :        107 :   gst_event_unref (event);
    1770                 :        107 :   gst_object_unref (src);
    1771                 :            : 
    1772                 :        107 :   return result;
    1773                 :            : 
    1774                 :            :   /* ERRORS */
    1775                 :            : subclass_failed:
    1776                 :            :   {
    1777         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "subclass refused event");
    1778                 :          0 :     goto done;
    1779                 :            :   }
    1780                 :            : }
    1781                 :            : 
    1782                 :            : static void
    1783                 :         35 : gst_base_src_set_property (GObject * object, guint prop_id,
    1784                 :            :     const GValue * value, GParamSpec * pspec)
    1785                 :            : {
    1786                 :            :   GstBaseSrc *src;
    1787                 :            : 
    1788                 :         35 :   src = GST_BASE_SRC (object);
    1789                 :            : 
    1790   [ +  +  -  -  :         35 :   switch (prop_id) {
                      - ]
    1791                 :            :     case PROP_BLOCKSIZE:
    1792                 :          1 :       gst_base_src_set_blocksize (src, g_value_get_ulong (value));
    1793                 :          1 :       break;
    1794                 :            :     case PROP_NUM_BUFFERS:
    1795                 :         34 :       src->num_buffers = g_value_get_int (value);
    1796                 :         34 :       break;
    1797                 :            :     case PROP_TYPEFIND:
    1798                 :          0 :       src->data.ABI.typefind = g_value_get_boolean (value);
    1799                 :          0 :       break;
    1800                 :            :     case PROP_DO_TIMESTAMP:
    1801                 :          0 :       gst_base_src_set_do_timestamp (src, g_value_get_boolean (value));
    1802                 :          0 :       break;
    1803                 :            :     default:
    1804                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1805                 :          0 :       break;
    1806                 :            :   }
    1807                 :         35 : }
    1808                 :            : 
    1809                 :            : static void
    1810                 :          1 : gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
    1811                 :            :     GParamSpec * pspec)
    1812                 :            : {
    1813                 :            :   GstBaseSrc *src;
    1814                 :            : 
    1815                 :          1 :   src = GST_BASE_SRC (object);
    1816                 :            : 
    1817   [ -  +  -  -  :          1 :   switch (prop_id) {
                      - ]
    1818                 :            :     case PROP_BLOCKSIZE:
    1819                 :          0 :       g_value_set_ulong (value, gst_base_src_get_blocksize (src));
    1820                 :          0 :       break;
    1821                 :            :     case PROP_NUM_BUFFERS:
    1822                 :          1 :       g_value_set_int (value, src->num_buffers);
    1823                 :          1 :       break;
    1824                 :            :     case PROP_TYPEFIND:
    1825                 :          0 :       g_value_set_boolean (value, src->data.ABI.typefind);
    1826                 :          0 :       break;
    1827                 :            :     case PROP_DO_TIMESTAMP:
    1828                 :          0 :       g_value_set_boolean (value, gst_base_src_get_do_timestamp (src));
    1829                 :          0 :       break;
    1830                 :            :     default:
    1831                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1832                 :          0 :       break;
    1833                 :            :   }
    1834                 :          1 : }
    1835                 :            : 
    1836                 :            : /* with STREAM_LOCK and LOCK */
    1837                 :            : static GstClockReturn
    1838                 :          0 : gst_base_src_wait (GstBaseSrc * basesrc, GstClock * clock, GstClockTime time)
    1839                 :            : {
    1840                 :            :   GstClockReturn ret;
    1841                 :            :   GstClockID id;
    1842                 :            : 
    1843                 :          0 :   id = gst_clock_new_single_shot_id (clock, time);
    1844                 :            : 
    1845                 :          0 :   basesrc->clock_id = id;
    1846                 :            :   /* release the live lock while waiting */
    1847                 :          0 :   GST_LIVE_UNLOCK (basesrc);
    1848                 :            : 
    1849                 :          0 :   ret = gst_clock_id_wait (id, NULL);
    1850                 :            : 
    1851                 :          0 :   GST_LIVE_LOCK (basesrc);
    1852                 :          0 :   gst_clock_id_unref (id);
    1853                 :          0 :   basesrc->clock_id = NULL;
    1854                 :            : 
    1855                 :          0 :   return ret;
    1856                 :            : }
    1857                 :            : 
    1858                 :            : /* perform synchronisation on a buffer.
    1859                 :            :  * with STREAM_LOCK.
    1860                 :            :  */
    1861                 :            : static GstClockReturn
    1862                 :     686564 : gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
    1863                 :            : {
    1864                 :            :   GstClockReturn result;
    1865                 :            :   GstClockTime start, end;
    1866                 :            :   GstBaseSrcClass *bclass;
    1867                 :            :   GstClockTime base_time;
    1868                 :            :   GstClock *clock;
    1869                 :     686564 :   GstClockTime now = GST_CLOCK_TIME_NONE, timestamp;
    1870                 :            :   gboolean do_timestamp, first, pseudo_live;
    1871                 :            : 
    1872                 :     686564 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    1873                 :            : 
    1874                 :     686564 :   start = end = -1;
    1875         [ +  + ]:     686564 :   if (bclass->get_times)
    1876                 :     539213 :     bclass->get_times (basesrc, buffer, &start, &end);
    1877                 :            : 
    1878                 :            :   /* get buffer timestamp */
    1879                 :     686564 :   timestamp = GST_BUFFER_TIMESTAMP (buffer);
    1880                 :            : 
    1881                 :            :   /* grab the lock to prepare for clocking and calculate the startup
    1882                 :            :    * latency. */
    1883                 :     686564 :   GST_OBJECT_LOCK (basesrc);
    1884                 :            : 
    1885                 :            :   /* if we are asked to sync against the clock we are a pseudo live element */
    1886 [ -  + ][ #  # ]:     686553 :   pseudo_live = (start != -1 && basesrc->is_live);
    1887                 :            :   /* check for the first buffer */
    1888                 :     686553 :   first = (basesrc->priv->latency == -1);
    1889                 :            : 
    1890 [ +  + ][ -  + ]:     686553 :   if (timestamp != -1 && pseudo_live) {
    1891                 :            :     GstClockTime latency;
    1892                 :            : 
    1893                 :            :     /* we have a timestamp and a sync time, latency is the diff */
    1894         [ #  # ]:          0 :     if (timestamp <= start)
    1895                 :          0 :       latency = start - timestamp;
    1896                 :            :     else
    1897                 :          0 :       latency = 0;
    1898                 :            : 
    1899         [ #  # ]:          0 :     if (first) {
    1900 [ #  # ][ #  # ]:          0 :       GST_DEBUG_OBJECT (basesrc, "pseudo_live with latency %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1901                 :            :           GST_TIME_ARGS (latency));
    1902                 :            :       /* first time we calculate latency, just configure */
    1903                 :          0 :       basesrc->priv->latency = latency;
    1904                 :            :     } else {
    1905         [ #  # ]:          0 :       if (basesrc->priv->latency != latency) {
    1906                 :            :         /* we have a new latency, FIXME post latency message */
    1907                 :          0 :         basesrc->priv->latency = latency;
    1908 [ #  # ][ #  # ]:          0 :         GST_DEBUG_OBJECT (basesrc, "latency changed to %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1909                 :            :             GST_TIME_ARGS (latency));
    1910                 :            :       }
    1911                 :            :     }
    1912         [ +  + ]:     686553 :   } else if (first) {
    1913         [ -  + ]:          7 :     GST_DEBUG_OBJECT (basesrc, "no latency needed, live %d, sync %d",
    1914                 :            :         basesrc->is_live, start != -1);
    1915                 :          7 :     basesrc->priv->latency = 0;
    1916                 :            :   }
    1917                 :            : 
    1918                 :            :   /* get clock, if no clock, we can't sync or do timestamps */
    1919         [ +  + ]:     686553 :   if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
    1920                 :      83657 :     goto no_clock;
    1921                 :            : 
    1922                 :     602896 :   base_time = GST_ELEMENT_CAST (basesrc)->base_time;
    1923                 :            : 
    1924                 :     602896 :   do_timestamp = basesrc->priv->do_timestamp;
    1925                 :            : 
    1926                 :            :   /* first buffer, calculate the timestamp offset */
    1927         [ +  + ]:     602896 :   if (first) {
    1928                 :            :     GstClockTime running_time;
    1929                 :            : 
    1930                 :          7 :     now = gst_clock_get_time (clock);
    1931                 :          7 :     running_time = now - base_time;
    1932                 :            : 
    1933 [ -  + ][ #  # ]:          7 :     GST_LOG_OBJECT (basesrc,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1934                 :            :         "startup timestamp: %" GST_TIME_FORMAT ", running_time %"
    1935                 :            :         GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
    1936                 :            :         GST_TIME_ARGS (running_time));
    1937                 :            : 
    1938 [ -  + ][ #  # ]:          7 :     if (pseudo_live && timestamp != -1) {
    1939                 :            :       /* live source and we need to sync, add startup latency to all timestamps
    1940                 :            :        * to get the real running_time. Live sources should always timestamp
    1941                 :            :        * according to the current running time. */
    1942                 :          0 :       basesrc->priv->ts_offset = GST_CLOCK_DIFF (timestamp, running_time);
    1943                 :            : 
    1944 [ #  # ][ #  # ]:          0 :       GST_LOG_OBJECT (basesrc, "live with sync, ts_offset %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1945                 :            :           GST_TIME_ARGS (basesrc->priv->ts_offset));
    1946                 :            :     } else {
    1947                 :          7 :       basesrc->priv->ts_offset = 0;
    1948         [ -  + ]:          7 :       GST_LOG_OBJECT (basesrc, "no timestamp offset needed");
    1949                 :            :     }
    1950                 :            : 
    1951         [ -  + ]:          7 :     if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
    1952         [ #  # ]:          0 :       if (do_timestamp)
    1953                 :          0 :         timestamp = running_time;
    1954                 :            :       else
    1955                 :          0 :         timestamp = 0;
    1956                 :            : 
    1957                 :          0 :       GST_BUFFER_TIMESTAMP (buffer) = timestamp;
    1958                 :            : 
    1959 [ #  # ][ #  # ]:          0 :       GST_LOG_OBJECT (basesrc, "created timestamp: %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1960                 :            :           GST_TIME_ARGS (timestamp));
    1961                 :            :     }
    1962                 :            : 
    1963                 :            :     /* add the timestamp offset we need for sync */
    1964                 :          7 :     timestamp += basesrc->priv->ts_offset;
    1965                 :            :   } else {
    1966                 :            :     /* not the first buffer, the timestamp is the diff between the clock and
    1967                 :            :      * base_time */
    1968 [ -  + ][ #  # ]:     602889 :     if (do_timestamp && !GST_CLOCK_TIME_IS_VALID (timestamp)) {
    1969                 :          0 :       now = gst_clock_get_time (clock);
    1970                 :            : 
    1971                 :          0 :       GST_BUFFER_TIMESTAMP (buffer) = now - base_time;
    1972                 :            : 
    1973 [ #  # ][ #  # ]:          0 :       GST_LOG_OBJECT (basesrc, "created timestamp: %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1974                 :            :           GST_TIME_ARGS (now - base_time));
    1975                 :            :     }
    1976                 :            :   }
    1977                 :            : 
    1978                 :            :   /* if we don't have a buffer timestamp, we don't sync */
    1979         [ +  - ]:     602882 :   if (!GST_CLOCK_TIME_IS_VALID (start))
    1980                 :     602882 :     goto no_sync;
    1981                 :            : 
    1982 [ #  # ][ #  # ]:          0 :   if (basesrc->is_live && GST_CLOCK_TIME_IS_VALID (timestamp)) {
    1983                 :            :     /* for pseudo live sources, add our ts_offset to the timestamp */
    1984                 :          0 :     GST_BUFFER_TIMESTAMP (buffer) += basesrc->priv->ts_offset;
    1985                 :          0 :     start += basesrc->priv->ts_offset;
    1986                 :            :   }
    1987                 :            : 
    1988 [ #  # ][ #  # ]:          0 :   GST_LOG_OBJECT (basesrc,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1989                 :            :       "waiting for clock, base time %" GST_TIME_FORMAT
    1990                 :            :       ", stream_start %" GST_TIME_FORMAT,
    1991                 :            :       GST_TIME_ARGS (base_time), GST_TIME_ARGS (start));
    1992                 :          0 :   GST_OBJECT_UNLOCK (basesrc);
    1993                 :            : 
    1994                 :          0 :   result = gst_base_src_wait (basesrc, clock, start + base_time);
    1995                 :            : 
    1996         [ #  # ]:          0 :   GST_LOG_OBJECT (basesrc, "clock entry done: %d", result);
    1997                 :            : 
    1998                 :          0 :   return result;
    1999                 :            : 
    2000                 :            :   /* special cases */
    2001                 :            : no_clock:
    2002                 :            :   {
    2003         [ -  + ]:      83657 :     GST_DEBUG_OBJECT (basesrc, "we have no clock");
    2004                 :      83657 :     GST_OBJECT_UNLOCK (basesrc);
    2005                 :      83657 :     return GST_CLOCK_OK;
    2006                 :            :   }
    2007                 :            : no_sync:
    2008                 :            :   {
    2009         [ -  + ]:     602882 :     GST_DEBUG_OBJECT (basesrc, "no sync needed");
    2010                 :     602882 :     GST_OBJECT_UNLOCK (basesrc);
    2011                 :     686563 :     return GST_CLOCK_OK;
    2012                 :            :   }
    2013                 :            : }
    2014                 :            : 
    2015                 :            : /* Called with STREAM_LOCK and LIVE_LOCK */
    2016                 :            : static gboolean
    2017                 :     686580 : gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
    2018                 :            : {
    2019                 :            :   guint64 size, maxsize;
    2020                 :            :   GstBaseSrcClass *bclass;
    2021                 :            :   GstFormat format;
    2022                 :            :   gint64 stop;
    2023                 :            : 
    2024                 :     686580 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    2025                 :            : 
    2026                 :     686580 :   format = src->segment.format;
    2027                 :     686580 :   stop = src->segment.stop;
    2028                 :            :   /* get total file size */
    2029                 :     686580 :   size = (guint64) src->segment.duration;
    2030                 :            : 
    2031                 :            :   /* only operate if we are working with bytes */
    2032         [ -  + ]:     686580 :   if (format != GST_FORMAT_BYTES)
    2033                 :          0 :     return TRUE;
    2034                 :            : 
    2035                 :            :   /* the max amount of bytes to read is the total size or
    2036                 :            :    * up to the segment.stop if present. */
    2037         [ -  + ]:     686580 :   if (stop != -1)
    2038                 :          0 :     maxsize = MIN (size, stop);
    2039                 :            :   else
    2040                 :     686580 :     maxsize = size;
    2041                 :            : 
    2042         [ -  + ]:     686580 :   GST_DEBUG_OBJECT (src,
    2043                 :            :       "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
    2044                 :            :       ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
    2045                 :            :       *length, size, stop, maxsize);
    2046                 :            : 
    2047                 :            :   /* check size if we have one */
    2048         [ +  + ]:     686591 :   if (maxsize != -1) {
    2049                 :            :     /* if we run past the end, check if the file became bigger and
    2050                 :            :      * retry. */
    2051         [ +  + ]:         19 :     if (G_UNLIKELY (offset + *length >= maxsize)) {
    2052                 :            :       /* see if length of the file changed */
    2053         [ +  - ]:          8 :       if (bclass->get_size)
    2054         [ -  + ]:          8 :         if (!bclass->get_size (src, &size))
    2055                 :          0 :           size = -1;
    2056                 :            : 
    2057                 :            :       /* make sure we don't exceed the configured segment stop
    2058                 :            :        * if it was set */
    2059         [ -  + ]:          8 :       if (stop != -1)
    2060                 :          0 :         maxsize = MIN (size, stop);
    2061                 :            :       else
    2062                 :          8 :         maxsize = size;
    2063                 :            : 
    2064                 :            :       /* if we are at or past the end, EOS */
    2065         [ +  + ]:          8 :       if (G_UNLIKELY (offset >= maxsize))
    2066                 :          4 :         goto unexpected_length;
    2067                 :            : 
    2068                 :            :       /* else we can clip to the end */
    2069         [ +  - ]:          4 :       if (G_UNLIKELY (offset + *length >= maxsize))
    2070                 :          4 :         *length = maxsize - offset;
    2071                 :            : 
    2072                 :            :     }
    2073                 :            :   }
    2074                 :            : 
    2075                 :            :   /* keep track of current position and update duration.
    2076                 :            :    * segment is in bytes, we checked that above. */
    2077                 :     686587 :   GST_OBJECT_LOCK (src);
    2078                 :     686590 :   gst_segment_set_duration (&src->segment, GST_FORMAT_BYTES, size);
    2079                 :     686575 :   gst_segment_set_last_stop (&src->segment, GST_FORMAT_BYTES, offset);
    2080                 :     686584 :   GST_OBJECT_UNLOCK (src);
    2081                 :            : 
    2082                 :     686584 :   return TRUE;
    2083                 :            : 
    2084                 :            :   /* ERRORS */
    2085                 :            : unexpected_length:
    2086                 :            :   {
    2087                 :     686588 :     return FALSE;
    2088                 :            :   }
    2089                 :            : }
    2090                 :            : 
    2091                 :            : /* must be called with LIVE_LOCK */
    2092                 :            : static GstFlowReturn
    2093                 :     686587 : gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
    2094                 :            :     GstBuffer ** buf)
    2095                 :            : {
    2096                 :            :   GstFlowReturn ret;
    2097                 :            :   GstBaseSrcClass *bclass;
    2098                 :            :   GstClockReturn status;
    2099                 :            : 
    2100                 :     686587 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    2101                 :            : 
    2102                 :            : again:
    2103         [ +  + ]:     686587 :   if (src->is_live) {
    2104         [ -  + ]:       3446 :     if (G_UNLIKELY (!src->live_running)) {
    2105                 :          0 :       ret = gst_base_src_wait_playing (src);
    2106         [ #  # ]:          0 :       if (ret != GST_FLOW_OK)
    2107                 :          0 :         goto stopped;
    2108                 :            :     }
    2109                 :            :   }
    2110                 :            : 
    2111         [ -  + ]:     686587 :   if (G_UNLIKELY (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)))
    2112                 :          0 :     goto not_started;
    2113                 :            : 
    2114         [ -  + ]:     686587 :   if (G_UNLIKELY (!bclass->create))
    2115                 :          0 :     goto no_function;
    2116                 :            : 
    2117         [ +  + ]:     686587 :   if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length)))
    2118                 :          4 :     goto unexpected_length;
    2119                 :            : 
    2120                 :            :   /* normally we don't count buffers */
    2121         [ +  + ]:     686585 :   if (G_UNLIKELY (src->num_buffers_left >= 0)) {
    2122         [ +  + ]:       7706 :     if (src->num_buffers_left == 0)
    2123                 :         23 :       goto reached_num_buffers;
    2124                 :            :     else
    2125                 :       7683 :       src->num_buffers_left--;
    2126                 :            :   }
    2127                 :            : 
    2128                 :            :   /* don't enter the create function if a pending EOS event was set. For the
    2129                 :            :    * logic of the pending_eos, check the event function of this class. */
    2130         [ +  + ]:     686562 :   if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos)))
    2131                 :          1 :     goto eos;
    2132                 :            : 
    2133         [ -  + ]:     686567 :   GST_DEBUG_OBJECT (src,
    2134                 :            :       "calling create offset %" G_GUINT64_FORMAT " length %u, time %"
    2135                 :            :       G_GINT64_FORMAT, offset, length, src->segment.time);
    2136                 :            : 
    2137                 :     686567 :   ret = bclass->create (src, offset, length, buf);
    2138                 :            : 
    2139                 :            :   /* The create function could be unlocked because we have a pending EOS. It's
    2140                 :            :    * possible that we have a valid buffer from create that we need to
    2141                 :            :    * discard when the create function returned _OK. */
    2142         [ +  + ]:     686553 :   if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
    2143         [ +  - ]:          1 :     if (ret == GST_FLOW_OK) {
    2144                 :          1 :       gst_buffer_unref (*buf);
    2145                 :          1 :       *buf = NULL;
    2146                 :            :     }
    2147                 :          1 :     goto eos;
    2148                 :            :   }
    2149                 :            : 
    2150         [ +  + ]:     686565 :   if (G_UNLIKELY (ret != GST_FLOW_OK))
    2151                 :          2 :     goto not_ok;
    2152                 :            : 
    2153                 :            :   /* no timestamp set and we are at offset 0, we can timestamp with 0 */
    2154 [ +  + ][ +  + ]:     686563 :   if (offset == 0 && src->segment.time == 0
    2155         [ +  + ]:     686035 :       && GST_BUFFER_TIMESTAMP (*buf) == -1) {
    2156                 :     677587 :     *buf = gst_buffer_make_metadata_writable (*buf);
    2157                 :     677586 :     GST_BUFFER_TIMESTAMP (*buf) = 0;
    2158                 :            :   }
    2159                 :            : 
    2160                 :            :   /* set pad caps on the buffer if the buffer had no caps */
    2161            [ + ]:     686562 :   if (GST_BUFFER_CAPS (*buf) == NULL) {
    2162                 :     686563 :     *buf = gst_buffer_make_metadata_writable (*buf);
    2163                 :     686561 :     gst_buffer_set_caps (*buf, GST_PAD_CAPS (src->srcpad));
    2164                 :            :   }
    2165                 :            : 
    2166                 :            :   /* now sync before pushing the buffer */
    2167                 :     686563 :   status = gst_base_src_do_sync (src, *buf);
    2168                 :            : 
    2169                 :            :   /* waiting for the clock could have made us flushing */
    2170         [ -  + ]:     686563 :   if (G_UNLIKELY (src->priv->flushing))
    2171                 :          0 :     goto flushing;
    2172                 :            : 
    2173   [ -  +  -  - ]:     686563 :   switch (status) {
    2174                 :            :     case GST_CLOCK_EARLY:
    2175                 :            :       /* the buffer is too late. We currently don't drop the buffer. */
    2176         [ #  # ]:          0 :       GST_DEBUG_OBJECT (src, "buffer too late!, returning anyway");
    2177                 :          0 :       break;
    2178                 :            :     case GST_CLOCK_OK:
    2179                 :            :       /* buffer synchronised properly */
    2180         [ -  + ]:     686563 :       GST_DEBUG_OBJECT (src, "buffer ok");
    2181                 :     686563 :       break;
    2182                 :            :     case GST_CLOCK_UNSCHEDULED:
    2183                 :            :       /* this case is triggered when we were waiting for the clock and
    2184                 :            :        * it got unlocked because we did a state change. In any case, get rid of
    2185                 :            :        * the buffer. */
    2186                 :          0 :       gst_buffer_unref (*buf);
    2187                 :          0 :       *buf = NULL;
    2188         [ #  # ]:          0 :       if (!src->live_running) {
    2189                 :            :         /* We return WRONG_STATE when we are not running to stop the dataflow also
    2190                 :            :          * get rid of the produced buffer. */
    2191         [ #  # ]:          0 :         GST_DEBUG_OBJECT (src,
    2192                 :            :             "clock was unscheduled (%d), returning WRONG_STATE", status);
    2193                 :          0 :         ret = GST_FLOW_WRONG_STATE;
    2194                 :            :       } else {
    2195                 :            :         /* If we are running when this happens, we quickly switched between
    2196                 :            :          * pause and playing. We try to produce a new buffer */
    2197         [ #  # ]:          0 :         GST_DEBUG_OBJECT (src,
    2198                 :            :             "clock was unscheduled (%d), but we are running", status);
    2199                 :          0 :         goto again;
    2200                 :            :       }
    2201                 :          0 :       break;
    2202                 :            :     default:
    2203                 :            :       /* all other result values are unexpected and errors */
    2204 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (src, CORE, CLOCK,
         [ #  # ][ #  # ]
    2205                 :            :           (_("Internal clock error.")),
    2206                 :            :           ("clock returned unexpected return value %d", status));
    2207                 :          0 :       gst_buffer_unref (*buf);
    2208                 :          0 :       *buf = NULL;
    2209                 :          0 :       ret = GST_FLOW_ERROR;
    2210                 :          0 :       break;
    2211                 :            :   }
    2212                 :     686539 :   return ret;
    2213                 :            : 
    2214                 :            :   /* ERROR */
    2215                 :            : stopped:
    2216                 :            :   {
    2217         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "wait_playing returned %d (%s)", ret,
    2218                 :            :         gst_flow_get_name (ret));
    2219                 :          0 :     return ret;
    2220                 :            :   }
    2221                 :            : not_ok:
    2222                 :            :   {
    2223         [ -  + ]:          2 :     GST_DEBUG_OBJECT (src, "create returned %d (%s)", ret,
    2224                 :            :         gst_flow_get_name (ret));
    2225                 :          2 :     return ret;
    2226                 :            :   }
    2227                 :            : not_started:
    2228                 :            :   {
    2229         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "getrange but not started");
    2230                 :          0 :     return GST_FLOW_WRONG_STATE;
    2231                 :            :   }
    2232                 :            : no_function:
    2233                 :            :   {
    2234         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "no create function");
    2235                 :          0 :     return GST_FLOW_ERROR;
    2236                 :            :   }
    2237                 :            : unexpected_length:
    2238                 :            :   {
    2239         [ -  + ]:          4 :     GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT
    2240                 :            :         ", size=%" G_GINT64_FORMAT ")", length, offset, src->segment.duration);
    2241                 :          4 :     return GST_FLOW_UNEXPECTED;
    2242                 :            :   }
    2243                 :            : reached_num_buffers:
    2244                 :            :   {
    2245         [ -  + ]:         23 :     GST_DEBUG_OBJECT (src, "sent all buffers");
    2246                 :         23 :     return GST_FLOW_UNEXPECTED;
    2247                 :            :   }
    2248                 :            : flushing:
    2249                 :            :   {
    2250         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "we are flushing");
    2251                 :          0 :     gst_buffer_unref (*buf);
    2252                 :          0 :     *buf = NULL;
    2253                 :          0 :     return GST_FLOW_WRONG_STATE;
    2254                 :            :   }
    2255                 :            : eos:
    2256                 :            :   {
    2257         [ -  + ]:          2 :     GST_DEBUG_OBJECT (src, "we are EOS");
    2258                 :     686570 :     return GST_FLOW_UNEXPECTED;
    2259                 :            :   }
    2260                 :            : }
    2261                 :            : 
    2262                 :            : static GstFlowReturn
    2263                 :      38629 : gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length,
    2264                 :            :     GstBuffer ** buf)
    2265                 :            : {
    2266                 :            :   GstBaseSrc *src;
    2267                 :            :   GstFlowReturn res;
    2268                 :            : 
    2269                 :      38629 :   src = GST_BASE_SRC_CAST (gst_object_ref (GST_OBJECT_PARENT (pad)));
    2270                 :            : 
    2271                 :      38629 :   GST_LIVE_LOCK (src);
    2272         [ -  + ]:      38629 :   if (G_UNLIKELY (src->priv->flushing))
    2273                 :          0 :     goto flushing;
    2274                 :            : 
    2275                 :      38629 :   res = gst_base_src_get_range (src, offset, length, buf);
    2276                 :            : 
    2277                 :            : done:
    2278                 :      38629 :   GST_LIVE_UNLOCK (src);
    2279                 :            : 
    2280                 :      38629 :   gst_object_unref (src);
    2281                 :            : 
    2282                 :      38629 :   return res;
    2283                 :            : 
    2284                 :            :   /* ERRORS */
    2285                 :            : flushing:
    2286                 :            :   {
    2287         [ #  # ]:          0 :     GST_DEBUG_OBJECT (src, "we are flushing");
    2288                 :          0 :     res = GST_FLOW_WRONG_STATE;
    2289                 :          0 :     goto done;
    2290                 :            :   }
    2291                 :            : }
    2292                 :            : 
    2293                 :            : static gboolean
    2294                 :         13 : gst_base_src_default_check_get_range (GstBaseSrc * src)
    2295                 :            : {
    2296                 :            :   gboolean res;
    2297                 :            : 
    2298         [ +  + ]:         13 :   if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
    2299         [ -  + ]:          6 :     GST_LOG_OBJECT (src, "doing start/stop to check get_range support");
    2300         [ +  - ]:          6 :     if (G_LIKELY (gst_base_src_start (src)))
    2301                 :          6 :       gst_base_src_stop (src);
    2302                 :            :   }
    2303                 :            : 
    2304                 :            :   /* we can operate in getrange mode if the native format is bytes
    2305                 :            :    * and we are seekable, this condition is set in the random_access
    2306                 :            :    * flag and is set in the _start() method. */
    2307                 :         13 :   res = src->random_access;
    2308                 :            : 
    2309                 :         13 :   return res;
    2310                 :            : }
    2311                 :            : 
    2312                 :            : static gboolean
    2313                 :         13 : gst_base_src_check_get_range (GstBaseSrc * src)
    2314                 :            : {
    2315                 :            :   GstBaseSrcClass *bclass;
    2316                 :            :   gboolean res;
    2317                 :            : 
    2318                 :         13 :   bclass = GST_BASE_SRC_GET_CLASS (src);
    2319                 :            : 
    2320         [ -  + ]:         13 :   if (bclass->check_get_range == NULL)
    2321                 :          0 :     goto no_function;
    2322                 :            : 
    2323                 :         13 :   res = bclass->check_get_range (src);
    2324         [ -  + ]:         13 :   GST_LOG_OBJECT (src, "%s() returned %d",
    2325                 :            :       GST_DEBUG_FUNCPTR_NAME (bclass->check_get_range), (gint) res);
    2326                 :            : 
    2327                 :         13 :   return res;
    2328                 :            : 
    2329                 :            :   /* ERRORS */
    2330                 :            : no_function:
    2331                 :            :   {
    2332         [ #  # ]:          0 :     GST_WARNING_OBJECT (src, "no check_get_range function set");
    2333                 :         13 :     return FALSE;
    2334                 :            :   }
    2335                 :            : }
    2336                 :            : 
    2337                 :            : static gboolean
    2338                 :          6 : gst_base_src_pad_check_get_range (GstPad * pad)
    2339                 :            : {
    2340                 :            :   GstBaseSrc *src;
    2341                 :            :   gboolean res;
    2342                 :            : 
    2343                 :          6 :   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
    2344                 :            : 
    2345                 :          6 :   res = gst_base_src_check_get_range (src);
    2346                 :            : 
    2347                 :          6 :   return res;
    2348                 :            : }
    2349                 :            : 
    2350                 :            : static void
    2351                 :     647972 : gst_base_src_loop (GstPad * pad)
    2352                 :            : {
    2353                 :            :   GstBaseSrc *src;
    2354                 :     647972 :   GstBuffer *buf = NULL;
    2355                 :            :   GstFlowReturn ret;
    2356                 :            :   gint64 position;
    2357                 :            :   gboolean eos;
    2358                 :            :   gulong blocksize;
    2359                 :     647972 :   GList *tags = NULL, *tmp;
    2360                 :            : 
    2361                 :     647972 :   eos = FALSE;
    2362                 :            : 
    2363                 :     647972 :   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
    2364                 :            : 
    2365                 :     647970 :   GST_LIVE_LOCK (src);
    2366                 :            : 
    2367         [ +  + ]:     647971 :   if (G_UNLIKELY (src->priv->flushing))
    2368                 :          6 :     goto flushing;
    2369                 :            : 
    2370                 :     647965 :   src->priv->last_sent_eos = FALSE;
    2371                 :            : 
    2372                 :     647965 :   blocksize = src->blocksize;
    2373                 :            : 
    2374                 :            :   /* if we operate in bytes, we can calculate an offset */
    2375         [ +  - ]:     647965 :   if (src->segment.format == GST_FORMAT_BYTES) {
    2376                 :     647965 :     position = src->segment.last_stop;
    2377                 :            :     /* for negative rates, start with subtracting the blocksize */
    2378         [ +  + ]:     647965 :     if (src->segment.rate < 0.0) {
    2379                 :            :       /* we cannot go below segment.start */
    2380         [ +  + ]:          8 :       if (position > src->segment.start + blocksize)
    2381                 :          7 :         position -= blocksize;
    2382                 :            :       else {
    2383                 :            :         /* last block, remainder up to segment.start */
    2384                 :          1 :         blocksize = position - src->segment.start;
    2385                 :          1 :         position = src->segment.start;
    2386                 :            :       }
    2387                 :            :     }
    2388                 :            :   } else
    2389                 :          0 :     position = -1;
    2390                 :            : 
    2391 [ -  + ][ #  # ]:     647965 :   GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %lu",
         [ #  # ][ #  # ]
                 [ #  # ]
    2392                 :            :       GST_TIME_ARGS (position), blocksize);
    2393                 :            : 
    2394                 :     647965 :   ret = gst_base_src_get_range (src, position, blocksize, &buf);
    2395         [ +  + ]:     647926 :   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    2396         [ -  + ]:         24 :     GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s",
    2397                 :            :         gst_flow_get_name (ret));
    2398                 :         24 :     GST_LIVE_UNLOCK (src);
    2399                 :         24 :     goto pause;
    2400                 :            :   }
    2401                 :            :   /* this should not happen */
    2402         [ -  + ]:     647902 :   if (G_UNLIKELY (buf == NULL))
    2403                 :          0 :     goto null_buffer;
    2404                 :            : 
    2405                 :            :   /* push events to close/start our segment before we push the buffer. */
    2406         [ +  + ]:     647902 :   if (G_UNLIKELY (src->priv->close_segment)) {
    2407                 :          1 :     gst_pad_push_event (pad, src->priv->close_segment);
    2408                 :          1 :     src->priv->close_segment = NULL;
    2409                 :            :   }
    2410         [ +  + ]:     647902 :   if (G_UNLIKELY (src->priv->start_segment)) {
    2411                 :        200 :     gst_pad_push_event (pad, src->priv->start_segment);
    2412                 :        200 :     src->priv->start_segment = NULL;
    2413                 :            :   }
    2414                 :     647902 :   src->priv->newsegment_pending = FALSE;
    2415                 :            : 
    2416         [ -  + ]:     647902 :   if (g_atomic_int_get (&src->priv->have_tags)) {
    2417                 :          0 :     GST_OBJECT_LOCK (src);
    2418                 :            :     /* take the tags */
    2419                 :          0 :     tags = src->priv->pending_tags;
    2420                 :          0 :     src->priv->pending_tags = NULL;
    2421                 :          0 :     g_atomic_int_set (&src->priv->have_tags, FALSE);
    2422                 :          0 :     GST_OBJECT_UNLOCK (src);
    2423                 :            :   }
    2424                 :            : 
    2425                 :            :   /* Push out pending tags if any */
    2426         [ -  + ]:     647942 :   if (G_UNLIKELY (tags != NULL)) {
    2427 [ #  # ][ #  # ]:          0 :     for (tmp = tags; tmp; tmp = g_list_next (tmp)) {
    2428                 :          0 :       GstEvent *ev = (GstEvent *) tmp->data;
    2429                 :          0 :       gst_pad_push_event (pad, ev);
    2430                 :            :     }
    2431                 :          0 :     g_list_free (tags);
    2432                 :            :   }
    2433                 :            : 
    2434                 :            :   /* figure out the new position */
    2435   [ +  -  -  - ]:     647942 :   switch (src->segment.format) {
    2436                 :            :     case GST_FORMAT_BYTES:
    2437                 :            :     {
    2438                 :     647942 :       guint bufsize = GST_BUFFER_SIZE (buf);
    2439                 :            : 
    2440                 :            :       /* we subtracted above for negative rates */
    2441         [ +  + ]:     647942 :       if (src->segment.rate >= 0.0)
    2442                 :     647934 :         position += bufsize;
    2443                 :     647942 :       break;
    2444                 :            :     }
    2445                 :            :     case GST_FORMAT_TIME:
    2446                 :            :     {
    2447                 :            :       GstClockTime start, duration;
    2448                 :            : 
    2449                 :          0 :       start = GST_BUFFER_TIMESTAMP (buf);
    2450                 :          0 :       duration = GST_BUFFER_DURATION (buf);
    2451                 :            : 
    2452         [ #  # ]:          0 :       if (GST_CLOCK_TIME_IS_VALID (start))
    2453                 :          0 :         position = start;
    2454                 :            :       else
    2455                 :          0 :         position = src->segment.last_stop;
    2456                 :            : 
    2457         [ #  # ]:          0 :       if (GST_CLOCK_TIME_IS_VALID (duration)) {
    2458         [ #  # ]:          0 :         if (src->segment.rate >= 0.0)
    2459                 :          0 :           position += duration;
    2460         [ #  # ]:          0 :         else if (position > duration)
    2461                 :          0 :           position -= duration;
    2462                 :            :         else
    2463                 :          0 :           position = 0;
    2464                 :            :       }
    2465                 :          0 :       break;
    2466                 :            :     }
    2467                 :            :     case GST_FORMAT_DEFAULT:
    2468         [ #  # ]:          0 :       if (src->segment.rate >= 0.0)
    2469                 :          0 :         position = GST_BUFFER_OFFSET_END (buf);
    2470                 :            :       else
    2471                 :          0 :         position = GST_BUFFER_OFFSET (buf);
    2472                 :          0 :       break;
    2473                 :            :     default:
    2474                 :          0 :       position = -1;
    2475                 :          0 :       break;
    2476                 :            :   }
    2477         [ +  + ]:     647942 :   if (position != -1) {
    2478         [ +  + ]:     647941 :     if (src->segment.rate >= 0.0) {
    2479                 :            :       /* positive rate, check if we reached the stop */
    2480         [ -  + ]:     647933 :       if (src->segment.stop != -1) {
    2481         [ #  # ]:          0 :         if (position >= src->segment.stop) {
    2482                 :          0 :           eos = TRUE;
    2483                 :          0 :           position = src->segment.stop;
    2484                 :            :         }
    2485                 :            :       }
    2486                 :            :     } else {
    2487                 :            :       /* negative rate, check if we reached the start. start is always set to
    2488                 :            :        * something different from -1 */
    2489         [ +  + ]:          8 :       if (position <= src->segment.start) {
    2490                 :          1 :         eos = TRUE;
    2491                 :          1 :         position = src->segment.start;
    2492                 :            :       }
    2493                 :            :       /* when going reverse, all buffers are DISCONT */
    2494                 :          8 :       src->priv->discont = TRUE;
    2495                 :            :     }
    2496                 :     647941 :     GST_OBJECT_LOCK (src);
    2497                 :     647942 :     gst_segment_set_last_stop (&src->segment, src->segment.format, position);
    2498                 :     647942 :     GST_OBJECT_UNLOCK (src);
    2499                 :            :   }
    2500                 :            : 
    2501         [ +  + ]:     647942 :   if (G_UNLIKELY (src->priv->discont)) {
    2502                 :        207 :     buf = gst_buffer_make_metadata_writable (buf);
    2503                 :        207 :     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
    2504                 :        207 :     src->priv->discont = FALSE;
    2505                 :            :   }
    2506                 :     647942 :   GST_LIVE_UNLOCK (src);
    2507                 :            : 
    2508                 :     647942 :   ret = gst_pad_push (pad, buf);
    2509         [ +  + ]:     647932 :   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    2510         [ -  + ]:        153 :     GST_INFO_OBJECT (src, "pausing after gst_pad_push() = %s",
    2511                 :            :         gst_flow_get_name (ret));
    2512                 :        153 :     goto pause;
    2513                 :            :   }
    2514                 :            : 
    2515         [ +  + ]:     647779 :   if (G_UNLIKELY (eos)) {
    2516         [ -  + ]:          1 :     GST_INFO_OBJECT (src, "pausing after end of segment");
    2517                 :          1 :     ret = GST_FLOW_UNEXPECTED;
    2518                 :          1 :     goto pause;
    2519                 :            :   }
    2520                 :            : 
    2521                 :            : done:
    2522                 :     647962 :   return;
    2523                 :            : 
    2524                 :            :   /* special cases */
    2525                 :            : flushing:
    2526                 :            :   {
    2527         [ -  + ]:          6 :     GST_DEBUG_OBJECT (src, "we are flushing");
    2528                 :          6 :     GST_LIVE_UNLOCK (src);
    2529                 :          6 :     ret = GST_FLOW_WRONG_STATE;
    2530                 :          6 :     goto pause;
    2531                 :            :   }
    2532                 :            : pause:
    2533                 :            :   {
    2534                 :        184 :     const gchar *reason = gst_flow_get_name (ret);
    2535                 :            :     GstEvent *event;
    2536                 :            : 
    2537         [ -  + ]:        184 :     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
    2538                 :        184 :     src->data.ABI.running = FALSE;
    2539                 :        184 :     gst_pad_pause_task (pad);
    2540         [ +  + ]:        184 :     if (ret == GST_FLOW_UNEXPECTED) {
    2541                 :            :       gboolean flag_segment;
    2542                 :            :       GstFormat format;
    2543                 :            :       gint64 last_stop;
    2544                 :            : 
    2545                 :            :       /* perform EOS logic */
    2546                 :         23 :       flag_segment = (src->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0;
    2547                 :         23 :       format = src->segment.format;
    2548                 :         23 :       last_stop = src->segment.last_stop;
    2549                 :            : 
    2550         [ -  + ]:         23 :       if (flag_segment) {
    2551                 :            :         GstMessage *message;
    2552                 :            : 
    2553                 :          0 :         message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
    2554                 :            :             format, last_stop);
    2555                 :          0 :         gst_message_set_seqnum (message, src->priv->seqnum);
    2556                 :          0 :         gst_element_post_message (GST_ELEMENT_CAST (src), message);
    2557                 :            :       } else {
    2558                 :         23 :         event = gst_event_new_eos ();
    2559                 :         23 :         gst_event_set_seqnum (event, src->priv->seqnum);
    2560                 :         23 :         gst_pad_push_event (pad, event);
    2561                 :         23 :         src->priv->last_sent_eos = TRUE;
    2562                 :            :       }
    2563 [ +  + ][ +  + ]:        161 :     } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_UNEXPECTED) {
    2564                 :          4 :       event = gst_event_new_eos ();
    2565                 :          4 :       gst_event_set_seqnum (event, src->priv->seqnum);
    2566                 :            :       /* for fatal errors we post an error message, post the error
    2567                 :            :        * first so the app knows about the error first.
    2568                 :            :        * Also don't do this for WRONG_STATE because it happens
    2569                 :            :        * due to flushing and posting an error message because of
    2570                 :            :        * that is the wrong thing to do, e.g. when we're doing
    2571                 :            :        * a flushing seek. */
    2572 [ +  - ][ -  + ]:          4 :       GST_ELEMENT_ERROR (src, STREAM, FAILED,
         [ +  - ][ -  + ]
    2573                 :            :           (_("Internal data flow error.")),
    2574                 :            :           ("streaming task paused, reason %s (%d)", reason, ret));
    2575                 :          4 :       gst_pad_push_event (pad, event);
    2576                 :          4 :       src->priv->last_sent_eos = TRUE;
    2577                 :            :     }
    2578                 :        184 :     goto done;
    2579                 :            :   }
    2580                 :            : null_buffer:
    2581                 :            :   {
    2582 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (src, STREAM, FAILED,
         [ #  # ][ #  # ]
    2583                 :            :         (_("Internal data flow error.")), ("element returned NULL buffer"));
    2584                 :          0 :     GST_LIVE_UNLOCK (src);
    2585                 :          0 :     goto done;
    2586                 :            :   }
    2587                 :            : }
    2588                 :            : 
    2589                 :            : /* default negotiation code.
    2590                 :            :  *
    2591                 :            :  * Take intersection between src and sink pads, take first
    2592                 :            :  * caps and fixate.
    2593                 :            :  */
    2594                 :            : static gboolean
    2595                 :        417 : gst_base_src_default_negotiate (GstBaseSrc * basesrc)
    2596                 :            : {
    2597                 :            :   GstCaps *thiscaps;
    2598                 :        417 :   GstCaps *caps = NULL;
    2599                 :        417 :   GstCaps *peercaps = NULL;
    2600                 :        417 :   gboolean result = FALSE;
    2601                 :            : 
    2602                 :            :   /* first see what is possible on our source pad */
    2603                 :        417 :   thiscaps = gst_pad_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
    2604         [ -  + ]:        417 :   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
    2605                 :            :   /* nothing or anything is allowed, we're done */
    2606 [ +  - ][ -  + ]:        417 :   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
    2607                 :            :     goto no_nego_needed;
    2608                 :            : 
    2609         [ #  # ]:          0 :   if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
    2610                 :          0 :     goto no_caps;
    2611                 :            : 
    2612                 :            :   /* get the peer caps */
    2613                 :          0 :   peercaps = gst_pad_peer_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
    2614         [ #  # ]:          0 :   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
    2615         [ #  # ]:          0 :   if (peercaps) {
    2616                 :            :     /* get intersection */
    2617                 :          0 :     caps = gst_caps_intersect_full (peercaps, thiscaps, GST_CAPS_INTERSECT_FIRST);
    2618         [ #  # ]:          0 :     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
    2619                 :          0 :     gst_caps_unref (peercaps);
    2620                 :            :   } else {
    2621                 :            :     /* no peer, work with our own caps then */
    2622                 :          0 :     caps = gst_caps_copy (thiscaps);
    2623                 :            :   }
    2624                 :          0 :   gst_caps_unref (thiscaps);
    2625         [ #  # ]:          0 :   if (caps) {
    2626                 :            :     /* take first (and best, since they are sorted) possibility */
    2627                 :          0 :     gst_caps_truncate (caps);
    2628                 :            : 
    2629                 :            :     /* now fixate */
    2630         [ #  # ]:          0 :     if (!gst_caps_is_empty (caps)) {
    2631                 :          0 :       gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
    2632         [ #  # ]:          0 :       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
    2633                 :            : 
    2634         [ #  # ]:          0 :       if (gst_caps_is_any (caps)) {
    2635                 :            :         /* hmm, still anything, so element can do anything and
    2636                 :            :          * nego is not needed */
    2637                 :          0 :         result = TRUE;
    2638         [ #  # ]:          0 :       } else if (gst_caps_is_fixed (caps)) {
    2639                 :            :         /* yay, fixed caps, use those then, it's possible that the subclass does
    2640                 :            :          * not accept this caps after all and we have to fail. */
    2641                 :          0 :         result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
    2642                 :            :       }
    2643                 :            :     }
    2644                 :          0 :     gst_caps_unref (caps);
    2645                 :            :   } else {
    2646         [ #  # ]:          0 :     GST_DEBUG_OBJECT (basesrc, "no common caps");
    2647                 :            :   }
    2648                 :          0 :   return result;
    2649                 :            : 
    2650                 :            : no_nego_needed:
    2651                 :            :   {
    2652         [ -  + ]:        417 :     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
    2653         [ +  - ]:        417 :     if (thiscaps)
    2654                 :        417 :       gst_caps_unref (thiscaps);
    2655                 :        417 :     return TRUE;
    2656                 :            :   }
    2657                 :            : no_caps:
    2658                 :            :   {
    2659 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
         [ #  # ][ #  # ]
    2660                 :            :         ("No supported formats found"),
    2661                 :            :         ("This element did not produce valid caps"));
    2662         [ #  # ]:          0 :     if (thiscaps)
    2663                 :          0 :       gst_caps_unref (thiscaps);
    2664                 :        417 :     return TRUE;
    2665                 :            :   }
    2666                 :            : }
    2667                 :            : 
    2668                 :            : static gboolean
    2669                 :        417 : gst_base_src_negotiate (GstBaseSrc * basesrc)
    2670                 :            : {
    2671                 :            :   GstBaseSrcClass *bclass;
    2672                 :        417 :   gboolean result = TRUE;
    2673                 :            : 
    2674                 :        417 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    2675                 :            : 
    2676         [ +  - ]:        417 :   if (bclass->negotiate)
    2677                 :        417 :     result = bclass->negotiate (basesrc);
    2678                 :            : 
    2679                 :        417 :   return result;
    2680                 :            : }
    2681                 :            : 
    2682                 :            : static gboolean
    2683                 :        436 : gst_base_src_start (GstBaseSrc * basesrc)
    2684                 :            : {
    2685                 :            :   GstBaseSrcClass *bclass;
    2686                 :            :   gboolean result;
    2687                 :            :   guint64 size;
    2688                 :            :   gboolean seekable;
    2689                 :            :   GstFormat format;
    2690                 :            : 
    2691         [ -  + ]:        436 :   if (GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
    2692                 :          0 :     return TRUE;
    2693                 :            : 
    2694         [ -  + ]:        436 :   GST_DEBUG_OBJECT (basesrc, "starting source");
    2695                 :            : 
    2696                 :        436 :   basesrc->num_buffers_left = basesrc->num_buffers;
    2697                 :            : 
    2698                 :        436 :   GST_OBJECT_LOCK (basesrc);
    2699                 :        436 :   gst_segment_init (&basesrc->segment, basesrc->segment.format);
    2700                 :        436 :   GST_OBJECT_UNLOCK (basesrc);
    2701                 :            : 
    2702                 :        436 :   basesrc->data.ABI.running = FALSE;
    2703                 :        436 :   basesrc->priv->newsegment_pending = FALSE;
    2704                 :            : 
    2705                 :        436 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    2706         [ +  + ]:        436 :   if (bclass->start)
    2707                 :        426 :     result = bclass->start (basesrc);
    2708                 :            :   else
    2709                 :         10 :     result = TRUE;
    2710                 :            : 
    2711         [ +  + ]:        436 :   if (!result)
    2712                 :         19 :     goto could_not_start;
    2713                 :            : 
    2714                 :        417 :   GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
    2715                 :            : 
    2716                 :        417 :   format = basesrc->segment.format;
    2717                 :            : 
    2718                 :            :   /* figure out the size */
    2719         [ +  - ]:        417 :   if (format == GST_FORMAT_BYTES) {
    2720         [ +  + ]:        417 :     if (bclass->get_size) {
    2721         [ +  + ]:         13 :       if (!(result = bclass->get_size (basesrc, &size)))
    2722                 :          9 :         size = -1;
    2723                 :            :     } else {
    2724                 :        404 :       result = FALSE;
    2725                 :        404 :       size = -1;
    2726                 :            :     }
    2727         [ -  + ]:        417 :     GST_DEBUG_OBJECT (basesrc, "setting size %" G_GUINT64_FORMAT, size);
    2728                 :            :     /* only update the size when operating in bytes, subclass is supposed
    2729                 :            :      * to set duration in the start method for other formats */
    2730                 :        417 :     GST_OBJECT_LOCK (basesrc);
    2731                 :        417 :     gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES, size);
    2732                 :        417 :     GST_OBJECT_UNLOCK (basesrc);
    2733                 :            :   } else {
    2734                 :          0 :     size = -1;
    2735                 :            :   }
    2736                 :            : 
    2737         [ -  + ]:        417 :   GST_DEBUG_OBJECT (basesrc,
    2738                 :            :       "format: %s, have size: %d, size: %" G_GUINT64_FORMAT ", duration: %"
    2739                 :            :       G_GINT64_FORMAT, gst_format_get_name (format), result, size,
    2740                 :            :       basesrc->segment.duration);
    2741                 :            : 
    2742                 :        417 :   seekable = gst_base_src_seekable (basesrc);
    2743         [ -  + ]:        417 :   GST_DEBUG_OBJECT (basesrc, "is seekable: %d", seekable);
    2744                 :            : 
    2745                 :            :   /* update for random access flag */
    2746 [ +  + ][ +  - ]:        417 :   basesrc->random_access = seekable && format == GST_FORMAT_BYTES;
    2747                 :            : 
    2748         [ -  + ]:        417 :   GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access);
    2749                 :            : 
    2750                 :            :   /* run typefind if we are random_access and the typefinding is enabled. */
    2751 [ +  + ][ -  + ]:        417 :   if (basesrc->random_access && basesrc->data.ABI.typefind && size != -1) {
                 [ #  # ]
    2752                 :            :     GstCaps *caps;
    2753                 :            : 
    2754         [ #  # ]:          0 :     if (!(caps = gst_type_find_helper (basesrc->srcpad, size)))
    2755                 :          0 :       goto typefind_failed;
    2756                 :            : 
    2757                 :          0 :     result = gst_pad_set_caps (basesrc->srcpad, caps);
    2758                 :          0 :     gst_caps_unref (caps);
    2759                 :            :   } else {
    2760                 :            :     /* use class or default negotiate function */
    2761         [ -  + ]:        417 :     if (!(result = gst_base_src_negotiate (basesrc)))
    2762                 :          0 :       goto could_not_negotiate;
    2763                 :            :   }
    2764                 :            : 
    2765                 :        417 :   return result;
    2766                 :            : 
    2767                 :            :   /* ERROR */
    2768                 :            : could_not_start:
    2769                 :            :   {
    2770         [ -  + ]:         19 :     GST_DEBUG_OBJECT (basesrc, "could not start");
    2771                 :            :     /* subclass is supposed to post a message. We don't have to call _stop. */
    2772                 :         19 :     return FALSE;
    2773                 :            :   }
    2774                 :            : could_not_negotiate:
    2775                 :            :   {
    2776         [ #  # ]:          0 :     GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
    2777 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
         [ #  # ][ #  # ]
    2778                 :            :         ("Could not negotiate format"), ("Check your filtered caps, if any"));
    2779                 :            :     /* we must call stop */
    2780                 :          0 :     gst_base_src_stop (basesrc);
    2781                 :          0 :     return FALSE;
    2782                 :            :   }
    2783                 :            : typefind_failed:
    2784                 :            :   {
    2785         [ #  # ]:          0 :     GST_DEBUG_OBJECT (basesrc, "could not typefind, stopping");
    2786 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (basesrc, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
         [ #  # ][ #  # ]
    2787                 :            :     /* we must call stop */
    2788                 :          0 :     gst_base_src_stop (basesrc);
    2789                 :        436 :     return FALSE;
    2790                 :            :   }
    2791                 :            : }
    2792                 :            : 
    2793                 :            : static gboolean
    2794                 :        417 : gst_base_src_stop (GstBaseSrc * basesrc)
    2795                 :            : {
    2796                 :            :   GstBaseSrcClass *bclass;
    2797                 :        417 :   gboolean result = TRUE;
    2798                 :            : 
    2799         [ -  + ]:        417 :   if (!GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
    2800                 :          0 :     return TRUE;
    2801                 :            : 
    2802         [ -  + ]:        417 :   GST_DEBUG_OBJECT (basesrc, "stopping source");
    2803                 :            : 
    2804                 :        417 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    2805         [ +  + ]:        417 :   if (bclass->stop)
    2806                 :        407 :     result = bclass->stop (basesrc);
    2807                 :            : 
    2808         [ +  - ]:        417 :   if (result)
    2809                 :        417 :     GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
    2810                 :            : 
    2811                 :        417 :   return result;
    2812                 :            : }
    2813                 :            : 
    2814                 :            : /* start or stop flushing dataprocessing
    2815                 :            :  */
    2816                 :            : static gboolean
    2817                 :       1636 : gst_base_src_set_flushing (GstBaseSrc * basesrc,
    2818                 :            :     gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing)
    2819                 :            : {
    2820                 :            :   GstBaseSrcClass *bclass;
    2821                 :            : 
    2822                 :       1636 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    2823                 :            : 
    2824 [ +  + ][ +  + ]:       1636 :   if (flushing && unlock) {
    2825                 :            :     /* unlock any subclasses, we need to do this before grabbing the
    2826                 :            :      * LIVE_LOCK since we hold this lock before going into ::create. We pass an
    2827                 :            :      * unlock to the params because of backwards compat (see seek handler)*/
    2828         [ +  + ]:        414 :     if (bclass->unlock)
    2829                 :         10 :       bclass->unlock (basesrc);
    2830                 :            :   }
    2831                 :            : 
    2832                 :            :   /* the live lock is released when we are blocked, waiting for playing or
    2833                 :            :    * when we sync to the clock. */
    2834                 :       1636 :   GST_LIVE_LOCK (basesrc);
    2835         [ +  + ]:       1636 :   if (playing)
    2836                 :        407 :     *playing = basesrc->live_running;
    2837                 :       1636 :   basesrc->priv->flushing = flushing;
    2838         [ +  + ]:       1636 :   if (flushing) {
    2839                 :            :     /* if we are locked in the live lock, signal it to make it flush */
    2840                 :        818 :     basesrc->live_running = TRUE;
    2841                 :            : 
    2842                 :            :     /* clear pending EOS if any */
    2843                 :        818 :     g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
    2844                 :            : 
    2845                 :            :     /* step 1, now that we have the LIVE lock, clear our unlock request */
    2846         [ +  + ]:        818 :     if (bclass->unlock_stop)
    2847                 :         20 :       bclass->unlock_stop (basesrc);
    2848                 :            : 
    2849                 :            :     /* step 2, unblock clock sync (if any) or any other blocking thing */
    2850         [ -  + ]:        818 :     if (basesrc->clock_id)
    2851                 :          0 :       gst_clock_id_unschedule (basesrc->clock_id);
    2852                 :            :   } else {
    2853                 :            :     /* signal the live source that it can start playing */
    2854                 :        818 :     basesrc->live_running = live_play;
    2855                 :            :   }
    2856                 :       1636 :   GST_LIVE_SIGNAL (basesrc);
    2857                 :       1636 :   GST_LIVE_UNLOCK (basesrc);
    2858                 :            : 
    2859                 :       1636 :   return TRUE;
    2860                 :            : }
    2861                 :            : 
    2862                 :            : /* the purpose of this function is to make sure that a live source blocks in the
    2863                 :            :  * LIVE lock or leaves the LIVE lock and continues playing. */
    2864                 :            : static gboolean
    2865                 :         16 : gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play)
    2866                 :            : {
    2867                 :            :   GstBaseSrcClass *bclass;
    2868                 :            : 
    2869                 :         16 :   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
    2870                 :            : 
    2871                 :            :   /* unlock subclasses locked in ::create, we only do this when we stop playing. */
    2872         [ +  + ]:         16 :   if (!live_play) {
    2873         [ -  + ]:          8 :     GST_DEBUG_OBJECT (basesrc, "unlock");
    2874         [ -  + ]:          8 :     if (bclass->unlock)
    2875                 :          0 :       bclass->unlock (basesrc);
    2876                 :            :   }
    2877                 :            : 
    2878                 :            :   /* we are now able to grab the LIVE lock, when we get it, we can be
    2879                 :            :    * waiting for PLAYING while blocked in the LIVE cond or we can be waiting
    2880                 :            :    * for the clock. */
    2881                 :         16 :   GST_LIVE_LOCK (basesrc);
    2882         [ -  + ]:         16 :   GST_DEBUG_OBJECT (basesrc, "unschedule clock");
    2883                 :            : 
    2884                 :            :   /* unblock clock sync (if any) */
    2885         [ -  + ]:         16 :   if (basesrc->clock_id)
    2886                 :          0 :     gst_clock_id_unschedule (basesrc->clock_id);
    2887                 :            : 
    2888                 :            :   /* configure what to do when we get to the LIVE lock. */
    2889         [ -  + ]:         16 :   GST_DEBUG_OBJECT (basesrc, "live running %d", live_play);
    2890                 :         16 :   basesrc->live_running = live_play;
    2891                 :            : 
    2892         [ +  + ]:         16 :   if (live_play) {
    2893                 :            :     gboolean start;
    2894                 :            : 
    2895                 :            :     /* clear our unlock request when going to PLAYING */
    2896         [ -  + ]:          8 :     GST_DEBUG_OBJECT (basesrc, "unlock stop");
    2897         [ -  + ]:          8 :     if (bclass->unlock_stop)
    2898                 :          0 :       bclass->unlock_stop (basesrc);
    2899                 :            : 
    2900                 :            :     /* for live sources we restart the timestamp correction */
    2901                 :          8 :     basesrc->priv->latency = -1;
    2902                 :            :     /* have to restart the task in case it stopped because of the unlock when
    2903                 :            :      * we went to PAUSED. Only do this if we operating in push mode. */
    2904                 :          8 :     GST_OBJECT_LOCK (basesrc->srcpad);
    2905                 :          8 :     start = (GST_PAD_ACTIVATE_MODE (basesrc->srcpad) == GST_ACTIVATE_PUSH);
    2906                 :          8 :     GST_OBJECT_UNLOCK (basesrc->srcpad);
    2907         [ +  - ]:          8 :     if (start)
    2908                 :          8 :       gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop,
    2909                 :          8 :           basesrc->srcpad);
    2910         [ -  + ]:          8 :     GST_DEBUG_OBJECT (basesrc, "signal");
    2911                 :          8 :     GST_LIVE_SIGNAL (basesrc);
    2912                 :            :   }
    2913                 :         16 :   GST_LIVE_UNLOCK (basesrc);
    2914                 :            : 
    2915                 :         16 :   return TRUE;
    2916                 :            : }
    2917                 :            : 
    2918                 :            : static gboolean
    2919                 :        828 : gst_base_src_activate_push (GstPad * pad, gboolean active)
    2920                 :            : {
    2921                 :            :   GstBaseSrc *basesrc;
    2922                 :            :   GstEvent *event;
    2923                 :            : 
    2924                 :        828 :   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
    2925                 :            : 
    2926                 :            :   /* prepare subclass first */
    2927         [ +  + ]:        828 :   if (active) {
    2928         [ -  + ]:        424 :     GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
    2929                 :            : 
    2930         [ +  + ]:        424 :     if (G_UNLIKELY (!basesrc->can_activate_push))
    2931                 :          1 :       goto no_push_activation;
    2932                 :            : 
    2933         [ +  + ]:        423 :     if (G_UNLIKELY (!gst_base_src_start (basesrc)))
    2934                 :         19 :       goto error_start;
    2935                 :            : 
    2936                 :        404 :     basesrc->priv->last_sent_eos = FALSE;
    2937                 :        404 :     basesrc->priv->discont = TRUE;
    2938                 :        404 :     gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
    2939                 :            : 
    2940                 :            :     /* do initial seek, which will start the task */
    2941                 :        404 :     GST_OBJECT_LOCK (basesrc);
    2942                 :        404 :     event = basesrc->data.ABI.pending_seek;
    2943                 :        404 :     basesrc->data.ABI.pending_seek = NULL;
    2944                 :        404 :     GST_OBJECT_UNLOCK (basesrc);
    2945                 :            : 
    2946                 :            :     /* no need to unlock anything, the task is certainly
    2947                 :            :      * not running here. The perform seek code will start the task when
    2948                 :            :      * finished. */
    2949         [ -  + ]:        404 :     if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
    2950                 :          0 :       goto seek_failed;
    2951                 :            : 
    2952         [ +  + ]:        404 :     if (event)
    2953                 :          1 :       gst_event_unref (event);
    2954                 :            :   } else {
    2955         [ -  + ]:        404 :     GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
    2956                 :            :     /* flush all */
    2957                 :        404 :     gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
    2958                 :            :     /* stop the task */
    2959                 :        404 :     gst_pad_stop_task (pad);
    2960                 :            :     /* now we can stop the source */
    2961         [ -  + ]:        404 :     if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
    2962                 :          0 :       goto error_stop;
    2963                 :            :   }
    2964                 :        808 :   return TRUE;
    2965                 :            : 
    2966                 :            :   /* ERRORS */
    2967                 :            : no_push_activation:
    2968                 :            :   {
    2969         [ -  + ]:          1 :     GST_WARNING_OBJECT (basesrc, "Subclass disabled push-mode activation");
    2970                 :          1 :     return FALSE;
    2971                 :            :   }
    2972                 :            : error_start:
    2973                 :            :   {
    2974         [ -  + ]:         19 :     GST_WARNING_OBJECT (basesrc, "Failed to start in push mode");
    2975                 :         19 :     return FALSE;
    2976                 :            :   }
    2977                 :            : seek_failed:
    2978                 :            :   {
    2979         [ #  # ]:          0 :     GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
    2980                 :            :     /* flush all */
    2981                 :          0 :     gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
    2982                 :            :     /* stop the task */
    2983                 :          0 :     gst_pad_stop_task (pad);
    2984                 :            :     /* Stop the basesrc */
    2985                 :          0 :     gst_base_src_stop (basesrc);
    2986         [ #  # ]:          0 :     if (event)
    2987                 :          0 :       gst_event_unref (event);
    2988                 :          0 :     return FALSE;
    2989                 :            :   }
    2990                 :            : error_stop:
    2991                 :            :   {
    2992         [ #  # ]:          0 :     GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode");
    2993                 :        828 :     return FALSE;
    2994                 :            :   }
    2995                 :            : }
    2996                 :            : 
    2997                 :            : static gboolean
    2998                 :         14 : gst_base_src_activate_pull (GstPad * pad, gboolean active)
    2999                 :            : {
    3000                 :            :   GstBaseSrc *basesrc;
    3001                 :            : 
    3002                 :         14 :   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
    3003                 :            : 
    3004                 :            :   /* prepare subclass first */
    3005         [ +  + ]:         14 :   if (active) {
    3006         [ -  + ]:          7 :     GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
    3007         [ -  + ]:          7 :     if (G_UNLIKELY (!gst_base_src_start (basesrc)))
    3008                 :          0 :       goto error_start;
    3009                 :            : 
    3010                 :            :     /* if not random_access, we cannot operate in pull mode for now */
    3011         [ -  + ]:          7 :     if (G_UNLIKELY (!gst_base_src_check_get_range (basesrc)))
    3012                 :          0 :       goto no_get_range;
    3013                 :            : 
    3014                 :            :     /* stop flushing now but for live sources, still block in the LIVE lock when
    3015                 :            :      * we are not yet PLAYING */
    3016                 :          7 :     gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
    3017                 :            :   } else {
    3018         [ -  + ]:          7 :     GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
    3019                 :            :     /* flush all, there is no task to stop */
    3020                 :          7 :     gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
    3021                 :            : 
    3022                 :            :     /* don't send EOS when going from PAUSED => READY when in pull mode */
    3023                 :          7 :     basesrc->priv->last_sent_eos = TRUE;
    3024                 :            : 
    3025         [ -  + ]:          7 :     if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
    3026                 :          0 :       goto error_stop;
    3027                 :            :   }
    3028                 :         14 :   return TRUE;
    3029                 :            : 
    3030                 :            :   /* ERRORS */
    3031                 :            : error_start:
    3032                 :            :   {
    3033         [ #  # ]:          0 :     GST_ERROR_OBJECT (basesrc, "Failed to start in pull mode");
    3034                 :          0 :     return FALSE;
    3035                 :            :   }
    3036                 :            : no_get_range:
    3037                 :            :   {
    3038         [ #  # ]:          0 :     GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
    3039                 :          0 :     gst_base_src_stop (basesrc);
    3040                 :          0 :     return FALSE;
    3041                 :            :   }
    3042                 :            : error_stop:
    3043                 :            :   {
    3044         [ #  # ]:          0 :     GST_ERROR_OBJECT (basesrc, "Failed to stop in pull mode");
    3045                 :         14 :     return FALSE;
    3046                 :            :   }
    3047                 :            : }
    3048                 :            : 
    3049                 :            : static GstStateChangeReturn
    3050                 :       1529 : gst_base_src_change_state (GstElement * element, GstStateChange transition)
    3051                 :            : {
    3052                 :            :   GstBaseSrc *basesrc;
    3053                 :            :   GstStateChangeReturn result;
    3054                 :       1529 :   gboolean no_preroll = FALSE;
    3055                 :            : 
    3056                 :       1529 :   basesrc = GST_BASE_SRC (element);
    3057                 :            : 
    3058   [ +  +  +  + ]:       1529 :   switch (transition) {
    3059                 :            :     case GST_STATE_CHANGE_NULL_TO_READY:
    3060                 :        217 :       break;
    3061                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
    3062                 :        431 :       no_preroll = gst_base_src_is_live (basesrc);
    3063                 :        431 :       break;
    3064                 :            :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
    3065         [ -  + ]:        113 :       GST_DEBUG_OBJECT (basesrc, "PAUSED->PLAYING");
    3066         [ +  + ]:        113 :       if (gst_base_src_is_live (basesrc)) {
    3067                 :            :         /* now we can start playback */
    3068                 :          8 :         gst_base_src_set_playing (basesrc, TRUE);
    3069                 :            :       }
    3070                 :        113 :       break;
    3071                 :            :     default:
    3072                 :        768 :       break;
    3073                 :            :   }
    3074                 :            : 
    3075         [ +  + ]:       1529 :   if ((result =
    3076                 :       1529 :           GST_ELEMENT_CLASS (parent_class)->change_state (element,
    3077                 :            :               transition)) == GST_STATE_CHANGE_FAILURE)
    3078                 :         20 :     goto failure;
    3079                 :            : 
    3080   [ +  +  +  + ]:       1509 :   switch (transition) {
    3081                 :            :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
    3082         [ -  + ]:        113 :       GST_DEBUG_OBJECT (basesrc, "PLAYING->PAUSED");
    3083         [ +  + ]:        113 :       if (gst_base_src_is_live (basesrc)) {
    3084                 :            :         /* make sure we block in the live lock in PAUSED */
    3085                 :          8 :         gst_base_src_set_playing (basesrc, FALSE);
    3086                 :          8 :         no_preroll = TRUE;
    3087                 :            :       }
    3088                 :        113 :       break;
    3089                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
    3090                 :            :     {
    3091                 :            :       GstEvent **event_p, *event;
    3092                 :            : 
    3093                 :            :       /* we don't need to unblock anything here, the pad deactivation code
    3094                 :            :        * already did this */
    3095                 :            : 
    3096                 :            :       /* FIXME, deprecate this behaviour, it is very dangerous.
    3097                 :            :        * the prefered way of sending EOS downstream is by sending
    3098                 :            :        * the EOS event to the element */
    3099         [ +  + ]:        411 :       if (!basesrc->priv->last_sent_eos) {
    3100         [ -  + ]:        377 :         GST_DEBUG_OBJECT (basesrc, "Sending EOS event");
    3101                 :        377 :         event = gst_event_new_eos ();
    3102                 :        377 :         gst_event_set_seqnum (event, basesrc->priv->seqnum);
    3103                 :        377 :         gst_pad_push_event (basesrc->srcpad, event);
    3104                 :        377 :         basesrc->priv->last_sent_eos = TRUE;
    3105                 :            :       }
    3106                 :        411 :       g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
    3107                 :        411 :       event_p = &basesrc->data.ABI.pending_seek;
    3108                 :        411 :       gst_event_replace (event_p, NULL);
    3109                 :        411 :       event_p = &basesrc->priv->close_segment;
    3110                 :        411 :       gst_event_replace (event_p, NULL);
    3111                 :        411 :       event_p = &basesrc->priv->start_segment;
    3112                 :        411 :       gst_event_replace (event_p, NULL);
    3113                 :        411 :       break;
    3114                 :            :     }
    3115                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
    3116                 :        216 :       break;
    3117                 :            :     default:
    3118                 :        769 :       break;
    3119                 :            :   }
    3120                 :            : 
    3121 [ +  + ][ +  - ]:       1509 :   if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
    3122                 :         20 :     result = GST_STATE_CHANGE_NO_PREROLL;
    3123                 :            : 
    3124                 :       1509 :   return result;
    3125                 :            : 
    3126                 :            :   /* ERRORS */
    3127                 :            : failure:
    3128                 :            :   {
    3129         [ -  + ]:         20 :     GST_DEBUG_OBJECT (basesrc, "parent failed state change");
    3130                 :       1529 :     return result;
    3131                 :            :   }
    3132                 :            : }

Generated by: LCOV version 1.9