mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
dshowsrcwrapper: refactor device selection, filter creation, and caps retrieval
This allows a future GstDeviceProvider to more easily query devices and caps.
This commit is contained in:
parent
e70af38d4e
commit
912ff02a21
4 changed files with 330 additions and 111 deletions
|
@ -23,10 +23,17 @@
|
||||||
|
|
||||||
#include "gstdshow.h"
|
#include "gstdshow.h"
|
||||||
#include "gstdshowfakesink.h"
|
#include "gstdshowfakesink.h"
|
||||||
|
#include "gstdshowvideosrc.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (dshowsrcwrapper_debug);
|
GST_DEBUG_CATEGORY_EXTERN (dshowsrcwrapper_debug);
|
||||||
#define GST_CAT_DEFAULT dshowsrcwrapper_debug
|
#define GST_CAT_DEFAULT dshowsrcwrapper_debug
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
wchar_to_gchar (WCHAR * w)
|
||||||
|
{
|
||||||
|
return g_utf16_to_utf8 ((const gunichar2 *) w, wcslen (w), NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
const GUID MEDIASUBTYPE_I420
|
const GUID MEDIASUBTYPE_I420
|
||||||
= { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
|
= { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
|
||||||
0x71}
|
0x71}
|
||||||
|
@ -238,9 +245,7 @@ gst_dshow_find_filter (CLSID input_majortype, CLSID input_subtype,
|
||||||
|
|
||||||
hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL);
|
hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL);
|
||||||
if (hres == S_OK && varFriendlyName.bstrVal) {
|
if (hres == S_OK && varFriendlyName.bstrVal) {
|
||||||
friendly_name =
|
friendly_name = wchar_to_gchar (varFriendlyName.bstrVal);
|
||||||
g_utf16_to_utf8 ((const gunichar2 *) varFriendlyName.bstrVal,
|
|
||||||
wcslen (varFriendlyName.bstrVal), NULL, NULL, NULL);
|
|
||||||
if (friendly_name)
|
if (friendly_name)
|
||||||
_strupr (friendly_name);
|
_strupr (friendly_name);
|
||||||
SysFreeString (varFriendlyName.bstrVal);
|
SysFreeString (varFriendlyName.bstrVal);
|
||||||
|
@ -288,6 +293,196 @@ clean:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_dshow_device_entry_free (DshowDeviceEntry * entry)
|
||||||
|
{
|
||||||
|
if (entry) {
|
||||||
|
g_free (entry->device);
|
||||||
|
entry->device = NULL;
|
||||||
|
g_free (entry->device_name);
|
||||||
|
entry->device_name = NULL;
|
||||||
|
if (entry->caps) {
|
||||||
|
gst_caps_unref (entry->caps);
|
||||||
|
entry->caps = NULL;
|
||||||
|
}
|
||||||
|
if (entry->moniker) {
|
||||||
|
entry->moniker->Release ();
|
||||||
|
entry->moniker = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_dshow_device_list_free (GList * devices)
|
||||||
|
{
|
||||||
|
GList *cur;
|
||||||
|
|
||||||
|
for (cur = devices; cur != NULL; cur = cur->next)
|
||||||
|
gst_dshow_device_entry_free ((DshowDeviceEntry *) cur->data);
|
||||||
|
|
||||||
|
g_list_free (devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
gst_dshow_enumerate_devices (const GUID * device_category, gboolean getcaps)
|
||||||
|
{
|
||||||
|
GList *result = NULL;
|
||||||
|
ICreateDevEnum *devices_enum = NULL;
|
||||||
|
IEnumMoniker *enum_moniker = NULL;
|
||||||
|
IMoniker *moniker = NULL;
|
||||||
|
HRESULT hres = S_FALSE;
|
||||||
|
ULONG fetched;
|
||||||
|
gint devidx = -1;
|
||||||
|
|
||||||
|
hres = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
IID_ICreateDevEnum, (void **) &devices_enum);
|
||||||
|
if (hres != S_OK) {
|
||||||
|
GST_ERROR ("Failed to create System Device Enumerator");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = devices_enum->CreateClassEnumerator (*device_category,
|
||||||
|
&enum_moniker, 0);
|
||||||
|
if (hres != S_OK || !enum_moniker) {
|
||||||
|
GST_ERROR ("Failed to create audio/video class device enumerator");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum_moniker->Reset ();
|
||||||
|
|
||||||
|
while (enum_moniker->Next (1, &moniker, &fetched) == S_OK) {
|
||||||
|
IPropertyBag *property_bag = 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) {
|
||||||
|
gchar *friendly_name = wchar_to_gchar (varFriendlyName.bstrVal);
|
||||||
|
|
||||||
|
devidx++;
|
||||||
|
GST_DEBUG ("Found device idx=%d: device-name='%s'",
|
||||||
|
devidx, friendly_name);
|
||||||
|
|
||||||
|
WCHAR *wszDisplayName = NULL;
|
||||||
|
hres = moniker->GetDisplayName (NULL, NULL, &wszDisplayName);
|
||||||
|
if (hres == S_OK && wszDisplayName) {
|
||||||
|
DshowDeviceEntry *entry = g_new0 (DshowDeviceEntry, 1);
|
||||||
|
gchar *device_path = NULL;
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
|
||||||
|
device_path = wchar_to_gchar (wszDisplayName);
|
||||||
|
CoTaskMemFree (wszDisplayName);
|
||||||
|
|
||||||
|
/* getting caps can be slow, so make it optional when enumerating */
|
||||||
|
if (getcaps) {
|
||||||
|
IBindCtx *lpbc = NULL;
|
||||||
|
hres = CreateBindCtx (0, &lpbc);
|
||||||
|
if (SUCCEEDED (hres)) {
|
||||||
|
IBaseFilter *video_cap_filter = NULL;
|
||||||
|
hres = moniker->BindToObject (lpbc, NULL, IID_IBaseFilter,
|
||||||
|
(LPVOID *) & video_cap_filter);
|
||||||
|
if (video_cap_filter) {
|
||||||
|
caps = gst_dshowvideosrc_getcaps_from_capture_filter (video_cap_filter, NULL);
|
||||||
|
video_cap_filter->Release ();
|
||||||
|
}
|
||||||
|
lpbc->Release ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->device = device_path;
|
||||||
|
entry->device_name = friendly_name;
|
||||||
|
entry->device_index = devidx;
|
||||||
|
entry->caps = caps;
|
||||||
|
entry->moniker = moniker;
|
||||||
|
moniker = NULL;
|
||||||
|
result = g_list_append (result, entry);
|
||||||
|
} else {
|
||||||
|
g_free (friendly_name);
|
||||||
|
}
|
||||||
|
SysFreeString (varFriendlyName.bstrVal);
|
||||||
|
}
|
||||||
|
property_bag->Release ();
|
||||||
|
}
|
||||||
|
if (moniker) {
|
||||||
|
moniker->Release ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
if (enum_moniker) {
|
||||||
|
enum_moniker->Release ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices_enum) {
|
||||||
|
devices_enum->Release ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DshowDeviceEntry *
|
||||||
|
gst_dshow_select_device (const GUID * device_category,
|
||||||
|
const gchar * device, const gchar * device_name, const gint device_index)
|
||||||
|
{
|
||||||
|
GList *devices = NULL;
|
||||||
|
GList *item = NULL;
|
||||||
|
DshowDeviceEntry *selected = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG ("Trying to select device-index=%d, device-name='%s', device='%s'",
|
||||||
|
device_index, device_name, device);
|
||||||
|
|
||||||
|
devices = gst_dshow_enumerate_devices (&CLSID_VideoInputDeviceCategory, FALSE);
|
||||||
|
|
||||||
|
for (item = devices; item != NULL; item = item->next) {
|
||||||
|
DshowDeviceEntry *entry = (DshowDeviceEntry *) item->data;
|
||||||
|
|
||||||
|
/* device will be used first, then device-name, then device-index */
|
||||||
|
if (device && g_strcmp0 (device, entry->device) == 0) {
|
||||||
|
selected = entry;
|
||||||
|
break;
|
||||||
|
} else if (device_name && g_strcmp0 (device_name, entry->device_name) == 0) {
|
||||||
|
selected = entry;
|
||||||
|
break;
|
||||||
|
} else if (device_index == entry->device_index) {
|
||||||
|
selected = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
devices = g_list_remove (devices, selected);
|
||||||
|
GST_DEBUG ("Selected device-index=%d, device-name='%s', device='%s'",
|
||||||
|
selected->device_index, selected->device_name, selected->device);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG ("No matching device found");
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_dshow_device_list_free (devices);
|
||||||
|
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
IBaseFilter *
|
||||||
|
gst_dshow_create_capture_filter (IMoniker *moniker)
|
||||||
|
{
|
||||||
|
HRESULT hres = S_OK;
|
||||||
|
IBindCtx *lpbc = NULL;
|
||||||
|
IBaseFilter *video_cap_filter = NULL;
|
||||||
|
|
||||||
|
g_assert (moniker != NULL);
|
||||||
|
|
||||||
|
hres = CreateBindCtx (0, &lpbc);
|
||||||
|
if (SUCCEEDED (hres)) {
|
||||||
|
hres = moniker->BindToObject (lpbc, NULL, IID_IBaseFilter,
|
||||||
|
(LPVOID *) & video_cap_filter);
|
||||||
|
lpbc->Release ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return video_cap_filter;
|
||||||
|
}
|
||||||
|
|
||||||
gchar *
|
gchar *
|
||||||
gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
||||||
|
@ -305,14 +500,14 @@ gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
||||||
hres = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
|
hres = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
|
||||||
IID_ICreateDevEnum, (void **) &devices_enum);
|
IID_ICreateDevEnum, (void **) &devices_enum);
|
||||||
if (hres != S_OK) {
|
if (hres != S_OK) {
|
||||||
/*error */
|
GST_ERROR ("Failed to create System Device Enumerator");
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = devices_enum->CreateClassEnumerator (*device_category,
|
hres = devices_enum->CreateClassEnumerator (*device_category,
|
||||||
&enum_moniker, 0);
|
&enum_moniker, 0);
|
||||||
if (hres != S_OK || !enum_moniker) {
|
if (hres != S_OK || !enum_moniker) {
|
||||||
/*error */
|
GST_ERROR ("Failed to create audio/video class device enumerator");
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,9 +525,7 @@ gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
||||||
|
|
||||||
hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL);
|
hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL);
|
||||||
if (hres == S_OK && varFriendlyName.bstrVal) {
|
if (hres == S_OK && varFriendlyName.bstrVal) {
|
||||||
gchar *friendly_name =
|
gchar *friendly_name = wchar_to_gchar (varFriendlyName.bstrVal);
|
||||||
g_utf16_to_utf8 ((const gunichar2 *) varFriendlyName.bstrVal,
|
|
||||||
wcslen (varFriendlyName.bstrVal), NULL, NULL, NULL);
|
|
||||||
|
|
||||||
devidx++;
|
devidx++;
|
||||||
GST_DEBUG ("Found device idx=%d: device-name='%s'",
|
GST_DEBUG ("Found device idx=%d: device-name='%s'",
|
||||||
|
@ -343,13 +536,13 @@ gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
||||||
*device_name = g_strdup (friendly_name);
|
*device_name = g_strdup (friendly_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*device_name && **device_name) && _stricmp (*device_name, friendly_name) == 0) {
|
if ((*device_name && **device_name)
|
||||||
|
&& _stricmp (*device_name, friendly_name) == 0) {
|
||||||
WCHAR *wszDisplayName = NULL;
|
WCHAR *wszDisplayName = NULL;
|
||||||
hres = moniker->GetDisplayName (NULL, NULL, &wszDisplayName);
|
hres = moniker->GetDisplayName (NULL, NULL, &wszDisplayName);
|
||||||
if (hres == S_OK && wszDisplayName) {
|
if (hres == S_OK && wszDisplayName) {
|
||||||
*device_index = devidx;
|
*device_index = devidx;
|
||||||
ret = g_utf16_to_utf8 ((const gunichar2 *) wszDisplayName,
|
ret = wchar_to_gchar (wszDisplayName);
|
||||||
wcslen (wszDisplayName), NULL, NULL, NULL);
|
|
||||||
CoTaskMemFree (wszDisplayName);
|
CoTaskMemFree (wszDisplayName);
|
||||||
}
|
}
|
||||||
bfound = TRUE;
|
bfound = TRUE;
|
||||||
|
|
|
@ -32,6 +32,17 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
|
typedef struct _DshowDeviceEntry DshowDeviceEntry;
|
||||||
|
|
||||||
|
struct _DshowDeviceEntry
|
||||||
|
{
|
||||||
|
gchar *device;
|
||||||
|
gchar *device_name;
|
||||||
|
gint device_index;
|
||||||
|
GstCaps *caps;
|
||||||
|
IMoniker *moniker;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _GstCapturePinMediaType
|
typedef struct _GstCapturePinMediaType
|
||||||
{
|
{
|
||||||
AM_MEDIA_TYPE *mediatype;
|
AM_MEDIA_TYPE *mediatype;
|
||||||
|
@ -102,4 +113,15 @@ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format,
|
||||||
/* configure the latency of the capture source */
|
/* configure the latency of the capture source */
|
||||||
bool gst_dshow_configure_latency (IPin *pCapturePin, guint bufSizeMS);
|
bool gst_dshow_configure_latency (IPin *pCapturePin, guint bufSizeMS);
|
||||||
|
|
||||||
|
/* enumerate devices of a given category (i.e., audio or video) */
|
||||||
|
void gst_dshow_device_entry_free (DshowDeviceEntry *entry);
|
||||||
|
void gst_dshow_device_list_free (GList * devices);
|
||||||
|
GList * gst_dshow_enumerate_devices (const GUID * device_category, gboolean getcaps);
|
||||||
|
|
||||||
|
DshowDeviceEntry * gst_dshow_select_device (const GUID * device_category,
|
||||||
|
const gchar *device, const gchar *device_name, const gint device_index);
|
||||||
|
|
||||||
|
/* create capture filter from moniker */
|
||||||
|
IBaseFilter *gst_dshow_create_capture_filter (IMoniker *moniker);
|
||||||
|
|
||||||
#endif /* _GSTDSHOW_ */
|
#endif /* _GSTDSHOW_ */
|
||||||
|
|
|
@ -89,13 +89,12 @@ static GstCaps *gst_dshowvideosrc_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
|
||||||
static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc,
|
static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc,
|
||||||
GstBuffer ** buf);
|
GstBuffer ** buf);
|
||||||
|
|
||||||
static gboolean gst_dshowvideosrc_create_capture_filter(GstDshowVideoSrc * src);
|
|
||||||
|
|
||||||
/*utils*/
|
/*utils*/
|
||||||
static GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc *
|
GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (IPin * pin,
|
||||||
src, IPin * pin);
|
GList ** pins_mediatypes);
|
||||||
static GstCaps *gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc *
|
GstCaps *gst_dshowvideosrc_getcaps_from_enum_mediatypes (IPin * pin,
|
||||||
src, IPin * pin);
|
GList ** pins_mediatypes);
|
||||||
|
|
||||||
static gboolean gst_dshowvideosrc_push_buffer (guint8 * buffer, guint size,
|
static gboolean gst_dshowvideosrc_push_buffer (guint8 * buffer, guint size,
|
||||||
gpointer src_object, GstClockTime duration);
|
gpointer src_object, GstClockTime duration);
|
||||||
|
|
||||||
|
@ -362,104 +361,62 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc, GstCaps * filter)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
GstCaps *
|
||||||
gst_dshowvideosrc_create_capture_filter(GstDshowVideoSrc * src)
|
gst_dshowvideosrc_getcaps_from_capture_filter (IBaseFilter * filter,
|
||||||
|
GList ** pins_mediatypes)
|
||||||
{
|
{
|
||||||
HRESULT hres = S_OK;
|
IPin *capture_pin = NULL;
|
||||||
IBindCtx *lpbc = NULL;
|
IEnumPins *enumpins = NULL;
|
||||||
IMoniker *videom;
|
HRESULT hres;
|
||||||
DWORD dwEaten;
|
GstCaps *caps;
|
||||||
gunichar2 *unidevice = NULL;
|
|
||||||
|
|
||||||
/* device will be used first, then device-name, then device-index */
|
g_assert (filter);
|
||||||
if (!src->device || src->device[0] == '\0') {
|
|
||||||
GST_DEBUG_OBJECT (src, "No device set, will enumerate to match device-name or device-index");
|
|
||||||
|
|
||||||
g_free (src->device);
|
caps = gst_caps_new_empty ();
|
||||||
src->device =
|
|
||||||
gst_dshow_getdevice_from_devicename (&CLSID_VideoInputDeviceCategory,
|
|
||||||
&src->device_name, &src->device_index);
|
|
||||||
if (!src->device) {
|
|
||||||
GST_ERROR ("No video device found.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "Opening device-index=%d, device-name='%s', device='%s'",
|
/* get the capture pins supported types */
|
||||||
src->device_index, src->device_name, src->device);
|
hres = filter->EnumPins (&enumpins);
|
||||||
|
if (SUCCEEDED (hres)) {
|
||||||
unidevice =
|
while (enumpins->Next (1, &capture_pin, NULL) == S_OK) {
|
||||||
g_utf8_to_utf16 (src->device, strlen (src->device), NULL, NULL, NULL);
|
IKsPropertySet *pKs = NULL;
|
||||||
|
|
||||||
if (!src->video_cap_filter) {
|
|
||||||
hres = CreateBindCtx (0, &lpbc);
|
|
||||||
if (SUCCEEDED (hres)) {
|
|
||||||
hres =
|
hres =
|
||||||
MkParseDisplayName (lpbc, (LPCOLESTR) unidevice, &dwEaten, &videom);
|
capture_pin->QueryInterface (IID_IKsPropertySet, (LPVOID *) & pKs);
|
||||||
if (SUCCEEDED (hres)) {
|
if (SUCCEEDED (hres) && pKs) {
|
||||||
hres = videom->BindToObject (lpbc, NULL, IID_IBaseFilter,
|
DWORD cbReturned;
|
||||||
(LPVOID *) & src->video_cap_filter);
|
GUID pin_category;
|
||||||
videom->Release ();
|
RPC_STATUS rpcstatus;
|
||||||
}
|
|
||||||
lpbc->Release ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (unidevice);
|
|
||||||
|
|
||||||
if (!src->caps) {
|
|
||||||
src->caps = gst_caps_new_empty ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src->video_cap_filter && gst_caps_is_empty (src->caps)) {
|
|
||||||
/* get the capture pins supported types */
|
|
||||||
IPin *capture_pin = NULL;
|
|
||||||
IEnumPins *enumpins = NULL;
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
hres = src->video_cap_filter->EnumPins (&enumpins);
|
|
||||||
if (SUCCEEDED (hres)) {
|
|
||||||
while (enumpins->Next (1, &capture_pin, NULL) == S_OK) {
|
|
||||||
IKsPropertySet *pKs = NULL;
|
|
||||||
hres =
|
hres =
|
||||||
capture_pin->QueryInterface (IID_IKsPropertySet, (LPVOID *) & pKs);
|
pKs->Get (AMPROPSETID_Pin,
|
||||||
if (SUCCEEDED (hres) && pKs) {
|
AMPROPERTY_PIN_CATEGORY, NULL, 0, &pin_category, sizeof (GUID),
|
||||||
DWORD cbReturned;
|
&cbReturned);
|
||||||
GUID pin_category;
|
|
||||||
RPC_STATUS rpcstatus;
|
|
||||||
|
|
||||||
hres =
|
/* we only want capture pins */
|
||||||
pKs->Get (AMPROPSETID_Pin,
|
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
|
||||||
AMPROPERTY_PIN_CATEGORY, NULL, 0, &pin_category, sizeof (GUID),
|
&rpcstatus) == 0) {
|
||||||
&cbReturned);
|
GstCaps *caps2;
|
||||||
|
caps2 = gst_dshowvideosrc_getcaps_from_streamcaps (capture_pin,
|
||||||
/* we only want capture pins */
|
pins_mediatypes);
|
||||||
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
|
if (caps2) {
|
||||||
&rpcstatus) == 0) {
|
gst_caps_append (caps, caps2);
|
||||||
{
|
} else {
|
||||||
GstCaps *caps =
|
caps2 = gst_dshowvideosrc_getcaps_from_enum_mediatypes (
|
||||||
gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin);
|
capture_pin, pins_mediatypes);
|
||||||
if (caps) {
|
if (caps2) {
|
||||||
GST_DEBUG_OBJECT (src, "Caps supported by device: %" GST_PTR_FORMAT, caps);
|
gst_caps_append (caps, caps2);
|
||||||
gst_caps_append (src->caps, caps);
|
|
||||||
} else {
|
|
||||||
caps = gst_dshowvideosrc_getcaps_from_enum_mediatypes (src, capture_pin);
|
|
||||||
if (caps) {
|
|
||||||
GST_DEBUG_OBJECT (src, "Caps supported by device: %" GST_PTR_FORMAT, caps);
|
|
||||||
gst_caps_append (src->caps, caps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pKs->Release ();
|
|
||||||
}
|
}
|
||||||
capture_pin->Release ();
|
pKs->Release ();
|
||||||
}
|
}
|
||||||
enumpins->Release ();
|
capture_pin->Release ();
|
||||||
}
|
}
|
||||||
|
enumpins->Release ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
GST_DEBUG ("Device supports these caps: %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -509,8 +466,40 @@ gst_dshowvideosrc_start (GstBaseSrc * bsrc)
|
||||||
{
|
{
|
||||||
HRESULT hres = S_FALSE;
|
HRESULT hres = S_FALSE;
|
||||||
GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (bsrc);
|
GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (bsrc);
|
||||||
|
DshowDeviceEntry *device_entry;
|
||||||
gst_dshowvideosrc_create_capture_filter (src);
|
IMoniker *moniker = NULL;
|
||||||
|
|
||||||
|
device_entry = gst_dshow_select_device (&CLSID_VideoInputDeviceCategory,
|
||||||
|
src->device, src->device_name, src->device_index);
|
||||||
|
if (device_entry == NULL) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to find device"), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (src->device);
|
||||||
|
g_free (src->device_name);
|
||||||
|
src->device = g_strdup (device_entry->device);
|
||||||
|
src->device_name = g_strdup (device_entry->device_name);
|
||||||
|
src->device_index = device_entry->device_index;
|
||||||
|
moniker = device_entry->moniker;
|
||||||
|
device_entry->moniker = NULL;
|
||||||
|
gst_dshow_device_entry_free (device_entry);
|
||||||
|
|
||||||
|
src->video_cap_filter = gst_dshow_create_capture_filter (moniker);
|
||||||
|
moniker->Release ();
|
||||||
|
if (src->video_cap_filter == NULL) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||||
|
("Failed to create capture filter for device"), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->caps = gst_dshowvideosrc_getcaps_from_capture_filter (
|
||||||
|
src->video_cap_filter, (GList**)&src->pins_mediatypes);
|
||||||
|
if (gst_caps_is_empty (src->caps)) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||||
|
("Failed to get any caps from devce"), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The filter graph now is created via the IGraphBuilder Interface
|
The filter graph now is created via the IGraphBuilder Interface
|
||||||
|
@ -600,6 +589,9 @@ gst_dshowvideosrc_start (GstBaseSrc * bsrc)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||||
|
("Failed to build filter graph"), (NULL));
|
||||||
|
|
||||||
if (src->dshow_fakesink) {
|
if (src->dshow_fakesink) {
|
||||||
src->dshow_fakesink->Release ();
|
src->dshow_fakesink->Release ();
|
||||||
src->dshow_fakesink = NULL;
|
src->dshow_fakesink = NULL;
|
||||||
|
@ -858,7 +850,12 @@ gst_dshowvideosrc_stop (GstBaseSrc * bsrc)
|
||||||
g_free (src->device);
|
g_free (src->device);
|
||||||
src->device = NULL;
|
src->device = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src->video_cap_filter) {
|
||||||
|
src->video_cap_filter->Release ();
|
||||||
|
src->video_cap_filter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,8 +909,8 @@ gst_dshowvideosrc_create (GstPushSrc * psrc, GstBuffer ** buf)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
GstCaps *
|
||||||
gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
gst_dshowvideosrc_getcaps_from_streamcaps (IPin * pin, GList ** pins_mediatypes)
|
||||||
{
|
{
|
||||||
GstCaps *caps = NULL;
|
GstCaps *caps = NULL;
|
||||||
HRESULT hres = S_OK;
|
HRESULT hres = S_OK;
|
||||||
|
@ -981,8 +978,9 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediacaps) {
|
if (mediacaps) {
|
||||||
src->pins_mediatypes =
|
if (pins_mediatypes != NULL) {
|
||||||
g_list_append (src->pins_mediatypes, pin_mediatype);
|
*pins_mediatypes = g_list_append (*pins_mediatypes, pin_mediatype);
|
||||||
|
}
|
||||||
gst_caps_append (caps, mediacaps);
|
gst_caps_append (caps, mediacaps);
|
||||||
} else {
|
} else {
|
||||||
/* failed to convert dshow caps */
|
/* failed to convert dshow caps */
|
||||||
|
@ -1001,8 +999,8 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
GstCaps *
|
||||||
gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc * src, IPin * pin)
|
gst_dshowvideosrc_getcaps_from_enum_mediatypes (IPin * pin, GList ** pins_mediatypes)
|
||||||
{
|
{
|
||||||
GstCaps *caps = NULL;
|
GstCaps *caps = NULL;
|
||||||
IEnumMediaTypes *enum_mediatypes = NULL;
|
IEnumMediaTypes *enum_mediatypes = NULL;
|
||||||
|
@ -1036,8 +1034,9 @@ gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc * src, IPin * p
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediacaps) {
|
if (mediacaps) {
|
||||||
src->pins_mediatypes =
|
if (pins_mediatypes != NULL) {
|
||||||
g_list_append (src->pins_mediatypes, pin_mediatype);
|
*pins_mediatypes = g_list_append (*pins_mediatypes, pin_mediatype);
|
||||||
|
}
|
||||||
gst_caps_append (caps, mediacaps);
|
gst_caps_append (caps, mediacaps);
|
||||||
} else {
|
} else {
|
||||||
/* failed to convert dshow caps */
|
/* failed to convert dshow caps */
|
||||||
|
|
|
@ -100,5 +100,10 @@ struct _GstDshowVideoSrcClass
|
||||||
|
|
||||||
GType gst_dshowvideosrc_get_type (void);
|
GType gst_dshowvideosrc_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
|
GstCaps * gst_dshowvideosrc_getcaps_from_capture_filter (IBaseFilter * filter,
|
||||||
|
GList ** pins_mediatypes);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* __GST_DSHOWVIDEOSRC_H__ */
|
#endif /* __GST_DSHOWVIDEOSRC_H__ */
|
||||||
|
|
Loading…
Reference in a new issue