Example #1
0
static void
sj_extractor_set_property (GObject *object, guint property_id,
                                       const GValue *value, GParamSpec *pspec)
{
  GstEncodingProfile *profile;
  SjExtractorPrivate *priv = SJ_EXTRACTOR (object)->priv;
  switch (property_id) {
  case PROP_PROFILE:
    if (priv->profile)
      gst_encoding_profile_unref (priv->profile);
    profile = GST_ENCODING_PROFILE (g_value_get_pointer (value));
    priv->profile = GST_ENCODING_PROFILE(gst_encoding_profile_ref (profile));
    priv->rebuild_pipeline = TRUE;
    g_object_notify (object, "profile");
    break;
  case PROP_PARANOIA:
    priv->paranoia_mode = g_value_get_int (value);
    if (priv->cdsrc)
      g_object_set (G_OBJECT (priv->cdsrc),
                    "paranoia-mode", priv->paranoia_mode,
                    NULL);
    break;
  case PROP_DEVICE:
    /* We need to cache this as the source will be recreated */
    g_free (priv->device_path);
    priv->device_path = g_value_dup_string (value);
    if (priv->cdsrc != NULL)
      g_object_set (G_OBJECT (priv->cdsrc),
                    "device", priv->device_path,
                    NULL);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  }
}
Example #2
0
static gboolean
match_profile (GstEncodingProfile *profile,
               GstCaps            *caps,
               GType              type)
{
        const GList *i, *profiles_list;
        const gchar *name;

        /* Profiles with an empty name are used only for inheritance and should
         * not be matched against. */
        name = gst_encoding_profile_get_name (profile);
        if (name[0] == '\0')
                return FALSE;

        profiles_list = gst_encoding_container_profile_get_profiles
                                     (GST_ENCODING_CONTAINER_PROFILE (profile));

        for (i = profiles_list; i; i = i->next){
                GstEncodingProfile *enc_profile = GST_ENCODING_PROFILE
                                        (i->data);
                const GstCaps *format = gst_encoding_profile_get_format
                                        (enc_profile);

                if (type == G_TYPE_FROM_INSTANCE (enc_profile) &&
                    caps_can_intersect_and_is_subset (caps, format))
                        return TRUE;
        }

        return FALSE;
}
/**
 * ges_project_add_encoding_profile:
 * @project: A #GESProject
 * @profile: A #GstEncodingProfile to add to the project. If a profile with
 * the same name already exists, it will be replaced
 *
 * Adds @profile to the project. It lets you save in what format
 * the project has been renders and keep a reference to those formats.
 * Also, those formats will be saves to the project file when possible.
 *
 * Returns: %TRUE if @profile could be added, %FALSE otherwize
 */
