summaryrefslogtreecommitdiff
path: root/sys/dshowsrcwrapper
diff options
context:
space:
mode:
authorJulien Isorce <julien.isorce@gmail.com>2009-09-09 12:41:17 +0200
committerJulien Isorce <julien.isorce@gmail.com>2009-09-09 12:41:17 +0200
commit76304164bb457459b7561d508d17d3af2bac4f70 (patch)
treea3e489df96444c619605596e534f5c45066128ed /sys/dshowsrcwrapper
parentaa7b9931ba976fa3f5c3fd67338818bb85ca2f58 (diff)
downloadgstreamer-plugins-bad-76304164bb457459b7561d508d17d3af2bac4f70.tar.gz
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.
Diffstat (limited to 'sys/dshowsrcwrapper')
-rw-r--r--sys/dshowsrcwrapper/gstdshow.cpp72
-rw-r--r--sys/dshowsrcwrapper/gstdshow.h14
-rw-r--r--sys/dshowsrcwrapper/gstdshowvideosrc.cpp103
3 files changed, 146 insertions, 43 deletions
diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp
index 86be548f6..980ff93c9 100644
--- a/sys/dshowsrcwrapper/gstdshow.cpp
+++ b/sys/dshowsrcwrapper/gstdshow.cpp
@@ -22,6 +22,11 @@
#include "gstdshow.h"
#include "gstdshowfakesink.h"
+const GUID MEDIASUBTYPE_I420
+ = { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
+ 0x71}
+};
+
void
gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt)
{
@@ -58,10 +63,45 @@ gst_dshow_free_pin_mediatype (gpointer pt)
}
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);
+ 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,
(BYTE *) & pin_mediatype->vscc);
if (FAILED (hres) || !pin_mediatype->mediatype) {
@@ -69,8 +109,13 @@ gst_dshow_new_pin_mediatype (IPin * pin, gint id, IAMStreamConfig * streamcaps)
return NULL;
}
- pin->AddRef ();
- pin_mediatype->capture_pin = pin;
+ 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;
return pin_mediatype;
}
@@ -98,6 +143,7 @@ gst_dshow_check_mediatype (AM_MEDIA_TYPE * media_type, const GUID sub_type,
return
UuidCompare (&media_type->subtype, (UUID *) & sub_type,
&rpcstatus) == 0 && rpcstatus == RPC_S_OK &&
+ //IsEqualGUID (&media_type->subtype, &sub_type)
UuidCompare (&media_type->formattype, (UUID *) & format_type,
&rpcstatus) == 0 && rpcstatus == RPC_S_OK;
}
@@ -350,20 +396,24 @@ gst_dshow_show_propertypage (IBaseFilter * base_filter)
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 *
gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar * name,
GstCapturePinMediaType * pin_mediatype)
{
GstCaps *video_caps = 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 */
switch (video_format) {
diff --git a/sys/dshowsrcwrapper/gstdshow.h b/sys/dshowsrcwrapper/gstdshow.h
index 0e98b0ad3..47c34e974 100644
--- a/sys/dshowsrcwrapper/gstdshow.h
+++ b/sys/dshowsrcwrapper/gstdshow.h
@@ -55,8 +55,15 @@ void gst_dshow_free_pin_mediatype (gpointer pt);
void gst_dshow_free_mediatype (AM_MEDIA_TYPE * pmt);
/* 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,
- IAMStreamConfig * streamcaps);
+GstCapturePinMediaType *gst_dshow_new_pin_mediatype (IPin * pin);
+
+/* 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 */
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*/
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 */
GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format,
const gchar * name, GstCapturePinMediaType * pin_mediatype);
diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp
index 433e2cbcc..c2f9efe9e 100644
--- a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp
+++ b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp
@@ -37,11 +37,6 @@ GST_ELEMENT_DETAILS ("DirectShow video capture source",
GST_DEBUG_CATEGORY_STATIC (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",
GST_PAD_SRC,
GST_PAD_ALWAYS,
@@ -103,7 +98,9 @@ static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc,
/*utils*/
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,
gpointer src_object, UINT64 start, UINT64 stop);
@@ -540,18 +537,16 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc)
/* we only want capture pins */
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
&rpcstatus) == 0) {
- IAMStreamConfig *streamcaps = NULL;
-
- if (SUCCEEDED (capture_pin->QueryInterface (IID_IAMStreamConfig,
- (LPVOID *) & streamcaps))) {
+ {
GstCaps *caps =
- gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin,
- streamcaps);
-
+ gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin);
if (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) {
g_free (unidevice);
}
@@ -874,8 +871,7 @@ gst_dshowvideosrc_create (GstPushSrc * psrc, GstBuffer ** buf)
}
static GstCaps *
-gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin,
- IAMStreamConfig * streamcaps)
+gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
{
GstCaps *caps = NULL;
HRESULT hres = S_OK;
@@ -883,36 +879,36 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin,
int isize = 0;
VIDEO_STREAM_CONFIG_CAPS vscc;
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;
+ }
streamcaps->GetNumberOfCapabilities (&icount, &isize);
- if (isize != sizeof (vscc))
+ if (isize != sizeof (vscc)) {
+ streamcaps->Release ();
return NULL;
+ }
caps = gst_caps_new_empty ();
- for (; i < icount; i++) {
+ for (i = 0; i < icount; i++) {
GstCapturePinMediaType *pin_mediatype =
- gst_dshow_new_pin_mediatype (pin, i, streamcaps);
+ gst_dshow_new_pin_mediatype_from_streamcaps (pin, i, streamcaps);
if (pin_mediatype) {
GstCaps *mediacaps = NULL;
+ GstVideoFormat video_format =
+ gst_dshow_guid_to_gst_video_format (pin_mediatype->mediatype);
- if (gst_dshow_check_mediatype (pin_mediatype->mediatype,
- MEDIASUBTYPE_I420, FORMAT_VideoInfo)) {
- 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,
+ if (video_format != GST_VIDEO_FORMAT_UNKNOWN) {
+ mediacaps = gst_dshow_new_video_caps (video_format, NULL,
pin_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 */
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)) {
gst_caps_unref (caps);
caps = NULL;