usb中的设备是连续游戏捕获。 pictureBox1中的流式预览显示了来自设备的视频,但它不是我可以从pictureBox1保存为像素的像素。
“没有办法抓住实际上没有显示的窗口的镜头。如果窗口不完全可见,那么这些像素根本不存在。”
另一个问题是我在graphedit中找不到连奏游戏捕捉设备。我也试过graphedit plus。但是列表中没有连奏设备。
这就是我在pictureBox1中创建预览和流式传输的方式
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;
using System.IO;
using System.Drawing.Imaging;
namespace Youtube_Manager
{
public partial class Elgato_Video_Capture : Form
{
IFileSinkFilter sink;
IFilterGraph2 graph;
ICaptureGraphBuilder2 captureGraph;
System.Drawing.Size videoSize;
string error = "";
List<Object> devices = new List<Object>();
IMediaControl mediaControl;
public Elgato_Video_Capture()
{
InitializeComponent();
if (comboBox1.Items.Count == 0)
{
for (int xx = 1; xx <= 8; xx++)
{
comboBox1.Items.Add(xx);
}
}
InitDevice();
timer1.Start();
}
IBaseFilter smartTeeFilter;
IPin outPin;
IPin inPin;
private void InitDevice()
{
try
{
//Set the video size to use for capture and recording
videoSize = new Size(827, 505);//1280, 720);
//Initialize filter graph and capture graph
graph = (IFilterGraph2)new FilterGraph();
captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(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
smartTeeFilter = (IBaseFilter)new SmartTee();
graph.AddFilter(smartTeeFilter, "Smart Tee");
outPin = GetPin(elgatoFilter, "Video");
inPin = GetPin(smartTeeFilter, "Input");
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(smartTeeFilter, "Preview");
inPin = GetPin(videoRendererFilter, "Input");
graph.Connect(outPin, inPin);
// int hr = graph.Connect(outPin, inPin); ;
// DsError.ThrowExceptionForHR(hr);
captureGraph.SetOutputFileName(MediaSubType.Avi, @"e:\screenshots\test1.mp4", out smartTeeFilter, out sink);
//Render stream from video renderer
captureGraph.RenderStream(PinCategory.VideoPort, 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, 827, 505);
//Start the preview
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);
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 == 2)// 4
{
CorectvidFormat = searchmedia;
}
}
hr = streamConfig.SetFormat(CorectvidFormat);
IntPtr pmt = IntPtr.Zero;
AMMediaType mediaType = new AMMediaType();
IAMStreamConfig streamConfig1 = (IAMStreamConfig)VideoOutPin;
hr = streamConfig1.GetFormat(out mediaType);
BitmapInfoHeader bmpih = new BitmapInfoHeader();
Marshal.PtrToStructure(mediaType.formatPtr, bmpih);
}
}
}
现在我尝试添加此方法以与样本采集器一起使用:
private void AddSampleGrabber(int hr, Guid elgatoguid, IFilterGraph2 pGraph)
{
//add SampleGrabber
IBaseFilter pSampleGrabber = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(elgatoguid));
hr = pGraph.AddFilter(pSampleGrabber, "SampleGrabber");
checkHR(hr, "Can't add SampleGrabber to graph");
//set callback
hr = ((ISampleGrabber)pSampleGrabber).SetCallback(new SampleGrabberCallback(), 0);
checkHR(hr, "Can't set callback.");
AMMediaType pmt = new AMMediaType();
pmt.majorType = MediaType.Video;
pmt.subType = MediaSubType.YUY2;
pmt.formatType = FormatType.VideoInfo;
pmt.fixedSizeSamples = true;
pmt.formatSize = 88;
pmt.sampleSize = 614400;
pmt.temporalCompression = false;
VideoInfoHeader format = new VideoInfoHeader();
format.SrcRect = new DsRect();
format.TargetRect = new DsRect();
format.BmiHeader = new BitmapInfoHeader();
format.BmiHeader.Size = 40;
format.BmiHeader.Width = 640;
format.BmiHeader.Height = 480;
format.BmiHeader.Planes = 1;
format.BmiHeader.BitCount = 16;
format.BmiHeader.Compression = 844715353;
format.BmiHeader.ImageSize = 614400;
pmt.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(format));
Marshal.StructureToPtr(format, pmt.formatPtr, false);
hr = ((IAMStreamConfig)GetPin(smartTeeFilter, "Capture")).SetFormat(pmt);
DsUtils.FreeAMMediaType(pmt);
checkHR(hr, "Can't set format");
//connect USB2.0 Camera and SampleGrabber
hr = pGraph.ConnectDirect(GetPin(smartTeeFilter, "Capture"), GetPin(pSampleGrabber, "Input"), null);
checkHR(hr, "Can't connect USB2.0 Camera and SampleGrabber");
//render the video
hr = captureGraph.RenderStream(null, null, pSampleGrabber, null, null);
checkHR(hr, "Can't render video from grabber");
}
class SampleGrabberCallback : ISampleGrabberCB
{
public SampleGrabberCallback()
{
}
public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
return 0;
}
public int SampleCB(double SampleTime, IMediaSample pSample)
{
if (pSample == null) return -1;
int len = pSample.GetActualDataLength();
IntPtr pbuf;
if (pSample.GetPointer(out pbuf) == 0 && len > 0)
{
byte[] buf = new byte[len];
Marshal.Copy(pbuf, buf, 0, len);
for (int i = 0; i < len; i += 2)
buf[i] = (byte)(255 - buf[i]);
Marshal.Copy(buf, 0, pbuf, len);
}
return 0;
}
}
但我在线上有例外:
hr = ((ISampleGrabber)pSampleGrabber).SetCallback(new SampleGrabberCallback(), 0);
无法将“System .__ ComObject”类型的COM对象强制转换为接口类型“DirectShowLib.ISampleGrabber”。此操作失败,因为对IID为“{6B652FFF-11FE-4FCE-92AD-0266B5D7C78F}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))
我想我根本就没用它。 而且我也不知道如何在以后使用它来抓取(保存到硬盘)流媒体的图像/视频。
答案 0 :(得分:0)
围绕pSampleGrabber
的代码毫无意义。它期望COM指针指向Sample Grabber Filter实例。预计其他过滤器不会实现ISampleGrabber
。然而,您正在尝试将视频捕获过滤器投射到它不应该的位置(E_NOINTERFACE
告诉您这一点!):
IBaseFilter pSampleGrabber =
(IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(elgatoguid));
您需要添加视频捕获过滤器,然后创建Sample Grabber实例,然后连接两者。然后渲染抓取器的输出。然后将您的回调与抓取器实例相关联。