mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
encodebin: Fallback to other profile if we fail with one
In some case we might have EncodingProfile that will be defined in a way that, for example if a Preset is not present, another profile for that stream should be used. A test is added showing the feature. https://bugzilla.gnome.org/show_bug.cgi?id=776188
This commit is contained in:
parent
2d1b5a1dc2
commit
c8ea302e57
2 changed files with 88 additions and 18 deletions
|
@ -315,7 +315,8 @@ static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin,
|
|||
GstEncodingProfile * profile);
|
||||
|
||||
static StreamGroup *_create_stream_group (GstEncodeBin * ebin,
|
||||
GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps);
|
||||
GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps,
|
||||
gboolean * encoder_not_found);
|
||||
static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
|
||||
static void stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup);
|
||||
static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
|
||||
|
@ -325,6 +326,8 @@ static GstPad *gst_encode_bin_request_profile_pad_signal (GstEncodeBin *
|
|||
|
||||
static inline GstElement *_get_formatter (GstEncodeBin * ebin,
|
||||
GstEncodingProfile * sprof);
|
||||
static void _post_missing_plugin_message (GstEncodeBin * ebin,
|
||||
GstEncodingProfile * prof);
|
||||
|
||||
static void
|
||||
gst_encode_bin_class_init (GstEncodeBinClass * klass)
|
||||
|
@ -632,7 +635,7 @@ stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof)
|
|||
|
||||
static inline GstEncodingProfile *
|
||||
next_unused_stream_profile (GstEncodeBin * ebin, GType ptype,
|
||||
const gchar * name, GstCaps * caps)
|
||||
const gchar * name, GstCaps * caps, GstEncodingProfile * previous_profile)
|
||||
{
|
||||
GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
|
||||
g_type_name (ptype), caps);
|
||||
|
@ -701,8 +704,11 @@ next_unused_stream_profile (GstEncodeBin * ebin, GType ptype,
|
|||
if (!gst_encoding_profile_is_enabled (sprof)) {
|
||||
GST_INFO_OBJECT (ebin, "%p is disabled, not using it", sprof);
|
||||
} else if (presence == 0
|
||||
|| (presence > stream_profile_used_count (ebin, sprof)))
|
||||
return sprof;
|
||||
|| (presence > stream_profile_used_count (ebin, sprof))) {
|
||||
|
||||
if (sprof != previous_profile)
|
||||
return sprof;
|
||||
}
|
||||
} else if (caps && ptype == G_TYPE_NONE) {
|
||||
GstCaps *outcaps;
|
||||
gboolean res;
|
||||
|
@ -713,7 +719,7 @@ next_unused_stream_profile (GstEncodeBin * ebin, GType ptype,
|
|||
res = gst_caps_can_intersect (outcaps, caps);
|
||||
gst_caps_unref (outcaps);
|
||||
|
||||
if (res)
|
||||
if (res && sprof != previous_profile)
|
||||
return sprof;
|
||||
}
|
||||
}
|
||||
|
@ -726,20 +732,39 @@ static GstPad *
|
|||
request_pad_for_stream (GstEncodeBin * encodebin, GType ptype,
|
||||
const gchar * name, GstCaps * caps)
|
||||
{
|
||||
StreamGroup *sgroup;
|
||||
StreamGroup *sgroup = NULL;
|
||||
GList *not_found_encoder_profs = NULL, *tmp;
|
||||
GstEncodingProfile *sprof;
|
||||
|
||||
GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
|
||||
|
||||
/* Figure out if we have a unused GstEncodingProfile we can use for
|
||||
* these caps */
|
||||
sprof = next_unused_stream_profile (encodebin, ptype, name, caps);
|
||||
while (sgroup == NULL) {
|
||||
gboolean encoder_not_found = FALSE;
|
||||
/* Figure out if we have a unused GstEncodingProfile we can use for
|
||||
* these caps */
|
||||
sprof = next_unused_stream_profile (encodebin, ptype, name, caps, sprof);
|
||||
|
||||
if (G_UNLIKELY (sprof == NULL))
|
||||
goto no_stream_profile;
|
||||
if (G_UNLIKELY (sprof == NULL))
|
||||
goto no_stream_profile;
|
||||
|
||||
sgroup = _create_stream_group (encodebin, sprof, name, caps);
|
||||
if (G_UNLIKELY (sgroup == NULL))
|
||||
sgroup = _create_stream_group (encodebin, sprof, name, caps,
|
||||
&encoder_not_found);
|
||||
|
||||
if (G_UNLIKELY (sgroup))
|
||||
break;
|
||||
|
||||
if (encoder_not_found) {
|
||||
not_found_encoder_profs = g_list_prepend (not_found_encoder_profs, sprof);
|
||||
if (name) {
|
||||
GST_DEBUG ("Could not create an encoder for %s", name);
|
||||
goto no_stream_group;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sgroup)
|
||||
goto no_stream_group;
|
||||
|
||||
return sgroup->ghostpad;
|
||||
|
@ -752,6 +777,10 @@ no_stream_profile:
|
|||
|
||||
no_stream_group:
|
||||
{
|
||||
for (tmp = not_found_encoder_profs; tmp; tmp = tmp->next)
|
||||
_post_missing_plugin_message (encodebin, tmp->data);
|
||||
g_list_free (not_found_encoder_profs);
|
||||
|
||||
GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1182,10 +1211,13 @@ _set_up_fake_encoder_pad_probe (GstEncodeBin * ebin, StreamGroup * sgroup)
|
|||
* Create the elements, StreamGroup, add the sink pad, link it to the muxer
|
||||
*
|
||||
* sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
|
||||
* sinkcaps: If non-NULL will be used to figure out how to setup the group */
|
||||
* sinkcaps: If non-NULL will be used to figure out how to setup the group
|
||||
* encoder_not_found: If non NULL, set to TRUE if failure happened because
|
||||
* the encoder could not be found
|
||||
*/
|
||||
static StreamGroup *
|
||||
_create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
|
||||
const gchar * sinkpadname, GstCaps * sinkcaps)
|
||||
const gchar * sinkpadname, GstCaps * sinkcaps, gboolean * encoder_not_found)
|
||||
{
|
||||
StreamGroup *sgroup = NULL;
|
||||
GstPad *sinkpad, *srcpad, *muxerpad = NULL;
|
||||
|
@ -1397,7 +1429,11 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
|
|||
g_object_unref (srcpad);
|
||||
} else if (gst_encoding_profile_get_preset (sgroup->profile)
|
||||
|| gst_encoding_profile_get_preset_name (sgroup->profile)) {
|
||||
_post_missing_plugin_message (ebin, sprof);
|
||||
|
||||
if (!encoder_not_found)
|
||||
_post_missing_plugin_message (ebin, sprof);
|
||||
else
|
||||
*encoder_not_found = TRUE;
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* passthrough can still work, if we discover that *
|
||||
|
@ -1907,14 +1943,15 @@ create_elements_and_pads (GstEncodeBin * ebin)
|
|||
|
||||
if (gst_encoding_profile_get_presence (sprof) != 0 &&
|
||||
gst_encoding_profile_is_enabled (sprof)) {
|
||||
if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL))
|
||||
if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL,
|
||||
NULL) == NULL))
|
||||
goto stream_error;
|
||||
}
|
||||
}
|
||||
gst_element_sync_state_with_parent (muxer);
|
||||
} else {
|
||||
if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
|
||||
NULL) == NULL))
|
||||
NULL, NULL) == NULL))
|
||||
goto stream_error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1081,6 +1081,38 @@ GST_START_TEST (test_encodebin_missing_plugin_messages)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_encodebin_fallback_profiles_on_failure)
|
||||
{
|
||||
GstElement *ebin;
|
||||
GstPad *sinkpad = NULL;
|
||||
GstCaps *vorbiscaps;
|
||||
GstEncodingProfile *profile, *vorbis_profile;
|
||||
|
||||
ebin = gst_element_factory_make ("encodebin", NULL);
|
||||
|
||||
/* Create a ogg profile with a vorbis sub profile
|
||||
* that can't be 'instanciated' because its preset is set
|
||||
* to nowaythispresetexists. */
|
||||
profile = create_ogg_vorbis_profile (0, "nowaythispresetexists");
|
||||
vorbis_profile = create_vorbis_only_profile ();
|
||||
gst_encoding_container_profile_add_profile (GST_ENCODING_CONTAINER_PROFILE
|
||||
(profile), vorbis_profile);
|
||||
set_profile (ebin, profile);
|
||||
|
||||
/* Check if the audio sink pad can be created, meaning
|
||||
* that the first profile with a 'nowaythispresetexists'
|
||||
* preset has been skipped. */
|
||||
vorbiscaps = gst_caps_from_string ("audio/x-vorbis");
|
||||
g_signal_emit_by_name (ebin, "request-pad", vorbiscaps, &sinkpad);
|
||||
_caps_match (sinkpad, "audio/x-raw;audio/x-vorbis");
|
||||
gst_element_release_request_pad (ebin, sinkpad);
|
||||
gst_object_unref (sinkpad);
|
||||
|
||||
gst_object_unref (ebin);
|
||||
};
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
encodebin_suite (void)
|
||||
{
|
||||
|
@ -1107,6 +1139,7 @@ encodebin_suite (void)
|
|||
tcase_add_test (tc_chain, test_encodebin_reuse);
|
||||
tcase_add_test (tc_chain, test_encodebin_named_requests);
|
||||
tcase_add_test (tc_chain, test_encodebin_missing_plugin_messages);
|
||||
tcase_add_test (tc_chain, test_encodebin_fallback_profiles_on_failure);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue