From 72c05d1cbb94f06e0340cf5578d6582322344f77 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Sun, 16 Nov 2014 15:54:56 +0100 Subject: [PATCH] encodebin: Add a way to disable caps renegotiation for output stream format In some cases, the user might want the stream outputted by encodebin to be in the exact same format during all the stream. We should let the user specify when this is the case. This commit add some API in the GstEncodingProfile to determine whether the format can be renegotiated after the encoding started or not. API: gst_encoding_profile_set_allow_dynamic_output gst_encoding_profile_get_allow_dynamic_output https://bugzilla.gnome.org/show_bug.cgi?id=740214 --- docs/libs/gst-plugins-base-libs-sections.txt | 2 + gst-libs/gst/pbutils/encoding-profile.c | 31 ++++++++++++ gst-libs/gst/pbutils/encoding-profile.h | 3 ++ gst/encoding/gstencodebin.c | 52 +++++++++++++++++++- win32/common/libgstpbutils.def | 2 + 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index c6f757e12e..0fff111c4a 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -2112,6 +2112,7 @@ gst_encoding_profile_from_discoverer gst_encoding_profile_get_name gst_encoding_profile_get_description gst_encoding_profile_get_format +gst_encoding_profile_get_allow_renegotiation gst_encoding_profile_get_preset gst_encoding_profile_get_preset_name gst_encoding_profile_get_presence @@ -2120,6 +2121,7 @@ gst_encoding_profile_get_file_extension gst_encoding_profile_set_name gst_encoding_profile_set_description gst_encoding_profile_set_format +gst_encoding_profile_set_allow_renegotiation gst_encoding_profile_set_preset gst_encoding_profile_set_preset_name gst_encoding_profile_set_restriction diff --git a/gst-libs/gst/pbutils/encoding-profile.c b/gst-libs/gst/pbutils/encoding-profile.c index ac56436592..770e2ce36e 100644 --- a/gst-libs/gst/pbutils/encoding-profile.c +++ b/gst-libs/gst/pbutils/encoding-profile.c @@ -188,6 +188,7 @@ struct _GstEncodingProfile gchar *preset_name; guint presence; GstCaps *restriction; + gboolean allow_dynamic_output; }; struct _GstEncodingProfileClass @@ -464,6 +465,35 @@ gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format) profile->format = gst_caps_ref (format); } +/** + * gst_encoding_profile_get_allow_dynamic_output: + * @profile: a #GstEncodingProfile + * + * Get whether the format that has been negotiated in at some point can be renegotiated + * later during the encoding. + */ +gboolean +gst_encoding_profile_get_allow_dynamic_output (GstEncodingProfile * profile) +{ + return profile->allow_dynamic_output; +} + +/** + * gst_encoding_profile_set_allow_dynamic_output: + * @profile: a #GstEncodingProfile + * @allow_dynamic_output: Whether the format that has been negotiated first can be renegotiated + * during the encoding + * + * Sets whether the format that has been negotiated in at some point can be renegotiated + * later during the encoding. + */ +void +gst_encoding_profile_set_allow_dynamic_output (GstEncodingProfile * profile, + gboolean allow_dynamic_output) +{ + profile->allow_dynamic_output = allow_dynamic_output; +} + /** * gst_encoding_profile_set_preset: * @profile: a #GstEncodingProfile @@ -837,6 +867,7 @@ common_creation (GType objtype, GstCaps * format, const gchar * preset, prof->restriction = gst_caps_ref (restriction); prof->presence = presence; prof->preset_name = NULL; + prof->allow_dynamic_output = TRUE; return prof; } diff --git a/gst-libs/gst/pbutils/encoding-profile.h b/gst-libs/gst/pbutils/encoding-profile.h index 60e148d9cc..401c547f0a 100644 --- a/gst-libs/gst/pbutils/encoding-profile.h +++ b/gst-libs/gst/pbutils/encoding-profile.h @@ -125,6 +125,9 @@ void gst_encoding_profile_set_description (GstEncodingProfile *pro GstCaps * gst_encoding_profile_get_format (GstEncodingProfile *profile); void gst_encoding_profile_set_format (GstEncodingProfile *profile, GstCaps *format); +gboolean gst_encoding_profile_get_allow_dynamic_output (GstEncodingProfile *profile); +void gst_encoding_profile_set_allow_dynamic_output (GstEncodingProfile *profile, + gboolean allow_dynamic_output); const gchar * gst_encoding_profile_get_preset (GstEncodingProfile *profile); const gchar * gst_encoding_profile_get_preset_name (GstEncodingProfile *profile); void gst_encoding_profile_set_preset (GstEncodingProfile *profile, diff --git a/gst/encoding/gstencodebin.c b/gst/encoding/gstencodebin.c index 3a88603548..b98c0f6f27 100644 --- a/gst/encoding/gstencodebin.c +++ b/gst/encoding/gstencodebin.c @@ -220,6 +220,7 @@ struct _StreamGroup GstElement *parser; GstElement *smartencoder; GstElement *outfilter; /* Output capsfilter (streamprofile.format) */ + gulong outputfilter_caps_sid; GstElement *formatter; GstElement *outqueue; /* Queue just before the muxer */ gulong restriction_sid; @@ -1078,6 +1079,34 @@ _profile_restriction_caps_cb (GstEncodingProfile * profile, g_object_set (group->capsfilter, "caps", restriction, NULL); } +static void +_outfilter_caps_set_cb (GstPad * outfilter_sinkpad, + GParamSpec * arg G_GNUC_UNUSED, StreamGroup * group) +{ + GstCaps *caps; + + g_object_get (outfilter_sinkpad, "caps", &caps, NULL); + GST_INFO_OBJECT (group->ebin, "Forcing caps to %" GST_PTR_FORMAT, caps); + g_object_set (group->outfilter, "caps", caps, NULL); + g_signal_handler_disconnect (outfilter_sinkpad, group->outputfilter_caps_sid); + group->outputfilter_caps_sid = 0; +} + +static void +_set_group_caps_format (StreamGroup * sgroup, GstEncodingProfile * prof, + GstCaps * format) +{ + g_object_set (sgroup->outfilter, "caps", format, NULL); + + if (!gst_encoding_profile_get_allow_dynamic_output (prof)) { + if (!sgroup->outputfilter_caps_sid) { + sgroup->outputfilter_caps_sid = + g_signal_connect (sgroup->outfilter->sinkpads->data, + "notify::caps", G_CALLBACK (_outfilter_caps_set_cb), sgroup); + } + } +} + static void _post_missing_plugin_message (GstEncodeBin * ebin, GstEncodingProfile * prof) { @@ -1211,7 +1240,7 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof, * This will receive the format caps from the streamprofile */ GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format); sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL); - g_object_set (sgroup->outfilter, "caps", format, NULL); + _set_group_caps_format (sgroup, sprof, format); gst_bin_add (GST_BIN (ebin), sgroup->outfilter); tosync = g_list_append (tosync, sgroup->outfilter); @@ -1989,8 +2018,15 @@ stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup) gst_element_set_state (sgroup->encoder, GST_STATE_NULL); if (sgroup->fakesink) gst_element_set_state (sgroup->fakesink, GST_STATE_NULL); - if (sgroup->outfilter) + if (sgroup->outfilter) { gst_element_set_state (sgroup->outfilter, GST_STATE_NULL); + + if (sgroup->outputfilter_caps_sid) { + g_signal_handler_disconnect (sgroup->outfilter->sinkpads->data, + sgroup->outputfilter_caps_sid); + sgroup->outputfilter_caps_sid = 0; + } + } if (sgroup->smartencoder) gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL); @@ -2148,6 +2184,18 @@ gst_encode_bin_activate (GstEncodeBin * ebin) static void gst_encode_bin_deactivate (GstEncodeBin * ebin) { + GList *tmp; + + for (tmp = ebin->streams; tmp; tmp = tmp->next) { + StreamGroup *sgroup = tmp->data; + GstCaps *format = gst_encoding_profile_get_format (sgroup->profile); + + _set_group_caps_format (sgroup, sgroup->profile, format); + + if (format) + gst_caps_unref (format); + } + ebin->active = FALSE; } diff --git a/win32/common/libgstpbutils.def b/win32/common/libgstpbutils.def index d7f365e1e9..81504cc7ef 100644 --- a/win32/common/libgstpbutils.def +++ b/win32/common/libgstpbutils.def @@ -84,6 +84,7 @@ EXPORTS gst_encoding_list_available_categories gst_encoding_profile_find gst_encoding_profile_from_discoverer + gst_encoding_profile_get_allow_dynamic_output gst_encoding_profile_get_description gst_encoding_profile_get_file_extension gst_encoding_profile_get_format @@ -96,6 +97,7 @@ EXPORTS gst_encoding_profile_get_type gst_encoding_profile_get_type_nick gst_encoding_profile_is_equal + gst_encoding_profile_set_allow_dynamic_output gst_encoding_profile_set_description gst_encoding_profile_set_format gst_encoding_profile_set_name