mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
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:
parent
aa7b9931ba
commit
76304164bb
4 changed files with 151 additions and 48 deletions
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
/>
|
||||
<Tool
|
||||
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"
|
||||
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib";"C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug""
|
||||
GenerateDebugInformation="true"
|
||||
|
@ -137,7 +137,7 @@
|
|||
/>
|
||||
<Tool
|
||||
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"
|
||||
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib";"C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release""
|
||||
GenerateDebugInformation="true"
|
||||
|
@ -214,7 +214,7 @@
|
|||
/>
|
||||
<Tool
|
||||
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"
|
||||
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib";"C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Debug_MBCS""
|
||||
GenerateDebugInformation="true"
|
||||
|
@ -290,7 +290,7 @@
|
|||
/>
|
||||
<Tool
|
||||
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"
|
||||
AdditionalLibraryDirectories="C:\msys\1.0\local\lib;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib";"C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses\Release_MBCS""
|
||||
GenerateDebugInformation="true"
|
||||
|
|
Loading…
Reference in a new issue