dshowvideosrc: use IEnumMediaTypes when IAMStreamConfig is not usable

For some device drivers IAMStreamConfig is not supported.
But EnumMediatypes does not provide range size and framerate.
This commit is contained in:
Julien Isorce 2009-09-09 12:41:17 +02:00
parent aa7b9931ba
commit 76304164bb
4 changed files with 151 additions and 48 deletions

View file

@ -22,6 +22,11 @@
#include "gstdshow.h" #include "gstdshow.h"
#include "gstdshowfakesink.h" #include "gstdshowfakesink.h"
const GUID MEDIASUBTYPE_I420
= { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
0x71}
};
void void
gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt) gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt)
{ {
@ -58,10 +63,45 @@ gst_dshow_free_pin_mediatype (gpointer pt)
} }
GstCapturePinMediaType * GstCapturePinMediaType *
gst_dshow_new_pin_mediatype (IPin * pin, gint id, IAMStreamConfig * streamcaps) gst_dshow_new_pin_mediatype (IPin * pin)
{ {
GstCapturePinMediaType *pin_mediatype = g_new0 (GstCapturePinMediaType, 1); GstCapturePinMediaType *pin_mediatype = g_new0 (GstCapturePinMediaType, 1);
pin->AddRef ();
pin_mediatype->capture_pin = pin;
return pin_mediatype;
}
GstCapturePinMediaType *
gst_dshow_new_pin_mediatype_from_enum_mediatypes (IPin * pin, IEnumMediaTypes *enum_mediatypes)
{
GstCapturePinMediaType *pin_mediatype = gst_dshow_new_pin_mediatype (pin);
VIDEOINFOHEADER *video_info = NULL;
HRESULT hres = enum_mediatypes->Next (1, &pin_mediatype->mediatype, NULL);
if (hres != S_OK || !pin_mediatype->mediatype) {
gst_dshow_free_pin_mediatype (pin_mediatype);
return NULL;
}
video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat;
pin_mediatype->defaultWidth = video_info->bmiHeader.biWidth;
pin_mediatype->defaultHeight = video_info->bmiHeader.biHeight;
pin_mediatype->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame);
pin_mediatype->granularityWidth = 1;
pin_mediatype->granularityHeight = 1;
return pin_mediatype;
}
GstCapturePinMediaType *
gst_dshow_new_pin_mediatype_from_streamcaps (IPin * pin, gint id, IAMStreamConfig * streamcaps)
{
GstCapturePinMediaType *pin_mediatype = gst_dshow_new_pin_mediatype (pin);
VIDEOINFOHEADER *video_info = NULL;
HRESULT hres = streamcaps->GetStreamCaps (id, &pin_mediatype->mediatype, HRESULT hres = streamcaps->GetStreamCaps (id, &pin_mediatype->mediatype,
(BYTE *) & pin_mediatype->vscc); (BYTE *) & pin_mediatype->vscc);
if (FAILED (hres) || !pin_mediatype->mediatype) { if (FAILED (hres) || !pin_mediatype->mediatype) {
@ -69,8 +109,13 @@ gst_dshow_new_pin_mediatype (IPin * pin, gint id, IAMStreamConfig * streamcaps)
return NULL; return NULL;
} }
pin->AddRef (); video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat;
pin_mediatype->capture_pin = pin;
pin_mediatype->defaultWidth = video_info->bmiHeader.biWidth;
pin_mediatype->defaultHeight = video_info->bmiHeader.biHeight;
pin_mediatype->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame);
pin_mediatype->granularityWidth = pin_mediatype->vscc.OutputGranularityX;
pin_mediatype->granularityHeight = pin_mediatype->vscc.OutputGranularityY;
return pin_mediatype; return pin_mediatype;
} }
@ -98,6 +143,7 @@ gst_dshow_check_mediatype (AM_MEDIA_TYPE * media_type, const GUID sub_type,
return return
UuidCompare (&media_type->subtype, (UUID *) & sub_type, UuidCompare (&media_type->subtype, (UUID *) & sub_type,
&rpcstatus) == 0 && rpcstatus == RPC_S_OK && &rpcstatus) == 0 && rpcstatus == RPC_S_OK &&
//IsEqualGUID (&media_type->subtype, &sub_type)
UuidCompare (&media_type->formattype, (UUID *) & format_type, UuidCompare (&media_type->formattype, (UUID *) & format_type,
&rpcstatus) == 0 && rpcstatus == RPC_S_OK; &rpcstatus) == 0 && rpcstatus == RPC_S_OK;
} }
@ -350,20 +396,24 @@ gst_dshow_show_propertypage (IBaseFilter * base_filter)
return ret; return ret;
} }
GstVideoFormat
gst_dshow_guid_to_gst_video_format (AM_MEDIA_TYPE *mediatype)
{
if (gst_dshow_check_mediatype (mediatype, MEDIASUBTYPE_I420, FORMAT_VideoInfo))
return GST_VIDEO_FORMAT_I420;
if (gst_dshow_check_mediatype (mediatype, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo))
return GST_VIDEO_FORMAT_BGR;
return GST_VIDEO_FORMAT_UNKNOWN;
}
GstCaps * GstCaps *
gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar * name, gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar * name,
GstCapturePinMediaType * pin_mediatype) GstCapturePinMediaType * pin_mediatype)
{ {
GstCaps *video_caps = NULL; GstCaps *video_caps = NULL;
GstStructure *video_structure = NULL; GstStructure *video_structure = NULL;
VIDEOINFOHEADER *video_info =
(VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat;
pin_mediatype->defaultWidth = video_info->bmiHeader.biWidth;
pin_mediatype->defaultHeight = video_info->bmiHeader.biHeight;
pin_mediatype->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame);
pin_mediatype->granularityWidth = pin_mediatype->vscc.OutputGranularityX;
pin_mediatype->granularityHeight = pin_mediatype->vscc.OutputGranularityY;
/* raw video format */ /* raw video format */
switch (video_format) { switch (video_format) {

View file

@ -55,8 +55,15 @@ void gst_dshow_free_pin_mediatype (gpointer pt);
void gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt); void gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt);
/* create a new capture media type that handles dshow video caps of a capture pin */ /* create a new capture media type that handles dshow video caps of a capture pin */
GstCapturePinMediaType *gst_dshow_new_pin_mediatype (IPin * pin, gint id, GstCapturePinMediaType *gst_dshow_new_pin_mediatype (IPin * pin);
IAMStreamConfig * streamcaps);
/* create a new capture media type from enum mediatype */
GstCapturePinMediaType * gst_dshow_new_pin_mediatype_from_enum_mediatypes (IPin * pin,
IEnumMediaTypes *enum_mediatypes);
/* create a new capture media type from streamcaps */
GstCapturePinMediaType *gst_dshow_new_pin_mediatype_from_streamcaps (IPin * pin,
gint id, IAMStreamConfig * streamcaps);
/* free the memory of all mediatypes of the input list if pin mediatype */ /* free the memory of all mediatypes of the input list if pin mediatype */
void gst_dshow_free_pins_mediatypes (GList * mediatypes); void gst_dshow_free_pins_mediatypes (GList * mediatypes);
@ -82,6 +89,9 @@ gchar *gst_dshow_getdevice_from_devicename (const GUID * device_category,
/* show the capture filter property page (generally used to setup the device). the page is modal*/ /* show the capture filter property page (generally used to setup the device). the page is modal*/
gboolean gst_dshow_show_propertypage (IBaseFilter * base_filter); gboolean gst_dshow_show_propertypage (IBaseFilter * base_filter);
/* translate GUID format to gsteamer video format */
GstVideoFormat gst_dshow_guid_to_gst_video_format (AM_MEDIA_TYPE *mediatype);
/* transform a dshow video caps to a gstreamer video caps */ /* transform a dshow video caps to a gstreamer video caps */
GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format,
const gchar * name, GstCapturePinMediaType * pin_mediatype); const gchar * name, GstCapturePinMediaType * pin_mediatype);

View file

@ -37,11 +37,6 @@ GST_ELEMENT_DETAILS ("DirectShow video capture source",
GST_DEBUG_CATEGORY_STATIC (dshowvideosrc_debug); GST_DEBUG_CATEGORY_STATIC (dshowvideosrc_debug);
#define GST_CAT_DEFAULT dshowvideosrc_debug #define GST_CAT_DEFAULT dshowvideosrc_debug
const GUID MEDIASUBTYPE_I420
= { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
0x71}
};
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
@ -103,7 +98,9 @@ static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc,
/*utils*/ /*utils*/
static GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * static GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc *
src, IPin * pin, IAMStreamConfig * streamcaps); src, IPin * pin);
static GstCaps *gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc *
src, IPin * pin);
static gboolean gst_dshowvideosrc_push_buffer (byte * buffer, long size, static gboolean gst_dshowvideosrc_push_buffer (byte * buffer, long size,
gpointer src_object, UINT64 start, UINT64 stop); gpointer src_object, UINT64 start, UINT64 stop);
@ -540,18 +537,16 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc)
/* we only want capture pins */ /* we only want capture pins */
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE, if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
&rpcstatus) == 0) { &rpcstatus) == 0) {
IAMStreamConfig *streamcaps = NULL; {
if (SUCCEEDED (capture_pin->QueryInterface (IID_IAMStreamConfig,
(LPVOID *) & streamcaps))) {
GstCaps *caps = GstCaps *caps =
gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin, gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin);
streamcaps);
if (caps) { if (caps) {
gst_caps_append (src->caps, caps); gst_caps_append (src->caps, caps);
} else {
caps = gst_dshowvideosrc_getcaps_from_enum_mediatypes (src, capture_pin);
if (caps)
gst_caps_append (src->caps, caps);
} }
streamcaps->Release ();
} }
} }
@ -564,6 +559,8 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc)
} }
} }
g_print ("caps: %s\n", gst_caps_to_string (src->caps));
if (unidevice) { if (unidevice) {
g_free (unidevice); g_free (unidevice);
} }
@ -874,8 +871,7 @@ gst_dshowvideosrc_create (GstPushSrc * psrc, GstBuffer ** buf)
} }
static GstCaps * static GstCaps *
gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
IAMStreamConfig * streamcaps)
{ {
GstCaps *caps = NULL; GstCaps *caps = NULL;
HRESULT hres = S_OK; HRESULT hres = S_OK;
@ -883,36 +879,36 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin,
int isize = 0; int isize = 0;
VIDEO_STREAM_CONFIG_CAPS vscc; VIDEO_STREAM_CONFIG_CAPS vscc;
int i = 0; int i = 0;
IAMStreamConfig *streamcaps = NULL;
if (!streamcaps) hres = pin->QueryInterface (IID_IAMStreamConfig, (LPVOID *) & streamcaps);
if (FAILED (hres)) {
GST_ERROR ("Failed to retrieve IAMStreamConfig (error=0x%x)", hres);
return NULL; return NULL;
}
streamcaps->GetNumberOfCapabilities (&icount, &isize); streamcaps->GetNumberOfCapabilities (&icount, &isize);
if (isize != sizeof (vscc)) if (isize != sizeof (vscc)) {
streamcaps->Release ();
return NULL; return NULL;
}
caps = gst_caps_new_empty (); caps = gst_caps_new_empty ();
for (; i < icount; i++) { for (i = 0; i < icount; i++) {
GstCapturePinMediaType *pin_mediatype = GstCapturePinMediaType *pin_mediatype =
gst_dshow_new_pin_mediatype (pin, i, streamcaps); gst_dshow_new_pin_mediatype_from_streamcaps (pin, i, streamcaps);
if (pin_mediatype) { if (pin_mediatype) {
GstCaps *mediacaps = NULL; GstCaps *mediacaps = NULL;
GstVideoFormat video_format =
gst_dshow_guid_to_gst_video_format (pin_mediatype->mediatype);
if (gst_dshow_check_mediatype (pin_mediatype->mediatype, if (video_format != GST_VIDEO_FORMAT_UNKNOWN) {
MEDIASUBTYPE_I420, FORMAT_VideoInfo)) { mediacaps = gst_dshow_new_video_caps (video_format, NULL,
mediacaps =
gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL,
pin_mediatype);
} else if (gst_dshow_check_mediatype (pin_mediatype->mediatype,
MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)) {
mediacaps =
gst_dshow_new_video_caps (GST_VIDEO_FORMAT_BGR, NULL,
pin_mediatype); pin_mediatype);
} else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype,
@ -939,10 +935,57 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin,
/* failed to convert dshow caps */ /* failed to convert dshow caps */
gst_dshow_free_pin_mediatype (pin_mediatype); gst_dshow_free_pin_mediatype (pin_mediatype);
} }
} }
} }
streamcaps->Release ();
if (caps && gst_caps_is_empty (caps)) {
gst_caps_unref (caps);
caps = NULL;
}
return caps;
}
static GstCaps *
gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc * src, IPin * pin)
{
GstCaps *caps = NULL;
IEnumMediaTypes *enum_mediatypes = NULL;
HRESULT hres = S_OK;
GstCapturePinMediaType *pin_mediatype = NULL;
hres = pin->EnumMediaTypes (&enum_mediatypes);
if (FAILED (hres)) {
GST_ERROR ("Failed to retrieve IEnumMediaTypes (error=0x%x)", hres);
return NULL;
}
caps = gst_caps_new_empty ();
while ((pin_mediatype = gst_dshow_new_pin_mediatype_from_enum_mediatypes (pin, enum_mediatypes)) != NULL) {
GstCaps *mediacaps = NULL;
GstVideoFormat video_format = gst_dshow_guid_to_gst_video_format (pin_mediatype->mediatype);
if (video_format != GST_VIDEO_FORMAT_UNKNOWN)
mediacaps = gst_video_format_new_caps (video_format,
pin_mediatype->defaultWidth, pin_mediatype->defaultHeight,
pin_mediatype->defaultFPS, 1, 1, 1);
if (mediacaps) {
src->pins_mediatypes =
g_list_append (src->pins_mediatypes, pin_mediatype);
gst_caps_append (caps, mediacaps);
} else {
/* failed to convert dshow caps */
gst_dshow_free_pin_mediatype (pin_mediatype);
}
}
enum_mediatypes->Release ();
if (caps && gst_caps_is_empty (caps)) { if (caps && gst_caps_is_empty (caps)) {
gst_caps_unref (caps); gst_caps_unref (caps);
caps = NULL; caps = NULL;

View file

@ -61,7 +61,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbasd.lib strmiids.lib" AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib libgstvideo-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbasd.lib strmiids.lib"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug&quot;" AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"
@ -137,7 +137,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbase.lib strmiids.lib" AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib libgstvideo-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbase.lib strmiids.lib"
LinkIncremental="1" LinkIncremental="1"
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release&quot;" AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"
@ -214,7 +214,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbasd.lib strmiids.lib" AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib libgstvideo-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbasd.lib strmiids.lib"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug_MBCS&quot;" AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug_MBCS&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"
@ -290,7 +290,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbase.lib strmiids.lib" AdditionalDependencies="libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib libgstaudio-0.10.lib libgstvideo-0.10.lib glib-2.0.lib gmodule-2.0.lib gobject-2.0.lib gthread-2.0.lib winmm.lib rpcrt4.lib strmbase.lib strmiids.lib"
LinkIncremental="1" LinkIncremental="1"
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release_MBCS&quot;" AdditionalLibraryDirectories="C:\msys\1.0\local\lib;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&quot;;&quot;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release_MBCS&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"