Esempio n. 1
0
GstCaps *
gst_type_find_helper_get_range (GstObject * obj,
    GstTypeFindHelperGetRangeFunction func, guint64 size,
    GstTypeFindProbability * prob)
{
  GstTypeFindHelper helper;
  GstTypeFind find;
  GSList *walk;
  GList *l, *type_list;
  GstCaps *result = NULL;

  g_return_val_if_fail (GST_IS_OBJECT (obj), NULL);
  g_return_val_if_fail (func != NULL, NULL);

  helper.buffers = NULL;
  helper.size = size;
  helper.last_offset = 0;
  helper.func = func;
  helper.best_probability = 0;
  helper.caps = NULL;
  helper.obj = obj;

  find.data = &helper;
  find.peek = helper_find_peek;
  find.suggest = helper_find_suggest;

  if (size == 0 || size == (guint64) - 1) {
    find.get_length = NULL;
  } else {
    find.get_length = helper_find_get_length;
  }

  /* FIXME: we need to keep this list within the registry */
  type_list = gst_type_find_factory_get_list ();
  type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

  for (l = type_list; l; l = l->next) {
    helper.factory = GST_TYPE_FIND_FACTORY (l->data);
    gst_type_find_factory_call_function (helper.factory, &find);
    if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
      break;
  }
  gst_plugin_feature_list_free (type_list);

  for (walk = helper.buffers; walk; walk = walk->next)
    gst_buffer_unref (GST_BUFFER_CAST (walk->data));
  g_slist_free (helper.buffers);

  if (helper.best_probability > 0)
    result = helper.caps;

  if (prob)
    *prob = helper.best_probability;

  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
      result, (guint) helper.best_probability);

  return result;
}
EXPORT_C
#endif

GstCaps *
gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
                                 GstTypeFindProbability * prob)
{
    GstTypeFindBufHelper helper;
    GstTypeFind find;
    GList *l, *type_list;
    GstCaps *result = NULL;

    g_return_val_if_fail (buf != NULL, NULL);
    g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
    g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
                          GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);

    helper.data = GST_BUFFER_DATA (buf);
    helper.size = GST_BUFFER_SIZE (buf);
    helper.best_probability = 0;
    helper.caps = NULL;
    helper.obj = obj;

    if (helper.data == NULL || helper.size == 0)
        return NULL;

    find.data = &helper;
    find.peek = buf_helper_find_peek;
    find.suggest = buf_helper_find_suggest;
    find.get_length = NULL;

    /* FIXME: we need to keep this list within the registry */
    type_list = gst_type_find_factory_get_list ();
    type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

    for (l = type_list; l; l = l->next) {
        helper.factory = GST_TYPE_FIND_FACTORY (l->data);
        gst_type_find_factory_call_function (helper.factory, &find);
        if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
            break;
    }
    gst_plugin_feature_list_free (type_list);

    if (helper.best_probability > 0)
        result = helper.caps;

    if (prob)
        *prob = helper.best_probability;

    GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
                    result, (guint) helper.best_probability);

    return result;
}
EXPORT_C
#endif

