mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +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.
|
* Functions to create and handle encoding profiles.
|
||||||
*
|
*
|
||||||
* Encoding profiles describe the media types and settings one wishes to use
|
* Encoding profiles describe the media types and settings one wishes to use for
|
||||||
* for an encoding process. The top-level profiles are commonly
|
* an encoding process. The top-level profiles are commonly
|
||||||
* #GstEncodingContainerProfile(s) (which contains a user-readable name and
|
* #GstEncodingContainerProfile(s) (which contains a user-readable name and
|
||||||
* description along with which container format to use). These, in turn,
|
* description along with which container format to use). These, in turn,
|
||||||
* reference one or more #GstEncodingProfile(s) which indicate which encoding
|
* reference one or more #GstEncodingProfile(s) which indicate which encoding
|
||||||
|
@ -101,18 +101,21 @@
|
||||||
*
|
*
|
||||||
* ### Setting properties on muxers or on the encoding profile itself
|
* ### Setting properties on muxers or on the encoding profile itself
|
||||||
*
|
*
|
||||||
* Moreover, you can set extra properties `presence`, `single-segment` and
|
* Moreover, you can set the extra properties:
|
||||||
* `variable-framerate` * of an * encoding profile using the `|presence=` syntax
|
*
|
||||||
* as in:
|
* * `|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..)
|
* ### 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
|
* You can also use the `restriction_caps->encoded_format_caps` syntax to
|
||||||
|
@ -297,6 +300,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* GstEncodingProfile API */
|
/* GstEncodingProfile API */
|
||||||
|
#define PROFILE_LOCK(profile) (g_mutex_lock(&((GstEncodingProfile*)profile)->lock))
|
||||||
|
#define PROFILE_UNLOCK(profile) (g_mutex_unlock(&((GstEncodingProfile*)profile)->lock))
|
||||||
|
|
||||||
struct _GstEncodingProfile
|
struct _GstEncodingProfile
|
||||||
{
|
{
|
||||||
|
@ -309,10 +314,14 @@ struct _GstEncodingProfile
|
||||||
gchar *preset;
|
gchar *preset;
|
||||||
gchar *preset_name;
|
gchar *preset_name;
|
||||||
guint presence;
|
guint presence;
|
||||||
GstCaps *restriction;
|
|
||||||
gboolean allow_dynamic_output;
|
gboolean allow_dynamic_output;
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
gboolean single_segment;
|
gboolean single_segment;
|
||||||
|
|
||||||
|
GMutex lock; // {
|
||||||
|
GstCaps *restriction;
|
||||||
|
GstStructure *element_properties;
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstEncodingProfileClass
|
struct _GstEncodingProfileClass
|
||||||
|
@ -326,6 +335,7 @@ enum
|
||||||
{
|
{
|
||||||
FIRST_PROPERTY,
|
FIRST_PROPERTY,
|
||||||
PROP_RESTRICTION_CAPS,
|
PROP_RESTRICTION_CAPS,
|
||||||
|
PROP_ELEMENT_PROPERTIES,
|
||||||
LAST_PROPERTY
|
LAST_PROPERTY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -391,6 +401,11 @@ _encoding_profile_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_RESTRICTION_CAPS:
|
case PROP_RESTRICTION_CAPS:
|
||||||
gst_value_set_caps (value, prof->restriction);
|
gst_value_set_caps (value, prof->restriction);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ELEMENT_PROPERTIES:
|
||||||
|
PROFILE_LOCK (prof);
|
||||||
|
gst_value_set_structure (value, prof->element_properties);
|
||||||
|
PROFILE_UNLOCK (prof);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -408,6 +423,14 @@ _encoding_profile_set_property (GObject * object, guint prop_id,
|
||||||
gst_encoding_profile_set_restriction (prof, gst_caps_copy
|
gst_encoding_profile_set_restriction (prof, gst_caps_copy
|
||||||
(gst_value_get_caps (value)));
|
(gst_value_get_caps (value)));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -441,11 +464,30 @@ gst_encoding_profile_class_init (GstEncodingProfileClass * klass)
|
||||||
_properties[PROP_RESTRICTION_CAPS] =
|
_properties[PROP_RESTRICTION_CAPS] =
|
||||||
g_param_spec_boxed ("restriction-caps", "Restriction caps",
|
g_param_spec_boxed ("restriction-caps", "Restriction caps",
|
||||||
"The restriction caps to use", GST_TYPE_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]);
|
_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 */
|
/* Container profiles */
|
||||||
|
|
||||||
struct _GstEncodingContainerProfile
|
struct _GstEncodingContainerProfile
|
||||||
|
@ -1648,6 +1768,30 @@ done:
|
||||||
return profile;
|
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 *
|
static GstEncodingProfile *
|
||||||
create_encoding_stream_profile (gchar * serialized_profile,
|
create_encoding_stream_profile (gchar * serialized_profile,
|
||||||
GList * muxers_and_encoders, GstCaps * raw_audio_caps,
|
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,
|
gchar *strcaps, *strpresence, **strprops_v, **restriction_format,
|
||||||
**preset_v, *preset_name = NULL, *factory_name = NULL,
|
**preset_v, *preset_name = NULL, *factory_name = NULL,
|
||||||
*variable_framerate = NULL;
|
*variable_framerate = NULL;
|
||||||
|
GstStructure *element_properties = NULL;
|
||||||
GstCaps *restrictioncaps = NULL;
|
GstCaps *restrictioncaps = NULL;
|
||||||
GstEncodingProfile *profile = NULL;
|
GstEncodingProfile *profile = NULL;
|
||||||
|
|
||||||
|
@ -1694,12 +1839,26 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (propi = 1; strprops_v[propi]; propi++) {
|
for (propi = 1; strprops_v[propi]; propi++) {
|
||||||
gchar **propv = g_strsplit (strprops_v[propi], "=", -1);
|
gchar **propv;
|
||||||
gchar *presence_str = NULL;
|
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]) {
|
if (propv[1] && propv[2]) {
|
||||||
g_warning ("Wrong format for property: %s, only 1 `=` is expected",
|
g_warning ("Wrong format for property: %s, only 1 `=` is expected",
|
||||||
strprops_v[propi]);
|
prop);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1723,6 +1882,9 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
||||||
|
|
||||||
single_segment = g_value_get_boolean (&v);
|
single_segment = g_value_get_boolean (&v);
|
||||||
g_value_reset (&v);
|
g_value_reset (&v);
|
||||||
|
} else {
|
||||||
|
g_warning ("Unsupported property: %s", propv[0]);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (presence_str) {
|
if (presence_str) {
|
||||||
|
@ -1806,6 +1968,9 @@ create_encoding_stream_profile (gchar * serialized_profile,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element_properties)
|
||||||
|
gst_encoding_profile_set_element_properties (profile, element_properties);
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,13 @@ GstEncodingProfile * gst_encoding_profile_from_discoverer (GstDiscovererInfo *in
|
||||||
GST_PBUTILS_API
|
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)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEncodingAudioProfile, gst_object_unref)
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEncodingContainerProfile, gst_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstEncodingContainerProfile, gst_object_unref)
|
||||||
|
|
|
@ -870,12 +870,84 @@ beach:
|
||||||
return parser;
|
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 *
|
static GstElement *
|
||||||
_create_element_and_set_preset (GstElementFactory * factory,
|
_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;
|
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"
|
GST_DEBUG ("Creating element from factory %s (preset factory name: %s"
|
||||||
" preset name: %s)", GST_OBJECT_NAME (factory), preset_name, preset);
|
" 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 */
|
/* 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;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -914,11 +992,8 @@ _get_encoder (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
|
||||||
GstElement *encoder = NULL;
|
GstElement *encoder = NULL;
|
||||||
GstElementFactory *encoderfact = NULL;
|
GstElementFactory *encoderfact = NULL;
|
||||||
GstCaps *format;
|
GstCaps *format;
|
||||||
const gchar *preset, *preset_name;
|
|
||||||
|
|
||||||
format = gst_encoding_profile_get_format (sprof);
|
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);
|
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) {
|
for (tmp = encoders; tmp; tmp = tmp->next) {
|
||||||
encoderfact = (GstElementFactory *) tmp->data;
|
encoderfact = (GstElementFactory *) tmp->data;
|
||||||
if ((encoder = _create_element_and_set_preset (encoderfact, preset,
|
if ((encoder = _create_element_and_set_preset (encoderfact, sprof, NULL)))
|
||||||
NULL, preset_name)))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1458,7 +1532,7 @@ _create_stream_group (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof,
|
||||||
tosync = g_list_append (tosync, sgroup->identity);
|
tosync = g_list_append (tosync, sgroup->identity);
|
||||||
} else {
|
} else {
|
||||||
GST_INFO_OBJECT (ebin, "Single segment is not supported when avoiding"
|
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;
|
GstElement *formatter = NULL;
|
||||||
GstElementFactory *formatterfact = NULL;
|
GstElementFactory *formatterfact = NULL;
|
||||||
GstCaps *format;
|
GstCaps *format;
|
||||||
const gchar *preset, *preset_name;
|
|
||||||
|
|
||||||
format = gst_encoding_profile_get_format (sprof);
|
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);
|
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));
|
GST_OBJECT_NAME (formatterfact));
|
||||||
|
|
||||||
if ((formatter =
|
if ((formatter =
|
||||||
_create_element_and_set_preset (formatterfact, preset,
|
_create_element_and_set_preset (formatterfact, sprof, NULL)))
|
||||||
NULL, preset_name)))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,10 +2038,9 @@ _get_muxer (GstEncodeBaseBin * ebin)
|
||||||
GstElementFactory *muxerfact = NULL;
|
GstElementFactory *muxerfact = NULL;
|
||||||
const GList *tmp;
|
const GList *tmp;
|
||||||
GstCaps *format;
|
GstCaps *format;
|
||||||
const gchar *preset, *preset_name;
|
const gchar *preset_name;
|
||||||
|
|
||||||
format = gst_encoding_profile_get_format (ebin->profile);
|
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);
|
preset_name = gst_encoding_profile_get_preset_name (ebin->profile);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ebin, "Getting list of muxers for format %" GST_PTR_FORMAT,
|
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
|
/* Only use a muxer than can use all streams and than can accept the
|
||||||
* preset (which may be present or not) */
|
* preset (which may be present or not) */
|
||||||
if (cansinkstreams && (muxer =
|
if (cansinkstreams && (muxer =
|
||||||
_create_element_and_set_preset (muxerfact, preset, "muxer",
|
_create_element_and_set_preset (muxerfact, ebin->profile, "muxer")))
|
||||||
preset_name)))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2259,8 +2326,11 @@ stream_group_free (GstEncodeBaseBin * ebin, StreamGroup * sgroup)
|
||||||
if (sgroup->inqueue)
|
if (sgroup->inqueue)
|
||||||
gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
|
gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
|
||||||
|
|
||||||
if (sgroup->encoder)
|
if (sgroup->encoder) {
|
||||||
gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
|
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)
|
if (sgroup->fakesink)
|
||||||
gst_element_set_state (sgroup->fakesink, GST_STATE_NULL);
|
gst_element_set_state (sgroup->fakesink, GST_STATE_NULL);
|
||||||
if (sgroup->outfilter) {
|
if (sgroup->outfilter) {
|
||||||
|
@ -2372,6 +2442,8 @@ gst_encode_base_bin_tear_down_profile (GstEncodeBaseBin * ebin)
|
||||||
|
|
||||||
/* Remove muxer if present */
|
/* Remove muxer if present */
|
||||||
if (ebin->muxer) {
|
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_element_set_state (ebin->muxer, GST_STATE_NULL);
|
||||||
gst_bin_remove (GST_BIN (ebin), ebin->muxer);
|
gst_bin_remove (GST_BIN (ebin), ebin->muxer);
|
||||||
ebin->muxer = NULL;
|
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',
|
'videorate/rate_2_0_with_decoder',
|
||||||
'compositor/renogotiate_failing_unsupported_src_format',
|
'compositor/renogotiate_failing_unsupported_src_format',
|
||||||
'giosrc/read-growing-file',
|
'giosrc/read-growing-file',
|
||||||
|
'encodebin/set-encoder-properties',
|
||||||
]
|
]
|
||||||
|
|
||||||
env = environment()
|
env = environment()
|
||||||
|
|
Loading…
Reference in a new issue