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