danielp - 2007-07-11

Maybe this should become the "hello world" of filters programming, a filter to turn video to gray scale.

The following code is my first transform filter, it only handles YUY2 input and output video type (80 lines "all included" ;-)

    public class GrayFilter : Filter
    {
        private InputPin   _inputPin;   // one input pin and one output pin
        private IOutputPin _outputPin;
        private IMediaType _vidType;    // store our video type

        public GrayFilter()
            : base("GrayFilter")
        {
            _inputPin = new InputPin("Input", this);
            _inputPin.CheckMediaTypeEvent += new CheckMediaTypeEventHandler(checkMediaTypeHandler);

            _outputPin = new DoGrayOutputPin("Output", this);
        }

        bool checkMediaTypeHandler(IInputPin p, IMediaType mt)
        {
            IVideoType vt = mt as IVideoType;
            if (vt == null || vt.Id != MediaType.YUY2)
                return false;
            else
            {
                // return true only for yuy2 and store the video type away
                _vidType = mt;
                return true;
            }
        }

        public override IEnumerable<IPin> Pins
        {
            get
            {
                yield return _inputPin; 
                yield return _outputPin; 
            }
        }

        unsafe public override void Receive(ISampleStream sender, ISample sample)
        {
            base.Receive(sender, sample);

            IMediaSample s = sample as IMediaSample;
            if (s != null)
            {
                // yuy2 is a packed format with 2 macro pix per uint
                // just overwrite every other bytes
                int length = s.Data.Length;
                fixed (byte* bptr = s.Data)
                {
                    for (int i = 1; i &lt; length; i += 2)
                        bptr[i] = (byte)128;
                }
            }
            // pass the sample along
            _outputPin.Receive(this, sample);

        }

        // need to define our outpin type since OutputPin is abstract
        public class DoGrayOutputPin : OutputPin
        {
            public DoGrayOutputPin(string name, IFilter owner)
                : base(name, owner)
            {
            }

            public override IEnumerable<IMediaType> OutputMediaTypes
            {
                get
                {
                    GrayFilter f = Owner as GrayFilter;                   
                    // return the video type of the input pin if it's connected
                    if (f != null && f._inputPin.Connected != null)
                        yield return f._vidType;
                    else
                        yield return null;
                }
            }
        }

    }

Just add the previous class and the following changes to testapp.cs:
(after the call to _graph.AddSource(...

IFilter doGrayFilter = new GrayFilter();
_graph.Connect(filter, doGrayFilter, true);

_graph.Render(doGrayFilter);

Since this is pretty new to everyone, your comments and suggestions are welcome.