如何使用Elgato预览实时更改分辨率

本文关键字:分辨率 实时 何使用 Elgato | 更新日期: 2023-09-27 17:59:54

我正在使用directshow预览连接到usb的Elgato设备的实时视频。

形式1:

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,所以它不会再次启动所有方法。

但在selectedindex changed事件中,当我调用etAndGetAllAvailableResolution(outPin)时;我在线获取异常:

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中的changeresolution选择索引事件时才调用它。然后它抛出异常。

那么我现在该怎么办呢?有人能透露/doscover并帮助我了解代码应该是什么样子吗?

如何使用Elgato预览实时更改分辨率

在连接引脚之前可以更改分辨率。如果它已连接并且流媒体处于活动状态,那么您需要停止,断开连接,像现在一样更改分辨率,然后重新连接并重新启动。