/// <summary> /// Stop streaming buffers and close device. /// </summary> public void Close() { LinuxVideoInterop.StreamOff(this.handle); if (this.file != null) { this.file.Close(); this.file.Dispose(); } }
/// <summary> /// Enumerate supported pixel formats. /// </summary> /// <returns>Supported formats.</returns> public IEnumerable <PixelFormat> SupportedPixelFormats() { foreach (var format in LinuxVideoInterop.EnumerateFormats(this.handle)) { if (format.Type == LinuxVideoInterop.BufferType.VideoCapture) { yield return(new PixelFormat(format)); } } }
/// <summary> /// Get current video format. /// </summary> /// <returns>Video format.</returns> public VideoFormat GetVideoFormat() { var format = new LinuxVideoInterop.VideoFormat() { Type = LinuxVideoInterop.BufferType.VideoCapture }; // note: only video capture supported LinuxVideoInterop.GetFormat(this.handle, ref format); return(new VideoFormat(format)); }
/// <summary> /// Stop streaming buffers and close device. /// </summary> public void Close() { if (this.file != null) { // stop any running background thread and wait for it to terminate this.isStopping = true; this.background?.Join(); LinuxVideoInterop.StreamOff(this.handle); this.file.Close(); this.file.Dispose(); this.file = null; } }
/// <summary> /// Open device. /// </summary> /// <remarks> /// This also queries the device capabilities and ensures that it supports video capture and streaming. /// </remarks> public void Open() { this.file = File.Open(this.device, FileMode.Open, FileAccess.ReadWrite); this.handle = this.file.SafeFileHandle.DangerousGetHandle().ToInt32(); this.capabilities = LinuxVideoInterop.QueryCapabilities(this.handle); if ((this.capabilities.Caps & LinuxVideoInterop.CapsFlags.VideoCapture) != LinuxVideoInterop.CapsFlags.VideoCapture) { throw new IOException("Device doesn't support video capture"); } if ((this.capabilities.Caps & LinuxVideoInterop.CapsFlags.Streaming) != LinuxVideoInterop.CapsFlags.Streaming) { throw new IOException("Device doesn't support streaming"); } }
private unsafe void ProcessFrames() { while (!this.isStopping) { if (this.OnFrame != null) { var buffer = LinuxVideoInterop.DequeBuffer(this.handle); var data = this.buffers[buffer.Index]; var time = buffer.TimeStamp; var frame = new ImageFrame(new IntPtr(data.Start), (int)buffer.BytesUsed, time.Seconds, time.MicroSeconds, this.handle, buffer); // re-EnqueBuffer upon dispose this.OnFrame.Invoke(this, frame); } else { Thread.Sleep(10); // wait for event subscriber } } }
/// <summary> /// Set video format. /// </summary> /// <param name="width">Format width in pixels.</param> /// <param name="height">Format height in pixels.</param> /// <param name="format">Pixel format.</param> public void SetVideoFormat(int width, int height, PixelFormat format) { #pragma warning disable SA1118 // Parameter must not span multiple lines LinuxVideoInterop.SetFormat( this.handle, new LinuxVideoInterop.VideoFormat() { Type = LinuxVideoInterop.BufferType.VideoCapture, Pixel = new LinuxVideoInterop.PixFormat() { Width = (uint)width, Height = (uint)height, PixelFormatId = format.InternalFormat.PixelFormatId, Field = LinuxVideoInterop.PixelField.None, // note: only supporting none }, }); #pragma warning restore SA1118 // Parameter must not span multiple lines }
/// <summary> /// Begin streaming buffers. /// </summary> public unsafe void StreamBuffers() { if (LinuxVideoInterop.ReqBufs(this.handle, NumberOfDriverBuffers, LinuxVideoInterop.Memory.MemoryMapping) != NumberOfDriverBuffers) { throw new IOException("Could not allocate buffers."); } try { // enque and memory map all the buffers for (var i = 0u; i < NumberOfDriverBuffers; i++) { var buf = LinuxVideoInterop.QueryBuf(this.handle, i); LinuxVideoInterop.EnqueBuffer(this.handle, buf); this.buffers[i] = new BufferInfo() { Initialized = true, Start = LinuxVideoInterop.MemoryMap(this.handle, buf), Buffer = buf, }; } LinuxVideoInterop.StreamOn(this.handle); this.background = new Thread(new ThreadStart(this.ProcessFrames)) { IsBackground = true }; this.isStopping = false; this.background.Start(); } catch { for (var i = 0u; i < NumberOfDriverBuffers; i++) { var buf = this.buffers[i]; if (buf.Initialized) { LinuxVideoInterop.MemoryUnmap(buf.Buffer); } } throw; } }
/// <summary> /// Dispose image frame (re-enqueuing underlying driver buffer). /// </summary> public void Dispose() { LinuxVideoInterop.EnqueBuffer(this.handle, this.buffer); }