Dequeue a frame from the driver (blocking). 从驱动出队一帧(阻塞)。 This is the **hot path** — called once per frame. No heap allocations, no poll(), single ioctl syscall. 这是**热路径** —— 每帧调用一次。 无堆分配、无 poll()、单次 ioctl 系统调用。
(&mut self)
| 192 | /// 这是**热路径** —— 每帧调用一次。 |
| 193 | /// 无堆分配、无 poll()、单次 ioctl 系统调用。 |
| 194 | pub fn dequeue(&mut self) -> Result<RawFrame<'_>> { |
| 195 | if !self.streaming { |
| 196 | return Err(CameraError::StreamNotStarted); |
| 197 | } |
| 198 | |
| 199 | // If the previous frame's buffer hasn't been returned, queue it now. |
| 200 | // This happens automatically when the user calls next_frame() again. |
| 201 | // 如果上一帧的缓冲区尚未归还,现在将其入队。 |
| 202 | // 当用户再次调用 next_frame() 时会自动执行此操作。 |
| 203 | if let Some(prev_idx) = self.pending_queue.take() { |
| 204 | v4l2_sys::queue_buffer(self.fd, prev_idx as u32)?; |
| 205 | } |
| 206 | |
| 207 | // Blocking DQBUF — the kernel wakes us when a frame is ready. |
| 208 | // 阻塞 DQBUF —— 帧就绪时内核唤醒我们。 |
| 209 | let v4l2_buf = v4l2_sys::dequeue_buffer(self.fd)?; |
| 210 | |
| 211 | let index = v4l2_buf.index as usize; |
| 212 | let bytesused = v4l2_buf.bytesused as usize; |
| 213 | |
| 214 | // Record this buffer as pending-queue (will be returned on next dequeue). |
| 215 | // 记录此缓冲区为待归还状态(下次 dequeue 时归还)。 |
| 216 | self.pending_queue = Some(index); |
| 217 | |
| 218 | // Create a slice of only the valid data portion. |
| 219 | // For MJPEG: bytesused ≈ 88KB, buffer length ≈ 614KB. |
| 220 | // 创建仅包含有效数据部分的切片。 |
| 221 | // 对于 MJPEG:bytesused ≈ 88KB,缓冲区总长 ≈ 614KB。 |
| 222 | let data = unsafe { |
| 223 | let buf = &self.buffers[index]; |
| 224 | std::slice::from_raw_parts(buf.ptr, bytesused) |
| 225 | }; |
| 226 | |
| 227 | Ok(RawFrame { |
| 228 | index, |
| 229 | data, |
| 230 | width: self.width, |
| 231 | height: self.height, |
| 232 | pixel_format: self.pixel_format, |
| 233 | sequence: v4l2_buf.sequence as u64, |
| 234 | timestamp_us: v4l2_buf.timestamp.tv_sec as u64 * 1_000_000 |
| 235 | + v4l2_buf.timestamp.tv_usec as u64, |
| 236 | }) |
| 237 | } |
| 238 | |
| 239 | /// Explicitly re-queue a buffer (return it to the driver). |
| 240 | /// 显式将缓冲区重新入队(归还给驱动)。 |
nothing calls this directly
no test coverage detected