diff options
author | Michael Smith <msmith@xiph.org> | 2008-09-24 17:21:41 +0000 |
---|---|---|
committer | Michael Smith <msmith@xiph.org> | 2008-09-24 17:21:41 +0000 |
commit | a51c4c16b25416ca55ddca56a14c89be63782a90 (patch) | |
tree | a954d27933478ef5c400881dc7c8f815f6884892 /sys/dshowdecwrapper/gstdshowutil.cpp | |
parent | 5a97c0d534f49c7732b93deb24c5b05473dece68 (diff) | |
download | gst-plugins-bad-a51c4c16b25416ca55ddca56a14c89be63782a90.tar.gz gst-plugins-bad-a51c4c16b25416ca55ddca56a14c89be63782a90.tar.bz2 gst-plugins-bad-a51c4c16b25416ca55ddca56a14c89be63782a90.zip |
sys/dshowdecwrapper/: Prefer known-good filters, create directly by GUID if possible, fall back to creating highest-m...
Original commit message from CVS:
* sys/dshowdecwrapper/gstdshowaudiodec.cpp:
* sys/dshowdecwrapper/gstdshowaudiodec.h:
* sys/dshowdecwrapper/gstdshowfakesrc.cpp:
* sys/dshowdecwrapper/gstdshowutil.cpp:
* sys/dshowdecwrapper/gstdshowutil.h:
* sys/dshowdecwrapper/gstdshowvideodec.cpp:
* sys/dshowdecwrapper/gstdshowvideodec.h:
Prefer known-good filters, create directly by GUID if possible,
fall back to creating highest-merit filter otherwise.
Fixes playback with random dshow filters installed in some
cases.
Diffstat (limited to 'sys/dshowdecwrapper/gstdshowutil.cpp')
-rw-r--r-- | sys/dshowdecwrapper/gstdshowutil.cpp | 153 |
1 files changed, 67 insertions, 86 deletions
diff --git a/sys/dshowdecwrapper/gstdshowutil.cpp b/sys/dshowdecwrapper/gstdshowutil.cpp index df2f65d1..ca1728be 100644 --- a/sys/dshowdecwrapper/gstdshowutil.cpp +++ b/sys/dshowdecwrapper/gstdshowutil.cpp @@ -20,6 +20,8 @@ */ #include <atlbase.h> +#include <dmodshow.h> +#include <dmoreg.h> #include "gstdshowutil.h" #include "gstdshowfakesrc.h" @@ -49,108 +51,87 @@ gst_dshow_get_pin_from_filter (IBaseFilter *filter, PIN_DIRECTION pindir) return NULL; } -gboolean gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype, - CLSID output_majortype, CLSID output_subtype, - gchar * prefered_filter_name, IBaseFilter **filter) +IBaseFilter * +gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype, + CLSID output_majortype, CLSID output_subtype, + PreferredFilter *preferred_filters) { - gboolean ret = FALSE; HRESULT hres; - GUID arrayInTypes[2]; - GUID arrayOutTypes[2]; - IFilterMapper2 *mapper = NULL; - IEnumMoniker *enum_moniker = NULL; - IMoniker *moniker = NULL; + GUID inTypes[2]; + GUID outTypes[2]; + CComPtr<IFilterMapper2> mapper; + CComPtr<IEnumMoniker> enum_moniker; + CComPtr<IMoniker> moniker; ULONG fetched; - gchar *prefered_filter_upper = NULL; - gboolean exit = FALSE; - - /* initialize output parameter */ - if (filter) - *filter = NULL; + IBaseFilter *filter; + + /* First, see if any of our preferred filters is available. + * If not, we fall back to the highest-ranked installed filter */ + if (preferred_filters) { + while (preferred_filters->filter_guid) + { + /* If the filter is a DMO, we need to do this a bit differently */ + if (preferred_filters->dmo_category) + { + CComPtr<IDMOWrapperFilter> wrapper; + + hres = CoCreateInstance (CLSID_DMOWrapperFilter, NULL, + CLSCTX_INPROC, + IID_IBaseFilter, (void **)&filter); + if (SUCCEEDED(hres)) { + hres = filter->QueryInterface (&wrapper); + if (SUCCEEDED(hres)) { + hres = wrapper->Init (*preferred_filters->filter_guid, + *preferred_filters->dmo_category); + if (SUCCEEDED(hres)) + return filter; + } + filter->Release(); + } + } + else + { + hres = CoCreateInstance (*preferred_filters->filter_guid, + NULL, CLSCTX_INPROC, + IID_IBaseFilter, (void **)&filter); + if (SUCCEEDED(hres)) + return filter; + } - /* create a private copy of prefered filter substring in upper case */ - if (prefered_filter_name) { - prefered_filter_upper = g_strdup (prefered_filter_name); - strupr (prefered_filter_upper); + /* Continue to the next filter */ + preferred_filters++; + } } hres = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **) &mapper); if (FAILED(hres)) - goto clean; + return NULL; - memcpy(&arrayInTypes[0], &input_majortype, sizeof (CLSID)); - memcpy(&arrayInTypes[1], &input_subtype, sizeof (CLSID)); - memcpy(&arrayOutTypes[0], &output_majortype, sizeof (CLSID)); - memcpy(&arrayOutTypes[1], &output_subtype, sizeof (CLSID)); - - hres = mapper->EnumMatchingFilters (&enum_moniker, 0, FALSE, MERIT_DO_NOT_USE+1, - TRUE, 1, arrayInTypes, NULL, NULL, FALSE, - TRUE, 1, arrayOutTypes, NULL, NULL); + inTypes[0] = input_majortype; + inTypes[1] = input_subtype; + outTypes[0] = output_majortype; + outTypes[1] = output_subtype; + + hres = mapper->EnumMatchingFilters (&enum_moniker, 0, + FALSE, MERIT_DO_NOT_USE+1, + TRUE, 1, inTypes, NULL, NULL, FALSE, + TRUE, 1, outTypes, NULL, NULL); if (FAILED(hres)) - goto clean; + return NULL; enum_moniker->Reset (); - - while(hres = enum_moniker->Next (1, &moniker, &fetched),hres == S_OK - && !exit) { - IBaseFilter *filter_temp = NULL; - IPropertyBag *property_bag = NULL; - gchar * friendly_name = NULL; - - hres = moniker->BindToStorage (NULL, NULL, IID_IPropertyBag, (void **)&property_bag); - if(SUCCEEDED(hres) && property_bag) { - VARIANT varFriendlyName; - VariantInit (&varFriendlyName); - - hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL); - if(hres == S_OK && varFriendlyName.bstrVal) { - friendly_name = g_utf16_to_utf8((const gunichar2*)varFriendlyName.bstrVal, - wcslen(varFriendlyName.bstrVal), NULL, NULL, NULL); - if (friendly_name) - strupr (friendly_name); - SysFreeString (varFriendlyName.bstrVal); - } - property_bag->Release (); - } - - hres = moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&filter_temp); - if(SUCCEEDED(hres) && filter_temp) { - ret = TRUE; - if (filter) { - if (*filter) - (*filter)->Release (); - - *filter = filter_temp; - (*filter)->AddRef (); - - if (prefered_filter_upper && friendly_name && - strstr(friendly_name, prefered_filter_upper)) - exit = TRUE; - } - /* if we just want to know if the formats are supported OR - if we don't care about what will be the filter used - => we can stop enumeration */ - if (!filter || !prefered_filter_upper) - exit = TRUE; - - filter_temp->Release (); + while(enum_moniker->Next (1, &moniker, &fetched) == S_OK) + { + hres = moniker->BindToObject(NULL, NULL, + IID_IBaseFilter, (void**)&filter); + if(SUCCEEDED(hres)) { + return filter; } - - if (friendly_name) - g_free (friendly_name); - moniker->Release (); + moniker.Release (); } -clean: - if (prefered_filter_upper) - g_free (prefered_filter_upper); - if (enum_moniker) - enum_moniker->Release (); - if (mapper) - mapper->Release (); - - return ret; + return NULL; } |