0

The device in the usb is legato game capture. The streaming preview in the pictureBox1 show the video from the device but it's not pixels that I can save from the pictureBox1 as images.

" There is no way to grab a shot of a window that is not actually being displayed. If the window is not completely visible, then those pixels simply do not exist. "

Another problem is that I can't find the legato game capture device in graphedit. I also tried graphedit plus. But the legato device not exist there in the list.

This is how i'm creating the preview and streaming it in 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);
        }
  }
} 

Now i tried to add this methods to use with the sample grabber:

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;
            }
        }

But i'm getting exception on the line:

hr = ((ISampleGrabber)pSampleGrabber).SetCallback(new SampleGrabberCallback(), 0);

Unable to cast COM object of type 'System.__ComObject' to interface type 'DirectShowLib.ISampleGrabber'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{6B652FFF-11FE-4FCE-92AD-0266B5D7C78F}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))

I guess i'm not using it right at all. And also I don't know how to use it later on to grab(save to hard disk) image/video of the streaming.

benny dayag
  • 139
  • 9

1 Answers1

0

The code around pSampleGrabber makes no sense. It expects a COM pointer to Sample Grabber Filter instance. No other filters are expected to implement ISampleGrabber. You however are trying to cast video capture filter to what it is not supposed to be (E_NOINTERFACE tells you exactly this!):

IBaseFilter pSampleGrabber = 
    (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(elgatoguid));

You need to add video capture filter, then create Sample Grabber instance, and then connect the two. Then render grabber's output. Then associate your callback with grabber instance.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • I can't find yet how to make the first step add a video capture filter. Tried to google but could not find. Is that so hard to do ? – benny dayag Apr 11 '16 at 23:16
  • Capture filter is created and added to the graph in your first posted code snippet (around `elgatoFilter`). – Roman R. Apr 12 '16 at 05:41