GstCaps *
gst_type_find_helper_for_extension (GstObject * obj, const gchar * extension)
{
    GList *l, *type_list;
    GstCaps *result = NULL;

    g_return_val_if_fail (extension != NULL, NULL);

    GST_LOG_OBJECT (obj, "finding caps for extension %s", extension);

    type_list = gst_type_find_factory_get_list ();
    type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

    for (l = type_list; l; l = g_list_next (l)) {
        GstTypeFindFactory *factory;
        gchar **ext;
        gint i;

        factory = GST_TYPE_FIND_FACTORY (l->data);

        /* get the extension that this typefind factory can handle */
        ext = gst_type_find_factory_get_extensions (factory);
        if (ext == NULL)
            continue;

        /* we only want to check those factories without a function */
        if (factory->function != NULL)
            continue;

        /* there are extension, see if one of them matches the requested
         * extension */
        for (i = 0; ext[i]; i++) {
            if (strcmp (ext[i], extension) == 0) {
                /* we found a matching extension, take the caps */
                if ((result = gst_type_find_factory_get_caps (factory))) {
                    gst_caps_ref (result);
                    goto done;
                }
            }
        }
    }
done:
    gst_plugin_feature_list_free (type_list);

    GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT, result);

    return result;
}
Esempio n. 4
0
/**
 * gst_type_find_helper_for_data_with_extension:
 * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
 * @data: (transfer none) (array length=size): * a pointer with data to typefind
 * @size: the size of @data
 * @extension: (allow-none): extension of the media, or %NULL
 * @prob: (out) (allow-none): location to store the probability of the found
 *     caps, or %NULL
 *
 * Tries to find what type of data is contained in the given @data, the
 * assumption being that the data represents the beginning of the stream or
 * file.
 *
 * All available typefinders will be called on the data in order of rank. If
 * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
 * typefinding is stopped immediately and the found caps will be returned
 * right away. Otherwise, all available typefind functions will the tried,
 * and the caps with the highest probability will be returned, or %NULL if
 * the content of @data could not be identified.
 *
 * When @extension is not %NULL, this function will first try the typefind
 * functions for the given extension, which might speed up the typefinding
 * in many cases.
 *
 * Free-function: gst_caps_unref
 *
 * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data,
 *     or %NULL if no type could be found. The caller should free the caps
 *     returned with gst_caps_unref().
 *
 * Since: 1.16
 *
 */
GstCaps *
gst_type_find_helper_for_data_with_extension (GstObject * obj,
    const guint8 * data, gsize size, const gchar * extension,
    GstTypeFindProbability * prob)
{
  GstTypeFindBufHelper helper;
  GstTypeFind find;
  GList *l, *type_list;
  GstCaps *result = NULL;

  g_return_val_if_fail (data != NULL, NULL);

  helper.data = data;
  helper.size = size;
  helper.best_probability = GST_TYPE_FIND_NONE;
  helper.caps = NULL;
  helper.obj = obj;

  if (helper.data == NULL || helper.size == 0)
    return NULL;

  find.data = &helper;
  find.peek = buf_helper_find_peek;
  find.suggest = buf_helper_find_suggest;
  find.get_length = NULL;

  type_list = gst_type_find_factory_get_list ();
  type_list = prioritize_extension (obj, type_list, extension);

  for (l = type_list; l; l = l->next) {
    helper.factory = GST_TYPE_FIND_FACTORY (l->data);
    gst_type_find_factory_call_function (helper.factory, &find);
    if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
      break;
  }
  gst_plugin_feature_list_free (type_list);

  if (helper.best_probability > 0)
    result = helper.caps;

  if (prob)
    *prob = helper.best_probability;

  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
      result, (guint) helper.best_probability);

  return result;
}
Esempio n. 5
0
static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
{
    res = gst_type_find_element_chain_do_typefinding (typefind);
    {
        GstCaps *caps;
        caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
          typefind->store, &probability);
        // gstreamer/libs/gst/base/gsttypefindhelper.c
        // All available typefinders will be called on the data in order of rank. If
        // a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
        // typefinding is stopped immediately and the found caps will be returned
        // right away. Otherwise, all available typefind functions will the tried,
        // and the caps with the highest probability will be returned
        {
            type_list = gst_type_find_factory_get_list ();
            type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

            gst_type_find_factory_call_function (helper.factory, &find);
            {
                // find function from factory
                new_factory =
                    GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory)));
                new_factory->function (find, new_factory->user_data);
                gst_object_unref (new_factory);
            } // gst_type_find_factory_call_function()
        } // gst_type_find_helper_for_buffer()

        /* probability is good enough too, so let's make it known ... */
        g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
            probability, caps);

        // stop typefind
        stop_typefinding (typefind);
        {
            // TODO: why set itself to NULL?
            gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

            // reset state to normal
            typefind->mode = MODE_NORMAL;

            // send cache event and buffers
            gst_type_find_element_send_cached_events (typefind);
            gst_pad_push (typefind->src, typefind->store);
        }
    } // gst_type_find_element_chain_do_typefinding()
}
/*
 * Class method: list
 *
 * Gets the list of all registered type find factories.
 *
 * Returns: an Array of Gst::TypeFindFactory objects.
 */
