protected void ProcessFrameReceived(object sender, NDI.VideoFrameReceivedEventArgs e)
        {
            if (!_BufferAllocated)
            {
                if (_FourCC != e.Frame.FourCC)
                {
                    string receivedFormatName = OutputFormat.FourCCToFormatName(e.Frame.FourCC);
                    if (receivedFormatName.Length == 0)
                    {
                        receivedFormatName = e.Frame.FourCC.ToString("X8");
                    }
                    _Log.Error($"Specified format {OutputFormat.Name} doesn't match NDI device format {receivedFormatName}");
                }

                _Log.Debug($"Creating video buffer {e.Frame.Width}x{e.Frame.Height} {OutputFormat.Name}");
                AllocateBuffer(e.Frame.Width, e.Frame.Height);
            }
            else if (e.Frame.Width != _Buffer.Width || e.Frame.Height != _Buffer.Height)
            {
                _Log.Debug($"Video size changed to {e.Frame.Width}x{e.Frame.Height}");
                if (e.Frame.Width * e.Frame.Height > _AllocatedPixels)
                {
                    // Only reallocate if pixel count increased
                    _Buffer.Free();
                    _BufferAllocated = false;
                    _Log.Debug($"Re-creating video buffer");
                    AllocateBuffer(e.Frame.Width, e.Frame.Height);
                }
                else
                {
                    _Buffer.Width  = e.Frame.Width;
                    _Buffer.Height = e.Frame.Height;
                    _Buffer.Stride = e.Frame.Stride;
                }
            }

            // Populate buffer with NDI frame data
            Marshal.Copy(e.Frame.BufferPtr, _Buffer.DataBuffer.Data, 0, e.Frame.Height * e.Frame.Stride);

            RaiseFrame(new VideoFrame(_Buffer));
        }