From e15ceca7ec23158873ea06ccfd35fa84094f576c Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Wed, 23 Nov 2016 12:22:16 +0900 Subject: [PATCH] [hls/tsdemux] add handling about non pcr live stream Change-Id: Ic10e786aab88385053f878f0393e2ae031ddbd94 --- ext/hls/gsthlsdemux.c | 30 ++++++++++++++++ gst-libs/gst/adaptivedemux/gstadaptivedemux.c | 13 ++++++- gst/mpegtsdemux/mpegtsbase.c | 18 ++++++++++ gst/mpegtsdemux/mpegtspacketizer.c | 51 +++++++++++++++++++++++++-- gst/mpegtsdemux/mpegtspacketizer.h | 16 ++++++--- packaging/gst-plugins-bad.spec | 4 +-- 6 files changed, 121 insertions(+), 11 deletions(-) diff --git a/ext/hls/gsthlsdemux.c b/ext/hls/gsthlsdemux.c index 3da3906..ab53aed 100644 --- a/ext/hls/gsthlsdemux.c +++ b/ext/hls/gsthlsdemux.c @@ -976,6 +976,35 @@ retry: * three fragments before the end of the list */ if (update == FALSE && demux->client->current && gst_m3u8_client_is_live (demux->client)) { +#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION + gint64 last_sequence, first_sequence, previous_sequence; + + GST_M3U8_CLIENT_LOCK (demux->client); + last_sequence = + GST_M3U8_MEDIA_FILE (g_list_last (demux->client->current-> + files)->data)->sequence; + first_sequence = + GST_M3U8_MEDIA_FILE (demux->client->current->files->data)->sequence; + + previous_sequence = demux->client->sequence; + + GST_DEBUG_OBJECT (demux, + "sequence:%" G_GINT64_FORMAT " , first_sequence:%" G_GINT64_FORMAT + " , last_sequence:%" G_GINT64_FORMAT, demux->client->sequence, + first_sequence, last_sequence); + if (demux->client->sequence >= last_sequence - 3) { + demux->client->sequence = MIN(MAX(MAX(first_sequence, last_sequence - 3),previous_sequence),last_sequence); + /* + [prasenjit.c] Refer 6.3.5 for draft-pantos-http-live-streaming-19. + As per specification , "In order to play the presentation normally, the next Media Segment to + load is the one with the lowest Media Sequence Number that is greater + than the Media Sequence Number of the last Media Segment loaded." + */ + GST_DEBUG_OBJECT (demux, + "Sequence is beyond playlist , but to maintain the playback flow , Not Moving Back if not passed Last Sequence. Loaded Sequence %" G_GINT64_FORMAT, + demux->client->sequence); + } +#else gint64 last_sequence, first_sequence; GST_M3U8_CLIENT_LOCK (demux->client); @@ -997,6 +1026,7 @@ retry: "Sequence is beyond playlist. Moving back to %" G_GINT64_FORMAT, demux->client->sequence); } +#endif GST_M3U8_CLIENT_UNLOCK (demux->client); } else if (demux->client->current && !gst_m3u8_client_is_live (demux->client)) { GstClockTime current_pos, target_pos; diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c index b6bba62..91ac6c5 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c @@ -1343,8 +1343,11 @@ gst_adaptive_demux_src_query (GstPad * pad, GstObject * parent, g_value_init (&value, G_TYPE_BOOLEAN); g_value_set_boolean (&value, TRUE); - gst_structure_set_value ((GstStructure *)s, "adaptive-streaming", &value); + + g_value_set_boolean (&value, gst_adaptive_demux_is_live (demux)); + gst_structure_set_value ((GstStructure *)s, "is-live", &value); + ret = TRUE; } else { GST_DEBUG_OBJECT (demux, "Unsupported query"); @@ -1669,6 +1672,14 @@ gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream, GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; if (G_UNLIKELY (stream->pending_caps)) { +#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION + gst_caps_make_writable (stream->pending_caps); + if (gst_adaptive_demux_is_live (demux)) { + gst_caps_set_simple (stream->pending_caps,"is_live", G_TYPE_BOOLEAN, TRUE, NULL); + } else { + gst_caps_set_simple (stream->pending_caps,"is_live", G_TYPE_BOOLEAN, FALSE, NULL); + } +#endif GST_DEBUG_OBJECT (stream->pad, "Setting pending caps: %" GST_PTR_FORMAT, stream->pending_caps); gst_pad_set_caps (stream->pad, stream->pending_caps); diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 4722478..de65ae3 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -1116,6 +1116,11 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) gboolean hard; MpegTSBase *base = GST_MPEGTS_BASE (parent); gboolean is_sticky = GST_EVENT_IS_STICKY (event); +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + GstStructure *structure = NULL; + GstCaps *caps = NULL; + gboolean caps_ret = FALSE; +#endif GST_DEBUG_OBJECT (base, "Got event %s", gst_event_type_get_name (GST_EVENT_TYPE (event))); @@ -1149,6 +1154,19 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) break; case GST_EVENT_CAPS: /* FIXME, do something */ +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + if (base->packetizer) { + gst_event_parse_caps (event, &caps); + GST_DEBUG_OBJECT (base, "got caps: %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + caps_ret = gst_structure_get_boolean (structure, "is_live", &base->packetizer->is_live_stream); + if (caps_ret == FALSE) + base->packetizer->is_live_stream = TRUE; + } else { + GST_DEBUG_OBJECT (base, "base->packetizer pointer is NULL !!!"); + } +#endif gst_event_unref (event); break; case GST_EVENT_FLUSH_STOP: diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 1cdb9e9..7765afa 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -272,6 +272,13 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer) packetizer->nb_seen_offsets = 0; packetizer->refoffset = -1; packetizer->last_in_time = GST_CLOCK_TIME_NONE; +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + packetizer->is_non_pcr_live_feed = FALSE; + packetizer->non_pcr_base_time = GST_CLOCK_TIME_NONE; + packetizer->last_live_pts = GST_CLOCK_TIME_NONE; + packetizer->last_live_pts_delta_apprx = GST_CLOCK_TIME_NONE; + packetizer->is_live_stream = FALSE; +#endif packetizer->pcr_discont_threshold = GST_SECOND; } @@ -443,6 +450,12 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 * } } #endif +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + if ((afcflags == 0x00) && (!(afcflags & MPEGTS_AFC_PCR_FLAG)) && (packetizer->is_live_stream)) { + GST_DEBUG ("Non-PCR Live Stream Case !!"); + packetizer->is_non_pcr_live_feed = TRUE; + } +#endif return TRUE; } @@ -582,6 +595,9 @@ mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer) packetizer->map_size = 0; packetizer->map_offset = 0; packetizer->last_in_time = GST_CLOCK_TIME_NONE; +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + packetizer->is_live_stream = FALSE; +#endif /* Close current PCR group */ PACKETIZER_GROUP_LOCK (packetizer); @@ -974,7 +990,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, * If it is not a PUSI * Accumulate the expected data and check for complete section * (loop) - * + * **/ if (packet->payload_unit_start_indicator) { @@ -1914,7 +1930,7 @@ record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable, GList *tmp; /* No current estimator. This happens for the initial value, or after * discont and flushes. Figure out where we need to record this position. - * + * * Possible choices: * 1) No groups at all: * Create a new group with pcr/offset @@ -2294,7 +2310,36 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, pts - PCRTIME_TO_GSTTIME (refpcr) + PCRTIME_TO_GSTTIME (refpcroffset); else GST_WARNING ("No groups, can't calculate timestamp"); - } else + } +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + else if ((packetizer->is_non_pcr_live_feed) && (GST_CLOCK_TIME_IS_VALID(pts))) { + /* + [prasenjit.c] For Live Youtube Channels , PCR flag does not come. + Due to this , base offset of the content pts values are not obtained , so playback does not work. + Currently based on the flag is_non_pcr_live_feed set in mpegts_packetizer_parse_adaptation_field_control , we are rebasing the pts values. + */ + GST_DEBUG ("non_pcr_base_time = %"GST_TIME_FORMAT" , last_live_pts = %"GST_TIME_FORMAT, + GST_TIME_ARGS (packetizer->non_pcr_base_time), GST_TIME_ARGS (packetizer->last_live_pts)); + if(!GST_CLOCK_TIME_IS_VALID (packetizer->non_pcr_base_time)) { + GST_DEBUG ("PCR Base Time reset to Current PTS"); + packetizer->non_pcr_base_time = pts; + } else if ((pts - packetizer->non_pcr_base_time) < packetizer->last_live_pts) { + GST_DEBUG ("Current PTS Less than Previous PTS !!"); + GstClockTime delta = ABSDIFF ((pts - packetizer->non_pcr_base_time), packetizer->last_live_pts); + packetizer->non_pcr_base_time = packetizer->non_pcr_base_time - delta; + } + + res = pts - packetizer->non_pcr_base_time; + packetizer->last_live_pts_delta_apprx = ABSDIFF (res, packetizer->last_live_pts); + packetizer->last_live_pts = res; + } else if ((packetizer->is_non_pcr_live_feed) && + (GST_CLOCK_TIME_IS_VALID(packetizer->last_live_pts)) && + (GST_CLOCK_TIME_IS_VALID(packetizer->last_live_pts_delta_apprx))) { + GST_DEBUG ("Invalid Live PTS : Resetting to last valid PTS"); + res = packetizer->last_live_pts + (packetizer->last_live_pts_delta_apprx / 2); + } +#endif + else GST_WARNING ("Not enough information to calculate proper timestamp"); PACKETIZER_GROUP_UNLOCK (packetizer); diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h index be8bf37..af90268 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -1,7 +1,7 @@ /* - * mpegtspacketizer.h - + * mpegtspacketizer.h - * Copyright (C) 2007 Alessandro Decina - * + * * Authors: * Alessandro Decina * @@ -277,7 +277,13 @@ struct _MpegTSPacketizer2 { /* Last inputted timestamp */ GstClockTime last_in_time; - +#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION + gboolean is_live_stream; + gboolean is_non_pcr_live_feed; + GstClockTime non_pcr_base_time; + GstClockTime last_live_pts; + GstClockTime last_live_pts_delta_apprx; +#endif /* offset to observations table */ guint8 pcrtablelut[0x2000]; MpegTSPCR *observations[MAX_PCR_OBS_CHANNELS]; @@ -313,8 +319,8 @@ typedef struct typedef struct { guint8 table_id; - /* the spec says sub_table_extension is the fourth and fifth byte of a - * section when the section_syntax_indicator is set to a value of "1". If + /* the spec says sub_table_extension is the fourth and fifth byte of a + * section when the section_syntax_indicator is set to a value of "1". If * section_syntax_indicator is 0, sub_table_extension will be set to 0 */ guint16 subtable_extension; guint8 version_number; diff --git a/packaging/gst-plugins-bad.spec b/packaging/gst-plugins-bad.spec index c63657d..7ba7e46 100644 --- a/packaging/gst-plugins-bad.spec +++ b/packaging/gst-plugins-bad.spec @@ -4,7 +4,7 @@ Name: gst-plugins-bad Version: 1.6.1 -Release: 7 +Release: 8 Summary: GStreamer Streaming-Media Framework Plug-Ins License: LGPL-2.0+ Group: Multimedia/Framework @@ -78,7 +78,7 @@ processing capabilities can be added simply by installing new plug-ins. %build export V=1 NOCONFIGURE=1 ./autogen.sh -export CFLAGS+=" -Wall -g -fPIC -DTIZEN_FEATURE_WLSINK_ENHANCEMENT -DTIZEN_FEATURE_AVOID_PAD_SWITCHING -DTIZEN_FEATURE_ADAPTIVE_MODIFICATION" +export CFLAGS+=" -Wall -g -fPIC -DTIZEN_FEATURE_WLSINK_ENHANCEMENT -DTIZEN_FEATURE_AVOID_PAD_SWITCHING -DTIZEN_FEATURE_ADAPTIVE_MODIFICATION -DTIZEN_FEATURE_TSDEMUX_MODIFICATION" %configure\ --disable-static\ --disable-examples\ -- 2.7.4