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.
This commit is contained in:
Michael Smith 2008-09-24 17:21:41 +00:00
parent 5a97c0d534
commit a51c4c16b2
8 changed files with 360 additions and 270 deletions

View file

@ -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> 2008-09-23 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_insert), * gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_insert),

View file

@ -49,6 +49,8 @@
#include "gstdshowaudiodec.h" #include "gstdshowaudiodec.h"
#include <mmreg.h> #include <mmreg.h>
#include <dmoreg.h>
#include <wmcodecdsp.h>
GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug); GST_DEBUG_CATEGORY_STATIC (dshowaudiodec_debug);
#define GST_CAT_DEFAULT dshowaudiodec_debug #define GST_CAT_DEFAULT dshowaudiodec_debug
@ -81,45 +83,76 @@ static gboolean gst_dshowaudiodec_setup_graph (GstDshowAudioDec * adec, GstCaps
{ fourcc , 0x0000, 0x0010, \ { fourcc , 0x0000, 0x0010, \
{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }} { 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[] = { static const AudioCodecEntry audio_dec_codecs[] = {
{"dshowadec_wma1", {"dshowadec_wma1", "Windows Media Audio 7",
"Windows Media Audio 7",
WAVE_FORMAT_MSAUDIO1, WAVE_FORMAT_MSAUDIO1,
"audio/x-wma, wmaversion = (int) 1"}, "audio/x-wma, wmaversion = (int) 1",
{"dshowadec_wma2", preferred_wma_filters},
"Windows Media Audio 8",
{"dshowadec_wma2", "Windows Media Audio 8",
WAVE_FORMAT_WMAUDIO2, WAVE_FORMAT_WMAUDIO2,
"audio/x-wma, wmaversion = (int) 2"}, "audio/x-wma, wmaversion = (int) 2",
{"dshowadec_wma3", preferred_wma_filters},
"Windows Media Audio 9 Professional",
{"dshowadec_wma3", "Windows Media Audio 9 Professional",
WAVE_FORMAT_WMAUDIO3, WAVE_FORMAT_WMAUDIO3,
"audio/x-wma, wmaversion = (int) 3"}, "audio/x-wma, wmaversion = (int) 3",
{"dshowadec_wma4", preferred_wma_filters},
"Windows Media Audio 9 Lossless",
{"dshowadec_wma4", "Windows Media Audio 9 Lossless",
WAVE_FORMAT_WMAUDIO_LOSSLESS, WAVE_FORMAT_WMAUDIO_LOSSLESS,
"audio/x-wma, wmaversion = (int) 4"}, "audio/x-wma, wmaversion = (int) 4",
{"dshowadec_wms", preferred_wma_filters},
"Windows Media Audio Voice v9",
{"dshowadec_wms", "Windows Media Audio Voice v9",
WAVE_FORMAT_WMAVOICE9, WAVE_FORMAT_WMAVOICE9,
"audio/x-wms"}, "audio/x-wms",
{"dshowadec_mp3", preferred_wma_filters},
"MPEG Layer 3 Audio",
{"dshowadec_mp3", "MPEG Layer 3 Audio",
WAVE_FORMAT_MPEGLAYER3, WAVE_FORMAT_MPEGLAYER3,
"audio/mpeg, " "audio/mpeg, "
"mpegversion = (int) 1, " "mpegversion = (int) 1, "
"layer = (int)3, " "layer = (int)3, "
"rate = (int) [ 8000, 48000 ], " "rate = (int) [ 8000, 48000 ], "
"channels = (int) [ 1, 2 ], " "channels = (int) [ 1, 2 ], "
"parsed= (boolean) true"}, "parsed= (boolean) true",
{"dshowadec_mpeg_1_2", preferred_mp3_filters},
"MPEG Layer 1,2 Audio",
{"dshowadec_mpeg_1_2", "MPEG Layer 1,2 Audio",
WAVE_FORMAT_MPEG, WAVE_FORMAT_MPEG,
"audio/mpeg, " "audio/mpeg, "
"mpegversion = (int) 1, " "mpegversion = (int) 1, "
"layer = (int) [ 1, 2 ], " "layer = (int) [ 1, 2 ], "
"rate = (int) [ 8000, 48000 ], " "rate = (int) [ 8000, 48000 ], "
"channels = (int) [ 1, 2 ], " "channels = (int) [ 1, 2 ], "
"parsed= (boolean) true"}, "parsed= (boolean) true",
preferred_mpegaudio_filters},
}; };
HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample) HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
@ -921,11 +954,12 @@ gst_dshowaudiodec_create_graph_and_filters (GstDshowAudioDec * adec)
adec->fakesrc->AddRef(); adec->fakesrc->AddRef();
/* create decoder filter */ /* create decoder filter */
if (!gst_dshow_find_filter (MEDIATYPE_Audio, adec->decfilter = gst_dshow_find_filter (MEDIATYPE_Audio,
insubtype, insubtype,
MEDIATYPE_Audio, MEDIATYPE_Audio,
outsubtype, outsubtype,
NULL, &adec->decfilter)) { klass->entry->preferred_filters);
if (adec->decfilter == NULL) {
GST_ELEMENT_ERROR (adec, STREAM, FAILED, GST_ELEMENT_ERROR (adec, STREAM, FAILED,
("Can't create an instance of the decoder filter"), (NULL)); ("Can't create an instance of the decoder filter"), (NULL));
goto error; goto error;
@ -1038,21 +1072,22 @@ dshow_adec_register (GstPlugin * plugin)
hr = CoInitialize(0); hr = CoInitialize(0);
for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (AudioCodecEntry); i++) { for (i = 0; i < sizeof (audio_dec_codecs) / sizeof (AudioCodecEntry); i++) {
GType type; GType type;
CComPtr<IBaseFilter> filter;
GUID insubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (audio_dec_codecs[i].format); GUID insubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (audio_dec_codecs[i].format);
GUID outsubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM); GUID outsubtype = GUID_MEDIASUBTYPE_FROM_FOURCC (WAVE_FORMAT_PCM);
if (gst_dshow_find_filter (MEDIATYPE_Audio,
filter = gst_dshow_find_filter (MEDIATYPE_Audio,
insubtype, insubtype,
MEDIATYPE_Audio, MEDIATYPE_Audio,
outsubtype, outsubtype,
NULL, NULL)) { audio_dec_codecs[i].preferred_filters);
GST_CAT_DEBUG (dshowaudiodec_debug, "Registering %s", if (filter)
audio_dec_codecs[i].element_name); {
GST_DEBUG ("Registering %s", audio_dec_codecs[i].element_name);
tmp = &audio_dec_codecs[i]; tmp = &audio_dec_codecs[i];
type = type = g_type_register_static (GST_TYPE_ELEMENT,
g_type_register_static (GST_TYPE_ELEMENT,
audio_dec_codecs[i].element_name, &info, (GTypeFlags)0); audio_dec_codecs[i].element_name, &info, (GTypeFlags)0);
if (!gst_element_register (plugin, audio_dec_codecs[i].element_name, if (!gst_element_register (plugin, audio_dec_codecs[i].element_name,
GST_RANK_PRIMARY, type)) { GST_RANK_PRIMARY, type)) {
@ -1060,9 +1095,10 @@ dshow_adec_register (GstPlugin * plugin)
} }
GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s", GST_CAT_DEBUG (dshowaudiodec_debug, "Registered %s",
audio_dec_codecs[i].element_name); audio_dec_codecs[i].element_name);
} else { }
GST_CAT_DEBUG (dshowaudiodec_debug, else {
"Element %s not registered (the format is not supported by the system)", GST_DEBUG ("Element %s not registered "
"(the format is not supported by the system)",
audio_dec_codecs[i].element_name); audio_dec_codecs[i].element_name);
} }
} }

