mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
encodebin: Add APIs to set element properties on encoding profiles
User often want to set encoder properties on encoding profiles, this introduces a way to easily 'preset' properties when defining the profile. This uses GstStructure to define those properties the same way it is done in `splitmux` for example as it makes simple to handle. This also defines a more complex structure type where we can map a set of properties to set depending on the muxer/encoder factory that has been picked by EncodeBin so it is quite flexible. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1002>
This commit is contained in:
parent
a8fdaba2ab
commit
a8fca8d040
5 changed files with 300 additions and 35 deletions
|
@ -30,8 +30,8 @@
|
|||
*
|
||||
* Functions to create and handle encoding profiles.
|
||||
*
|
||||
* Encoding profiles describe the media types and settings one wishes to use
|
||||
* for an encoding process. The top-level profiles are commonly
|
||||
* Encoding profiles describe the media types and settings one wishes to use for
|
||||
* an encoding process. The top-level profiles are commonly
|
||||
* #GstEncodingContainerProfile(s) (which contains a user-readable name and
|
||||
* description along with which container format to use). These, in turn,
|
||||
* reference one or more #GstEncodingProfile(s) which indicate which encoding
|
||||
|
@ -101,18 +101,21 @@
|
|||
*
|
||||
* ### Setting properties on muxers or on the encoding profile itself
|
||||
*
|
||||
* Moreover, you can set extra properties `presence`, `single-segment` and
|
||||
* `variable-framerate` * of an * encoding profile using the `|presence=` syntax
|
||||
* as in:
|
||||
* Moreover, you can set the extra properties:
|
||||
*
|
||||
* * `|element-properties,property1=true` (See
|
||||
* #gst_encoding_profile_set_element_properties)
|
||||
* * `|presence=true` (See See #gst_encoding_profile_get_presence)
|
||||
* * `|single-segment=true` (See #gst_encoding_profile_set_single_segment)
|
||||
* * `|single-segment=true` (See
|
||||
* #gst_encoding_video_profile_set_variableframerate)
|
||||
*
|
||||
* for example:
|
||||
*
|
||||
* ```
|
||||
* video/webm:video/x-vp8|presence=1,variable-framerate=true|single-segment=true:audio/x-vorbis
|
||||
* video/webm:video/x-vp8|presence=1|element-properties,target-bitrate=500000:audio/x-vorbis
|
||||
* ```
|
||||
*
|
||||
* This field allows specifies the maximum number of times a
|
||||
* #GstEncodingProfile can be used inside an encodebin. If 0, it is not a
|
||||
* mandatory stream and can be used as many times as necessary.
|
||||
*
|
||||
* ### Enforcing properties to the stream itself (video size, number of audio channels, etc..)
|
||||
*
|
||||
* You can also use the `restriction_caps->encoded_format_caps` syntax to
|
||||
|
@ -297,6 +300,8 @@
|
|||
#include <string.h>
|
||||
|
||||
/* GstEncodingProfile API */
|
||||
#define PROFILE_LOCK(profile) (g_mutex_lock(&((GstEncodingProfile*)profile)->lock))
|
||||
#define PROFILE_UNLOCK(profile) (g_mutex_unlock(&((GstEncodingProfile*)profile)->lock))
|
||||
|
||||
struct _GstEncodingProfile
|
||||
{
|
||||
|
@ -309,10 +314,14 @@ struct _GstEncodingProfile
|
|||
gchar *preset;
|
||||
gchar *preset_name;
|
||||
guint presence;
|
||||
GstCaps *restriction;
|
||||
gboolean allow_dynamic_output;
|
||||
gboolean enabled;
|
||||
gboolean single_segment;
|
||||
|
||||
GMutex lock; // {
|
||||
GstCaps *restriction;
|
||||
GstStructure *element_properties;
|
||||
// }
|
||||
};
|
||||
|
||||
struct _GstEncodingProfileClass
|
||||
|
@ -326,6 +335,7 @@ enum
|
|||
{
|
||||
FIRST_PROPERTY,
|
||||
PROP_RESTRICTION_CAPS,
|
||||
PROP_ELEMENT_PROPERTIES,
|
||||
LAST_PROPERTY
|
||||
};
|
||||
|
||||
|
@ -391,6 +401,11 @@ _encoding_profile_get_property (GObject * object, guint prop_id,
|
|||
case PROP_RESTRICTION_CAPS:
|
||||
gst_value_set_caps (value, prof->restriction);
|
||||
break;
|
||||
case PROP_ELEMENT_PROPERTIES:
|
||||
PROFILE_LOCK (prof);
|
||||
gst_value_set_structure (value, prof->element_properties);
|
||||
PROFILE_UNLOCK (prof);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -408,6 +423,14 @@ _encoding_profile_set_property (GObject * object, guint prop_id,
|
|||
gst_encoding_profile_set_restriction (prof, gst_caps_copy
|
||||
(gst_value_get_caps (value)));
|
||||
break;
|
||||
case PROP_ELEMENT_PROPERTIES:
|
||||
{
|
||||
const GstStructure *structure = gst_value_get_structure (value);
|
||||
|
||||
gst_encoding_profile_set_element_properties (prof,
|
||||
structure ? gst_structure_copy (structure) : NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -441,11 +464,30 @@ gst_encoding_profile_class_init (GstEncodingProfileClass * klass)
|
|||
_properties[PROP_RESTRICTION_CAPS] =
|
||||
g_param_spec_boxed ("restriction-caps", "Restriction caps",
|
||||
"The restriction caps to use", GST_TYPE_CAPS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_RESTRICTION_CAPS, _properties[PROP_RESTRICTION_CAPS]);
|
||||
/**
|
||||
* GstEncodingProfile:element-properties:
|
||||
*
|
||||
* A #GstStructure defining the properties to be set to the element
|
||||
* the profile represents.
|
||||
*
|
||||
* For example for `av1enc`:
|
||||
*
|
||||
* ```
|
||||
* element-properties,row-mt=true, end-usage=vbr
|
||||
* ```
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
_properties[PROP_ELEMENT_PROPERTIES] =
|
||||
g_param_spec_boxed ("element-properties", "Element properties",
|
||||
"The element properties to use. "
|
||||
"Example: {properties,boolean-prop=true,string-prop=\"hi\"}.",
|
||||
GST_TYPE_STRUCTURE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, LAST_PROPERTY, _properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -791,6 +833,84 @@ gst_encoding_profile_set_restriction (GstEncodingProfile * profile,
|
|||
_properties[PROP_RESTRICTION_CAPS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_element_properties:
|
||||
* @self: a #GstEncodingProfile
|
||||
* @element_properties: (transfer full): A #GstStructure defining the properties
|
||||
* to be set to the element the profile represents.
|
||||
*
|
||||
* This allows setting the muxing/encoding element properties.
|
||||
*
|
||||
* **Set properties generically**
|
||||
*
|
||||
* ``` properties
|
||||
* [element-properties, boolean-prop=true, string-prop="hi"]
|
||||
* ```
|
||||
*
|
||||
* **Mapping properties with well known element factories**
|
||||
*
|
||||
* ``` properties
|
||||
* element-properties-map, map = {
|
||||
* [openh264enc, gop-size=32, ],
|
||||
* [x264enc, key-int-max=32, tune=zerolatency],
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_element_properties (GstEncodingProfile * self,
|
||||
GstStructure * element_properties)
|
||||
{
|
||||
g_return_if_fail (GST_IS_ENCODING_PROFILE (self));
|
||||
g_return_if_fail (!element_properties
|
||||
|| GST_IS_STRUCTURE (element_properties));
|
||||
|
||||
#ifndef G_DISABLE_CHECKS
|
||||
if (element_properties &&
|
||||
(gst_structure_has_name (element_properties, "element-properties-map")
|
||||
|| gst_structure_has_name (element_properties, "properties-map")
|
||||
|| gst_structure_has_name (element_properties, "map")))
|
||||
g_return_if_fail (gst_structure_has_field_typed (element_properties, "map",
|
||||
GST_TYPE_LIST));
|
||||
#endif
|
||||
|
||||
PROFILE_LOCK (self);
|
||||
if (self->element_properties)
|
||||
gst_structure_free (self->element_properties);
|
||||
if (element_properties)
|
||||
self->element_properties = element_properties;
|
||||
else
|
||||
self->element_properties = NULL;
|
||||
PROFILE_UNLOCK (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self),
|
||||
_properties[PROP_ELEMENT_PROPERTIES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_element_properties:
|
||||
* @self: a #GstEncodingProfile
|
||||
*
|
||||
* Returns: (transfer full) (nullable): The properties that are going to be set on the underlying element
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstStructure *
|
||||
gst_encoding_profile_get_element_properties (GstEncodingProfile * self)
|
||||
{
|
||||
GstStructure *res = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (self), NULL);
|
||||
|
||||
PROFILE_LOCK (self);
|
||||
if (self->element_properties)
|
||||
res = gst_structure_copy (self->element_properties);
|
||||
PROFILE_UNLOCK (self);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Container profiles */
|
||||
|
||||
struct _GstEncodingContainerProfile
|
||||
|
@ -1648,6 +1768,30 @@ done:
|
|||
return profile;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_structure_validate_name (const gchar * name)
|
||||
{
|
||||
const gchar *s;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (G_UNLIKELY (!g_ascii_isalpha (*name)))
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: test name string more */
|
||||
s = &name[1];
|
||||
while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL))
|
||||
s++;
|
||||
|
||||
if (*s == ',')
|
||||
return TRUE;
|
||||
|
||||
if (G_UNLIKELY (*s != '\0'))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstEncodingProfile *
|
||||
create_encoding_stream_profile (gchar * serialized_profile,
|
||||
GList * muxers_and_encoders, GstCaps * raw_audio_caps,
|
||||
|
@ -1659,6 +1803,7 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
|||
gchar *strcaps, *strpresence, **strprops_v, **restriction_format,
|
||||
**preset_v, *preset_name = NULL, *factory_name = NULL,
|
||||
*variable_framerate = NULL;
|
||||
GstStructure *element_properties = NULL;
|
||||
GstCaps *restrictioncaps = NULL;
|
||||
GstEncodingProfile *profile = NULL;
|
||||
|
||||
|
@ -1694,12 +1839,26 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
|||
}
|
||||
|
||||
for (propi = 1; strprops_v[propi]; propi++) {
|
||||
gchar **propv = g_strsplit (strprops_v[propi], "=", -1);
|
||||
gchar **propv;
|
||||
gchar *presence_str = NULL;
|
||||
gchar *prop = strprops_v[propi];
|
||||
GstStructure *tmpstruct = NULL;
|
||||
|
||||
if (gst_structure_validate_name (prop))
|
||||
tmpstruct = gst_structure_new_from_string (prop);
|
||||
if (tmpstruct) {
|
||||
if (element_properties)
|
||||
gst_structure_free (element_properties);
|
||||
|
||||
element_properties = tmpstruct;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
propv = g_strsplit (prop, "=", -1);
|
||||
if (propv[1] && propv[2]) {
|
||||
g_warning ("Wrong format for property: %s, only 1 `=` is expected",
|
||||
strprops_v[propi]);
|
||||
prop);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1723,6 +1882,9 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
|||
|
||||
single_segment = g_value_get_boolean (&v);
|
||||
g_value_reset (&v);
|
||||
} else {
|
||||
g_warning ("Unsupported property: %s", propv[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (presence_str) {
|
||||
|
@ -1806,6 +1968,9 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (element_properties)
|
||||
gst_encoding_profile_set_element_properties (profile, element_properties);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,14 @@ GST_PBUTILS_API
|
|||
GstEncodingProfile * gst_encoding_profile_from_discoverer (GstDiscovererInfo *info);
|
||||
|
||||
GST_PBUTILS_API
|
||||
GstEncodingProfile * gst_encoding_profile_copy (GstEncodingProfile *self);
|
||||
GstEncodingProfile * gst_encoding_profile_copy (GstEncodingProfile *self);
|
||||
|
||||
GST_PBUTILS_API
|
||||
void gst_encoding_profile_set_element_properties (GstEncodingProfile *self,
|
||||
GstStructure *element_properties);
|
||||
|
||||
GST_PBUTILS_API
|
||||
GstStructure *gst_encoding_profile_get_element_properties (GstEncodingProfile *self);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEncodingAudioProfile, gst_object_unref)
|
||||
|
||||
|
|
|
@ -870,12 +870,84 @@ beach:
|
|||
return parser;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_properties (GQuark property_id, const GValue * value, GObject * element)
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "Setting %s", g_quark_to_string (property_id));
|
||||
g_object_set_property (element, g_quark_to_string (property_id), value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_element_properties_from_encoding_profile (GstEncodingProfile * profile,
|
||||
GParamSpec * arg G_GNUC_UNUSED, GstElement * element)
|
||||
{
|
||||
gint i;
|
||||
const GValue *v;
|
||||
GstElementFactory *factory;
|
||||
GstStructure *properties =
|
||||
gst_encoding_profile_get_element_properties (profile);
|
||||
|
||||
if (!properties)
|
||||
return;
|
||||
|
||||
if (!gst_structure_has_name (properties, "element-properties-map")) {
|
||||
gst_structure_foreach (properties,
|
||||
(GstStructureForeachFunc) _set_properties, element);
|
||||
goto done;
|
||||
}
|
||||
|
||||
factory = gst_element_get_factory (element);
|
||||
if (!factory) {
|
||||
GST_INFO_OBJECT (profile, "No factory for underlying element, "
|
||||
"not setting properties");
|
||||
return;
|
||||
}
|
||||
|
||||
v = gst_structure_get_value (properties, "map");
|
||||
for (i = 0; i < gst_value_list_get_size (v); i++) {
|
||||
const GValue *map_value = gst_value_list_get_value (v, i);
|
||||
const GstStructure *tmp_properties;
|
||||
|
||||
if (!GST_VALUE_HOLDS_STRUCTURE (map_value)) {
|
||||
g_warning ("Invalid value type %s in the property map "
|
||||
"(expected GstStructure)", G_VALUE_TYPE_NAME (map_value));
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp_properties = gst_value_get_structure (map_value);
|
||||
if (!gst_structure_has_name (tmp_properties, GST_OBJECT_NAME (factory))) {
|
||||
GST_INFO_OBJECT (GST_OBJECT_PARENT (element),
|
||||
"Ignoring values for %" GST_PTR_FORMAT, tmp_properties);
|
||||
continue;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (GST_OBJECT_PARENT (element),
|
||||
"Setting %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, tmp_properties,
|
||||
element);
|
||||
gst_structure_foreach (tmp_properties,
|
||||
(GstStructureForeachFunc) _set_properties, element);
|
||||
goto done;
|
||||
}
|
||||
|
||||
GST_ERROR_OBJECT (GST_OBJECT_PARENT (element), "Unknown factory: %s",
|
||||
GST_OBJECT_NAME (factory));
|
||||
|
||||
done:
|
||||
gst_structure_free (properties);
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
_create_element_and_set_preset (GstElementFactory * factory,
|
||||
const gchar * preset, const gchar * name, const gchar * preset_name)
|
||||
GstEncodingProfile * profile, const gchar * name)
|
||||
{
|
||||
GstElement *res = NULL;
|
||||
const gchar *preset;
|
||||
const gchar *preset_name;
|
||||
|
||||
preset_name = gst_encoding_profile_get_preset_name (profile);
|
||||
preset = gst_encoding_profile_get_preset (profile);
|
||||
GST_DEBUG ("Creating element from factory %s (preset factory name: %s"
|
||||
" preset name: %s)", GST_OBJECT_NAME (factory), preset_name, preset);
|
||||
|
||||
|
@ -902,6 +974,12 @@ _create_element_and_set_preset (GstElementFactory * factory,
|
|||
}
|
||||
}
|
||||
/* Else we keep it */
|
||||
if (res) {
|
||||
set_element_properties_from_encoding_profile (profile, NULL, res);
|
||||
|
||||
g_signal_connect (profile, "notify::element-properties",
|
||||
G_CALLBACK (set_element_properties_from_encoding_profile), res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -914,11 +992,8 @@ _get_encoder (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
|
|||
GstElement *encoder = NULL;
|
||||
GstElementFactory *encoderfact = NULL;
|
||||
GstCaps *format;
|
||||
const gchar *preset, *preset_name;
|
||||
|
||||
format = gst_encoding_profile_get_format (sprof);
|
||||
preset = gst_encoding_profile_get_preset (sprof);
|
||||
preset_name = gst_encoding_profile_get_preset_name (sprof);
|
||||
|
||||
GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
|
||||
|
||||
|
@ -948,8 +1023,7 @@ _get_encoder (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
|
|||
|
||||
for (tmp = encoders; tmp; tmp = tmp->next) {
|
||||
encoderfact = (GstElementFactory *) tmp->data;
|
||||
if ((encoder = _create_element_and_set_preset (encoderfact, preset,
|
||||
NULL, preset_name)))
|
||||
if ((encoder = _create_element_and_set_preset (encoderfact, sprof, NULL)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1532,7 @@ _create_stream_group (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof,
|
|||
tosync = g_list_append (tosync, sgroup->identity);
|
||||
} else {
|
||||
GST_INFO_OBJECT (ebin, "Single segment is not supported when avoiding"
|
||||
" to reencode!");
|
||||
" to re-encode!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1900,11 +1974,7 @@ _get_formatter (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
|
|||
GstElement *formatter = NULL;
|
||||
GstElementFactory *formatterfact = NULL;
|
||||
GstCaps *format;
|
||||
const gchar *preset, *preset_name;
|
||||
|
||||
format = gst_encoding_profile_get_format (sprof);
|
||||
preset = gst_encoding_profile_get_preset (sprof);
|
||||
preset_name = gst_encoding_profile_get_preset_name (sprof);
|
||||
|
||||
GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
|
||||
|
||||
|
@ -1923,8 +1993,7 @@ _get_formatter (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
|
|||
GST_OBJECT_NAME (formatterfact));
|
||||
|
||||
if ((formatter =
|
||||
_create_element_and_set_preset (formatterfact, preset,
|
||||
NULL, preset_name)))
|
||||
_create_element_and_set_preset (formatterfact, sprof, NULL)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1969,10 +2038,9 @@ _get_muxer (GstEncodeBaseBin * ebin)
|
|||
GstElementFactory *muxerfact = NULL;
|
||||
const GList *tmp;
|
||||
GstCaps *format;
|
||||
const gchar *preset, *preset_name;
|
||||
const gchar *preset_name;
|
||||
|
||||
format = gst_encoding_profile_get_format (ebin->profile);
|
||||
preset = gst_encoding_profile_get_preset (ebin->profile);
|
||||
preset_name = gst_encoding_profile_get_preset_name (ebin->profile);
|
||||
|
||||
GST_DEBUG_OBJECT (ebin, "Getting list of muxers for format %" GST_PTR_FORMAT,
|
||||
|
@ -2037,8 +2105,7 @@ _get_muxer (GstEncodeBaseBin * ebin)
|
|||
/* Only use a muxer than can use all streams and than can accept the
|
||||
* preset (which may be present or not) */
|
||||
if (cansinkstreams && (muxer =
|
||||
_create_element_and_set_preset (muxerfact, preset, "muxer",
|
||||
preset_name)))
|
||||
_create_element_and_set_preset (muxerfact, ebin->profile, "muxer")))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2259,8 +2326,11 @@ stream_group_free (GstEncodeBaseBin * ebin, StreamGroup * sgroup)
|
|||
if (sgroup->inqueue)
|
||||
gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
|
||||
|
||||
if (sgroup->encoder)
|
||||
if (sgroup->encoder) {
|
||||
gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
|
||||
g_signal_handlers_disconnect_by_func (sgroup->profile,
|
||||
set_element_properties_from_encoding_profile, sgroup->encoder);
|
||||
}
|
||||
if (sgroup->fakesink)
|
||||
gst_element_set_state (sgroup->fakesink, GST_STATE_NULL);
|
||||
if (sgroup->outfilter) {
|
||||
|
@ -2372,6 +2442,8 @@ gst_encode_base_bin_tear_down_profile (GstEncodeBaseBin * ebin)
|
|||
|
||||
/* Remove muxer if present */
|
||||
if (ebin->muxer) {
|
||||
g_signal_handlers_disconnect_by_func (ebin->profile,
|
||||
set_element_properties_from_encoding_profile, ebin->muxer);
|
||||
gst_element_set_state (ebin->muxer, GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (ebin), ebin->muxer);
|
||||
ebin->muxer = NULL;
|
||||
|
|
20
tests/validate/encodebin/set-encoder-properties.validatetest
Normal file
20
tests/validate/encodebin/set-encoder-properties.validatetest
Normal file
|
@ -0,0 +1,20 @@
|
|||
meta,
|
||||
seek=false,
|
||||
handles-states=true,
|
||||
args = {
|
||||
"audiotestsrc num-buffers=4 ! encodebin name=ebin profile=\"vorbisenc|element-properties,managed=true,name=audioencoder\" ! fakesink",
|
||||
}
|
||||
|
||||
pause
|
||||
check-properties, audioencoder::managed=true
|
||||
|
||||
set-properties, ebin::profile::element-properties=[
|
||||
element-properties-map, map = {
|
||||
[vorbisenc, managed=false],
|
||||
[somethingelse, whatever=false],
|
||||
},
|
||||
]
|
||||
|
||||
check-properties, audioencoder::managed=false
|
||||
|
||||
stop
|
|
@ -19,6 +19,7 @@ tests = [
|
|||
'videorate/rate_2_0_with_decoder',
|
||||
'compositor/renogotiate_failing_unsupported_src_format',
|
||||
'giosrc/read-growing-file',
|
||||
'encodebin/set-encoder-properties',
|
||||
]
|
||||
|
||||
env = environment()
|
||||
|
|
Loading…
Reference in a new issue