diff --git a/gst-libs/gst/pbutils/encoding-profile.c b/gst-libs/gst/pbutils/encoding-profile.c
index 9d28ce91ac..347ced4ac4 100644
--- a/gst-libs/gst/pbutils/encoding-profile.c
+++ b/gst-libs/gst/pbutils/encoding-profile.c
@@ -49,6 +49,90 @@
* to) file using the #GstEncodingTarget API.
*
*
+ *
+ *
+ * The encoding profile serialization format
+ * This is the serialization format of a GstEncodingProfile.
+ *
+ * Internally the transcoding application uses GstEncodeBin. gst-validate-transcoding-&GST_API_VERSION; uses its own
+ * serialization format to describe the GstEncodeBin.profile
+ * property of the encodebin.
+ *
+ *
+ *
+ * The simplest serialized profile looks like:
+ *
+ *
+ * muxer_source_caps:videoencoder_source_caps:audioencoder_source_caps
+ *
+ *
+ *
+ * For example to encode a stream into a WebM container, with an OGG audio stream and a VP8 video stream,
+ * the serialized GstEncodingProfile will look like:
+ *
+ *
+ * video/webm:video/x-vp8:audio/x-vorbis
+ *
+ *
+ *
+ * You can also set the preset name of the encoding profile using the caps+preset_name syntax as in:
+ *
+ *
+ * video/webm:video/x-vp8+youtube-preset:audio/x-vorbis
+ *
+ *
+ *
+ * Moreover, you can set the presence property of an
+ * encoding profile using the |presence
syntax as in:
+ *
+ *
+ * video/webm:video/x-vp8|1:audio/x-vorbis
+ *
+ *
+ *
+ * This field allows you to specify how many times maximum a GstEncodingProfile can be used inside an encodebin.
+ *
+ *
+ * You can also use the restriction_caps->encoded_format_caps
syntax to specify the
+ * restriction caps
+ * to be set on a GstEncodingProfile. It corresponds to the
+ * restriction GstCaps to apply before
+ * the encoder that will be used in the profile. The fields present in restriction
+ * caps are properties of the raw stream (that is, before encoding), such as height
+ * and width for video and depth and sampling rate for audio. This property does not
+ * make sense for muxers.
+ *
+ *
+ * To force a video stream to be encoded with a Full HD resolution (using WebM as the container format,
+ * VP8 as the video codec and Vorbis as the audio codec), you should use:
+ *
+ *
+ * video/webm:video/x-raw,width=1920,height=1080->video/x-vp8:audio/x-vorbis
+ *
+ *
+ * Some serialized encoding formats examples:
+ *
+ * MP3 audio and H264 in MP4:
+ *
+ *
+ * video/quicktime,variant=iso:video/x-h264:audio/mpeg,mpegversion=1,layer=3
+ *
+ *
+ *
+ * Vorbis and theora in OGG:
+ *
+ *
+ * application/ogg:video/x-theora:audio/x-vorbis
+ *
+ *
+ *
+ * AC3 and H264 in MPEG-TS:
+ *
+ *
+ * video/mpegts:video/x-h264:audio/x-ac3
+ *
+ *
+ *
*
* Example: Creating a profile
*
@@ -1255,6 +1339,131 @@ combo_search (const gchar * pname)
return res;
}
+static GstEncodingProfile *
+parse_encoding_profile (const gchar * value)
+{
+ GstCaps *caps;
+ GstEncodingProfile *res;
+ char *preset_name = NULL;
+ gchar **restriction_format, **preset_v;
+
+ guint i, presence = 0;
+ GstCaps *restrictioncaps = NULL;
+ gchar **strpresence_v, **strcaps_v = g_strsplit (value, ":", 0);
+
+ if (strcaps_v[0] && *strcaps_v[0]) {
+ caps = gst_caps_from_string (strcaps_v[0]);
+ if (caps == NULL) {
+ GST_ERROR ("Could not parse caps %s", strcaps_v[0]);
+ return NULL;
+ }
+ res =
+ GST_ENCODING_PROFILE (gst_encoding_container_profile_new
+ ("User profile", "User profile", caps, NULL));
+ gst_caps_unref (caps);
+ } else {
+ res = NULL;
+ }
+
+ for (i = 1; strcaps_v[i] && *strcaps_v[i]; i++) {
+ GstEncodingProfile *profile = NULL;
+ gchar *strcaps, *strpresence;
+
+ restriction_format = g_strsplit (strcaps_v[i], "->", 0);
+ if (restriction_format[1]) {
+ restrictioncaps = gst_caps_from_string (restriction_format[0]);
+ strcaps = g_strdup (restriction_format[1]);
+ } else {
+ restrictioncaps = NULL;
+ strcaps = g_strdup (restriction_format[0]);
+ }
+ g_strfreev (restriction_format);
+
+ preset_v = g_strsplit (strcaps, "+", 0);
+ if (preset_v[1]) {
+ strpresence = preset_v[1];
+ g_free (strcaps);
+ strcaps = g_strdup (preset_v[0]);
+ } else {
+ strpresence = preset_v[0];
+ }
+
+ strpresence_v = g_strsplit (strpresence, "|", 0);
+ if (strpresence_v[1]) { /* We have a presence */
+ gchar *endptr;
+
+ if (preset_v[1]) { /* We have preset and presence */
+ preset_name = g_strdup (strpresence_v[0]);
+ } else { /* We have a presence but no preset */
+ g_free (strcaps);
+ strcaps = g_strdup (strpresence_v[0]);
+ }
+
+ presence = g_ascii_strtoll (strpresence_v[1], &endptr, 10);
+ if (endptr == strpresence_v[1]) {
+ g_printerr ("Wrong presence %s\n", strpresence_v[1]);
+
+ return NULL;
+ }
+ } else { /* We have no presence */
+ if (preset_v[1]) { /* Not presence but preset */
+ preset_name = g_strdup (preset_v[1]);
+ g_free (strcaps);
+ strcaps = g_strdup (preset_v[0]);
+ } /* Else we have no presence nor preset */
+ }
+ g_strfreev (strpresence_v);
+ g_strfreev (preset_v);
+
+ GST_DEBUG ("Creating preset with restrictions: %" GST_PTR_FORMAT
+ ", caps: %s, preset %s, presence %d", restrictioncaps, strcaps,
+ preset_name ? preset_name : "none", presence);
+
+ caps = gst_caps_from_string (strcaps);
+ g_free (strcaps);
+ if (caps == NULL) {
+ g_warning ("Could not create caps for %s", strcaps_v[i]);
+
+ return NULL;
+ }
+
+ if (g_str_has_prefix (strcaps_v[i], "audio/")) {
+ profile = GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps,
+ preset_name, restrictioncaps, presence));
+ } else if (g_str_has_prefix (strcaps_v[i], "video/") ||
+ g_str_has_prefix (strcaps_v[i], "image/")) {
+ profile = GST_ENCODING_PROFILE (gst_encoding_video_profile_new (caps,
+ preset_name, restrictioncaps, presence));
+ }
+
+ g_free (preset_name);
+ gst_caps_unref (caps);
+ if (restrictioncaps)
+ gst_caps_unref (restrictioncaps);
+
+ if (profile == NULL) {
+ g_warning ("No way to create a preset for caps: %s", strcaps_v[i]);
+
+ return NULL;
+ }
+
+ if (res) {
+ if (gst_encoding_container_profile_add_profile
+ (GST_ENCODING_CONTAINER_PROFILE (res),
+ profile) == FALSE) {
+ g_warning ("Can not create a preset for caps: %s", strcaps_v[i]);
+
+ return NULL;
+ }
+ } else {
+ res = profile;
+ }
+ }
+ g_strfreev (strcaps_v);
+
+ return res;
+}
+
/* GValue transform function */
static void
string_to_profile_transform (const GValue * src_value, GValue * dest_value)
@@ -1277,6 +1486,9 @@ gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s)
profile = combo_search (s);
+ if (!profile)
+ profile = parse_encoding_profile (s);
+
if (profile) {
g_value_take_object (value, (GObject *) profile);
return TRUE;