static VALUE
rg_s_list (void)
{
    GList *list;
    GList *orig;
    VALUE arr;

    arr = rb_ary_new ();
    orig = gst_type_find_factory_get_list();
    for (list = orig; list != NULL; list = g_list_next (list)) {
        GstTypeFindFactory *tff = GST_TYPE_FIND_FACTORY (list->data);
        rb_ary_push (arr, RGST_TYPE_FIND_FACTORY_NEW (tff));
    }
    if (orig != NULL) {
        g_list_free (orig);
    }
    return arr;
}
Esempio n. 7
0
/**
 * gst_type_find_helper_get_range_ext:
 * @obj: A #GstObject that will be passed as first argument to @func
 * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
 *        be used to access data at random offsets when doing the typefinding
 * @size: The length in bytes
 * @extension: extension of the media
 * @prob: (out) (allow-none): location to store the probability of the found
 *     caps, or #NULL
 *
 * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
 * however, this function will use the specified function @func to obtain the
 * data needed by the typefind functions, rather than operating on a given
 * source pad. This is useful mostly for elements like tag demuxers which
 * strip off data at the beginning and/or end of a file and want to typefind
 * the stripped data stream before adding their own source pad (the specified
 * callback can then call the upstream peer pad with offsets adjusted for the
 * tag size, for example).
 *
 * When @extension is not NULL, this function will first try the typefind
 * functions for the given extension, which might speed up the typefinding
 * in many cases.
 *
 * Free-function: gst_caps_unref
 *
 * Returns: (transfer full): the #GstCaps corresponding to the data stream.
 *     Returns #NULL if no #GstCaps matches the data stream.
 *
 * Since: 0.10.26
 */
