mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
encodebin: Autoplug formatters
Autoplug formatters for streams if a formatter with secondary or higher rank is found. Formatters are autoplugged when there is no muxer or when the muxer doesn't implement the tagsetter interface. Currently only the first formatter found is plugged, this might help in lots of cases, but it doesn't solve the 'lamemp3 ! xingmux ! id3mux' case. https://bugzilla.gnome.org/show_bug.cgi?id=649841
This commit is contained in:
parent
0060900d68
commit
b5fb542386
1 changed files with 104 additions and 8 deletions
|
@ -162,6 +162,7 @@ struct _GstEncodeBin
|
||||||
|
|
||||||
/* available muxers, encoders and parsers */
|
/* available muxers, encoders and parsers */
|
||||||
GList *muxers;
|
GList *muxers;
|
||||||
|
GList *formatters;
|
||||||
GList *encoders;
|
GList *encoders;
|
||||||
GList *parsers;
|
GList *parsers;
|
||||||
|
|
||||||
|
@ -205,6 +206,7 @@ struct _StreamGroup
|
||||||
GstElement *parser;
|
GstElement *parser;
|
||||||
GstElement *smartencoder;
|
GstElement *smartencoder;
|
||||||
GstElement *outfilter; /* Output capsfilter (streamprofile.format) */
|
GstElement *outfilter; /* Output capsfilter (streamprofile.format) */
|
||||||
|
GstElement *formatter;
|
||||||
GstElement *outqueue; /* Queue just before the muxer */
|
GstElement *outqueue; /* Queue just before the muxer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -279,6 +281,9 @@ static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
|
||||||
static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
|
static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
|
||||||
|
static inline GstElement *_get_formatter (GstEncodeBin * ebin,
|
||||||
|
GstEncodingProfile * sprof);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_encode_bin_class_init (GstEncodeBinClass * klass)
|
gst_encode_bin_class_init (GstEncodeBinClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -388,6 +393,9 @@ gst_encode_bin_dispose (GObject * object)
|
||||||
if (ebin->muxers)
|
if (ebin->muxers)
|
||||||
gst_plugin_feature_list_free (ebin->muxers);
|
gst_plugin_feature_list_free (ebin->muxers);
|
||||||
|
|
||||||
|
if (ebin->formatters)
|
||||||
|
gst_plugin_feature_list_free (ebin->formatters);
|
||||||
|
|
||||||
if (ebin->encoders)
|
if (ebin->encoders)
|
||||||
gst_plugin_feature_list_free (ebin->encoders);
|
gst_plugin_feature_list_free (ebin->encoders);
|
||||||
|
|
||||||
|
@ -410,15 +418,14 @@ static void
|
||||||
gst_encode_bin_init (GstEncodeBin * encode_bin)
|
gst_encode_bin_init (GstEncodeBin * encode_bin)
|
||||||
{
|
{
|
||||||
GstPadTemplate *tmpl;
|
GstPadTemplate *tmpl;
|
||||||
GList *formatters;
|
|
||||||
|
|
||||||
encode_bin->muxers =
|
encode_bin->muxers =
|
||||||
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
|
||||||
GST_RANK_MARGINAL);
|
GST_RANK_MARGINAL);
|
||||||
formatters =
|
|
||||||
|
encode_bin->formatters =
|
||||||
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
|
||||||
GST_RANK_SECONDARY);
|
GST_RANK_SECONDARY);
|
||||||
encode_bin->muxers = g_list_concat (encode_bin->muxers, formatters);
|
|
||||||
|
|
||||||
encode_bin->encoders =
|
encode_bin->encoders =
|
||||||
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
|
||||||
|
@ -910,6 +917,16 @@ no_template:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_has_class (GstElement * element, const gchar * classname)
|
||||||
|
{
|
||||||
|
GstElementClass *klass;
|
||||||
|
|
||||||
|
klass = GST_ELEMENT_GET_CLASS (element);
|
||||||
|
|
||||||
|
return strstr (klass->details.klass, classname) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME : Add handling of streams that don't need encoding */
|
/* FIXME : Add handling of streams that don't need encoding */
|
||||||
/* FIXME : Add handling of streams that don't require conversion elements */
|
/* FIXME : Add handling of streams that don't require conversion elements */
|
||||||
/*
|
/*
|
||||||
|
@ -966,6 +983,7 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
|
||||||
muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
|
muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
|
||||||
if (G_UNLIKELY (muxerpad == NULL))
|
if (G_UNLIKELY (muxerpad == NULL))
|
||||||
goto no_muxer_pad;
|
goto no_muxer_pad;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output Queue.
|
/* Output Queue.
|
||||||
|
@ -988,6 +1006,26 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
|
||||||
}
|
}
|
||||||
gst_object_unref (srcpad);
|
gst_object_unref (srcpad);
|
||||||
|
|
||||||
|
/* Check if we need a formatter
|
||||||
|
* If we have no muxer or
|
||||||
|
* if the muxer isn't a formatter and doesn't implement the tagsetter interface
|
||||||
|
*/
|
||||||
|
if (!ebin->muxer
|
||||||
|
|| (!gst_element_implements_interface (ebin->muxer, GST_TYPE_TAG_SETTER)
|
||||||
|
|| !_has_class (ebin->muxer, "Formatter"))) {
|
||||||
|
sgroup->formatter = _get_formatter (ebin, sprof);
|
||||||
|
if (sgroup->formatter) {
|
||||||
|
GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
|
||||||
|
|
||||||
|
gst_bin_add (GST_BIN (ebin), sgroup->formatter);
|
||||||
|
tosync = g_list_append (tosync, sgroup->formatter);
|
||||||
|
if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
|
||||||
|
goto formatter_link_failure;
|
||||||
|
last = sgroup->formatter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Output capsfilter
|
/* Output capsfilter
|
||||||
* This will receive the format caps from the streamprofile */
|
* This will receive the format caps from the streamprofile */
|
||||||
GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
|
GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
|
||||||
|
@ -1327,10 +1365,15 @@ muxer_link_failure:
|
||||||
GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
|
GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
outfilter_link_failure:
|
formatter_link_failure:
|
||||||
GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
|
GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
outfilter_link_failure:
|
||||||
|
GST_ERROR_OBJECT (ebin,
|
||||||
|
"Couldn't link output filter to output queue/formatter");
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
passthrough_link_failure:
|
passthrough_link_failure:
|
||||||
GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
|
GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -1390,10 +1433,49 @@ _factory_can_sink_caps (GstElementFactory * factory, const GstCaps * caps)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline GstElement *
|
||||||
|
_get_formatter (GstEncodeBin * ebin, GstEncodingProfile * sprof)
|
||||||
|
{
|
||||||
|
GList *formatters, *tmpfmtr;
|
||||||
|
GstElement *formatter = NULL;
|
||||||
|
GstElementFactory *formatterfact = NULL;
|
||||||
|
const GstCaps *format;
|
||||||
|
const gchar *preset;
|
||||||
|
|
||||||
|
format = gst_encoding_profile_get_format (sprof);
|
||||||
|
preset = gst_encoding_profile_get_preset (sprof);
|
||||||
|
|
||||||
|
GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
|
||||||
|
|
||||||
|
formatters =
|
||||||
|
gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
if (formatters == NULL)
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
/* FIXME : signal the user if he wants this */
|
||||||
|
for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
|
||||||
|
formatterfact = (GstElementFactory *) tmpfmtr->data;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
|
||||||
|
GST_PLUGIN_FEATURE_NAME (formatterfact));
|
||||||
|
|
||||||
|
if ((formatter =
|
||||||
|
_create_element_and_set_preset (formatterfact, preset, NULL)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_plugin_feature_list_free (formatters);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
static inline GstElement *
|
static inline GstElement *
|
||||||
_get_muxer (GstEncodeBin * ebin)
|
_get_muxer (GstEncodeBin * ebin)
|
||||||
{
|
{
|
||||||
GList *muxers, *tmpmux;
|
GList *muxers, *formatters, *tmpmux;
|
||||||
GstElement *muxer = NULL;
|
GstElement *muxer = NULL;
|
||||||
GstElementFactory *muxerfact = NULL;
|
GstElementFactory *muxerfact = NULL;
|
||||||
const GList *tmp;
|
const GList *tmp;
|
||||||
|
@ -1408,6 +1490,12 @@ _get_muxer (GstEncodeBin * ebin)
|
||||||
muxers =
|
muxers =
|
||||||
gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
|
gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
|
||||||
|
|
||||||
|
formatters =
|
||||||
|
gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
muxers = g_list_concat (muxers, formatters);
|
||||||
|
|
||||||
if (muxers == NULL)
|
if (muxers == NULL)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
|
@ -1592,9 +1680,17 @@ stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup)
|
||||||
if (sgroup->outqueue)
|
if (sgroup->outqueue)
|
||||||
gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
|
gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
|
||||||
|
|
||||||
/* Capsfilter - outqueue */
|
if (sgroup->formatter) {
|
||||||
gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
|
/* capsfilter - formatter - outqueue */
|
||||||
gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
|
gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
|
||||||
|
gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
|
||||||
|
gst_element_unlink (sgroup->formatter, sgroup->outqueue);
|
||||||
|
gst_element_unlink (sgroup->outfilter, sgroup->formatter);
|
||||||
|
} else {
|
||||||
|
/* Capsfilter - outqueue */
|
||||||
|
gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
|
||||||
|
gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
|
||||||
|
}
|
||||||
gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
|
gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
|
||||||
gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
|
gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue