LCOV - code coverage report
Current view: top level - gst/mpegdemux - gstmpegdemux.c (source / functions) Hit Total Coverage
Test: GStreamer Bad Plug-ins 0.10.21.1 Lines: 148 1303 11.4 %
Date: 2011-03-25 Functions: 13 44 29.5 %
Branches: 36 1146 3.1 %

           Branch data     Line data    Source code
       1                 :            :  /*
       2                 :            :   * This library is licensed under 2 different licenses and you
       3                 :            :   * can choose to use it under the terms of either one of them. The
       4                 :            :   * two licenses are the MPL 1.1 and the LGPL.
       5                 :            :   *
       6                 :            :   * MPL:
       7                 :            :   *
       8                 :            :   * The contents of this file are subject to the Mozilla Public License
       9                 :            :   * Version 1.1 (the "License"); you may not use this file except in
      10                 :            :   * compliance with the License. You may obtain a copy of the License at
      11                 :            :   * http://www.mozilla.org/MPL/.
      12                 :            :   *
      13                 :            :   * Software distributed under the License is distributed on an "AS IS"
      14                 :            :   * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
      15                 :            :   * License for the specific language governing rights and limitations
      16                 :            :   * under the License.
      17                 :            :   *
      18                 :            :   * LGPL:
      19                 :            :   *
      20                 :            :   * This library is free software; you can redistribute it and/or
      21                 :            :   * modify it under the terms of the GNU Library General Public
      22                 :            :   * License as published by the Free Software Foundation; either
      23                 :            :   * version 2 of the License, or (at your option) any later version.
      24                 :            :   *
      25                 :            :   * This library is distributed in the hope that it will be useful,
      26                 :            :   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      27                 :            :   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      28                 :            :   * Library General Public License for more details.
      29                 :            :   *
      30                 :            :   * You should have received a copy of the GNU Library General Public
      31                 :            :   * License along with this library; if not, write to the
      32                 :            :   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      33                 :            :   * Boston, MA 02111-1307, USA.
      34                 :            :   *
      35                 :            :   * The Original Code is Fluendo MPEG Demuxer plugin.
      36                 :            :   *
      37                 :            :   * The Initial Developer of the Original Code is Fluendo, S.L.
      38                 :            :   * Portions created by Fluendo, S.L. are Copyright (C) 2005
      39                 :            :   * Fluendo, S.L. All Rights Reserved.
      40                 :            :   *
      41                 :            :   * Contributor(s): Wim Taymans <wim@fluendo.com>
      42                 :            :   *                 Jan Schmidt <thaytan@noraisin.net>
      43                 :            :   */
      44                 :            : 
      45                 :            : #ifdef HAVE_CONFIG_H
      46                 :            : #include "config.h"
      47                 :            : #endif
      48                 :            : 
      49                 :            : #include <string.h>
      50                 :            : 
      51                 :            : #include "gstmpegdefs.h"
      52                 :            : #include "gstmpegdemux.h"
      53                 :            : 
      54                 :            : #define MAX_DVD_AUDIO_STREAMS       8
      55                 :            : #define MAX_DVD_SUBPICTURE_STREAMS  32
      56                 :            : #define BLOCK_SZ                    32768
      57                 :            : #define SCAN_SCR_SZ                 12
      58                 :            : #define SCAN_PTS_SZ                 80
      59                 :            : 
      60                 :            : #define SEGMENT_THRESHOLD (300*GST_MSECOND)
      61                 :            : #define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND)
      62                 :            : 
      63                 :            : typedef enum
      64                 :            : {
      65                 :            :   SCAN_SCR,
      66                 :            :   SCAN_DTS,
      67                 :            :   SCAN_PTS
      68                 :            : } SCAN_MODE;
      69                 :            : 
      70                 :            : /* We clamp scr delta with 0 so negative bytes won't be possible */
      71                 :            : #define GSTTIME_TO_BYTES(time) \
      72                 :            :   ((time != -1) ? gst_util_uint64_scale (MAX(0,(gint64) (GSTTIME_TO_MPEGTIME(time))), demux->scr_rate_n, demux->scr_rate_d) : -1)
      73                 :            : #define BYTES_TO_GSTTIME(bytes) ((bytes != -1) ? MPEGTIME_TO_GSTTIME(gst_util_uint64_scale (bytes, demux->scr_rate_d, demux->scr_rate_n)) : -1)
      74                 :            : 
      75                 :            : #define ADAPTER_OFFSET_FLUSH(_bytes_) demux->adapter_offset += (_bytes_)
      76                 :            : 
      77                 :            : GST_DEBUG_CATEGORY_STATIC (gstflupsdemux_debug);
      78                 :            : #define GST_CAT_DEFAULT (gstflupsdemux_debug)
      79                 :            : 
      80                 :            : /* MPEG2Demux signals and args */
      81                 :            : enum
      82                 :            : {
      83                 :            :   /* FILL ME */
      84                 :            :   LAST_SIGNAL
      85                 :            : };
      86                 :            : 
      87                 :            : enum
      88                 :            : {
      89                 :            :   ARG_0,
      90                 :            :   ARG_SYNC,
      91                 :            :   /* FILL ME */
      92                 :            : };
      93                 :            : 
      94                 :            : static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
      95                 :            :     GST_PAD_SINK,
      96                 :            :     GST_PAD_ALWAYS,
      97                 :            :     GST_STATIC_CAPS ("video/mpeg, "
      98                 :            :         "mpegversion = (int) { 1, 2 }, "
      99                 :            :         "systemstream = (boolean) TRUE;" "video/x-cdxa")
     100                 :            :     );
     101                 :            : 
     102                 :            : static GstStaticPadTemplate video_template =
     103                 :            :     GST_STATIC_PAD_TEMPLATE ("video_%02x",
     104                 :            :     GST_PAD_SRC,
     105                 :            :     GST_PAD_SOMETIMES,
     106                 :            :     GST_STATIC_CAPS ("video/mpeg, "
     107                 :            :         "mpegversion = (int) { 1, 2, 4 }, " "systemstream = (boolean) FALSE;"
     108                 :            :         "video/x-h264")
     109                 :            :     );
     110                 :            : 
     111                 :            : static GstStaticPadTemplate audio_template =
     112                 :            :     GST_STATIC_PAD_TEMPLATE ("audio_%02x",
     113                 :            :     GST_PAD_SRC,
     114                 :            :     GST_PAD_SOMETIMES,
     115                 :            :     GST_STATIC_CAPS ("audio/mpeg, "
     116                 :            :         "mpegversion = (int) { 1, 4 };"
     117                 :            :         "audio/x-private1-lpcm; "
     118                 :            :         "audio/x-private1-ac3;" "audio/x-private1-dts;" "audio/ac3")
     119                 :            :     );
     120                 :            : 
     121                 :            : static GstStaticPadTemplate subpicture_template =
     122                 :            : GST_STATIC_PAD_TEMPLATE ("subpicture_%02x",
     123                 :            :     GST_PAD_SRC,
     124                 :            :     GST_PAD_SOMETIMES,
     125                 :            :     GST_STATIC_CAPS ("video/x-dvd-subpicture")
     126                 :            :     );
     127                 :            : 
     128                 :            : static GstStaticPadTemplate private_template =
     129                 :            : GST_STATIC_PAD_TEMPLATE ("private_%d",
     130                 :            :     GST_PAD_SRC,
     131                 :            :     GST_PAD_SOMETIMES,
     132                 :            :     GST_STATIC_CAPS_ANY);
     133                 :            : 
     134                 :            : static void gst_flups_demux_base_init (GstFluPSDemuxClass * klass);
     135                 :            : static void gst_flups_demux_class_init (GstFluPSDemuxClass * klass);
     136                 :            : static void gst_flups_demux_init (GstFluPSDemux * demux);
     137                 :            : static void gst_flups_demux_finalize (GstFluPSDemux * demux);
     138                 :            : static void gst_flups_demux_reset (GstFluPSDemux * demux);
     139                 :            : 
     140                 :            : static gboolean gst_flups_demux_sink_event (GstPad * pad, GstEvent * event);
     141                 :            : static GstFlowReturn gst_flups_demux_chain (GstPad * pad, GstBuffer * buffer);
     142                 :            : static gboolean gst_flups_demux_sink_activate (GstPad * sinkpad);
     143                 :            : static gboolean gst_flups_demux_sink_activate_push (GstPad * sinkpad,
     144                 :            :     gboolean active);
     145                 :            : static gboolean gst_flups_demux_sink_activate_pull (GstPad * sinkpad,
     146                 :            :     gboolean active);
     147                 :            : static void gst_flups_demux_loop (GstPad * pad);
     148                 :            : 
     149                 :            : static gboolean gst_flups_demux_src_event (GstPad * pad, GstEvent * event);
     150                 :            : static gboolean gst_flups_demux_src_query (GstPad * pad, GstQuery * query);
     151                 :            : static const GstQueryType *gst_flups_demux_src_query_type (GstPad * pad);
     152                 :            : 
     153                 :            : static GstStateChangeReturn gst_flups_demux_change_state (GstElement * element,
     154                 :            :     GstStateChange transition);
     155                 :            : 
     156                 :            : static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux,
     157                 :            :     guint64 * pos, SCAN_MODE mode, guint64 * rts);
     158                 :            : static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux,
     159                 :            :     guint64 * pos, SCAN_MODE mode, guint64 * rts);
     160                 :            : 
     161                 :            : static inline void gst_flups_demux_send_segment_updates (GstFluPSDemux * demux,
     162                 :            :     GstClockTime new_time);
     163                 :            : static inline void gst_flups_demux_clear_times (GstFluPSDemux * demux);
     164                 :            : 
     165                 :            : static GstElementClass *parent_class = NULL;
     166                 :            : 
     167                 :            : /*static guint gst_flups_demux_signals[LAST_SIGNAL] = { 0 };*/
     168                 :            : 
     169                 :            : GType
     170                 :         54 : gst_flups_demux_get_type (void)
     171                 :            : {
     172                 :            :   static GType flups_demux_type = 0;
     173                 :            : 
     174         [ +  + ]:         54 :   if (!flups_demux_type) {
     175                 :            :     static const GTypeInfo flups_demux_info = {
     176                 :            :       sizeof (GstFluPSDemuxClass),
     177                 :            :       (GBaseInitFunc) gst_flups_demux_base_init,
     178                 :            :       NULL,
     179                 :            :       (GClassInitFunc) gst_flups_demux_class_init,
     180                 :            :       NULL,
     181                 :            :       NULL,
     182                 :            :       sizeof (GstFluPSDemux),
     183                 :            :       0,
     184                 :            :       (GInstanceInitFunc) gst_flups_demux_init,
     185                 :            :     };
     186                 :            : 
     187                 :          6 :     flups_demux_type =
     188                 :          6 :         g_type_register_static (GST_TYPE_ELEMENT, "GstMpegPSDemux",
     189                 :            :         &flups_demux_info, 0);
     190                 :            : 
     191         [ +  - ]:          6 :     GST_DEBUG_CATEGORY_INIT (gstflupsdemux_debug, "mpegpsdemux", 0,
     192                 :            :         "MPEG program stream demultiplexer element");
     193                 :            :   }
     194                 :            : 
     195                 :         54 :   return flups_demux_type;
     196                 :            : }
     197                 :            : 
     198                 :            : static void
     199                 :          6 : gst_flups_demux_base_init (GstFluPSDemuxClass * klass)
     200                 :            : {
     201                 :          6 :   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
     202                 :            : 
     203                 :          6 :   klass->sink_template = gst_static_pad_template_get (&sink_template);
     204                 :          6 :   klass->video_template = gst_static_pad_template_get (&video_template);
     205                 :          6 :   klass->audio_template = gst_static_pad_template_get (&audio_template);
     206                 :          6 :   klass->subpicture_template =
     207                 :          6 :       gst_static_pad_template_get (&subpicture_template);
     208                 :          6 :   klass->private_template = gst_static_pad_template_get (&private_template);
     209                 :            : 
     210                 :          6 :   gst_element_class_add_pad_template (element_class, klass->video_template);
     211                 :          6 :   gst_element_class_add_pad_template (element_class, klass->audio_template);
     212                 :          6 :   gst_element_class_add_pad_template (element_class,
     213                 :            :       klass->subpicture_template);
     214                 :          6 :   gst_element_class_add_pad_template (element_class, klass->private_template);
     215                 :          6 :   gst_element_class_add_pad_template (element_class, klass->sink_template);
     216                 :            : 
     217                 :          6 :   gst_element_class_set_details_simple (element_class,
     218                 :            :       "The Fluendo MPEG Program Stream Demuxer", "Codec/Demuxer",
     219                 :            :       "Demultiplexes MPEG Program Streams", "Wim Taymans <wim@fluendo.com>");
     220                 :          6 : }
     221                 :            : 
     222                 :            : static void
     223                 :          6 : gst_flups_demux_class_init (GstFluPSDemuxClass * klass)
     224                 :            : {
     225                 :            :   GObjectClass *gobject_class;
     226                 :            :   GstElementClass *gstelement_class;
     227                 :            : 
     228                 :          6 :   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
     229                 :            : 
     230                 :          6 :   gobject_class = (GObjectClass *) klass;
     231                 :          6 :   gstelement_class = (GstElementClass *) klass;
     232                 :            : 
     233                 :          6 :   gobject_class->finalize = (GObjectFinalizeFunc) gst_flups_demux_finalize;
     234                 :            : 
     235                 :          6 :   gstelement_class->change_state = gst_flups_demux_change_state;
     236                 :          6 : }
     237                 :            : 
     238                 :            : static void
     239                 :          3 : gst_flups_demux_init (GstFluPSDemux * demux)
     240                 :            : {
     241                 :          3 :   GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux);
     242                 :            : 
     243                 :          3 :   demux->sinkpad = gst_pad_new_from_template (klass->sink_template, "sink");
     244                 :          3 :   gst_pad_set_event_function (demux->sinkpad,
     245                 :          3 :       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_event));
     246                 :          3 :   gst_pad_set_chain_function (demux->sinkpad,
     247                 :          3 :       GST_DEBUG_FUNCPTR (gst_flups_demux_chain));
     248                 :          3 :   gst_pad_set_activate_function (demux->sinkpad,
     249                 :          3 :       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate));
     250                 :          3 :   gst_pad_set_activatepull_function (demux->sinkpad,
     251                 :          3 :       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate_pull));
     252                 :          3 :   gst_pad_set_activatepush_function (demux->sinkpad,
     253                 :          3 :       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate_push));
     254                 :            : 
     255                 :          3 :   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
     256                 :            : 
     257                 :          3 :   demux->streams =
     258                 :          3 :       g_malloc0 (sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
     259                 :          3 :   demux->streams_found =
     260                 :          3 :       g_malloc0 (sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
     261                 :          3 :   demux->found_count = 0;
     262                 :            : 
     263                 :          3 : }
     264                 :            : 
     265                 :            : static void
     266                 :          3 : gst_flups_demux_finalize (GstFluPSDemux * demux)
     267                 :            : {
     268                 :          3 :   gst_flups_demux_reset (demux);
     269                 :          3 :   g_free (demux->streams);
     270                 :          3 :   g_free (demux->streams_found);
     271                 :            : 
     272                 :          3 :   G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (demux));
     273                 :          3 : }
     274                 :            : 
     275                 :            : static void
     276                 :         10 : gst_flups_demux_reset (GstFluPSDemux * demux)
     277                 :            : {
     278                 :            :   /* Clean up the streams and pads we allocated */
     279                 :            :   gint i;
     280                 :            :   GstEvent **p_ev;
     281                 :            : 
     282         [ +  + ]:       2570 :   for (i = 0; i < GST_FLUPS_DEMUX_MAX_STREAMS; i++) {
     283                 :       2560 :     GstFluPSStream *stream = demux->streams[i];
     284                 :            : 
     285         [ -  + ]:       2560 :     if (stream != NULL) {
     286         [ #  # ]:          0 :       if (stream->pad)
     287                 :          0 :         gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
     288                 :            : 
     289                 :          0 :       g_free (stream);
     290                 :          0 :       demux->streams[i] = NULL;
     291                 :            :     }
     292                 :            :   }
     293                 :         10 :   memset (demux->streams_found, 0,
     294                 :            :       sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
     295                 :         10 :   demux->found_count = 0;
     296                 :         10 :   p_ev = &demux->lang_codes;
     297                 :            : 
     298                 :         10 :   gst_event_replace (p_ev, NULL);
     299                 :         10 : }
     300                 :            : 
     301                 :            : static GstFluPSStream *
     302                 :          0 : gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type)
     303                 :            : {
     304                 :            :   GstFluPSStream *stream;
     305                 :            :   GstPadTemplate *template;
     306                 :            :   gchar *name;
     307                 :          0 :   GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux);
     308                 :            :   GstCaps *caps;
     309                 :          0 :   GstClockTime threshold = SEGMENT_THRESHOLD;
     310                 :            : 
     311                 :          0 :   name = NULL;
     312                 :          0 :   template = NULL;
     313                 :          0 :   caps = NULL;
     314                 :            : 
     315         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "create stream id 0x%02x, type 0x%02x", id,
     316                 :            :       stream_type);
     317                 :            : 
     318   [ #  #  #  #  :          0 :   switch (stream_type) {
          #  #  #  #  #  
                   #  # ]
     319                 :            :     case ST_VIDEO_MPEG1:
     320                 :            :     case ST_VIDEO_MPEG2:
     321                 :            :     case ST_VIDEO_MPEG4:
     322                 :            :     case ST_GST_VIDEO_MPEG1_OR_2:
     323                 :            :     {
     324                 :          0 :       gint mpeg_version = 1;
     325 [ #  # ][ #  # ]:          0 :       if (stream_type == ST_VIDEO_MPEG2 ||
     326         [ #  # ]:          0 :           (stream_type == ST_GST_VIDEO_MPEG1_OR_2 && demux->is_mpeg2_pack)) {
     327                 :          0 :         mpeg_version = 2;
     328                 :            :       }
     329         [ #  # ]:          0 :       if (stream_type == ST_VIDEO_MPEG4) {
     330                 :          0 :         mpeg_version = 4;
     331                 :            :       }
     332                 :            : 
     333                 :          0 :       template = klass->video_template;
     334                 :          0 :       name = g_strdup_printf ("video_%02x", id);
     335                 :          0 :       caps = gst_caps_new_simple ("video/mpeg",
     336                 :            :           "mpegversion", G_TYPE_INT, mpeg_version,
     337                 :            :           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
     338                 :          0 :       threshold = VIDEO_SEGMENT_THRESHOLD;
     339                 :          0 :       break;
     340                 :            :     }
     341                 :            :     case ST_AUDIO_MPEG1:
     342                 :            :     case ST_AUDIO_MPEG2:
     343                 :          0 :       template = klass->audio_template;
     344                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     345                 :          0 :       caps = gst_caps_new_simple ("audio/mpeg",
     346                 :            :           "mpegversion", G_TYPE_INT, 1, NULL);
     347                 :          0 :       break;
     348                 :            :     case ST_PRIVATE_SECTIONS:
     349                 :            :     case ST_PRIVATE_DATA:
     350                 :            :     case ST_MHEG:
     351                 :            :     case ST_DSMCC:
     352                 :          0 :       break;
     353                 :            :     case ST_AUDIO_AAC:
     354                 :          0 :       template = klass->audio_template;
     355                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     356                 :          0 :       caps = gst_caps_new_simple ("audio/mpeg",
     357                 :            :           "mpegversion", G_TYPE_INT, 4, NULL);
     358                 :          0 :       break;
     359                 :            :     case ST_VIDEO_H264:
     360                 :          0 :       template = klass->video_template;
     361                 :          0 :       name = g_strdup_printf ("video_%02x", id);
     362                 :          0 :       caps = gst_caps_new_simple ("video/x-h264", NULL);
     363                 :          0 :       threshold = VIDEO_SEGMENT_THRESHOLD;
     364                 :          0 :       break;
     365                 :            :     case ST_PS_AUDIO_AC3:
     366                 :          0 :       template = klass->audio_template;
     367                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     368                 :          0 :       caps = gst_caps_new_simple ("audio/x-private1-ac3", NULL);
     369                 :          0 :       break;
     370                 :            :     case ST_PS_AUDIO_DTS:
     371                 :          0 :       template = klass->audio_template;
     372                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     373                 :          0 :       caps = gst_caps_new_simple ("audio/x-private1-dts", NULL);
     374                 :          0 :       break;
     375                 :            :     case ST_PS_AUDIO_LPCM:
     376                 :          0 :       template = klass->audio_template;
     377                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     378                 :          0 :       caps = gst_caps_new_simple ("audio/x-private1-lpcm", NULL);
     379                 :          0 :       break;
     380                 :            :     case ST_PS_DVD_SUBPICTURE:
     381                 :          0 :       template = klass->subpicture_template;
     382                 :          0 :       name = g_strdup_printf ("subpicture_%02x", id);
     383                 :          0 :       caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
     384                 :          0 :       break;
     385                 :            :     case ST_GST_AUDIO_RAWA52:
     386                 :          0 :       template = klass->audio_template;
     387                 :          0 :       name = g_strdup_printf ("audio_%02x", id);
     388                 :          0 :       caps = gst_caps_new_simple ("audio/ac3", NULL);
     389                 :          0 :       break;
     390                 :            :     default:
     391                 :          0 :       break;
     392                 :            :   }
     393                 :            : 
     394 [ #  # ][ #  # ]:          0 :   if (name == NULL || template == NULL || caps == NULL)
                 [ #  # ]
     395                 :          0 :     return NULL;
     396                 :            : 
     397                 :          0 :   stream = g_new0 (GstFluPSStream, 1);
     398                 :          0 :   stream->id = id;
     399                 :          0 :   stream->discont = TRUE;
     400                 :          0 :   stream->need_segment = TRUE;
     401                 :          0 :   stream->notlinked = FALSE;
     402                 :          0 :   stream->type = stream_type;
     403                 :          0 :   stream->pad = gst_pad_new_from_template (template, name);
     404                 :          0 :   stream->segment_thresh = threshold;
     405                 :          0 :   gst_pad_set_event_function (stream->pad,
     406                 :          0 :       GST_DEBUG_FUNCPTR (gst_flups_demux_src_event));
     407                 :          0 :   gst_pad_set_query_function (stream->pad,
     408                 :          0 :       GST_DEBUG_FUNCPTR (gst_flups_demux_src_query));
     409                 :          0 :   gst_pad_set_query_type_function (stream->pad,
     410                 :          0 :       GST_DEBUG_FUNCPTR (gst_flups_demux_src_query_type));
     411                 :          0 :   gst_pad_use_fixed_caps (stream->pad);
     412                 :          0 :   gst_pad_set_caps (stream->pad, caps);
     413                 :          0 :   gst_caps_unref (caps);
     414         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "create pad %s, caps %" GST_PTR_FORMAT, name, caps);
     415                 :          0 :   g_free (name);
     416                 :            : 
     417                 :            : 
     418                 :          0 :   return stream;
     419                 :            : }
     420                 :            : 
     421                 :            : static GstFluPSStream *
     422                 :          0 : gst_flups_demux_get_stream (GstFluPSDemux * demux, gint id, gint type)
     423                 :            : {
     424                 :          0 :   GstFluPSStream *stream = demux->streams[id];
     425                 :            : 
     426         [ #  # ]:          0 :   if (stream == NULL) {
     427         [ #  # ]:          0 :     if (!(stream = gst_flups_demux_create_stream (demux, id, type)))
     428                 :          0 :       goto unknown_stream;
     429                 :            : 
     430         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "adding pad for stream id 0x%02x type 0x%02x", id,
     431                 :            :         type);
     432                 :            : 
     433                 :          0 :     gst_pad_set_active (stream->pad, TRUE);
     434                 :          0 :     gst_element_add_pad (GST_ELEMENT (demux), stream->pad);
     435                 :            : 
     436                 :          0 :     demux->streams[id] = stream;
     437                 :          0 :     demux->streams_found[demux->found_count++] = stream;
     438                 :            :   }
     439                 :          0 :   return stream;
     440                 :            : 
     441                 :            :   /* ERROR */
     442                 :            : unknown_stream:
     443                 :            :   {
     444         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "unknown stream id 0x%02x type 0x%02x", id, type);
     445                 :          0 :     return NULL;
     446                 :            :   }
     447                 :            : }
     448                 :            : 
     449                 :            : static GstFlowReturn
     450                 :          0 : gst_flups_demux_send_data (GstFluPSDemux * demux, GstFluPSStream * stream,
     451                 :            :     GstBuffer * buf)
     452                 :            : {
     453                 :            :   GstFlowReturn result;
     454                 :            :   guint64 timestamp;
     455                 :            :   guint size;
     456                 :            : 
     457         [ #  # ]:          0 :   if (stream == NULL)
     458                 :          0 :     goto no_stream;
     459                 :            : 
     460                 :            :   /* timestamps */
     461         [ #  # ]:          0 :   if (G_UNLIKELY (demux->next_pts != G_MAXUINT64))
     462                 :          0 :     timestamp = MPEGTIME_TO_GSTTIME (demux->next_pts);
     463                 :            :   else
     464                 :          0 :     timestamp = GST_CLOCK_TIME_NONE;
     465                 :            : 
     466                 :            :   /* discont */
     467         [ #  # ]:          0 :   if (G_UNLIKELY (stream->need_segment)) {
     468                 :            :     gint64 time, start, stop;
     469                 :            :     GstEvent *newsegment;
     470                 :            : 
     471 [ #  # ][ #  # ]:          0 :     GST_DEBUG ("timestamp:%" GST_TIME_FORMAT " base_time %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     472                 :            :         " src_segment.start:%" GST_TIME_FORMAT " .stop:%" GST_TIME_FORMAT,
     473                 :            :         GST_TIME_ARGS (timestamp), GST_TIME_ARGS (demux->base_time),
     474                 :            :         GST_TIME_ARGS (demux->src_segment.start),
     475                 :            :         GST_TIME_ARGS (demux->src_segment.stop));
     476                 :            : 
     477 [ #  # ][ #  # ]:          0 :     if (GST_CLOCK_TIME_IS_VALID (demux->base_time) &&
     478                 :          0 :         GST_CLOCK_TIME_IS_VALID (demux->src_segment.start))
     479                 :          0 :       start = demux->base_time + demux->src_segment.start;
     480                 :            :     else
     481                 :          0 :       start = 0;
     482                 :            : 
     483 [ #  # ][ #  # ]:          0 :     if (GST_CLOCK_TIME_IS_VALID (demux->src_segment.stop) &&
     484                 :          0 :         GST_CLOCK_TIME_IS_VALID (demux->base_time))
     485                 :          0 :       stop = demux->base_time + demux->src_segment.stop;
     486                 :            :     else
     487                 :          0 :       stop = -1;
     488                 :            : 
     489         [ #  # ]:          0 :     if (timestamp != GST_CLOCK_TIME_NONE) {
     490         [ #  # ]:          0 :       if (demux->src_segment.rate > 0) {
     491         [ #  # ]:          0 :         if (GST_CLOCK_DIFF (start, timestamp) > GST_SECOND)
     492                 :          0 :           start = timestamp;
     493                 :            :       } else {
     494         [ #  # ]:          0 :         if (GST_CLOCK_DIFF (stop, timestamp) > GST_SECOND)
     495                 :          0 :           stop = timestamp;
     496                 :            :       }
     497                 :            :     }
     498 [ #  # ][ #  # ]:          0 :     if (GST_CLOCK_TIME_IS_VALID (demux->base_time) && start > demux->base_time)
     499                 :          0 :       time = start - demux->base_time;
     500                 :            :     else
     501                 :          0 :       time = 0;
     502                 :            : 
     503 [ #  # ][ #  # ]:          0 :     GST_INFO_OBJECT (demux, "sending new segment: rate %g applied_rate %g "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     504                 :            :         "start: %" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
     505                 :            :         ", time: %" GST_TIME_FORMAT " to pad %" GST_PTR_FORMAT,
     506                 :            :         demux->sink_segment.rate, demux->sink_segment.applied_rate,
     507                 :            :         GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
     508                 :            :         GST_TIME_ARGS (time), stream->pad);
     509                 :            : 
     510                 :          0 :     newsegment = gst_event_new_new_segment_full (FALSE,
     511                 :            :         demux->sink_segment.rate, demux->sink_segment.applied_rate,
     512                 :            :         GST_FORMAT_TIME, start, stop, time);
     513                 :            : 
     514                 :          0 :     gst_pad_push_event (stream->pad, newsegment);
     515                 :            : 
     516                 :          0 :     stream->need_segment = FALSE;
     517                 :            :   }
     518                 :            : 
     519                 :            :   /* OK, sent new segment now prepare the buffer for sending */
     520                 :            :   /* caps */
     521                 :          0 :   gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
     522                 :          0 :   GST_BUFFER_TIMESTAMP (buf) = timestamp;
     523                 :            : 
     524                 :            :   /* update position in the segment */
     525                 :          0 :   gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
     526                 :          0 :       MPEGTIME_TO_GSTTIME (demux->current_scr - demux->first_scr));
     527 [ #  # ][ #  # ]:          0 :   GST_LOG_OBJECT (demux, "last stop position is now %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     528                 :            :       " current scr is %" GST_TIME_FORMAT,
     529                 :            :       GST_TIME_ARGS (demux->src_segment.last_stop),
     530                 :            :       GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->current_scr)));
     531                 :            : 
     532         [ #  # ]:          0 :   if (demux->src_segment.last_stop != GST_CLOCK_TIME_NONE) {
     533                 :          0 :     GstClockTime new_time = demux->base_time + demux->src_segment.last_stop;
     534                 :            : 
     535 [ #  # ][ #  # ]:          0 :     if (stream->last_ts == GST_CLOCK_TIME_NONE || stream->last_ts < new_time) {
     536                 :            : #if 0
     537                 :            :       g_print ("last_ts update on pad %s to time %" GST_TIME_FORMAT "\n",
     538                 :            :           GST_PAD_NAME (stream->pad), GST_TIME_ARGS (cur_scr_time));
     539                 :            : #endif
     540                 :          0 :       stream->last_ts = new_time;
     541                 :            :     }
     542                 :            : 
     543                 :          0 :     gst_flups_demux_send_segment_updates (demux, new_time);
     544                 :            :   }
     545                 :            : 
     546                 :            :   /* Set the buffer discont flag, and clear discont state on the stream */
     547         [ #  # ]:          0 :   if (stream->discont) {
     548         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "marking discont buffer");
     549                 :          0 :     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
     550                 :            : 
     551                 :          0 :     stream->discont = FALSE;
     552                 :            :   }
     553                 :          0 :   size = GST_BUFFER_SIZE (buf);
     554                 :            : 
     555                 :          0 :   demux->next_pts = G_MAXUINT64;
     556                 :          0 :   demux->next_dts = G_MAXUINT64;
     557                 :            : 
     558                 :          0 :   result = gst_pad_push (stream->pad, buf);
     559 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "pushed stream id 0x%02x type 0x%02x, time: %"
         [ #  # ][ #  # ]
                 [ #  # ]
     560                 :            :       GST_TIME_FORMAT ", size %d. result: %s",
     561                 :            :       stream->id, stream->type, GST_TIME_ARGS (timestamp),
     562                 :            :       size, gst_flow_get_name (result));
     563                 :            : 
     564                 :          0 :   return result;
     565                 :            : 
     566                 :            :   /* ERROR */
     567                 :            : no_stream:
     568                 :            :   {
     569         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "no stream given");
     570                 :          0 :     gst_buffer_unref (buf);
     571                 :          0 :     return GST_FLOW_OK;
     572                 :            :   }
     573                 :            : }
     574                 :            : 
     575                 :            : static inline void
     576                 :          0 : gst_flups_demux_mark_discont (GstFluPSDemux * demux, gboolean discont,
     577                 :            :     gboolean need_segment)
     578                 :            : {
     579                 :          0 :   gint i, count = demux->found_count;
     580                 :            : 
     581                 :            :   /* mark discont on all streams */
     582         [ #  # ]:          0 :   for (i = 0; i < count; i++) {
     583                 :          0 :     GstFluPSStream *stream = demux->streams_found[i];
     584                 :            : 
     585         [ #  # ]:          0 :     if (G_LIKELY (stream)) {
     586                 :          0 :       stream->discont |= discont;
     587                 :          0 :       stream->need_segment |= need_segment;
     588         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "marked stream as discont %d, need_segment %d",
     589                 :            :           stream->discont, stream->need_segment);
     590                 :            :     }
     591                 :            :   }
     592                 :          0 : }
     593                 :            : 
     594                 :            : static inline gboolean
     595                 :          0 : gst_flups_demux_send_event (GstFluPSDemux * demux, GstEvent * event)
     596                 :            : {
     597                 :          0 :   gint i, count = demux->found_count;
     598                 :          0 :   gboolean ret = FALSE;
     599                 :            : 
     600         [ #  # ]:          0 :   for (i = 0; i < count; i++) {
     601                 :          0 :     GstFluPSStream *stream = demux->streams_found[i];
     602                 :            : 
     603 [ #  # ][ #  # ]:          0 :     if (stream && !stream->notlinked) {
     604                 :          0 :       (void) gst_event_ref (event);
     605                 :            : 
     606         [ #  # ]:          0 :       if (!gst_pad_push_event (stream->pad, event)) {
     607         [ #  # ]:          0 :         GST_DEBUG_OBJECT (stream, "event %s was not handled correctly",
     608                 :            :             GST_EVENT_TYPE_NAME (event));
     609                 :            :       } else {
     610                 :            :         /* If at least one push returns TRUE, then we return TRUE. */
     611         [ #  # ]:          0 :         GST_DEBUG_OBJECT (stream, "event %s was handled correctly",
     612                 :            :             GST_EVENT_TYPE_NAME (event));
     613                 :          0 :         ret = TRUE;
     614                 :            :       }
     615                 :            :     }
     616                 :            :   }
     617                 :            : 
     618                 :          0 :   gst_event_unref (event);
     619                 :          0 :   return ret;
     620                 :            : }
     621                 :            : 
     622                 :            : static gboolean
     623                 :          0 : gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
     624                 :            : {
     625                 :          0 :   const GstStructure *structure = gst_event_get_structure (event);
     626                 :          0 :   const char *type = gst_structure_get_string (structure, "event");
     627                 :            :   gint i;
     628                 :            :   gchar cur_stream_name[32];
     629                 :            :   GstFluPSStream *temp;
     630                 :            : 
     631         [ #  # ]:          0 :   if (strcmp (type, "dvd-lang-codes") == 0) {
     632                 :            :     GstEvent **p_ev;
     633                 :            :     /* Store the language codes event on the element, then iterate over the 
     634                 :            :      * streams it specifies and retrieve them. The stream creation code then 
     635                 :            :      * creates the pad appropriately and sends tag events as needed */
     636                 :          0 :     p_ev = &demux->lang_codes, event;
     637                 :          0 :     gst_event_replace (p_ev, event);
     638                 :            : 
     639         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "Handling language codes event");
     640                 :            : 
     641                 :            :     /* Create a video pad to ensure have it before emit no more pads */
     642                 :          0 :     temp = gst_flups_demux_get_stream (demux, 0xe0, ST_VIDEO_MPEG2);
     643                 :            : 
     644                 :            :     /* Read out the languages for audio streams and request each one that 
     645                 :            :      * is present */
     646         [ #  # ]:          0 :     for (i = 0; i < MAX_DVD_AUDIO_STREAMS; i++) {
     647                 :            :       gint stream_format;
     648                 :            :       gint stream_id;
     649                 :            : 
     650                 :          0 :       g_snprintf (cur_stream_name, 32, "audio-%d-format", i);
     651         [ #  # ]:          0 :       if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
     652                 :          0 :         break;
     653                 :            : 
     654   [ #  #  #  #  :          0 :       switch (stream_format) {
                   #  # ]
     655                 :            :         case 0x0:
     656                 :            :           /* AC3 */
     657                 :          0 :           stream_id = 0x80 + i;
     658                 :          0 :           temp = gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_AC3);
     659                 :          0 :           break;
     660                 :            :         case 0x2:
     661                 :            :         case 0x3:
     662                 :            :           /* MPEG audio without and with extension stream are
     663                 :            :            * treated the same */
     664                 :          0 :           stream_id = 0xC0 + i;
     665                 :          0 :           temp = gst_flups_demux_get_stream (demux, stream_id, ST_AUDIO_MPEG1);
     666                 :          0 :           break;
     667                 :            :         case 0x4:
     668                 :            :           /* LPCM */
     669                 :          0 :           stream_id = 0xA0 + i;
     670                 :          0 :           temp =
     671                 :            :               gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_LPCM);
     672                 :          0 :           break;
     673                 :            :         case 0x6:
     674                 :            :           /* DTS */
     675                 :          0 :           stream_id = 0x88 + i;
     676                 :          0 :           temp = gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_DTS);
     677                 :          0 :           break;
     678                 :            :         case 0x7:
     679                 :            :           /* FIXME: What range is SDDS? */
     680                 :          0 :           break;
     681                 :            :         default:
     682         [ #  # ]:          0 :           GST_WARNING_OBJECT (demux,
     683                 :            :               "Unknown audio stream format in language code event: %d",
     684                 :            :               stream_format);
     685                 :          0 :           break;
     686                 :            :       }
     687                 :            :     }
     688                 :            : 
     689                 :            :     /* And subtitle streams */
     690         [ #  # ]:          0 :     for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) {
     691                 :          0 :       g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i);
     692                 :            : 
     693         [ #  # ]:          0 :       if (gst_structure_get_string (structure, cur_stream_name) == NULL)
     694                 :          0 :         break;
     695                 :            : 
     696                 :            :       /* Retrieve the subpicture stream to force pad creation */
     697                 :          0 :       temp = gst_flups_demux_get_stream (demux, 0x20 + i, ST_PS_DVD_SUBPICTURE);
     698                 :            :     }
     699                 :            : 
     700         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "Created all pads from Language Codes event, "
     701                 :            :         "signalling no-more-pads");
     702                 :            : 
     703                 :          0 :     gst_element_no_more_pads (GST_ELEMENT (demux));
     704                 :          0 :     demux->need_no_more_pads = FALSE;
     705                 :            :   }
     706                 :            : 
     707                 :          0 :   gst_event_unref (event);
     708                 :          0 :   return TRUE;
     709                 :            : }
     710                 :            : 
     711                 :            : static void
     712                 :          7 : gst_flups_demux_flush (GstFluPSDemux * demux)
     713                 :            : {
     714         [ -  + ]:          7 :   GST_DEBUG_OBJECT (demux, "flushing demuxer");
     715                 :          7 :   gst_adapter_clear (demux->adapter);
     716                 :          7 :   gst_adapter_clear (demux->rev_adapter);
     717                 :          7 :   gst_pes_filter_drain (&demux->filter);
     718                 :          7 :   gst_flups_demux_clear_times (demux);
     719                 :          7 :   demux->adapter_offset = G_MAXUINT64;
     720                 :          7 :   demux->current_scr = G_MAXUINT64;
     721                 :          7 :   demux->bytes_since_scr = 0;
     722                 :          7 : }
     723                 :            : 
     724                 :            : static inline void
     725                 :          7 : gst_flups_demux_clear_times (GstFluPSDemux * demux)
     726                 :            : {
     727                 :          7 :   gint i, count = demux->found_count;
     728                 :            : 
     729                 :            :   /* Clear the last ts for all streams */
     730         [ -  + ]:          7 :   for (i = 0; i < count; i++) {
     731                 :          0 :     GstFluPSStream *stream = demux->streams_found[i];
     732                 :            : 
     733         [ #  # ]:          0 :     if (G_LIKELY (stream)) {
     734                 :          0 :       stream->last_seg_start = stream->last_ts = GST_CLOCK_TIME_NONE;
     735                 :            :     }
     736                 :            :   }
     737                 :          7 : }
     738                 :            : 
     739                 :            : static inline void
     740                 :          0 : gst_flups_demux_send_segment_updates (GstFluPSDemux * demux,
     741                 :            :     GstClockTime new_start)
     742                 :            : {
     743                 :            :   GstClockTime base_time, stop, time;
     744                 :          0 :   gint i, count = demux->found_count;
     745                 :          0 :   GstEvent *event = NULL;
     746                 :            : 
     747                 :            :   /* Advance all lagging streams by sending a segment update */
     748         [ #  # ]:          0 :   if ((base_time = demux->base_time) == GST_CLOCK_TIME_NONE)
     749                 :          0 :     base_time = 0;
     750                 :            : 
     751                 :          0 :   stop = demux->src_segment.stop;
     752         [ #  # ]:          0 :   if (stop != GST_CLOCK_TIME_NONE)
     753                 :          0 :     stop += base_time;
     754                 :            : 
     755         [ #  # ]:          0 :   if (new_start > stop)
     756                 :          0 :     return;
     757                 :            : 
     758                 :          0 :   time = demux->src_segment.time;
     759                 :          0 :   time += new_start - (demux->src_segment.start + base_time);
     760                 :            : 
     761                 :            :   /* FIXME: Handle reverse playback */
     762         [ #  # ]:          0 :   for (i = 0; i < count; i++) {
     763                 :          0 :     GstFluPSStream *stream = demux->streams_found[i];
     764                 :            : 
     765         [ #  # ]:          0 :     if (stream) {
     766 [ #  # ][ #  # ]:          0 :       if (stream->last_ts == GST_CLOCK_TIME_NONE ||
     767                 :          0 :           stream->last_ts < demux->src_segment.start + base_time)
     768                 :          0 :         stream->last_ts = demux->src_segment.start + base_time;
     769                 :            : 
     770         [ #  # ]:          0 :       if (stream->last_ts + stream->segment_thresh < new_start) {
     771                 :            : #if 0
     772                 :            :         g_print ("Segment update to pad %s time %" GST_TIME_FORMAT " stop now %"
     773                 :            :             GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad),
     774                 :            :             GST_TIME_ARGS (new_start), GST_TIME_ARGS (demux->src_segment.stop));
     775                 :            : #endif
     776 [ #  # ][ #  # ]:          0 :         GST_DEBUG_OBJECT (demux,
         [ #  # ][ #  # ]
                 [ #  # ]
     777                 :            :             "Segment update to pad %s time %" GST_TIME_FORMAT,
     778                 :            :             GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_start));
     779         [ #  # ]:          0 :         if (event == NULL) {
     780                 :          0 :           event = gst_event_new_new_segment_full (TRUE,
     781                 :            :               demux->src_segment.rate, demux->src_segment.applied_rate,
     782                 :            :               GST_FORMAT_TIME, new_start, stop, time);
     783                 :            :         }
     784                 :          0 :         gst_event_ref (event);
     785                 :          0 :         gst_pad_push_event (stream->pad, event);
     786                 :          0 :         stream->last_seg_start = stream->last_ts = new_start;
     787                 :          0 :         stream->need_segment = FALSE;
     788                 :            :       }
     789                 :            :     }
     790                 :            :   }
     791                 :            : 
     792         [ #  # ]:          0 :   if (event)
     793                 :          0 :     gst_event_unref (event);
     794                 :            : }
     795                 :            : 
     796                 :            : static inline void
     797                 :          0 : gst_flups_demux_close_segment (GstFluPSDemux * demux)
     798                 :            : {
     799                 :          0 :   gint i, count = demux->found_count;
     800                 :          0 :   GstEvent *event = NULL;
     801                 :            :   guint64 base_time;
     802                 :            : 
     803         [ #  # ]:          0 :   GST_INFO_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT,
     804                 :            :       &demux->src_segment);
     805                 :            : 
     806                 :            :   /* FIXME: Need to send a different segment-close to each pad where the
     807                 :            :    * last_seg_start != clock_time_none, as that indicates a sparse-stream
     808                 :            :    * event was sent there */
     809                 :            : 
     810         [ #  # ]:          0 :   if ((base_time = demux->base_time) == (guint64) - 1)
     811                 :          0 :     base_time = 0;
     812                 :            : 
     813                 :            :   /* Close the current segment for a linear playback */
     814         [ #  # ]:          0 :   if (demux->src_segment.rate >= 0) {
     815                 :            :     /* for forward playback, we played from start to last_stop */
     816                 :          0 :     event = gst_event_new_new_segment (TRUE,
     817                 :            :         demux->src_segment.rate, demux->src_segment.format,
     818                 :          0 :         demux->src_segment.start + base_time,
     819                 :          0 :         demux->src_segment.last_stop + base_time, demux->src_segment.time);
     820                 :            :   } else {
     821                 :            :     gint64 stop;
     822                 :            : 
     823         [ #  # ]:          0 :     if ((stop = demux->src_segment.stop) == -1)
     824                 :          0 :       stop = demux->src_segment.duration;
     825                 :            : 
     826                 :            :     /* for reverse playback, we played from stop to last_stop. */
     827                 :          0 :     event = gst_event_new_new_segment (TRUE,
     828                 :            :         demux->src_segment.rate, demux->src_segment.format,
     829                 :          0 :         demux->src_segment.last_stop + base_time,
     830                 :          0 :         stop + base_time, demux->src_segment.last_stop);
     831                 :            :   }
     832                 :            : 
     833         [ #  # ]:          0 :   if (event) {
     834         [ #  # ]:          0 :     for (i = 0; i < count; i++) {
     835                 :          0 :       GstFluPSStream *stream = demux->streams_found[i];
     836                 :            : 
     837 [ #  # ][ #  # ]:          0 :       if (stream && !stream->notlinked && !stream->need_segment) {
                 [ #  # ]
     838                 :          0 :         (void) gst_event_ref (event);
     839                 :            : 
     840         [ #  # ]:          0 :         if (!gst_pad_push_event (stream->pad, event)) {
     841         [ #  # ]:          0 :           GST_DEBUG_OBJECT (stream, "event %s was not handled correctly",
     842                 :            :               GST_EVENT_TYPE_NAME (event));
     843                 :            :         } else {
     844                 :            :           /* If at least one push returns TRUE, then we return TRUE. */
     845         [ #  # ]:          0 :           GST_DEBUG_OBJECT (stream, "event %s was handled correctly",
     846                 :            :               GST_EVENT_TYPE_NAME (event));
     847                 :            :         }
     848                 :            :       }
     849                 :            :     }
     850                 :            : 
     851                 :          0 :     gst_event_unref (event);
     852                 :            :   }
     853                 :          0 : }
     854                 :            : 
     855                 :            : static inline gboolean
     856                 :          0 : have_open_streams (GstFluPSDemux * demux)
     857                 :            : {
     858                 :          0 :   return (demux->streams_found[0] != NULL);
     859                 :            : }
     860                 :            : 
     861                 :            : static gboolean
     862                 :          0 : gst_flups_demux_sink_event (GstPad * pad, GstEvent * event)
     863                 :            : {
     864                 :          0 :   gboolean res = TRUE;
     865                 :            :   GstFluPSDemux *demux;
     866                 :            : 
     867                 :          0 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
     868                 :            : 
     869   [ #  #  #  #  :          0 :   switch (GST_EVENT_TYPE (event)) {
                   #  # ]
     870                 :            :     case GST_EVENT_FLUSH_START:
     871                 :          0 :       gst_flups_demux_send_event (demux, event);
     872                 :          0 :       break;
     873                 :            :     case GST_EVENT_FLUSH_STOP:
     874                 :          0 :       gst_flups_demux_send_event (demux, event);
     875                 :          0 :       gst_segment_init (&demux->sink_segment, GST_FORMAT_UNDEFINED);
     876                 :          0 :       gst_flups_demux_flush (demux);
     877                 :          0 :       break;
     878                 :            :     case GST_EVENT_NEWSEGMENT:
     879                 :            :     {
     880                 :            :       gboolean update;
     881                 :            :       gdouble rate;
     882                 :            :       GstFormat format;
     883                 :            :       gint64 start, stop, time;
     884                 :            : 
     885                 :            :       /* Close current segment */
     886                 :          0 :       gst_flups_demux_close_segment (demux);
     887                 :            : 
     888                 :            :       {
     889                 :            :         gdouble arate;
     890                 :            : 
     891                 :          0 :         gst_event_parse_new_segment_full (event, &update, &rate, &arate,
     892                 :            :             &format, &start, &stop, &time);
     893                 :          0 :         gst_segment_set_newsegment_full (&demux->sink_segment, update, rate,
     894                 :            :             arate, format, start, stop, time);
     895                 :            : 
     896 [ #  # ][ #  # ]:          0 :         if (format == GST_FORMAT_BYTES && demux->scr_rate_n != G_MAXUINT64
     897         [ #  # ]:          0 :             && demux->scr_rate_d != G_MAXUINT64) {
     898                 :            : 
     899 [ #  # ][ #  # ]:          0 :           gst_segment_set_newsegment_full (&demux->src_segment, update, rate,
                 [ #  # ]
     900                 :          0 :               arate, GST_FORMAT_TIME, BYTES_TO_GSTTIME (start),
     901                 :          0 :               BYTES_TO_GSTTIME (stop), BYTES_TO_GSTTIME (time));
     902                 :            :         }
     903                 :            : 
     904                 :            :       }
     905                 :            : 
     906         [ #  # ]:          0 :       GST_INFO_OBJECT (demux, "received new segment: rate %g "
     907                 :            :           "format %d, start: %" G_GINT64_FORMAT ", stop: %" G_GINT64_FORMAT
     908                 :            :           ", time: %" G_GINT64_FORMAT, rate, format, start, stop, time);
     909                 :            : 
     910                 :            :       /* we need to emit a new segment */
     911                 :          0 :       gst_flups_demux_mark_discont (demux, TRUE, TRUE);
     912                 :          0 :       gst_event_unref (event);
     913                 :            : 
     914                 :          0 :       break;
     915                 :            :     }
     916                 :            :     case GST_EVENT_EOS:
     917         [ #  # ]:          0 :       GST_INFO_OBJECT (demux, "Received EOS");
     918         [ #  # ]:          0 :       if (!gst_flups_demux_send_event (demux, event)
     919         [ #  # ]:          0 :           && !have_open_streams (demux)) {
     920         [ #  # ]:          0 :         GST_WARNING_OBJECT (demux, "EOS and no streams open");
     921 [ #  # ][ #  # ]:          0 :         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
         [ #  # ][ #  # ]
     922                 :            :             ("Internal data stream error."), ("No valid streams detected"));
     923                 :            :       }
     924                 :          0 :       break;
     925                 :            :     case GST_EVENT_CUSTOM_DOWNSTREAM:
     926                 :            :     case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
     927                 :            :     {
     928                 :          0 :       const GstStructure *structure = gst_event_get_structure (event);
     929                 :            : 
     930         [ #  # ]:          0 :       if (structure != NULL
     931         [ #  # ]:          0 :           && gst_structure_has_name (structure, "application/x-gst-dvd")) {
     932                 :          0 :         res = gst_flups_demux_handle_dvd_event (demux, event);
     933                 :            :       } else {
     934                 :          0 :         gst_flups_demux_send_event (demux, event);
     935                 :            :       }
     936                 :          0 :       break;
     937                 :            :     }
     938                 :            :     default:
     939                 :          0 :       gst_flups_demux_send_event (demux, event);
     940                 :          0 :       break;
     941                 :            :   }
     942                 :            : 
     943                 :          0 :   gst_object_unref (demux);
     944                 :            : 
     945                 :          0 :   return res;
     946                 :            : }
     947                 :            : 
     948                 :            : static gboolean
     949                 :          0 : gst_flups_demux_handle_seek_push (GstFluPSDemux * demux, GstEvent * event)
     950                 :            : {
     951                 :          0 :   gboolean res = FALSE;
     952                 :            :   gdouble rate;
     953                 :            :   GstFormat format;
     954                 :            :   GstSeekFlags flags;
     955                 :            :   GstSeekType start_type, stop_type;
     956                 :            :   gint64 start, stop;
     957                 :            :   gint64 bstart, bstop;
     958                 :            :   GstEvent *bevent;
     959                 :            : 
     960                 :          0 :   gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
     961                 :            :       &stop_type, &stop);
     962                 :            : 
     963 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     964                 :            :       " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
     965                 :            :       GST_TIME_ARGS (stop));
     966                 :            : 
     967         [ #  # ]:          0 :   if (format == GST_FORMAT_BYTES) {
     968         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
     969                 :          0 :     goto not_supported;
     970                 :            :   }
     971                 :            : 
     972         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "seek - trying directly upstream first");
     973                 :            : 
     974                 :            :   /* first try original format seek */
     975                 :          0 :   (void) gst_event_ref (event);
     976         [ #  # ]:          0 :   if ((res = gst_pad_push_event (demux->sinkpad, event)))
     977                 :          0 :     goto done;
     978                 :            : 
     979         [ #  # ]:          0 :   if (format != GST_FORMAT_TIME) {
     980                 :            :     /* From here down, we only support time based seeks */
     981         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
     982                 :          0 :     goto not_supported;
     983                 :            :   }
     984                 :            : 
     985                 :            :   /* We need to convert to byte based seek and we need a scr_rate for that. */
     986 [ #  # ][ #  # ]:          0 :   if (demux->scr_rate_n == G_MAXUINT64 || demux->scr_rate_d == G_MAXUINT64) {
     987         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "seek not possible, no scr_rate");
     988                 :          0 :     goto not_supported;
     989                 :            :   }
     990                 :            : 
     991         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "try with scr_rate interpolation");
     992                 :            : 
     993 [ #  # ][ #  # ]:          0 :   bstart = GSTTIME_TO_BYTES (start);
     994 [ #  # ][ #  # ]:          0 :   bstop = GSTTIME_TO_BYTES (stop);
     995                 :            : 
     996         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "in bytes bstart %" G_GINT64_FORMAT " bstop %"
     997                 :            :       G_GINT64_FORMAT, bstart, bstop);
     998                 :          0 :   bevent = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
     999                 :            :       bstart, stop_type, bstop);
    1000                 :            : 
    1001                 :          0 :   res = gst_pad_push_event (demux->sinkpad, bevent);
    1002                 :            : 
    1003                 :            : done:
    1004                 :          0 :   gst_event_unref (event);
    1005                 :          0 :   return res;
    1006                 :            : 
    1007                 :            : not_supported:
    1008                 :            :   {
    1009                 :          0 :     gst_event_unref (event);
    1010                 :            : 
    1011                 :          0 :     return FALSE;
    1012                 :            :   }
    1013                 :            : }
    1014                 :            : 
    1015                 :            : static inline void
    1016                 :          0 : gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment)
    1017                 :            : {
    1018                 :            :   gboolean found;
    1019                 :            :   guint64 fscr, offset;
    1020                 :          0 :   guint64 scr = GSTTIME_TO_MPEGTIME (seeksegment->last_stop + demux->base_time);
    1021                 :          0 :   guint64 scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
    1022                 :          0 :   guint64 scr_rate_d = demux->last_scr - demux->first_scr;
    1023                 :            : 
    1024                 :            :   /* In some clips the PTS values are completely unaligned with SCR values.
    1025                 :            :    * To improve the seek in that situation we apply a factor considering the
    1026                 :            :    * relationship between last PTS and last SCR */
    1027         [ #  # ]:          0 :   if (demux->last_scr > demux->last_pts)
    1028                 :          0 :     scr = gst_util_uint64_scale (scr, demux->last_scr, demux->last_pts);
    1029                 :            : 
    1030                 :          0 :   scr = MIN (demux->last_scr, scr);
    1031                 :          0 :   scr = MAX (demux->first_scr, scr);
    1032                 :          0 :   fscr = scr;
    1033                 :            : 
    1034         [ #  # ]:          0 :   GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT
    1035                 :            :       ", trying to go at SCR: %" G_GUINT64_FORMAT, &demux->sink_segment, scr);
    1036                 :            : 
    1037         [ #  # ]:          0 :   offset = MIN (gst_util_uint64_scale (scr, scr_rate_n, scr_rate_d),
    1038                 :            :       demux->sink_segment.stop);
    1039                 :            : 
    1040                 :          0 :   found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
    1041         [ #  # ]:          0 :   if (!found) {
    1042                 :          0 :     found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
    1043                 :            :   }
    1044                 :            : 
    1045 [ #  # ][ #  # ]:          0 :   while (found && fscr < scr) {
    1046                 :          0 :     offset++;
    1047                 :          0 :     found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
    1048                 :            :   }
    1049                 :            : 
    1050 [ #  # ][ #  # ]:          0 :   while (found && fscr > scr && offset > 0) {
                 [ #  # ]
    1051                 :          0 :     offset--;
    1052                 :          0 :     found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
    1053                 :            :   }
    1054                 :            : 
    1055 [ #  # ][ #  # ]:          0 :   GST_INFO_OBJECT (demux, "doing seek at offset %" G_GUINT64_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    1056                 :            :       " SCR: %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
    1057                 :            :       offset, fscr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (fscr)));
    1058                 :          0 :   gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
    1059                 :          0 : }
    1060                 :            : 
    1061                 :            : static gboolean
    1062                 :          0 : gst_flups_demux_handle_seek_pull (GstFluPSDemux * demux, GstEvent * event)
    1063                 :            : {
    1064                 :            :   GstFormat format;
    1065                 :            :   GstSeekFlags flags;
    1066                 :            :   GstSeekType start_type, stop_type;
    1067                 :            :   gint64 start, stop;
    1068                 :            :   gdouble rate;
    1069                 :            :   gboolean update, flush, keyframe;
    1070                 :            :   GstSegment seeksegment;
    1071                 :          0 :   GstClockTime first_pts = MPEGTIME_TO_GSTTIME (demux->first_pts);
    1072                 :            : 
    1073                 :          0 :   gst_event_parse_seek (event, &rate, &format, &flags,
    1074                 :            :       &start_type, &start, &stop_type, &stop);
    1075                 :            : 
    1076         [ #  # ]:          0 :   if (format != GST_FORMAT_TIME)
    1077                 :          0 :     goto wrong_format;
    1078                 :            : 
    1079 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "Seek requested start %" GST_TIME_FORMAT " stop %"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1080                 :            :       GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
    1081                 :            : 
    1082                 :            :   /* We need to convert to byte based seek and we need a scr_rate for that. */
    1083 [ #  # ][ #  # ]:          0 :   if (demux->scr_rate_n == G_MAXUINT64 || demux->scr_rate_d == G_MAXUINT64)
    1084                 :            :     goto no_scr_rate;
    1085                 :            : 
    1086                 :          0 :   flush = flags & GST_SEEK_FLAG_FLUSH;
    1087                 :          0 :   keyframe = flags & GST_SEEK_FLAG_KEY_UNIT;
    1088                 :            : 
    1089         [ #  # ]:          0 :   if (flush) {
    1090                 :            :     /* Flush start up and downstream to make sure data flow and loops are
    1091                 :            :        idle */
    1092                 :          0 :     demux->flushing = TRUE;
    1093                 :          0 :     gst_flups_demux_send_event (demux, gst_event_new_flush_start ());
    1094                 :          0 :     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
    1095                 :            :   } else {
    1096                 :            :     /* Pause the pulling task */
    1097                 :          0 :     gst_pad_pause_task (demux->sinkpad);
    1098                 :            :   }
    1099                 :            : 
    1100                 :            :   /* Take the stream lock */
    1101                 :          0 :   GST_PAD_STREAM_LOCK (demux->sinkpad);
    1102                 :            : 
    1103         [ #  # ]:          0 :   if (flush) {
    1104                 :            :     /* Stop flushing upstream we need to pull */
    1105                 :          0 :     demux->flushing = FALSE;
    1106                 :          0 :     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
    1107                 :            :   }
    1108                 :            : 
    1109                 :            :   /* Work on a copy until we are sure the seek succeeded. */
    1110                 :          0 :   memcpy (&seeksegment, &demux->src_segment, sizeof (GstSegment));
    1111                 :            : 
    1112         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
    1113                 :            :       &demux->src_segment);
    1114                 :            : 
    1115                 :            :   /* Apply the seek to our segment */
    1116                 :          0 :   gst_segment_set_seek (&seeksegment, rate, format, flags,
    1117                 :            :       start_type, start, stop_type, stop, &update);
    1118                 :            : 
    1119         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "seek segment configured %" GST_SEGMENT_FORMAT,
    1120                 :            :       &seeksegment);
    1121                 :            : 
    1122 [ #  # ][ #  # ]:          0 :   if (flush || seeksegment.last_stop != demux->src_segment.last_stop) {
    1123                 :            :     /* Do the actual seeking */
    1124                 :          0 :     gst_flups_demux_do_seek (demux, &seeksegment);
    1125                 :            :   }
    1126                 :            : 
    1127                 :            :   /* check the limits */
    1128         [ #  # ]:          0 :   if (seeksegment.rate > 0.0) {
    1129         [ #  # ]:          0 :     if (seeksegment.start < first_pts - demux->base_time) {
    1130                 :          0 :       seeksegment.start = first_pts - demux->base_time;
    1131                 :          0 :       seeksegment.last_stop = seeksegment.start;
    1132                 :            :     }
    1133                 :            :   }
    1134                 :            : 
    1135                 :            :   /* update the rate in our src segment */
    1136                 :          0 :   demux->sink_segment.rate = rate;
    1137                 :            : 
    1138         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "seek segment adjusted %" GST_SEGMENT_FORMAT,
    1139                 :            :       &seeksegment);
    1140                 :            : 
    1141         [ #  # ]:          0 :   if (flush) {
    1142                 :            :     /* Stop flushing, the sinks are at time 0 now */
    1143                 :          0 :     gst_flups_demux_send_event (demux, gst_event_new_flush_stop ());
    1144                 :            :   } else {
    1145                 :          0 :     gst_flups_demux_close_segment (demux);
    1146                 :            :   }
    1147                 :            : 
    1148 [ #  # ][ #  # ]:          0 :   if (flush || seeksegment.last_stop != demux->src_segment.last_stop) {
    1149                 :          0 :     gst_flups_demux_flush (demux);
    1150                 :            :   }
    1151                 :            : 
    1152                 :            :   /* Ok seek succeeded, take the newly configured segment */
    1153                 :          0 :   memcpy (&demux->src_segment, &seeksegment, sizeof (GstSegment));
    1154                 :            : 
    1155                 :            :   /* Notify about the start of a new segment */
    1156         [ #  # ]:          0 :   if (demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) {
    1157                 :          0 :     gst_element_post_message (GST_ELEMENT (demux),
    1158                 :          0 :         gst_message_new_segment_start (GST_OBJECT (demux),
    1159                 :            :             demux->src_segment.format, demux->src_segment.last_stop));
    1160                 :            :   }
    1161                 :            : 
    1162                 :            :   /* Tell all the stream a new segment is needed */
    1163                 :          0 :   gst_flups_demux_mark_discont (demux, TRUE, TRUE);
    1164                 :            : 
    1165                 :          0 :   gst_pad_start_task (demux->sinkpad,
    1166                 :          0 :       (GstTaskFunction) gst_flups_demux_loop, demux->sinkpad);
    1167                 :            : 
    1168                 :          0 :   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
    1169                 :            : 
    1170                 :          0 :   gst_event_unref (event);
    1171                 :          0 :   return TRUE;
    1172                 :            : 
    1173                 :            :   /* ERRORS */
    1174                 :            : wrong_format:
    1175                 :            :   {
    1176         [ #  # ]:          0 :     GST_WARNING_OBJECT (demux, "we only support seeking in TIME or BYTES "
    1177                 :            :         "formats");
    1178                 :          0 :     gst_event_unref (event);
    1179                 :          0 :     return FALSE;
    1180                 :            :   }
    1181                 :            : no_scr_rate:
    1182                 :            :   {
    1183         [ #  # ]:          0 :     GST_WARNING_OBJECT (demux, "seek not possible, no scr_rate");
    1184                 :          0 :     gst_event_unref (event);
    1185                 :          0 :     return FALSE;
    1186                 :            :   }
    1187                 :            : }
    1188                 :            : 
    1189                 :            : static gboolean
    1190                 :          0 : gst_flups_demux_src_event (GstPad * pad, GstEvent * event)
    1191                 :            : {
    1192                 :          0 :   gboolean res = FALSE;
    1193                 :            :   GstFluPSDemux *demux;
    1194                 :            : 
    1195                 :          0 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
    1196                 :            : 
    1197         [ #  # ]:          0 :   switch (GST_EVENT_TYPE (event)) {
    1198                 :            :     case GST_EVENT_SEEK:
    1199         [ #  # ]:          0 :       if (demux->random_access) {
    1200                 :          0 :         res = gst_flups_demux_handle_seek_pull (demux, event);
    1201                 :            :       } else {
    1202                 :          0 :         res = gst_flups_demux_handle_seek_push (demux, event);
    1203                 :            :       }
    1204                 :          0 :       break;
    1205                 :            :     default:
    1206                 :          0 :       res = gst_pad_push_event (demux->sinkpad, event);
    1207                 :          0 :       break;
    1208                 :            :   }
    1209                 :            : 
    1210                 :          0 :   gst_object_unref (demux);
    1211                 :            : 
    1212                 :          0 :   return res;
    1213                 :            : }
    1214                 :            : 
    1215                 :            : static const GstQueryType *
    1216                 :          0 : gst_flups_demux_src_query_type (GstPad * pad)
    1217                 :            : {
    1218                 :            :   static const GstQueryType types[] = {
    1219                 :            :     GST_QUERY_POSITION,
    1220                 :            :     GST_QUERY_DURATION,
    1221                 :            :     GST_QUERY_SEEKING,
    1222                 :            :     0
    1223                 :            :   };
    1224                 :            : 
    1225                 :          0 :   return types;
    1226                 :            : }
    1227                 :            : 
    1228                 :            : static gboolean
    1229                 :          0 : gst_flups_demux_src_query (GstPad * pad, GstQuery * query)
    1230                 :            : {
    1231                 :          0 :   gboolean res = FALSE;
    1232                 :            :   GstFluPSDemux *demux;
    1233                 :            : 
    1234                 :          0 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
    1235                 :            : 
    1236         [ #  # ]:          0 :   GST_LOG_OBJECT (demux, "Have query of type %d on pad %" GST_PTR_FORMAT,
    1237                 :            :       GST_QUERY_TYPE (query), pad);
    1238                 :            : 
    1239   [ #  #  #  # ]:          0 :   switch (GST_QUERY_TYPE (query)) {
    1240                 :            :     case GST_QUERY_POSITION:
    1241                 :            :     {
    1242                 :            :       GstFormat format;
    1243                 :            : 
    1244                 :          0 :       gst_query_parse_position (query, &format, NULL);
    1245                 :            : 
    1246         [ #  # ]:          0 :       if (format != GST_FORMAT_TIME) {
    1247         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "position not supported for format %d",
    1248                 :            :             format);
    1249                 :          0 :         goto not_supported;
    1250                 :            :       }
    1251                 :            : 
    1252 [ #  # ][ #  # ]:          0 :       GST_LOG_OBJECT (demux, "Position at GStreamer Time:%" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1253                 :            :           GST_TIME_ARGS (demux->src_segment.last_stop));
    1254                 :            : 
    1255                 :          0 :       gst_query_set_position (query, format, demux->src_segment.last_stop);
    1256                 :          0 :       res = TRUE;
    1257                 :          0 :       break;
    1258                 :            :     }
    1259                 :            :     case GST_QUERY_DURATION:
    1260                 :            :     {
    1261                 :            :       GstFormat format;
    1262                 :            :       gint64 duration;
    1263                 :            :       GstPad *peer;
    1264                 :            : 
    1265                 :          0 :       gst_query_parse_duration (query, &format, NULL);
    1266                 :            : 
    1267 [ #  # ][ #  # ]:          0 :       if (G_LIKELY (format == GST_FORMAT_TIME &&
    1268                 :            :               GST_CLOCK_TIME_IS_VALID (demux->src_segment.duration))) {
    1269                 :          0 :         gst_query_set_duration (query, GST_FORMAT_TIME,
    1270                 :            :             demux->src_segment.duration);
    1271                 :          0 :         res = TRUE;
    1272                 :          0 :         break;
    1273                 :            :       }
    1274                 :            : 
    1275         [ #  # ]:          0 :       if ((peer = gst_pad_get_peer (demux->sinkpad)) == NULL) {
    1276         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "duration not possible, no peer");
    1277                 :          0 :         goto not_supported;
    1278                 :            :       }
    1279                 :            : 
    1280                 :            :       /* For any format other than bytes, see if upstream knows first */
    1281         [ #  # ]:          0 :       if (format == GST_FORMAT_BYTES) {
    1282         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "duration not supported for format %d",
    1283                 :            :             format);
    1284                 :          0 :         gst_object_unref (peer);
    1285                 :          0 :         goto not_supported;
    1286                 :            :       }
    1287                 :            : 
    1288         [ #  # ]:          0 :       if (gst_pad_query (peer, query)) {
    1289                 :          0 :         gst_object_unref (peer);
    1290                 :          0 :         res = TRUE;
    1291                 :          0 :         break;
    1292                 :            :       }
    1293                 :            : 
    1294                 :            :       /* Upstream didn't know, so we can only answer TIME queries from
    1295                 :            :        * here on */
    1296         [ #  # ]:          0 :       if (format != GST_FORMAT_TIME) {
    1297         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "duration not supported for format %d",
    1298                 :            :             format);
    1299                 :          0 :         gst_object_unref (peer);
    1300                 :          0 :         goto not_supported;
    1301                 :            :       }
    1302                 :            : 
    1303         [ #  # ]:          0 :       if (demux->mux_rate == -1) {
    1304         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "duration not possible, no mux_rate");
    1305                 :          0 :         gst_object_unref (peer);
    1306                 :          0 :         goto not_supported;
    1307                 :            :       }
    1308                 :            : 
    1309                 :          0 :       gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
    1310                 :            : 
    1311         [ #  # ]:          0 :       if (!gst_pad_query (peer, query)) {
    1312         [ #  # ]:          0 :         GST_LOG_OBJECT (demux, "query on peer pad failed");
    1313                 :          0 :         gst_object_unref (peer);
    1314                 :          0 :         goto not_supported;
    1315                 :            :       }
    1316                 :          0 :       gst_object_unref (peer);
    1317                 :            : 
    1318                 :          0 :       gst_query_parse_duration (query, &format, &duration);
    1319                 :            : 
    1320         [ #  # ]:          0 :       GST_LOG_OBJECT (demux,
    1321                 :            :           "query on peer pad reported bytes %" G_GUINT64_FORMAT, duration);
    1322                 :            : 
    1323         [ #  # ]:          0 :       duration = BYTES_TO_GSTTIME (duration);
    1324                 :            : 
    1325 [ #  # ][ #  # ]:          0 :       GST_LOG_OBJECT (demux, "converted to time %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
    1326                 :            :           GST_TIME_ARGS (duration));
    1327                 :            : 
    1328                 :          0 :       gst_query_set_duration (query, GST_FORMAT_TIME, duration);
    1329                 :          0 :       res = TRUE;
    1330                 :          0 :       break;
    1331                 :            :     }
    1332                 :            :     case GST_QUERY_SEEKING:{
    1333                 :            :       GstFormat fmt;
    1334                 :            : 
    1335                 :          0 :       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
    1336                 :            : 
    1337                 :          0 :       res = TRUE;
    1338         [ #  # ]:          0 :       if (demux->random_access) {
    1339                 :            :         /* In pull mode we can seek in TIME format if we have the SCR */
    1340 [ #  # ][ #  # ]:          0 :         if (fmt != GST_FORMAT_TIME || demux->scr_rate_n == G_MAXUINT64
    1341         [ #  # ]:          0 :             || demux->scr_rate_d == G_MAXUINT64)
    1342                 :          0 :           gst_query_set_seeking (query, fmt, FALSE, -1, -1);
    1343                 :            :         else
    1344                 :          0 :           gst_query_set_seeking (query, fmt, TRUE, 0, -1);
    1345                 :            :       } else {
    1346         [ #  # ]:          0 :         if (fmt == GST_FORMAT_BYTES) {
    1347                 :            :           /* Seeking in BYTES format not supported at all */
    1348                 :          0 :           gst_query_set_seeking (query, fmt, FALSE, -1, -1);
    1349                 :            :         } else {
    1350                 :            :           GstQuery *peerquery;
    1351                 :            :           gboolean seekable;
    1352                 :            : 
    1353                 :            :           /* Then ask upstream */
    1354                 :          0 :           res = gst_pad_peer_query (demux->sinkpad, query);
    1355         [ #  # ]:          0 :           if (res) {
    1356                 :            :             /* If upstream can handle seeks we're done, if it
    1357                 :            :              * can't we still have our TIME->BYTES conversion seek
    1358                 :            :              */
    1359                 :          0 :             gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
    1360 [ #  # ][ #  # ]:          0 :             if (seekable || fmt != GST_FORMAT_TIME)
    1361                 :            :               goto beach;
    1362                 :            :           }
    1363                 :            : 
    1364                 :            :           /* We can seek if upstream supports BYTES seeks and we
    1365                 :            :            * have the SCR
    1366                 :            :            */
    1367                 :          0 :           peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
    1368                 :          0 :           res = gst_pad_peer_query (demux->sinkpad, peerquery);
    1369 [ #  # ][ #  # ]:          0 :           if (!res || demux->scr_rate_n == G_MAXUINT64
    1370         [ #  # ]:          0 :               || demux->scr_rate_d == G_MAXUINT64) {
    1371                 :          0 :             gst_query_set_seeking (query, fmt, FALSE, -1, -1);
    1372                 :            :           } else {
    1373                 :          0 :             gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
    1374         [ #  # ]:          0 :             if (seekable)
    1375                 :          0 :               gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
    1376                 :            :             else
    1377                 :          0 :               gst_query_set_seeking (query, fmt, FALSE, -1, -1);
    1378                 :            :           }
    1379                 :            : 
    1380                 :          0 :           gst_query_unref (peerquery);
    1381                 :          0 :           res = TRUE;
    1382                 :            :         }
    1383                 :            :       }
    1384                 :          0 :       break;
    1385                 :            :     }
    1386                 :            :     default:
    1387                 :          0 :       res = gst_pad_query_default (pad, query);
    1388                 :          0 :       break;
    1389                 :            :   }
    1390                 :            : 
    1391                 :            : beach:
    1392                 :          0 :   gst_object_unref (demux);
    1393                 :            : 
    1394                 :          0 :   return res;
    1395                 :            : 
    1396                 :            : not_supported:
    1397                 :            :   {
    1398                 :          0 :     gst_object_unref (demux);
    1399                 :            : 
    1400                 :          0 :     return FALSE;
    1401                 :            :   }
    1402                 :            : }
    1403                 :            : 
    1404                 :            : static void
    1405                 :          7 : gst_flups_demux_reset_psm (GstFluPSDemux * demux)
    1406                 :            : {
    1407                 :            :   gint i;
    1408                 :            : 
    1409                 :            : #define FILL_TYPE(start, stop, type)  \
    1410                 :            :   for (i=start; i <= stop; i++)      \
    1411                 :            :     demux->psm[i] = type;
    1412                 :            : 
    1413         [ +  + ]:        231 :   FILL_TYPE (0x00, 0x1f, -1);
    1414         [ +  + ]:        231 :   FILL_TYPE (0x20, 0x3f, ST_PS_DVD_SUBPICTURE);
    1415         [ +  + ]:        455 :   FILL_TYPE (0x40, 0x7f, -1);
    1416         [ +  + ]:         63 :   FILL_TYPE (0x80, 0x87, ST_PS_AUDIO_AC3);
    1417         [ +  + ]:        175 :   FILL_TYPE (0x88, 0x9f, ST_PS_AUDIO_DTS);
    1418         [ +  + ]:        119 :   FILL_TYPE (0xa0, 0xaf, ST_PS_AUDIO_LPCM);
    1419         [ +  + ]:         14 :   FILL_TYPE (0xbd, 0xbd, -1);
    1420         [ +  + ]:        231 :   FILL_TYPE (0xc0, 0xdf, ST_AUDIO_MPEG1);
    1421         [ +  + ]:        119 :   FILL_TYPE (0xe0, 0xef, ST_GST_VIDEO_MPEG1_OR_2);
    1422         [ +  + ]:        119 :   FILL_TYPE (0xf0, 0xff, -1);
    1423                 :            : 
    1424                 :            : #undef FILL_TYPE
    1425                 :          7 : }
    1426                 :            : 
    1427                 :            : /* ISO/IEC 13818-1:
    1428                 :            :  * pack_header() {
    1429                 :            :  *     pack_start_code                                   32  bslbf  -+
    1430                 :            :  *     '01'                                               2  bslbf   |
    1431                 :            :  *     system_clock_reference_base [32..30]               3  bslbf   |
    1432                 :            :  *     marker_bit                                         1  bslbf   |
    1433                 :            :  *     system_clock_reference_base [29..15]              15  bslbf   |
    1434                 :            :  *     marker_bit                                         1  bslbf   |
    1435                 :            :  *     system_clock_reference_base [14..0]               15  bslbf   |
    1436                 :            :  *     marker_bit                                         1  bslbf   | 112 bits
    1437                 :            :  *     system_clock_reference_extension                   9  ubslbf  |
    1438                 :            :  *     marker_bit                                         1  bslbf   |
    1439                 :            :  *     program_mux_rate                                  22  ubslbf  |
    1440                 :            :  *     marker_bit                                         1  bslbf   |
    1441                 :            :  *     marker_bit                                         1  bslbf   |
    1442                 :            :  *     reserved                                           5  bslbf   |
    1443                 :            :  *     pack_stuffing_length                               3  ubslbf -+
    1444                 :            :  *
    1445                 :            :  *     for (i = 0; i < pack_stuffing_length; i++) {
    1446                 :            :  *         stuffing_byte '1111 1111'                      8  bslbf
    1447                 :            :  *     }
    1448                 :            :  *
    1449                 :            :  * 112 bits = 14 bytes, as max value for pack_stuffing_length is 7, then
    1450                 :            :  * in total it's needed 14 + 7 = 21 bytes.
    1451                 :            :  */
    1452                 :            : #define PACK_START_SIZE     21
    1453                 :            : 
    1454                 :            : static GstFlowReturn
    1455                 :          0 : gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
    1456                 :            : {
    1457                 :            :   const guint8 *data;
    1458                 :            :   guint length;
    1459                 :            :   guint32 scr1, scr2;
    1460                 :            :   guint64 scr, scr_adjusted, new_rate;
    1461                 :            :   guint64 scr_rate_n;
    1462                 :            :   guint64 scr_rate_d;
    1463                 :          0 :   guint avail = gst_adapter_available (demux->adapter);
    1464                 :            : 
    1465         [ #  # ]:          0 :   GST_DEBUG ("parsing pack start");
    1466                 :            : 
    1467         [ #  # ]:          0 :   if (G_UNLIKELY (avail < PACK_START_SIZE))
    1468                 :          0 :     goto need_more_data;
    1469                 :            : 
    1470                 :          0 :   data = gst_adapter_peek (demux->adapter, PACK_START_SIZE);
    1471                 :            : 
    1472                 :            :   /* skip start code */
    1473                 :          0 :   data += 4;
    1474                 :            : 
    1475                 :          0 :   scr1 = GST_READ_UINT32_BE (data);
    1476                 :          0 :   scr2 = GST_READ_UINT32_BE (data + 4);
    1477                 :            : 
    1478                 :            :   /* fixed length to begin with, start code and two scr values */
    1479                 :          0 :   length = 8 + 4;
    1480                 :            : 
    1481                 :            :   /* start parsing the stream */
    1482         [ #  # ]:          0 :   if ((*data & 0xc0) == 0x40) {
    1483                 :            :     guint32 scr_ext;
    1484                 :            :     guint32 next32;
    1485                 :            :     guint8 stuffing_bytes;
    1486                 :            : 
    1487         [ #  # ]:          0 :     GST_DEBUG ("Found MPEG2 stream");
    1488                 :          0 :     demux->is_mpeg2_pack = TRUE;
    1489                 :            : 
    1490                 :            :     /* mpeg2 has more data */
    1491                 :          0 :     length += 2;
    1492                 :            : 
    1493                 :            :     /* :2=01 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 */
    1494                 :            : 
    1495                 :            :     /* check markers */
    1496         [ #  # ]:          0 :     if (G_UNLIKELY ((scr1 & 0xc4000400) != 0x44000400))
    1497                 :          0 :       goto lost_sync;
    1498                 :            : 
    1499                 :          0 :     scr = ((guint64) scr1 & 0x38000000) << 3;
    1500                 :          0 :     scr |= ((guint64) scr1 & 0x03fff800) << 4;
    1501                 :          0 :     scr |= ((guint64) scr1 & 0x000003ff) << 5;
    1502                 :          0 :     scr |= ((guint64) scr2 & 0xf8000000) >> 27;
    1503                 :            : 
    1504                 :            :     /* marker:1==1 ! scr_ext:9 ! marker:1==1 */
    1505         [ #  # ]:          0 :     if (G_UNLIKELY ((scr2 & 0x04010000) != 0x04010000))
    1506                 :          0 :       goto lost_sync;
    1507                 :            : 
    1508                 :          0 :     scr_ext = (scr2 & 0x03fe0000) >> 17;
    1509                 :            :     /* We keep the offset of this scr */
    1510                 :          0 :     demux->cur_scr_offset = demux->adapter_offset + 12;
    1511                 :            : 
    1512         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "SCR: 0x%08" G_GINT64_MODIFIER "x SCRE: 0x%08x",
    1513                 :            :         scr, scr_ext);
    1514                 :            : 
    1515         [ #  # ]:          0 :     if (scr_ext) {
    1516                 :          0 :       scr = (scr * 300 + scr_ext % 300) / 300;
    1517                 :            :     }
    1518                 :            :     /* SCR has been converted into units of 90Khz ticks to make it comparable
    1519                 :            :        to DTS/PTS, that also implies 1 tick rounding error */
    1520                 :          0 :     data += 6;
    1521                 :            :     /* PMR:22 ! :2==11 ! reserved:5 ! stuffing_len:3 */
    1522                 :          0 :     next32 = GST_READ_UINT32_BE (data);
    1523         [ #  # ]:          0 :     if (G_UNLIKELY ((next32 & 0x00000300) != 0x00000300))
    1524                 :          0 :       goto lost_sync;
    1525                 :            : 
    1526                 :          0 :     new_rate = (next32 & 0xfffffc00) >> 10;
    1527                 :            : 
    1528                 :          0 :     stuffing_bytes = (next32 & 0x07);
    1529         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "stuffing bytes: %d", stuffing_bytes);
    1530                 :            : 
    1531                 :          0 :     data += 4;
    1532                 :          0 :     length += stuffing_bytes;
    1533         [ #  # ]:          0 :     while (stuffing_bytes--) {
    1534         [ #  # ]:          0 :       if (*data++ != 0xff)
    1535                 :          0 :         goto lost_sync;
    1536                 :            :     }
    1537                 :            :   } else {
    1538         [ #  # ]:          0 :     GST_DEBUG ("Found MPEG1 stream");
    1539                 :          0 :     demux->is_mpeg2_pack = FALSE;
    1540                 :            : 
    1541                 :            :     /* check markers */
    1542         [ #  # ]:          0 :     if (G_UNLIKELY ((scr1 & 0xf1000100) != 0x21000100))
    1543                 :          0 :       goto lost_sync;
    1544                 :            : 
    1545         [ #  # ]:          0 :     if (G_UNLIKELY ((scr2 & 0x01800001) != 0x01800001))
    1546                 :          0 :       goto lost_sync;
    1547                 :            : 
    1548                 :            :     /* :4=0010 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 ! marker:1==1 */
    1549                 :          0 :     scr = ((guint64) scr1 & 0x0e000000) << 5;
    1550                 :          0 :     scr |= ((guint64) scr1 & 0x00fffe00) << 6;
    1551                 :          0 :     scr |= ((guint64) scr1 & 0x000000ff) << 7;
    1552                 :          0 :     scr |= ((guint64) scr2 & 0xfe000000) >> 25;
    1553                 :            : 
    1554                 :            :     /* We keep the offset of this scr */
    1555                 :          0 :     demux->cur_scr_offset = demux->adapter_offset + 8;
    1556                 :            : 
    1557                 :            :     /* marker:1==1 ! mux_rate:22 ! marker:1==1 */
    1558                 :          0 :     new_rate = (scr2 & 0x007ffffe) >> 1;
    1559                 :            : 
    1560                 :          0 :     data += 8;
    1561                 :            :   }
    1562                 :          0 :   new_rate *= MPEG_MUX_RATE_MULT;
    1563                 :            : 
    1564                 :            :   /* scr adjusted is the new scr found + the colected adjustment */
    1565                 :          0 :   scr_adjusted = scr + demux->scr_adjust;
    1566                 :            : 
    1567 [ #  # ][ #  # ]:          0 :   GST_LOG_OBJECT (demux,
         [ #  # ][ #  # ]
                 [ #  # ]
    1568                 :            :       "SCR: %" G_GINT64_FORMAT " (%" G_GINT64_FORMAT "), mux_rate %"
    1569                 :            :       G_GINT64_FORMAT ", GStreamer Time:%" GST_TIME_FORMAT,
    1570                 :            :       scr, scr_adjusted, new_rate,
    1571                 :            :       GST_TIME_ARGS (MPEGTIME_TO_GSTTIME ((guint64) scr)));
    1572                 :            : 
    1573                 :            :   /* keep the first src in order to calculate delta time */
    1574         [ #  # ]:          0 :   if (G_UNLIKELY (demux->first_scr == G_MAXUINT64)) {
    1575                 :          0 :     demux->first_scr = scr;
    1576                 :          0 :     demux->first_scr_offset = demux->cur_scr_offset;
    1577                 :          0 :     demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr);
    1578                 :            :     /* at begin consider the new_rate as the scr rate, bytes/clock ticks */
    1579                 :          0 :     scr_rate_n = new_rate;
    1580                 :          0 :     scr_rate_d = CLOCK_FREQ;
    1581         [ #  # ]:          0 :   } else if (G_LIKELY (demux->first_scr_offset != demux->cur_scr_offset)) {
    1582                 :            :     /* estimate byte rate related to the SCR */
    1583                 :          0 :     scr_rate_n = demux->cur_scr_offset - demux->first_scr_offset;
    1584                 :          0 :     scr_rate_d = scr_adjusted - demux->first_scr;
    1585                 :            :   } else {
    1586                 :          0 :     scr_rate_n = demux->scr_rate_n;
    1587                 :          0 :     scr_rate_d = demux->scr_rate_d;
    1588                 :            :   }
    1589                 :            : 
    1590 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "%s mode scr: %" G_GUINT64_FORMAT " at %"
    1591                 :            :       G_GUINT64_FORMAT ", first scr: %" G_GUINT64_FORMAT
    1592                 :            :       " at %" G_GUINT64_FORMAT ", scr rate: %" G_GUINT64_FORMAT
    1593                 :            :       "/%" G_GUINT64_FORMAT "(%f)",
    1594                 :            :       ((demux->sink_segment.rate >= 0.0) ? "forward" : "backward"),
    1595                 :            :       scr, demux->cur_scr_offset,
    1596                 :            :       demux->first_scr, demux->first_scr_offset,
    1597                 :            :       scr_rate_n, scr_rate_d, (float) scr_rate_n / scr_rate_d);
    1598                 :            : 
    1599                 :            :   /* adjustment of the SCR */
    1600         [ #  # ]:          0 :   if (G_LIKELY (demux->current_scr != G_MAXUINT64)) {
    1601                 :            :     gint64 diff;
    1602                 :          0 :     guint64 old_scr, old_mux_rate, bss, adjust = 0;
    1603                 :            : 
    1604                 :            :     /* keep SCR of the previous packet */
    1605                 :          0 :     old_scr = demux->current_scr;
    1606                 :          0 :     old_mux_rate = demux->mux_rate;
    1607                 :            : 
    1608                 :            :     /* Bytes since SCR is the amount we placed in the adapter since then
    1609                 :            :      * (demux->bytes_since_scr) minus the amount remaining in the adapter,
    1610                 :            :      * clamped to >= 0 */
    1611                 :          0 :     bss = MAX (0, (gint) (demux->bytes_since_scr - avail));
    1612                 :            : 
    1613                 :            :     /* estimate the new SCR using the previous one according the notes
    1614                 :            :        on point 2.5.2.2 of the ISO/IEC 13818-1 document */
    1615         [ #  # ]:          0 :     if (old_mux_rate != 0)
    1616                 :          0 :       adjust = (bss * CLOCK_FREQ) / old_mux_rate;
    1617                 :            : 
    1618         [ #  # ]:          0 :     if (demux->sink_segment.rate >= 0.0)
    1619                 :          0 :       demux->next_scr = old_scr + adjust;
    1620                 :            :     else
    1621                 :          0 :       demux->next_scr = old_scr - adjust;
    1622                 :            : 
    1623         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux,
    1624                 :            :         "bss: %" G_GUINT64_FORMAT ", next_scr: %" G_GUINT64_FORMAT
    1625                 :            :         ", old_scr: %" G_GUINT64_FORMAT ", scr: %" G_GUINT64_FORMAT,
    1626                 :            :         bss, demux->next_scr, old_scr, scr_adjusted);
    1627                 :            : 
    1628                 :            :     /* calculate the absolute deference between the last scr and
    1629                 :            :        the new one */
    1630         [ #  # ]:          0 :     if (G_UNLIKELY (old_scr > scr_adjusted))
    1631                 :          0 :       diff = old_scr - scr_adjusted;
    1632                 :            :     else
    1633                 :          0 :       diff = scr_adjusted - old_scr;
    1634                 :            : 
    1635                 :            :     /* if the difference is more than 1 second we need to reconfigure
    1636                 :            :        adjustment */
    1637         [ #  # ]:          0 :     if (G_UNLIKELY (diff > CLOCK_FREQ)) {
    1638                 :          0 :       demux->scr_adjust = demux->next_scr - scr;
    1639         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "discont found, diff: %" G_GINT64_FORMAT
    1640                 :            :           ", adjust %" G_GINT64_FORMAT, diff, demux->scr_adjust);
    1641                 :          0 :       scr_adjusted = demux->next_scr;
    1642                 :            :       /* don't update rate estimation on disconts */
    1643                 :          0 :       scr_rate_n = demux->scr_rate_n;
    1644                 :          0 :       scr_rate_d = demux->scr_rate_d;
    1645                 :            :     } else {
    1646                 :          0 :       demux->next_scr = scr_adjusted;
    1647                 :            :     }
    1648                 :            :   }
    1649                 :            : 
    1650                 :            :   /* update the current_scr and rate members */
    1651                 :          0 :   demux->mux_rate = new_rate;
    1652                 :          0 :   demux->current_scr = scr_adjusted;
    1653                 :          0 :   demux->scr_rate_n = scr_rate_n;
    1654                 :          0 :   demux->scr_rate_d = scr_rate_d;
    1655                 :            : 
    1656                 :            :   /* Reset the bytes_since_scr value to count the data remaining in the
    1657                 :            :    * adapter */
    1658                 :          0 :   demux->bytes_since_scr = avail;
    1659                 :            : 
    1660                 :          0 :   gst_adapter_flush (demux->adapter, length);
    1661                 :          0 :   ADAPTER_OFFSET_FLUSH (length);
    1662                 :          0 :   return GST_FLOW_OK;
    1663                 :            : 
    1664                 :            : lost_sync:
    1665                 :            :   {
    1666         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "lost sync");
    1667                 :          0 :     return GST_FLOW_LOST_SYNC;
    1668                 :            :   }
    1669                 :            : need_more_data:
    1670                 :            :   {
    1671         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "need more data");
    1672                 :          0 :     return GST_FLOW_NEED_MORE_DATA;
    1673                 :            :   }
    1674                 :            : }
    1675                 :            : 
    1676                 :            : /* ISO/IEC 13818-1:
    1677                 :            :  * system_header () {
    1678                 :            :  *     system_header_start_code                          32  bslbf  -+
    1679                 :            :  *     header_length                                     16  uimsbf  |
    1680                 :            :  *     marker_bit                                         1  bslbf   |
    1681                 :            :  *     rate_bound                                        22  uimsbf  |
    1682                 :            :  *     marker_bit                                         1  bslbf   |
    1683                 :            :  *     audio_bound                                        6  uimsbf  |
    1684                 :            :  *     fixed_flag                                         1  bslbf   |
    1685                 :            :  *     CSPS_flag                                          1  bslbf   | 96 bits
    1686                 :            :  *     system_audio_lock_flag                             1  bslbf   |
    1687                 :            :  *     system_video_lock_flag                             1  bslbf   |
    1688                 :            :  *     marker_bit                                         1  bslbf   |
    1689                 :            :  *     video_bound                                        5  uimsbf  |
    1690                 :            :  *     packet_rate_restriction_flag                       1  bslbf   |
    1691                 :            :  *     reserved_bits                                      7  bslbf  -+
    1692                 :            :  *     while (nextbits () = = '1') {
    1693                 :            :  *         stream_id                                      8  uimsbf -+
    1694                 :            :  *         '11'                                           2  bslbf   | 24 bits
    1695                 :            :  *         P-STD_buffer_bound_scale                       1  bslbf   |
    1696                 :            :  *         P-STD_buffer_size_bound                       13  uimsbf -+
    1697                 :            :  *     }
    1698                 :            :  * }
    1699                 :            :  * 96 bits = 12 bytes, 24 bits = 3 bytes.
    1700                 :            :  */
    1701                 :            : 
    1702                 :            : static GstFlowReturn
    1703                 :          0 : gst_flups_demux_parse_sys_head (GstFluPSDemux * demux)
    1704                 :            : {
    1705                 :            :   guint16 length;
    1706                 :            :   const guint8 *data;
    1707                 :            :   gboolean csps;
    1708                 :            : 
    1709                 :            :   /* start code + length */
    1710         [ #  # ]:          0 :   if (!(data = gst_adapter_peek (demux->adapter, 6)))
    1711                 :          0 :     goto need_more_data;
    1712                 :            : 
    1713                 :            :   /* skip start code */
    1714                 :          0 :   data += 4;
    1715                 :            : 
    1716                 :          0 :   length = GST_READ_UINT16_BE (data);
    1717         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "length %d", length);
    1718                 :            : 
    1719                 :          0 :   length += 6;
    1720                 :            : 
    1721         [ #  # ]:          0 :   if (!(data = gst_adapter_peek (demux->adapter, length)))
    1722                 :          0 :     goto need_more_data;
    1723                 :            : 
    1724                 :            :   /* skip start code and length */
    1725                 :          0 :   data += 6;
    1726                 :            : 
    1727                 :            :   /* marker:1==1 ! rate_bound:22 | marker:1==1 */
    1728         [ #  # ]:          0 :   if ((*data & 0x80) != 0x80)
    1729                 :          0 :     goto marker_expected;
    1730                 :            : 
    1731                 :            :   {
    1732                 :            :     guint32 rate_bound;
    1733                 :            : 
    1734         [ #  # ]:          0 :     if ((data[2] & 0x01) != 0x01)
    1735                 :          0 :       goto marker_expected;
    1736                 :            : 
    1737                 :          0 :     rate_bound = ((guint32) data[0] & 0x7f) << 15;
    1738                 :          0 :     rate_bound |= ((guint32) data[1]) << 7;
    1739                 :          0 :     rate_bound |= ((guint32) data[2] & 0xfe) >> 1;
    1740                 :          0 :     rate_bound *= MPEG_MUX_RATE_MULT;
    1741                 :            : 
    1742         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "rate bound %u", rate_bound);
    1743                 :            : 
    1744                 :          0 :     data += 3;
    1745                 :            :   }
    1746                 :            : 
    1747                 :            :   /* audio_bound:6==1 ! fixed:1 | constrained:1 */
    1748                 :            :   {
    1749                 :            :     guint8 audio_bound;
    1750                 :            :     gboolean fixed;
    1751                 :            : 
    1752                 :            :     /* max number of simultaneous audio streams active */
    1753                 :          0 :     audio_bound = (data[0] & 0xfc) >> 2;
    1754                 :            :     /* fixed or variable bitrate */
    1755                 :          0 :     fixed = (data[0] & 0x02) == 0x02;
    1756                 :            :     /* meeting constraints */
    1757                 :          0 :     csps = (data[0] & 0x01) == 0x01;
    1758                 :            : 
    1759         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "audio_bound %d, fixed %d, constrained %d",
    1760                 :            :         audio_bound, fixed, csps);
    1761                 :          0 :     data += 1;
    1762                 :            :   }
    1763                 :            : 
    1764                 :            :   /* audio_lock:1 | video_lock:1 | marker:1==1 | video_bound:5 */
    1765                 :            :   {
    1766                 :            :     gboolean audio_lock;
    1767                 :            :     gboolean video_lock;
    1768                 :            :     guint8 video_bound;
    1769                 :            : 
    1770                 :          0 :     audio_lock = (data[0] & 0x80) == 0x80;
    1771                 :          0 :     video_lock = (data[0] & 0x40) == 0x40;
    1772                 :            : 
    1773         [ #  # ]:          0 :     if ((data[0] & 0x20) != 0x20)
    1774                 :          0 :       goto marker_expected;
    1775                 :            : 
    1776                 :            :     /* max number of simultaneous video streams active */
    1777                 :          0 :     video_bound = (data[0] & 0x1f);
    1778                 :            : 
    1779         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "audio_lock %d, video_lock %d, video_bound %d",
    1780                 :            :         audio_lock, video_lock, video_bound);
    1781                 :          0 :     data += 1;
    1782                 :            :   }
    1783                 :            : 
    1784                 :            :   /* packet_rate_restriction:1 | reserved:7==0x7F */
    1785                 :            :   {
    1786                 :            :     gboolean packet_rate_restriction;
    1787                 :            : 
    1788         [ #  # ]:          0 :     if ((data[0] & 0x7f) != 0x7f)
    1789                 :          0 :       goto marker_expected;
    1790                 :            : 
    1791                 :            :     /* only valid if csps is set */
    1792         [ #  # ]:          0 :     if (csps) {
    1793                 :          0 :       packet_rate_restriction = (data[0] & 0x80) == 0x80;
    1794                 :            : 
    1795         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "packet_rate_restriction %d",
    1796                 :            :           packet_rate_restriction);
    1797                 :            :     }
    1798                 :            :   }
    1799                 :          0 :   data += 1;
    1800                 :            : 
    1801                 :            :   {
    1802                 :          0 :     gint stream_count = (length - 12) / 3;
    1803                 :            :     gint i;
    1804                 :            : 
    1805         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "number of streams: %d ", stream_count);
    1806                 :            : 
    1807         [ #  # ]:          0 :     for (i = 0; i < stream_count; i++) {
    1808                 :            :       guint8 stream_id;
    1809                 :            :       gboolean STD_buffer_bound_scale;
    1810                 :            :       guint16 STD_buffer_size_bound;
    1811                 :            :       guint32 buf_byte_size_bound;
    1812                 :            : 
    1813                 :          0 :       stream_id = *data++;
    1814         [ #  # ]:          0 :       if (!(stream_id & 0x80))
    1815                 :          0 :         goto sys_len_error;
    1816                 :            : 
    1817                 :            :       /* check marker bits */
    1818         [ #  # ]:          0 :       if ((*data & 0xC0) != 0xC0)
    1819                 :          0 :         goto no_placeholder_bits;
    1820                 :            : 
    1821                 :          0 :       STD_buffer_bound_scale = *data & 0x20;
    1822                 :          0 :       STD_buffer_size_bound = ((guint16) (*data++ & 0x1F)) << 8;
    1823                 :          0 :       STD_buffer_size_bound |= *data++;
    1824                 :            : 
    1825         [ #  # ]:          0 :       if (STD_buffer_bound_scale == 0) {
    1826                 :          0 :         buf_byte_size_bound = STD_buffer_size_bound * 128;
    1827                 :            :       } else {
    1828                 :          0 :         buf_byte_size_bound = STD_buffer_size_bound * 1024;
    1829                 :            :       }
    1830                 :            : 
    1831         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "STD_buffer_bound_scale %d",
    1832                 :            :           STD_buffer_bound_scale);
    1833         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "STD_buffer_size_bound %d or %d bytes",
    1834                 :            :           STD_buffer_size_bound, buf_byte_size_bound);
    1835                 :            :     }
    1836                 :            :   }
    1837                 :            : 
    1838                 :          0 :   gst_adapter_flush (demux->adapter, length);
    1839                 :          0 :   ADAPTER_OFFSET_FLUSH (length);
    1840                 :          0 :   return GST_FLOW_OK;
    1841                 :            : 
    1842                 :            :   /* ERRORS */
    1843                 :            : marker_expected:
    1844                 :            :   {
    1845         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "expecting marker");
    1846                 :          0 :     return GST_FLOW_LOST_SYNC;
    1847                 :            :   }
    1848                 :            : no_placeholder_bits:
    1849                 :            :   {
    1850         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "expecting placeholder bit values"
    1851                 :            :         " '11' after stream id");
    1852                 :          0 :     return GST_FLOW_LOST_SYNC;
    1853                 :            :   }
    1854                 :            : sys_len_error:
    1855                 :            :   {
    1856         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "error in system header length");
    1857                 :          0 :     return GST_FLOW_LOST_SYNC;
    1858                 :            :   }
    1859                 :            : need_more_data:
    1860                 :            :   {
    1861         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "need more data");
    1862                 :          0 :     return GST_FLOW_NEED_MORE_DATA;
    1863                 :            :   }
    1864                 :            : }
    1865                 :            : 
    1866                 :            : static GstFlowReturn
    1867                 :          0 : gst_flups_demux_parse_psm (GstFluPSDemux * demux)
    1868                 :            : {
    1869                 :          0 :   guint16 length = 0, info_length = 0, es_map_length = 0;
    1870                 :          0 :   guint8 psm_version = 0;
    1871                 :            :   const guint8 *data, *es_map_base;
    1872                 :            :   gboolean applicable;
    1873                 :            : 
    1874                 :            :   /* start code + length */
    1875         [ #  # ]:          0 :   if (!(data = gst_adapter_peek (demux->adapter, 6)))
    1876                 :          0 :     goto need_more_data;
    1877                 :            : 
    1878                 :            :   /* skip start code */
    1879                 :          0 :   data += 4;
    1880                 :            : 
    1881                 :          0 :   length = GST_READ_UINT16_BE (data);
    1882         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "length %u", length);
    1883                 :            : 
    1884         [ #  # ]:          0 :   if (G_UNLIKELY (length > 0x3FA))
    1885                 :          0 :     goto psm_len_error;
    1886                 :            : 
    1887                 :          0 :   length += 6;
    1888                 :            : 
    1889         [ #  # ]:          0 :   if (!(data = gst_adapter_peek (demux->adapter, length)))
    1890                 :          0 :     goto need_more_data;
    1891                 :            : 
    1892                 :            :   /* skip start code and length */
    1893                 :          0 :   data += 6;
    1894                 :            : 
    1895                 :            :   /* Read PSM applicable bit together with version */
    1896                 :          0 :   psm_version = GST_READ_UINT8 (data);
    1897                 :          0 :   applicable = (psm_version & 0x80) >> 7;
    1898                 :          0 :   psm_version &= 0x1F;
    1899         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "PSM version %u (applicable now %u)", psm_version,
    1900                 :            :       applicable);
    1901                 :            : 
    1902                 :            :   /* Jump over version and marker bit */
    1903                 :          0 :   data += 2;
    1904                 :            : 
    1905                 :            :   /* Read PS info length */
    1906                 :          0 :   info_length = GST_READ_UINT16_BE (data);
    1907                 :            :   /* Cap it to PSM length - needed bytes for ES map length and CRC */
    1908                 :          0 :   info_length = MIN (length - 16, info_length);
    1909         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "PS info length %u bytes", info_length);
    1910                 :            : 
    1911                 :            :   /* Jump over that section */
    1912                 :          0 :   data += (2 + info_length);
    1913                 :            : 
    1914                 :            :   /* Read ES map length */
    1915                 :          0 :   es_map_length = GST_READ_UINT16_BE (data);
    1916                 :            :   /* Cap it to PSM remaining length -  CRC */
    1917                 :          0 :   es_map_length = MIN (length - (16 + info_length), es_map_length);
    1918         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "ES map length %u bytes", es_map_length);
    1919                 :            : 
    1920                 :            :   /* Jump over the size */
    1921                 :          0 :   data += 2;
    1922                 :            : 
    1923                 :            :   /* Now read the ES map */
    1924                 :          0 :   es_map_base = data;
    1925         [ #  # ]:          0 :   while (es_map_base + 4 <= data + es_map_length) {
    1926                 :          0 :     guint8 stream_type = 0, stream_id = 0;
    1927                 :          0 :     guint16 stream_info_length = 0;
    1928                 :            : 
    1929                 :          0 :     stream_type = GST_READ_UINT8 (es_map_base);
    1930                 :          0 :     es_map_base++;
    1931                 :          0 :     stream_id = GST_READ_UINT8 (es_map_base);
    1932                 :          0 :     es_map_base++;
    1933                 :          0 :     stream_info_length = GST_READ_UINT16_BE (es_map_base);
    1934                 :          0 :     es_map_base += 2;
    1935                 :            :     /* Cap stream_info_length */
    1936                 :          0 :     stream_info_length = MIN (data + es_map_length - es_map_base,
    1937                 :            :         stream_info_length);
    1938                 :            : 
    1939         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "Stream type %02X with id %02X and %u bytes info",
    1940                 :            :         stream_type, stream_id, stream_info_length);
    1941         [ #  # ]:          0 :     if (G_LIKELY (stream_id != 0xbd))
    1942                 :          0 :       demux->psm[stream_id] = stream_type;
    1943                 :            :     else {
    1944                 :            :       /* Ignore stream type for private_stream_1 and discover it looking at
    1945                 :            :        * the stream data.
    1946                 :            :        * Fixes demuxing some clips with lpcm that was wrongly declared as
    1947                 :            :        * mpeg audio */
    1948         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "stream type for private_stream_1 ignored");
    1949                 :            :     }
    1950                 :          0 :     es_map_base += stream_info_length;
    1951                 :            :   }
    1952                 :            : 
    1953                 :          0 :   gst_adapter_flush (demux->adapter, length);
    1954                 :          0 :   ADAPTER_OFFSET_FLUSH (length);
    1955                 :          0 :   return GST_FLOW_OK;
    1956                 :            : 
    1957                 :            : psm_len_error:
    1958                 :            :   {
    1959         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "error in PSM length");
    1960                 :          0 :     return GST_FLOW_LOST_SYNC;
    1961                 :            :   }
    1962                 :            : need_more_data:
    1963                 :            :   {
    1964         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "need more data");
    1965                 :          0 :     return GST_FLOW_NEED_MORE_DATA;
    1966                 :            :   }
    1967                 :            : }
    1968                 :            : 
    1969                 :            : static void
    1970                 :          0 : gst_flups_demux_resync_cb (GstPESFilter * filter, GstFluPSDemux * demux)
    1971                 :            : {
    1972                 :          0 : }
    1973                 :            : 
    1974                 :            : static GstFlowReturn
    1975                 :          0 : gst_flups_demux_data_cb (GstPESFilter * filter, gboolean first,
    1976                 :            :     GstBuffer * buffer, GstFluPSDemux * demux)
    1977                 :            : {
    1978                 :            :   GstBuffer *out_buf;
    1979                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    1980                 :            :   gint stream_type;
    1981                 :            :   guint32 start_code;
    1982                 :            :   guint8 id;
    1983                 :            :   guint8 *data;
    1984                 :            :   guint datalen;
    1985                 :          0 :   guint offset = 0;
    1986                 :            : 
    1987                 :          0 :   data = GST_BUFFER_DATA (buffer);
    1988                 :          0 :   datalen = GST_BUFFER_SIZE (buffer);
    1989                 :            : 
    1990                 :          0 :   start_code = filter->start_code;
    1991                 :          0 :   id = filter->id;
    1992                 :            : 
    1993         [ #  # ]:          0 :   if (first) {
    1994                 :            :     /* find the stream type */
    1995                 :          0 :     stream_type = demux->psm[id];
    1996         [ #  # ]:          0 :     if (stream_type == -1) {
    1997                 :            :       /* no stream type, if PS1, get the new id */
    1998 [ #  # ][ #  # ]:          0 :       if (start_code == ID_PRIVATE_STREAM_1 && datalen >= 2) {
    1999                 :            :         guint8 nframes;
    2000                 :            : 
    2001                 :            :         /* VDR writes A52 streams without any header bytes
    2002                 :            :          * (see ftp://ftp.mplayerhq.hu/MPlayer/samples/MPEG-VOB/vdr-AC3) */
    2003         [ #  # ]:          0 :         if (datalen >= 4) {
    2004                 :          0 :           guint hdr = GST_READ_UINT32_BE (data);
    2005                 :            : 
    2006         [ #  # ]:          0 :           if (G_UNLIKELY ((hdr & 0xffff0000) == AC3_SYNC_WORD)) {
    2007                 :          0 :             id = 0x80;
    2008                 :          0 :             stream_type = demux->psm[id] = ST_GST_AUDIO_RAWA52;
    2009         [ #  # ]:          0 :             GST_DEBUG_OBJECT (demux, "Found VDR raw A52 stream");
    2010                 :            :           }
    2011                 :            :         }
    2012                 :            : 
    2013         [ #  # ]:          0 :         if (G_LIKELY (stream_type == -1)) {
    2014                 :            :           /* new id is in the first byte */
    2015                 :          0 :           id = data[offset++];
    2016                 :          0 :           datalen--;
    2017                 :            : 
    2018                 :            :           /* and remap */
    2019                 :          0 :           stream_type = demux->psm[id];
    2020                 :            : 
    2021                 :            :           /* Now, if it's a subpicture stream - no more, otherwise
    2022                 :            :            * take the first byte too, since it's the frame count in audio
    2023                 :            :            * streams and our backwards compat convention is to strip it off */
    2024         [ #  # ]:          0 :           if (stream_type != ST_PS_DVD_SUBPICTURE) {
    2025                 :            :             /* Number of audio frames in this packet */
    2026                 :          0 :             nframes = data[offset++];
    2027                 :          0 :             datalen--;
    2028         [ #  # ]:          0 :             GST_DEBUG_OBJECT (demux, "private type 0x%02x, %d frames", id,
    2029                 :            :                 nframes);
    2030                 :            :           } else {
    2031         [ #  # ]:          0 :             GST_DEBUG_OBJECT (demux, "private type 0x%02x, stream type %d", id,
    2032                 :            :                 stream_type);
    2033                 :            :           }
    2034                 :            :         }
    2035                 :            :       }
    2036         [ #  # ]:          0 :       if (stream_type == -1)
    2037                 :          0 :         goto unknown_stream_type;
    2038                 :            :     }
    2039         [ #  # ]:          0 :     if (filter->pts != -1) {
    2040                 :          0 :       demux->next_pts = filter->pts + demux->scr_adjust;
    2041         [ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "PTS = %" G_GUINT64_FORMAT
    2042                 :            :           "(%" G_GUINT64_FORMAT ")", filter->pts, demux->next_pts);
    2043                 :            :     } else
    2044                 :          0 :       demux->next_pts = G_MAXUINT64;
    2045                 :            : 
    2046         [ #  # ]:          0 :     if (filter->dts != -1) {
    2047                 :          0 :       demux->next_dts = filter->dts + demux->scr_adjust;
    2048                 :            :     } else {
    2049                 :          0 :       demux->next_dts = demux->next_pts;
    2050                 :            :     }
    2051         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "DTS = orig %" G_GUINT64_FORMAT
    2052                 :            :         " (%" G_GUINT64_FORMAT ")", filter->dts, demux->next_dts);
    2053                 :            : 
    2054                 :          0 :     demux->current_stream = gst_flups_demux_get_stream (demux, id, stream_type);
    2055                 :            :   }
    2056                 :            : 
    2057         [ #  # ]:          0 :   if (G_UNLIKELY (demux->current_stream == NULL)) {
    2058         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "Dropping buffer for unknown stream id 0x%02x",
    2059                 :            :         id);
    2060                 :          0 :     goto done;
    2061                 :            :   }
    2062                 :            : 
    2063                 :            :   /* After 2 seconds of bitstream emit no more pads */
    2064         [ #  # ]:          0 :   if (demux->need_no_more_pads
    2065         [ #  # ]:          0 :       && (demux->current_scr - demux->first_scr) > 2 * CLOCK_FREQ) {
    2066         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "no more pads, notifying");
    2067                 :          0 :     gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
    2068                 :          0 :     demux->need_no_more_pads = FALSE;
    2069                 :            :   }
    2070                 :            : 
    2071                 :            :   /* If the stream is not-linked, don't bother creating a sub-buffer
    2072                 :            :    * to send to it, unless we're processing a discont (which resets
    2073                 :            :    * the not-linked status and tries again */
    2074         [ #  # ]:          0 :   if (demux->current_stream->discont) {
    2075         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "stream is discont");
    2076                 :          0 :     demux->current_stream->notlinked = FALSE;
    2077                 :            :   }
    2078                 :            : 
    2079         [ #  # ]:          0 :   if (demux->current_stream->notlinked == FALSE) {
    2080                 :          0 :     out_buf = gst_buffer_create_sub (buffer, offset, datalen);
    2081                 :            : 
    2082                 :          0 :     ret = gst_flups_demux_send_data (demux, demux->current_stream, out_buf);
    2083         [ #  # ]:          0 :     if (ret == GST_FLOW_NOT_LINKED) {
    2084                 :          0 :       demux->current_stream->notlinked = TRUE;
    2085                 :          0 :       ret = GST_FLOW_OK;
    2086                 :            :     }
    2087                 :            :   }
    2088                 :            : 
    2089                 :            : done:
    2090                 :          0 :   gst_buffer_unref (buffer);
    2091                 :            : 
    2092                 :          0 :   return ret;
    2093                 :            : 
    2094                 :            :   /* ERRORS */
    2095                 :            : unknown_stream_type:
    2096                 :            :   {
    2097         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "unknown stream type %02x", id);
    2098                 :          0 :     ret = GST_FLOW_OK;
    2099                 :          0 :     goto done;
    2100                 :            :   }
    2101                 :            : }
    2102                 :            : 
    2103                 :            : static gboolean
    2104                 :          0 : gst_flups_demux_resync (GstFluPSDemux * demux, gboolean save)
    2105                 :            : {
    2106                 :            :   const guint8 *data;
    2107                 :            :   gint avail;
    2108                 :            :   guint32 code;
    2109                 :            :   gint offset;
    2110                 :            :   gboolean found;
    2111                 :            : 
    2112                 :          0 :   avail = gst_adapter_available (demux->adapter);
    2113         [ #  # ]:          0 :   if (G_UNLIKELY (avail < 4))
    2114                 :          0 :     goto need_data;
    2115                 :            : 
    2116                 :            :   /* Common case, read 4 bytes an check it */
    2117                 :          0 :   data = gst_adapter_peek (demux->adapter, 4);
    2118                 :            : 
    2119                 :            :   /* read currect code */
    2120                 :          0 :   code = GST_READ_UINT32_BE (data);
    2121                 :            : 
    2122                 :            :   /* The common case is that the sync code is at 0 bytes offset */
    2123         [ #  # ]:          0 :   if (G_LIKELY ((code & 0xffffff00) == 0x100L)) {
    2124         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "Found resync code %08x after 0 bytes", code);
    2125                 :          0 :     demux->last_sync_code = code;
    2126                 :          0 :     return TRUE;
    2127                 :            :   }
    2128                 :            : 
    2129                 :            :   /* Otherwise, we are starting at byte 4 and we need to search
    2130                 :            :      the sync code in all available data in the adapter */
    2131                 :          0 :   offset = 4;
    2132         [ #  # ]:          0 :   if (offset >= avail)
    2133                 :          0 :     goto need_data;             /* Not enough data to find sync */
    2134                 :            : 
    2135                 :          0 :   data = gst_adapter_peek (demux->adapter, avail);
    2136                 :            : 
    2137                 :            :   do {
    2138                 :          0 :     code = (code << 8) | data[offset++];
    2139                 :          0 :     found = (code & 0xffffff00) == 0x100L;
    2140 [ #  # ][ #  # ]:          0 :   } while (offset < avail && !found);
    2141                 :            : 
    2142 [ #  # ][ #  # ]:          0 :   if (!save || demux->sink_segment.rate >= 0.0) {
    2143         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "flushing %d bytes", offset - 4);
    2144                 :            :     /* forward playback, we can discard and flush the skipped bytes */
    2145                 :          0 :     gst_adapter_flush (demux->adapter, offset - 4);
    2146                 :          0 :     ADAPTER_OFFSET_FLUSH (offset - 4);
    2147                 :            :   } else {
    2148         [ #  # ]:          0 :     if (found) {
    2149         [ #  # ]:          0 :       GST_LOG_OBJECT (demux, "reverse saving %d bytes", offset - 4);
    2150                 :            :       /* reverse playback, we keep the flushed bytes and we will append them to
    2151                 :            :        * the next buffer in the chain function, which is the previous buffer in
    2152                 :            :        * the stream. */
    2153                 :          0 :       gst_adapter_push (demux->rev_adapter,
    2154                 :          0 :           gst_adapter_take_buffer (demux->adapter, offset - 4));
    2155                 :            :     } else {
    2156         [ #  # ]:          0 :       GST_LOG_OBJECT (demux, "reverse saving %d bytes", avail);
    2157                 :            :       /* nothing found, keep all bytes */
    2158                 :          0 :       gst_adapter_push (demux->rev_adapter,
    2159                 :            :           gst_adapter_take_buffer (demux->adapter, avail));
    2160                 :            :     }
    2161                 :            :   }
    2162                 :            : 
    2163         [ #  # ]:          0 :   if (found) {
    2164         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "Found resync code %08x after %d bytes",
    2165                 :            :         code, offset - 4);
    2166                 :          0 :     demux->last_sync_code = code;
    2167                 :            :   } else {
    2168         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "No resync after skipping %d", offset);
    2169                 :            :   }
    2170                 :            : 
    2171                 :          0 :   return found;
    2172                 :            : 
    2173                 :            : need_data:
    2174                 :            :   {
    2175         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "we need more data for resync %d", avail);
    2176                 :          0 :     return FALSE;
    2177                 :            :   }
    2178                 :            : }
    2179                 :            : 
    2180                 :            : static inline gboolean
    2181                 :          0 : gst_flups_demux_is_pes_sync (guint32 sync)
    2182                 :            : {
    2183 [ #  # ][ #  # ]:          0 :   return ((sync & 0xfc) == 0xbc) ||
    2184         [ #  # ]:          0 :       ((sync & 0xe0) == 0xc0) || ((sync & 0xf0) == 0xe0);
    2185                 :            : }
    2186                 :            : 
    2187                 :            : static inline gboolean
    2188                 :          0 : gst_flups_demux_scan_ts (GstFluPSDemux * demux, const guint8 * data,
    2189                 :            :     SCAN_MODE mode, guint64 * rts)
    2190                 :            : {
    2191                 :          0 :   gboolean ret = FALSE;
    2192                 :            :   guint32 scr1, scr2;
    2193                 :            :   guint64 scr;
    2194                 :            :   guint64 pts, dts;
    2195                 :            :   guint32 code;
    2196                 :            : 
    2197                 :            :   /* read the 4 bytes for the sync code */
    2198                 :          0 :   code = GST_READ_UINT32_BE (data);
    2199         [ #  # ]:          0 :   if (G_LIKELY (code != ID_PS_PACK_START_CODE))
    2200                 :          0 :     goto beach;
    2201                 :            : 
    2202                 :            :   /* skip start code */
    2203                 :          0 :   data += 4;
    2204                 :            : 
    2205                 :          0 :   scr1 = GST_READ_UINT32_BE (data);
    2206                 :          0 :   scr2 = GST_READ_UINT32_BE (data + 4);
    2207                 :            : 
    2208                 :            :   /* start parsing the stream */
    2209         [ #  # ]:          0 :   if ((*data & 0xc0) == 0x40) {
    2210                 :            :     guint32 scr_ext;
    2211                 :            :     guint32 next32;
    2212                 :            :     guint8 stuffing_bytes;
    2213                 :            : 
    2214                 :            :     /* :2=01 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 */
    2215                 :            : 
    2216                 :            :     /* check markers */
    2217         [ #  # ]:          0 :     if ((scr1 & 0xc4000400) != 0x44000400)
    2218                 :          0 :       goto beach;
    2219                 :            : 
    2220                 :          0 :     scr = ((guint64) scr1 & 0x38000000) << 3;
    2221                 :          0 :     scr |= ((guint64) scr1 & 0x03fff800) << 4;
    2222                 :          0 :     scr |= ((guint64) scr1 & 0x000003ff) << 5;
    2223                 :          0 :     scr |= ((guint64) scr2 & 0xf8000000) >> 27;
    2224                 :            : 
    2225                 :            :     /* marker:1==1 ! scr_ext:9 ! marker:1==1 */
    2226         [ #  # ]:          0 :     if ((scr2 & 0x04010000) != 0x04010000)
    2227                 :          0 :       goto beach;
    2228                 :            : 
    2229                 :          0 :     scr_ext = (scr2 & 0x03fe0000) >> 17;
    2230                 :            : 
    2231         [ #  # ]:          0 :     if (scr_ext) {
    2232                 :          0 :       scr = (scr * 300 + scr_ext % 300) / 300;
    2233                 :            :     }
    2234                 :            :     /* SCR has been converted into units of 90Khz ticks to make it comparable
    2235                 :            :        to DTS/PTS, that also implies 1 tick rounding error */
    2236                 :          0 :     data += 6;
    2237                 :            :     /* PMR:22 ! :2==11 ! reserved:5 ! stuffing_len:3 */
    2238                 :          0 :     next32 = GST_READ_UINT32_BE (data);
    2239         [ #  # ]:          0 :     if ((next32 & 0x00000300) != 0x00000300)
    2240                 :          0 :       goto beach;
    2241                 :            : 
    2242                 :          0 :     stuffing_bytes = (next32 & 0x07);
    2243                 :          0 :     data += 4;
    2244         [ #  # ]:          0 :     while (stuffing_bytes--) {
    2245         [ #  # ]:          0 :       if (*data++ != 0xff)
    2246                 :          0 :         goto beach;
    2247                 :            :     }
    2248                 :            :   } else {
    2249                 :            :     /* check markers */
    2250         [ #  # ]:          0 :     if ((scr1 & 0xf1000100) != 0x21000100)
    2251                 :          0 :       goto beach;
    2252                 :            : 
    2253         [ #  # ]:          0 :     if ((scr2 & 0x01800001) != 0x01800001)
    2254                 :          0 :       goto beach;
    2255                 :            : 
    2256                 :            :     /* :4=0010 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 ! marker:1==1 */
    2257                 :          0 :     scr = ((guint64) scr1 & 0x0e000000) << 5;
    2258                 :          0 :     scr |= ((guint64) scr1 & 0x00fffe00) << 6;
    2259                 :          0 :     scr |= ((guint64) scr1 & 0x000000ff) << 7;
    2260                 :          0 :     scr |= ((guint64) scr2 & 0xfe000000) >> 25;
    2261                 :          0 :     data += 8;
    2262                 :            :   }
    2263                 :            : 
    2264         [ #  # ]:          0 :   if (mode == SCAN_SCR) {
    2265                 :          0 :     *rts = scr;
    2266                 :          0 :     ret = TRUE;
    2267                 :            :   }
    2268                 :            : 
    2269                 :            :   /* read the 4 bytes for the PES sync code */
    2270                 :          0 :   code = GST_READ_UINT32_BE (data);
    2271         [ #  # ]:          0 :   if (!gst_flups_demux_is_pes_sync (code))
    2272                 :          0 :     goto beach;
    2273                 :            : 
    2274         [ #  # ]:          0 :   switch (code) {
    2275                 :            :     case ID_PS_PROGRAM_STREAM_MAP:
    2276                 :            :     case ID_PRIVATE_STREAM_2:
    2277                 :            :     case ID_ECM_STREAM:
    2278                 :            :     case ID_EMM_STREAM:
    2279                 :            :     case ID_PROGRAM_STREAM_DIRECTORY:
    2280                 :            :     case ID_DSMCC_STREAM:
    2281                 :            :     case ID_ITU_TREC_H222_TYPE_E_STREAM:
    2282                 :            :     case ID_PADDING_STREAM:
    2283                 :          0 :       goto beach;
    2284                 :            :     default:
    2285                 :          0 :       break;
    2286                 :            :   }
    2287                 :            : 
    2288                 :            :   /* skip sync code and size */
    2289                 :          0 :   data += 6;
    2290                 :            : 
    2291                 :          0 :   pts = dts = -1;
    2292                 :            : 
    2293                 :            :   /* stuffing bits, first two bits are '10' for mpeg2 pes so this code is
    2294                 :            :    * not triggered. */
    2295                 :            :   while (TRUE) {
    2296         [ #  # ]:          0 :     if (*data != 0xff)
    2297                 :          0 :       break;
    2298                 :          0 :     data++;
    2299                 :          0 :   }
    2300                 :            : 
    2301                 :            :   /* STD buffer size, never for mpeg2 */
    2302         [ #  # ]:          0 :   if ((*data & 0xc0) == 0x40)
    2303                 :          0 :     data += 2;
    2304                 :            : 
    2305                 :            :   /* PTS but no DTS, never for mpeg2 */
    2306         [ #  # ]:          0 :   if ((*data & 0xf0) == 0x20) {
    2307 [ #  # ][ #  # ]:          0 :     READ_TS (data, pts, beach);
                 [ #  # ]
    2308                 :            :   }
    2309                 :            :   /* PTS and DTS, never for mpeg2 */
    2310         [ #  # ]:          0 :   else if ((*data & 0xf0) == 0x30) {
    2311 [ #  # ][ #  # ]:          0 :     READ_TS (data, pts, beach);
                 [ #  # ]
    2312 [ #  # ][ #  # ]:          0 :     READ_TS (data, dts, beach);
                 [ #  # ]
    2313         [ #  # ]:          0 :   } else if ((*data & 0xc0) == 0x80) {
    2314                 :            :     /* mpeg2 case */
    2315                 :            :     guchar flags;
    2316                 :            : 
    2317                 :            :     /* 2: '10'
    2318                 :            :      * 2: PES_scrambling_control
    2319                 :            :      * 1: PES_priority
    2320                 :            :      * 1: data_alignment_indicator
    2321                 :            :      * 1: copyright
    2322                 :            :      * 1: original_or_copy
    2323                 :            :      */
    2324                 :          0 :     flags = *data++;
    2325                 :            : 
    2326         [ #  # ]:          0 :     if ((flags & 0xc0) != 0x80)
    2327                 :          0 :       goto beach;
    2328                 :            : 
    2329                 :            :     /* 2: PTS_DTS_flags
    2330                 :            :      * 1: ESCR_flag
    2331                 :            :      * 1: ES_rate_flag
    2332                 :            :      * 1: DSM_trick_mode_flag
    2333                 :            :      * 1: additional_copy_info_flag
    2334                 :            :      * 1: PES_CRC_flag
    2335                 :            :      * 1: PES_extension_flag
    2336                 :            :      */
    2337                 :          0 :     flags = *data++;
    2338                 :            : 
    2339                 :            :     /* 8: PES_header_data_length */
    2340                 :          0 :     data++;
    2341                 :            : 
    2342                 :            :     /* only DTS: this is invalid */
    2343         [ #  # ]:          0 :     if ((flags & 0xc0) == 0x40)
    2344                 :          0 :       goto beach;
    2345                 :            : 
    2346                 :            :     /* check for PTS */
    2347         [ #  # ]:          0 :     if ((flags & 0x80)) {
    2348 [ #  # ][ #  # ]:          0 :       READ_TS (data, pts, beach);
                 [ #  # ]
    2349                 :            :     }
    2350                 :            :     /* check for DTS */
    2351         [ #  # ]:          0 :     if ((flags & 0x40)) {
    2352 [ #  # ][ #  # ]:          0 :       READ_TS (data, dts, beach);
                 [ #  # ]
    2353                 :            :     }
    2354                 :            :   }
    2355                 :            : 
    2356 [ #  # ][ #  # ]:          0 :   if (mode == SCAN_DTS && dts != -1) {
    2357                 :          0 :     *rts = dts;
    2358                 :          0 :     ret = TRUE;
    2359                 :            :   }
    2360                 :            : 
    2361 [ #  # ][ #  # ]:          0 :   if (mode == SCAN_PTS && pts != -1) {
    2362                 :          0 :     *rts = pts;
    2363                 :          0 :     ret = TRUE;
    2364                 :            :   }
    2365                 :            : beach:
    2366                 :          0 :   return ret;
    2367                 :            : }
    2368                 :            : 
    2369                 :            : static inline gboolean
    2370                 :          0 : gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
    2371                 :            :     SCAN_MODE mode, guint64 * rts)
    2372                 :            : {
    2373                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    2374                 :          0 :   GstBuffer *buffer = NULL;
    2375                 :          0 :   guint64 offset = *pos;
    2376                 :          0 :   gboolean found = FALSE;
    2377                 :          0 :   guint64 ts = 0;
    2378         [ #  # ]:          0 :   guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
    2379                 :          0 :   guint cursor, to_read = BLOCK_SZ;
    2380                 :            :   guint8 *data;
    2381                 :            :   guint end_scan;
    2382                 :            : 
    2383                 :            :   do {
    2384         [ #  # ]:          0 :     if (offset + scan_sz > demux->sink_segment.stop)
    2385                 :          0 :       return FALSE;
    2386                 :            : 
    2387         [ #  # ]:          0 :     if (offset + to_read > demux->sink_segment.stop)
    2388                 :          0 :       to_read = demux->sink_segment.stop - offset;
    2389                 :            : 
    2390                 :            :     /* read some data */
    2391                 :          0 :     ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
    2392         [ #  # ]:          0 :     if (G_UNLIKELY (ret != GST_FLOW_OK))
    2393                 :          0 :       return FALSE;
    2394                 :            : 
    2395                 :          0 :     data = GST_BUFFER_DATA (buffer);
    2396                 :          0 :     end_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
    2397                 :            :     /* scan the block */
    2398 [ #  # ][ #  # ]:          0 :     for (cursor = 0; !found && cursor <= end_scan; cursor++) {
    2399                 :          0 :       found = gst_flups_demux_scan_ts (demux, data++, mode, &ts);
    2400                 :            :     }
    2401                 :            : 
    2402                 :            :     /* done with the buffer, unref it */
    2403                 :          0 :     gst_buffer_unref (buffer);
    2404                 :            : 
    2405         [ #  # ]:          0 :     if (found) {
    2406                 :          0 :       *rts = ts;
    2407                 :          0 :       *pos = offset + cursor - 1;
    2408                 :            :     } else {
    2409                 :          0 :       offset += cursor;
    2410                 :            :     }
    2411 [ #  # ][ #  # ]:          0 :   } while (!found && offset < demux->sink_segment.stop);
    2412                 :            : 
    2413                 :          0 :   return found;
    2414                 :            : }
    2415                 :            : 
    2416                 :            : static inline gboolean
    2417                 :          0 : gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
    2418                 :            :     SCAN_MODE mode, guint64 * rts)
    2419                 :            : {
    2420                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    2421                 :          0 :   GstBuffer *buffer = NULL;
    2422                 :          0 :   guint64 offset = *pos;
    2423                 :          0 :   gboolean found = FALSE;
    2424                 :          0 :   guint64 ts = 0;
    2425         [ #  # ]:          0 :   guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
    2426                 :          0 :   guint cursor, to_read = BLOCK_SZ;
    2427                 :            :   guint start_scan;
    2428                 :            :   guint8 *data;
    2429                 :            : 
    2430                 :            :   do {
    2431         [ #  # ]:          0 :     if (offset < scan_sz - 1)
    2432                 :          0 :       return FALSE;
    2433                 :            : 
    2434         [ #  # ]:          0 :     if (offset > BLOCK_SZ)
    2435                 :          0 :       offset -= BLOCK_SZ;
    2436                 :            :     else {
    2437                 :          0 :       to_read = offset + 1;
    2438                 :          0 :       offset = 0;
    2439                 :            :     }
    2440                 :            :     /* read some data */
    2441                 :          0 :     ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
    2442         [ #  # ]:          0 :     if (G_UNLIKELY (ret != GST_FLOW_OK))
    2443                 :          0 :       return FALSE;
    2444                 :            : 
    2445                 :          0 :     start_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
    2446                 :          0 :     data = GST_BUFFER_DATA (buffer) + start_scan;
    2447                 :            :     /* scan the block */
    2448 [ #  # ][ #  # ]:          0 :     for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) {
    2449                 :          0 :       found = gst_flups_demux_scan_ts (demux, data--, mode, &ts);
    2450                 :            :     }
    2451                 :            : 
    2452                 :            :     /* done with the buffer, unref it */
    2453                 :          0 :     gst_buffer_unref (buffer);
    2454                 :            : 
    2455         [ #  # ]:          0 :     if (found) {
    2456                 :          0 :       *rts = ts;
    2457                 :          0 :       *pos = offset + cursor;
    2458                 :            :     }
    2459                 :            : 
    2460 [ #  # ][ #  # ]:          0 :   } while (!found && offset > 0);
    2461                 :            : 
    2462                 :          0 :   return found;
    2463                 :            : }
    2464                 :            : 
    2465                 :            : static inline gboolean
    2466                 :          0 : gst_flups_sink_get_duration (GstFluPSDemux * demux)
    2467                 :            : {
    2468                 :          0 :   gboolean res = FALSE;
    2469                 :            :   GstPad *peer;
    2470                 :          0 :   GstFormat format = GST_FORMAT_BYTES;
    2471                 :          0 :   gint64 length = 0;
    2472                 :            :   guint64 offset;
    2473                 :            :   guint i;
    2474                 :          0 :   guint64 scr = 0;
    2475                 :            : 
    2476                 :            :   /* init the sink segment */
    2477                 :          0 :   gst_segment_init (&demux->sink_segment, format);
    2478                 :            : 
    2479                 :            :   /* get peer to figure out length */
    2480         [ #  # ]:          0 :   if ((peer = gst_pad_get_peer (demux->sinkpad)) == NULL)
    2481                 :          0 :     goto beach;
    2482                 :            : 
    2483                 :          0 :   res = gst_pad_query_duration (peer, &format, &length);
    2484                 :          0 :   gst_object_unref (peer);
    2485                 :            : 
    2486 [ #  # ][ #  # ]:          0 :   if (!res || length <= 0)
    2487                 :            :     goto beach;
    2488                 :            : 
    2489         [ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "file length %" G_GINT64_FORMAT, length);
    2490                 :            : 
    2491                 :            :   /* update the sink segment */
    2492                 :          0 :   demux->sink_segment.stop = length;
    2493                 :          0 :   gst_segment_set_duration (&demux->sink_segment, format, length);
    2494                 :          0 :   gst_segment_set_last_stop (&demux->sink_segment, format, 0);
    2495                 :            : 
    2496                 :            :   /* Scan for notorious SCR and PTS to calculate the duration */
    2497                 :            :   /* scan for first SCR in the stream */
    2498                 :          0 :   offset = demux->sink_segment.start;
    2499                 :          0 :   gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr);
    2500 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    2501                 :            :       " in packet starting at %" G_GUINT64_FORMAT,
    2502                 :            :       demux->first_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)),
    2503                 :            :       offset);
    2504                 :          0 :   demux->first_scr_offset = offset;
    2505                 :            :   /* scan for last SCR in the stream */
    2506                 :          0 :   offset = demux->sink_segment.stop;
    2507                 :          0 :   gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &demux->last_scr);
    2508 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    2509                 :            :       " in packet starting at %" G_GUINT64_FORMAT,
    2510                 :            :       demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)),
    2511                 :            :       offset);
    2512                 :          0 :   demux->last_scr_offset = offset;
    2513                 :            :   /* scan for first PTS in the stream */
    2514                 :          0 :   offset = demux->sink_segment.start;
    2515                 :          0 :   gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts);
    2516 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    2517                 :            :       " in packet starting at %" G_GUINT64_FORMAT,
    2518                 :            :       demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)),
    2519                 :            :       offset);
    2520                 :            :   /* scan for last PTS in the stream */
    2521                 :          0 :   offset = demux->sink_segment.stop;
    2522                 :          0 :   gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, &demux->last_pts);
    2523 [ #  # ][ #  # ]:          0 :   GST_DEBUG_OBJECT (demux, "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    2524                 :            :       " in packet starting at %" G_GUINT64_FORMAT,
    2525                 :            :       demux->last_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)),
    2526                 :            :       offset);
    2527                 :            :   /* Detect wrong SCR values */
    2528         [ #  # ]:          0 :   if (demux->first_scr > demux->last_scr) {
    2529         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "Wrong SCR values detected, searching for "
    2530                 :            :         "a better first SCR value");
    2531                 :          0 :     offset = demux->first_scr_offset;
    2532         [ #  # ]:          0 :     for (i = 0; i < 10; i++) {
    2533                 :          0 :       offset++;
    2534                 :          0 :       gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr);
    2535         [ #  # ]:          0 :       if (scr < demux->last_scr) {
    2536                 :          0 :         demux->first_scr = scr;
    2537                 :          0 :         demux->first_scr_offset = offset;
    2538                 :            :         /* Start demuxing from the right place */
    2539                 :          0 :         demux->sink_segment.last_stop = offset;
    2540 [ #  # ][ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "Replaced First SCR: %" G_GINT64_FORMAT
         [ #  # ][ #  # ]
                 [ #  # ]
    2541                 :            :             " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT,
    2542                 :            :             demux->first_scr,
    2543                 :            :             GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), offset);
    2544                 :          0 :         break;
    2545                 :            :       }
    2546                 :            :     }
    2547                 :            :   }
    2548                 :            :   /* Set the base_time and avg rate */
    2549                 :          0 :   demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr);
    2550                 :          0 :   demux->scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
    2551                 :          0 :   demux->scr_rate_d = demux->last_scr - demux->first_scr;
    2552                 :            : 
    2553 [ #  # ][ #  # ]:          0 :   if (G_LIKELY (demux->first_pts != G_MAXUINT64 &&
    2554                 :            :           demux->last_pts != G_MAXUINT64)) {
    2555                 :            :     /* update the src segment */
    2556                 :          0 :     demux->src_segment.start =
    2557                 :          0 :         MPEGTIME_TO_GSTTIME (demux->first_pts) - demux->base_time;
    2558                 :          0 :     demux->src_segment.stop = -1;
    2559                 :          0 :     gst_segment_set_duration (&demux->src_segment, GST_FORMAT_TIME,
    2560                 :          0 :         MPEGTIME_TO_GSTTIME (demux->last_pts - demux->first_pts));
    2561                 :          0 :     gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
    2562                 :            :         demux->src_segment.start);
    2563                 :            :   }
    2564         [ #  # ]:          0 :   GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT,
    2565                 :            :       &demux->sink_segment);
    2566         [ #  # ]:          0 :   GST_INFO_OBJECT (demux, "src segment configured %" GST_SEGMENT_FORMAT,
    2567                 :            :       &demux->src_segment);
    2568                 :            : 
    2569                 :          0 :   res = TRUE;
    2570                 :            : 
    2571                 :            : beach:
    2572                 :          0 :   return res;
    2573                 :            : }
    2574                 :            : 
    2575                 :            : static inline GstFlowReturn
    2576                 :          0 : gst_flups_demux_pull_block (GstPad * pad, GstFluPSDemux * demux,
    2577                 :            :     guint64 offset, guint size)
    2578                 :            : {
    2579                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    2580                 :            :   GstBuffer *buffer;
    2581                 :          0 :   ret = gst_pad_pull_range (pad, offset, size, &buffer);
    2582         [ #  # ]:          0 :   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    2583         [ #  # ]:          0 :     GST_DEBUG_OBJECT (demux, "pull range at %" G_GUINT64_FORMAT
    2584                 :            :         " size %u failed", offset, size);
    2585                 :          0 :     goto beach;
    2586                 :            :   } else
    2587         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "pull range at %" G_GUINT64_FORMAT
    2588                 :            :         " size %u done", offset, size);
    2589                 :            : 
    2590         [ #  # ]:          0 :   if (demux->sink_segment.rate < 0) {
    2591         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "setting discont flag on backward rate");
    2592                 :          0 :     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
    2593                 :            :   }
    2594                 :          0 :   ret = gst_flups_demux_chain (pad, buffer);
    2595                 :            : 
    2596                 :            : beach:
    2597                 :          0 :   return ret;
    2598                 :            : }
    2599                 :            : 
    2600                 :            : static void
    2601                 :          0 : gst_flups_demux_loop (GstPad * pad)
    2602                 :            : {
    2603                 :            :   GstFluPSDemux *demux;
    2604                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    2605                 :          0 :   guint64 offset = 0;
    2606                 :            : 
    2607                 :          0 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
    2608                 :            : 
    2609         [ #  # ]:          0 :   if (G_UNLIKELY (demux->flushing)) {
    2610                 :          0 :     ret = GST_FLOW_WRONG_STATE;
    2611                 :          0 :     goto pause;
    2612                 :            :   }
    2613                 :            : 
    2614         [ #  # ]:          0 :   if (G_UNLIKELY (demux->sink_segment.format == GST_FORMAT_UNDEFINED))
    2615                 :          0 :     gst_flups_sink_get_duration (demux);
    2616                 :            : 
    2617                 :          0 :   offset = demux->sink_segment.last_stop;
    2618         [ #  # ]:          0 :   if (demux->sink_segment.rate >= 0) {
    2619                 :          0 :     guint size = BLOCK_SZ;
    2620         [ #  # ]:          0 :     if (G_LIKELY (demux->sink_segment.stop != -1)) {
    2621                 :          0 :       size = MIN (size, demux->sink_segment.stop - offset);
    2622                 :            :     }
    2623                 :            :     /* pull in data */
    2624                 :          0 :     ret = gst_flups_demux_pull_block (pad, demux, offset, size);
    2625                 :            : 
    2626                 :            :     /* pause if something went wrong */
    2627         [ #  # ]:          0 :     if (G_UNLIKELY (ret != GST_FLOW_OK))
    2628                 :          0 :       goto pause;
    2629                 :            : 
    2630                 :            :     /* update our position */
    2631                 :          0 :     offset += size;
    2632                 :          0 :     gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
    2633                 :            : 
    2634                 :            :     /* check EOS condition */
    2635 [ #  # ][ #  # ]:          0 :     if ((demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) &&
    2636         [ #  # ]:          0 :         ((demux->sink_segment.last_stop >= demux->sink_segment.stop) ||
    2637         [ #  # ]:          0 :             (demux->src_segment.stop != -1 &&
    2638                 :          0 :                 demux->src_segment.last_stop >= demux->src_segment.stop))) {
    2639 [ #  # ][ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "forward mode using segment reached end of "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2640                 :            :           "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
    2641                 :            :           " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %"
    2642                 :            :           G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.last_stop),
    2643                 :            :           GST_TIME_ARGS (demux->src_segment.stop),
    2644                 :            :           demux->sink_segment.last_stop, demux->sink_segment.stop);
    2645                 :          0 :       ret = GST_FLOW_UNEXPECTED;
    2646                 :          0 :       goto pause;
    2647                 :            :     }
    2648                 :            :   } else {                      /* Reverse playback */
    2649                 :          0 :     guint64 size = MIN (offset, BLOCK_SZ);
    2650                 :            : 
    2651                 :            :     /* pull in data */
    2652                 :          0 :     ret = gst_flups_demux_pull_block (pad, demux, offset - size, size);
    2653                 :            : 
    2654                 :            :     /* pause if something went wrong */
    2655         [ #  # ]:          0 :     if (G_UNLIKELY (ret != GST_FLOW_OK))
    2656                 :          0 :       goto pause;
    2657                 :            : 
    2658                 :            :     /* update our position */
    2659                 :          0 :     offset -= size;
    2660                 :          0 :     gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
    2661                 :            : 
    2662                 :            :     /* check EOS condition */
    2663 [ #  # ][ #  # ]:          0 :     if (demux->sink_segment.last_stop <= demux->sink_segment.start ||
    2664                 :          0 :         demux->src_segment.last_stop <= demux->src_segment.start) {
    2665 [ #  # ][ #  # ]:          0 :       GST_DEBUG_OBJECT (demux, "reverse mode using segment reached end of "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2666                 :            :           "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
    2667                 :            :           " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %"
    2668                 :            :           G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.last_stop),
    2669                 :            :           GST_TIME_ARGS (demux->src_segment.start),
    2670                 :            :           demux->sink_segment.last_stop, demux->sink_segment.start);
    2671                 :          0 :       ret = GST_FLOW_UNEXPECTED;
    2672                 :          0 :       goto pause;
    2673                 :            :     }
    2674                 :            :   }
    2675                 :            : 
    2676                 :          0 :   gst_object_unref (demux);
    2677                 :            : 
    2678                 :          0 :   return;
    2679                 :            : 
    2680                 :            : pause:
    2681                 :            :   {
    2682                 :          0 :     const gchar *reason = gst_flow_get_name (ret);
    2683                 :            : 
    2684         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
    2685                 :          0 :     gst_pad_pause_task (pad);
    2686                 :            : 
    2687         [ #  # ]:          0 :     if (ret == GST_FLOW_UNEXPECTED) {
    2688                 :            :       /* perform EOS logic */
    2689                 :          0 :       gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
    2690         [ #  # ]:          0 :       if (demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) {
    2691                 :            :         gint64 stop;
    2692                 :            : 
    2693                 :            :         /* for segment playback we need to post when (in stream time)
    2694                 :            :          * we stopped, this is either stop (when set) or the duration. */
    2695         [ #  # ]:          0 :         if ((stop = demux->src_segment.stop) == -1)
    2696                 :          0 :           stop = demux->src_segment.duration;
    2697                 :            : 
    2698         [ #  # ]:          0 :         if (demux->sink_segment.rate >= 0) {
    2699         [ #  # ]:          0 :           GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
    2700                 :          0 :           gst_element_post_message (GST_ELEMENT_CAST (demux),
    2701                 :            :               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
    2702                 :            :                   GST_FORMAT_TIME, stop));
    2703                 :            :         } else {                /* Reverse playback */
    2704         [ #  # ]:          0 :           GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
    2705                 :            :               "segment");
    2706                 :          0 :           gst_element_post_message (GST_ELEMENT_CAST (demux),
    2707                 :            :               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
    2708                 :            :                   GST_FORMAT_TIME, demux->src_segment.start));
    2709                 :            :         }
    2710                 :            :       } else {
    2711                 :            :         /* normal playback, send EOS to all linked pads */
    2712                 :          0 :         gst_element_no_more_pads (GST_ELEMENT (demux));
    2713         [ #  # ]:          0 :         GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
    2714         [ #  # ]:          0 :         if (!gst_flups_demux_send_event (demux, gst_event_new_eos ())
    2715         [ #  # ]:          0 :             && !have_open_streams (demux)) {
    2716         [ #  # ]:          0 :           GST_WARNING_OBJECT (demux, "EOS and no streams open");
    2717 [ #  # ][ #  # ]:          0 :           GST_ELEMENT_ERROR (demux, STREAM, FAILED,
         [ #  # ][ #  # ]
    2718                 :            :               ("Internal data stream error."), ("No valid streams detected"));
    2719                 :            :         }
    2720                 :            :       }
    2721 [ #  # ][ #  # ]:          0 :     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
    2722 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (demux, STREAM, FAILED,
         [ #  # ][ #  # ]
    2723                 :            :           ("Internal data stream error."),
    2724                 :            :           ("stream stopped, reason %s", reason));
    2725                 :          0 :       gst_flups_demux_send_event (demux, gst_event_new_eos ());
    2726                 :            :     }
    2727                 :            : 
    2728                 :          0 :     gst_object_unref (demux);
    2729                 :          0 :     return;
    2730                 :            :   }
    2731                 :            : }
    2732                 :            : 
    2733                 :            : /* If we can pull that's prefered */
    2734                 :            : static gboolean
    2735                 :          7 : gst_flups_demux_sink_activate (GstPad * sinkpad)
    2736                 :            : {
    2737         [ -  + ]:          7 :   if (gst_pad_check_pull_range (sinkpad)) {
    2738                 :          0 :     return gst_pad_activate_pull (sinkpad, TRUE);
    2739                 :            :   } else {
    2740                 :          7 :     return gst_pad_activate_push (sinkpad, TRUE);
    2741                 :            :   }
    2742                 :            : }
    2743                 :            : 
    2744                 :            : /* This function gets called when we activate ourselves in push mode. */
    2745                 :            : static gboolean
    2746                 :         14 : gst_flups_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
    2747                 :            : {
    2748                 :            :   GstFluPSDemux *demux;
    2749                 :            : 
    2750                 :         14 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (sinkpad));
    2751                 :            : 
    2752                 :         14 :   demux->random_access = FALSE;
    2753                 :            : 
    2754                 :         14 :   gst_object_unref (demux);
    2755                 :            : 
    2756                 :         14 :   return TRUE;
    2757                 :            : }
    2758                 :            : 
    2759                 :            : /* this function gets called when we activate ourselves in pull mode.
    2760                 :            :  * We can perform  random access to the resource and we start a task
    2761                 :            :  * to start reading */
    2762                 :            : static gboolean
    2763                 :          0 : gst_flups_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
    2764                 :            : {
    2765                 :            :   GstFluPSDemux *demux;
    2766                 :            : 
    2767                 :          0 :   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (sinkpad));
    2768                 :            : 
    2769         [ #  # ]:          0 :   if (active) {
    2770         [ #  # ]:          0 :     GST_DEBUG ("pull mode activated");
    2771                 :          0 :     demux->random_access = TRUE;
    2772                 :          0 :     gst_object_unref (demux);
    2773                 :          0 :     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flups_demux_loop,
    2774                 :            :         sinkpad);
    2775                 :            :   } else {
    2776                 :          0 :     demux->random_access = FALSE;
    2777                 :          0 :     gst_object_unref (demux);
    2778                 :          0 :     return gst_pad_stop_task (sinkpad);
    2779                 :            :   }
    2780                 :            : }
    2781                 :            : 
    2782                 :            : static GstFlowReturn
    2783                 :          0 : gst_flups_demux_chain (GstPad * pad, GstBuffer * buffer)
    2784                 :            : {
    2785                 :          0 :   GstFluPSDemux *demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
    2786                 :          0 :   GstFlowReturn ret = GST_FLOW_OK;
    2787                 :            :   guint32 avail;
    2788                 :            :   gboolean save, discont;
    2789                 :            : 
    2790                 :          0 :   discont = GST_BUFFER_IS_DISCONT (buffer);
    2791                 :            : 
    2792         [ #  # ]:          0 :   if (discont) {
    2793         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "Received buffer with discont flag and"
    2794                 :            :         " offset %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buffer));
    2795                 :            : 
    2796                 :          0 :     gst_pes_filter_drain (&demux->filter);
    2797                 :          0 :     gst_flups_demux_mark_discont (demux, TRUE, FALSE);
    2798                 :            : 
    2799                 :            :     /* mark discont on all streams */
    2800         [ #  # ]:          0 :     if (demux->sink_segment.rate >= 0.0) {
    2801                 :          0 :       demux->current_scr = G_MAXUINT64;
    2802                 :          0 :       demux->bytes_since_scr = 0;
    2803                 :            :     }
    2804                 :            :   } else {
    2805         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "Received buffer with offset %" G_GUINT64_FORMAT,
    2806                 :            :         GST_BUFFER_OFFSET (buffer));
    2807                 :            :   }
    2808                 :            : 
    2809                 :            :   /* We keep the offset to interpolate SCR */
    2810                 :          0 :   demux->adapter_offset = GST_BUFFER_OFFSET (buffer);
    2811                 :            : 
    2812                 :          0 :   gst_adapter_push (demux->adapter, buffer);
    2813                 :          0 :   demux->bytes_since_scr += GST_BUFFER_SIZE (buffer);
    2814                 :            : 
    2815                 :          0 :   avail = gst_adapter_available (demux->rev_adapter);
    2816         [ #  # ]:          0 :   if (avail > 0) {
    2817         [ #  # ]:          0 :     GST_LOG_OBJECT (demux, "appending %u saved bytes", avail);
    2818                 :            :     /* if we have a previous reverse chunk, append this now */
    2819                 :            :     /* FIXME this code assumes we receive discont buffers all thei
    2820                 :            :      * time */
    2821                 :          0 :     gst_adapter_push (demux->adapter,
    2822                 :            :         gst_adapter_take_buffer (demux->rev_adapter, avail));
    2823                 :            :   }
    2824                 :            : 
    2825                 :          0 :   avail = gst_adapter_available (demux->adapter);
    2826         [ #  # ]:          0 :   GST_LOG_OBJECT (demux, "avail now: %d, state %d", avail, demux->filter.state);
    2827                 :            : 
    2828      [ #  #  # ]:          0 :   switch (demux->filter.state) {
    2829                 :            :     case STATE_DATA_SKIP:
    2830                 :            :     case STATE_DATA_PUSH:
    2831                 :          0 :       ret = gst_pes_filter_process (&demux->filter);
    2832                 :          0 :       break;
    2833                 :            :     case STATE_HEADER_PARSE:
    2834                 :          0 :       break;
    2835                 :            :     default:
    2836                 :          0 :       break;
    2837                 :            :   }
    2838                 :            : 
    2839   [ #  #  #  # ]:          0 :   switch (ret) {
    2840                 :            :     case GST_FLOW_NEED_MORE_DATA:
    2841                 :            :       /* Go and get more data */
    2842                 :          0 :       ret = GST_FLOW_OK;
    2843                 :          0 :       goto done;
    2844                 :            :     case GST_FLOW_LOST_SYNC:
    2845                 :            :       /* for FLOW_OK or lost-sync, carry onto resync */
    2846                 :          0 :       ret = GST_FLOW_OK;
    2847                 :          0 :       break;
    2848                 :            :     case GST_FLOW_OK:
    2849                 :          0 :       break;
    2850                 :            :     default:
    2851                 :            :       /* Any other return value should be sent upstream immediately */
    2852                 :          0 :       goto done;
    2853                 :            :   }
    2854                 :            : 
    2855                 :            :   /* align adapter data to sync boundary, we keep the data up to the next sync
    2856                 :            :    * point. */
    2857                 :          0 :   save = TRUE;
    2858         [ #  # ]:          0 :   while (gst_flups_demux_resync (demux, save)) {
    2859                 :          0 :     gboolean ps_sync = TRUE;
    2860         [ #  # ]:          0 :     if (G_UNLIKELY (demux->flushing)) {
    2861                 :          0 :       ret = GST_FLOW_WRONG_STATE;
    2862                 :          0 :       goto done;
    2863                 :            :     }
    2864                 :            : 
    2865                 :            :     /* now switch on last synced byte */
    2866   [ #  #  #  #  :          0 :     switch (demux->last_sync_code) {
                      # ]
    2867                 :            :       case ID_PS_PACK_START_CODE:
    2868                 :          0 :         ret = gst_flups_demux_parse_pack_start (demux);
    2869                 :          0 :         break;
    2870                 :            :       case ID_PS_SYSTEM_HEADER_START_CODE:
    2871                 :          0 :         ret = gst_flups_demux_parse_sys_head (demux);
    2872                 :          0 :         break;
    2873                 :            :       case ID_PS_END_CODE:
    2874                 :          0 :         ret = GST_FLOW_OK;
    2875                 :          0 :         goto done;
    2876                 :            :       case ID_PS_PROGRAM_STREAM_MAP:
    2877                 :          0 :         ret = gst_flups_demux_parse_psm (demux);
    2878                 :          0 :         break;
    2879                 :            :       default:
    2880         [ #  # ]:          0 :         if (gst_flups_demux_is_pes_sync (demux->last_sync_code)) {
    2881                 :          0 :           ret = gst_pes_filter_process (&demux->filter);
    2882                 :            :         } else {
    2883         [ #  # ]:          0 :           GST_DEBUG_OBJECT (demux, "sync_code=%08x, non PES sync found"
    2884                 :            :               ", continuing", demux->last_sync_code);
    2885                 :          0 :           ps_sync = FALSE;
    2886                 :          0 :           ret = GST_FLOW_LOST_SYNC;
    2887                 :            :         }
    2888                 :          0 :         break;
    2889                 :            :     }
    2890                 :            :     /* if we found a ps sync, we stop saving the data, any non-ps sync gets
    2891                 :            :      * saved up to the next ps sync. */
    2892         [ #  # ]:          0 :     if (ps_sync)
    2893                 :          0 :       save = FALSE;
    2894                 :            : 
    2895      [ #  #  # ]:          0 :     switch (ret) {
    2896                 :            :       case GST_FLOW_NEED_MORE_DATA:
    2897         [ #  # ]:          0 :         GST_DEBUG_OBJECT (demux, "need more data");
    2898                 :          0 :         ret = GST_FLOW_OK;
    2899                 :          0 :         goto done;
    2900                 :            :       case GST_FLOW_LOST_SYNC:
    2901 [ #  # ][ #  # ]:          0 :         if (!save || demux->sink_segment.rate >= 0.0) {
    2902         [ #  # ]:          0 :           GST_DEBUG_OBJECT (demux, "flushing 3 bytes");
    2903                 :          0 :           gst_adapter_flush (demux->adapter, 3);
    2904                 :          0 :           ADAPTER_OFFSET_FLUSH (3);
    2905                 :            :         } else {
    2906         [ #  # ]:          0 :           GST_DEBUG_OBJECT (demux, "saving 3 bytes");
    2907                 :          0 :           gst_adapter_push (demux->rev_adapter,
    2908                 :            :               gst_adapter_take_buffer (demux->adapter, 3));
    2909                 :            :         }
    2910                 :          0 :         ret = GST_FLOW_OK;
    2911                 :          0 :         break;
    2912                 :            :       default:
    2913                 :          0 :         break;
    2914                 :            :     }
    2915                 :            :   }
    2916                 :            : done:
    2917                 :          0 :   gst_object_unref (demux);
    2918                 :            : 
    2919                 :          0 :   return ret;
    2920                 :            : }
    2921                 :            : 
    2922                 :            : static GstStateChangeReturn
    2923                 :         34 : gst_flups_demux_change_state (GstElement * element, GstStateChange transition)
    2924                 :            : {
    2925                 :         34 :   GstFluPSDemux *demux = GST_FLUPS_DEMUX (element);
    2926                 :            :   GstStateChangeReturn result;
    2927                 :            : 
    2928      [ +  +  + ]:         34 :   switch (transition) {
    2929                 :            :     case GST_STATE_CHANGE_NULL_TO_READY:
    2930                 :          4 :       demux->adapter = gst_adapter_new ();
    2931                 :          4 :       demux->rev_adapter = gst_adapter_new ();
    2932                 :          4 :       demux->adapter_offset = G_MAXUINT64;
    2933                 :          4 :       gst_pes_filter_init (&demux->filter, demux->adapter,
    2934                 :            :           &demux->adapter_offset);
    2935                 :          4 :       gst_pes_filter_set_callbacks (&demux->filter,
    2936                 :            :           (GstPESFilterData) gst_flups_demux_data_cb,
    2937                 :            :           (GstPESFilterResync) gst_flups_demux_resync_cb, demux);
    2938                 :          4 :       demux->filter.gather_pes = TRUE;
    2939                 :          4 :       demux->first_scr = G_MAXUINT64;
    2940                 :          4 :       demux->last_scr = G_MAXUINT64;
    2941                 :          4 :       demux->current_scr = G_MAXUINT64;
    2942                 :          4 :       demux->base_time = G_MAXUINT64;
    2943                 :          4 :       demux->scr_rate_n = G_MAXUINT64;
    2944                 :          4 :       demux->scr_rate_d = G_MAXUINT64;
    2945                 :          4 :       demux->first_pts = G_MAXUINT64;
    2946                 :          4 :       demux->last_pts = G_MAXUINT64;
    2947                 :          4 :       break;
    2948                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
    2949                 :          7 :       demux->current_scr = G_MAXUINT64;
    2950                 :          7 :       demux->mux_rate = G_MAXUINT64;
    2951                 :          7 :       demux->next_pts = G_MAXUINT64;
    2952                 :          7 :       demux->next_dts = G_MAXUINT64;
    2953                 :          7 :       demux->first_scr = G_MAXUINT64;
    2954                 :          7 :       demux->last_scr = G_MAXUINT64;
    2955                 :          7 :       demux->base_time = G_MAXUINT64;
    2956                 :          7 :       demux->scr_rate_n = G_MAXUINT64;
    2957                 :          7 :       demux->scr_rate_d = G_MAXUINT64;
    2958                 :          7 :       demux->need_no_more_pads = TRUE;
    2959                 :          7 :       demux->first_pts = G_MAXUINT64;
    2960                 :          7 :       demux->last_pts = G_MAXUINT64;
    2961                 :          7 :       gst_flups_demux_reset_psm (demux);
    2962                 :          7 :       gst_segment_init (&demux->sink_segment, GST_FORMAT_UNDEFINED);
    2963                 :          7 :       gst_segment_init (&demux->src_segment, GST_FORMAT_TIME);
    2964                 :          7 :       gst_flups_demux_flush (demux);
    2965                 :          7 :       break;
    2966                 :            :     default:
    2967                 :         23 :       break;
    2968                 :            :   }
    2969                 :            : 
    2970                 :         34 :   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
    2971                 :            : 
    2972      [ +  +  + ]:         34 :   switch (transition) {
    2973                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
    2974                 :          7 :       gst_flups_demux_reset (demux);
    2975                 :          7 :       break;
    2976                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
    2977                 :          4 :       gst_pes_filter_uninit (&demux->filter);
    2978                 :          4 :       g_object_unref (demux->adapter);
    2979                 :          4 :       demux->adapter = NULL;
    2980                 :          4 :       g_object_unref (demux->rev_adapter);
    2981                 :          4 :       demux->rev_adapter = NULL;
    2982                 :          4 :       break;
    2983                 :            :     default:
    2984                 :         23 :       break;
    2985                 :            :   }
    2986                 :            : 
    2987                 :         34 :   return result;
    2988                 :            : }
    2989                 :            : 
    2990                 :            : gboolean
    2991                 :          6 : gst_flups_demux_plugin_init (GstPlugin * plugin)
    2992                 :            : {
    2993         [ -  + ]:          6 :   if (!gst_element_register (plugin, "mpegpsdemux",
    2994                 :            :           GST_RANK_PRIMARY, GST_TYPE_FLUPS_DEMUX))
    2995                 :          0 :     return FALSE;
    2996                 :            : 
    2997                 :          6 :   return TRUE;
    2998                 :            : }

Generated by: LCOV version 1.9