mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
splitmux: Fix file switch-on-caps-change.
Switching to a new fragment because the input caps have changed didn't properly end the previous file. Use the normal EOS sequence to ensure that happens. Add a test that it works.
This commit is contained in:
parent
e82c24e893
commit
3a813a0dcc
2 changed files with 108 additions and 11 deletions
|
@ -944,22 +944,22 @@ handle_mq_output (GstPad * pad, GstPadProbeInfo * info, MqStreamCtx * ctx)
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* This is in the case the muxer doesn't allow this change of caps */
|
/* This is in the case the muxer doesn't allow this change of caps */
|
||||||
|
|
||||||
GST_SPLITMUX_LOCK (splitmux);
|
GST_SPLITMUX_LOCK (splitmux);
|
||||||
locked = TRUE;
|
locked = TRUE;
|
||||||
ctx->caps_change = TRUE;
|
ctx->caps_change = TRUE;
|
||||||
splitmux->ready_for_output = FALSE;
|
|
||||||
|
|
||||||
if (splitmux->output_state != SPLITMUX_OUTPUT_STATE_START_NEXT_FILE) {
|
if (splitmux->output_state != SPLITMUX_OUTPUT_STATE_START_NEXT_FILE) {
|
||||||
|
GST_DEBUG_OBJECT (splitmux,
|
||||||
|
"New caps were not accepted. Switching output file");
|
||||||
if (ctx->out_eos == FALSE) {
|
if (ctx->out_eos == FALSE) {
|
||||||
send_eos (splitmux, ctx);
|
splitmux->output_state = SPLITMUX_OUTPUT_STATE_ENDING_FILE;
|
||||||
|
GST_SPLITMUX_BROADCAST_OUTPUT (splitmux);
|
||||||
}
|
}
|
||||||
splitmux->output_state = SPLITMUX_OUTPUT_STATE_START_NEXT_FILE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lets it fall through, if it fails again, then the muxer just can't
|
/* Lets it fall through, if it fails again, then the muxer just can't
|
||||||
|
@ -983,9 +983,10 @@ handle_mq_output (GstPad * pad, GstPadProbeInfo * info, MqStreamCtx * ctx)
|
||||||
* because it would cause a new file to be created without the first
|
* because it would cause a new file to be created without the first
|
||||||
* buffer being available.
|
* buffer being available.
|
||||||
*/
|
*/
|
||||||
if (ctx->caps_change && GST_EVENT_IS_STICKY (event))
|
if (ctx->caps_change && GST_EVENT_IS_STICKY (event)) {
|
||||||
return GST_PAD_PROBE_DROP;
|
gst_event_unref (event);
|
||||||
else
|
return GST_PAD_PROBE_HANDLED;
|
||||||
|
} else
|
||||||
return GST_PAD_PROBE_PASS;
|
return GST_PAD_PROBE_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,10 +220,10 @@ test_playback (const gchar * in_pattern, GstClockTime exp_first_time,
|
||||||
gst_message_unref (msg);
|
gst_message_unref (msg);
|
||||||
|
|
||||||
/* Check we saw the entire range of values */
|
/* Check we saw the entire range of values */
|
||||||
fail_unless (first_ts == 0,
|
fail_unless (first_ts == exp_first_time,
|
||||||
"Expected start of playback range 0, got %" GST_TIME_FORMAT,
|
"Expected start of playback range 0, got %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (first_ts));
|
GST_TIME_ARGS (first_ts));
|
||||||
fail_unless (last_ts == (3 * GST_SECOND),
|
fail_unless (last_ts == exp_last_time,
|
||||||
"Expected end of playback range 3s, got %" GST_TIME_FORMAT,
|
"Expected end of playback range 3s, got %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (last_ts));
|
GST_TIME_ARGS (last_ts));
|
||||||
|
|
||||||
|
@ -572,6 +572,87 @@ GST_START_TEST (test_splitmuxsrc_sparse_streams)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
struct CapsChangeData
|
||||||
|
{
|
||||||
|
guint count;
|
||||||
|
GstElement *cf;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstPadProbeReturn
|
||||||
|
switch_caps (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct CapsChangeData *data = (struct CapsChangeData *) (user_data);
|
||||||
|
|
||||||
|
if (data->count == 4) {
|
||||||
|
GST_INFO ("Saw 5 buffers to the encoder. Switching caps");
|
||||||
|
gst_util_set_object_arg (G_OBJECT (data->cf), "caps",
|
||||||
|
"video/x-raw,width=160,height=128,framerate=10/1");
|
||||||
|
}
|
||||||
|
data->count++;
|
||||||
|
return GST_PAD_PROBE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_splitmuxsrc_caps_change)
|
||||||
|
{
|
||||||
|
GstMessage *msg;
|
||||||
|
GstElement *pipeline;
|
||||||
|
GstElement *sink;
|
||||||
|
GstElement *cf;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
gchar *dest_pattern;
|
||||||
|
guint count;
|
||||||
|
gchar *in_pattern;
|
||||||
|
struct CapsChangeData data;
|
||||||
|
|
||||||
|
/* This test creates a new file only by changing the caps, which
|
||||||
|
* qtmux will reject (for now - if qtmux starts supporting caps
|
||||||
|
* changes, this test will break and need fixing/disabling */
|
||||||
|
pipeline =
|
||||||
|
gst_parse_launch
|
||||||
|
("videotestsrc num-buffers=10 !"
|
||||||
|
" capsfilter name=c caps=video/x-raw,width=80,height=64,framerate=10/1 !"
|
||||||
|
" jpegenc ! splitmuxsink name=splitsink muxer=qtmux", NULL);
|
||||||
|
fail_if (pipeline == NULL);
|
||||||
|
sink = gst_bin_get_by_name (GST_BIN (pipeline), "splitsink");
|
||||||
|
fail_if (sink == NULL);
|
||||||
|
g_signal_connect (sink, "format-location-full",
|
||||||
|
(GCallback) check_format_location, NULL);
|
||||||
|
dest_pattern = g_build_filename (tmpdir, "out%05d.mp4", NULL);
|
||||||
|
g_object_set (G_OBJECT (sink), "location", dest_pattern, NULL);
|
||||||
|
g_free (dest_pattern);
|
||||||
|
g_object_unref (sink);
|
||||||
|
|
||||||
|
cf = gst_bin_get_by_name (GST_BIN (pipeline), "c");
|
||||||
|
sinkpad = gst_element_get_static_pad (cf, "sink");
|
||||||
|
|
||||||
|
data.cf = cf;
|
||||||
|
data.count = 0;
|
||||||
|
|
||||||
|
gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER,
|
||||||
|
switch_caps, &data, NULL);
|
||||||
|
|
||||||
|
gst_object_unref (sinkpad);
|
||||||
|
gst_object_unref (cf);
|
||||||
|
|
||||||
|
msg = run_pipeline (pipeline);
|
||||||
|
|
||||||
|
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR)
|
||||||
|
dump_error (msg);
|
||||||
|
fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
|
||||||
|
gst_message_unref (msg);
|
||||||
|
|
||||||
|
gst_object_unref (pipeline);
|
||||||
|
|
||||||
|
count = count_files (tmpdir);
|
||||||
|
fail_unless (count == 2, "Expected 2 output files, got %d", count);
|
||||||
|
|
||||||
|
in_pattern = g_build_filename (tmpdir, "out*.mp4", NULL);
|
||||||
|
test_playback (in_pattern, 0, GST_SECOND);
|
||||||
|
g_free (in_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
/* For verifying bug https://bugzilla.gnome.org/show_bug.cgi?id=762893 */
|
/* For verifying bug https://bugzilla.gnome.org/show_bug.cgi?id=762893 */
|
||||||
GST_START_TEST (test_splitmuxsink_reuse_simple)
|
GST_START_TEST (test_splitmuxsink_reuse_simple)
|
||||||
{
|
{
|
||||||
|
@ -606,7 +687,9 @@ splitmux_suite (void)
|
||||||
TCase *tc_chain = tcase_create ("general");
|
TCase *tc_chain = tcase_create ("general");
|
||||||
TCase *tc_chain_basic = tcase_create ("basic");
|
TCase *tc_chain_basic = tcase_create ("basic");
|
||||||
TCase *tc_chain_complex = tcase_create ("complex");
|
TCase *tc_chain_complex = tcase_create ("complex");
|
||||||
gboolean have_theora, have_ogg, have_vorbis, have_matroska;
|
TCase *tc_chain_caps_change = tcase_create ("caps_change");
|
||||||
|
gboolean have_theora, have_ogg, have_vorbis, have_matroska, have_qtmux,
|
||||||
|
have_jpeg;
|
||||||
|
|
||||||
/* we assume that if encoder/muxer are there, decoder/demuxer will be a well */
|
/* we assume that if encoder/muxer are there, decoder/demuxer will be a well */
|
||||||
have_theora = gst_registry_check_feature_version (gst_registry_get (),
|
have_theora = gst_registry_check_feature_version (gst_registry_get (),
|
||||||
|
@ -617,10 +700,15 @@ splitmux_suite (void)
|
||||||
"vorbisenc", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
"vorbisenc", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
||||||
have_matroska = gst_registry_check_feature_version (gst_registry_get (),
|
have_matroska = gst_registry_check_feature_version (gst_registry_get (),
|
||||||
"matroskamux", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
"matroskamux", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
||||||
|
have_qtmux = gst_registry_check_feature_version (gst_registry_get (),
|
||||||
|
"qtmux", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
||||||
|
have_jpeg = gst_registry_check_feature_version (gst_registry_get (),
|
||||||
|
"jpegenc", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
|
||||||
|
|
||||||
suite_add_tcase (s, tc_chain);
|
suite_add_tcase (s, tc_chain);
|
||||||
suite_add_tcase (s, tc_chain_basic);
|
suite_add_tcase (s, tc_chain_basic);
|
||||||
suite_add_tcase (s, tc_chain_complex);
|
suite_add_tcase (s, tc_chain_complex);
|
||||||
|
suite_add_tcase (s, tc_chain_caps_change);
|
||||||
|
|
||||||
tcase_add_test (tc_chain_basic, test_splitmuxsink_reuse_simple);
|
tcase_add_test (tc_chain_basic, test_splitmuxsink_reuse_simple);
|
||||||
|
|
||||||
|
@ -643,6 +731,14 @@ splitmux_suite (void)
|
||||||
GST_INFO ("Skipping tests, missing plugins: theora and/or ogg");
|
GST_INFO ("Skipping tests, missing plugins: theora and/or ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (have_qtmux && have_jpeg) {
|
||||||
|
tcase_add_checked_fixture (tc_chain_caps_change, tempdir_setup,
|
||||||
|
tempdir_cleanup);
|
||||||
|
tcase_add_test (tc_chain_caps_change, test_splitmuxsrc_caps_change);
|
||||||
|
} else {
|
||||||
|
GST_INFO ("Skipping tests, missing plugins: jpegenc or mp4mux");
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue