sys/dshowdecwrapper/: Prefer known-good filters, create directly by GUID if possible...
authorMichael Smith <msmith@xiph.org>
Wed, 24 Sep 2008 17:21:41 +0000 (17:21 +0000)
committerMichael Smith <msmith@xiph.org>
Wed, 24 Sep 2008 17:21:41 +0000 (17:21 +0000)
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.

ChangeLog
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

index a7a8ae0..1f34e0f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-09-24  Michael Smith <msmith@songbirdnest.com>
+
+       * 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.
+
 2008-09-23  Wim Taymans  <wim.taymans@collabora.co.uk>
 
        * gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_insert),
index dd2d98d..c2efec1 100644 (file)
@@ -49,6 +49,8 @@
 
 #include "gstdshowaudiodec.h"
 #include <mmreg.h>
+#include <dmoreg.h>
+#include <wmcodecdsp.h>
 
 GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug);
 #define GST_CAT_DEFAULT dshowaudiodec_debug
@@ -81,45 +83,76 @@ static gboolean gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec, GstCaps
     { fourcc , 0x0000, 0x0010, \
     { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }}
 
+/* WMA we should always use the DMO */
+static PreferredFilter preferred_wma_filters[] = {
+  {&CLSID_CWMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER},
+  {0}
+};
+
+/* Prefer the Vista (DMO) decoder if present, otherwise the XP
+ * decoder (not a DMO), otherwise fallback to highest-merit */
+static const GUID CLSID_XP_MP3_DECODER = {0x38BE3000, 0xDBF4, 0x11D0,
+   {0x86,0x0E,0x00,0xA0,0x24,0xCF,0xEF,0x6D}};
+static PreferredFilter preferred_mp3_filters[] = {
+  {&CLSID_CMP3DecMediaObject, &DMOCATEGORY_AUDIO_DECODER},
+  {&CLSID_XP_MP3_DECODER},
+  {0}
+};
+
+/* MPEG 1/2: use the MPEG Audio Decoder filter */
+static const GUID CLSID_WINDOWS_MPEG_AUDIO_DECODER = 
+  {0x4A2286E0, 0x7BEF, 0x11CE, 
+   {0x9B, 0xD9, 0x00, 0x00, 0xE2, 0x02, 0x59, 0x9C}};
+static PreferredFilter preferred_mpegaudio_filters[] = {
+  {&CLSID_WINDOWS_MPEG_AUDIO_DECODER},
+  {0}
+};
+
 static const AudioCodecEntry audio_dec_codecs[] = {
-  {"dshowadec_wma1",
-   "Windows Media Audio 7",
+  {"dshowadec_wma1", "Windows Media Audio 7",
    WAVE_FORMAT_MSAUDIO1,
-   "audio/x-wma, wmaversion = (int) 1"},
-  {"dshowadec_wma2",
-   "Windows Media Audio 8",
+   "audio/x-wma, wmaversion = (int) 1",
+   preferred_wma_filters},
+
+  {"dshowadec_wma2", "Windows Media Audio 8",
    WAVE_FORMAT_WMAUDIO2,
-   "audio/x-wma, wmaversion = (int) 2"},
-  {"dshowadec_wma3",
-   "Windows Media Audio 9 Professional",
+   "audio/x-wma, wmaversion = (int) 2",
+   preferred_wma_filters},
+
+  {"dshowadec_wma3", "Windows Media Audio 9 Professional",
    WAVE_FORMAT_WMAUDIO3,
-   "audio/x-wma, wmaversion = (int) 3"},
-  {"dshowadec_wma4",
-   "Windows Media Audio 9 Lossless",
+   "audio/x-wma, wmaversion = (int) 3",
+   preferred_wma_filters},
+
+  {"dshowadec_wma4", "Windows Media Audio 9 Lossless",
    WAVE_FORMAT_WMAUDIO_LOSSLESS,
-   "audio/x-wma, wmaversion = (int) 4"},
-  {"dshowadec_wms",
-   "Windows Media Audio Voice v9",
+   "audio/x-wma, wmaversion = (int) 4",
+   preferred_wma_filters},
+
+  {"dshowadec_wms", "Windows Media Audio Voice v9",
    WAVE_FORMAT_WMAVOICE9,
-   "audio/x-wms"},
-  {"dshowadec_mp3",
-   "MPEG Layer 3 Audio",
+   "audio/x-wms",
+   preferred_wma_filters},
+
+  {"dshowadec_mp3", "MPEG Layer 3 Audio",
    WAVE_FORMAT_MPEGLAYER3,
    "audio/mpeg, "
        "mpegversion = (int) 1, "
        "layer = (int)3, "
        "rate = (int) [ 8000, 48000 ], "
        "channels = (int) [ 1, 2 ], "
-       "parsed= (boolean) true"},
-  {"dshowadec_mpeg_1_2",
-   "MPEG Layer 1,2 Audio",
+       "parsed= (boolean) true",
+   preferred_mp3_filters},
+
+  {"dshowadec_mpeg_1_2", "MPEG Layer 1,2 Audio",
    WAVE_FORMAT_MPEG,
    "audio/mpeg, "
        "mpegversion = (int) 1, "
        "layer = (int) [ 1, 2 ], "
        "rate = (int) [ 8000, 48000 ], "
        "channels = (int) [ 1, 2 ], "
-       "parsed= (boolean) true"},
+       "parsed= (boolean) true",
+   preferred_mpegaudio_filters},
 };
 
 HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
