1 /* GStreamer encoding profiles library
2 * Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
3 * (C) 2009-2010 Nokia Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:encoding-profile
23 * @title: GstEncodingProfile
24 * @short_description: Encoding profile library
26 * - GstEncodingProfile
27 * - GstEncodingContainerProfile
28 * - GstEncodingVideoProfile
29 * - GstEncodingAudioProfile
31 * Functions to create and handle encoding profiles.
33 * Encoding profiles describe the media types and settings one wishes to use for
34 * an encoding process. The top-level profiles are commonly
35 * #GstEncodingContainerProfile(s) (which contains a user-readable name and
36 * description along with which container format to use). These, in turn,
37 * reference one or more #GstEncodingProfile(s) which indicate which encoding
38 * format should be used on each individual streams.
40 * #GstEncodingProfile(s) can be provided to the 'encodebin' element, which will
41 * take care of selecting and setting up the required elements to produce an
42 * output stream conforming to the specifications of the profile.
44 * The encoding profiles do not necessarily specify which #GstElement to use for
45 * the various encoding and muxing steps, as they allow to specifying the format
48 * Encoding profiles can be created at runtime by the application or loaded from
49 * (and saved to) file using the #GstEncodingTarget API.
51 * ## The encoding profile serialization format
53 * Encoding profiles can be serialized to be used in the command line tools or
54 * to set it on other other #GObject-s using #gst_util_set_object_arg for
57 * The serialization format aims at being simple to understand although flexible
58 * enough to describe any possible encoding profile. There are several ways to
59 * describe the profile depending on the context but the general idea is that it
60 * is a colon separated list of EncodingProfiles descriptions, the first one
61 * needs to describe a #GstEncodingContainerProfile and the following ones
62 * describe elementary streams.
64 * ### Using encoders and muxer element factory name
67 * muxer_factory_name:video_encoder_factory_name:audio_encoder_factory_name
70 * For example to encode a stream into a WebM container, with an OGG audio
71 * stream and a VP8 video stream, the serialized #GstEncodingProfile looks like:
74 * webmmux:vp8enc:vorbisenc
77 * ### Define the encoding profile in a generic way using caps:
80 * muxer_source_caps:video_encoder_source_caps:audio_encoder_source_caps
83 * For example to encode a stream into a WebM container, with an OGG audio
84 * stream and a VP8 video stream, the serialized #GstEncodingProfile looks like:
87 * video/webm:video/x-vp8:audio/x-vorbis
90 * It is possible to mix caps and element type names so you can specify a
91 * specific video encoder while using caps for other encoders/muxer.
95 * You can also set the preset name of the encoding profile using the
96 * caps+preset_name syntax as in:
99 * video/webm:video/x-vp8+youtube-preset:audio/x-vorbis
102 * ### Setting properties on muxers or on the encoding profile itself
104 * Moreover, you can set the extra properties:
106 * * `|element-properties,property1=true` (See
107 * #gst_encoding_profile_set_element_properties)
108 * * `|presence=true` (See See #gst_encoding_profile_get_presence)
109 * * `|single-segment=true` (See #gst_encoding_profile_set_single_segment)
110 * * `|single-segment=true` (See
111 * #gst_encoding_video_profile_set_variableframerate)
116 * video/webm:video/x-vp8|presence=1|element-properties,target-bitrate=500000:audio/x-vorbis
119 * ### Enforcing properties to the stream itself (video size, number of audio channels, etc..)
121 * You can also use the `restriction_caps->encoded_format_caps` syntax to
122 * specify the restriction caps to be set on a #GstEncodingProfile
124 * It corresponds to the restriction #GstCaps to apply before the encoder that
125 * will be used in the profile (See #gst_encoding_profile_get_restriction). The
126 * fields present in restriction caps are properties of the raw stream (that is,
127 * before encoding), such as height and width for video and depth and sampling
128 * rate for audio. This property does not make sense for muxers. See
129 * #gst_encoding_profile_get_restriction for more details.
131 * To force a video stream to be encoded with a Full HD resolution (using WebM
132 * as the container format, VP8 as the video codec and Vorbis as the audio
133 * codec), you should use:
136 * "video/webm:video/x-raw,width=1920,height=1080->video/x-vp8:audio/x-vorbis"
139 * > NOTE: Make sure to enclose into quotes to avoid '>' to be reinterpreted by
142 * In the case you are specifying encoders directly, the following is also
146 * matroskamux:x264enc,width=1920,height=1080:audio/x-vorbis
149 * ## Some serialized encoding formats examples
151 * ### MP3 audio and H264 in MP4**
154 * video/quicktime,variant=iso:video/x-h264:audio/mpeg,mpegversion=1,layer=3
157 * ### Vorbis and theora in OGG
160 * application/ogg:video/x-theora:audio/x-vorbis
163 * ### AC3 and H264 in MPEG-TS
166 * video/mpegts:video/x-h264:audio/x-ac3
169 * ## Loading a profile from encoding targets
171 * Anywhere you have to use a string to define a #GstEncodingProfile, you
172 * can use load it from a #GstEncodingTarget using the following syntaxes:
175 * target_name[/profilename/category]
181 * /path/to/target.gep:profilename
186 * ### Creating a profile
189 * #include <gst/pbutils/encoding-profile.h>
191 * GstEncodingProfile *
192 * create_ogg_theora_profile(void)
194 * GstEncodingContainerProfile *prof;
197 * caps = gst_caps_from_string("application/ogg");
198 * prof = gst_encoding_container_profile_new("Ogg audio/video",
199 * "Standard OGG/THEORA/VORBIS",
201 * gst_caps_unref (caps);
203 * caps = gst_caps_from_string("video/x-theora");
204 * gst_encoding_container_profile_add_profile(prof,
205 * (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0));
206 * gst_caps_unref (caps);
208 * caps = gst_caps_from_string("audio/x-vorbis");
209 * gst_encoding_container_profile_add_profile(prof,
210 * (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0));
211 * gst_caps_unref (caps);
213 * return (GstEncodingProfile*) prof;
218 * ### Example: Using an encoder preset with a profile
221 * #include <gst/pbutils/encoding-profile.h>
223 * GstEncodingProfile *
224 * create_ogg_theora_profile(void)
226 * GstEncodingVideoProfile *v;
227 * GstEncodingAudioProfile *a;
228 * GstEncodingContainerProfile *prof;
232 * caps = gst_caps_from_string ("application/ogg");
233 * prof = gst_encoding_container_profile_new ("Ogg audio/video",
234 * "Standard OGG/THEORA/VORBIS",
236 * gst_caps_unref (caps);
238 * preset = GST_PRESET (gst_element_factory_make ("theoraenc", "theorapreset"));
239 * g_object_set (preset, "bitrate", 1000, NULL);
240 * // The preset will be saved on the filesystem,
241 * // so try to use a descriptive name
242 * gst_preset_save_preset (preset, "theora_bitrate_preset");
243 * gst_object_unref (preset);
245 * caps = gst_caps_from_string ("video/x-theora");
246 * v = gst_encoding_video_profile_new (caps, "theora_bitrate_preset", NULL, 0);
247 * gst_encoding_container_profile_add_profile (prof, (GstEncodingProfile*) v);
248 * gst_caps_unref (caps);
250 * caps = gst_caps_from_string ("audio/x-vorbis");
251 * a = gst_encoding_audio_profile_new (caps, NULL, NULL, 0);
252 * gst_encoding_container_profile_add_profile (prof, (GstEncodingProfile*) a);
253 * gst_caps_unref (caps);
255 * return (GstEncodingProfile*) prof;
260 * ### Listing categories, targets and profiles
263 * #include <gst/pbutils/encoding-profile.h>
265 * GstEncodingProfile *prof;
266 * GList *categories, *tmpc;
267 * GList *targets, *tmpt;
269 * categories = gst_encoding_list_available_categories ();
271 * ... Show available categories to user ...
273 * for (tmpc = categories; tmpc; tmpc = tmpc->next) {
274 * gchar *category = (gchar *) tmpc->data;
276 * ... and we can list all targets within that category ...
278 * targets = gst_encoding_list_all_targets (category);
280 * ... and show a list to our users ...
282 * g_list_foreach (targets, (GFunc) gst_encoding_target_unref, NULL);
283 * g_list_free (targets);
286 * g_list_foreach (categories, (GFunc) g_free, NULL);
287 * g_list_free (categories);
297 #include "encoding-profile.h"
298 #include "encoding-target.h"
302 /* GstEncodingProfile API */
303 #define PROFILE_LOCK(profile) (g_mutex_lock(&((GstEncodingProfile*)profile)->lock))
304 #define PROFILE_UNLOCK(profile) (g_mutex_unlock(&((GstEncodingProfile*)profile)->lock))
306 struct _GstEncodingProfile
317 gboolean allow_dynamic_output;
319 gboolean single_segment;
322 GstCaps *restriction;
323 GstStructure *element_properties;
327 struct _GstEncodingProfileClass
329 GObjectClass parent_class;
331 void (*copy) (GstEncodingProfile * self, GstEncodingProfile * copy);
337 PROP_RESTRICTION_CAPS,
338 PROP_ELEMENT_PROPERTIES,
342 static GParamSpec *_properties[LAST_PROPERTY];
344 static void string_to_profile_transform (const GValue * src_value,
345 GValue * dest_value);
346 static gboolean gst_encoding_profile_deserialize_valfunc (GValue * value,
348 static gchar *gst_encoding_profile_serialize_valfunc (GValue * value);
350 static void gst_encoding_profile_class_init (GstEncodingProfileClass * klass);
351 static gpointer gst_encoding_profile_parent_class = NULL;
354 gst_encoding_profile_class_intern_init (gpointer klass)
356 gst_encoding_profile_parent_class = g_type_class_peek_parent (klass);
357 gst_encoding_profile_class_init ((GstEncodingProfileClass *) klass);
361 gst_encoding_profile_get_type (void)
363 static volatile gsize g_define_type_id__volatile = 0;
365 if (g_once_init_enter (&g_define_type_id__volatile)) {
366 GType g_define_type_id = g_type_register_static_simple (G_TYPE_OBJECT,
367 g_intern_static_string ("GstEncodingProfile"),
368 sizeof (GstEncodingProfileClass),
369 (GClassInitFunc) gst_encoding_profile_class_intern_init,
370 sizeof (GstEncodingProfile),
373 static GstValueTable gstvtable = {
375 (GstValueCompareFunc) NULL,
376 (GstValueSerializeFunc) gst_encoding_profile_serialize_valfunc,
377 (GstValueDeserializeFunc) gst_encoding_profile_deserialize_valfunc
380 gstvtable.type = g_define_type_id;
382 /* Register a STRING=>PROFILE GValueTransformFunc */
383 g_value_register_transform_func (G_TYPE_STRING, g_define_type_id,
384 string_to_profile_transform);
385 /* Register gst-specific GValue functions */
386 gst_value_register (&gstvtable);
388 g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
390 return g_define_type_id__volatile;
395 _encoding_profile_get_property (GObject * object, guint prop_id,
396 GValue * value, GParamSpec * pspec)
398 GstEncodingProfile *prof = (GstEncodingProfile *) object;
401 case PROP_RESTRICTION_CAPS:
402 gst_value_set_caps (value, prof->restriction);
404 case PROP_ELEMENT_PROPERTIES:
406 gst_value_set_structure (value, prof->element_properties);
407 PROFILE_UNLOCK (prof);
410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
416 _encoding_profile_set_property (GObject * object, guint prop_id,
417 const GValue * value, GParamSpec * pspec)
419 GstEncodingProfile *prof = (GstEncodingProfile *) object;
422 case PROP_RESTRICTION_CAPS:
423 gst_encoding_profile_set_restriction (prof, gst_caps_copy
424 (gst_value_get_caps (value)));
426 case PROP_ELEMENT_PROPERTIES:
428 const GstStructure *structure = gst_value_get_structure (value);
430 gst_encoding_profile_set_element_properties (prof,
431 structure ? gst_structure_copy (structure) : NULL);
435 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
441 gst_encoding_profile_finalize (GObject * object)
443 GstEncodingProfile *prof = (GstEncodingProfile *) object;
446 gst_caps_unref (prof->format);
447 g_free (prof->preset);
448 g_free (prof->description);
449 if (prof->restriction)
450 gst_caps_unref (prof->restriction);
451 g_free (prof->preset_name);
455 gst_encoding_profile_class_init (GstEncodingProfileClass * klass)
457 GObjectClass *gobject_class = (GObjectClass *) klass;
459 gobject_class->finalize = gst_encoding_profile_finalize;
461 gobject_class->set_property = _encoding_profile_set_property;
462 gobject_class->get_property = _encoding_profile_get_property;
464 _properties[PROP_RESTRICTION_CAPS] =
465 g_param_spec_boxed ("restriction-caps", "Restriction caps",
466 "The restriction caps to use", GST_TYPE_CAPS,
467 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
470 * GstEncodingProfile:element-properties:
472 * A #GstStructure defining the properties to be set to the element
473 * the profile represents.
475 * For example for `av1enc`:
478 * element-properties,row-mt=true, end-usage=vbr
483 _properties[PROP_ELEMENT_PROPERTIES] =
484 g_param_spec_boxed ("element-properties", "Element properties",
485 "The element properties to use. "
486 "Example: {properties,boolean-prop=true,string-prop=\"hi\"}.",
488 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
490 g_object_class_install_properties (gobject_class, LAST_PROPERTY, _properties);
494 * gst_encoding_profile_get_name:
495 * @profile: a #GstEncodingProfile
497 * Returns: the name of the profile, can be %NULL.
500 gst_encoding_profile_get_name (GstEncodingProfile * profile)
502 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
504 return profile->name;
508 * gst_encoding_profile_get_description:
509 * @profile: a #GstEncodingProfile
511 * Returns: the description of the profile, can be %NULL.
514 gst_encoding_profile_get_description (GstEncodingProfile * profile)
516 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
518 return profile->description;
522 * gst_encoding_profile_get_format:
523 * @profile: a #GstEncodingProfile
525 * Returns: (transfer full): the #GstCaps corresponding to the media format used
526 * in the profile. Unref after usage.
529 gst_encoding_profile_get_format (GstEncodingProfile * profile)
531 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
533 return (profile->format ? gst_caps_ref (profile->format) : NULL);
537 * gst_encoding_profile_get_preset:
538 * @profile: a #GstEncodingProfile
540 * Returns: the name of the #GstPreset to be used in the profile.
541 * This is the name that has been set when saving the preset.
544 gst_encoding_profile_get_preset (GstEncodingProfile * profile)
546 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
548 return profile->preset;
552 * gst_encoding_profile_get_preset_name:
553 * @profile: a #GstEncodingProfile
555 * Returns: the name of the #GstPreset factory to be used in the profile.
558 gst_encoding_profile_get_preset_name (GstEncodingProfile * profile)
560 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
562 return profile->preset_name;
566 * gst_encoding_profile_get_presence:
567 * @profile: a #GstEncodingProfile
569 * Returns: The number of times the profile is used in its parent
570 * container profile. If 0, it is not a mandatory stream.
573 gst_encoding_profile_get_presence (GstEncodingProfile * profile)
575 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), 0);
577 return profile->presence;
581 * gst_encoding_profile_get_enabled:
582 * @profile: a #GstEncodingProfile
584 * Returns: Whether @profile is enabled or not
589 gst_encoding_profile_is_enabled (GstEncodingProfile * profile)
591 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
593 return profile->enabled;
597 * gst_encoding_profile_get_restriction:
598 * @profile: a #GstEncodingProfile
600 * Returns: (transfer full): The restriction #GstCaps to apply before the encoder
601 * that will be used in the profile. The fields present in restriction caps are
602 * properties of the raw stream (that is before encoding), such as height and
603 * width for video and depth and sampling rate for audio. Does not apply to
604 * #GstEncodingContainerProfile (since there is no corresponding raw stream).
605 * Can be %NULL. Unref after usage.
608 gst_encoding_profile_get_restriction (GstEncodingProfile * profile)
610 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
613 return (profile->restriction ? gst_caps_ref (profile->restriction) : NULL);
617 * gst_encoding_profile_set_name:
618 * @profile: a #GstEncodingProfile
619 * @name: (allow-none): the name to set on the profile
621 * Set @name as the given name for the @profile. A copy of @name will be made
625 gst_encoding_profile_set_name (GstEncodingProfile * profile, const gchar * name)
627 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
629 g_free (profile->name);
630 profile->name = g_strdup (name);
634 * gst_encoding_profile_set_description:
635 * @profile: a #GstEncodingProfile
636 * @description: (allow-none): the description to set on the profile
638 * Set @description as the given description for the @profile. A copy of
639 * @description will be made internally.
642 gst_encoding_profile_set_description (GstEncodingProfile * profile,
643 const gchar * description)
645 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
647 g_free (profile->description);
648 profile->description = g_strdup (description);
652 * gst_encoding_profile_set_format:
653 * @profile: a #GstEncodingProfile
654 * @format: (transfer none): the media format to use in the profile.
656 * Sets the media format used in the profile.
659 gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format)
661 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
664 gst_caps_unref (profile->format);
665 profile->format = gst_caps_ref (format);
669 * gst_encoding_profile_get_allow_dynamic_output:
670 * @profile: a #GstEncodingProfile
672 * Get whether the format that has been negotiated in at some point can be renegotiated
673 * later during the encoding.
676 gst_encoding_profile_get_allow_dynamic_output (GstEncodingProfile * profile)
678 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
680 return profile->allow_dynamic_output;
684 * gst_encoding_profile_set_allow_dynamic_output:
685 * @profile: a #GstEncodingProfile
686 * @allow_dynamic_output: Whether the format that has been negotiated first can be renegotiated
687 * during the encoding
689 * Sets whether the format that has been negotiated in at some point can be renegotiated
690 * later during the encoding.
693 gst_encoding_profile_set_allow_dynamic_output (GstEncodingProfile * profile,
694 gboolean allow_dynamic_output)
696 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
698 profile->allow_dynamic_output = allow_dynamic_output;
702 * gst_encoding_profile_get_single_segment:
703 * @profile: a #GstEncodingProfile
705 * Returns: #TRUE if the stream represented by @profile should use a single
706 * segment before the encoder, #FALSE otherwise. This means that buffers will be retimestamped
707 * and segments will be eat so as to appear as one segment.
712 gst_encoding_profile_get_single_segment (GstEncodingProfile * profile)
714 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
716 return profile->single_segment;
720 * gst_encoding_profile_set_single_segment:
721 * @profile: a #GstEncodingProfile
722 * @single_segment: #TRUE if the stream represented by @profile should use a
723 * single segment before the encoder, #FALSE otherwise.
725 * If using a single segment, buffers will be retimestamped and segments will be
726 * eat so as to appear as one segment.
728 * > *NOTE*: Single segment is not property supported when using
729 * > #encodebin:avoid-reencoding
734 gst_encoding_profile_set_single_segment (GstEncodingProfile * profile,
735 gboolean single_segment)
737 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
739 profile->single_segment = single_segment;
743 * gst_encoding_profile_set_preset:
744 * @profile: a #GstEncodingProfile
745 * @preset: (nullable): the element preset to use
747 * Sets the name of the #GstElement that implements the #GstPreset interface
748 * to use for the profile.
749 * This is the name that has been set when saving the preset.
752 gst_encoding_profile_set_preset (GstEncodingProfile * profile,
753 const gchar * preset)
755 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
757 g_free (profile->preset);
758 profile->preset = g_strdup (preset);
762 * gst_encoding_profile_set_preset_name:
763 * @profile: a #GstEncodingProfile
764 * @preset_name: (allow-none): The name of the preset to use in this @profile.
766 * Sets the name of the #GstPreset's factory to be used in the profile.
769 gst_encoding_profile_set_preset_name (GstEncodingProfile * profile,
770 const gchar * preset_name)
772 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
774 g_free (profile->preset_name);
775 profile->preset_name = g_strdup (preset_name);
779 * gst_encoding_profile_set_presence:
780 * @profile: a #GstEncodingProfile
781 * @presence: the number of time the profile can be used
783 * Set the number of time the profile is used in its parent
784 * container profile. If 0, it is not a mandatory stream
787 gst_encoding_profile_set_presence (GstEncodingProfile * profile, guint presence)
789 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
791 profile->presence = presence;
795 * gst_encoding_profile_set_enabled:
796 * @profile: a #GstEncodingProfile
797 * @enabled: %FALSE to disable @profile, %TRUE to enable it
799 * Set whether the profile should be used or not.
804 gst_encoding_profile_set_enabled (GstEncodingProfile * profile,
807 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
809 profile->enabled = enabled;
813 * gst_encoding_profile_set_restriction:
814 * @profile: a #GstEncodingProfile
815 * @restriction: (allow-none) (transfer full): the restriction to apply
817 * Set the restriction #GstCaps to apply before the encoder
818 * that will be used in the profile. See gst_encoding_profile_get_restriction()
819 * for more about restrictions. Does not apply to #GstEncodingContainerProfile.
822 gst_encoding_profile_set_restriction (GstEncodingProfile * profile,
823 GstCaps * restriction)
825 g_return_if_fail (restriction == NULL || GST_IS_CAPS (restriction));
826 g_return_if_fail (GST_IS_ENCODING_PROFILE (profile));
828 if (profile->restriction)
829 gst_caps_unref (profile->restriction);
830 profile->restriction = restriction;
832 g_object_notify_by_pspec (G_OBJECT (profile),
833 _properties[PROP_RESTRICTION_CAPS]);
837 * gst_encoding_profile_set_element_properties:
838 * @self: a #GstEncodingProfile
839 * @element_properties: (transfer full): A #GstStructure defining the properties
840 * to be set to the element the profile represents.
842 * This allows setting the muxing/encoding element properties.
844 * **Set properties generically**
847 * [element-properties, boolean-prop=true, string-prop="hi"]
850 * **Mapping properties with well known element factories**
853 * element-properties-map, map = {
854 * [openh264enc, gop-size=32, ],
855 * [x264enc, key-int-max=32, tune=zerolatency],
862 gst_encoding_profile_set_element_properties (GstEncodingProfile * self,
863 GstStructure * element_properties)
865 g_return_if_fail (GST_IS_ENCODING_PROFILE (self));
866 g_return_if_fail (!element_properties
867 || GST_IS_STRUCTURE (element_properties));
869 #ifndef G_DISABLE_CHECKS
870 if (element_properties &&
871 (gst_structure_has_name (element_properties, "element-properties-map")
872 || gst_structure_has_name (element_properties, "properties-map")
873 || gst_structure_has_name (element_properties, "map")))
874 g_return_if_fail (gst_structure_has_field_typed (element_properties, "map",
879 if (self->element_properties)
880 gst_structure_free (self->element_properties);
881 if (element_properties)
882 self->element_properties = element_properties;
884 self->element_properties = NULL;
885 PROFILE_UNLOCK (self);
887 g_object_notify_by_pspec (G_OBJECT (self),
888 _properties[PROP_ELEMENT_PROPERTIES]);
892 * gst_encoding_profile_get_element_properties:
893 * @self: a #GstEncodingProfile
895 * Returns: (transfer full) (nullable): The properties that are going to be set on the underlying element
900 gst_encoding_profile_get_element_properties (GstEncodingProfile * self)
902 GstStructure *res = NULL;
904 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (self), NULL);
907 if (self->element_properties)
908 res = gst_structure_copy (self->element_properties);
909 PROFILE_UNLOCK (self);
914 /* Container profiles */
916 struct _GstEncodingContainerProfile
918 GstEncodingProfile parent;
920 GList *encodingprofiles;
923 struct _GstEncodingContainerProfileClass
925 GstEncodingProfileClass parent;
928 G_DEFINE_TYPE (GstEncodingContainerProfile, gst_encoding_container_profile,
929 GST_TYPE_ENCODING_PROFILE);
932 gst_encoding_container_profile_init (GstEncodingContainerProfile * prof)
934 /* Nothing to initialize */
938 gst_encoding_container_profile_finalize (GObject * object)
940 GstEncodingContainerProfile *prof = (GstEncodingContainerProfile *) object;
942 g_list_foreach (prof->encodingprofiles, (GFunc) g_object_unref, NULL);
943 g_list_free (prof->encodingprofiles);
945 G_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize
950 gst_encoding_container_profile_copy (GstEncodingProfile * profile,
951 GstEncodingProfile * copy_profile)
953 GstEncodingContainerProfile *self = GST_ENCODING_CONTAINER_PROFILE (profile),
954 *copy = GST_ENCODING_CONTAINER_PROFILE (copy_profile);
957 for (tmp = self->encodingprofiles; tmp; tmp = tmp->next) {
958 gst_encoding_container_profile_add_profile (copy,
959 gst_encoding_profile_copy (tmp->data));
964 gst_encoding_container_profile_class_init (GstEncodingContainerProfileClass * k)
966 GObjectClass *gobject_class = (GObjectClass *) k;
968 gobject_class->finalize = gst_encoding_container_profile_finalize;
970 ((GstEncodingProfileClass *) k)->copy = gst_encoding_container_profile_copy;
974 * gst_encoding_container_profile_get_profiles:
975 * @profile: a #GstEncodingContainerProfile
977 * Returns: (element-type GstPbutils.EncodingProfile) (transfer none):
978 * the list of contained #GstEncodingProfile.
981 gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *
984 g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (profile), NULL);
986 return profile->encodingprofiles;
991 struct _GstEncodingVideoProfile
993 GstEncodingProfile parent;
996 gboolean variableframerate;
999 struct _GstEncodingVideoProfileClass
1001 GstEncodingProfileClass parent;
1004 G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile,
1005 GST_TYPE_ENCODING_PROFILE);
1008 gst_encoding_video_profile_copy (GstEncodingProfile * profile,
1009 GstEncodingProfile * copy_profile)
1011 GstEncodingVideoProfile *self = GST_ENCODING_VIDEO_PROFILE (profile),
1012 *copy = GST_ENCODING_VIDEO_PROFILE (copy_profile);
1014 copy->pass = self->pass;
1015 copy->variableframerate = self->variableframerate;
1019 gst_encoding_video_profile_init (GstEncodingVideoProfile * prof)
1021 /* Nothing to initialize */
1025 gst_encoding_video_profile_class_init (GstEncodingVideoProfileClass * klass)
1027 ((GstEncodingProfileClass *) klass)->copy = gst_encoding_video_profile_copy;
1031 * gst_encoding_video_profile_get_pass:
1032 * @prof: a #GstEncodingVideoProfile
1034 * Get the pass number if this is part of a multi-pass profile.
1036 * Returns: The pass number. Starts at 1 for multi-pass. 0 if this is
1037 * not a multi-pass profile
1040 gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof)
1042 g_return_val_if_fail (GST_IS_ENCODING_VIDEO_PROFILE (prof), 0);
1048 * gst_encoding_video_profile_get_variableframerate:
1049 * @prof: a #GstEncodingVideoProfile
1051 * > *NOTE*: Fixed framerate won't be enforced when #encodebin:avoid-reencoding
1054 * Returns: Whether non-constant video framerate is allowed for encoding.
1057 gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *
1060 g_return_val_if_fail (GST_IS_ENCODING_VIDEO_PROFILE (prof), FALSE);
1062 return prof->variableframerate;
1066 * gst_encoding_video_profile_set_pass:
1067 * @prof: a #GstEncodingVideoProfile
1068 * @pass: the pass number for this profile
1070 * Sets the pass number of this video profile. The first pass profile should have
1071 * this value set to 1. If this video profile isn't part of a multi-pass profile,
1072 * you may set it to 0 (the default value).
1075 gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass)
1077 g_return_if_fail (GST_IS_ENCODING_VIDEO_PROFILE (prof));
1083 * gst_encoding_video_profile_set_variableframerate:
1084 * @prof: a #GstEncodingVideoProfile
1085 * @variableframerate: a boolean
1087 * If set to %TRUE, then the incoming stream will be allowed to have non-constant
1088 * framerate. If set to %FALSE (default value), then the incoming stream will
1089 * be normalized by dropping/duplicating frames in order to produce a
1090 * constance framerate.
1093 gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *
1094 prof, gboolean variableframerate)
1096 g_return_if_fail (GST_IS_ENCODING_VIDEO_PROFILE (prof));
1098 prof->variableframerate = variableframerate;
1101 /* Audio profiles */
1103 struct _GstEncodingAudioProfile
1105 GstEncodingProfile parent;
1108 struct _GstEncodingAudioProfileClass
1110 GstEncodingProfileClass parent;
1113 G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile,
1114 GST_TYPE_ENCODING_PROFILE);
1117 gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof)
1119 /* Nothing to initialize */
1123 gst_encoding_audio_profile_class_init (GstEncodingAudioProfileClass * klass)
1127 static inline gboolean
1128 _gst_caps_is_equal_safe (GstCaps * a, GstCaps * b)
1132 if ((a == NULL) || (b == NULL))
1134 return gst_caps_is_equal (a, b);
1138 _compare_container_encoding_profiles (GstEncodingContainerProfile * ca,
1139 GstEncodingContainerProfile * cb)
1143 if (g_list_length (ca->encodingprofiles) !=
1144 g_list_length (cb->encodingprofiles))
1147 for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) {
1148 GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
1149 if (!gst_encoding_container_profile_contains_profile (ca, prof))
1157 _compare_encoding_profiles (const GstEncodingProfile * a,
1158 const GstEncodingProfile * b)
1160 if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) ||
1161 !_gst_caps_is_equal_safe (a->format, b->format) ||
1162 (g_strcmp0 (a->preset, b->preset) != 0) ||
1163 (g_strcmp0 (a->preset_name, b->preset_name) != 0) ||
1164 (g_strcmp0 (a->name, b->name) != 0) ||
1165 (g_strcmp0 (a->description, b->description) != 0))
1168 if (GST_IS_ENCODING_CONTAINER_PROFILE (a))
1170 _compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE
1171 (a), GST_ENCODING_CONTAINER_PROFILE (b));
1173 if (GST_IS_ENCODING_VIDEO_PROFILE (a)) {
1174 GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a;
1175 GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b;
1177 if ((va->pass != vb->pass)
1178 || (va->variableframerate != vb->variableframerate))
1186 * gst_encoding_container_profile_contains_profile:
1187 * @container: a #GstEncodingContainerProfile
1188 * @profile: a #GstEncodingProfile
1190 * Checks if @container contains a #GstEncodingProfile identical to
1193 * Returns: %TRUE if @container contains a #GstEncodingProfile identical
1194 * to @profile, else %FALSE.
1197 gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile *
1198 container, GstEncodingProfile * profile)
1200 g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
1201 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1203 return (g_list_find_custom (container->encodingprofiles, profile,
1204 (GCompareFunc) _compare_encoding_profiles) != NULL);
1208 * gst_encoding_container_profile_add_profile:
1209 * @container: the #GstEncodingContainerProfile to use
1210 * @profile: (transfer full): the #GstEncodingProfile to add.
1212 * Add a #GstEncodingProfile to the list of profiles handled by @container.
1214 * No copy of @profile will be made, if you wish to use it elsewhere after this
1215 * method you should increment its reference count.
1217 * Returns: %TRUE if the @stream was properly added, else %FALSE.
1220 gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *
1221 container, GstEncodingProfile * profile)
1223 g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
1224 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1226 container->encodingprofiles =
1227 g_list_append (container->encodingprofiles, profile);
1232 static GstEncodingProfile *
1233 common_creation (GType objtype, GstCaps * format, const gchar * preset,
1234 const gchar * name, const gchar * description, GstCaps * restriction,
1237 GstEncodingProfile *prof;
1239 prof = (GstEncodingProfile *) g_object_new (objtype, NULL);
1242 prof->name = g_strdup (name);
1244 prof->description = g_strdup (description);
1246 prof->preset = g_strdup (preset);
1248 prof->format = gst_caps_ref (format);
1250 prof->restriction = gst_caps_ref (restriction);
1251 prof->presence = presence;
1252 prof->preset_name = NULL;
1253 prof->allow_dynamic_output = TRUE;
1254 prof->enabled = TRUE;
1260 * gst_encoding_container_profile_new:
1261 * @name: (allow-none): The name of the container profile, can be %NULL
1262 * @description: (allow-none): The description of the container profile,
1264 * @format: (transfer none): The format to use for this profile
1265 * @preset: (allow-none): The preset to use for this profile.
1267 * Creates a new #GstEncodingContainerProfile.
1269 * Returns: The newly created #GstEncodingContainerProfile.
1271 GstEncodingContainerProfile *
1272 gst_encoding_container_profile_new (const gchar * name,
1273 const gchar * description, GstCaps * format, const gchar * preset)
1275 g_return_val_if_fail (GST_IS_CAPS (format), NULL);
1277 return (GstEncodingContainerProfile *)
1278 common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset,
1279 name, description, NULL, 0);
1283 * gst_encoding_video_profile_new:
1284 * @format: (transfer none): the #GstCaps
1285 * @preset: (allow-none): the preset(s) to use on the encoder, can be %NULL
1286 * @restriction: (allow-none): the #GstCaps used to restrict the input to the encoder, can be
1287 * NULL. See gst_encoding_profile_get_restriction() for more details.
1288 * @presence: the number of time this stream must be used. 0 means any number of
1289 * times (including never)
1291 * Creates a new #GstEncodingVideoProfile
1293 * All provided allocatable arguments will be internally copied, so can be
1294 * safely freed/unreferenced after calling this method.
1296 * If you wish to control the pass number (in case of multi-pass scenarios),
1297 * please refer to the gst_encoding_video_profile_set_pass() documentation.
1299 * If you wish to use/force a constant framerate please refer to the
1300 * gst_encoding_video_profile_set_variableframerate() documentation.
1302 * Returns: the newly created #GstEncodingVideoProfile.
1304 GstEncodingVideoProfile *
1305 gst_encoding_video_profile_new (GstCaps * format, const gchar * preset,
1306 GstCaps * restriction, guint presence)
1308 return (GstEncodingVideoProfile *)
1309 common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL,
1310 NULL, restriction, presence);
1314 * gst_encoding_audio_profile_new:
1315 * @format: (transfer none): the #GstCaps
1316 * @preset: (allow-none): the preset(s) to use on the encoder, can be %NULL
1317 * @restriction: (allow-none): the #GstCaps used to restrict the input to the encoder, can be
1318 * NULL. See gst_encoding_profile_get_restriction() for more details.
1319 * @presence: the number of time this stream must be used. 0 means any number of
1320 * times (including never)
1322 * Creates a new #GstEncodingAudioProfile
1324 * All provided allocatable arguments will be internally copied, so can be
1325 * safely freed/unreferenced after calling this method.
1327 * Returns: the newly created #GstEncodingAudioProfile.
1329 GstEncodingAudioProfile *
1330 gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset,
1331 GstCaps * restriction, guint presence)
1333 return (GstEncodingAudioProfile *)
1334 common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL,
1335 NULL, restriction, presence);
1340 * gst_encoding_profile_is_equal:
1341 * @a: a #GstEncodingProfile
1342 * @b: a #GstEncodingProfile
1344 * Checks whether the two #GstEncodingProfile are equal
1346 * Returns: %TRUE if @a and @b are equal, else %FALSE.
1349 gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b)
1351 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (a), FALSE);
1352 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (b), FALSE);
1354 return (_compare_encoding_profiles (a, b) == 0);
1359 * gst_encoding_profile_get_input_caps:
1360 * @profile: a #GstEncodingProfile
1362 * Computes the full output caps that this @profile will be able to consume.
1364 * Returns: (transfer full): The full caps the given @profile can consume. Call
1365 * gst_caps_unref() when you are done with the caps.
1368 gst_encoding_profile_get_input_caps (GstEncodingProfile * profile)
1372 GstStructure *st, *outst;
1377 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
1379 if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
1380 GstCaps *res = gst_caps_new_empty ();
1382 for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
1383 ltmp; ltmp = ltmp->next) {
1384 GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
1385 res = gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof));
1390 fcaps = profile->format;
1393 if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
1394 return gst_caps_ref (fcaps);
1396 /* Combine the format with the restriction caps */
1397 outst = gst_caps_get_structure (fcaps, 0);
1398 out_name = gst_structure_get_name_id (outst);
1399 tmp = gst_caps_new_empty ();
1400 len = gst_caps_get_size (profile->restriction);
1402 for (i = 0; i < len; i++) {
1403 st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
1404 st->name = out_name;
1405 gst_caps_append_structure (tmp, st);
1408 out = gst_caps_intersect (tmp, fcaps);
1409 gst_caps_unref (tmp);
1415 * gst_encoding_profile_get_type_nick:
1416 * @profile: a #GstEncodingProfile
1418 * Returns: the human-readable name of the type of @profile.
1421 gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
1423 if (GST_IS_ENCODING_CONTAINER_PROFILE (profile))
1425 if (GST_IS_ENCODING_VIDEO_PROFILE (profile))
1427 if (GST_IS_ENCODING_AUDIO_PROFILE (profile))
1432 extern const gchar *pb_utils_get_file_extension_from_caps (const GstCaps *
1434 gboolean pb_utils_is_tag (const GstCaps * caps);
1437 gst_encoding_profile_has_format (GstEncodingProfile * profile,
1438 const gchar * media_type)
1443 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1445 caps = gst_encoding_profile_get_format (profile);
1446 ret = gst_structure_has_name (gst_caps_get_structure (caps, 0), media_type);
1447 gst_caps_unref (caps);
1453 gst_encoding_container_profile_has_video (GstEncodingContainerProfile * profile)
1457 g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (profile), FALSE);
1459 for (l = profile->encodingprofiles; l != NULL; l = l->next) {
1460 if (GST_IS_ENCODING_VIDEO_PROFILE (l->data))
1462 if (GST_IS_ENCODING_CONTAINER_PROFILE (l->data) &&
1463 gst_encoding_container_profile_has_video (l->data))
1471 * gst_encoding_profile_get_file_extension:
1472 * @profile: a #GstEncodingProfile
1474 * Returns: a suitable file extension for @profile, or NULL.
1477 gst_encoding_profile_get_file_extension (GstEncodingProfile * profile)
1479 GstEncodingContainerProfile *cprofile;
1480 const gchar *ext = NULL;
1485 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
1487 caps = gst_encoding_profile_get_format (profile);
1488 ext = pb_utils_get_file_extension_from_caps (caps);
1490 if (!GST_IS_ENCODING_CONTAINER_PROFILE (profile))
1493 cprofile = GST_ENCODING_CONTAINER_PROFILE (profile);
1495 num_children = g_list_length (cprofile->encodingprofiles);
1497 /* if it's a tag container profile (e.g. id3mux/apemux), we need
1498 * to look at what's inside it */
1499 if (pb_utils_is_tag (caps)) {
1500 GST_DEBUG ("tag container profile");
1501 if (num_children == 1) {
1502 GstEncodingProfile *child_profile = cprofile->encodingprofiles->data;
1504 ext = gst_encoding_profile_get_file_extension (child_profile);
1506 GST_WARNING ("expected exactly one child profile with tag profile");
1511 if (num_children == 0)
1515 has_video = gst_encoding_container_profile_has_video (cprofile);
1518 if (g_strcmp0 (ext, "ogg") == 0) {
1519 /* ogg with video => .ogv */
1524 /* ogg with just speex audio => .spx */
1525 if (num_children == 1) {
1526 GstEncodingProfile *child_profile = cprofile->encodingprofiles->data;
1528 if (GST_IS_ENCODING_AUDIO_PROFILE (child_profile) &&
1529 gst_encoding_profile_has_format (child_profile, "audio/x-speex")) {
1534 /* does anyone actually use .oga for ogg audio files? */
1539 if (has_video && g_strcmp0 (ext, "mka") == 0) {
1544 /* Windows Media / ASF */
1545 if (gst_encoding_profile_has_format (profile, "video/x-ms-asf")) {
1547 guint num_wmv = 0, num_wma = 0, num_other = 0;
1549 for (l = cprofile->encodingprofiles; l != NULL; l = l->next) {
1550 if (gst_encoding_profile_has_format (l->data, "video/x-wmv"))
1552 else if (gst_encoding_profile_has_format (l->data, "audio/x-wma"))
1560 else if (num_wmv > 0)
1562 else if (num_wma > 0)
1570 GST_INFO ("caps %" GST_PTR_FORMAT ", ext: %s", caps, GST_STR_NULL (ext));
1571 gst_caps_unref (caps);
1576 * gst_encoding_profile_find:
1577 * @targetname: (transfer none): The name of the target
1578 * @profilename: (transfer none) (allow-none): The name of the profile, if %NULL
1579 * provided, it will default to the encoding profile called `default`.
1580 * @category: (transfer none) (allow-none): The target category. Can be %NULL
1582 * Find the #GstEncodingProfile with the specified name and category.
1584 * Returns: (transfer full): The matching #GstEncodingProfile or %NULL.
1586 GstEncodingProfile *
1587 gst_encoding_profile_find (const gchar * targetname, const gchar * profilename,
1588 const gchar * category)
1590 GstEncodingProfile *res = NULL;
1591 GstEncodingTarget *target;
1593 g_return_val_if_fail (targetname != NULL, NULL);
1595 target = gst_encoding_target_load (targetname, category, NULL);
1598 gst_encoding_target_get_profile (target,
1599 profilename ? profilename : "default");
1600 gst_encoding_target_unref (target);
1606 static GstEncodingProfile *
1607 combo_search (const gchar * pname)
1609 GstEncodingProfile *res = NULL;
1614 split = g_strsplit (pname, "/", 3);
1615 split_length = g_strv_length (split);
1616 if (split_length > 3)
1619 res = gst_encoding_profile_find (split[0],
1620 split_length == 2 ? split[1] : NULL, split_length == 3 ? split[2] : NULL);
1630 get_profile_format_from_possible_factory_name (const gchar * factory_desc,
1631 gchar ** new_factory_name, GstCaps ** restrictions,
1632 gboolean * is_rendering_muxer)
1635 GstCaps *caps = NULL, *tmpcaps = gst_caps_from_string (factory_desc);
1636 GstStructure *tmpstruct;
1637 GstElementFactory *fact = NULL;
1639 if (is_rendering_muxer)
1640 *is_rendering_muxer = FALSE;
1641 *new_factory_name = NULL;
1642 if (gst_caps_get_size (tmpcaps) != 1)
1645 tmpstruct = gst_caps_get_structure (tmpcaps, 0);
1646 fact = gst_element_factory_find (gst_structure_get_name (tmpstruct));
1650 if (!gst_element_factory_list_is_type (fact,
1651 GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MUXER)) {
1652 GST_ERROR_OBJECT (fact,
1653 "is not an encoder or muxer, it can't be"
1654 " used in an encoding profile.");
1658 for (tmp = (GList *) gst_element_factory_get_static_pad_templates (fact);
1659 tmp; tmp = tmp->next) {
1660 GstStaticPadTemplate *templ = ((GstStaticPadTemplate *) tmp->data);
1662 if (templ->direction == GST_PAD_SRC) {
1663 GstCaps *tmpcaps = gst_static_caps_get (&templ->static_caps);
1665 if (gst_caps_get_size (tmpcaps) > 0)
1667 gst_caps_new_empty_simple (gst_structure_get_name
1668 (gst_caps_get_structure (tmpcaps, 0)));
1670 gst_caps_unref (tmpcaps);
1677 *new_factory_name = g_strdup (gst_structure_get_name (tmpstruct));
1679 if (gst_structure_n_fields (tmpstruct) && restrictions) {
1680 const gchar *sname =
1681 gst_structure_get_name (gst_caps_get_structure (caps, 0));
1683 if (g_str_has_prefix (sname, "audio/"))
1684 gst_structure_set_name (tmpstruct, "audio/x-raw");
1685 else if (g_str_has_prefix (sname, "video/") ||
1686 g_str_has_prefix (sname, "image/"))
1687 gst_structure_set_name (tmpstruct, "video/x-raw");
1689 *restrictions = tmpcaps;
1692 } else if (gst_element_factory_list_is_type (fact,
1693 GST_ELEMENT_FACTORY_TYPE_MUXER)) {
1694 *new_factory_name = g_strdup (gst_structure_get_name (tmpstruct));
1696 caps = gst_caps_ref (gst_caps_new_empty ());
1697 if (is_rendering_muxer)
1698 *is_rendering_muxer = TRUE;
1704 gst_object_unref (fact);
1707 gst_caps_unref (tmpcaps);
1712 static GstEncodingProfile *
1713 create_encoding_profile_from_caps (GstCaps * caps, gchar * preset_name,
1714 GstCaps * restrictioncaps, gint presence, gboolean single_segment,
1715 gchar * factory_name, GList * muxers_and_encoders, GstCaps * raw_audio_caps,
1716 GstCaps * raw_video_caps, gboolean is_rendering_muxer)
1718 GstEncodingProfile *profile = NULL;
1719 GList *factories = NULL;
1720 gboolean is_raw_audio = FALSE, is_raw_video = FALSE;
1722 if (is_rendering_muxer) {
1724 GST_ENCODING_PROFILE (gst_encoding_container_profile_new
1725 ("User profile", "User profile", caps, NULL));
1729 if (gst_caps_can_intersect (raw_audio_caps, caps)) {
1730 is_raw_audio = TRUE;
1731 } else if (gst_caps_can_intersect (raw_video_caps, caps)) {
1732 is_raw_video = TRUE;
1734 factories = gst_element_factory_list_filter (muxers_and_encoders, caps,
1735 GST_PAD_SRC, FALSE);
1738 GST_INFO ("Could not find factory for %" GST_PTR_FORMAT, caps);
1743 if (is_raw_audio || (factories
1744 && gst_element_factory_list_is_type (factories->data,
1745 GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER)))
1747 GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps, preset_name,
1748 restrictioncaps, presence));
1749 else if (is_raw_video || (factories
1750 && gst_element_factory_list_is_type (factories->data,
1751 GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER)))
1753 GST_ENCODING_PROFILE (gst_encoding_video_profile_new (caps, preset_name,
1754 restrictioncaps, presence));
1755 else if (gst_element_factory_list_is_type (factories->data,
1756 GST_ELEMENT_FACTORY_TYPE_MUXER))
1758 GST_ENCODING_PROFILE (gst_encoding_container_profile_new
1759 ("User profile", "User profile", caps, NULL));
1762 if (factory_name && profile)
1763 gst_encoding_profile_set_preset_name (profile, factory_name);
1764 gst_encoding_profile_set_single_segment (profile, single_segment);
1766 g_free (factory_name);
1772 gst_structure_validate_name (const gchar * name)
1776 g_return_val_if_fail (name != NULL, FALSE);
1778 if (G_UNLIKELY (!g_ascii_isalpha (*name)))
1781 /* FIXME: test name string more */
1783 while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL))
1789 if (G_UNLIKELY (*s != '\0'))
1795 static GstEncodingProfile *
1796 create_encoding_stream_profile (gchar * serialized_profile,
1797 GList * muxers_and_encoders, GstCaps * raw_audio_caps,
1798 GstCaps * raw_video_caps)
1802 gboolean single_segment = FALSE;
1803 gchar *strcaps, *strpresence, **strprops_v, **restriction_format,
1804 **preset_v, *preset_name = NULL, *factory_name = NULL,
1805 *variable_framerate = NULL;
1806 GstStructure *element_properties = NULL;
1807 GstCaps *restrictioncaps = NULL;
1808 GstEncodingProfile *profile = NULL;
1810 restriction_format = g_strsplit (serialized_profile, "->", 0);
1811 if (restriction_format[1]) {
1812 restrictioncaps = gst_caps_from_string (restriction_format[0]);
1813 strcaps = g_strdup (restriction_format[1]);
1815 restrictioncaps = NULL;
1816 strcaps = g_strdup (restriction_format[0]);
1818 g_strfreev (restriction_format);
1820 preset_v = g_strsplit (strcaps, "+", 0);
1822 strpresence = preset_v[1];
1824 strcaps = g_strdup (preset_v[0]);
1826 strpresence = preset_v[0];
1829 strprops_v = g_strsplit (strpresence, "|", 0);
1830 if (strprops_v[1]) { /* We have a properties */
1834 if (preset_v[1]) { /* We have preset and properties */
1835 preset_name = g_strdup (strprops_v[0]);
1836 } else { /* We have a properties but no preset */
1838 strcaps = g_strdup (strprops_v[0]);
1841 for (propi = 1; strprops_v[propi]; propi++) {
1843 gchar *presence_str = NULL;
1844 gchar *prop = strprops_v[propi];
1845 GstStructure *tmpstruct = NULL;
1847 if (gst_structure_validate_name (prop))
1848 tmpstruct = gst_structure_new_from_string (prop);
1850 if (element_properties)
1851 gst_structure_free (element_properties);
1853 element_properties = tmpstruct;
1858 propv = g_strsplit (prop, "=", -1);
1859 if (propv[1] && propv[2]) {
1860 g_warning ("Wrong format for property: %s, only 1 `=` is expected",
1867 presence_str = propv[0];
1868 } else if (!g_strcmp0 (propv[0], "presence")) {
1869 presence_str = propv[1];
1870 } else if (!g_strcmp0 (propv[0], "variable-framerate")) {
1871 variable_framerate = g_strdup (propv[1]);
1872 } else if (!g_strcmp0 (propv[0], "single-segment")) {
1873 GValue v = G_VALUE_INIT;
1875 g_value_init (&v, G_TYPE_BOOLEAN);
1876 if (!gst_value_deserialize (&v, propv[1])) {
1877 g_warning ("Invalid value for property 'single-segment': %s",
1883 single_segment = g_value_get_boolean (&v);
1886 g_warning ("Unsupported property: %s", propv[0]);
1891 presence = g_ascii_strtoll (presence_str, &endptr, 10);
1893 if (endptr == strprops_v[1]) {
1894 g_warning ("Wrong presence %s", presence_str);
1899 } else { /* We have no presence */
1900 if (preset_v[1]) { /* Not presence but preset */
1901 preset_name = g_strdup (preset_v[1]);
1903 strcaps = g_strdup (preset_v[0]);
1904 } /* Else we have no presence nor preset */
1906 g_strfreev (strprops_v);
1907 g_strfreev (preset_v);
1909 GST_DEBUG ("Creating preset with restrictions: %" GST_PTR_FORMAT
1910 ", caps: %s, preset %s, presence %d", restrictioncaps, strcaps,
1911 preset_name ? preset_name : "none", presence);
1913 caps = gst_caps_from_string (strcaps);
1915 profile = create_encoding_profile_from_caps (caps, preset_name,
1916 restrictioncaps, presence, single_segment, NULL, muxers_and_encoders,
1917 raw_audio_caps, raw_video_caps, FALSE);
1918 gst_caps_unref (caps);
1922 gboolean is_rendering_muxer;
1924 caps = get_profile_format_from_possible_factory_name (strcaps,
1925 &factory_name, restrictioncaps ? NULL : &restrictioncaps,
1926 &is_rendering_muxer);
1928 profile = create_encoding_profile_from_caps (caps, preset_name,
1929 restrictioncaps, presence, single_segment, factory_name,
1930 muxers_and_encoders, raw_audio_caps, raw_video_caps,
1931 is_rendering_muxer);
1932 gst_caps_unref (caps);
1935 g_free (preset_name);
1938 if (restrictioncaps)
1939 gst_caps_unref (restrictioncaps);
1941 if (variable_framerate) {
1942 if (GST_IS_ENCODING_VIDEO_PROFILE (profile)) {
1946 g_value_init (&v, G_TYPE_BOOLEAN);
1947 if (gst_value_deserialize (&v, variable_framerate)) {
1948 gst_encoding_video_profile_set_variableframerate
1949 (GST_ENCODING_VIDEO_PROFILE (profile), g_value_get_boolean (&v));
1951 GST_WARNING ("Invalid value for variable_framerate: %s",
1952 variable_framerate);
1958 ("Variable framerate specified on a non video encoding profile");
1961 g_free (variable_framerate);
1964 if (profile == NULL) {
1965 GST_ERROR ("No way to create a profile for description: %s",
1966 serialized_profile);
1971 if (element_properties)
1972 gst_encoding_profile_set_element_properties (profile, element_properties);
1977 static GstEncodingProfile *
1978 parse_encoding_profile (const gchar * value)
1980 GstEncodingProfile *res = NULL;
1981 gchar *caps_str = NULL;
1983 g_regex_split_simple ("(?<!\\\\)(?:\\\\\\\\)*:", value, 0, 0);
1985 GList *muxers_and_encoders =
1986 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER |
1987 GST_ELEMENT_FACTORY_TYPE_MUXER,
1989 GstCaps *raw_video_caps = gst_caps_new_empty_simple ("video/x-raw");
1990 GstCaps *raw_audio_caps = gst_caps_new_empty_simple ("audio/x-raw");
1992 /* The regex returns NULL if no ":" found, handle that case. */
1993 if (strcaps_v == NULL)
1994 strcaps_v = g_strsplit (value, ":", 0);
1996 for (i = 0; strcaps_v[i] && *strcaps_v[i]; i++) {
1997 GstEncodingProfile *profile;
1998 caps_str = g_strcompress (strcaps_v[i]);
2000 create_encoding_stream_profile (caps_str, muxers_and_encoders,
2001 raw_audio_caps, raw_video_caps);
2004 GST_ERROR ("Could not create profile for caps: %s", caps_str);
2009 if (!GST_IS_ENCODING_CONTAINER_PROFILE (res)) {
2010 GST_ERROR ("The first described encoding profile was not a container"
2011 " but you are trying to add more profiles to it. This is not possible");
2015 if (!gst_encoding_container_profile_add_profile
2016 (GST_ENCODING_CONTAINER_PROFILE (res), profile)) {
2017 GST_ERROR ("Can not add profile for caps: %s", caps_str);
2024 g_clear_pointer (&caps_str, g_free);
2029 g_strfreev (strcaps_v);
2030 gst_caps_unref (raw_audio_caps);
2031 gst_caps_unref (raw_video_caps);
2032 gst_plugin_feature_list_free (muxers_and_encoders);
2037 g_clear_object (&res);
2042 static GstEncodingProfile *
2043 profile_from_string (const gchar * string)
2045 GstEncodingProfile *profile;
2046 gchar *filename_end;
2048 profile = combo_search (string);
2053 filename_end = g_strrstr (string, ".gep");
2055 GstEncodingTarget *target;
2056 gchar *profilename = NULL, *filename;
2058 if (filename_end[4] == ':')
2059 profilename = g_strdup (&filename_end[5]);
2061 if (filename_end[4] == '\0' || profilename) {
2062 filename = g_strndup (string, filename_end - string + strlen (".gep"));
2064 target = gst_encoding_target_load_from_file (filename, NULL);
2066 profile = gst_encoding_target_get_profile (target,
2067 profilename ? profilename : "default");
2068 gst_encoding_target_unref (target);
2071 g_free (profilename);
2077 profile = parse_encoding_profile (string);
2082 /* GValue transform function */
2084 string_to_profile_transform (const GValue * src_value, GValue * dest_value)
2086 const gchar *profilename;
2087 GstEncodingProfile *profile;
2089 profilename = g_value_get_string (src_value);
2091 profile = profile_from_string (profilename);
2094 g_value_take_object (dest_value, (GObject *) profile);
2098 serialize_profile (GString * res, GstEncodingProfile * profile)
2103 g_string_append_c (res, ':');
2105 if (profile->restriction) {
2106 tmp = gst_caps_to_string (profile->restriction);
2107 g_string_append_printf (res, "%s->", tmp);
2111 tmp = gst_caps_to_string (profile->format);
2112 g_string_append (res, tmp);
2114 if (profile->presence)
2115 g_string_append_printf (res, "|presence=%d", profile->presence);
2117 if (profile->single_segment)
2118 g_string_append_printf (res, "%ssingle-segment=true",
2119 profile->presence ? "" : "|");
2121 if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
2124 for (tmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles; tmp;
2126 serialize_profile (res, tmp->data);
2131 gst_encoding_profile_serialize_valfunc (GValue * value)
2133 GString *res = g_string_new (NULL);
2134 GstEncodingProfile *profile = g_value_get_object (value);
2136 serialize_profile (res, profile);
2138 return g_string_free (res, FALSE);
2142 gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s)
2144 GstEncodingProfile *profile;
2146 profile = profile_from_string (s);
2149 g_value_take_object (value, (GObject *) profile);
2156 static GstEncodingProfile *
2157 create_stream_profile_recurse (GstEncodingProfile * toplevel,
2158 GstDiscovererStreamInfo * sinfo)
2160 GstEncodingProfile *profile = NULL;
2164 caps = gst_discoverer_stream_info_get_caps (sinfo);
2166 /* Should unify this with copy_and_clean_caps() */
2167 s = gst_caps_get_structure (caps, 0);
2168 if (gst_structure_has_field (s, "codec_data")
2169 || gst_structure_has_field (s, "streamheader")
2170 || gst_structure_has_field (s, "parsed")
2171 || gst_structure_has_field (s, "framed")
2172 || gst_structure_has_field (s, "stream-format")
2173 || gst_structure_has_field (s, "alignment")) {
2174 caps = gst_caps_make_writable (caps);
2175 s = gst_caps_get_structure (caps, 0);
2176 gst_structure_remove_field (s, "codec_data");
2177 gst_structure_remove_field (s, "streamheader");
2178 gst_structure_remove_field (s, "parsed");
2179 gst_structure_remove_field (s, "framed");
2180 gst_structure_remove_field (s, "stream-format");
2181 gst_structure_remove_field (s, "alignment");
2184 GST_LOG ("Stream: %" GST_PTR_FORMAT, caps);
2185 if (GST_IS_DISCOVERER_AUDIO_INFO (sinfo)) {
2187 (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL,
2189 } else if (GST_IS_DISCOVERER_VIDEO_INFO (sinfo)) {
2191 (GstEncodingProfile *) gst_encoding_video_profile_new (caps, NULL,
2193 } else if (GST_IS_DISCOVERER_CONTAINER_INFO (sinfo)) {
2194 GList *streams, *stream;
2197 gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO
2200 if (!toplevel || !GST_IS_ENCODING_CONTAINER_PROFILE (toplevel)) {
2201 GstEncodingProfile *prev_toplevel = toplevel;
2203 toplevel = (GstEncodingProfile *)
2204 gst_encoding_container_profile_new ("auto-generated",
2205 "Automatically generated from GstDiscovererInfo", caps, NULL);
2207 gst_encoding_container_profile_add_profile
2208 (GST_ENCODING_CONTAINER_PROFILE (toplevel), prev_toplevel);
2211 for (stream = streams; stream; stream = stream->next)
2212 create_stream_profile_recurse (toplevel,
2213 (GstDiscovererStreamInfo *) stream->data);
2214 gst_discoverer_stream_info_list_free (streams);
2216 GST_FIXME ("Ignoring stream of type '%s'",
2217 g_type_name (G_OBJECT_TYPE (sinfo)));
2218 /* subtitles or other ? ignore for now */
2220 gst_caps_unref (caps);
2223 const gchar *stream_id = gst_discoverer_stream_info_get_stream_id (sinfo);
2226 const gchar *subid = strchr (stream_id, '/');
2228 gst_encoding_profile_set_name (profile, subid ? subid : stream_id);
2231 if (GST_IS_ENCODING_CONTAINER_PROFILE (toplevel))
2232 gst_encoding_container_profile_add_profile ((GstEncodingContainerProfile
2237 if (!toplevel && profile)
2240 sinfo = gst_discoverer_stream_info_get_next (sinfo);
2242 return create_stream_profile_recurse (toplevel, sinfo);
2248 _compare_profile_names (const GstEncodingProfile * a,
2249 const GstEncodingProfile * b)
2251 return g_strcmp0 (a->name, b->name);
2255 * gst_encoding_profile_from_discoverer:
2256 * @info: (transfer none): The #GstDiscovererInfo to read from
2258 * Creates a #GstEncodingProfile matching the formats from the given
2259 * #GstDiscovererInfo. Streams other than audio or video (eg,
2260 * subtitles), are currently ignored.
2262 * Returns: (transfer full): The new #GstEncodingProfile or %NULL.
2264 GstEncodingProfile *
2265 gst_encoding_profile_from_discoverer (GstDiscovererInfo * info)
2267 GstEncodingProfile *profile;
2268 GstDiscovererStreamInfo *sinfo;
2270 if (!info || gst_discoverer_info_get_result (info) != GST_DISCOVERER_OK)
2273 sinfo = gst_discoverer_info_get_stream_info (info);
2277 profile = create_stream_profile_recurse (NULL, sinfo);
2278 if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
2279 if (!gst_encoding_container_profile_get_profiles
2280 (GST_ENCODING_CONTAINER_PROFILE (profile))) {
2281 GST_ERROR ("Failed to add any streams");
2282 g_object_unref (profile);
2285 /* Sort by stream ID */
2286 GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles =
2287 g_list_sort (GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles,
2288 (GCompareFunc) _compare_profile_names);
2292 return (GstEncodingProfile *) profile;
2296 * gst_encoding_profile_copy:
2297 * @self: The #GstEncodingProfile to copy
2299 * Makes a deep copy of @self
2301 * Returns: (transfer full): The copy of @self
2305 GstEncodingProfile *
2306 gst_encoding_profile_copy (GstEncodingProfile * self)
2308 GstEncodingProfileClass *klass =
2309 (GstEncodingProfileClass *) G_OBJECT_GET_CLASS (self);
2310 GstEncodingProfile *copy =
2311 common_creation (G_OBJECT_TYPE (self), self->format, self->preset,
2312 self->name, self->description, self->restriction, self->presence);
2314 copy->enabled = self->enabled;
2315 copy->allow_dynamic_output = self->allow_dynamic_output;
2316 gst_encoding_profile_set_preset_name (copy, self->preset_name);
2317 gst_encoding_profile_set_description (copy, self->description);
2320 klass->copy (self, copy);