2015-06-26 8 views
-1

Я использую directshow для предварительного просмотра видео в реальном времени с устройства Elgato, подключенного к 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(); 
     } 
    } 
} 

EDIT

В случае 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); I; м адресности исключение на линии:

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 и начать все сначала.

В другой стороны, если я "м не повторный вызов InitDevice в ComboBox1 выбранного индекса события, то он будет бросать исключение.

Прежде чем я назвал SetAndGetAllAvailableResolution() перед подключением контактов в графике. Но теперь я 'm, называя это только тогда, когда разрешение изменения в выбранном событии индексирования comboBox1, а затем генерирует исключение.

Итак, что мне теперь делать? Может ли кто-нибудь открыть/doscover и помочь мне в том, как должен выглядеть код?

+0

Возможно, слишком много информации ... большинство людей не прочтут это извините. – kjbartel

ответ

1

Разрешение может быть изменено до вывода i s подключен. Если он подключен и потоковая передача активна, вам необходимо остановить, отключить его, изменить разрешение, как сейчас, а затем подключиться обратно и перезагрузить.

+0

Я отредактировал мой вопрос, и после изменений, которые я проверил с точкой останова при изменении разрешения, он останавливает mediaControl, а затем он снова становится на нижней части mediaContro.Run(); но видео никогда не будет продолжаться. И я также не уверен, что я снова подключу outPin. –

+0

Итак, вы что-то делаете, а затем «InitDevice» начинает его с самого начала? В любом случае, вам придется отлаживать его. –