mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +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 "gstdshowfakesink.h"
|
||||
#include "gstdshowvideosrc.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (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
|
||||
= { 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
|
||||
0x71}
|
||||
|
@ -238,9 +245,7 @@ gst_dshow_find_filter (CLSID input_majortype, CLSID input_subtype,
|
|||
|
||||
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);
|
||||
friendly_name = wchar_to_gchar (varFriendlyName.bstrVal);
|
||||
if (friendly_name)
|
||||
_strupr (friendly_name);
|
||||
SysFreeString (varFriendlyName.bstrVal);
|
||||
|
@ -288,6 +293,196 @@ clean:
|
|||
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 *
|
||||
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,
|
||||
IID_ICreateDevEnum, (void **) &devices_enum);
|
||||
if (hres != S_OK) {
|
||||
/*error */
|
||||
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) {
|
||||
/*error */
|
||||
GST_ERROR ("Failed to create audio/video class device enumerator");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
|
@ -330,9 +525,7 @@ gst_dshow_getdevice_from_devicename (const GUID * device_category,
|
|||
|
||||
hres = property_bag->Read (L"FriendlyName", &varFriendlyName, NULL);
|
||||
if (hres == S_OK && varFriendlyName.bstrVal) {
|
||||
gchar *friendly_name =
|
||||
g_utf16_to_utf8 ((const gunichar2 *) varFriendlyName.bstrVal,
|
||||
wcslen (varFriendlyName.bstrVal), NULL, NULL, NULL);
|
||||
gchar *friendly_name = wchar_to_gchar (varFriendlyName.bstrVal);
|
||||
|
||||
devidx++;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
hres = moniker->GetDisplayName (NULL, NULL, &wszDisplayName);
|
||||
if (hres == S_OK && wszDisplayName) {
|
||||
*device_index = devidx;
|
||||
ret = g_utf16_to_utf8 ((const gunichar2 *) wszDisplayName,
|
||||
wcslen (wszDisplayName), NULL, NULL, NULL);
|
||||
ret = wchar_to_gchar (wszDisplayName);
|
||||
CoTaskMemFree (wszDisplayName);
|
||||
}
|
||||
bfound = TRUE;
|
||||
|
|
|
@ -32,6 +32,17 @@
|
|||
#include <gst/gst.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
|
||||
{
|
||||
AM_MEDIA_TYPE *mediatype;
|
||||
|
@ -102,4 +113,15 @@ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format,
|
|||
/* configure the latency of the capture source */
|
||||
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_ */
|
||||
|
|
|
@ -89,13 +89,12 @@ static GstCaps *gst_dshowvideosrc_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
|
|||
static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc,
|
||||
GstBuffer ** buf);
|
||||
|
||||
static gboolean gst_dshowvideosrc_create_capture_filter(GstDshowVideoSrc * src);
|
||||
|
||||
/*utils*/
|
||||
static GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc *
|
||||
src, IPin * pin);
|
||||
static GstCaps *gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc *
|
||||
src, IPin * pin);
|
||||
GstCaps *gst_dshowvideosrc_getcaps_from_streamcaps (IPin * pin,
|
||||
GList ** pins_mediatypes);
|
||||
GstCaps *gst_dshowvideosrc_getcaps_from_enum_mediatypes (IPin * pin,
|
||||
GList ** pins_mediatypes);
|
||||
|
||||
static gboolean gst_dshowvideosrc_push_buffer (guint8 * buffer, guint size,
|
||||
gpointer src_object, GstClockTime duration);
|
||||
|
||||
|
@ -362,104 +361,62 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc, GstCaps * filter)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dshowvideosrc_create_capture_filter(GstDshowVideoSrc * src)
|
||||
GstCaps *
|
||||
gst_dshowvideosrc_getcaps_from_capture_filter (IBaseFilter * filter,
|
||||
GList ** pins_mediatypes)
|
||||
{
|
||||
HRESULT hres = S_OK;
|
||||
IBindCtx *lpbc = NULL;
|
||||
IMoniker *videom;
|
||||
DWORD dwEaten;
|
||||
gunichar2 *unidevice = NULL;
|
||||
IPin *capture_pin = NULL;
|
||||
IEnumPins *enumpins = NULL;
|
||||
HRESULT hres;
|
||||
GstCaps *caps;
|
||||
|
||||
/* device will be used first, then device-name, then device-index */
|
||||
if (!src->device || src->device[0] == '\0') {
|
||||
GST_DEBUG_OBJECT (src, "No device set, will enumerate to match device-name or device-index");
|
||||
g_assert (filter);
|
||||
|
||||
g_free (src->device);
|
||||
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;
|
||||
}
|
||||
}
|
||||
caps = gst_caps_new_empty ();
|
||||
|
||||
GST_DEBUG_OBJECT (src, "Opening device-index=%d, device-name='%s', device='%s'",
|
||||
src->device_index, src->device_name, src->device);
|
||||
|
||||
unidevice =
|
||||
g_utf8_to_utf16 (src->device, strlen (src->device), NULL, NULL, NULL);
|
||||
|
||||
if (!src->video_cap_filter) {
|
||||
hres = CreateBindCtx (0, &lpbc);
|
||||
if (SUCCEEDED (hres)) {
|
||||
/* get the capture pins supported types */
|
||||
hres = filter->EnumPins (&enumpins);
|
||||
if (SUCCEEDED (hres)) {
|
||||
while (enumpins->Next (1, &capture_pin, NULL) == S_OK) {
|
||||
IKsPropertySet *pKs = NULL;
|
||||
hres =
|
||||
MkParseDisplayName (lpbc, (LPCOLESTR) unidevice, &dwEaten, &videom);
|
||||
if (SUCCEEDED (hres)) {
|
||||
hres = videom->BindToObject (lpbc, NULL, IID_IBaseFilter,
|
||||
(LPVOID *) & src->video_cap_filter);
|
||||
videom->Release ();
|
||||
}
|
||||
lpbc->Release ();
|
||||
}
|
||||
}
|
||||
capture_pin->QueryInterface (IID_IKsPropertySet, (LPVOID *) & pKs);
|
||||
if (SUCCEEDED (hres) && pKs) {
|
||||
DWORD cbReturned;
|
||||
GUID pin_category;
|
||||
RPC_STATUS rpcstatus;
|
||||
|
||||
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 =
|
||||
capture_pin->QueryInterface (IID_IKsPropertySet, (LPVOID *) & pKs);
|
||||
if (SUCCEEDED (hres) && pKs) {
|
||||
DWORD cbReturned;
|
||||
GUID pin_category;
|
||||
RPC_STATUS rpcstatus;
|
||||
pKs->Get (AMPROPSETID_Pin,
|
||||
AMPROPERTY_PIN_CATEGORY, NULL, 0, &pin_category, sizeof (GUID),
|
||||
&cbReturned);
|
||||
|
||||
hres =
|
||||
pKs->Get (AMPROPSETID_Pin,
|
||||
AMPROPERTY_PIN_CATEGORY, NULL, 0, &pin_category, sizeof (GUID),
|
||||
&cbReturned);
|
||||
|
||||
/* we only want capture pins */
|
||||
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
|
||||
&rpcstatus) == 0) {
|
||||
{
|
||||
GstCaps *caps =
|
||||
gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin);
|
||||
if (caps) {
|
||||
GST_DEBUG_OBJECT (src, "Caps supported by device: %" GST_PTR_FORMAT, caps);
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* we only want capture pins */
|
||||
if (UuidCompare (&pin_category, (UUID *) & PIN_CATEGORY_CAPTURE,
|
||||
&rpcstatus) == 0) {
|
||||
GstCaps *caps2;
|
||||
caps2 = gst_dshowvideosrc_getcaps_from_streamcaps (capture_pin,
|
||||
pins_mediatypes);
|
||||
if (caps2) {
|
||||
gst_caps_append (caps, caps2);
|
||||
} else {
|
||||
caps2 = gst_dshowvideosrc_getcaps_from_enum_mediatypes (
|
||||
capture_pin, pins_mediatypes);
|
||||
if (caps2) {
|
||||
gst_caps_append (caps, caps2);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
@ -509,8 +466,40 @@ gst_dshowvideosrc_start (GstBaseSrc * bsrc)
|
|||
{
|
||||
HRESULT hres = S_FALSE;
|
||||
GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (bsrc);
|
||||
|
||||
gst_dshowvideosrc_create_capture_filter (src);
|
||||
DshowDeviceEntry *device_entry;
|
||||
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
|
||||
|
@ -600,6 +589,9 @@ gst_dshowvideosrc_start (GstBaseSrc * bsrc)
|
|||
return TRUE;
|
||||
|
||||
error:
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||
("Failed to build filter graph"), (NULL));
|
||||
|
||||
if (src->dshow_fakesink) {
|
||||
src->dshow_fakesink->Release ();
|
||||
src->dshow_fakesink = NULL;
|
||||
|
@ -858,7 +850,12 @@ gst_dshowvideosrc_stop (GstBaseSrc * bsrc)
|
|||
g_free (src->device);
|
||||
src->device = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (src->video_cap_filter) {
|
||||
src->video_cap_filter->Release ();
|
||||
src->video_cap_filter = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -912,8 +909,8 @@ gst_dshowvideosrc_create (GstPushSrc * psrc, GstBuffer ** buf)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
||||
GstCaps *
|
||||
gst_dshowvideosrc_getcaps_from_streamcaps (IPin * pin, GList ** pins_mediatypes)
|
||||
{
|
||||
GstCaps *caps = NULL;
|
||||
HRESULT hres = S_OK;
|
||||
|
@ -981,8 +978,9 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
|||
}
|
||||
|
||||
if (mediacaps) {
|
||||
src->pins_mediatypes =
|
||||
g_list_append (src->pins_mediatypes, pin_mediatype);
|
||||
if (pins_mediatypes != NULL) {
|
||||
*pins_mediatypes = g_list_append (*pins_mediatypes, pin_mediatype);
|
||||
}
|
||||
gst_caps_append (caps, mediacaps);
|
||||
} else {
|
||||
/* failed to convert dshow caps */
|
||||
|
@ -1001,8 +999,8 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin)
|
|||
return caps;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc * src, IPin * pin)
|
||||
GstCaps *
|
||||
gst_dshowvideosrc_getcaps_from_enum_mediatypes (IPin * pin, GList ** pins_mediatypes)
|
||||
{
|
||||
GstCaps *caps = NULL;
|
||||
IEnumMediaTypes *enum_mediatypes = NULL;
|
||||
|
@ -1036,8 +1034,9 @@ gst_dshowvideosrc_getcaps_from_enum_mediatypes (GstDshowVideoSrc * src, IPin * p
|
|||
}
|
||||
|
||||
if (mediacaps) {
|
||||
src->pins_mediatypes =
|
||||
g_list_append (src->pins_mediatypes, pin_mediatype);
|
||||
if (pins_mediatypes != NULL) {
|
||||
*pins_mediatypes = g_list_append (*pins_mediatypes, pin_mediatype);
|
||||
}
|
||||
gst_caps_append (caps, mediacaps);
|
||||
} else {
|
||||
/* failed to convert dshow caps */
|
||||
|
|
|
@ -100,5 +100,10 @@ struct _GstDshowVideoSrcClass
|
|||
|
||||
GType gst_dshowvideosrc_get_type (void);
|
||||
|
||||
|
||||
GstCaps * gst_dshowvideosrc_getcaps_from_capture_filter (IBaseFilter * filter,
|
||||
GList ** pins_mediatypes);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_DSHOWVIDEOSRC_H__ */
|
||||
|
|
Loading…
Reference in a new issue