GstCaps *
gst_type_find_helper_get_range_ext (GstObject * obj,
    GstTypeFindHelperGetRangeFunction func, guint64 size,
    const gchar * extension, GstTypeFindProbability * prob)
{
  GstTypeFindHelper helper;
  GstTypeFind find;
  GSList *walk;
  GList *l, *type_list;
  GstCaps *result = NULL;
  gint pos = 0;

  g_return_val_if_fail (GST_IS_OBJECT (obj), NULL);
  g_return_val_if_fail (func != NULL, NULL);

  helper.buffers = NULL;
  helper.size = size;
  helper.last_offset = 0;
  helper.func = func;
  helper.best_probability = GST_TYPE_FIND_NONE;
  helper.caps = NULL;
  helper.obj = obj;

  find.data = &helper;
  find.peek = helper_find_peek;
  find.suggest = helper_find_suggest;

  if (size == 0 || size == (guint64) - 1) {
    find.get_length = NULL;
  } else {
    find.get_length = helper_find_get_length;
  }

  type_list = gst_type_find_factory_get_list ();

  /* move the typefinders for the extension first in the list. The idea is that
   * when one of them returns MAX we don't need to search further as there is a
   * very high chance we got the right type. */
  if (extension) {
    GList *next;

    GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head",
        extension);

    for (l = type_list; l; l = next) {
      GstTypeFindFactory *factory;
      gint i;
      gchar **ext;

      next = l->next;

      factory = GST_TYPE_FIND_FACTORY (l->data);

      ext = gst_type_find_factory_get_extensions (factory);
      if (ext == NULL)
        continue;

      GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
          GST_PLUGIN_FEATURE_NAME (factory), extension);

      for (i = 0; ext[i]; i++) {
        if (strcmp (ext[i], extension) == 0) {
          /* found extension, move in front */
          GST_LOG_OBJECT (obj, "moving typefind for extension %s to head",
              extension);
          /* remove entry from list */
          type_list = g_list_delete_link (type_list, l);
          /* insert at the position */
          type_list = g_list_insert (type_list, factory, pos);
          /* next element will be inserted after this one */
          pos++;
          break;
        }
      }
    }
  }

  for (l = type_list; l; l = l->next) {
    helper.factory = GST_TYPE_FIND_FACTORY (l->data);
    gst_type_find_factory_call_function (helper.factory, &find);
    if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
      break;
  }
  gst_plugin_feature_list_free (type_list);

  for (walk = helper.buffers; walk; walk = walk->next)
    gst_buffer_unref (GST_BUFFER_CAST (walk->data));
  g_slist_free (helper.buffers);

  if (helper.best_probability > 0)
    result = helper.caps;

  if (prob)
    *prob = helper.best_probability;

  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
      result, (guint) helper.best_probability);

  return result;
}
/*virtual*/ nsresult 
sbGStreamerMediacoreFactory::OnGetCapabilities(
                             sbIMediacoreCapabilities **aCapabilities)
{
  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
  nsAutoMonitor mon(mMonitor);

  // TODO: This function is now a _huge_ mess. We should talk to product about
  // what files we want to import / etc, some time soon - e.g. the current
  // approach is to treat anything even vaguely-plausibly audio-related as
  // audio (even if we can't play it!), but to only import a small list of fixed
  // extensions for videos (excluding many things we might be able to play).

  nsresult rv;
  if (!mCapabilities) {
    nsRefPtr<sbMediacoreCapabilities> caps;
    NS_NEWXPCOM(caps, sbMediacoreCapabilities);
    NS_ENSURE_TRUE(caps, NS_ERROR_OUT_OF_MEMORY);

    rv = caps->Init();
    NS_ENSURE_SUCCESS(rv, rv);

    // Build a big list of extensions based on everything gstreamer knows about,
    // plus some known ones, minus a few known non-media-file extensions that
    // gstreamer has typefinders for.

    nsCOMPtr<nsIPrefBranch> rootPrefBranch =
      do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsTArray<nsString> audioExtensions;
    nsTArray<nsString> videoExtensions;
    
    // XXX Mook: we have a silly list of blacklisted extensions because we don't
    // support them and we're being stupid and guessing things based on them.
    // This crap should really look for a plugin that may possibly actually decode
    // these things, or something better.  Whatever the real solution is, this
    // isn't it :(
    nsCString blacklistExtensions;
    { // for scope
      const char defaultBlacklistExtensions[] =
        "txt,htm,html,xml,pdf,cpl,msstyles,scr,sys,ocx,bz2,gz,zip,Z,rar,tar,dll,"
        "exe,a,bmp,png,gif,jpeg,jpg,jpe,tif,tiff,xpm,dat,swf,swfl,stm,cgi,sf,xcf,"
        "far,wvc,mpc,mpp,mp+,ra,rm,rmvb";
      char* blacklistExtensionsPtr = nsnull;
      rv = rootPrefBranch->GetCharPref(BLACKLIST_EXTENSIONS_PREF,
                                       &blacklistExtensionsPtr);
      if (NS_SUCCEEDED(rv)) {
        blacklistExtensions.Adopt(blacklistExtensionsPtr);
      } else {
        blacklistExtensions.Assign(defaultBlacklistExtensions);
      }
      blacklistExtensions.Insert(',', 0);
      blacklistExtensions.Append(',');
      LOG(("sbGStreamerMediacoreFactory: blacklisted extensions: %s\n",
           blacklistExtensions.BeginReading()));
    }

    const char *extraAudioExtensions[] = {"m4r", "m4p", "oga",
                                          "ogg", "aac", "3gp"};
#ifdef XP_WIN
    const char *extraWindowsAudioExtensions[] = {"wma" };
#endif

    { // for scope

      // Per bug 19550 -
      // Severly limit the video extensions that are imported by default to:
      //   * ogv (all platforms)
      //   * wmv (windows only)
      //   * mp4/m4v/mov (w/ qtvideowrapper plugin)
      //   * divx/avi/mkv (w/ ewmpeg4dec plugin)
      videoExtensions.AppendElement(NS_LITERAL_STRING("ogv"));
#ifdef XP_WIN
      videoExtensions.AppendElement(NS_LITERAL_STRING("wmv"));
#endif

      char* knownVideoExtensionsPtr = nsnull;
      rv = rootPrefBranch->GetCharPref(VIDEO_EXTENSIONS_PREF,
                                       &knownVideoExtensionsPtr);
      if (NS_SUCCEEDED(rv)) {
        // The override video extension pref contains a CSV string.
        nsString_Split(NS_ConvertUTF8toUTF16(knownVideoExtensionsPtr),
                       NS_LITERAL_STRING(","),
                       videoExtensions);
      }

#ifdef PR_LOGGING
      nsString videoExtensionStr;
      for (PRUint32 i = 0; i < videoExtensions.Length(); i++) {
        videoExtensionStr.Append(videoExtensions[i]);
        if (i < videoExtensions.Length() - 1) {
          videoExtensionStr.AppendLiteral(", ");
        }
      }

      LOG(("sbGStreamerMediacoreFactory: video file extensions: %s\n",
            videoExtensionStr.get()));
#endif

      // Check for the 'qtvideowrapper' plugin to add mp4/m4v extensions.
      PRBool foundQTPlugin = PR_FALSE;
      GstPlugin *plugin = gst_default_registry_find_plugin("qtvideowrapper");
      if (plugin) {
        foundQTPlugin = PR_TRUE;
        videoExtensions.AppendElement(NS_LITERAL_STRING("mp4"));
        videoExtensions.AppendElement(NS_LITERAL_STRING("m4v"));
        videoExtensions.AppendElement(NS_LITERAL_STRING("mov"));
        gst_object_unref(plugin);
      }

      // Check for the 'ewmpeg4dec' plugin to add divx/avi extensions.
      plugin = gst_default_registry_find_plugin("ewmpeg4dec");
      if (plugin) {
        videoExtensions.AppendElement(NS_LITERAL_STRING("divx"));
        videoExtensions.AppendElement(NS_LITERAL_STRING("avi"));
        videoExtensions.AppendElement(NS_LITERAL_STRING("mkv"));

        // This plugin will also handle "mp4" and "m4v", only append those
        // extensions if they haven't been added already.
        if (!foundQTPlugin) {
          videoExtensions.AppendElement(NS_LITERAL_STRING("mp4"));
          videoExtensions.AppendElement(NS_LITERAL_STRING("m4v"));
        }

        gst_object_unref(plugin);
      }
    }

    GList *walker, *list;

    list = gst_type_find_factory_get_list ();
    walker = list;
    while (walker) {
      GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walker->data);
      gboolean blacklisted = FALSE;
      const gchar* factoryName = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));
      gboolean isAudioFactory = g_str_has_prefix(factoryName, "audio/");

      gchar **factoryexts = gst_type_find_factory_get_extensions (factory);
      if (factoryexts) {
        while (*factoryexts) {
          gboolean isAudioExtension = isAudioFactory;
          nsCString extension(*factoryexts);
          nsCString delimitedExtension(extension);
          delimitedExtension.Insert(',', 0);
          delimitedExtension.Append(',');
          
          blacklisted = (blacklistExtensions.Find(delimitedExtension) != -1);
          #if PR_LOGGING
            if (blacklisted) {
                LOG(("sbGStreamerMediacoreFactory: Ignoring extension '%s'", *factoryexts));
            }
          #endif /* PR_LOGGING */

          if (!blacklisted && isAudioExtension) {
            audioExtensions.AppendElement(NS_ConvertUTF8toUTF16(*factoryexts));
            LOG(("sbGStreamerMediacoreFactory: registering audio extension %s\n",
                  *factoryexts));
          }

          factoryexts++;
        }
      }
      walker = g_list_next (walker);
    }
    g_list_free (list);

    for (unsigned int i = 0; i < NS_ARRAY_LENGTH(extraAudioExtensions); i++) {
      nsString ext = NS_ConvertUTF8toUTF16(extraAudioExtensions[i]);
      if(!audioExtensions.Contains(ext))
        audioExtensions.AppendElement(ext);
    }