gboolean
ges_project_add_encoding_profile (GESProject * project,
    GstEncodingProfile * profile)
{
  GList *tmp;
  GESProjectPrivate *priv;

  g_return_val_if_fail (GES_IS_PROJECT (project), FALSE);
  g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);

  priv = project->priv;
  for (tmp = priv->encoding_profiles; tmp; tmp = tmp->next) {
    GstEncodingProfile *tmpprofile = GST_ENCODING_PROFILE (tmp->data);

    if (g_strcmp0 (gst_encoding_profile_get_name (tmpprofile),
            gst_encoding_profile_get_name (profile)) == 0) {
      GST_INFO_OBJECT (project, "Already have profile: %s, replacing it",
          gst_encoding_profile_get_name (profile));

      gst_object_unref (tmp->data);
      tmp->data = gst_object_ref (profile);
      return TRUE;
    }
  }

  priv->encoding_profiles = g_list_prepend (priv->encoding_profiles,
      gst_object_ref (profile));

  return TRUE;
}
static void
print_profile (GUPnPDLNAProfile *profile, gpointer unused)
{
        GstEncodingProfile *enc_profile;
        const GList *tmp;
        gchar *caps_str;

        enc_profile = gupnp_dlna_profile_get_encoding_profile (profile);
        tmp = gst_encoding_container_profile_get_profiles
                                        (GST_ENCODING_CONTAINER_PROFILE (enc_profile));

        g_print ("%s %-30s%-35s",
                 gupnp_dlna_profile_get_extended (profile) ? "*" : " ",
                 gupnp_dlna_profile_get_name (profile),
                 gupnp_dlna_profile_get_mime (profile));

        if (verbose) {
                caps_str = gst_caps_to_string
                        (gst_encoding_profile_get_format (enc_profile));
                g_print ("\n`- container: %s\n", caps_str);
                g_free (caps_str);

                while (tmp) {
                        print_caps (gst_encoding_profile_get_format
                                        (GST_ENCODING_PROFILE (tmp->data)));
                        tmp = tmp->next;
                }
        }

        g_print ("\n");
        gst_encoding_profile_unref (enc_profile);
}
static GPtrArray *
get_missing_plugin_strings (GList *profiles, gboolean get_descriptions)
{
	RBEncoder *encoder;
	GPtrArray *strings;
	GList *l;

	encoder = rb_encoder_new ();
	strings = g_ptr_array_new_with_free_func (g_free);
	for (l = profiles; l != NULL; l = l->next) {
		GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data);
		char **details, **descriptions;
		char **d;
		int i;

		rb_encoder_get_missing_plugins (encoder, profile, &details, &descriptions);
		d = get_descriptions ? descriptions : details;
		for (i = 0; d[i] != NULL; i++) {
			g_ptr_array_add (strings, g_strdup (d[i]));
		}
		g_strfreev (details);
		g_strfreev (descriptions);
	}
	g_ptr_array_add (strings, NULL);
	g_object_unref (encoder);

	return strings;
}
Example #6
0
static void populate_profile_combo (GtkComboBox *combo)
{
  GstEncodingTarget *target;
  const GList *p;
  GtkTreeModel *model;

  model = GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING));

  target = rb_gst_get_default_encoding_target ();
  for (p = gst_encoding_target_get_profiles (target); p != NULL; p = p->next) {
    GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
    char *media_type;

    media_type = rb_gst_encoding_profile_get_media_type (profile);
    if (media_type == NULL) {
      continue;
    }
    gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
                                       NULL, NULL, -1,
                                       0, media_type,
                                       1, gst_encoding_profile_get_description (profile),
                                       -1);
    g_free (media_type);
  }

  gtk_combo_box_set_model (GTK_COMBO_BOX (combo), model);
  g_object_unref (model);
}
static GstEncodingProfile *
_create_profile (GESBaseXmlFormatter * self,
    const gchar * type, const gchar * parent, const gchar * name,
    const gchar * description, GstCaps * format, const gchar * preset,
    const gchar * preset_name, gint id, guint presence, GstCaps * restriction,
    guint pass, gboolean variableframerate, gboolean enabled)
{
  GstEncodingProfile *profile = NULL;

  if (!g_strcmp0 (type, "container")) {
    profile = GST_ENCODING_PROFILE (gst_encoding_container_profile_new (name,
            description, format, preset));
    gst_encoding_profile_set_preset_name (profile, preset_name);

    return profile;
  } else if (!g_strcmp0 (type, "video")) {
    GstEncodingVideoProfile *sprof = gst_encoding_video_profile_new (format,
        preset, restriction, presence);

    gst_encoding_video_profile_set_variableframerate (sprof, variableframerate);
    gst_encoding_video_profile_set_pass (sprof, pass);

    profile = GST_ENCODING_PROFILE (sprof);
  } else if (!g_strcmp0 (type, "audio")) {
    profile = GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (format,
            preset, restriction, presence));
  } else {
    GST_ERROR_OBJECT (self, "Unknown profile format '%s'", type);

    return NULL;
  }

  gst_encoding_profile_set_name (profile, name);
  gst_encoding_profile_set_enabled (profile, enabled);
  gst_encoding_profile_set_description (profile, description);
  gst_encoding_profile_set_preset_name (profile, preset_name);

  return profile;
}
static GstEncodingProfile *
make_profile_from_info (GstDiscovererInfo * info)
{
  GstEncodingContainerProfile *profile = NULL;
  GstDiscovererStreamInfo *sinfo = gst_discoverer_info_get_stream_info (info);

  /* Get the container format */
  if (GST_IS_DISCOVERER_CONTAINER_INFO (sinfo)) {
    GList *tmp, *substreams;

    profile = gst_encoding_container_profile_new ((gchar *) "concatenate", NULL,
        gst_discoverer_stream_info_get_caps (sinfo), NULL);

    substreams =
        gst_discoverer_container_info_get_streams ((GstDiscovererContainerInfo
            *) sinfo);

    /* For each on the formats add stream profiles */
    for (tmp = substreams; tmp; tmp = tmp->next) {
      GstDiscovererStreamInfo *stream = GST_DISCOVERER_STREAM_INFO (tmp->data);
      GstEncodingProfile *sprof = NULL;

      if (GST_IS_DISCOVERER_VIDEO_INFO (stream)) {
        sprof = (GstEncodingProfile *)
            gst_encoding_video_profile_new (gst_discoverer_stream_info_get_caps
            (stream), NULL, NULL, 1);
      } else if (GST_IS_DISCOVERER_AUDIO_INFO (stream)) {
        sprof = (GstEncodingProfile *)
            gst_encoding_audio_profile_new (gst_discoverer_stream_info_get_caps
            (stream), NULL, NULL, 1);
      } else {
        GST_WARNING ("Unsupported streams");
      }

      if (sprof)
        gst_encoding_container_profile_add_profile (profile, sprof);
    }
    if (substreams)
      gst_discoverer_stream_info_list_free (substreams);
  } else {
    GST_ERROR ("No container format !!!");
  }

  if (sinfo)
    gst_discoverer_stream_info_unref (sinfo);

  return GST_ENCODING_PROFILE (profile);
}
void
rygel_gst_utils_dump_encoding_profile (GstEncodingProfile *profile,
                                       gint                indent) {
  gchar *indent_s;
  const GstCaps *caps;
  gchar *format_name;
  const GstCaps *restriction;

  g_return_if_fail (profile != NULL);

  indent_s = g_strnfill ((gsize) indent, ' ');
  g_debug ("%s%s:", indent_s, gst_encoding_profile_get_name (profile));

  caps = gst_encoding_profile_get_format (profile);
  format_name = gst_caps_to_string (caps);
  g_debug ("%s  Format: %s", indent_s, format_name);
  g_free (format_name);

  restriction = gst_encoding_profile_get_restriction (profile);
  if (restriction) {
    gchar *restriction_name = gst_caps_to_string (restriction);
    g_debug ("%s  Restriction: %s", indent_s, restriction_name);
    g_free (restriction_name);
  }

  if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
    GstEncodingContainerProfile *container = GST_ENCODING_CONTAINER_PROFILE (profile);
    const GList *subprofile_collection = gst_encoding_container_profile_get_profiles (container);
    const GList *subprofile_it;

    for (subprofile_it = subprofile_collection; subprofile_it != NULL; subprofile_it = subprofile_it->next) {
      GstEncodingProfile *subprofile = GST_ENCODING_PROFILE (subprofile_it->data);

      rygel_gst_utils_dump_encoding_profile (subprofile, indent + 4);
    }
  }

  g_free (indent_s);
}
void
ges_base_xml_formatter_add_encoding_profile (GESBaseXmlFormatter * self,
    const gchar * type, const gchar * parent, const gchar * name,
    const gchar * description, GstCaps * format, const gchar * preset,
    const gchar * preset_name, guint id, guint presence, GstCaps * restriction,
    guint pass, gboolean variableframerate, GstStructure * properties,
    GError ** error)
{
  const GList *tmp;
  GstEncodingProfile *profile;
  GstEncodingContainerProfile *parent_profile = NULL;
  GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);

  if (priv->check_only)
    goto done;

  if (parent == NULL) {
    profile =
        _create_profile (self, type, parent, name, description, format, preset,
        preset_name, id, presence, restriction, pass, variableframerate);
    ges_project_add_encoding_profile (GES_FORMATTER (self)->project, profile);
    gst_object_unref (profile);

    goto done;
  }

  for (tmp = ges_project_list_encoding_profiles (GES_FORMATTER (self)->project);
      tmp; tmp = tmp->next) {
    GstEncodingProfile *tmpprofile = GST_ENCODING_PROFILE (tmp->data);

    if (g_strcmp0 (gst_encoding_profile_get_name (tmpprofile),
            gst_encoding_profile_get_name (tmpprofile)) == 0) {

      if (!GST_IS_ENCODING_CONTAINER_PROFILE (tmpprofile)) {
        g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
            "Profile '%s' parent %s is not a container...'", name, parent);
        goto done;
      }

      parent_profile = GST_ENCODING_CONTAINER_PROFILE (tmpprofile);
      break;
    }
  }

  if (parent_profile == NULL) {
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
        "Profile '%s' parent %s does not exist'", name, parent);
    goto done;
  }

  profile =
      _create_profile (self, type, parent, name, description, format, preset,
      preset_name, id, presence, restriction, pass, variableframerate);

  if (profile == NULL)
    goto done;

  gst_encoding_container_profile_add_profile (parent_profile, profile);

