Sign in to follow this  
wh1sp3rik

[DXSHOW] Get webcam bitmap

Recommended Posts

wh1sp3rik    248

Hello,

 

Trying to figure out, how to get a bitmap from webcam output.

The problem is in colours. it seems a webcam output is YUV color space and i am not sure, how to display it right as most other examples are not care about that.

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 System.Runtime.InteropServices;
using System.Drawing.Imaging;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
        public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

        public IGraphBuilder gb;
        public ICaptureGraphBuilder2 cgb;
        public IBaseFilter filter;
        static SampleGrabberCallback cb;
        VideoInfoHeader header;
        static Form1 thisform;



        public class SampleGrabberCallback : ISampleGrabberCB
        {

            int ISampleGrabberCB.SampleCB(Double SampleTime, IMediaSample sample)
            {
                return 0;
            }

            int ISampleGrabberCB.BufferCB( Double SampleTime, IntPtr dataPtr, Int32 BufferLen ) 
            {                  
                Bitmap bitmap = new Bitmap(640, 480, 640*3, PixelFormat.Format24bbp, dataPtr);

                Graphics g = thisform.panel1.CreateGraphics();
                g.DrawImageUnscaled(bitmap, 0, 0, 640, 480);

                return 0;
            }
        }

        public Form1()
        {
            InitializeComponent();
            thisform = this;

            DsDevice[] videoInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);            
            object obj = null; Guid iid = typeof(IBaseFilter).GUID;
            videoInputDevices[1].Mon.BindToObject(null, null, ref iid, out obj);
            filter = (IBaseFilter)obj;
            ISampleGrabber grabberFilter = (ISampleGrabber)new SampleGrabber();
            IBaseFilter baseGrabber = (IBaseFilter)grabberFilter;

 

            ((IAMCameraControl)filter).Set(CameraControlProperty.Exposure, 0, CameraControlFlags.Auto);
            

            gb  = (IGraphBuilder) new FilterGraph();
            cgb = (ICaptureGraphBuilder2) new CaptureGraphBuilder2();
            
            cgb.SetFiltergraph(gb);
            

            IEnumPins pins;
            IPin [] inputPin = { null };
            IPin [] outputPin = { null };

            filter.EnumPins(out pins);
            pins.Next(1, outputPin, IntPtr.Zero);

            baseGrabber.EnumPins(out pins);
            pins.Next(1, inputPin, IntPtr.Zero);

            gb.AddFilter(filter, "First Filter");
            gb.AddFilter(baseGrabber, "Grabber Filter");
            gb.Connect(outputPin[0], inputPin[0]);


            grabberFilter.SetBufferSamples(true);

            AMMediaType media = new AMMediaType();
            media.majorType = MediaType.Video;
            media.subType = MediaSubType.RGB24;
            media.formatType = FormatType.VideoInfo;

            grabberFilter.SetMediaType(media);
            grabberFilter.GetConnectedMediaType(media);
            header = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader)); 


            cb = new SampleGrabberCallback();          

            grabberFilter.SetCallback(cb, 1);


            cgb.RenderStream(PinCategory.Preview, MediaType.Video, filter, null, null);
            ((IVideoWindow)gb).put_Owner(this.panel1.Handle);
            ((IVideoWindow)gb).put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
            ((IVideoWindow)gb).put_Visible(OABool.True);
            ((IVideoWindow)gb).SetWindowPosition(0, 0, this.panel1.Width, this.panel1.Height);
            ((IMediaControl)gb).Run();
        }

        private void OnResize(object sender, EventArgs e)
        {
            ((IVideoWindow)gb).SetWindowPosition(0, 0, this.panel1.Width, this.panel1.Height);
        }
    }
}

This is my code, it enumerate video devices ( my default device is number 1, you should use 0, if you have only one device ), SampleGrabber calls callback function and i can get a buffer there.

 

I tried most formats Format24bbp, Format16bpp565 .. and .. ok, if it's YUV, i should convert it, but i though i can just specify type in mediatype as examples are doing it.

 

I also attached full source with directshownet library. if someone has a time to check, i will be very happy as i am trying to figure it out whole a day, reading tutorials, samples ... smile.png

 

Thank you very much

Edited by wh1sp3rik

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this