#if XP_WIN
    for (unsigned int i = 0; i < NS_ARRAY_LENGTH(extraWindowsAudioExtensions); i++) {
      nsString ext = NS_ConvertUTF8toUTF16(extraWindowsAudioExtensions[i]);
      if(!audioExtensions.Contains(ext))
        audioExtensions.AppendElement(ext);
    }
#endif

    rv = caps->SetAudioExtensions(audioExtensions);
    NS_ENSURE_SUCCESS(rv, rv);

    // Audio playback is always allowed.
    rv = caps->SetSupportsAudioPlayback(PR_TRUE);
    NS_ENSURE_SUCCESS(rv, rv);

    PRBool videoDisabled = PR_FALSE;
    rv = rootPrefBranch->GetBoolPref(
                                    "songbird.mediacore.gstreamer.disablevideo",
                                    &videoDisabled);
    NS_ENSURE_SUCCESS(rv, rv);
    if (!videoDisabled) {
      rv = caps->SetVideoExtensions(videoExtensions);
      NS_ENSURE_SUCCESS(rv, rv);

      rv = caps->SetSupportsVideoPlayback(PR_TRUE);
      NS_ENSURE_SUCCESS(rv, rv);
    }

    mCapabilities = caps;
  }

  rv = CallQueryInterface(mCapabilities.get(), aCapabilities);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
