我正在使用directshow预览连接到USB的Elgato设备的实时视频。
在form1中:
private void button3_Click(object sender, EventArgs e)
{
Elgato_Video_Capture evc = new Elgato_Video_Capture();
evc.Show();
}
然后是新表格:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DirectShowLib;
using DirectShowLib.BDA;
using DirectShowLib.DES;
using DirectShowLib.DMO;
using DirectShowLib.Dvd;
using DirectShowLib.MultimediaStreaming;
using DirectShowLib.SBE;
using System.Runtime.InteropServices;
using System.Management;
namespace Youtube_Manager
{
public partial class Elgato_Video_Capture : Form
{
IAMStreamConfig iasc;
IFilterGraph2 graph;
ICaptureGraphBuilder2 captureGraph;
IBaseFilter elgatoFilter;
IBaseFilter smartTeeFilter;
IBaseFilter videoRendererFilter;
Size videoSize;
string error = "";
List<Object> devices = new List<Object>();
public Elgato_Video_Capture()
{
InitializeComponent();
InitDevice();
}
private void InitDevice()
{
try
{
//Set the video size to use for capture and recording
videoSize = new Size(640, 480);//827, 505);//1280, 720);
//Initialize filter graph and capture graph
graph = (IFilterGraph2)new FilterGraph();
captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graph);
//rot = new DsROTEntry(graph);
//Create filter for Elgato
Guid elgatoGuid = new Guid("39F50F4C-99E1-464A-B6F9-D605B4FB5918");
Type comType = Type.GetTypeFromCLSID(elgatoGuid);
IBaseFilter elgatoFilter = (IBaseFilter)Activator.CreateInstance(comType);
graph.AddFilter(elgatoFilter, "Elgato Video Capture Filter");
//Create smart tee filter, add to graph, connect Elgato's video out to smart tee in
IBaseFilter smartTeeFilter = (IBaseFilter)new SmartTee();
graph.AddFilter(smartTeeFilter, "Smart Tee");
IPin outPin = GetPin(elgatoFilter, "Video"); //GetPin(PinDirection.Output, "Video", elgatoFilter);
//IPin inPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Input, smartTeeFilter);
IPin inPin = GetPin(smartTeeFilter, "Input");//GetPin(PinDirection.Input, smartTeeFilter);
SetAndGetAllAvailableResolution(outPin);
graph.Connect(outPin, inPin);
//Create video renderer filter, add it to graph, connect smartTee Preview pin to video renderer's input pin
IBaseFilter videoRendererFilter = (IBaseFilter)new VideoRenderer();
graph.AddFilter(videoRendererFilter, "Video Renderer");
// outPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Output, "Preview", smartTeeFilter);
outPin = GetPin(smartTeeFilter, "Preview");//GetPin(PinDirection.Output, "Preview", smartTeeFilter);
//outPin = GetPin(smartTeeFilter, "Capture");//GetPin(PinDirection.Output, "Preview", smartTeeFilter);
//inPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Input, videoRendererFilter);
inPin = GetPin(videoRendererFilter, "Input");//GetPin(PinDirection.Input, videoRendererFilter);
graph.Connect(outPin, inPin);
//Render stream from video renderer
captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, videoRendererFilter, null, null);
//Set the video preview to be the videoFeed panel
IVideoWindow vw = (IVideoWindow)graph;
vw.put_Owner(pictureBox1.Handle);
vw.put_MessageDrain(this.Handle);
vw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings | WindowStyle.ClipChildren);
vw.SetWindowPosition(0, 0, 640, 480);//1280, 720);
//Start the preview
IMediaControl mediaControl = graph as IMediaControl;
mediaControl.Run();
}
catch (Exception err)
{
error = err.ToString();
}
}
IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
checkHR(-1, "Pin not found");
return null;
}
public void checkHR(int hr, string msg)
{
if (hr < 0)
{
MessageBox.Show(msg);
DsError.ThrowExceptionForHR(hr);
}
}
public void SetAndGetAllAvailableResolution(IPin VideoOutPin)
{
int hr = 0;
IAMStreamConfig streamConfig = (IAMStreamConfig)VideoOutPin;
AMMediaType searchmedia;
AMMediaType CorectvidFormat = new AMMediaType();
IntPtr ptr;
int piCount, piSize;
hr = streamConfig.GetNumberOfCapabilities(out piCount, out piSize);
ptr = Marshal.AllocCoTaskMem(piSize);
if (comboBox1.Items.Count == 0)
{
for (int xx = 1; xx <= piCount; xx++)
{
comboBox1.Items.Add(xx);
}
}
for (int i = 0; i < piCount; i++)
{
hr = streamConfig.GetStreamCaps(i, out searchmedia, ptr);
VideoInfoHeader v = new VideoInfoHeader();
Marshal.PtrToStructure(searchmedia.formatPtr, v);
if (i == comboBox1.SelectedIndex)//2)// 4
{
CorectvidFormat = searchmedia;
}
}
hr = streamConfig.SetFormat(CorectvidFormat);
}
private void Elgato_Video_Capture_Load(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
InitDevice();
}
}
}
修改
在我现在做的comboBox1 selecyedindex事件中:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (resolutionChanged == true)
{
mediaControl.Stop();
outPin.Disconnect();
SetAndGetAllAvailableResolution(outPin);
outPin.Connect(outPin, null);
mediaControl.Run();
}
}
问题是我没有再次调用InitDevice,因此它不会再次启动所有方法。
但是当我调用etAndGetAllAvailableResolution(outPin)时,在selectedindex更改事件中; 我在线上发现异常:
IAMStreamConfig streamConfig = (IAMStreamConfig)VideoOutPin;
InvalidCastException的
Unable to cast COM object of type 'System.__ComObject' to interface type 'DirectShowLib.IAMStreamConfig'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{C6E13340-30AC-11D0-A18C-00A0C9118956}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))
所以从一方面我不想做出改变然后再调用InitDevice并重新开始。
另一方面,如果我没有在comboBox1选择的索引事件中再次调用InitDevice,那么它将抛出异常。
在连接图中的引脚之前,我调用了SetAndGetAllAvailableResolution()之前。但是现在我只是在comboBox1选择索引事件中更改分辨率时才调用它。然后抛出异常。
那我现在该怎么办? 有人可以透露/ doscover并帮助我了解代码的外观吗?
答案 0 :(得分:1)
在连接引脚之前可以更改分辨率。如果已连接且流式处于活动状态,则需要停止,断开连接,更改分辨率,然后再连接并重新启动。