View file

@ -60,6 +60,7 @@ typedef struct {
gchar *element_longname; /* Description string for element */ gchar *element_longname; /* Description string for element */
gint32 format; /* WAVEFORMATEX format */ gint32 format; /* WAVEFORMATEX format */
gchar *sinkcaps; /* GStreamer caps of input format */ gchar *sinkcaps; /* GStreamer caps of input format */
PreferredFilter *preferred_filters; /* NULL-terminated list of preferred filters */
} AudioCodecEntry; } AudioCodecEntry;
#define GST_TYPE_DSHOWAUDIODEC (gst_dshowaudiodec_get_type()) #define GST_TYPE_DSHOWAUDIODEC (gst_dshowaudiodec_get_type())

View file

@ -46,6 +46,25 @@ HRESULT FakeOutputPin::GetMediaType(int iPosition,
return VFW_S_NO_MORE_ITEMS; 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) HRESULT FakeOutputPin::CheckMediaType(const CMediaType *pmt)
{ {

View file

@ -20,6 +20,8 @@
*/ */
#include <atlbase.h> #include <atlbase.h>
#include <dmodshow.h>
#include <dmoreg.h>
#include "gstdshowutil.h" #include "gstdshowutil.h"
#include "gstdshowfakesrc.h" #include "gstdshowfakesrc.h"
@ -49,108 +51,87 @@ gst_dshow_get_pin_from_filter (IBaseFilter *filter, PIN_DIRECTION pindir)
return NULL; return NULL;
} }
gboolean gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype, IBaseFilter *
gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype,
CLSID output_majortype, CLSID output_subtype, CLSID output_majortype, CLSID output_subtype,
gchar * prefered_filter_name, IBaseFilter **filter) PreferredFilter *preferred_filters)
{ {
gboolean ret = FALSE;
HRESULT hres; HRESULT hres;
GUID arrayInTypes[2]; GUID inTypes[2];
GUID arrayOutTypes[2]; GUID outTypes[2];
IFilterMapper2 *mapper = NULL; CComPtr<IFilterMapper2> mapper;
IEnumMoniker *enum_moniker = NULL; CComPtr<IEnumMoniker> enum_moniker;
IMoniker *moniker = NULL; CComPtr<IMoniker> moniker;
ULONG fetched; ULONG fetched;
gchar *prefered_filter_upper = NULL; IBaseFilter *filter;
gboolean exit = FALSE;
/* initialize output parameter */ /* First, see if any of our preferred filters is available.
if (filter) * If not, we fall back to the highest-ranked installed filter */
*filter = NULL; 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;
/* create a private copy of prefered filter substring in upper case */ hres = CoCreateInstance (CLSID_DMOWrapperFilter, NULL,
if (prefered_filter_name) { CLSCTX_INPROC,
prefered_filter_upper = g_strdup (prefered_filter_name); IID_IBaseFilter, (void **)&filter);
strupr (prefered_filter_upper); 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;
}
/* Continue to the next filter */
preferred_filters++;
}
} }
hres = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, hres = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
IID_IFilterMapper2, (void **) &mapper); IID_IFilterMapper2, (void **) &mapper);
if (FAILED(hres)) if (FAILED(hres))
goto clean; return NULL;
memcpy(&arrayInTypes[0], &input_majortype, sizeof (CLSID)); inTypes[0] = input_majortype;
memcpy(&arrayInTypes[1], &input_subtype, sizeof (CLSID)); inTypes[1] = input_subtype;
memcpy(&arrayOutTypes[0], &output_majortype, sizeof (CLSID)); outTypes[0] = output_majortype;
memcpy(&arrayOutTypes[1], &output_subtype, sizeof (CLSID)); outTypes[1] = output_subtype;
hres = mapper->EnumMatchingFilters (&enum_moniker, 0, FALSE, MERIT_DO_NOT_USE+1, hres = mapper->EnumMatchingFilters (&enum_moniker, 0,
TRUE, 1, arrayInTypes, NULL, NULL, FALSE, FALSE, MERIT_DO_NOT_USE+1,
TRUE, 1, arrayOutTypes, NULL, NULL); TRUE, 1, inTypes, NULL, NULL, FALSE,
TRUE, 1, outTypes, NULL, NULL);
if (FAILED(hres)) if (FAILED(hres))
goto clean; return NULL;
enum_moniker->Reset (); enum_moniker->Reset ();
while(hres = enum_moniker->Next (1, &moniker, &fetched),hres == S_OK while(enum_moniker->Next (1, &moniker, &fetched) == S_OK)
&& !exit) { {
IBaseFilter *filter_temp = NULL; hres = moniker->BindToObject(NULL, NULL,
IPropertyBag *property_bag = NULL; IID_IBaseFilter, (void**)&filter);
gchar * friendly_name = NULL; if(SUCCEEDED(hres)) {
return filter;
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 (); moniker.Release ();
} }
hres = moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&filter_temp); return NULL;
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 ();
}
if (friendly_name)
g_free (friendly_name);
moniker->Release ();
}
clean:
if (prefered_filter_upper)
g_free (prefered_filter_upper);
if (enum_moniker)
enum_moniker->Release ();
if (mapper)
mapper->Release ();
return ret;
} }