static HashSet<String> mimeTypeCache()
{

    do_gst_init();

    static HashSet<String> cache;
    static bool typeListInitialized = false;

    if (!typeListInitialized) {
        // These subtypes are already beeing supported by WebKit itself
        HashSet<String> ignoredApplicationSubtypes;
        ignoredApplicationSubtypes.add(String("javascript"));
        ignoredApplicationSubtypes.add(String("ecmascript"));
        ignoredApplicationSubtypes.add(String("x-javascript"));
        ignoredApplicationSubtypes.add(String("xml"));
        ignoredApplicationSubtypes.add(String("xhtml+xml"));
        ignoredApplicationSubtypes.add(String("rss+xml"));
        ignoredApplicationSubtypes.add(String("atom+xml"));
        ignoredApplicationSubtypes.add(String("x-ftp-directory"));
        ignoredApplicationSubtypes.add(String("x-java-applet"));
        ignoredApplicationSubtypes.add(String("x-java-bean"));
        ignoredApplicationSubtypes.add(String("x-java-vm"));
        ignoredApplicationSubtypes.add(String("x-shockwave-flash"));

        GList* factories = gst_type_find_factory_get_list();
        for (GList* iterator = factories; iterator; iterator = iterator->next) {
            GstTypeFindFactory* factory = GST_TYPE_FIND_FACTORY(iterator->data);
            GstCaps* caps = gst_type_find_factory_get_caps(factory);

            // Splitting the capability by comma and taking the first part
            // as capability can be something like "audio/x-wavpack, framed=(boolean)false"
            GOwnPtr<gchar> capabilityString(gst_caps_to_string(caps));
            gchar** capability = g_strsplit(capabilityString.get(), ",", 2);
            gchar** mimetype = g_strsplit(capability[0], "/", 2);

            // GStreamer plugins can be capable of supporting types which WebKit supports
            // by default. In that case, we should not consider these types supportable by GStreamer.
            // Examples of what GStreamer can support but should not be added:
            // text/plain, text/html, image/jpeg, application/xml
            if (g_str_equal(mimetype[0], "audio") ||
                    g_str_equal(mimetype[0], "video") ||
                    (g_str_equal(mimetype[0], "application") &&
                        !ignoredApplicationSubtypes.contains(String(mimetype[1])))) {
                cache.add(String(capability[0]));

                // These formats are supported by GStreamer, but not correctly advertised
                if (g_str_equal(capability[0], "video/x-h264") ||
                    g_str_equal(capability[0], "audio/x-m4a")) {
                    cache.add(String("video/mp4"));
                    cache.add(String("audio/aac"));
                }

                if (g_str_equal(capability[0], "video/x-theora"))
                    cache.add(String("video/ogg"));

                if (g_str_equal(capability[0], "audio/x-wav"))
                    cache.add(String("audio/wav"));

                if (g_str_equal(capability[0], "audio/mpeg")) {
                    // This is what we are handling: mpegversion=(int)1, layer=(int)[ 1, 3 ]
                    gchar** versionAndLayer = g_strsplit(capability[1], ",", 2);

                    if (g_str_has_suffix (versionAndLayer[0], "(int)1")) {
                        for (int i = 0; versionAndLayer[1][i] != '\0'; i++) {
                            if (versionAndLayer[1][i] == '1')
                                cache.add(String("audio/mp1"));
                            else if (versionAndLayer[1][i] == '2')
                                cache.add(String("audio/mp2"));
                            else if (versionAndLayer[1][i] == '3')
                                cache.add(String("audio/mp3"));
                        }
                    }

                    g_strfreev(versionAndLayer);
                }
            }

            g_strfreev(capability);
            g_strfreev(mimetype);
        }

        gst_plugin_feature_list_free(factories);
        typeListInitialized = true;
    }

    return cache;
}
Esempio n. 10
0
// Obtains a list of supported extensions from typefind factories
// TODO: improve the list. It is obviously incomplete.
wxArrayString
GStreamerImportPlugin::GetSupportedExtensions()
{
   // We refresh the extensions each time this is called in case the
   // user had installed additional gstreamer plugins while Audacity
   // was active.
   mExtensions.Empty();

   // Gather extensions from all factories that support audio
   GList *factories = gst_type_find_factory_get_list();
   for (GList *list = factories; list != NULL; list = g_list_next(list))
   {
      GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY(list->data);

      // We need the capabilities to determine if it handles audio
      GstCaps *caps = gst_type_find_factory_get_caps(factory);
      if (!caps)
      {
         continue;
      }

      // Check each structure in the caps for audio
      for (guint c = 0, clen = gst_caps_get_size(caps); c < clen; c++)
      {
         // Bypass if it isn't for audio
         GstStructure *str = gst_caps_get_structure(caps, c);
         if (!g_str_has_prefix(gst_structure_get_name(str), "audio"))
         {
            continue;
         }

         // This factory can handle audio, so get the extensions
         const gchar *const *extensions = gst_type_find_factory_get_extensions(factory);
         if (!extensions)
         {
            continue;
         }

         // Add each extension to the list
         for (guint i = 0; extensions[i] != NULL; i++)
         {
            wxString extension = wxString::FromUTF8(extensions[i]);
            if (mExtensions.Index(extension.c_str(), false) == wxNOT_FOUND)
            {
               mExtensions.Add(extension);
            }
         }
      }
   }
   gst_plugin_feature_list_free(factories);

   // Get them in a decent order
   mExtensions.Sort();

   // Log it for debugging
   wxString extensions = wxT("Extensions:");
   for (size_t i = 0; i < mExtensions.GetCount(); i++)
   {
      extensions = extensions + wxT(" ") + mExtensions[i];
   }
   wxLogMessage(wxT("%s"), extensions.c_str());

   return mExtensions;
}
Esempio n. 11
0
/**
 * gst_type_find_helper_get_range_full:
 * @obj: A #GstObject that will be passed as first argument to @func
 * @parent: (allow-none): the parent of @obj or %NULL
 * @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
 *        be used to access data at random offsets when doing the typefinding
 * @size: The length in bytes
 * @extension: (allow-none): extension of the media, or %NULL
 * @caps: (out) (transfer full): returned caps
 * @prob: (out) (allow-none): location to store the probability of the found
 *     caps, or %NULL
 *
 * Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
 * however, this function will use the specified function @func to obtain the
 * data needed by the typefind functions, rather than operating on a given
 * source pad. This is useful mostly for elements like tag demuxers which
 * strip off data at the beginning and/or end of a file and want to typefind
 * the stripped data stream before adding their own source pad (the specified
 * callback can then call the upstream peer pad with offsets adjusted for the
 * tag size, for example).
 *
 * When @extension is not %NULL, this function will first try the typefind
 * functions for the given extension, which might speed up the typefinding
 * in many cases.
 *
 * Returns: the last %GstFlowReturn from pulling a buffer or %GST_FLOW_OK if
 *          typefinding was successful.
 *
 * Since: 1.14.3
 */
