LCOV - code coverage report
Current view: top level - gst/mpegdemux - mpegtsparse.c (source / functions) Hit Total Coverage
Test: GStreamer Bad Plug-ins 0.10.21.1 Lines: 87 603 14.4 %
Date: 2011-03-25 Functions: 13 50 26.0 %
Branches: 10 279 3.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * mpegtsparse.c - 
       3                 :            :  * Copyright (C) 2007 Alessandro Decina
       4                 :            :  * 
       5                 :            :  * Authors:
       6                 :            :  *   Alessandro Decina <alessandro@nnva.org>
       7                 :            :  *   Zaheer Abbas Merali <zaheerabbas at merali dot org>
       8                 :            :  *
       9                 :            :  * This library is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU Library General Public
      11                 :            :  * License as published by the Free Software Foundation; either
      12                 :            :  * version 2 of the License, or (at your option) any later version.
      13                 :            :  *
      14                 :            :  * This library is distributed in the hope that it will be useful,
      15                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17                 :            :  * Library General Public License for more details.
      18                 :            :  *
      19                 :            :  * You should have received a copy of the GNU Library General Public
      20                 :            :  * License along with this library; if not, write to the
      21                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      22                 :            :  * Boston, MA 02111-1307, USA.
      23                 :            :  */
      24                 :            : 
      25                 :            : #ifdef HAVE_CONFIG_H
      26                 :            : #include "config.h"
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include <stdlib.h>
      30                 :            : 
      31                 :            : #include "mpegtsparse.h"
      32                 :            : #include "gstmpegdesc.h"
      33                 :            : 
      34                 :            : /* latency in mseconds */
      35                 :            : #define TS_LATENCY 700
      36                 :            : 
      37                 :            : #define TABLE_ID_UNSET 0xFF
      38                 :            : #define RUNNING_STATUS_RUNNING 4
      39                 :            : 
      40                 :            : GST_DEBUG_CATEGORY_STATIC (mpegts_parse_debug);
      41                 :            : #define GST_CAT_DEFAULT mpegts_parse_debug
      42                 :            : 
      43                 :            : typedef struct _MpegTSParsePad MpegTSParsePad;
      44                 :            : 
      45                 :            : typedef struct
      46                 :            : {
      47                 :            :   guint16 pid;
      48                 :            :   guint8 stream_type;
      49                 :            : } MpegTSParseStream;
      50                 :            : 
      51                 :            : typedef struct
      52                 :            : {
      53                 :            :   gint program_number;
      54                 :            :   guint16 pmt_pid;
      55                 :            :   guint16 pcr_pid;
      56                 :            :   GstStructure *pmt_info;
      57                 :            :   GHashTable *streams;
      58                 :            :   gint patcount;
      59                 :            :   gint selected;
      60                 :            :   gboolean active;
      61                 :            :   MpegTSParsePad *tspad;
      62                 :            : } MpegTSParseProgram;
      63                 :            : 
      64                 :            : struct _MpegTSParsePad
      65                 :            : {
      66                 :            :   GstPad *pad;
      67                 :            : 
      68                 :            :   /* the program number that the peer wants on this pad */
      69                 :            :   gint program_number;
      70                 :            :   MpegTSParseProgram *program;
      71                 :            : 
      72                 :            :   /* set to FALSE before a push and TRUE after */
      73                 :            :   gboolean pushed;
      74                 :            : 
      75                 :            :   /* the return of the latest push */
      76                 :            :   GstFlowReturn flow_return;
      77                 :            : 
      78                 :            :   GstTagList *tags;
      79                 :            :   guint event_id;
      80                 :            : };
      81                 :            : 
      82                 :            : static GQuark QUARK_PROGRAMS;
      83                 :            : static GQuark QUARK_PROGRAM_NUMBER;
      84                 :            : static GQuark QUARK_PID;
      85                 :            : static GQuark QUARK_PCR_PID;
      86                 :            : static GQuark QUARK_STREAMS;
      87                 :            : static GQuark QUARK_STREAM_TYPE;
      88                 :            : 
      89                 :            : static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
      90                 :            :     GST_PAD_SINK,
      91                 :            :     GST_PAD_ALWAYS,
      92                 :            :     GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
      93                 :            :     );
      94                 :            : 
      95                 :            : static GstStaticPadTemplate src_template =
      96                 :            : GST_STATIC_PAD_TEMPLATE ("src%d", GST_PAD_SRC,
      97                 :            :     GST_PAD_REQUEST,
      98                 :            :     GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
      99                 :            :     );
     100                 :            : 
     101                 :            : static GstStaticPadTemplate program_template =
     102                 :            : GST_STATIC_PAD_TEMPLATE ("program_%d", GST_PAD_SRC,
     103                 :            :     GST_PAD_SOMETIMES,
     104                 :            :     GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
     105                 :            :     );
     106                 :            : 
     107                 :            : enum
     108                 :            : {
     109                 :            :   ARG_0,
     110                 :            :   PROP_PROGRAM_NUMBERS,
     111                 :            :   /* FILL ME */
     112                 :            : };
     113                 :            : 
     114                 :            : static void mpegts_parse_set_property (GObject * object, guint prop_id,
     115                 :            :     const GValue * value, GParamSpec * pspec);
     116                 :            : static void mpegts_parse_get_property (GObject * object, guint prop_id,
     117                 :            :     GValue * value, GParamSpec * pspec);
     118                 :            : static void mpegts_parse_dispose (GObject * object);
     119                 :            : static void mpegts_parse_finalize (GObject * object);
     120                 :            : 
     121                 :            : static MpegTSParsePad *mpegts_parse_create_tspad (MpegTSParse * parse,
     122                 :            :     const gchar * name);
     123                 :            : static void mpegts_parse_destroy_tspad (MpegTSParse * parse,
     124                 :            :     MpegTSParsePad * tspad);
     125                 :            : static GstPad *mpegts_parse_activate_program (MpegTSParse * parse,
     126                 :            :     MpegTSParseProgram * program);
     127                 :            : static void mpegts_parse_free_program (MpegTSParseProgram * program);
     128                 :            : static void mpegts_parse_free_stream (MpegTSParseStream * ptream);
     129                 :            : static void mpegts_parse_reset_selected_programs (MpegTSParse * parse,
     130                 :            :     gchar * programs);
     131                 :            : 
     132                 :            : static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad);
     133                 :            : static GstPad *mpegts_parse_request_new_pad (GstElement * element,
     134                 :            :     GstPadTemplate * templ, const gchar * name);
     135                 :            : static void mpegts_parse_release_pad (GstElement * element, GstPad * pad);
     136                 :            : static GstFlowReturn mpegts_parse_chain (GstPad * pad, GstBuffer * buf);
     137                 :            : static gboolean mpegts_parse_sink_event (GstPad * pad, GstEvent * event);
     138                 :            : static GstStateChangeReturn mpegts_parse_change_state (GstElement * element,
     139                 :            :     GstStateChange transition);
     140                 :            : static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query);
     141                 :            : static void _extra_init (GType type);
     142                 :            : static void mpegts_parse_get_tags_from_sdt (MpegTSParse * parse,
     143                 :            :     GstStructure * sdt_info);
     144                 :            : static void mpegts_parse_get_tags_from_eit (MpegTSParse * parse,
     145                 :            :     GstStructure * eit_info);
     146                 :            : 
     147         [ +  + ]:         55 : GST_BOILERPLATE_FULL (MpegTSParse, mpegts_parse, GstElement, GST_TYPE_ELEMENT,
     148                 :         55 :     _extra_init);
     149                 :            : 
     150                 :            : static const guint32 crc_tab[256] = {
     151                 :            :   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
     152                 :            :   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
     153                 :            :   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
     154                 :            :   0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
     155                 :            :   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
     156                 :            :   0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
     157                 :            :   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
     158                 :            :   0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
     159                 :            :   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
     160                 :            :   0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
     161                 :            :   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
     162                 :            :   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
     163                 :            :   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
     164                 :            :   0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
     165                 :            :   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
     166                 :            :   0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
     167                 :            :   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
     168                 :            :   0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
     169                 :            :   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
     170                 :            :   0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
     171                 :            :   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
     172                 :            :   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
     173                 :            :   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
     174                 :            :   0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
     175                 :            :   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
     176                 :            :   0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
     177                 :            :   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
     178                 :            :   0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
     179                 :            :   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
     180                 :            :   0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
     181                 :            :   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
     182                 :            :   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
     183                 :            :   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
     184                 :            :   0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
     185                 :            :   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
     186                 :            :   0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
     187                 :            :   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
     188                 :            :   0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
     189                 :            :   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
     190                 :            :   0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
     191                 :            :   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
     192                 :            :   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
     193                 :            :   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
     194                 :            : };
     195                 :            : 
     196                 :            : /* relicenced to LGPL from fluendo ts demuxer */
     197                 :            : static guint32
     198                 :          0 : mpegts_parse_calc_crc32 (guint8 * data, guint datalen)
     199                 :            : {
     200                 :            :   gint i;
     201                 :          0 :   guint32 crc = 0xffffffff;
     202                 :            : 
     203         [ #  # ]:          0 :   for (i = 0; i < datalen; i++) {
     204                 :          0 :     crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
     205                 :            :   }
     206                 :          0 :   return crc;
     207                 :            : }
     208                 :            : 
     209                 :            : static void
     210                 :          6 : _extra_init (GType type)
     211                 :            : {
     212                 :          6 :   QUARK_PROGRAMS = g_quark_from_string ("programs");
     213                 :          6 :   QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number");
     214                 :          6 :   QUARK_PID = g_quark_from_string ("pid");
     215                 :          6 :   QUARK_PCR_PID = g_quark_from_string ("pcr-pid");
     216                 :          6 :   QUARK_STREAMS = g_quark_from_string ("streams");
     217                 :          6 :   QUARK_STREAM_TYPE = g_quark_from_string ("stream-type");
     218                 :          6 : }
     219                 :            : 
     220                 :            : static void
     221                 :          6 : mpegts_parse_base_init (gpointer klass)
     222                 :            : {
     223                 :          6 :   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
     224                 :            : 
     225                 :          6 :   gst_element_class_add_pad_template (element_class,
     226                 :            :       gst_static_pad_template_get (&sink_template));
     227                 :          6 :   gst_element_class_add_pad_template (element_class,
     228                 :            :       gst_static_pad_template_get (&src_template));
     229                 :          6 :   gst_element_class_add_pad_template (element_class,
     230                 :            :       gst_static_pad_template_get (&program_template));
     231                 :            : 
     232                 :          6 :   gst_element_class_set_details_simple (element_class,
     233                 :            :       "MPEG transport stream parser", "Codec/Parser",
     234                 :            :       "Parses MPEG2 transport streams",
     235                 :            :       "Alessandro Decina <alessandro@nnva.org>, "
     236                 :            :       "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
     237                 :          6 : }
     238                 :            : 
     239                 :            : static void
     240                 :          6 : mpegts_parse_class_init (MpegTSParseClass * klass)
     241                 :            : {
     242                 :            :   GObjectClass *gobject_class;
     243                 :            :   GstElementClass *element_class;
     244                 :            : 
     245                 :          6 :   element_class = GST_ELEMENT_CLASS (klass);
     246                 :          6 :   element_class->pad_removed = mpegts_parse_pad_removed;
     247                 :          6 :   element_class->request_new_pad = mpegts_parse_request_new_pad;
     248                 :          6 :   element_class->release_pad = mpegts_parse_release_pad;
     249                 :          6 :   element_class->change_state = mpegts_parse_change_state;
     250                 :            : 
     251                 :          6 :   gobject_class = G_OBJECT_CLASS (klass);
     252                 :          6 :   gobject_class->set_property = mpegts_parse_set_property;
     253                 :          6 :   gobject_class->get_property = mpegts_parse_get_property;
     254                 :          6 :   gobject_class->dispose = mpegts_parse_dispose;
     255                 :          6 :   gobject_class->finalize = mpegts_parse_finalize;
     256                 :            : 
     257                 :          6 :   g_object_class_install_property (gobject_class, PROP_PROGRAM_NUMBERS,
     258                 :            :       g_param_spec_string ("program-numbers",
     259                 :            :           "Program Numbers",
     260                 :            :           "Colon separated list of programs", "",
     261                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     262                 :          6 : }
     263                 :            : 
     264                 :            : static gboolean
     265                 :          7 : foreach_psi_pid_remove (gpointer key, gpointer value, gpointer data)
     266                 :            : {
     267                 :          7 :   return TRUE;
     268                 :            : }
     269                 :            : 
     270                 :            : static void
     271                 :         10 : mpegts_parse_reset (MpegTSParse * parse)
     272                 :            : {
     273                 :         10 :   mpegts_packetizer_clear (parse->packetizer);
     274                 :         10 :   g_hash_table_foreach_remove (parse->psi_pids, foreach_psi_pid_remove, NULL);
     275                 :            : 
     276                 :            :   /* PAT */
     277                 :         10 :   g_hash_table_insert (parse->psi_pids,
     278                 :            :       GINT_TO_POINTER (0), GINT_TO_POINTER (1));
     279                 :            :   /* pmt pids will be added and removed dynamically */
     280                 :            : 
     281                 :         10 : }
     282                 :            : 
     283                 :            : static void
     284                 :          3 : mpegts_parse_init (MpegTSParse * parse, MpegTSParseClass * klass)
     285                 :            : {
     286                 :          3 :   parse->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
     287                 :          3 :   gst_pad_set_chain_function (parse->sinkpad, mpegts_parse_chain);
     288                 :          3 :   gst_pad_set_event_function (parse->sinkpad, mpegts_parse_sink_event);
     289                 :          3 :   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
     290                 :            : 
     291                 :          3 :   parse->disposed = FALSE;
     292                 :          3 :   parse->need_sync_program_pads = FALSE;
     293                 :          3 :   parse->packetizer = mpegts_packetizer_new ();
     294                 :          3 :   parse->program_numbers = g_strdup ("");
     295                 :          3 :   parse->pads_to_add = NULL;
     296                 :          3 :   parse->pads_to_remove = NULL;
     297                 :          3 :   parse->programs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
     298                 :            :       NULL, (GDestroyNotify) mpegts_parse_free_program);
     299                 :          3 :   parse->psi_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
     300                 :          3 :   parse->pes_pids = g_hash_table_new (g_direct_hash, g_direct_equal);
     301                 :          3 :   mpegts_parse_reset (parse);
     302                 :            : 
     303                 :          3 : }
     304                 :            : 
     305                 :            : static void
     306                 :          3 : mpegts_parse_dispose (GObject * object)
     307                 :            : {
     308                 :          3 :   MpegTSParse *parse = GST_MPEGTS_PARSE (object);
     309                 :            : 
     310         [ +  - ]:          3 :   if (!parse->disposed) {
     311                 :          3 :     g_object_unref (parse->packetizer);
     312                 :          3 :     parse->disposed = TRUE;
     313                 :            :   }
     314                 :            : 
     315         [ +  - ]:          3 :   if (G_OBJECT_CLASS (parent_class)->dispose)
     316                 :          3 :     G_OBJECT_CLASS (parent_class)->dispose (object);
     317                 :          3 : }
     318                 :            : 
     319                 :            : static void
     320                 :          3 : mpegts_parse_finalize (GObject * object)
     321                 :            : {
     322                 :          3 :   MpegTSParse *parse = GST_MPEGTS_PARSE (object);
     323                 :            : 
     324                 :          3 :   g_free (parse->program_numbers);
     325         [ -  + ]:          3 :   if (parse->pat) {
     326                 :          0 :     gst_structure_free (parse->pat);
     327                 :          0 :     parse->pat = NULL;
     328                 :            :   }
     329                 :          3 :   g_hash_table_destroy (parse->programs);
     330                 :          3 :   g_hash_table_destroy (parse->psi_pids);
     331                 :          3 :   g_hash_table_destroy (parse->pes_pids);
     332                 :            : 
     333         [ +  - ]:          3 :   if (G_OBJECT_CLASS (parent_class)->finalize)
     334                 :          3 :     G_OBJECT_CLASS (parent_class)->finalize (object);
     335                 :          3 : }
     336                 :            : 
     337                 :            : static void
     338                 :          0 : mpegts_parse_set_property (GObject * object, guint prop_id,
     339                 :            :     const GValue * value, GParamSpec * pspec)
     340                 :            : {
     341                 :          0 :   MpegTSParse *parse = GST_MPEGTS_PARSE (object);
     342                 :            : 
     343         [ #  # ]:          0 :   switch (prop_id) {
     344                 :            :     case PROP_PROGRAM_NUMBERS:
     345                 :          0 :       mpegts_parse_reset_selected_programs (parse, g_value_dup_string (value));
     346                 :          0 :       break;
     347                 :            :     default:
     348                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     349                 :            :   }
     350                 :          0 : }
     351                 :            : 
     352                 :            : static void
     353                 :          0 : mpegts_parse_get_property (GObject * object, guint prop_id,
     354                 :            :     GValue * value, GParamSpec * pspec)
     355                 :            : {
     356                 :          0 :   MpegTSParse *parse = GST_MPEGTS_PARSE (object);
     357                 :            : 
     358         [ #  # ]:          0 :   switch (prop_id) {
     359                 :            :     case PROP_PROGRAM_NUMBERS:
     360                 :          0 :       g_value_set_string (value, parse->program_numbers);
     361                 :          0 :       break;
     362                 :            :     default:
     363                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     364                 :            :   }
     365                 :          0 : }
     366                 :            : 
     367                 :            : static MpegTSParseProgram *
     368                 :          0 : mpegts_parse_add_program (MpegTSParse * parse,
     369                 :            :     gint program_number, guint16 pmt_pid)
     370                 :            : {
     371                 :            :   MpegTSParseProgram *program;
     372                 :            : 
     373                 :          0 :   program = g_new0 (MpegTSParseProgram, 1);
     374                 :          0 :   program->program_number = program_number;
     375                 :          0 :   program->pmt_pid = pmt_pid;
     376                 :          0 :   program->pcr_pid = G_MAXUINT16;
     377                 :          0 :   program->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
     378                 :            :       NULL, (GDestroyNotify) mpegts_parse_free_stream);
     379                 :          0 :   program->patcount = 0;
     380                 :          0 :   program->selected = 0;
     381                 :          0 :   program->active = FALSE;
     382                 :            : 
     383                 :          0 :   g_hash_table_insert (parse->programs,
     384                 :          0 :       GINT_TO_POINTER (program_number), program);
     385                 :            : 
     386                 :          0 :   return program;
     387                 :            : }
     388                 :            : 
     389                 :            : static MpegTSParseProgram *
     390                 :          0 : mpegts_parse_get_program (MpegTSParse * parse, gint program_number)
     391                 :            : {
     392                 :            :   MpegTSParseProgram *program;
     393                 :            : 
     394                 :          0 :   program = (MpegTSParseProgram *) g_hash_table_lookup (parse->programs,
     395                 :          0 :       GINT_TO_POINTER ((gint) program_number));
     396                 :            : 
     397                 :          0 :   return program;
     398                 :            : }
     399                 :            : 
     400                 :            : static GstPad *
     401                 :          0 : mpegts_parse_activate_program (MpegTSParse * parse,
     402                 :            :     MpegTSParseProgram * program)
     403                 :            : {
     404                 :            :   MpegTSParsePad *tspad;
     405                 :            :   gchar *pad_name;
     406                 :            : 
     407                 :          0 :   pad_name = g_strdup_printf ("program_%d", program->program_number);
     408                 :            : 
     409                 :          0 :   tspad = mpegts_parse_create_tspad (parse, pad_name);
     410                 :          0 :   tspad->program_number = program->program_number;
     411                 :          0 :   tspad->program = program;
     412                 :          0 :   program->tspad = tspad;
     413                 :          0 :   g_free (pad_name);
     414                 :          0 :   gst_pad_set_active (tspad->pad, TRUE);
     415                 :          0 :   program->active = TRUE;
     416                 :            : 
     417                 :          0 :   return tspad->pad;
     418                 :            : }
     419                 :            : 
     420                 :            : static GstPad *
     421                 :          0 : mpegts_parse_deactivate_program (MpegTSParse * parse,
     422                 :            :     MpegTSParseProgram * program)
     423                 :            : {
     424                 :            :   MpegTSParsePad *tspad;
     425                 :            : 
     426                 :          0 :   tspad = program->tspad;
     427                 :          0 :   gst_pad_set_active (tspad->pad, FALSE);
     428                 :          0 :   program->active = FALSE;
     429                 :            : 
     430                 :            :   /* tspad will be destroyed in GstElementClass::pad_removed */
     431                 :            : 
     432                 :          0 :   return tspad->pad;
     433                 :            : }
     434                 :            : 
     435                 :            : static void
     436                 :          0 : mpegts_parse_free_program (MpegTSParseProgram * program)
     437                 :            : {
     438         [ #  # ]:          0 :   if (program->pmt_info)
     439                 :          0 :     gst_structure_free (program->pmt_info);
     440                 :            : 
     441                 :          0 :   g_hash_table_destroy (program->streams);
     442                 :            : 
     443                 :          0 :   g_free (program);
     444                 :          0 : }
     445                 :            : 
     446                 :            : static void
     447                 :          0 : mpegts_parse_remove_program (MpegTSParse * parse, gint program_number)
     448                 :            : {
     449                 :          0 :   g_hash_table_remove (parse->programs, GINT_TO_POINTER (program_number));
     450                 :          0 : }
     451                 :            : 
     452                 :            : static void
     453                 :          0 : mpegts_parse_sync_program_pads (MpegTSParse * parse)
     454                 :            : {
     455                 :            :   GList *walk;
     456                 :            : 
     457         [ #  # ]:          0 :   GST_INFO_OBJECT (parse, "begin sync pads");
     458         [ #  # ]:          0 :   for (walk = parse->pads_to_remove; walk; walk = walk->next)
     459                 :          0 :     gst_element_remove_pad (GST_ELEMENT (parse), GST_PAD (walk->data));
     460                 :            : 
     461         [ #  # ]:          0 :   for (walk = parse->pads_to_add; walk; walk = walk->next)
     462                 :          0 :     gst_element_add_pad (GST_ELEMENT (parse), GST_PAD (walk->data));
     463                 :            : 
     464         [ #  # ]:          0 :   if (parse->pads_to_add)
     465                 :          0 :     g_list_free (parse->pads_to_add);
     466                 :            : 
     467         [ #  # ]:          0 :   if (parse->pads_to_remove)
     468                 :          0 :     g_list_free (parse->pads_to_remove);
     469                 :            : 
     470                 :          0 :   GST_OBJECT_LOCK (parse);
     471                 :          0 :   parse->pads_to_remove = NULL;
     472                 :          0 :   parse->pads_to_add = NULL;
     473                 :          0 :   parse->need_sync_program_pads = FALSE;
     474                 :          0 :   GST_OBJECT_UNLOCK (parse);
     475                 :            : 
     476         [ #  # ]:          0 :   GST_INFO_OBJECT (parse, "end sync pads");
     477                 :          0 : }
     478                 :            : 
     479                 :            : 
     480                 :            : static MpegTSParseStream *
     481                 :          0 : mpegts_parse_program_add_stream (MpegTSParse * parse,
     482                 :            :     MpegTSParseProgram * program, guint16 pid, guint8 stream_type)
     483                 :            : {
     484                 :            :   MpegTSParseStream *stream;
     485                 :            : 
     486                 :          0 :   stream = g_new0 (MpegTSParseStream, 1);
     487                 :          0 :   stream->pid = pid;
     488                 :          0 :   stream->stream_type = stream_type;
     489                 :            : 
     490                 :          0 :   g_hash_table_insert (program->streams, GINT_TO_POINTER ((gint) pid), stream);
     491                 :            : 
     492                 :          0 :   return stream;
     493                 :            : }
     494                 :            : 
     495                 :            : static void
     496                 :          0 : foreach_program_activate_or_deactivate (gpointer key, gpointer value,
     497                 :            :     gpointer data)
     498                 :            : {
     499                 :          0 :   MpegTSParse *parse = GST_MPEGTS_PARSE (data);
     500                 :          0 :   MpegTSParseProgram *program = (MpegTSParseProgram *) value;
     501                 :            : 
     502                 :            :   /* at this point selected programs have program->selected == 2,
     503                 :            :    * unselected programs thay may have to be deactivated have selected == 1 and
     504                 :            :    * unselected inactive programs have selected == 0 */
     505                 :            : 
     506   [ #  #  #  # ]:          0 :   switch (--program->selected) {
     507                 :            :     case 1:
     508                 :            :       /* selected */
     509 [ #  # ][ #  # ]:          0 :       if (!program->active && program->pmt_pid != G_MAXUINT16)
     510                 :          0 :         parse->pads_to_add = g_list_append (parse->pads_to_add,
     511                 :          0 :             mpegts_parse_activate_program (parse, program));
     512                 :          0 :       break;
     513                 :            :     case 0:
     514                 :            :       /* unselected */
     515         [ #  # ]:          0 :       if (program->active)
     516                 :          0 :         parse->pads_to_remove = g_list_append (parse->pads_to_remove,
     517                 :          0 :             mpegts_parse_deactivate_program (parse, program));
     518                 :          0 :       break;
     519                 :            :     case -1:
     520                 :            :       /* was already unselected */
     521                 :          0 :       program->selected = 0;
     522                 :          0 :       break;
     523                 :            :     default:
     524                 :          0 :       g_return_if_reached ();
     525                 :            :   }
     526                 :            : }
     527                 :            : 
     528                 :            : static void
     529                 :          0 : mpegts_parse_reset_selected_programs (MpegTSParse * parse,
     530                 :            :     gchar * program_numbers)
     531                 :            : {
     532                 :          0 :   GST_OBJECT_LOCK (parse);
     533         [ #  # ]:          0 :   if (parse->program_numbers)
     534                 :          0 :     g_free (parse->program_numbers);
     535                 :            : 
     536                 :          0 :   parse->program_numbers = program_numbers;
     537                 :            : 
     538         [ #  # ]:          0 :   if (*parse->program_numbers != '\0') {
     539                 :            :     gint program_number;
     540                 :            :     MpegTSParseProgram *program;
     541                 :            :     gchar **progs, **walk;
     542                 :            : 
     543                 :          0 :     progs = g_strsplit (parse->program_numbers, ":", 0);
     544                 :            : 
     545                 :          0 :     walk = progs;
     546         [ #  # ]:          0 :     while (*walk != NULL) {
     547                 :          0 :       program_number = strtol (*walk, NULL, 0);
     548                 :          0 :       program = mpegts_parse_get_program (parse, program_number);
     549         [ #  # ]:          0 :       if (program == NULL)
     550                 :            :         /* create the program, it will get activated once we get a PMT for it */
     551                 :          0 :         program = mpegts_parse_add_program (parse, program_number, G_MAXUINT16);
     552                 :            : 
     553                 :          0 :       program->selected = 2;
     554                 :          0 :       ++walk;
     555                 :            :     }
     556                 :          0 :     g_strfreev (progs);
     557                 :            :   }
     558                 :            : 
     559                 :          0 :   g_hash_table_foreach (parse->programs,
     560                 :            :       foreach_program_activate_or_deactivate, parse);
     561                 :            : 
     562 [ #  # ][ #  # ]:          0 :   if (parse->pads_to_remove || parse->pads_to_add)
     563                 :          0 :     parse->need_sync_program_pads = TRUE;
     564                 :          0 :   GST_OBJECT_UNLOCK (parse);
     565                 :          0 : }
     566                 :            : 
     567                 :            : static void
     568                 :          0 : mpegts_parse_free_stream (MpegTSParseStream * stream)
     569                 :            : {
     570                 :          0 :   g_free (stream);
     571                 :          0 : }
     572                 :            : 
     573                 :            : static void
     574                 :          0 : mpegts_parse_program_remove_stream (MpegTSParse * parse,
     575                 :            :     MpegTSParseProgram * program, guint16 pid)
     576                 :            : {
     577                 :          0 :   g_hash_table_remove (program->streams, GINT_TO_POINTER ((gint) pid));
     578                 :          0 : }
     579                 :            : 
     580                 :            : static void
     581                 :          0 : mpegts_parse_deactivate_pmt (MpegTSParse * parse, MpegTSParseProgram * program)
     582                 :            : {
     583                 :            :   gint i;
     584                 :            :   guint pid;
     585                 :            :   guint stream_type;
     586                 :            :   GstStructure *stream;
     587                 :            :   const GValue *streams;
     588                 :            :   const GValue *value;
     589                 :            : 
     590         [ #  # ]:          0 :   if (program->pmt_info) {
     591                 :          0 :     streams = gst_structure_id_get_value (program->pmt_info, QUARK_STREAMS);
     592                 :            : 
     593         [ #  # ]:          0 :     for (i = 0; i < gst_value_list_get_size (streams); ++i) {
     594                 :          0 :       value = gst_value_list_get_value (streams, i);
     595                 :          0 :       stream = g_value_get_boxed (value);
     596                 :          0 :       gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
     597                 :            :           QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
     598                 :          0 :       mpegts_parse_program_remove_stream (parse, program, (guint16) pid);
     599                 :          0 :       g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid));
     600                 :            :     }
     601                 :            : 
     602                 :            :     /* remove pcr stream */
     603                 :          0 :     mpegts_parse_program_remove_stream (parse, program, program->pcr_pid);
     604                 :          0 :     g_hash_table_remove (parse->pes_pids,
     605                 :          0 :         GINT_TO_POINTER ((gint) program->pcr_pid));
     606                 :            :   }
     607                 :          0 : }
     608                 :            : 
     609                 :            : static MpegTSParsePad *
     610                 :          0 : mpegts_parse_create_tspad (MpegTSParse * parse, const gchar * pad_name)
     611                 :            : {
     612                 :            :   GstPad *pad;
     613                 :            :   MpegTSParsePad *tspad;
     614                 :            : 
     615                 :          0 :   pad = gst_pad_new_from_static_template (&program_template, pad_name);
     616                 :          0 :   gst_pad_set_query_function (pad,
     617                 :          0 :       GST_DEBUG_FUNCPTR (mpegts_parse_src_pad_query));
     618                 :            : 
     619                 :            :   /* create our wrapper */
     620                 :          0 :   tspad = g_new0 (MpegTSParsePad, 1);
     621                 :          0 :   tspad->pad = pad;
     622                 :          0 :   tspad->program_number = -1;
     623                 :          0 :   tspad->program = NULL;
     624                 :          0 :   tspad->pushed = FALSE;
     625                 :          0 :   tspad->flow_return = GST_FLOW_NOT_LINKED;
     626                 :          0 :   gst_pad_set_element_private (pad, tspad);
     627                 :            : 
     628                 :          0 :   return tspad;
     629                 :            : }
     630                 :            : 
     631                 :            : static void
     632                 :          0 : mpegts_parse_destroy_tspad (MpegTSParse * parse, MpegTSParsePad * tspad)
     633                 :            : {
     634         [ #  # ]:          0 :   if (tspad->tags) {
     635                 :          0 :     gst_tag_list_free (tspad->tags);
     636                 :            :   }
     637                 :            : 
     638                 :            :   /* free the wrapper */
     639                 :          0 :   g_free (tspad);
     640                 :          0 : }
     641                 :            : 
     642                 :            : static void
     643                 :          3 : mpegts_parse_pad_removed (GstElement * element, GstPad * pad)
     644                 :            : {
     645                 :            :   MpegTSParsePad *tspad;
     646                 :          3 :   MpegTSParse *parse = GST_MPEGTS_PARSE (element);
     647                 :            : 
     648         [ +  - ]:          3 :   if (gst_pad_get_direction (pad) == GST_PAD_SINK)
     649                 :          3 :     return;
     650                 :            : 
     651                 :          0 :   tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad);
     652                 :          0 :   mpegts_parse_destroy_tspad (parse, tspad);
     653                 :            : 
     654         [ #  # ]:          0 :   if (GST_ELEMENT_CLASS (parent_class)->pad_removed)
     655                 :          0 :     GST_ELEMENT_CLASS (parent_class)->pad_removed (element, pad);
     656                 :            : }
     657                 :            : 
     658                 :            : static GstPad *
     659                 :          0 : mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template,
     660                 :            :     const gchar * unused)
     661                 :            : {
     662                 :            :   MpegTSParse *parse;
     663                 :            :   gchar *name;
     664                 :            :   GstPad *pad;
     665                 :            : 
     666         [ #  # ]:          0 :   g_return_val_if_fail (template != NULL, NULL);
     667 [ #  # ][ #  # ]:          0 :   g_return_val_if_fail (GST_IS_MPEGTS_PARSE (element), NULL);
         [ #  # ][ #  # ]
     668                 :            : 
     669                 :          0 :   parse = GST_MPEGTS_PARSE (element);
     670                 :            : 
     671                 :          0 :   GST_OBJECT_LOCK (element);
     672                 :          0 :   name = g_strdup_printf ("src%d", parse->req_pads++);
     673                 :          0 :   GST_OBJECT_UNLOCK (element);
     674                 :            : 
     675                 :          0 :   pad = mpegts_parse_create_tspad (parse, name)->pad;
     676                 :          0 :   gst_pad_set_active (pad, TRUE);
     677                 :          0 :   gst_element_add_pad (element, pad);
     678                 :          0 :   g_free (name);
     679                 :            : 
     680                 :          0 :   return pad;
     681                 :            : }
     682                 :            : 
     683                 :            : static void
     684                 :          0 : mpegts_parse_release_pad (GstElement * element, GstPad * pad)
     685                 :            : {
     686 [ #  # ][ #  # ]:          0 :   g_return_if_fail (GST_IS_MPEGTS_PARSE (element));
         [ #  # ][ #  # ]
     687                 :            : 
     688                 :          0 :   gst_pad_set_active (pad, FALSE);
     689                 :            :   /* we do the cleanup in GstElement::pad-removed */
     690                 :          0 :   gst_element_remove_pad (element, pad);
     691                 :            : }
     692                 :            : 
     693                 :            : static GstFlowReturn
     694                 :          0 : mpegts_parse_tspad_push_section (MpegTSParse * parse, MpegTSParsePad * tspad,
     695                 :            :     MpegTSPacketizerSection * section, GstBuffer * buffer)
     696                 :            : {
     697                 :          0 :   GstFlowReturn ret = GST_FLOW_NOT_LINKED;
     698                 :          0 :   gboolean to_push = TRUE;
     699                 :            : 
     700         [ #  # ]:          0 :   if (tspad->program_number != -1) {
     701         [ #  # ]:          0 :     if (tspad->program) {
     702                 :            :       /* we push all sections to all pads except PMTs which we
     703                 :            :        * only push to pads meant to receive that program number */
     704         [ #  # ]:          0 :       if (section->table_id == 0x02) {
     705                 :            :         /* PMT */
     706         [ #  # ]:          0 :         if (section->subtable_extension != tspad->program_number)
     707                 :          0 :           to_push = FALSE;
     708                 :            :       }
     709                 :            :     } else {
     710                 :            :       /* there's a program filter on the pad but the PMT for the program has not
     711                 :            :        * been parsed yet, ignore the pad until we get a PMT */
     712                 :          0 :       to_push = FALSE;
     713                 :          0 :       ret = GST_FLOW_OK;
     714                 :            :     }
     715                 :            :   }
     716         [ #  # ]:          0 :   GST_DEBUG_OBJECT (parse,
     717                 :            :       "pushing section: %d program number: %d table_id: %d", to_push,
     718                 :            :       tspad->program_number, section->table_id);
     719         [ #  # ]:          0 :   if (to_push) {
     720                 :          0 :     ret = gst_pad_push (tspad->pad, buffer);
     721                 :            :   } else {
     722                 :          0 :     gst_buffer_unref (buffer);
     723         [ #  # ]:          0 :     if (gst_pad_is_linked (tspad->pad))
     724                 :          0 :       ret = GST_FLOW_OK;
     725                 :            :   }
     726                 :            : 
     727                 :          0 :   return ret;
     728                 :            : }
     729                 :            : 
     730                 :            : static GstFlowReturn
     731                 :          0 : mpegts_parse_tspad_push (MpegTSParse * parse, MpegTSParsePad * tspad,
     732                 :            :     guint16 pid, GstBuffer * buffer)
     733                 :            : {
     734                 :          0 :   GstFlowReturn ret = GST_FLOW_NOT_LINKED;
     735                 :          0 :   GHashTable *pad_pids = NULL;
     736                 :            : 
     737         [ #  # ]:          0 :   if (tspad->program_number != -1) {
     738         [ #  # ]:          0 :     if (tspad->program) {
     739                 :          0 :       pad_pids = tspad->program->streams;
     740                 :            : 
     741         [ #  # ]:          0 :       if (tspad->tags) {
     742                 :          0 :         gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse),
     743                 :            :             tspad->pad, tspad->tags);
     744                 :          0 :         tspad->tags = NULL;
     745                 :            :       }
     746                 :            :     } else {
     747                 :            :       /* there's a program filter on the pad but the PMT for the program has not
     748                 :            :        * been parsed yet, ignore the pad until we get a PMT */
     749                 :          0 :       gst_buffer_unref (buffer);
     750                 :          0 :       ret = GST_FLOW_OK;
     751                 :          0 :       goto out;
     752                 :            :     }
     753                 :            :   }
     754                 :            : 
     755   [ #  #  #  # ]:          0 :   if (pad_pids == NULL ||
     756                 :          0 :       g_hash_table_lookup (pad_pids, GINT_TO_POINTER ((gint) pid)) != NULL) {
     757                 :            :     /* push if there's no filter or if the pid is in the filter */
     758                 :          0 :     ret = gst_pad_push (tspad->pad, buffer);
     759                 :            :   } else {
     760                 :          0 :     gst_buffer_unref (buffer);
     761         [ #  # ]:          0 :     if (gst_pad_is_linked (tspad->pad))
     762                 :          0 :       ret = GST_FLOW_OK;
     763                 :            :   }
     764                 :            : 
     765                 :            : out:
     766                 :          0 :   return ret;
     767                 :            : }
     768                 :            : 
     769                 :            : static void
     770                 :          0 : pad_clear_for_push (GstPad * pad, MpegTSParse * parse)
     771                 :            : {
     772                 :          0 :   MpegTSParsePad *tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad);
     773                 :            : 
     774                 :          0 :   tspad->flow_return = GST_FLOW_NOT_LINKED;
     775                 :          0 :   tspad->pushed = FALSE;
     776                 :          0 : }
     777                 :            : 
     778                 :            : static GstFlowReturn
     779                 :          0 : mpegts_parse_push (MpegTSParse * parse, MpegTSPacketizerPacket * packet,
     780                 :            :     MpegTSPacketizerSection * section)
     781                 :            : {
     782                 :            :   guint32 pads_cookie;
     783                 :          0 :   gboolean done = FALSE;
     784                 :          0 :   GstPad *pad = NULL;
     785                 :            :   MpegTSParsePad *tspad;
     786                 :            :   guint16 pid;
     787                 :            :   GstBuffer *buffer;
     788                 :            :   GstFlowReturn ret;
     789                 :            :   GList *srcpads;
     790                 :            : 
     791                 :          0 :   pid = packet->pid;
     792                 :          0 :   buffer = gst_buffer_make_metadata_writable (packet->buffer);
     793                 :            :   /* we have the same caps on all the src pads */
     794                 :          0 :   gst_buffer_set_caps (buffer, parse->packetizer->caps);
     795                 :            : 
     796                 :          0 :   GST_OBJECT_LOCK (parse);
     797                 :            :   /* clear tspad->pushed on pads */
     798                 :          0 :   g_list_foreach (GST_ELEMENT_CAST (parse)->srcpads,
     799                 :            :       (GFunc) pad_clear_for_push, parse);
     800         [ #  # ]:          0 :   if (GST_ELEMENT_CAST (parse)->srcpads)
     801                 :          0 :     ret = GST_FLOW_NOT_LINKED;
     802                 :            :   else
     803                 :          0 :     ret = GST_FLOW_OK;
     804                 :            : 
     805                 :            :   /* Get cookie and source pads list */
     806                 :          0 :   pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie;
     807                 :          0 :   srcpads = GST_ELEMENT_CAST (parse)->srcpads;
     808         [ #  # ]:          0 :   if (G_LIKELY (srcpads)) {
     809                 :          0 :     pad = GST_PAD_CAST (srcpads->data);
     810                 :          0 :     g_object_ref (pad);
     811                 :            :   }
     812                 :          0 :   GST_OBJECT_UNLOCK (parse);
     813                 :            : 
     814 [ #  # ][ #  # ]:          0 :   while (pad && !done) {
     815                 :          0 :     tspad = gst_pad_get_element_private (pad);
     816                 :            : 
     817         [ #  # ]:          0 :     if (G_LIKELY (!tspad->pushed)) {
     818                 :            :       /* ref the buffer as gst_pad_push takes a ref but we want to reuse the
     819                 :            :        * same buffer for next pushes */
     820                 :          0 :       gst_buffer_ref (buffer);
     821         [ #  # ]:          0 :       if (section) {
     822                 :          0 :         tspad->flow_return =
     823                 :          0 :             mpegts_parse_tspad_push_section (parse, tspad, section, buffer);
     824                 :            :       } else {
     825                 :          0 :         tspad->flow_return =
     826                 :          0 :             mpegts_parse_tspad_push (parse, tspad, pid, buffer);
     827                 :            :       }
     828                 :          0 :       tspad->pushed = TRUE;
     829                 :            : 
     830 [ #  # ][ #  # ]:          0 :       if (G_UNLIKELY (tspad->flow_return != GST_FLOW_OK
     831                 :            :               && tspad->flow_return != GST_FLOW_NOT_LINKED)) {
     832                 :            :         /* return the error upstream */
     833                 :          0 :         ret = tspad->flow_return;
     834                 :          0 :         done = TRUE;
     835                 :            :       }
     836                 :            : 
     837                 :            :     }
     838                 :            : 
     839         [ #  # ]:          0 :     if (ret == GST_FLOW_NOT_LINKED)
     840                 :          0 :       ret = tspad->flow_return;
     841                 :            : 
     842                 :          0 :     g_object_unref (pad);
     843                 :            : 
     844         [ #  # ]:          0 :     if (G_UNLIKELY (!done)) {
     845                 :          0 :       GST_OBJECT_LOCK (parse);
     846         [ #  # ]:          0 :       if (G_UNLIKELY (pads_cookie != GST_ELEMENT_CAST (parse)->pads_cookie)) {
     847                 :            :         /* resync */
     848         [ #  # ]:          0 :         GST_DEBUG ("resync");
     849                 :          0 :         pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie;
     850                 :          0 :         srcpads = GST_ELEMENT_CAST (parse)->srcpads;
     851                 :            :       } else {
     852         [ #  # ]:          0 :         GST_DEBUG ("getting next pad");
     853                 :            :         /* Get next pad */
     854         [ #  # ]:          0 :         srcpads = g_list_next (srcpads);
     855                 :            :       }
     856                 :            : 
     857         [ #  # ]:          0 :       if (srcpads) {
     858                 :          0 :         pad = GST_PAD_CAST (srcpads->data);
     859                 :          0 :         g_object_ref (pad);
     860                 :            :       } else
     861                 :          0 :         done = TRUE;
     862                 :          0 :       GST_OBJECT_UNLOCK (parse);
     863                 :            :     }
     864                 :            :   }
     865                 :            : 
     866                 :          0 :   gst_buffer_unref (buffer);
     867                 :          0 :   packet->buffer = NULL;
     868                 :            : 
     869                 :          0 :   return ret;
     870                 :            : }
     871                 :            : 
     872                 :            : static gboolean
     873                 :          0 : mpegts_parse_is_psi (MpegTSParse * parse, MpegTSPacketizerPacket * packet)
     874                 :            : {
     875                 :          0 :   gboolean retval = FALSE;
     876                 :            :   guint8 table_id;
     877                 :            :   int i;
     878                 :            :   static const guint8 si_tables[] =
     879                 :            :       { 0x00, 0x01, 0x02, 0x03, 0x40, 0x41, 0x42, 0x46, 0x4A, 0x4E, 0x4F, 0x50,
     880                 :            :     0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
     881                 :            :     0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
     882                 :            :     0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x7E,
     883                 :            :     0x7F, TABLE_ID_UNSET
     884                 :            :   };
     885         [ #  # ]:          0 :   if (g_hash_table_lookup (parse->psi_pids,
     886                 :          0 :           GINT_TO_POINTER ((gint) packet->pid)) != NULL)
     887                 :          0 :     retval = TRUE;
     888                 :            :   /* check is it is a pes pid */
     889         [ #  # ]:          0 :   if (g_hash_table_lookup (parse->pes_pids,
     890                 :          0 :           GINT_TO_POINTER ((gint) packet->pid)) != NULL)
     891                 :          0 :     return FALSE;
     892         [ #  # ]:          0 :   if (!retval) {
     893         [ #  # ]:          0 :     if (packet->payload_unit_start_indicator) {
     894                 :          0 :       table_id = *(packet->data);
     895                 :          0 :       i = 0;
     896         [ #  # ]:          0 :       while (si_tables[i] != TABLE_ID_UNSET) {
     897         [ #  # ]:          0 :         if (G_UNLIKELY (si_tables[i] == table_id)) {
     898         [ #  # ]:          0 :           GST_DEBUG_OBJECT (parse, "Packet has table id 0x%x", table_id);
     899                 :          0 :           retval = TRUE;
     900                 :          0 :           break;
     901                 :            :         }
     902                 :          0 :         i++;
     903                 :            :       }
     904                 :            :     } else {
     905                 :          0 :       MpegTSPacketizerStream *stream = parse->packetizer->streams[packet->pid];
     906         [ #  # ]:          0 :       if (stream) {
     907                 :          0 :         i = 0;
     908         [ #  # ]:          0 :         GST_DEBUG_OBJECT (parse, "section table id: 0x%x",
     909                 :            :             stream->section_table_id);
     910         [ #  # ]:          0 :         while (si_tables[i] != TABLE_ID_UNSET) {
     911         [ #  # ]:          0 :           if (G_UNLIKELY (si_tables[i] == stream->section_table_id)) {
     912                 :          0 :             retval = TRUE;
     913                 :          0 :             break;
     914                 :            :           }
     915                 :          0 :           i++;
     916                 :            :         }
     917                 :            :       }
     918                 :            :     }
     919                 :            :   }
     920                 :            : 
     921         [ #  # ]:          0 :   GST_DEBUG_OBJECT (parse, "Packet of pid 0x%x is psi: %d", packet->pid,
     922                 :            :       retval);
     923                 :          0 :   return retval;
     924                 :            : }
     925                 :            : 
     926                 :            : static void
     927                 :          0 : mpegts_parse_apply_pat (MpegTSParse * parse, GstStructure * pat_info)
     928                 :            : {
     929                 :            :   const GValue *value;
     930                 :            :   GstStructure *old_pat;
     931                 :            :   GstStructure *program_info;
     932                 :            :   guint program_number;
     933                 :            :   guint pid;
     934                 :            :   MpegTSParseProgram *program;
     935                 :            :   gint i;
     936                 :            :   const GValue *programs;
     937                 :            : 
     938                 :          0 :   old_pat = parse->pat;
     939                 :          0 :   parse->pat = gst_structure_copy (pat_info);
     940                 :            : 
     941         [ #  # ]:          0 :   GST_INFO_OBJECT (parse, "PAT %" GST_PTR_FORMAT, pat_info);
     942                 :            : 
     943                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
     944                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
     945                 :            :           gst_structure_copy (pat_info)));
     946                 :            : 
     947                 :          0 :   GST_OBJECT_LOCK (parse);
     948                 :          0 :   programs = gst_structure_id_get_value (pat_info, QUARK_PROGRAMS);
     949                 :            :   /* activate the new table */
     950         [ #  # ]:          0 :   for (i = 0; i < gst_value_list_get_size (programs); ++i) {
     951                 :          0 :     value = gst_value_list_get_value (programs, i);
     952                 :            : 
     953                 :          0 :     program_info = g_value_get_boxed (value);
     954                 :          0 :     gst_structure_id_get (program_info, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
     955                 :            :         &program_number, QUARK_PID, G_TYPE_UINT, &pid, NULL);
     956                 :            : 
     957                 :          0 :     program = mpegts_parse_get_program (parse, program_number);
     958         [ #  # ]:          0 :     if (program) {
     959         [ #  # ]:          0 :       if (program->pmt_pid != pid) {
     960         [ #  # ]:          0 :         if (program->pmt_pid != G_MAXUINT16) {
     961                 :            :           /* pmt pid changed */
     962                 :          0 :           g_hash_table_remove (parse->psi_pids,
     963                 :          0 :               GINT_TO_POINTER ((gint) program->pmt_pid));
     964                 :            :         }
     965                 :            : 
     966                 :          0 :         program->pmt_pid = pid;
     967                 :          0 :         g_hash_table_insert (parse->psi_pids,
     968                 :          0 :             GINT_TO_POINTER ((gint) pid), GINT_TO_POINTER (1));
     969                 :            :       }
     970                 :            :     } else {
     971                 :          0 :       g_hash_table_insert (parse->psi_pids,
     972                 :          0 :           GINT_TO_POINTER ((gint) pid), GINT_TO_POINTER (1));
     973                 :          0 :       program = mpegts_parse_add_program (parse, program_number, pid);
     974                 :            :     }
     975                 :          0 :     program->patcount += 1;
     976 [ #  # ][ #  # ]:          0 :     if (program->selected && !program->active)
     977                 :          0 :       parse->pads_to_add = g_list_append (parse->pads_to_add,
     978                 :          0 :           mpegts_parse_activate_program (parse, program));
     979                 :            :   }
     980                 :            : 
     981         [ #  # ]:          0 :   if (old_pat) {
     982                 :            :     /* deactivate the old table */
     983                 :            : 
     984                 :          0 :     programs = gst_structure_id_get_value (old_pat, QUARK_PROGRAMS);
     985         [ #  # ]:          0 :     for (i = 0; i < gst_value_list_get_size (programs); ++i) {
     986                 :          0 :       value = gst_value_list_get_value (programs, i);
     987                 :            : 
     988                 :          0 :       program_info = g_value_get_boxed (value);
     989                 :          0 :       gst_structure_id_get (program_info,
     990                 :            :           QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number,
     991                 :            :           QUARK_PID, G_TYPE_UINT, &pid, NULL);
     992                 :            : 
     993                 :          0 :       program = mpegts_parse_get_program (parse, program_number);
     994         [ #  # ]:          0 :       if (program == NULL) {
     995         [ #  # ]:          0 :         GST_DEBUG_OBJECT (parse, "broken PAT, duplicated entry for program %d",
     996                 :            :             program_number);
     997                 :          0 :         continue;
     998                 :            :       }
     999                 :            : 
    1000         [ #  # ]:          0 :       if (--program->patcount > 0)
    1001                 :            :         /* the program has been referenced by the new pat, keep it */
    1002                 :          0 :         continue;
    1003                 :            : 
    1004         [ #  # ]:          0 :       GST_INFO_OBJECT (parse, "PAT removing program %" GST_PTR_FORMAT,
    1005                 :            :           program_info);
    1006                 :            : 
    1007         [ #  # ]:          0 :       if (program->active)
    1008                 :          0 :         parse->pads_to_remove = g_list_append (parse->pads_to_remove,
    1009                 :          0 :             mpegts_parse_deactivate_program (parse, program));
    1010                 :            : 
    1011                 :          0 :       mpegts_parse_deactivate_pmt (parse, program);
    1012                 :          0 :       mpegts_parse_remove_program (parse, program_number);
    1013                 :          0 :       g_hash_table_remove (parse->psi_pids, GINT_TO_POINTER ((gint) pid));
    1014                 :          0 :       mpegts_packetizer_remove_stream (parse->packetizer, pid);
    1015                 :            :     }
    1016                 :            : 
    1017                 :          0 :     gst_structure_free (old_pat);
    1018                 :            :   }
    1019                 :            : 
    1020                 :          0 :   GST_OBJECT_UNLOCK (parse);
    1021                 :            : 
    1022                 :          0 :   mpegts_parse_sync_program_pads (parse);
    1023                 :          0 : }
    1024                 :            : 
    1025                 :            : static void
    1026                 :          0 : mpegts_parse_apply_pmt (MpegTSParse * parse,
    1027                 :            :     guint16 pmt_pid, GstStructure * pmt_info)
    1028                 :            : {
    1029                 :            :   MpegTSParseProgram *program;
    1030                 :            :   guint program_number;
    1031                 :            :   guint pcr_pid;
    1032                 :            :   guint pid;
    1033                 :            :   guint stream_type;
    1034                 :            :   GstStructure *stream;
    1035                 :            :   gint i;
    1036                 :            :   const GValue *new_streams;
    1037                 :            :   const GValue *value;
    1038                 :            : 
    1039                 :          0 :   gst_structure_id_get (pmt_info,
    1040                 :            :       QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number,
    1041                 :            :       QUARK_PCR_PID, G_TYPE_UINT, &pcr_pid, NULL);
    1042                 :          0 :   new_streams = gst_structure_id_get_value (pmt_info, QUARK_STREAMS);
    1043                 :            : 
    1044                 :          0 :   GST_OBJECT_LOCK (parse);
    1045                 :          0 :   program = mpegts_parse_get_program (parse, program_number);
    1046         [ #  # ]:          0 :   if (program) {
    1047                 :            :     /* deactivate old pmt */
    1048                 :          0 :     mpegts_parse_deactivate_pmt (parse, program);
    1049         [ #  # ]:          0 :     if (program->pmt_info)
    1050                 :          0 :       gst_structure_free (program->pmt_info);
    1051                 :          0 :     program->pmt_info = NULL;
    1052                 :            :   } else {
    1053                 :            :     /* no PAT?? */
    1054                 :          0 :     g_hash_table_insert (parse->psi_pids,
    1055                 :          0 :         GINT_TO_POINTER ((gint) pmt_pid), GINT_TO_POINTER (1));
    1056                 :          0 :     program = mpegts_parse_add_program (parse, program_number, pid);
    1057                 :            :   }
    1058                 :            : 
    1059                 :            :   /* activate new pmt */
    1060                 :          0 :   program->pmt_info = gst_structure_copy (pmt_info);
    1061                 :          0 :   program->pmt_pid = pmt_pid;
    1062                 :          0 :   program->pcr_pid = pcr_pid;
    1063                 :          0 :   mpegts_parse_program_add_stream (parse, program, (guint16) pcr_pid, -1);
    1064                 :          0 :   g_hash_table_insert (parse->pes_pids, GINT_TO_POINTER ((gint) pcr_pid),
    1065                 :            :       GINT_TO_POINTER (1));
    1066                 :            : 
    1067         [ #  # ]:          0 :   for (i = 0; i < gst_value_list_get_size (new_streams); ++i) {
    1068                 :          0 :     value = gst_value_list_get_value (new_streams, i);
    1069                 :          0 :     stream = g_value_get_boxed (value);
    1070                 :            : 
    1071                 :          0 :     gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid,
    1072                 :            :         QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL);
    1073                 :          0 :     mpegts_parse_program_add_stream (parse, program,
    1074                 :          0 :         (guint16) pid, (guint8) stream_type);
    1075                 :          0 :     g_hash_table_insert (parse->pes_pids, GINT_TO_POINTER ((gint) pid),
    1076                 :            :         GINT_TO_POINTER ((gint) 1));
    1077                 :            : 
    1078                 :            :   }
    1079                 :          0 :   GST_OBJECT_UNLOCK (parse);
    1080                 :            : 
    1081         [ #  # ]:          0 :   GST_DEBUG_OBJECT (parse, "new pmt %" GST_PTR_FORMAT, pmt_info);
    1082                 :            : 
    1083                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
    1084                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
    1085                 :            :           gst_structure_copy (pmt_info)));
    1086                 :          0 : }
    1087                 :            : 
    1088                 :            : static void
    1089                 :          0 : mpegts_parse_apply_nit (MpegTSParse * parse,
    1090                 :            :     guint16 pmt_pid, GstStructure * nit_info)
    1091                 :            : {
    1092                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
    1093                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
    1094                 :            :           gst_structure_copy (nit_info)));
    1095                 :          0 : }
    1096                 :            : 
    1097                 :            : static void
    1098                 :          0 : mpegts_parse_apply_sdt (MpegTSParse * parse,
    1099                 :            :     guint16 pmt_pid, GstStructure * sdt_info)
    1100                 :            : {
    1101                 :          0 :   mpegts_parse_get_tags_from_sdt (parse, sdt_info);
    1102                 :            : 
    1103                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
    1104                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
    1105                 :            :           gst_structure_copy (sdt_info)));
    1106                 :          0 : }
    1107                 :            : 
    1108                 :            : static void
    1109                 :          0 : mpegts_parse_apply_eit (MpegTSParse * parse,
    1110                 :            :     guint16 pmt_pid, GstStructure * eit_info)
    1111                 :            : {
    1112                 :          0 :   mpegts_parse_get_tags_from_eit (parse, eit_info);
    1113                 :            : 
    1114                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
    1115                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
    1116                 :            :           gst_structure_copy (eit_info)));
    1117                 :          0 : }
    1118                 :            : 
    1119                 :            : static void
    1120                 :          0 : mpegts_parse_apply_tdt (MpegTSParse * parse,
    1121                 :            :     guint16 tdt_pid, GstStructure * tdt_info)
    1122                 :            : {
    1123                 :          0 :   gst_element_post_message (GST_ELEMENT_CAST (parse),
    1124                 :          0 :       gst_message_new_element (GST_OBJECT (parse),
    1125                 :            :           gst_structure_copy (tdt_info)));
    1126                 :            : 
    1127                 :          0 :   gst_element_send_event (GST_ELEMENT_CAST (parse),
    1128                 :            :       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
    1129                 :            :           gst_structure_copy (tdt_info)));
    1130                 :          0 : }
    1131                 :            : 
    1132                 :            : static gboolean
    1133                 :          0 : mpegts_parse_handle_psi (MpegTSParse * parse, MpegTSPacketizerSection * section)
    1134                 :            : {
    1135                 :          0 :   gboolean res = TRUE;
    1136                 :          0 :   GstStructure *structure = NULL;
    1137                 :            : 
    1138                 :            :   /* table ids 0x70 - 0x73 do not have a crc */
    1139 [ #  # ][ #  # ]:          0 :   if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x73)) {
    1140         [ #  # ]:          0 :     if (G_UNLIKELY (mpegts_parse_calc_crc32 (GST_BUFFER_DATA (section->buffer),
    1141                 :            :                 GST_BUFFER_SIZE (section->buffer)) != 0)) {
    1142         [ #  # ]:          0 :       GST_WARNING_OBJECT (parse, "bad crc in psi pid 0x%x", section->pid);
    1143                 :          0 :       return FALSE;
    1144                 :            :     }
    1145                 :            :   }
    1146                 :            : 
    1147   [ #  #  #  #  :          0 :   switch (section->table_id) {
                #  #  # ]
    1148                 :            :     case 0x00:
    1149                 :            :       /* PAT */
    1150                 :          0 :       structure = mpegts_packetizer_parse_pat (parse->packetizer, section);
    1151         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1152                 :          0 :         mpegts_parse_apply_pat (parse, structure);
    1153                 :            :       else
    1154                 :          0 :         res = FALSE;
    1155                 :            : 
    1156                 :          0 :       break;
    1157                 :            :     case 0x02:
    1158                 :          0 :       structure = mpegts_packetizer_parse_pmt (parse->packetizer, section);
    1159         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1160                 :          0 :         mpegts_parse_apply_pmt (parse, section->pid, structure);
    1161                 :            :       else
    1162                 :          0 :         res = FALSE;
    1163                 :            : 
    1164                 :          0 :       break;
    1165                 :            :     case 0x40:
    1166                 :            :       /* NIT, actual network */
    1167                 :            :     case 0x41:
    1168                 :            :       /* NIT, other network */
    1169                 :          0 :       structure = mpegts_packetizer_parse_nit (parse->packetizer, section);
    1170         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1171                 :          0 :         mpegts_parse_apply_nit (parse, section->pid, structure);
    1172                 :            :       else
    1173                 :          0 :         res = FALSE;
    1174                 :            : 
    1175                 :          0 :       break;
    1176                 :            :     case 0x42:
    1177                 :            :     case 0x46:
    1178                 :          0 :       structure = mpegts_packetizer_parse_sdt (parse->packetizer, section);
    1179         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1180                 :          0 :         mpegts_parse_apply_sdt (parse, section->pid, structure);
    1181                 :            :       else
    1182                 :          0 :         res = FALSE;
    1183                 :          0 :       break;
    1184                 :            :     case 0x4E:
    1185                 :            :     case 0x4F:
    1186                 :            :       /* EIT, present/following */
    1187                 :            :     case 0x50:
    1188                 :            :     case 0x51:
    1189                 :            :     case 0x52:
    1190                 :            :     case 0x53:
    1191                 :            :     case 0x54:
    1192                 :            :     case 0x55:
    1193                 :            :     case 0x56:
    1194                 :            :     case 0x57:
    1195                 :            :     case 0x58:
    1196                 :            :     case 0x59:
    1197                 :            :     case 0x5A:
    1198                 :            :     case 0x5B:
    1199                 :            :     case 0x5C:
    1200                 :            :     case 0x5D:
    1201                 :            :     case 0x5E:
    1202                 :            :     case 0x5F:
    1203                 :            :     case 0x60:
    1204                 :            :     case 0x61:
    1205                 :            :     case 0x62:
    1206                 :            :     case 0x63:
    1207                 :            :     case 0x64:
    1208                 :            :     case 0x65:
    1209                 :            :     case 0x66:
    1210                 :            :     case 0x67:
    1211                 :            :     case 0x68:
    1212                 :            :     case 0x69:
    1213                 :            :     case 0x6A:
    1214                 :            :     case 0x6B:
    1215                 :            :     case 0x6C:
    1216                 :            :     case 0x6D:
    1217                 :            :     case 0x6E:
    1218                 :            :     case 0x6F:
    1219                 :            :       /* EIT, schedule */
    1220                 :          0 :       structure = mpegts_packetizer_parse_eit (parse->packetizer, section);
    1221         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1222                 :          0 :         mpegts_parse_apply_eit (parse, section->pid, structure);
    1223                 :            :       else
    1224                 :          0 :         res = FALSE;
    1225                 :          0 :       break;
    1226                 :            :     case 0x70:
    1227                 :            :       /* TDT (Time and Date table) */
    1228                 :          0 :       structure = mpegts_packetizer_parse_tdt (parse->packetizer, section);
    1229         [ #  # ]:          0 :       if (G_LIKELY (structure))
    1230                 :          0 :         mpegts_parse_apply_tdt (parse, section->pid, structure);
    1231                 :            :       else
    1232                 :          0 :         res = FALSE;
    1233                 :          0 :       break;
    1234                 :            :     default:
    1235                 :          0 :       break;
    1236                 :            :   }
    1237                 :            : 
    1238         [ #  # ]:          0 :   if (structure)
    1239                 :          0 :     gst_structure_free (structure);
    1240                 :            : 
    1241                 :          0 :   return res;
    1242                 :            : }
    1243                 :            : 
    1244                 :            : static void
    1245                 :          0 : mpegts_parse_get_tags_from_sdt (MpegTSParse * parse, GstStructure * sdt_info)
    1246                 :            : {
    1247                 :            :   const GValue *services;
    1248                 :            :   guint i;
    1249                 :            : 
    1250                 :          0 :   services = gst_structure_get_value (sdt_info, "services");
    1251                 :            : 
    1252         [ #  # ]:          0 :   for (i = 0; i < gst_value_list_get_size (services); i++) {
    1253                 :            :     const GstStructure *service;
    1254                 :            :     const gchar *sid_str;
    1255                 :            :     gchar *tmp;
    1256                 :            :     gint program_number;
    1257                 :            :     MpegTSParseProgram *program;
    1258                 :            : 
    1259                 :          0 :     service = gst_value_get_structure (gst_value_list_get_value (services, i));
    1260                 :            : 
    1261                 :            :     /* get program_number from structure name
    1262                 :            :      * which looks like service-%d */
    1263                 :          0 :     sid_str = gst_structure_get_name (service);
    1264                 :          0 :     tmp = g_strstr_len (sid_str, -1, "-");
    1265                 :          0 :     program_number = atoi (++tmp);
    1266                 :            : 
    1267                 :          0 :     program = mpegts_parse_get_program (parse, program_number);
    1268 [ #  # ][ #  # ]:          0 :     if (program && program->tspad && !program->tspad->tags) {
                 [ #  # ]
    1269                 :          0 :       program->tspad->tags = gst_tag_list_new_full (GST_TAG_ARTIST,
    1270                 :            :           gst_structure_get_string (service, "name"), NULL);
    1271                 :            :     }
    1272                 :            :   }
    1273                 :          0 : }
    1274                 :            : 
    1275                 :            : static void
    1276                 :          0 : mpegts_parse_get_tags_from_eit (MpegTSParse * parse, GstStructure * eit_info)
    1277                 :            : {
    1278                 :            :   const GValue *events;
    1279                 :            :   guint i;
    1280                 :            :   guint program_number;
    1281                 :            :   MpegTSParseProgram *program;
    1282                 :            :   gboolean present_following;
    1283                 :            : 
    1284                 :          0 :   gst_structure_get_uint (eit_info, "service-id", &program_number);
    1285                 :          0 :   program = mpegts_parse_get_program (parse, program_number);
    1286                 :            : 
    1287                 :          0 :   gst_structure_get_boolean (eit_info, "present-following", &present_following);
    1288                 :            : 
    1289 [ #  # ][ #  # ]:          0 :   if (program && program->tspad && present_following) {
                 [ #  # ]
    1290                 :          0 :     events = gst_structure_get_value (eit_info, "events");
    1291                 :            : 
    1292         [ #  # ]:          0 :     for (i = 0; i < gst_value_list_get_size (events); i++) {
    1293                 :            :       const GstStructure *event;
    1294                 :            :       const gchar *title;
    1295                 :            :       guint status;
    1296                 :            :       guint event_id;
    1297                 :            :       guint duration;
    1298                 :            : 
    1299                 :          0 :       event = gst_value_get_structure (gst_value_list_get_value (events, i));
    1300                 :            : 
    1301                 :          0 :       title = gst_structure_get_string (event, "name");
    1302                 :          0 :       gst_structure_get_uint (event, "event-id", &event_id);
    1303                 :          0 :       gst_structure_get_uint (event, "running-status", &status);
    1304                 :            : 
    1305 [ #  # ][ #  # ]:          0 :       if (title && event_id != program->tspad->event_id
    1306         [ #  # ]:          0 :           && status == RUNNING_STATUS_RUNNING) {
    1307                 :          0 :         gst_structure_get_uint (event, "duration", &duration);
    1308                 :            : 
    1309                 :          0 :         program->tspad->event_id = event_id;
    1310                 :          0 :         program->tspad->tags = gst_tag_list_new_full (GST_TAG_TITLE,
    1311                 :            :             title, GST_TAG_DURATION, duration * GST_SECOND, NULL);
    1312                 :            :       }
    1313                 :            :     }
    1314                 :            :   }
    1315                 :          0 : }
    1316                 :            : 
    1317                 :            : static gboolean
    1318                 :          0 : mpegts_parse_sink_event (GstPad * pad, GstEvent * event)
    1319                 :            : {
    1320                 :            :   gboolean res;
    1321                 :          0 :   MpegTSParse *parse =
    1322                 :          0 :       GST_MPEGTS_PARSE (gst_object_get_parent (GST_OBJECT (pad)));
    1323                 :            : 
    1324         [ #  # ]:          0 :   switch (GST_EVENT_TYPE (event)) {
    1325                 :            :     case GST_EVENT_FLUSH_STOP:
    1326                 :          0 :       mpegts_packetizer_clear (parse->packetizer);
    1327                 :          0 :       res = gst_pad_event_default (pad, event);
    1328                 :          0 :       break;
    1329                 :            :     default:
    1330                 :          0 :       res = gst_pad_event_default (pad, event);
    1331                 :            :   }
    1332                 :            : 
    1333                 :          0 :   gst_object_unref (parse);
    1334                 :          0 :   return res;
    1335                 :            : }
    1336                 :            : 
    1337                 :            : static GstFlowReturn
    1338                 :          0 : mpegts_parse_chain (GstPad * pad, GstBuffer * buf)
    1339                 :            : {
    1340                 :          0 :   GstFlowReturn res = GST_FLOW_OK;
    1341                 :            :   MpegTSParse *parse;
    1342                 :            :   gboolean parsed;
    1343                 :            :   MpegTSPacketizerPacketReturn pret;
    1344                 :            :   MpegTSPacketizer *packetizer;
    1345                 :            :   MpegTSPacketizerPacket packet;
    1346                 :            : 
    1347                 :          0 :   parse = GST_MPEGTS_PARSE (gst_object_get_parent (GST_OBJECT (pad)));
    1348                 :          0 :   packetizer = parse->packetizer;
    1349                 :            : 
    1350                 :          0 :   mpegts_packetizer_push (parse->packetizer, buf);
    1351         [ #  # ]:          0 :   while (((pret =
    1352                 :          0 :               mpegts_packetizer_next_packet (parse->packetizer,
    1353         [ #  # ]:          0 :                   &packet)) != PACKET_NEED_MORE) && res == GST_FLOW_OK) {
    1354         [ #  # ]:          0 :     if (G_UNLIKELY (pret == PACKET_BAD))
    1355                 :            :       /* bad header, skip the packet */
    1356                 :          0 :       goto next;
    1357                 :            : 
    1358                 :            :     /* parse PSI data */
    1359 [ #  # ][ #  # ]:          0 :     if (packet.payload != NULL && mpegts_parse_is_psi (parse, &packet)) {
    1360                 :            :       MpegTSPacketizerSection section;
    1361                 :            : 
    1362                 :          0 :       parsed = mpegts_packetizer_push_section (packetizer, &packet, &section);
    1363         [ #  # ]:          0 :       if (G_UNLIKELY (!parsed))
    1364                 :            :         /* bad section data */
    1365                 :          0 :         goto next;
    1366                 :            : 
    1367         [ #  # ]:          0 :       if (G_LIKELY (section.complete)) {
    1368                 :            :         /* section complete */
    1369                 :          0 :         parsed = mpegts_parse_handle_psi (parse, &section);
    1370                 :          0 :         gst_buffer_unref (section.buffer);
    1371                 :            : 
    1372         [ #  # ]:          0 :         if (G_UNLIKELY (!parsed))
    1373                 :            :           /* bad PSI table */
    1374                 :          0 :           goto next;
    1375                 :            :       }
    1376                 :            :       /* we need to push section packet downstream */
    1377                 :          0 :       res = mpegts_parse_push (parse, &packet, &section);
    1378                 :            : 
    1379                 :            :     } else {
    1380                 :            :       /* push the packet downstream */
    1381                 :          0 :       res = mpegts_parse_push (parse, &packet, NULL);
    1382                 :            :     }
    1383                 :            : 
    1384                 :            :   next:
    1385                 :          0 :     mpegts_packetizer_clear_packet (parse->packetizer, &packet);
    1386                 :            :   }
    1387                 :            : 
    1388         [ #  # ]:          0 :   if (parse->need_sync_program_pads)
    1389                 :          0 :     mpegts_parse_sync_program_pads (parse);
    1390                 :            : 
    1391                 :          0 :   gst_object_unref (parse);
    1392                 :          0 :   return res;
    1393                 :            : }
    1394                 :            : 
    1395                 :            : static GstStateChangeReturn
    1396                 :         34 : mpegts_parse_change_state (GstElement * element, GstStateChange transition)
    1397                 :            : {
    1398                 :            :   MpegTSParse *parse;
    1399                 :            :   GstStateChangeReturn ret;
    1400                 :            : 
    1401                 :         34 :   parse = GST_MPEGTS_PARSE (element);
    1402                 :         34 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
    1403                 :            : 
    1404         [ +  + ]:         34 :   switch (transition) {
    1405                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
    1406                 :          7 :       mpegts_parse_reset (parse);
    1407                 :          7 :       break;
    1408                 :            :     default:
    1409                 :         27 :       break;
    1410                 :            :   }
    1411                 :            : 
    1412                 :         34 :   return ret;
    1413                 :            : }
    1414                 :            : 
    1415                 :            : static gboolean
    1416                 :          0 : mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query)
    1417                 :            : {
    1418                 :          0 :   MpegTSParse *parse = GST_MPEGTS_PARSE (gst_pad_get_parent (pad));
    1419                 :            :   gboolean res;
    1420                 :            : 
    1421         [ #  # ]:          0 :   switch (GST_QUERY_TYPE (query)) {
    1422                 :            :     case GST_QUERY_LATENCY:
    1423                 :            :     {
    1424         [ #  # ]:          0 :       if ((res = gst_pad_peer_query (parse->sinkpad, query))) {
    1425                 :            :         gboolean is_live;
    1426                 :            :         GstClockTime min_latency, max_latency;
    1427                 :            : 
    1428                 :          0 :         gst_query_parse_latency (query, &is_live, &min_latency, &max_latency);
    1429         [ #  # ]:          0 :         if (is_live) {
    1430                 :          0 :           min_latency += TS_LATENCY * GST_MSECOND;
    1431         [ #  # ]:          0 :           if (max_latency != GST_CLOCK_TIME_NONE)
    1432                 :          0 :             max_latency += TS_LATENCY * GST_MSECOND;
    1433                 :            :         }
    1434                 :            : 
    1435                 :          0 :         gst_query_set_latency (query, is_live, min_latency, max_latency);
    1436                 :            :       }
    1437                 :            : 
    1438                 :          0 :       break;
    1439                 :            :     }
    1440                 :            :     default:
    1441                 :          0 :       res = gst_pad_query_default (pad, query);
    1442                 :            :   }
    1443                 :          0 :   gst_object_unref (parse);
    1444                 :          0 :   return res;
    1445                 :            : }
    1446                 :            : 
    1447                 :            : gboolean
    1448                 :          6 : gst_mpegtsparse_plugin_init (GstPlugin * plugin)
    1449                 :            : {
    1450         [ +  - ]:          6 :   GST_DEBUG_CATEGORY_INIT (mpegts_parse_debug, "mpegtsparse", 0,
    1451                 :            :       "MPEG transport stream parser");
    1452                 :            : 
    1453                 :          6 :   gst_mpegtsdesc_init_debug ();
    1454                 :            : 
    1455                 :          6 :   return gst_element_register (plugin, "mpegtsparse",
    1456                 :            :       GST_RANK_NONE, GST_TYPE_MPEGTS_PARSE);
    1457                 :            : }

Generated by: LCOV version 1.9