View file

@ -31,12 +31,18 @@
#include <glib.h> #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 */ /* get a pin from directshow filter */
IPin *gst_dshow_get_pin_from_filter (IBaseFilter *filter, PIN_DIRECTION pindir); IPin *gst_dshow_get_pin_from_filter (IBaseFilter *filter, PIN_DIRECTION pindir);
/* find and return a filter according to the input and output types */ /* find and return a filter according to the input and output types */
gboolean gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype, IBaseFilter *
gst_dshow_find_filter(CLSID input_majortype, CLSID input_subtype,
CLSID output_majortype, CLSID output_subtype, CLSID output_majortype, CLSID output_subtype,
gchar * prefered_filter_name, IBaseFilter **filter); PreferredFilter *preferred_filters);
#endif /* _GST_DSHOW_UTIL_H_ */ #endif /* _GST_DSHOW_UTIL_H_ */

View file

@ -48,6 +48,8 @@
#endif #endif
#include <atlbase.h> #include <atlbase.h>
#include <dmoreg.h>
#include <wmcodecdsp.h>
#include "gstdshowvideodec.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_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 }} #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 */ /* video codecs array */
static const VideoCodecEntry video_dec_codecs[] = { static const VideoCodecEntry video_dec_codecs[] = {
{"dshowvdec_wmv1", {"dshowvdec_wmv1", "Windows Media Video 7",
"Windows Media Video 7",
"DMO",
GST_MAKE_FOURCC ('W', 'M', 'V', '1'), GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV1, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV1,
"video/x-wmv, wmvversion = (int) 1", "video/x-wmv, wmvversion = (int) 1",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_wmv2", preferred_wmv_filters},
"Windows Media Video 8",
"DMO", {"dshowvdec_wmv2", "Windows Media Video 8",
GST_MAKE_FOURCC ('W', 'M', 'V', '2'), GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV2,
"video/x-wmv, wmvversion = (int) 2", "video/x-wmv, wmvversion = (int) 2",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_wmv3", preferred_wmv_filters},
"Windows Media Video 9",
"DMO", {"dshowvdec_wmv3", "Windows Media Video 9",
GST_MAKE_FOURCC ('W', 'M', 'V', '3'), GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV3, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVV3,
"video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMV3", "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMV3",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_wmvp", preferred_wmv_filters},
"Windows Media Video 9 Image",
"DMO", {"dshowvdec_wmvp", "Windows Media Video 9 Image",
GST_MAKE_FOURCC ('W', 'M', 'V', 'P'), GST_MAKE_FOURCC ('W', 'M', 'V', 'P'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVP, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVP,
"video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVP", "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVP",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_wmva", preferred_wmv_filters},
"Windows Media Video 9 Advanced",
"DMO", {"dshowvdec_wmva", "Windows Media Video 9 Advanced",
GST_MAKE_FOURCC ('W', 'M', 'V', 'A'), GST_MAKE_FOURCC ('W', 'M', 'V', 'A'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVA, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_WMVA,
"video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVA", "video/x-wmv, wmvversion = (int) 3, " "format = (fourcc) WMVA",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_cinepak", preferred_wmv_filters},
"Cinepack",
"AVI Decompressor", {"dshowvdec_cinepak", "Cinepack",
0x64697663, 0x64697663,
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_CVID, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_CVID,
"video/x-cinepak", "video/x-cinepak",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_RGB32, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_RGB32,
"video/x-raw-rgb, bpp=(int)32, depth=(int)24, " "video/x-raw-rgb, bpp=(int)32, depth=(int)24, "
"endianness=(int)4321, red_mask=(int)65280, " "endianness=(int)4321, red_mask=(int)65280, "
"green_mask=(int)16711680, blue_mask=(int)-16777216"}, "green_mask=(int)16711680, blue_mask=(int)-16777216",
{"dshowvdec_msmpeg41", preferred_cinepack_filters},
"Microsoft ISO MPEG-4 version 1",
"DMO", {"dshowvdec_msmpeg41", "Microsoft ISO MPEG-4 version 1",
GST_MAKE_FOURCC ('M', 'P', '4', 'S'), GST_MAKE_FOURCC ('M', 'P', '4', 'S'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP4S, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP4S,
"video/x-msmpeg, msmpegversion=(int)41", "video/x-msmpeg, msmpegversion=(int)41",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_msmpeg42", preferred_mp4s_filters},
"Microsoft ISO MPEG-4 version 2",
"DMO", {"dshowvdec_msmpeg42", "Microsoft ISO MPEG-4 version 2",
GST_MAKE_FOURCC ('M', 'P', '4', '2'), GST_MAKE_FOURCC ('M', 'P', '4', '2'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP42, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP42,
"video/x-msmpeg, msmpegversion=(int)42", "video/x-msmpeg, msmpegversion=(int)42",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_msmpeg43", preferred_mpeg4_filters},
"Microsoft ISO MPEG-4 version 3",
"DMO", {"dshowvdec_msmpeg43", "Microsoft ISO MPEG-4 version 3",
GST_MAKE_FOURCC ('M', 'P', '4', '3'), GST_MAKE_FOURCC ('M', 'P', '4', '3'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP43, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MP43,
"video/x-msmpeg, msmpegversion=(int)43", "video/x-msmpeg, msmpegversion=(int)43",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_msmpeg4", preferred_mp43_filters},
"Microsoft ISO MPEG-4 version 1.1",
"DMO", {"dshowvdec_msmpeg4", "Microsoft ISO MPEG-4 version 1.1",
GST_MAKE_FOURCC ('M', '4', 'S', '2'), GST_MAKE_FOURCC ('M', '4', 'S', '2'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_M4S2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_M4S2,
"video/x-msmpeg, msmpegversion=(int)4", "video/x-msmpeg, msmpegversion=(int)4",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
preferred_mp4s_filters},
{"dshowvdec_mpeg1", {"dshowvdec_mpeg1",
"MPEG-1 Video", "MPEG-1 Video",
"MPEG Video Decoder",
GST_MAKE_FOURCC ('M', 'P', 'E', 'G'), GST_MAKE_FOURCC ('M', 'P', 'E', 'G'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPEG1Payload, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_MPEG1Payload,
"video/mpeg, mpegversion= (int) 1, " "video/mpeg, mpegversion= (int) 1, "
"parsed= (boolean) true, " "systemstream= (boolean) false", "parsed= (boolean) true, " "systemstream= (boolean) false",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2",
{"dshowvdec_xvid", preferred_mpeg1_filters},
"XVID Video",
"ffdshow", {"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'), GST_MAKE_FOURCC ('X', 'V', 'I', 'D'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_XVID, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_XVID,
"video/x-xvid", "video/x-xvid",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2"},
{"dshowvdec_divx5",
"DIVX 5.0 Video", {"dshowvdec_divx5", "DIVX 5.0 Video",
"ffdshow",
GST_MAKE_FOURCC ('D', 'X', '5', '0'), GST_MAKE_FOURCC ('D', 'X', '5', '0'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DX50, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DX50,
"video/x-divx, divxversion=(int)5", "video/x-divx, divxversion=(int)5",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2"},
{"dshowvdec_divx4",
"DIVX 4.0 Video", {"dshowvdec_divx4", "DIVX 4.0 Video",
"ffdshow",
GST_MAKE_FOURCC ('D', 'I', 'V', 'X'), GST_MAKE_FOURCC ('D', 'I', 'V', 'X'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIVX, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIVX,
"video/x-divx, divxversion=(int)4", "video/x-divx, divxversion=(int)4",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)YUY2"}, "video/x-raw-yuv, format=(fourcc)YUY2"},
{"dshowvdec_divx3",
"DIVX 3.0 Video", {"dshowvdec_divx3", "DIVX 3.0 Video",
"ffdshow",
GST_MAKE_FOURCC ('D', 'I', 'V', '3'), GST_MAKE_FOURCC ('D', 'I', 'V', '3'),
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIV3, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_DIV3,
"video/x-divx, divxversion=(int)3", "video/x-divx, divxversion=(int)3",
GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2, GUID_MEDIATYPE_VIDEO, GUID_MEDIASUBTYPE_YUY2,
"video/x-raw-yuv, format=(fourcc)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"
} */
}; };
HRESULT VideoFakeSink::DoRenderSample(IMediaSample *pMediaSample) HRESULT VideoFakeSink::DoRenderSample(IMediaSample *pMediaSample)
@ -975,11 +1005,13 @@ gst_dshowvideodec_create_graph_and_filters (GstDshowVideoDec * vdec)
} }
/* search a decoder filter and create it */ /* 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->input_subtype,
klass->entry->output_majortype, klass->entry->output_majortype,
klass->entry->output_subtype, 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 " GST_ELEMENT_ERROR (vdec, STREAM, FAILED, ("Can't create an instance "
"of the decoder filter"), (NULL)); "of the decoder filter"), (NULL));
goto error; goto error;
@ -1136,15 +1168,17 @@ dshow_vdec_register (GstPlugin * plugin)
for (i = 0; i < sizeof (video_dec_codecs) / sizeof (VideoCodecEntry); i++) { for (i = 0; i < sizeof (video_dec_codecs) / sizeof (VideoCodecEntry); i++) {
GType type; 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].input_subtype,
video_dec_codecs[i].output_majortype, video_dec_codecs[i].output_majortype,
video_dec_codecs[i].output_subtype, 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", GST_DEBUG ("Registering %s", video_dec_codecs[i].element_name);
video_dec_codecs[i].element_name);
tmp = &video_dec_codecs[i]; tmp = &video_dec_codecs[i];
type = type =
@ -1154,11 +1188,10 @@ dshow_vdec_register (GstPlugin * plugin)
GST_RANK_PRIMARY, type)) { GST_RANK_PRIMARY, type)) {
return FALSE; return FALSE;
} }
GST_CAT_DEBUG (dshowvideodec_debug, "Registered %s", GST_DEBUG ("Registered %s", video_dec_codecs[i].element_name);
video_dec_codecs[i].element_name);
} else { } else {
GST_CAT_DEBUG (dshowvideodec_debug, GST_DEBUG ("Element %s not registered "
"Element %s not registered (the format is not supported by the system)", "(the format is not supported by the system)",
video_dec_codecs[i].element_name); video_dec_codecs[i].element_name);
} }
} }

View file

@ -55,7 +55,6 @@ G_BEGIN_DECLS
typedef struct { typedef struct {
gchar *element_name; /* The gst element factory name */ gchar *element_name; /* The gst element factory name */
gchar *element_longname; /* Description string for element */ gchar *element_longname; /* Description string for element */
gchar *preferred_filter_substring; /* TODO: Remove this? */
gint32 format; /* ??? */ gint32 format; /* ??? */
GUID input_majortype; GUID input_majortype;
GUID input_subtype; GUID input_subtype;
@ -63,6 +62,7 @@ typedef struct {
GUID output_majortype; GUID output_majortype;
GUID output_subtype; GUID output_subtype;
gchar *srccaps; gchar *srccaps;
PreferredFilter *preferred_filters;
} VideoCodecEntry; } VideoCodecEntry;
#define GST_TYPE_DSHOWVIDEODEC (gst_dshowvideodec_get_type()) #define GST_TYPE_DSHOWVIDEODEC (gst_dshowvideodec_get_type())