diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c index a5fa54fa70..13a599f875 100644 --- a/libs/gst/base/gstbaseparse.c +++ b/libs/gst/base/gstbaseparse.c @@ -3569,6 +3569,9 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR); g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR); + GST_DEBUG_OBJECT (parse, "Bisecting for time %" GST_TIME_FORMAT, + GST_TIME_ARGS (*_time)); + /* TODO also make keyframe aware if useful some day */ time = *_time; @@ -3591,9 +3594,17 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, /* need initial positions; start and end */ lpos = parse->priv->first_frame_offset; ltime = parse->priv->first_frame_ts; - htime = parse->priv->duration; + if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &htime)) { + GST_DEBUG_OBJECT (parse, "Unknown time duration, cannot bisect"); + return GST_FLOW_ERROR; + } hpos = parse->priv->upstream_size; + GST_DEBUG_OBJECT (parse, + "Bisection initial bounds: bytes %" G_GINT64_FORMAT " %" G_GINT64_FORMAT + ", times %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, lpos, htime, + GST_TIME_ARGS (ltime), GST_TIME_ARGS (htime)); + /* check preconditions are satisfied; * start and end are needed, except for special case where we scan for * last frame to determine duration */ diff --git a/libs/gst/check/gstcheck.h b/libs/gst/check/gstcheck.h index 74099ed661..84f2347e96 100644 --- a/libs/gst/check/gstcheck.h +++ b/libs/gst/check/gstcheck.h @@ -284,8 +284,10 @@ static inline GThread * gst_g_thread_create (GThreadFunc func, gpointer data, gboolean joinable, GError **error) { - g_assert (joinable); - return g_thread_try_new ("gst-check", func, data, error); + GThread *thread = g_thread_try_new ("gst-check", func, data, error); + if (!joinable) + g_thread_unref (thread); + return thread; } #define g_mutex_new gst_g_mutex_new static inline GMutex * diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index 71084460dd..b08e63af9c 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -405,7 +405,8 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) structure = gst_message_get_structure (msg); sstr = gst_structure_to_string (structure); sink->last_message = - g_strdup_printf ("message ******* M (type: %d, %s) %p", + g_strdup_printf ("message ******* (%s:%s) M (type: %d, %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), GST_MESSAGE_TYPE (msg), sstr, msg); gst_message_unref (msg); } else { @@ -416,7 +417,8 @@ gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) } sink->last_message = - g_strdup_printf ("event ******* E (type: %d, %s) %p", + g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), GST_EVENT_TYPE (event), sstr, event); } g_free (sstr); @@ -493,15 +495,14 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) } { - const char *flag_list[12] = { - "ro", "media4", "", "", - "preroll", "discont", "incaps", "gap", - "delta_unit", "media1", "media2", "media3" + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" }; int i; char *end = flag_str; end[0] = '\0'; - for (i = 0; i < 12; i++) { + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { strcpy (end, flag_list[i]); end += strlen (end); @@ -513,12 +514,13 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) } sink->last_message = - g_strdup_printf ("chain ******* < (%5" G_GSIZE_FORMAT - " bytes, timestamp: %s" ", duration: %s, offset: %" G_GINT64_FORMAT - ", offset_end: %" G_GINT64_FORMAT ", flags: %d %s) %p", - gst_buffer_get_size (buf), ts_str, dur_str, GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, - flag_str, buf); + g_strdup_printf ("chain ******* (%s:%s) (%u bytes, timestamp: %s" + ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" + G_GINT64_FORMAT ", flags: %d %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), + (guint) gst_buffer_get_size (buf), ts_str, + dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf); GST_OBJECT_UNLOCK (sink); gst_fake_sink_notify_last_message (sink); diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 9a367a0810..4dee64ae6a 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -440,7 +440,8 @@ gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event) sstr = g_strdup (""); src->last_message = - g_strdup_printf ("event ******* E (type: %d, %s) %p", + g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), GST_EVENT_TYPE (event), sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (src); @@ -833,6 +834,7 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, if (!src->silent) { gchar ts_str[64], dur_str[64]; + gchar flag_str[100]; GST_OBJECT_LOCK (src); g_free (src->last_message); @@ -851,12 +853,32 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, g_strlcpy (dur_str, "none", sizeof (dur_str)); } + { + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" + }; + int i; + char *end = flag_str; + end[0] = '\0'; + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { + if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { + strcpy (end, flag_list[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + } + src->last_message = - g_strdup_printf ("get ******* > (%5d bytes, timestamp: %s" + g_strdup_printf ("create ******* (%s:%s) (%u bytes, timestamp: %s" ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" - G_GINT64_FORMAT ", flags: %d) %p", (gint) size, ts_str, - dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), - GST_MINI_OBJECT_CAST (buf)->flags, buf); + G_GINT64_FORMAT ", flags: %d %s) %p", + GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size, + ts_str, dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf); GST_OBJECT_UNLOCK (src); #if !GLIB_CHECK_VERSION(2,26,0) diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 3e699aaf01..2a3350d486 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -32,6 +32,7 @@ #endif #include +#include #include "../../gst/gst-i18n-lib.h" #include "gstidentity.h" @@ -574,18 +575,39 @@ gst_identity_update_last_message_for_buffer (GstIdentity * identity, const gchar * action, GstBuffer * buf, gsize size) { gchar ts_str[64], dur_str[64]; + gchar flag_str[100]; GST_OBJECT_LOCK (identity); + { + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" + }; + int i; + char *end = flag_str; + end[0] = '\0'; + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { + if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { + strcpy (end, flag_list[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + } + g_free (identity->last_message); - identity->last_message = g_strdup_printf ("%s ******* (%s:%s)i " + identity->last_message = g_strdup_printf ("%s ******* (%s:%s) " "(%" G_GSIZE_FORMAT " bytes, timestamp: %s, duration: %s, offset: %" - G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - action, GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), - size, print_pretty_time (ts_str, sizeof (ts_str), - GST_BUFFER_TIMESTAMP (buf)), print_pretty_time (dur_str, - sizeof (dur_str), GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT + ", flags: %d %s) %p", action, + GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size, + print_pretty_time (ts_str, sizeof (ts_str), GST_BUFFER_TIMESTAMP (buf)), + print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_BUFFER_FLAGS (buf), flag_str, buf); GST_OBJECT_UNLOCK (identity); diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c index a7e33b03ff..89dc92de41 100644 --- a/plugins/elements/gstinputselector.c +++ b/plugins/elements/gstinputselector.c @@ -674,16 +674,19 @@ gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) /* if we have a pending segment, push it out now */ if (G_UNLIKELY (prev_active_sinkpad != active_sinkpad || selpad->segment_pending)) { - GST_DEBUG_OBJECT (pad, - "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, - seg->start, seg->stop, seg->time); + if (G_UNLIKELY (seg->format == GST_FORMAT_UNDEFINED)) { + GST_ERROR_OBJECT (pad, "Buffers arrived before NEWSEGMENT event"); + } else { + GST_DEBUG_OBJECT (pad, + "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, + seg->start, seg->stop, seg->time); - start_event = gst_event_new_segment (seg); - gst_event_set_seqnum (start_event, selpad->segment_seqnum); - - selpad->segment_pending = FALSE; + start_event = gst_event_new_segment (seg); + gst_event_set_seqnum (start_event, selpad->segment_seqnum); + selpad->segment_pending = FALSE; + } } GST_INPUT_SELECTOR_UNLOCK (sel); diff --git a/plugins/elements/gstoutputselector.c b/plugins/elements/gstoutputselector.c index adc63fdfc3..4b2aef1805 100644 --- a/plugins/elements/gstoutputselector.c +++ b/plugins/elements/gstoutputselector.c @@ -173,7 +173,7 @@ gst_output_selector_init (GstOutputSelector * sel) /* srcpad management */ sel->active_srcpad = NULL; sel->nb_srcpads = 0; - gst_segment_init (&sel->segment, GST_FORMAT_TIME); + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); sel->pending_srcpad = NULL; sel->resend_latest = FALSE; @@ -383,8 +383,9 @@ gst_output_selector_switch (GstOutputSelector * osel) osel->pending_srcpad = NULL; GST_OBJECT_UNLOCK (GST_OBJECT (osel)); - /* Send SEGMENT event and latest buffer if switching succeeded */ - if (res) { + /* Send SEGMENT event and latest buffer if switching succeeded + * and we already have a valid segment configured */ + if (res && osel->segment.format != GST_FORMAT_UNDEFINED) { /* Send SEGMENT to the pad we are going to switch to */ seg = &osel->segment; /* If resending then mark segment start and position accordingly */ diff --git a/tests/check/elements/selector.c b/tests/check/elements/selector.c index 355d846f32..fb75ea5ba0 100644 --- a/tests/check/elements/selector.c +++ b/tests/check/elements/selector.c @@ -198,6 +198,19 @@ selector_set_active_pad (GstElement * elem, GstPad * selpad) g_free (padname); } +static void +push_newsegment_events (GList * input_pads) +{ + GList *l; + + for (l = input_pads; l; l = l->next) { + GstPad *pad = l->data; + + gst_pad_push_event (pad, gst_event_new_new_segment_full (FALSE, 1.0, 1.0, + GST_FORMAT_BYTES, 0, -1, 0)); + } +} + /* Push buffers and switch for each selector pad */ static void push_switched_buffers (GList * input_pads, @@ -253,6 +266,7 @@ run_output_selector_buffer_count (gint num_output_pads, fail_unless (gst_element_set_state (sel, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing"); + push_newsegment_events (input_pads); push_switched_buffers (input_pads, sel, output_pads, num_buffers_per_output); count_output_buffers (output_pads, num_buffers_per_output); fail_unless (gst_element_set_state (sel, @@ -326,6 +340,7 @@ run_input_selector_buffer_count (gint num_input_pads, fail_unless (gst_element_set_state (sel, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing"); + push_newsegment_events (input_pads); push_switched_buffers (input_pads, sel, input_pads, num_buffers_per_input); count_output_buffers (output_pads, (num_input_pads * num_buffers_per_input)); fail_unless (gst_element_set_state (sel,