mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
mpegpsdemux: Rework gap sending
Take the gap logic from mpegtsdemux, and don't send gap events on a stream that's outputting buffers with no timestamps. Time isn't advancing, but the stream has buffers - so it's not sparse. Fixes #2374 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4333>
This commit is contained in:
parent
b90c0bd79b
commit
1b762ba012
2 changed files with 36 additions and 16 deletions
|
@ -59,8 +59,8 @@
|
||||||
#define SCAN_SCR_SZ 12
|
#define SCAN_SCR_SZ 12
|
||||||
#define SCAN_PTS_SZ 80
|
#define SCAN_PTS_SZ 80
|
||||||
|
|
||||||
#define SEGMENT_THRESHOLD (300*GST_MSECOND)
|
#define DEFAULT_GAP_THRESHOLD (300*GST_MSECOND)
|
||||||
#define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND)
|
#define VIDEO_GAP_THRESHOLD (500*GST_MSECOND)
|
||||||
|
|
||||||
#define DURATION_SCAN_LIMIT 4 * 1024 * 1024
|
#define DURATION_SCAN_LIMIT 4 * 1024 * 1024
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ gst_ps_demux_create_stream (GstPsDemux * demux, gint id, gint stream_type,
|
||||||
gchar *name;
|
gchar *name;
|
||||||
GstPsDemuxClass *klass = GST_PS_DEMUX_GET_CLASS (demux);
|
GstPsDemuxClass *klass = GST_PS_DEMUX_GET_CLASS (demux);
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstClockTime threshold = SEGMENT_THRESHOLD;
|
GstClockTime gap_threshold = DEFAULT_GAP_THRESHOLD;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
gchar *stream_id;
|
gchar *stream_id;
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ gst_ps_demux_create_stream (GstPsDemux * demux, gint id, gint stream_type,
|
||||||
"mpegversion", G_TYPE_INT, mpeg_version,
|
"mpegversion", G_TYPE_INT, mpeg_version,
|
||||||
"systemstream", G_TYPE_BOOLEAN, FALSE,
|
"systemstream", G_TYPE_BOOLEAN, FALSE,
|
||||||
"parsed", G_TYPE_BOOLEAN, FALSE, NULL);
|
"parsed", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||||
threshold = VIDEO_SEGMENT_THRESHOLD;
|
gap_threshold = VIDEO_GAP_THRESHOLD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ST_AUDIO_MPEG1:
|
case ST_AUDIO_MPEG1:
|
||||||
|
@ -488,14 +488,14 @@ gst_ps_demux_create_stream (GstPsDemux * demux, gint id, gint stream_type,
|
||||||
name = g_strdup_printf ("video_%02x", id);
|
name = g_strdup_printf ("video_%02x", id);
|
||||||
caps = gst_caps_new_simple ("video/x-h264",
|
caps = gst_caps_new_simple ("video/x-h264",
|
||||||
"stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
"stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
||||||
threshold = VIDEO_SEGMENT_THRESHOLD;
|
gap_threshold = VIDEO_GAP_THRESHOLD;
|
||||||
break;
|
break;
|
||||||
case ST_VIDEO_H265:
|
case ST_VIDEO_H265:
|
||||||
template = klass->video_template;
|
template = klass->video_template;
|
||||||
name = g_strdup_printf ("video_%02x", id);
|
name = g_strdup_printf ("video_%02x", id);
|
||||||
caps = gst_caps_new_simple ("video/x-h265",
|
caps = gst_caps_new_simple ("video/x-h265",
|
||||||
"stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
"stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
||||||
threshold = VIDEO_SEGMENT_THRESHOLD;
|
gap_threshold = VIDEO_GAP_THRESHOLD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ST_PS_AUDIO_AC3:
|
case ST_PS_AUDIO_AC3:
|
||||||
|
@ -542,7 +542,11 @@ gst_ps_demux_create_stream (GstPsDemux * demux, gint id, gint stream_type,
|
||||||
stream->type = stream_type;
|
stream->type = stream_type;
|
||||||
stream->pending_tags = NULL;
|
stream->pending_tags = NULL;
|
||||||
stream->pad = gst_pad_new_from_template (template, name);
|
stream->pad = gst_pad_new_from_template (template, name);
|
||||||
stream->segment_thresh = threshold;
|
stream->gap_threshold = gap_threshold;
|
||||||
|
stream->nb_out_buffers = 0;
|
||||||
|
stream->gap_ref_buffers = 0;
|
||||||
|
stream->gap_ref_pts = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
gst_pad_set_event_function (stream->pad,
|
gst_pad_set_event_function (stream->pad,
|
||||||
GST_DEBUG_FUNCPTR (gst_ps_demux_src_event));
|
GST_DEBUG_FUNCPTR (gst_ps_demux_src_event));
|
||||||
gst_pad_set_query_function (stream->pad,
|
gst_pad_set_query_function (stream->pad,
|
||||||
|
@ -766,6 +770,8 @@ gst_ps_demux_send_data (GstPsDemux * demux, GstPsStream * stream,
|
||||||
GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT,
|
GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT,
|
||||||
stream->id, stream->type, GST_TIME_ARGS (pts), gst_buffer_get_size (buf));
|
stream->id, stream->type, GST_TIME_ARGS (pts), gst_buffer_get_size (buf));
|
||||||
result = gst_pad_push (stream->pad, buf);
|
result = gst_pad_push (stream->pad, buf);
|
||||||
|
stream->nb_out_buffers += 1;
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "result: %s", gst_flow_get_name (result));
|
GST_LOG_OBJECT (demux, "result: %s", gst_flow_get_name (result));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1001,13 +1007,13 @@ gst_ps_demux_clear_times (GstPsDemux * demux)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
gst_ps_demux_send_gap_updates (GstPsDemux * demux, GstClockTime new_start)
|
gst_ps_demux_send_gap_updates (GstPsDemux * demux, GstClockTime time)
|
||||||
{
|
{
|
||||||
GstClockTime base_time, stop;
|
GstClockTime base_time, stop;
|
||||||
gint i, count = demux->found_count;
|
gint i, count = demux->found_count;
|
||||||
GstEvent *event = NULL;
|
GstEvent *event = NULL;
|
||||||
|
|
||||||
if (new_start == GST_CLOCK_TIME_NONE)
|
if (time == GST_CLOCK_TIME_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Advance all lagging streams by sending a gap event */
|
/* Advance all lagging streams by sending a gap event */
|
||||||
|
@ -1018,7 +1024,7 @@ gst_ps_demux_send_gap_updates (GstPsDemux * demux, GstClockTime new_start)
|
||||||
if (stop != GST_CLOCK_TIME_NONE)
|
if (stop != GST_CLOCK_TIME_NONE)
|
||||||
stop += base_time;
|
stop += base_time;
|
||||||
|
|
||||||
if (new_start > stop)
|
if (time > stop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIXME: Handle reverse playback */
|
/* FIXME: Handle reverse playback */
|
||||||
|
@ -1030,19 +1036,25 @@ gst_ps_demux_send_gap_updates (GstPsDemux * demux, GstClockTime new_start)
|
||||||
stream->last_ts < demux->src_segment.start + base_time)
|
stream->last_ts < demux->src_segment.start + base_time)
|
||||||
stream->last_ts = demux->src_segment.start + base_time;
|
stream->last_ts = demux->src_segment.start + base_time;
|
||||||
|
|
||||||
if (stream->last_ts + stream->segment_thresh < new_start) {
|
if (stream->last_ts + stream->gap_threshold < time &&
|
||||||
|
stream->nb_out_buffers == stream->gap_ref_buffers &&
|
||||||
|
stream->gap_ref_pts != stream->last_ts) {
|
||||||
/* should send segment info before gap event */
|
/* should send segment info before gap event */
|
||||||
gst_ps_demux_send_segment (demux, stream, GST_CLOCK_TIME_NONE);
|
gst_ps_demux_send_segment (demux, stream, GST_CLOCK_TIME_NONE);
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux,
|
GST_LOG_OBJECT (demux,
|
||||||
"Sending gap update to pad %s from time %" GST_TIME_FORMAT " to %"
|
"Sending gap update to pad %s from time %" GST_TIME_FORMAT " to %"
|
||||||
GST_TIME_FORMAT, GST_PAD_NAME (stream->pad),
|
GST_TIME_FORMAT, GST_PAD_NAME (stream->pad),
|
||||||
GST_TIME_ARGS (stream->last_ts), GST_TIME_ARGS (new_start));
|
GST_TIME_ARGS (stream->last_ts), GST_TIME_ARGS (time));
|
||||||
event =
|
event = gst_event_new_gap (stream->last_ts, time - stream->last_ts);
|
||||||
gst_event_new_gap (stream->last_ts, new_start - stream->last_ts);
|
|
||||||
gst_pad_push_event (stream->pad, event);
|
gst_pad_push_event (stream->pad, event);
|
||||||
stream->last_ts = new_start;
|
stream->last_ts = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update GAP tracking vars so we don't re-check this stream for a while */
|
||||||
|
stream->gap_ref_pts = time;
|
||||||
|
if (stream->last_ts != GST_CLOCK_TIME_NONE && stream->last_ts > time)
|
||||||
|
stream->gap_ref_pts = stream->last_ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,15 @@ struct _GstPsStream
|
||||||
gint id;
|
gint id;
|
||||||
gint type;
|
gint type;
|
||||||
|
|
||||||
GstClockTime segment_thresh;
|
/* Threshold for sending a GAP event on this stream */
|
||||||
|
GstClockTime gap_threshold;
|
||||||
|
/* Reference PTS used to detect gaps */
|
||||||
|
GstClockTime gap_ref_pts;
|
||||||
|
/* Number of outputted buffers */
|
||||||
|
guint32 nb_out_buffers;
|
||||||
|
/* Reference number of buffers for gaps */
|
||||||
|
guint32 gap_ref_buffers;
|
||||||
|
|
||||||
GstClockTime last_ts;
|
GstClockTime last_ts;
|
||||||
|
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
|
|
Loading…
Reference in a new issue