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; }
static GList * prioritize_extension (GstObject * obj, GList * type_list, const gchar * extension) { gint pos = 0; GList *next, *l; if (!extension) return type_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. */ GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head", extension); for (l = type_list; l; l = next) { const gchar *const *ext; GstTypeFindFactory *factory; 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_OBJECT_NAME (factory), extension); while (*ext != NULL) { if (strcmp (*ext, 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; } ++ext; } } return type_list; }
/* * Method: extensions * * Gets the extensions associated with a type find factory. * * Returns: an Array of String objects, or nil if no extensions are * associated with the type find factory. */ static VALUE rg_extensions(VALUE self) { VALUE ary; gchar **extensions; ary = rb_ary_new (); extensions = gst_type_find_factory_get_extensions(SELF(self)); if (!extensions) return ary; while (*extensions) { rb_ary_push(ary, CSTR2RVAL(*extensions)); extensions++; } return ary; }
/** * 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 void print_element_list (gboolean print_all) { int plugincount = 0, featurecount = 0, blacklistcount = 0; GList *plugins, *orig_plugins; orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get ()); while (plugins) { GList *features, *orig_features; GstPlugin *plugin; plugin = (GstPlugin *) (plugins->data); plugins = g_list_next (plugins); plugincount++; if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED)) { blacklistcount++; continue; } orig_features = features = gst_registry_get_feature_list_by_plugin (gst_registry_get (), gst_plugin_get_name (plugin)); while (features) { GstPluginFeature *feature; if (G_UNLIKELY (features->data == NULL)) goto next; feature = GST_PLUGIN_FEATURE (features->data); featurecount++; if (GST_IS_ELEMENT_FACTORY (feature)) { GstElementFactory *factory; factory = GST_ELEMENT_FACTORY (feature); if (print_all) print_element_info (factory, TRUE); else g_print ("%s: %s: %s\n", gst_plugin_get_name (plugin), GST_OBJECT_NAME (factory), gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)); } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { GstTypeFindFactory *factory; const gchar *const *extensions; factory = GST_TYPE_FIND_FACTORY (feature); if (!print_all) g_print ("%s: %s: ", gst_plugin_get_name (plugin), gst_plugin_feature_get_name (feature)); extensions = gst_type_find_factory_get_extensions (factory); if (extensions != NULL) { guint i = 0; while (extensions[i]) { if (!print_all) g_print ("%s%s", i > 0 ? ", " : "", extensions[i]); i++; } if (!print_all) g_print ("\n"); } else { if (!print_all) g_print ("no extensions\n"); } } else { if (!print_all) n_print ("%s: %s (%s)\n", gst_plugin_get_name (plugin), GST_OBJECT_NAME (feature), g_type_name (G_OBJECT_TYPE (feature))); } next: features = g_list_next (features); } gst_plugin_feature_list_free (orig_features); } gst_plugin_list_free (orig_plugins); g_print ("\n"); g_print (_("Total count: ")); g_print (ngettext ("%d plugin", "%d plugins", plugincount), plugincount); if (blacklistcount) { g_print (" ("); g_print (ngettext ("%d blacklist entry", "%d blacklist entries", blacklistcount), blacklistcount); g_print (" not shown)"); } g_print (", "); g_print (ngettext ("%d feature", "%d features", featurecount), featurecount); g_print ("\n"); }
static void print_plugin_features (GstPlugin * plugin) { GList *features, *origlist; gint num_features = 0; gint num_elements = 0; gint num_tracers = 0; gint num_typefinders = 0; gint num_devproviders = 0; gint num_other = 0; origlist = features = gst_registry_get_feature_list_by_plugin (gst_registry_get (), gst_plugin_get_name (plugin)); while (features) { GstPluginFeature *feature; feature = GST_PLUGIN_FEATURE (features->data); if (GST_IS_ELEMENT_FACTORY (feature)) { GstElementFactory *factory; factory = GST_ELEMENT_FACTORY (feature); n_print (" %s: %s\n", GST_OBJECT_NAME (factory), gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)); num_elements++; } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { GstTypeFindFactory *factory; const gchar *const *extensions; factory = GST_TYPE_FIND_FACTORY (feature); extensions = gst_type_find_factory_get_extensions (factory); if (extensions) { guint i = 0; g_print (" %s: %s: ", gst_plugin_get_name (plugin), gst_plugin_feature_get_name (feature)); while (extensions[i]) { g_print ("%s%s", i > 0 ? ", " : "", extensions[i]); i++; } g_print ("\n"); } else g_print (" %s: %s: no extensions\n", gst_plugin_get_name (plugin), gst_plugin_feature_get_name (feature)); num_typefinders++; } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) { GstDeviceProviderFactory *factory; factory = GST_DEVICE_PROVIDER_FACTORY (feature); n_print (" %s: %s\n", GST_OBJECT_NAME (factory), gst_device_provider_factory_get_metadata (factory, GST_ELEMENT_METADATA_LONGNAME)); num_devproviders++; } else if (GST_IS_TRACER_FACTORY (feature)) { n_print (" %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), g_type_name (G_OBJECT_TYPE (feature))); num_tracers++; } else if (feature) { n_print (" %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), g_type_name (G_OBJECT_TYPE (feature))); num_other++; } num_features++; features = g_list_next (features); } gst_plugin_feature_list_free (origlist); n_print ("\n"); n_print (" %d features:\n", num_features); if (num_elements > 0) n_print (" +-- %d elements\n", num_elements); if (num_typefinders > 0) n_print (" +-- %d typefinders\n", num_typefinders); if (num_devproviders > 0) n_print (" +-- %d device providers\n", num_devproviders); if (num_tracers > 0) n_print (" +-- %d tracers\n", num_tracers); if (num_other > 0) n_print (" +-- %d other objects\n", num_other); n_print ("\n"); }
// 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; }