GstFlowReturn
gst_type_find_helper_get_range_full (GstObject * obj, GstObject * parent,
    GstTypeFindHelperGetRangeFunction func, guint64 size,
    const gchar * extension, GstCaps ** caps, GstTypeFindProbability * prob)
{
  GstTypeFindHelper helper;
  GstTypeFind find;
  GSList *walk;
  GList *l, *type_list;
  GstCaps *result = NULL;

  g_return_val_if_fail (GST_IS_OBJECT (obj), GST_FLOW_ERROR);
  g_return_val_if_fail (func != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (caps != NULL, GST_FLOW_ERROR);

  *caps = NULL;

  helper.buffers = NULL;
  helper.size = size;
  helper.last_offset = 0;
  helper.func = func;
  helper.best_probability = GST_TYPE_FIND_NONE;
  helper.caps = NULL;
  helper.obj = obj;
  helper.parent = parent;
  helper.flow_ret = GST_FLOW_OK;

  find.data = &helper;
  find.peek = helper_find_peek;
  find.suggest = helper_find_suggest;

  if (size == 0 || size == (guint64) - 1) {
    find.get_length = NULL;
  } else {
    find.get_length = helper_find_get_length;
  }

  type_list = gst_type_find_factory_get_list ();
  type_list = prioritize_extension (obj, type_list, extension);

  for (l = type_list; l; l = l->next) {
    helper.factory = GST_TYPE_FIND_FACTORY (l->data);
    gst_type_find_factory_call_function (helper.factory, &find);
    if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM) {
      /* Any other flow return can be ignored here, we found
       * something before any error with highest probability */
      helper.flow_ret = GST_FLOW_OK;
      break;
    } else if (helper.flow_ret != GST_FLOW_OK
        && helper.flow_ret != GST_FLOW_EOS) {
      /* We had less than maximum probability and an error, don't return
       * any caps as they might be with a lower probability than what
       * we would've gotten when continuing if there was no error */
      gst_caps_replace (&helper.caps, NULL);
      break;
    }
  }
  gst_plugin_feature_list_free (type_list);

  for (walk = helper.buffers; walk; walk = walk->next) {
    GstMappedBuffer *bmap = (GstMappedBuffer *) walk->data;

    gst_buffer_unmap (bmap->buffer, &bmap->map);
    gst_buffer_unref (bmap->buffer);
    g_slice_free (GstMappedBuffer, bmap);
  }
  g_slist_free (helper.buffers);

  if (helper.best_probability > 0)
    result = helper.caps;

  if (prob)
    *prob = helper.best_probability;

  *caps = result;
  if (helper.flow_ret == GST_FLOW_EOS) {
    /* Some typefinder might've tried to read too much, if we
     * didn't get any meaningful caps because of that this is
     * just a normal error */
    helper.flow_ret = GST_FLOW_ERROR;
  }

  GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
      result, (guint) helper.best_probability);

  return helper.flow_ret;
}