return pad;
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static GstPad *
+gst_hls_demux_stream_create_pad (GstAdaptiveDemuxStream * stream)
+{
+ GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
+ return gst_hls_demux_create_pad (hlsdemux);
+}
+#endif
+
static guint64
gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
{
GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
caps, prob);
-
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ gst_adaptive_demux_stream_check_switch_pad (stream, caps,
+ gst_hls_demux_stream_create_pad);
+ GST_DEBUG_OBJECT (stream->pad, "Overwriting PTS to %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (hlsdemux->current_pts));
+ stream->fragment.timestamp = hlsdemux->current_pts;
+#else
gst_adaptive_demux_stream_set_caps (stream, caps);
+#endif
hlsdemux->do_typefind = FALSE;
}
}
/* set up our source for download */
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ hlsdemux->current_pts = timestamp;
+#endif
if (hlsdemux->reset_pts || discont) {
stream->fragment.timestamp = timestamp;
} else {
return FALSE;
gst_hls_demux_change_playlist (hlsdemux, bitrate, &changed);
+#ifndef GST_EXT_AVOID_PAD_SWITCHING
if (changed)
gst_hls_demux_setup_streams (GST_ADAPTIVE_DEMUX_CAST (hlsdemux));
+#endif
return changed;
}
GstM3U8Client *client; /* M3U8 client */
gboolean do_typefind; /* Whether we need to typefind the next buffer */
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ GstClockTime current_pts;
+#endif
+
/* Cache for the last key */
gchar *key_url;
GstFragment *key_fragment;
demux->stream_struct_size = struct_size;
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void
+gst_adaptive_demux_stream_push_stream_start (GstAdaptiveDemux * demux,
+ GstAdaptiveDemuxStream * stream)
+{
+ GstPad *pad = stream->pad;
+ gchar *stream_id;
+ GstEvent *event;
+ gchar *name = gst_pad_get_name (pad);
+
+ stream_id =
+ gst_pad_create_stream_id_printf (pad, GST_ELEMENT_CAST (demux), "%s-%04d",
+ name, stream->stream_id_counter++);
+
+ event =
+ gst_pad_get_sticky_event (GST_ADAPTIVE_DEMUX_SINK_PAD (demux),
+ GST_EVENT_STREAM_START, 0);
+ if (event) {
+ if (gst_event_parse_group_id (event, &demux->group_id))
+ demux->have_group_id = TRUE;
+ else
+ demux->have_group_id = FALSE;
+ gst_event_unref (event);
+ } else if (!demux->have_group_id) {
+ demux->have_group_id = TRUE;
+ demux->group_id = gst_util_group_id_next ();
+ }
+ event = gst_event_new_stream_start (stream_id);
+ if (demux->have_group_id)
+ gst_event_set_group_id (event, demux->group_id);
+
+ gst_pad_push_event (pad, event);
+ g_free (stream_id);
+ g_free (name);
+}
+#endif
+
static gboolean
gst_adaptive_demux_expose_stream (GstAdaptiveDemux * demux,
GstAdaptiveDemuxStream * stream)
{
GstPad *pad = stream->pad;
+
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ gst_pad_set_active (pad, TRUE);
+ stream->need_header = TRUE;
+
+ gst_adaptive_demux_stream_push_stream_start (demux, stream);
+#else
gchar *name = gst_pad_get_name (pad);
GstEvent *event;
gchar *stream_id;
gst_pad_push_event (pad, event);
g_free (stream_id);
g_free (name);
+#endif
GST_DEBUG_OBJECT (demux, "Adding srcpad %s:%s with caps %" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (pad), stream->pending_caps);
gst_caps_replace (&stream->pending_caps, caps);
gst_caps_unref (caps);
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+
+/**
+ * gst_adaptive_demux_stream_check_switch_pad:
+ * @stream:
+ * @caps: the #GstCaps of the new stream
+ * @create_pad_func: callback to create a pad if needed
+ *
+ * Compares @caps with the current caps on pad and with the allowed
+ * downstream caps. If the caps is compatible it just sets a new caps
+ * on the pad, otherwise it will request a new pad to be created and
+ * switch pads.
+ *
+ * This only works currently for streams that only have a single output
+ * due to the way pad switching works in groups. (HLS demux can use it)
+ *
+ * Return: %TRUE if a new pad was created
+ */
+gboolean
+gst_adaptive_demux_stream_check_switch_pad (GstAdaptiveDemuxStream * stream,
+ GstCaps * caps, GstAdaptiveDemuxStreamCreatePadFunc create_pad_func)
+{
+ GstCaps *current_caps;
+ gboolean ret;
+
+ current_caps = gst_pad_get_current_caps (stream->pad);
+ if (current_caps == NULL || gst_caps_is_equal (current_caps, caps) ||
+ gst_pad_query_accept_caps (stream->pad, caps)) {
+
+ /* no need to switch pads */
+ ret = FALSE;
+ GST_DEBUG_OBJECT (stream->pad, "New caps compatible with old one."
+ " Scheduling new stream-start, caps and segment events");
+ gst_adaptive_demux_stream_push_stream_start (stream->demux, stream);
+ gst_adaptive_demux_stream_set_caps (stream, caps);
+ if (stream->pending_segment)
+ gst_event_unref (stream->pending_segment);
+ stream->pending_segment = gst_event_new_segment (&stream->segment);
+ } else {
+ GstPad *old_pad;
+
+ /* need to switch pad for a new one */
+ ret = TRUE;
+
+ GST_DEBUG_OBJECT (stream->pad, "New caps is incompatible with old "
+ "one. Need to switch pads");
+ old_pad = stream->pad;
+ stream->pad = create_pad_func (stream);
+ gst_adaptive_demux_stream_set_caps (stream, caps);
+ gst_adaptive_demux_expose_stream (stream->demux, stream);
+
+ /* FIXME currently there is no way of properly replacing a single
+ * pad in the stream. This will only work for streams that have
+ * a single source pad */
+ gst_element_no_more_pads (GST_ELEMENT_CAST (stream->demux));
+
+ gst_pad_push_event (old_pad, gst_event_new_eos ());
+ gst_pad_set_active (old_pad, FALSE);
+ gst_element_remove_pad (GST_ELEMENT_CAST (stream->demux), old_pad);
+ gst_object_unref (old_pad);
+ }
+
+ if (current_caps)
+ gst_caps_unref (current_caps);
+ return ret;
+}
+#endif
void
gst_adaptive_demux_stream_set_tags (GstAdaptiveDemuxStream * stream,
typedef struct _GstAdaptiveDemuxClass GstAdaptiveDemuxClass;
typedef struct _GstAdaptiveDemuxPrivate GstAdaptiveDemuxPrivate;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+typedef GstPad * (*GstAdaptiveDemuxStreamCreatePadFunc) (GstAdaptiveDemuxStream * stream);
+#endif
+
struct _GstAdaptiveDemuxStreamFragment
{
GstClockTime timestamp;
GstAdaptiveDemux *demux;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ gint stream_id_counter;
+#endif
GstSegment segment;
GstAdapter *adapter;
gst_adaptive_demux_stream_advance_fragment_unlocked (GstAdaptiveDemux * demux,
GstAdaptiveDemuxStream * stream, GstClockTime duration);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+gboolean gst_adaptive_demux_stream_check_switch_pad (GstAdaptiveDemuxStream * stream,
+ GstCaps * caps, GstAdaptiveDemuxStreamCreatePadFunc create_pad_func);
+#endif
+
G_END_DECLS
#endif
}
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void
+mpegts_base_clear (MpegTSBase * base)
+{
+ mpegts_packetizer_clear (base->packetizer);
+ memset (base->is_pes, 0, 1024);
+ memset (base->known_psi, 0, 1024);
+
+ /* FIXME : Actually these are not *always* know SI streams
+ * depending on the variant of mpeg-ts being used. */
+
+ /* Known PIDs : PAT, TSDT, IPMP CIT */
+ MPEGTS_BIT_SET (base->known_psi, 0);
+ MPEGTS_BIT_SET (base->known_psi, 2);
+ MPEGTS_BIT_SET (base->known_psi, 3);
+ /* TDT, TOT, ST */
+ MPEGTS_BIT_SET (base->known_psi, 0x14);
+ /* network synchronization */
+ MPEGTS_BIT_SET (base->known_psi, 0x15);
+
+ /* ATSC */
+ MPEGTS_BIT_SET (base->known_psi, 0x1ffb);
+
+ if (base->pat) {
+ g_ptr_array_unref (base->pat);
+ base->pat = NULL;
+ }
+
+ gst_segment_init (&base->segment, GST_FORMAT_UNDEFINED);
+ base->last_seek_seqnum = (guint32) - 1;
+
+ base->seen_pat = FALSE;
+ base->seek_offset = -1;
+
+ g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program,
+ base);
+}
+#endif
static void
mpegts_base_reset (MpegTSBase * base)
{
MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ mpegts_base_clear (base);
+ base->mode = BASE_MODE_STREAMING;
+#else
mpegts_packetizer_clear (base->packetizer);
memset (base->is_pes, 0, 1024);
memset (base->known_psi, 0, 1024);
g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program,
base);
-
+#endif
if (klass->reset)
klass->reset (base);
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+MpegTSBaseStream *
+mpegts_base_stream_ref (MpegTSBaseStream * stream)
+{
+ g_return_val_if_fail (stream != NULL, NULL);
+
+ GST_TRACE ("%p ref %d->%d", stream, stream->refcount, stream->refcount + 1);
+
+ g_atomic_int_inc (&stream->refcount);
+
+ return stream;
+}
+
+void
+mpegts_base_stream_unref (MpegTSBaseStream * stream)
+{
+ g_return_if_fail (stream != NULL);
+
+ GST_TRACE ("%p unref %d->%d", stream, stream->refcount, stream->refcount - 1);
+
+ g_return_if_fail (stream->refcount > 0);
+
+ if (g_atomic_int_dec_and_test (&stream->refcount)) {
+ g_free (stream);
+ }
+}
+#endif
/* returns NULL if no matching descriptor found *
* otherwise returns a descriptor that needs to *
}
bstream = g_malloc0 (base->stream_size);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ bstream->refcount = 1;
+#endif
bstream->pid = pid;
bstream->stream_type = stream_type;
bstream->stream = stream;
klass->stream_removed (base, stream);
program->stream_list = g_list_remove_all (program->stream_list, stream);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ mpegts_base_stream_unref (stream);
+#else
g_free (stream);
+#endif
program->streams[pid] = NULL;
}
res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event);
break;
case GST_EVENT_STREAM_START:
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ GST_DEBUG_OBJECT (base,
+ "Handling stream-start, flushing all pending data");
+ mpegts_base_drain (base);
+ mpegts_base_flush (base, TRUE);
+ mpegts_packetizer_flush (base->packetizer, TRUE);
+ mpegts_base_clear (base);
+ mpegts_packetizer_clear (base->packetizer);
+#endif
gst_event_unref (event);
break;
case GST_EVENT_CAPS:
struct _MpegTSBaseStream
{
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ gint refcount;
+#endif
guint16 pid;
guint8 stream_type;
G_GNUC_INTERNAL GType mpegts_base_get_type(void);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+G_GNUC_INTERNAL MpegTSBaseStream *mpegts_base_stream_ref (MpegTSBaseStream * stream);
+G_GNUC_INTERNAL void mpegts_base_stream_unref (MpegTSBaseStream * stream);
+#endif
G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_get_program (MpegTSBase * base, gint program_number);
G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid);
GstTsDemuxKeyFrameScanFunction scan_function;
TSDemuxH264ParsingInfos h264infos;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ /* For pad matching to avoid switching pads */
+ TSDemuxStream *matched_stream;
+#endif
};
#define VIDEO_CAPS \
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream);
static void gst_ts_demux_stream_flush (TSDemuxStream * stream,
GstTSDemux * demux, gboolean hard);
-
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void gst_ts_demux_remove_stream (GstTSDemux * tsdemux,
+ TSDemuxStream * stream, gboolean push_eos);
+static void gst_ts_demux_remove_old_streams (GstTSDemux * demux,
+ gboolean push_eos);
+#endif
static gboolean push_event (MpegTSBase * base, GstEvent * event);
static void gst_ts_demux_check_and_sync_streams (GstTSDemux * demux,
GstClockTime time);
demux->group_id = G_MAXUINT;
demux->last_seek_offset = -1;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ gst_ts_demux_remove_old_streams (demux, FALSE);
+#endif
}
static void
}
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void
+gst_ts_demux_stream_send_stream_start (MpegTSBase * base,
+ MpegTSBaseStream * bstream, GstPad * pad)
+{
+ GstTSDemux *demux = GST_TS_DEMUX_CAST (base);
+ TSDemuxStream *stream = (TSDemuxStream *) bstream;
+ GstEvent *event;
+ gchar *stream_id;
+
+ stream_id =
+ gst_pad_create_stream_id_printf (pad, GST_ELEMENT_CAST (base), "%08x",
+ bstream->pid);
+
+ event = gst_pad_get_sticky_event (base->sinkpad, GST_EVENT_STREAM_START, 0);
+ if (event) {
+ if (gst_event_parse_group_id (event, &demux->group_id))
+ demux->have_group_id = TRUE;
+ else
+ demux->have_group_id = FALSE;
+ gst_event_unref (event);
+ } else if (!demux->have_group_id) {
+ demux->have_group_id = TRUE;
+ demux->group_id = gst_util_group_id_next ();
+ }
+ event = gst_event_new_stream_start (stream_id);
+ if (demux->have_group_id)
+ gst_event_set_group_id (event, demux->group_id);
+ if (stream->sparse)
+ gst_event_set_stream_flags (event, GST_STREAM_FLAG_SPARSE);
+
+ gst_pad_push_event (pad, event);
+ g_free (stream_id);
+}
+#endif
+
static GstPad *
create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
MpegTSBaseProgram * program)
{
+#ifndef GST_EXT_AVOID_PAD_SWITCHING
GstTSDemux *demux = GST_TS_DEMUX (base);
+#endif
TSDemuxStream *stream = (TSDemuxStream *) bstream;
gchar *name = NULL;
GstCaps *caps = NULL;
}
if (template && name && caps) {
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ GST_LOG ("stream:%p creating pad with name %s and caps %" GST_PTR_FORMAT,
+ stream, name, caps);
+ pad = gst_pad_new_from_template (template, name);
+ gst_pad_set_active (pad, TRUE);
+ gst_pad_use_fixed_caps (pad);
+
+ stream->sparse = sparse;
+ gst_ts_demux_stream_send_stream_start (base, bstream, pad);
+#else
GstEvent *event;
gchar *stream_id;
gst_pad_push_event (pad, event);
g_free (stream_id);
+#endif
gst_pad_set_caps (pad, caps);
if (!stream->taglist)
stream->taglist = gst_tag_list_new_empty ();
return pad;
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void
+gst_ts_demux_remove_old_streams (GstTSDemux * demux, gboolean push_eos)
+{
+ if (demux->old_streams) {
+ GList *iter;
+ for (iter = demux->old_streams; iter; iter = g_list_next (iter)) {
+ TSDemuxStream *stream = iter->data;
+
+ gst_ts_demux_remove_stream (demux, stream, push_eos);
+ mpegts_base_stream_unref ((MpegTSBaseStream *) stream);
+ }
+ g_list_free (demux->old_streams);
+ demux->old_streams = NULL;
+ }
+
+}
+#endif
+
static void
gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * bstream,
MpegTSBaseProgram * program)
}
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static void
+gst_ts_demux_stream_rename_stopping_pad (GstTSDemux * demux,
+ TSDemuxStream * stream)
+{
+ if (stream->pad) {
+ gchar *name;
+
+ GST_DEBUG_OBJECT (stream->pad, "Renaming stopping pad: %s",
+ GST_PAD_NAME (stream->pad));
+ name = g_strdup_printf ("%s_stopping", GST_PAD_NAME (stream->pad));
+ gst_object_set_name (GST_OBJECT_CAST (stream->pad), name);
+
+ g_free (name);
+ }
+}
+
+static void
+gst_ts_demux_remove_stream (GstTSDemux * tsdemux, TSDemuxStream * stream,
+ gboolean push_eos)
+{
+ if (stream->pad) {
+ if (push_eos && stream->active) {
+ GST_DEBUG_OBJECT (stream->pad, "Pushing out EOS");
+ gst_pad_push_event (stream->pad, gst_event_new_eos ());
+ gst_pad_set_active (stream->pad, FALSE);
+ }
+
+ GST_DEBUG_OBJECT (stream->pad, "Removing pad");
+ gst_element_remove_pad (GST_ELEMENT_CAST (tsdemux), stream->pad);
+ stream->active = FALSE;
+ stream->pad = NULL;
+ }
+}
+#endif
+
static void
gst_ts_demux_stream_removed (MpegTSBase * base, MpegTSBaseStream * bstream)
{
TSDemuxStream *stream = (TSDemuxStream *) bstream;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ GstTSDemux *tsdemux = (GstTSDemux *) base;
+#endif
if (stream->pad) {
gst_flow_combiner_remove_pad (GST_TS_DEMUX_CAST (base)->flowcombiner,
/* Flush out all data */
GST_DEBUG_OBJECT (stream->pad, "Flushing out pending data");
gst_ts_demux_push_pending_data ((GstTSDemux *) base, stream);
-
+#ifndef GST_EXT_AVOID_PAD_SWITCHING
GST_DEBUG_OBJECT (stream->pad, "Pushing out EOS");
gst_pad_push_event (stream->pad, gst_event_new_eos ());
gst_pad_set_active (stream->pad, FALSE);
+#endif
}
-
+#ifndef GST_EXT_AVOID_PAD_SWITCHING
GST_DEBUG_OBJECT (stream->pad, "Removing pad");
gst_element_remove_pad (GST_ELEMENT_CAST (base), stream->pad);
stream->active = FALSE;
+#endif
}
+#ifndef GST_EXT_AVOID_PAD_SWITCHING
stream->pad = NULL;
+#endif
}
gst_ts_demux_stream_flush (stream, GST_TS_DEMUX_CAST (base), TRUE);
}
tsdemux_h264_parsing_info_clear (&stream->h264infos);
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ /* Keep our reference as we can only finish the stream once we added
+ * pads for the new program or the pipeline might go EOS */
+ mpegts_base_stream_ref (bstream);
+ tsdemux->old_streams = g_list_append (tsdemux->old_streams, bstream);
+#endif
}
static void
gst_ts_demux_stream_flush (walk->data, demux, hard);
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+static gboolean
+gst_ts_demux_find_matching_stream (GstTSDemux * demux, TSDemuxStream * stream,
+ GList * streams_list)
+{
+ GstCaps *this_caps;
+
+ if (stream->pad == NULL)
+ return TRUE;
+
+ this_caps = gst_pad_get_current_caps (stream->pad);
+ for (; streams_list; streams_list = g_list_next (streams_list)) {
+ TSDemuxStream *other_stream = streams_list->data;
+
+ if (other_stream->pad == NULL)
+ continue;
+
+ if (other_stream->matched_stream)
+ continue;
+
+ if (gst_pad_peer_query_accept_caps (other_stream->pad, this_caps)) {
+ /* TODO we are not checking the PIDs so the pad names will be
+ * inconsistent with the new streams' PIDs */
+ other_stream->matched_stream = stream;
+ stream->matched_stream = other_stream;
+ gst_caps_unref (this_caps);
+ return TRUE;
+ }
+ }
+
+ gst_caps_unref (this_caps);
+ GST_DEBUG_OBJECT (demux, "No match found for stream: %p %" GST_PTR_FORMAT,
+ stream, stream->pad);
+ return FALSE;
+}
+
+static gboolean
+push_sticky_event (GstPad * pad, GstEvent ** event, gpointer udata)
+{
+ GstPad *other_pad = udata;
+
+ gst_pad_push_event (other_pad, gst_event_ref (*event));
+
+ return TRUE;
+}
+
+static gboolean
+gst_ts_demux_check_streams_match (GstTSDemux * demux)
+{
+ GList *iter;
+ gint old_length = 0;
+ gint new_length = 0;
+
+ if (!demux->old_streams) {
+ GST_DEBUG_OBJECT (demux, "No old streams present, streams don't match");
+ return FALSE;
+ }
+
+ /* Initialize matching variables */
+ for (iter = demux->program->stream_list; iter; iter = g_list_next (iter)) {
+ TSDemuxStream *stream = iter->data;
+ if (stream->pad) {
+ new_length++;
+ stream->matched_stream = NULL;
+ }
+ }
+ for (iter = demux->old_streams; iter; iter = g_list_next (iter)) {
+ TSDemuxStream *stream = iter->data;
+ if (stream->pad) {
+ old_length++;
+ stream->matched_stream = NULL;
+ }
+ }
+
+ if (new_length != old_length) {
+ GST_DEBUG_OBJECT (demux,
+ "Number of streams is different, no match possible");
+ return FALSE;
+ }
+
+ for (iter = demux->program->stream_list; iter; iter = g_list_next (iter)) {
+ if (!gst_ts_demux_find_matching_stream (demux, iter->data,
+ demux->old_streams))
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (demux, "Streams matched, no need for pad switching");
+
+ /* do the pad replacement, unref pads from new streams and use the pads
+ * from the old ones */
+ for (iter = demux->program->stream_list; iter; iter = g_list_next (iter)) {
+ TSDemuxStream *stream = iter->data;
+
+ if (stream->pad) {
+ GstPad *pad = stream->pad;
+
+ stream->pad = stream->matched_stream->pad;
+ stream->matched_stream->pad = NULL;
+
+ gst_ts_demux_stream_send_stream_start ((MpegTSBase *) demux,
+ (MpegTSBaseStream *) stream, stream->pad);
+
+ gst_pad_sticky_events_foreach (pad, push_sticky_event, stream->pad);
+
+ gst_object_unref (pad);
+ }
+ }
+
+ return TRUE;
+}
+#endif
static void
gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program)
{
gst_event_unref (demux->segment_event);
demux->segment_event = NULL;
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ /* Check if the new streams match the old ones to
+ * prevent switching pads if not needed */
+ if (gst_ts_demux_check_streams_match (demux))
+ return;
+
+ /* 1) Rename old pad names to avoid clashes (matching PIDs)
+ * 2) add new streams
+ * 3) Fire no-more-pads */
+ for (tmp = demux->old_streams; tmp; tmp = tmp->next) {
+ TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
+ gst_ts_demux_stream_rename_stopping_pad (demux, stream);
+ }
+ for (tmp = program->stream_list; tmp; tmp = tmp->next) {
+ TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
+ activate_pad_for_stream (demux, stream);
+ }
+ gst_element_no_more_pads ((GstElement *) demux);
+ gst_ts_demux_remove_old_streams (demux, TRUE);
+#else
/* Add all streams, then fire no-more-pads */
for (tmp = program->stream_list; tmp; tmp = tmp->next) {
TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
activate_pad_for_stream (demux, stream);
}
gst_element_no_more_pads ((GstElement *) demux);
+#endif
}
}
/*< private >*/
MpegTSBaseProgram *program; /* Current program */
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ GList *old_streams;
+#endif
+
/* segments to be sent */
GstSegment segment;
GstEvent *segment_event;
{
gint i;
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ h264parse->state = 0;
+#endif
h264parse->width = 0;
h264parse->height = 0;
h264parse->fps_num = 0;
res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
break;
}
+#ifdef GST_EXT_AVOID_PAD_SWITCHING
+ case GST_EVENT_STREAM_START:
+ res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
+ gst_h264_parse_reset ((GstH264Parse *) parse);
+ break;
+#endif
default:
res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
break;
Name: gst-plugins-bad
Version: 1.6.1
-Release: 1
+Release: 2
Summary: GStreamer Streaming-Media Framework Plug-Ins
License: GPL-2.0+ and LGPL-2.1+
Group: Multimedia/Framework
%build
export V=1
NOCONFIGURE=1 ./autogen.sh
-export CFLAGS="-DGST_WLSINK_ENHANCEMENT -DGST_TBM_SUPPORT -DMESA_EGL_NO_X11_HEADERS"
+export CFLAGS="-DGST_WLSINK_ENHANCEMENT -DGST_TBM_SUPPORT -DMESA_EGL_NO_X11_HEADERS -DGST_EXT_AVOID_PAD_SWITCHING"
%configure\
--disable-static\
--disable-examples\