/// <summary> /// Creates a buffer to be used with Video4Linux streaming I/O. /// </summary> /// <param name="adapter">The parental Video4Linux device.</param> /// <param name="buffer">The struct holding the buffer information.</param> internal Buffer(Analog.Adapter adapter, v4l2_buffer buffer) { this.adapter = adapter; this.buffer = buffer; mapMemory(); }
private unsafe NewImageBufferReadyEventArgs GetFrameDataPooled(V4l2FrameBuffer *buffers) { // Get one frame from the buffer v4l2_buffer frame = new v4l2_buffer { type = v4l2_buf_type.V4L2_BUF_TYPE_VIDEO_CAPTURE, memory = v4l2_memory.V4L2_MEMORY_MMAP, }; V4l2Struct(V4l2Request.VIDIOC_DQBUF, ref frame); // Get data from pointer IntPtr intptr = buffers[frame.index].Start; var length = (int)buffers[frame.index].Length; byte[] dataBuffer = Array.Empty <byte>(); if (ImageBufferPoolingEnabled) { dataBuffer = ArrayPool <byte> .Shared.Rent(length); } else { dataBuffer = new byte[length]; } Marshal.Copy(source: intptr, destination: dataBuffer, startIndex: 0, length: (int)buffers[frame.index].Length); // Requeue the buffer V4l2Struct(V4l2Request.VIDIOC_QBUF, ref frame); return(new NewImageBufferReadyEventArgs(dataBuffer, length)); }
/// HACK: we should read until we reached count /// HACK: offset is ignored private int readMM(byte[] buffer, int offset, int count) { if (!adapter.Capabilities.Contains(AdapterCapability.Streaming)) { throw new Exception("Device does not support streaming."); } v4l2_buffer buf = new v4l2_buffer(); buf.type = adapter.Buffers[0].Type; buf.memory = adapter.Buffers[0].Memory; // read one image if (adapter.IoControl.DequeueBuffer(ref buf) == 0) { Analog.Buffer dbuf = adapter.Buffers[(int)buf.index]; // max length = buffer length if ((int)dbuf.Length < count) { count = (int)dbuf.Length; } // copy all the data from the buffer Marshal.Copy(dbuf.Start, buffer, 0, count); // re-enqueue the buffer dbuf.Enqueue(); return(count); } return(0); }
/// <summary> /// Queries the device for information about each requested buffer. /// </summary> /// <param name="req">Struct with information about the request buffers.</param> private void fetchBuffers(v4l2_requestbuffers req) { for (uint i = 0; i < req.count; i++) { v4l2_buffer buffer = new v4l2_buffer(); buffer.index = i; buffer.type = req.type; buffer.memory = req.memory; if (ioControl.QueryBuffer(ref buffer) < 0) { throw new Exception("VIDIOC_QUERYBUF"); } buffers.Add(new Analog.Buffer(this, buffer)); } }
private unsafe V4l2FrameBuffer[] ApplyFrameBuffers() { // Apply for buffers, use memory mapping v4l2_requestbuffers req = new v4l2_requestbuffers { count = BufferCount, type = v4l2_buf_type.V4L2_BUF_TYPE_VIDEO_CAPTURE, memory = v4l2_memory.V4L2_MEMORY_MMAP }; V4l2Struct(VideoSettings.VIDIOC_REQBUFS, ref req); // Mapping the applied buffer to user space V4l2FrameBuffer[] buffers = new V4l2FrameBuffer[BufferCount]; for (uint i = 0; i < BufferCount; i++) { v4l2_buffer buffer = new v4l2_buffer { index = i, type = v4l2_buf_type.V4L2_BUF_TYPE_VIDEO_CAPTURE, memory = v4l2_memory.V4L2_MEMORY_MMAP }; V4l2Struct(VideoSettings.VIDIOC_QUERYBUF, ref buffer); buffers[i].Length = buffer.length; buffers[i].Start = Interop.mmap(IntPtr.Zero, (int)buffer.length, MemoryMappedProtections.PROT_READ | MemoryMappedProtections.PROT_WRITE, MemoryMappedFlags.MAP_SHARED, _deviceFileDescriptor, (int)buffer.m.offset); } // Put the buffer in the processing queue for (uint i = 0; i < BufferCount; i++) { v4l2_buffer buffer = new v4l2_buffer { index = i, type = v4l2_buf_type.V4L2_BUF_TYPE_VIDEO_CAPTURE, memory = v4l2_memory.V4L2_MEMORY_MMAP }; V4l2Struct(VideoSettings.VIDIOC_QBUF, ref buffer); } return(buffers); }
private unsafe byte[] GetFrameData(V4l2FrameBuffer *buffers) { // Get one frame from the buffer v4l2_buffer frame = new v4l2_buffer { type = v4l2_buf_type.V4L2_BUF_TYPE_VIDEO_CAPTURE, memory = v4l2_memory.V4L2_MEMORY_MMAP, }; V4l2Struct(VideoSettings.VIDIOC_DQBUF, ref frame); // Get data from pointer IntPtr intptr = buffers[frame.index].Start; byte[] dataBuffer = new byte[buffers[frame.index].Length]; Marshal.Copy(source: intptr, destination: dataBuffer, startIndex: 0, length: (int)buffers[frame.index].Length); // Requeue the buffer V4l2Struct(VideoSettings.VIDIOC_QBUF, ref frame); return(dataBuffer); }
public static extern int ioctl(int fd, UInt64 request, ref v4l2_buffer buf);
public static extern int ioctl(int fd, UInt64 request, ref v4l2_buffer buf);
/// <summary> /// Calls VIDIOC_QBUF. /// </summary> public int EnqueueBuffer(ref v4l2_buffer buffer) { return(ioctl(deviceHandle, v4l2_operation.EnqueueBuffer, ref buffer)); }
/// <summary> /// Calls VIDIOC_QUERYBUF. /// </summary> public int QueryBuffer(ref v4l2_buffer buffer) { return(ioctl(deviceHandle, v4l2_operation.QueryBuffer, ref buffer)); }
ioctl(int device, v4l2_operation request, ref v4l2_buffer argp);