Question

I am getting wrong image result from SampleGrabber filter. Instead of colourfull image, image is in grayscale with red/green pixels between and image is repeated twice horizontaly.

I had to forget something important.

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
    {
        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.Format24bppRgb, 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.formatPtr = IntPtr.Zero;

            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);
            ((IMediaControl)gb).Run();
        }
    }
}

This is my code. I enumerated all video devices. My device has ID 1. I created filter where webcam data is passed then i connected samplegrabber filter to the previous filter. Callback function is called when image is ready.

Unfortunately, image output is wrong and i have no idea why.

Also callback says bufferlen is 614 400 bytes. Strange as it means that pixel has only 16 bits. (640*480*2). Does it mean, buffer has different colorspace ? YUV ? Most examples does not care about color space and it's working fine. Also i specified RGB24 in mediaType.

Thank you very much for helping me.

Was it helpful?

Solution

You are supposed to set your Sample Grabber up before connecting its input. Your request to make it 24-bit RGB is late and your actual connection and media type is different. You are still ignoring this on your callback and hence the broken picture.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top