mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 04:22:27 +00:00
Cleanly handle removing the last object in a composition
The strategy here is to seek at the new end of the composition. And in GES we always add a 1ns long gap at the end of the tracks so that all track have the exact same duration, and we have black frames when the timeline is empty
This commit is contained in:
parent
f3f27bd636
commit
1bfe0b7ef3
4 changed files with 126 additions and 7 deletions
|
@ -218,7 +218,7 @@ update_gaps (GESTrack * track)
|
|||
duration = MAX (duration, end);
|
||||
}
|
||||
|
||||
/* 4- Add a gap at the end of the timeline if needed */
|
||||
/* 3- Add a gap at the end of the timeline if needed */
|
||||
if (priv->timeline) {
|
||||
g_object_get (priv->timeline, "duration", &timeline_duration, NULL);
|
||||
|
||||
|
@ -233,6 +233,10 @@ update_gaps (GESTrack * track)
|
|||
}
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (track, "Adding a one second gap at the end");
|
||||
gap = gap_new (track, timeline_duration, 1);
|
||||
priv->gaps = g_list_prepend (priv->gaps, gap);
|
||||
|
||||
/* 4- Remove old gaps */
|
||||
g_list_free_full (gaps, (GDestroyNotify) free_gap);
|
||||
}
|
||||
|
|
|
@ -1328,7 +1328,9 @@ get_new_seek_event (NleComposition * comp, gboolean initial,
|
|||
GST_TIME_FORMAT, GST_TIME_ARGS (priv->segment->stop),
|
||||
GST_TIME_ARGS (priv->segment_stop));
|
||||
|
||||
start = MAX (priv->segment->start, priv->segment_start);
|
||||
start = GST_CLOCK_TIME_IS_VALID (priv->segment->start)
|
||||
? MAX (priv->segment->start, priv->segment_start)
|
||||
: priv->segment_start;
|
||||
stop = GST_CLOCK_TIME_IS_VALID (priv->segment->stop)
|
||||
? MIN (priv->segment->stop, priv->segment_stop)
|
||||
: priv->segment_stop;
|
||||
|
@ -2801,12 +2803,19 @@ update_pipeline (NleComposition * comp, GstClockTime currenttime, gint32 seqnum,
|
|||
NleCompositionPrivate *priv = comp->priv;
|
||||
GstClockTime new_stop = GST_CLOCK_TIME_NONE;
|
||||
GstClockTime new_start = GST_CLOCK_TIME_NONE;
|
||||
GstClockTime duration = NLE_OBJECT (comp)->duration - 1;
|
||||
|
||||
GstState nextstate = (GST_STATE_NEXT (comp) == GST_STATE_VOID_PENDING) ?
|
||||
GST_STATE (comp) : GST_STATE_NEXT (comp);
|
||||
|
||||
_assert_proper_thread (comp);
|
||||
|
||||
if (currenttime >= duration) {
|
||||
currenttime = duration;
|
||||
priv->segment->start = GST_CLOCK_TIME_NONE;
|
||||
priv->segment->stop = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (comp,
|
||||
"currenttime:%" GST_TIME_FORMAT
|
||||
" Reason: %s, Seqnum: %i", GST_TIME_ARGS (currenttime),
|
||||
|
|
|
@ -358,7 +358,6 @@ static GCond cond;
|
|||
static void
|
||||
commited_cb (GstElement * comp, gboolean changed)
|
||||
{
|
||||
GST_ERROR ("commited !!");
|
||||
g_mutex_lock (&lock);
|
||||
g_cond_signal (&cond);
|
||||
g_mutex_unlock (&lock);
|
||||
|
|
|
@ -187,6 +187,116 @@ GST_START_TEST (test_remove_invalid_object)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static GstClockTime
|
||||
_query_position_cb (GstElement * composition, GstPipeline * pipeline)
|
||||
{
|
||||
gint64 position;
|
||||
|
||||
if (gst_element_query_position (GST_ELEMENT (pipeline), GST_FORMAT_TIME,
|
||||
&position))
|
||||
return position;
|
||||
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_remove_last_object)
|
||||
{
|
||||
GstBin *composition;
|
||||
GstElement *source1, *audiotestsrc, *source2, *audiotestsrc2, *fakesink,
|
||||
*pipeline;
|
||||
GstBus *bus;
|
||||
GstMessage *message;
|
||||
gboolean ret;
|
||||
gint64 position = 0;
|
||||
GstClockTime duration;
|
||||
|
||||
pipeline = GST_ELEMENT (gst_pipeline_new (NULL));
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
|
||||
composition = GST_BIN (gst_element_factory_make ("nlecomposition",
|
||||
"composition"));
|
||||
|
||||
g_signal_connect (composition, "query-position",
|
||||
G_CALLBACK (_query_position_cb), pipeline);
|
||||
|
||||
gst_element_set_state (GST_ELEMENT (composition), GST_STATE_READY);
|
||||
|
||||
fakesink = gst_element_factory_make ("fakesink", NULL);
|
||||
gst_bin_add_many (GST_BIN (pipeline), GST_ELEMENT (composition), fakesink,
|
||||
NULL);
|
||||
gst_element_link (GST_ELEMENT (composition), fakesink);
|
||||
|
||||
source1 = gst_element_factory_make ("nlesource", "source1");
|
||||
audiotestsrc = gst_element_factory_make ("audiotestsrc", "audiotestsrc1");
|
||||
gst_bin_add (GST_BIN (source1), audiotestsrc);
|
||||
g_object_set (source1, "start", (guint64) 0 * GST_SECOND,
|
||||
"duration", 10 * GST_SECOND, "inpoint", (guint64) 0, "priority", 1, NULL);
|
||||
|
||||
nle_composition_add (composition, source1);
|
||||
|
||||
source2 = gst_element_factory_make ("nlesource", "source1");
|
||||
audiotestsrc2 = gst_element_factory_make ("audiotestsrc", "audiotestsrc1");
|
||||
gst_bin_add (GST_BIN (source2), audiotestsrc2);
|
||||
g_object_set (source2, "start", (guint64) 10 * GST_SECOND,
|
||||
"duration", 10 * GST_SECOND, "inpoint", (guint64) 0, "priority", 1, NULL);
|
||||
|
||||
nle_composition_add (composition, source2);
|
||||
|
||||
fail_if (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED)
|
||||
== GST_STATE_CHANGE_FAILURE);
|
||||
message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
|
||||
GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (message));
|
||||
|
||||
commit_and_wait (GST_ELEMENT (composition), &ret);
|
||||
|
||||
message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
|
||||
GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (message));
|
||||
|
||||
gst_element_seek_simple (pipeline,
|
||||
GST_FORMAT_TIME,
|
||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 15 * GST_SECOND);
|
||||
|
||||
message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
|
||||
GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (message));
|
||||
|
||||
ret =
|
||||
gst_element_query_position (GST_ELEMENT (pipeline), GST_FORMAT_TIME,
|
||||
&position);
|
||||
fail_unless_equals_uint64 (position, 15 * GST_SECOND);
|
||||
|
||||
gst_element_seek_simple (pipeline,
|
||||
GST_FORMAT_TIME,
|
||||
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 18 * GST_SECOND);
|
||||
|
||||
message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
|
||||
GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (message));
|
||||
|
||||
ret =
|
||||
gst_element_query_position (GST_ELEMENT (pipeline), GST_FORMAT_TIME,
|
||||
&position);
|
||||
fail_unless_equals_uint64 (position, 18 * GST_SECOND);
|
||||
|
||||
nle_composition_remove (composition, source2);
|
||||
|
||||
commit_and_wait (GST_ELEMENT (composition), &ret);
|
||||
g_object_get (composition, "duration", &duration, NULL);
|
||||
fail_unless_equals_uint64 (duration, 10 * GST_SECOND);
|
||||
|
||||
ret =
|
||||
gst_element_query_position (GST_ELEMENT (pipeline), GST_FORMAT_TIME,
|
||||
&position);
|
||||
fail_unless_equals_uint64 (position, 10 * GST_SECOND - 1);
|
||||
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_dispose_on_commit)
|
||||
{
|
||||
GstElement *composition;
|
||||
|
@ -235,7 +345,6 @@ GST_START_TEST (test_simple_audiomixer)
|
|||
pipeline = GST_ELEMENT (gst_pipeline_new (NULL));
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
|
||||
GST_ERROR ("Pipeline refcounts: %i", ((GObject *) pipeline)->ref_count);
|
||||
composition = gst_element_factory_make ("nlecomposition", "composition");
|
||||
gst_element_set_state (composition, GST_STATE_READY);
|
||||
fakesink = gst_element_factory_make ("fakesink", NULL);
|
||||
|
@ -250,7 +359,6 @@ GST_START_TEST (test_simple_audiomixer)
|
|||
"priority", 0, NULL);
|
||||
nle_composition_add (GST_BIN (composition), nle_audiomixer);
|
||||
|
||||
GST_ERROR ("Pipeline refcounts: %i", ((GObject *) pipeline)->ref_count);
|
||||
/* source 1 */
|
||||
nlesource1 = gst_element_factory_make ("nlesource", "nlesource1");
|
||||
audiotestsrc1 = gst_element_factory_make ("audiotestsrc", "audiotestsrc1");
|
||||
|
@ -270,8 +378,6 @@ GST_START_TEST (test_simple_audiomixer)
|
|||
GST_DEBUG ("Adding composition to pipeline");
|
||||
gst_bin_add_many (GST_BIN (pipeline), composition, fakesink, NULL);
|
||||
|
||||
GST_ERROR ("Pipeline refcounts: %i", ((GObject *) pipeline)->ref_count);
|
||||
|
||||
fail_unless (nle_composition_add (GST_BIN (composition), nlesource2));
|
||||
fail_unless (gst_element_link (composition, fakesink) == TRUE);
|
||||
|
||||
|
@ -336,6 +442,7 @@ gnonlin_suite (void)
|
|||
|
||||
tcase_add_test (tc_chain, test_change_object_start_stop_in_current_stack);
|
||||
tcase_add_test (tc_chain, test_remove_invalid_object);
|
||||
tcase_add_test (tc_chain, test_remove_last_object);
|
||||
|
||||
tcase_add_test (tc_chain, test_dispose_on_commit);
|
||||
|
||||
|
|
Loading…
Reference in a new issue