private (LocalAudioSourceCapability[] caps, bool success) GetCapabilities(DsDevice device) { Log.Information($"Audio ({device.Name}): Getting Caps"); var list = new List <LocalAudioSourceCapability>(); bool failed = false; IntPtr pCaps = IntPtr.Zero; IFilterGraph2 filterGraph2 = null; IBaseFilter sourceFilter = null; IAMStreamConfig streamConfig = null; object pin = null; int count = 0; int size = 0; try { filterGraph2 = new FilterGraph() as IFilterGraph2; if (filterGraph2 == null) { throw new NotSupportedException("filter2 is null"); } LocalVideoSourceManager.AddCaptureFilter(filterGraph2, device, out sourceFilter); pin = DsFindPin.ByCategory(sourceFilter, PinCategory.Capture, 0); if (pin == null) { Log.Information($"Audio ({device.Name}): First pin is null"); pin = sourceFilter; } streamConfig = pin as IAMStreamConfig; if (streamConfig == null) { throw new NotSupportedException("pin is null"); } LocalVideoSourceManager.Checked(() => streamConfig.GetNumberOfCapabilities(out count, out size), "GetNumberOfCapabilities", null); if (count <= 0) { throw new NotSupportedException("This video source does not report capabilities."); } if (size != Marshal.SizeOf(typeof(AudioStreamConfigCaps))) { throw new NotSupportedException("Unable to retrieve video source capabilities. This video source requires a larger VideoStreamConfigCaps structure."); } // Alloc memory for structure pCaps = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(AudioStreamConfigCaps))); for (int i = 0; i < count; i++) { AMMediaType mediaType = null; LocalVideoSourceManager.Checked(() => streamConfig.GetStreamCaps(i, out mediaType, pCaps), "GetStreamCaps", null); AudioStreamConfigCaps caps = (AudioStreamConfigCaps)Marshal.PtrToStructure(pCaps, typeof(AudioStreamConfigCaps)); var result = new LocalAudioSourceCapability() { MinimumChannels = caps.MinimumChannels, MaximumChannels = caps.MaximumChannels, MinimumSampleFrequency = caps.MinimumSampleFrequency, MaximumSampleFrequency = caps.MaximumSampleFrequency }; list.Add(result); } } catch (Exception e) { Log.Error(e, $"Error during retreiving caps for '{device.Name}'"); failed = true; } finally { if (pCaps != IntPtr.Zero) { Marshal.FreeCoTaskMem(pCaps); } } Log.Information($"Audio ({device.Name}): Releasing"); try { LocalVideoSourceManager.ReleaseComObject(sourceFilter); LocalVideoSourceManager.ReleaseComObject(filterGraph2); LocalVideoSourceManager.ReleaseComObject(streamConfig); LocalVideoSourceManager.ReleaseComObject(pin); } catch (Exception e) { Log.Error(e, $"ReleaseComObject({device.Name}) failed"); } Log.Information($"Caps {device.Name}: Count: {list.Count}/{count}, Str={size} ({string.Join("; ", list.Where(s => !s.IsStandart()).Select(s => s.ToString()))})"); return(list.ToArray(), !failed); }
private (LocalVideoSourceCapability[] caps, InputDeviceState state) GetCapabilities(DsDevice device) { if (_initialLogging) { Log.Information($"Caps {device.Name}: getting"); } var list = new List <LocalVideoSourceCapability>(); IntPtr pCaps = IntPtr.Zero; IFilterGraph2 filterGraph2 = null; IBaseFilter sourceFilter = null; IAMStreamConfig streamConfig = null; object pin = null; InputDeviceState state = InputDeviceState.Ready; try { filterGraph2 = new FilterGraph() as IFilterGraph2; if (filterGraph2 == null) { throw new NotSupportedException("filter2 is null"); } LocalVideoSourceManager.AddCaptureFilter(filterGraph2, device, out sourceFilter); pin = DsFindPin.ByCategory(sourceFilter, PinCategory.Capture, 0); if (pin == null) { pin = sourceFilter; } streamConfig = pin as IAMStreamConfig; if (streamConfig == null) { throw new NotSupportedException("pin is null"); } int count = 0; int size = 0; Checked(() => streamConfig.GetNumberOfCapabilities(out count, out size), "GetNumberOfCapabilities", null); if (count <= 0) { throw new NotSupportedException("This video source does not report capabilities."); } if (size != Marshal.SizeOf(typeof(VideoStreamConfigCaps))) { throw new NotSupportedException("Unable to retrieve video source capabilities. This video source requires a larger VideoStreamConfigCaps structure."); } // Alloc memory for structure pCaps = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(VideoStreamConfigCaps))); for (int i = 0; i < count; i++) { AMMediaType mediaType = null; Checked(() => streamConfig.GetStreamCaps(i, out mediaType, pCaps), "GetStreamCaps", null); VideoStreamConfigCaps caps = (VideoStreamConfigCaps)Marshal.PtrToStructure(pCaps, typeof(VideoStreamConfigCaps)); var format = GetMediaTypeInfo(mediaType, out var height, out var width, out var compression, out var videoInfoHeader, out var videoInfoHeader2); var result = new LocalVideoSourceCapability() { MaxF = GetFps(caps.MinFrameInterval), MinF = GetFps(caps.MaxFrameInterval), Fmt = format, W = width, H = height, }; list.Add(result); } } catch (UnauthorizedAccessException e) { Log.Warning(e, $"Error during retreiving caps for '{device.Name}' (Locked)"); state = InputDeviceState.Locked; } catch (Exception e) { Log.Error(e, $"Error during retreiving caps for '{device.Name}'"); state = InputDeviceState.Failed; } finally { if (pCaps != IntPtr.Zero) { Marshal.FreeCoTaskMem(pCaps); } } try { ReleaseComObject(sourceFilter); ReleaseComObject(filterGraph2); ReleaseComObject(streamConfig); ReleaseComObject(pin); } catch (Exception e) { Log.Error(e, $"ReleaseComObject('{device.Name}') failed"); } if (_initialLogging) { Log.Information($"Caps {device.Name}: {string.Join("; ", list.Select(s => s.ToString()))}"); } return(list.ToArray(), state); }