done:
  if (format)
    gst_caps_unref (format);
  if (restriction)
    gst_caps_unref (restriction);
}
/**
 * rb_track_transfer_batch_check_profiles:
 * @batch: a #RBTrackTransferBatch
 * @missing_plugin_profiles: (out) (element-type GstPbutils.EncodingProfile): holds a #GList of #GstEncodingProfiles on return
 * @error_count: holds the number of entries that cannot be transferred on return
 *
 * Checks that all entries in the batch can be transferred in a format
 * supported by the destination.  If no encoding profile is available for
 * some entries, but installing additional plugins could make a profile
 * available, a list of profiles that require additional plugins is returned.
 *
 * Return value: %TRUE if some entries can be transferred without additional plugins
 */
gboolean
rb_track_transfer_batch_check_profiles (RBTrackTransferBatch *batch, GList **missing_plugin_profiles, int *error_count)
{
	RBEncoder *encoder = rb_encoder_new ();
	gboolean ret = FALSE;
	const GList *l;

	rb_debug ("checking profiles");

	/* first, figure out which profiles that we care about would require additional plugins to use */
	g_list_free (batch->priv->missing_plugin_profiles);
	batch->priv->missing_plugin_profiles = NULL;

	for (l = gst_encoding_target_get_profiles (batch->priv->target); l != NULL; l = l->next) {
		GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data);
		char *profile_media_type;
		profile_media_type = rb_gst_encoding_profile_get_media_type (profile);
		if (profile_media_type != NULL &&
		    (rb_gst_media_type_is_lossless (profile_media_type) == FALSE) &&
		    rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) {
			batch->priv->missing_plugin_profiles = g_list_append (batch->priv->missing_plugin_profiles, profile);
		}
		g_free (profile_media_type);
	}
	g_object_unref (encoder);

	rb_debug ("have %d profiles with missing plugins", g_list_length (batch->priv->missing_plugin_profiles));

	for (l = batch->priv->entries; l != NULL; l = l->next) {
		RhythmDBEntry *entry = (RhythmDBEntry *)l->data;
		GstEncodingProfile *profile;

		profile = NULL;
		if (select_profile_for_entry (batch, entry, &profile, FALSE) == TRUE) {
			if (profile != NULL) {
				rb_debug ("found profile %s for %s",
					  gst_encoding_profile_get_name (profile),
					  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			} else {
				rb_debug ("copying entry %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			}
			ret = TRUE;
			continue;
		}

		(*error_count)++;
		if (select_profile_for_entry (batch, entry, &profile, TRUE) == FALSE) {
			rb_debug ("unable to transfer %s (media type %s)",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION),
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE));
		} else {
			rb_debug ("require additional plugins to transfer %s (media type %s)",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION),
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE));
			if (*missing_plugin_profiles == NULL) {
				*missing_plugin_profiles = g_list_copy (batch->priv->missing_plugin_profiles);
			}
		}
	}
	return ret;
}
static gboolean
select_profile_for_entry (RBTrackTransferBatch *batch, RhythmDBEntry *entry, GstEncodingProfile **rprofile, gboolean allow_missing)
{
	const char *source_media_type = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE);
	const GList *p;
	int best = 0;

	for (p = gst_encoding_target_get_profiles (batch->priv->target); p != NULL; p = p->next) {
		GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
		char *profile_media_type;
		const char *preferred_media_type;
		gboolean transcode_lossless;
		gboolean is_preferred;
		gboolean is_lossless;
		gboolean is_source;
		gboolean is_missing;
		int rank;

		profile_media_type = rb_gst_encoding_profile_get_media_type (profile);
		if (batch->priv->settings) {
			preferred_media_type = g_settings_get_string (batch->priv->settings, "media-type");
			if (rb_gst_media_type_is_lossless (preferred_media_type)) {
				transcode_lossless = FALSE;
			} else {
				transcode_lossless = g_settings_get_boolean (batch->priv->settings, "transcode-lossless");
			}

			is_preferred = (rb_gst_media_type_matches_profile (profile, preferred_media_type));
		} else {
			preferred_media_type = NULL;
			transcode_lossless = FALSE;
			is_preferred = FALSE;
		}

		is_missing = (g_list_find (batch->priv->missing_plugin_profiles, profile) != NULL);
		if (g_str_has_prefix (source_media_type, "audio/x-raw") == FALSE) {
			is_source = rb_gst_media_type_matches_profile (profile, source_media_type);
		} else {
			/* always transcode raw audio */
			is_source = FALSE;
		}

		if (profile_media_type != NULL) {
			is_lossless = (rb_gst_media_type_is_lossless (profile_media_type));
		} else {
			is_lossless = (rb_gst_media_type_is_lossless (source_media_type));
		}

		if (is_missing && allow_missing == FALSE && is_source == FALSE) {
			/* this only applies if transcoding would be required */
			rb_debug ("can't use encoding %s due to missing plugins", profile_media_type);
			rank = 0;
		} else if (transcode_lossless && is_lossless) {
			/* this overrides is_source so all lossless files get transcoded */
			rb_debug ("don't want lossless encoding %s", profile_media_type);
			rank = 0;
		} else if (is_source) {
			/* this overrides is_preferred so we don't transcode unneccessarily */
			rb_debug ("can use source encoding %s", profile_media_type);
			rank = 100;
			profile = NULL;
		} else if (is_preferred) {
			/* otherwise, always use the preferred encoding if available */
			rb_debug ("can use preferred encoding %s", profile_media_type);
			rank = 50;
		} else if (is_lossless == FALSE) {
			/* if we can't use the preferred encoding, we prefer lossy encodings over lossless, for space reasons */
			rb_debug ("can use lossy encoding %s", profile_media_type);
			rank = 25;
		} else {
			rb_debug ("can use lossless encoding %s", profile_media_type);
			rank = 10;
		}

		g_free (profile_media_type);
		if (rank > best) {
			*rprofile = profile;
			best = rank;
		}
	}

	return (best > 0);
}
static void
missing_encoder_response_cb (GtkDialog *dialog, gint response, RBTrackTransferQueue *queue)
{
	GClosure *retry;
	GstEncodingTarget *target;
	GPtrArray *details;
	GList *profiles;
	const GList *l;
	RBEncoder *encoder;

	switch (response) {
	case GTK_RESPONSE_YES:
		/* 'continue' -> start the batch */
		rb_debug ("starting batch regardless of missing plugins");
		actually_start_batch (queue);
		break;

	case GTK_RESPONSE_CANCEL:
	case GTK_RESPONSE_DELETE_EVENT:
		/* 'cancel' -> cancel the batch and start the next one */
		rb_debug ("cancelling batch");
		_rb_track_transfer_batch_cancel (queue->priv->current);
		g_object_unref (queue->priv->current);
		queue->priv->current = NULL;

		start_next_batch (queue);
		break;

	case GTK_RESPONSE_ACCEPT:
		/* 'install plugins' -> try to install encoder/muxer */

		/* get profiles that need plugins installed */
		profiles = NULL;
		encoder = rb_encoder_new ();
		g_object_get (queue->priv->current, "encoding-target", &target, NULL);
		for (l = gst_encoding_target_get_profiles (target); l != NULL; l = l->next) {
			GstEncodingProfile *profile = GST_ENCODING_PROFILE (l->data);
			char *profile_media_type;
			profile_media_type = rb_gst_encoding_profile_get_media_type (profile);
			if (profile_media_type != NULL &&
			    (rb_gst_media_type_is_lossless (profile_media_type) == FALSE) &&
			    rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) {
				profiles = g_list_append (profiles, profile);
			}
			g_free (profile_media_type);
		}
		g_object_unref (encoder);
		g_object_unref (target);

		if (profiles == NULL) {
			rb_debug ("apparently we don't need any plugins any more");
			actually_start_batch (queue);
			break;
		}

		rb_debug ("attempting plugin installation");
		details = get_missing_plugin_strings (profiles, FALSE);
		retry = g_cclosure_new ((GCallback) missing_plugins_retry_cb,
					g_object_ref (queue),
					(GClosureNotify) g_object_unref);
		g_closure_set_marshal (retry, g_cclosure_marshal_VOID__BOOLEAN);
		if (rb_missing_plugins_install ((const char **)details->pdata, FALSE, retry)) {
			rb_debug ("attempting to install missing plugins for transcoding");
		} else {
			rb_debug ("proceeding without the missing plugins for transcoding");
			actually_start_batch (queue);
		}

		g_closure_sink (retry);
		g_ptr_array_free (details, TRUE);
		g_list_free (profiles);
		break;

	default:
		g_assert_not_reached ();
	}

	gtk_widget_destroy (GTK_WIDGET (dialog));
}
static gboolean
select_profile_for_entry (RBTrackTransferBatch *batch, RhythmDBEntry *entry, GstEncodingProfile **rprofile, gboolean allow_missing)
{
	/* probably want a way to pass in some policy about lossless encoding
	 * here.  possibilities:
	 * - convert everything to lossy
	 * - if transcoding is required, use lossy
	 * - keep lossless encoded files lossless
	 * - if transcoding is required, use lossless
	 * - convert everything to lossless
	 *
	 * of course this only applies to targets that include lossless profiles..
	 */

	const char *media_type = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MEDIA_TYPE);
	GstEncodingProfile *lossless = NULL;
	gboolean found_lossy = FALSE;
	const GList *p;

	for (p = gst_encoding_target_get_profiles (batch->priv->target); p != NULL; p = p->next) {
		GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
		char *profile_media_type;
		gboolean is_missing;
		gboolean skip;

		if (g_str_has_prefix (media_type, "audio/x-raw") == FALSE &&
		    rb_gst_media_type_matches_profile (profile, media_type)) {
			/* source file is already in a supported encoding, so just copy it */
			*rprofile = NULL;
			return TRUE;
		}

		skip = FALSE;
		is_missing = (g_list_find (batch->priv->missing_plugin_profiles, profile) != NULL);

		profile_media_type = rb_gst_encoding_profile_get_media_type (profile);
		if (profile_media_type == NULL) {
			if (g_str_has_prefix (media_type, "audio/x-raw")) {
				skip = TRUE;
			}
		} else if (rb_gst_media_type_is_lossless (profile_media_type)) {
			skip = TRUE;
			if (allow_missing == FALSE && is_missing) {
				/* ignore entirely */
			} else if (lossless == NULL) {
				/* remember the first lossless profile that works */
				lossless = profile;
			}
		} else {
			found_lossy = TRUE;
			if (allow_missing == FALSE && is_missing) {
				skip = TRUE;
			}
		}

		if (skip == FALSE && *rprofile == NULL) {
			*rprofile = profile;
		}
		g_free (profile_media_type);
	}

	/* if we only found a lossless encoding, use it */
	if (*rprofile == NULL && found_lossy == FALSE && lossless != NULL) {
		*rprofile = lossless;
	}

	return (*rprofile != NULL);
}
static GstEncodingProfile *
parse_encoding_profile (const gchar * value)
{
  GstEncodingProfile *res;
  gchar **strpresence_v, **strcaps_v = g_strsplit (value, ":", 0);
  guint i;

  if (strcaps_v[0] && *strcaps_v[0]) {
    GstCaps *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;
    gchar *preset_name = NULL;
    GstCaps *caps;
    gchar **restriction_format, **preset_v;
    guint presence = 0;
    GstCaps *restrictioncaps = NULL;

    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]) {
        GST_ERROR ("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)) {
        g_warning ("Can not create a preset for caps: %s", strcaps_v[i]);

        return NULL;
      }
    } else {
      res = profile;
    }
  }
  g_strfreev (strcaps_v);

  return res;
}