@@ -230,7 +263,7 @@ HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
 done:
   return S_OK;
 }
-    
+
 HRESULT AudioFakeSink::CheckMediaType(const CMediaType *pmt)
 {
   if(pmt != NULL)
@@ -921,11 +954,12 @@ gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec * adec)
   adec->fakesrc->AddRef();
 
   /* create decoder filter */
-  if (!gst_dshow_find_filter (MEDIATYPE_Audio,
+  adec->decfilter = gst_dshow_find_filter (MEDIATYPE_Audio,
           insubtype,
           MEDIATYPE_Audio,
           outsubtype,
-          NULL, &adec->decfilter)) {
+          klass->entry->preferred_filters);
+  if (adec->decfilter == NULL) {
     GST_ELEMENT_ERROR (adec, STREAM, FAILED,
         ("Can't create an instance of the decoder filter"), (NULL));
     goto error;
@@ -1038,21 +1072,22 @@ dshow_adec_register (GstPlugin * plugin)
   hr = CoInitialize(0);
   for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (AudioCodecEntry); i++) {
     GType type;
-
+    CComPtr<IBaseFilter> filter;
     GUID insubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (audio_dec_codecs[i].format);
     GUID outsubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM);
-    if (gst_dshow_find_filter (MEDIATYPE_Audio,
+
+    filter = gst_dshow_find_filter (MEDIATYPE_Audio,
             insubtype,
             MEDIATYPE_Audio,
             outsubtype,
-            NULL, NULL)) {
+            audio_dec_codecs[i].preferred_filters);
 
-      GST_CAT_DEBUG (dshowaudiodec_debug, "Registering %s",
-          audio_dec_codecs[i].element_name);
+    if (filter) 
+    {
+      GST_DEBUG ("Registering %s", audio_dec_codecs[i].element_name);
 
       tmp = &audio_dec_codecs[i];
-      type =
-          g_type_register_static (GST_TYPE_ELEMENT,
+      type = g_type_register_static (GST_TYPE_ELEMENT,
           audio_dec_codecs[i].element_name, &info, (GTypeFlags)0);
       if (!gst_element_register (plugin, audio_dec_codecs[i].element_name,
               GST_RANK_PRIMARY, type)) {
@@ -1060,10 +1095,11 @@ dshow_adec_register (GstPlugin * plugin)
       }
       GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s",
           audio_dec_codecs[i].element_name);
-    } else {
-      GST_CAT_DEBUG (dshowaudiodec_debug,
-          "Element %s not registered (the format is not supported by the system)",
-          audio_dec_codecs[i].element_name);
+    }
+    else {
+      GST_DEBUG ("Element %s not registered "
+                 "(the format is not supported by the system)",
+                 audio_dec_codecs[i].element_name);
     }
   }
 
index 6301b31..37f1607 100644 (file)
@@ -60,6 +60,7 @@ typedef struct {
   gchar *element_longname;  /* Description string for element */
   gint32 format;            /* WAVEFORMATEX format */
   gchar *sinkcaps;          /* GStreamer caps of input format */
+  PreferredFilter *preferred_filters; /* NULL-terminated list of preferred filters */
 } AudioCodecEntry;
 
 #define GST_TYPE_DSHOWAUDIODEC               (gst_dshowaudiodec_get_type())
index 8095c36..170e9ed 100644 (file)
@@ -46,14 +46,33 @@ HRESULT FakeOutputPin::GetMediaType(int iPosition,
   
   return VFW_S_NO_MORE_ITEMS;
 }
+#if 0
+#define GUID_FORMAT "0x%.8x 0x%.4x 0x%.4x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x"
+#define GUID_ARGS(g) g.Data1, g.Data2, g.Data3, \
+  g.Data4[0], g.Data4[1], g.Data4[2], g.Data4[3], \
+  g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]
+
+static void printMediaType (AM_MEDIA_TYPE *mt)
+{
+  GST_DEBUG (":: majortype: "GUID_FORMAT, GUID_ARGS(mt->majortype));
+  GST_DEBUG (":: subtype: "GUID_FORMAT, GUID_ARGS(mt->subtype));
+
+  GST_DEBUG (":: bFixedSizeSamples: %d", mt->bFixedSizeSamples);
+  GST_DEBUG (":: bTemporalCompression: %d", mt->bTemporalCompression);
+  GST_DEBUG (":: cbFormat: %d", mt->cbFormat);
+  GST_DEBUG (":: formattype: %x", mt->formattype);
+  GST_DEBUG (":: lSampleSize: %lu", mt->lSampleSize);
+  GST_DEBUG (":: pbFormat: %p", mt->pbFormat);
+}
+#endif
 
 HRESULT FakeOutputPin::CheckMediaType(const CMediaType *pmt)
 {
-    if (m_MediaType == *pmt) {
-        return S_OK;
-    }
+  if (m_MediaType == *pmt) {
+    return S_OK;
+  }
 
-    return S_FALSE;
+  return S_FALSE;
 }
 
 HRESULT FakeOutputPin::DecideBufferSize (IMemAllocator *pAlloc, 
index df2f65d..ca1728b 100644 (file)
@@ -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;
 }
 
