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; }
/** * 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; }
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; }
/** * 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; }
// 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; }
/** * 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; }