index 0b5ca90..80299fb 100644 (file)
 
 #include <glib.h>
 
+typedef struct {
+  const GUID *filter_guid;  /* The filter GUID, or DMO GUID */
+  const GUID *dmo_category; /* If non-NULL, the filter is a DMO of this
+                               category */
+} PreferredFilter;
+
 /* get a pin from directshow filter */
 IPin *gst_dshow_get_pin_from_filter (IBaseFilter *filter, PIN_DIRECTION pindir);
 
 /* find and return a filter according to the input and output types */
-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);
 #endif /* _GST_DSHOW_UTIL_H_ */
index 80a1a19..e16de6f 100644 (file)
@@ -48,6 +48,8 @@
 #endif
 
 #include <atlbase.h>
+#include <dmoreg.h>
+#include <wmcodecdsp.h>
 
 #include "gstdshowvideodec.h"
 
@@ -107,140 +109,168 @@ static gboolean gst_dshowvideodec_get_filter_output_format (GstDshowVideoDec *
 #define GUID_MEDIASUBTYPE_RGB32   {0xe436eb7e, 0x524f, 0x11ce, { 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 }}
 #define GUID_MEDIASUBTYPE_RGB565  {0xe436eb7b, 0x524f, 0x11ce, { 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 }}
 
+/* WMV always uses the WMV DMO */
+static PreferredFilter preferred_wmv_filters[] = {
+  {&CLSID_CWMVDecMediaObject, &DMOCATEGORY_VIDEO_DECODER}, {0}
+};
+
+static const GUID CLSID_AVI_DECOMPRESSOR = 
+  {0xCF49D4E0, 0x1115, 0x11CE, 
+   {0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
+static PreferredFilter preferred_cinepack_filters[] = {
+  {&CLSID_AVI_DECOMPRESSOR}, {0}
+};
+
+/* Various MPEG-4 video variants */
+// MPG4, mpg4, MP42, mp42
+static PreferredFilter preferred_mpeg4_filters[] = {
+  {&CLSID_CMpeg4DecMediaObject, &DMOCATEGORY_VIDEO_DECODER}, {0}};
+// MP4S, mp4s, M4S2, m4s2
+static PreferredFilter preferred_mp4s_filters[] = {
+  {&CLSID_CMpeg4sDecMediaObject, &DMOCATEGORY_VIDEO_DECODER}, {0}};
+// MP43, mp43
+static PreferredFilter preferred_mp43_filters[] = {
+  {&CLSID_CMpeg43DecMediaObject, &DMOCATEGORY_VIDEO_DECODER}, {0}};
+
+static const GUID CLSID_MPEG_VIDEO_DECODER = 
+  {0xFEB50740, 0x7BEF, 0x11CE, 
+   {0x9B, 0xD9, 0x00, 0x00, 0xE2, 0x02, 0x59, 0x9C}};
+static PreferredFilter preferred_mpeg1_filters[] = {
+  {&CLSID_MPEG_VIDEO_DECODER}, {0}
+};
+
+
 /* video codecs array */
 static const VideoCodecEntry video_dec_codecs[] = {
-  {"dshowvdec_wmv1",
-        "Windows Media Video 7",
-        "DMO",
-        GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV1,
-        "video/x-wmv, wmvversion = (int) 1",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_wmv2",
-        "Windows Media Video 8",
-        "DMO",
-        GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV2,
-        "video/x-wmv, wmvversion = (int) 2",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_wmv3",
-        "Windows Media Video 9",
-        "DMO",
-        GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV3,
-        "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMV3",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_wmvp",
-        "Windows Media Video 9 Image",
-        "DMO",
-        GST_MAKE_FOURCC ('W', 'M', 'V', 'P'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVP,
-        "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVP",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_wmva",
-        "Windows Media Video 9 Advanced",
-        "DMO",
-        GST_MAKE_FOURCC ('W', 'M', 'V', 'A'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVA,
-        "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVA",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_cinepak",
-        "Cinepack",
-        "AVI Decompressor",
-        0x64697663,
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_CVID,
-        "video/x-cinepak",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_RGB32,
-      "video/x-raw-rgb, bpp=(int)32, depth=(int)24, "
-        "endianness=(int)4321, red_mask=(int)65280, "
-        "green_mask=(int)16711680, blue_mask=(int)-16777216"},
-  {"dshowvdec_msmpeg41",
-        "Microsoft ISO MPEG-4 version 1",
-        "DMO",
-        GST_MAKE_FOURCC ('M', 'P', '4', 'S'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP4S,
-        "video/x-msmpeg, msmpegversion=(int)41",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_msmpeg42",
-        "Microsoft ISO MPEG-4 version 2",
-        "DMO",
-        GST_MAKE_FOURCC ('M', 'P', '4', '2'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP42,
-        "video/x-msmpeg, msmpegversion=(int)42",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_msmpeg43",
-        "Microsoft ISO MPEG-4 version 3",
-        "DMO",
-        GST_MAKE_FOURCC ('M', 'P', '4', '3'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP43,
-        "video/x-msmpeg, msmpegversion=(int)43",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_msmpeg4",
-        "Microsoft ISO MPEG-4 version 1.1",
-        "DMO",
-        GST_MAKE_FOURCC ('M', '4', 'S', '2'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_M4S2,
-        "video/x-msmpeg, msmpegversion=(int)4",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
+  {"dshowvdec_wmv1", "Windows Media Video 7",
+   GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV1,
+   "video/x-wmv, wmvversion = (int) 1",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_wmv_filters},
+
+  {"dshowvdec_wmv2", "Windows Media Video 8",
+   GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV2,
+   "video/x-wmv, wmvversion = (int) 2",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_wmv_filters},
+
+  {"dshowvdec_wmv3", "Windows Media Video 9",
+   GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV3,
+   "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMV3",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_wmv_filters},
+
+  {"dshowvdec_wmvp", "Windows Media Video 9 Image",
+   GST_MAKE_FOURCC ('W', 'M', 'V', 'P'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVP,
+   "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVP",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_wmv_filters},
+
+  {"dshowvdec_wmva", "Windows Media Video 9 Advanced",
+   GST_MAKE_FOURCC ('W', 'M', 'V', 'A'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVA,
+   "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVA",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_wmv_filters},
+
+  {"dshowvdec_cinepak", "Cinepack",
+   0x64697663,
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_CVID,
+   "video/x-cinepak",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_RGB32,
+   "video/x-raw-rgb, bpp=(int)32, depth=(int)24, "
+       "endianness=(int)4321, red_mask=(int)65280, "
+       "green_mask=(int)16711680, blue_mask=(int)-16777216",
+   preferred_cinepack_filters},
+
+  {"dshowvdec_msmpeg41", "Microsoft ISO MPEG-4 version 1",
+   GST_MAKE_FOURCC ('M', 'P', '4', 'S'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP4S,
+   "video/x-msmpeg, msmpegversion=(int)41",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mp4s_filters},
+
+  {"dshowvdec_msmpeg42", "Microsoft ISO MPEG-4 version 2",
+   GST_MAKE_FOURCC ('M', 'P', '4', '2'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP42,
+   "video/x-msmpeg, msmpegversion=(int)42",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mpeg4_filters},
+
+  {"dshowvdec_msmpeg43", "Microsoft ISO MPEG-4 version 3",
+   GST_MAKE_FOURCC ('M', 'P', '4', '3'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP43,
+   "video/x-msmpeg, msmpegversion=(int)43",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mp43_filters},
+
+  {"dshowvdec_msmpeg4", "Microsoft ISO MPEG-4 version 1.1",
+   GST_MAKE_FOURCC ('M', '4', 'S', '2'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_M4S2,
+   "video/x-msmpeg, msmpegversion=(int)4",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mp4s_filters},
+
   {"dshowvdec_mpeg1",
-        "MPEG-1 Video",
-        "MPEG Video Decoder",
-        GST_MAKE_FOURCC ('M', 'P', 'E', 'G'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPEG1Payload,
-        "video/mpeg, mpegversion= (int) 1, "
-        "parsed= (boolean) true, " "systemstream= (boolean) false",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_xvid",
-        "XVID Video",
-        "ffdshow",
-        GST_MAKE_FOURCC ('X', 'V', 'I', 'D'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_XVID,
-        "video/x-xvid",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_divx5",
-        "DIVX 5.0 Video",
-        "ffdshow",
-        GST_MAKE_FOURCC ('D', 'X', '5', '0'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DX50,
-        "video/x-divx, divxversion=(int)5",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_divx4",
-        "DIVX 4.0 Video",
-        "ffdshow",
-        GST_MAKE_FOURCC ('D', 'I', 'V', 'X'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIVX,
-        "video/x-divx, divxversion=(int)4",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"},
-  {"dshowvdec_divx3",
-        "DIVX 3.0 Video",
-        "ffdshow",
-        GST_MAKE_FOURCC ('D', 'I', 'V', '3'),
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIV3,
-        "video/x-divx, divxversion=(int)3",
-        GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-      "video/x-raw-yuv, format=(fourcc)YUY2"}
-  /*,
-     { "dshowvdec_mpeg4",
-     "DMO",
-     GST_MAKE_FOURCC ('M', 'P', 'G', '4'),
-     GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPG4,
-     "video/mpeg, msmpegversion=(int)4",
-     GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
-     "video/x-raw-yuv, format=(fourcc)YUY2"
-     } */
+   "MPEG-1 Video",
+   GST_MAKE_FOURCC ('M', 'P', 'E', 'G'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPEG1Payload,
+   "video/mpeg, mpegversion= (int) 1, "
+       "parsed= (boolean) true, " "systemstream= (boolean) false",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mpeg1_filters},
+   
+  {"dshowvdec_mpeg4", "MPEG-4 Video",
+   GST_MAKE_FOURCC ('M', 'P', 'G', '4'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPG4,
+   "video/mpeg, msmpegversion=(int)4",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2",
+   preferred_mpeg4_filters},
+
+  /* The rest of these have no preferred filter; windows doesn't come
+   * with anything appropriate */
+  {"dshowvdec_xvid", "XVID Video",
+   GST_MAKE_FOURCC ('X', 'V', 'I', 'D'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_XVID,
+   "video/x-xvid",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2"},
+
+  {"dshowvdec_divx5", "DIVX 5.0 Video",
+   GST_MAKE_FOURCC ('D', 'X', '5', '0'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DX50,
+   "video/x-divx, divxversion=(int)5",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2"},
+
+  {"dshowvdec_divx4", "DIVX 4.0 Video",
+   GST_MAKE_FOURCC ('D', 'I', 'V', 'X'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIVX,
+   "video/x-divx, divxversion=(int)4",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2"},
+
+  {"dshowvdec_divx3", "DIVX 3.0 Video",
+   GST_MAKE_FOURCC ('D', 'I', 'V', '3'),
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIV3,
+   "video/x-divx, divxversion=(int)3",
+   GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
+   "video/x-raw-yuv, format=(fourcc)YUY2"}
 };
 
 HRESULT VideoFakeSink::DoRenderSample(IMediaSample *pMediaSample)
@@ -975,11 +1005,13 @@ gst_dshowvideodec_create_graph_and_filters (GstDshowVideoDec * vdec)
   }
 
   /* search a decoder filter and create it */
-  if (!gst_dshow_find_filter (klass->entry->input_majortype,
+  vdec->decfilter = gst_dshow_find_filter (
+          klass->entry->input_majortype,
           klass->entry->input_subtype,
           klass->entry->output_majortype,
           klass->entry->output_subtype,
-          klass->entry->preferred_filter_substring, &vdec->decfilter)) {
+          klass->entry->preferred_filters);
+  if (vdec->decfilter == NULL) {
     GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
             "of the decoder filter"), (NULL));
     goto error;
@@ -1136,15 +1168,17 @@ dshow_vdec_register (GstPlugin * plugin)
 
   for (i = 0; i < sizeof (video_dec_codecs) / sizeof (VideoCodecEntry); i++) {
     GType type;
+    CComPtr<IBaseFilter> filter;
 
-    if (gst_dshow_find_filter (video_dec_codecs[i].input_majortype,
+    filter = gst_dshow_find_filter (
+            video_dec_codecs[i].input_majortype,
             video_dec_codecs[i].input_subtype,
             video_dec_codecs[i].output_majortype,
             video_dec_codecs[i].output_subtype,
-            video_dec_codecs[i].preferred_filter_substring, NULL)) {
+            video_dec_codecs[i].preferred_filters);
+    if (filter != NULL) {
 
-      GST_CAT_DEBUG (dshowvideodec_debug, "Registering %s",
-          video_dec_codecs[i].element_name);
+      GST_DEBUG ("Registering %s", video_dec_codecs[i].element_name);
 
       tmp = &video_dec_codecs[i];
       type =
@@ -1154,12 +1188,11 @@ dshow_vdec_register (GstPlugin * plugin)
               GST_RANK_PRIMARY, type)) {
         return FALSE;
       }
-      GST_CAT_DEBUG (dshowvideodec_debug, "Registered %s",
-          video_dec_codecs[i].element_name);
+      GST_DEBUG ("Registered %s", video_dec_codecs[i].element_name);
     } else {
-      GST_CAT_DEBUG (dshowvideodec_debug,
-          "Element %s not registered (the format is not supported by the system)",
-          video_dec_codecs[i].element_name);
+      GST_DEBUG ("Element %s not registered "
+        "(the format is not supported by the system)",
+        video_dec_codecs[i].element_name);
     }
   }
 
index 29953d8..66bb002 100644 (file)
@@ -55,7 +55,6 @@ G_BEGIN_DECLS
 typedef struct {
   gchar *element_name;      /* The gst element factory name */
   gchar *element_longname;  /* Description string for element */
-  gchar *preferred_filter_substring; /* TODO: Remove this? */
   gint32 format;            /* ??? */
   GUID input_majortype;
   GUID input_subtype;
@@ -63,6 +62,7 @@ typedef struct {
   GUID output_majortype;
   GUID output_subtype;
   gchar *srccaps;
+  PreferredFilter *preferred_filters;
 } VideoCodecEntry;
 
 #define GST_TYPE_DSHOWVIDEODEC               (gst_dshowvideodec_get_type())