ioctl: introduce and use V4l2Buffer structure

Introduce a simple V4l2Buffer (inspired from DqBuffer) that makes it
easy to queue/dequeue/query buffers from a single structure. This allows
further simplifications, like the removal of the DqBuf trait which is
now equivalent to QueryBuf.
diff --git a/lib/examples/vicodec_test/ioctl_api.rs b/lib/examples/vicodec_test/ioctl_api.rs
index 4e60a87..8805433 100644
--- a/lib/examples/vicodec_test/ioctl_api.rs
+++ b/lib/examples/vicodec_test/ioctl_api.rs
@@ -249,7 +249,7 @@
         dqbuf::<()>(&fd, output_queue).expect("Failed to dequeue output buffer");
 
         // The CAPTURE buffer, on the other hand, we want to examine more closely.
-        let cap_dqbuf: DqBuffer =
+        let cap_dqbuf: V4l2Buffer =
             dqbuf(&fd, capture_queue).expect("Failed to dequeue capture buffer");
         let bytes_used = cap_dqbuf.get_first_plane().bytesused() as usize;
 
diff --git a/lib/src/device/queue.rs b/lib/src/device/queue.rs
index 35388d3..26437b9 100644
--- a/lib/src/device/queue.rs
+++ b/lib/src/device/queue.rs
@@ -483,7 +483,7 @@
     type Dequeued = DqBuffer<D, P>;
 
     fn try_dequeue(&self) -> DqBufResult<Self::Dequeued> {
-        let dqbuf: ioctl::DqBuffer = match ioctl::dqbuf(&self.inner, self.inner.type_) {
+        let dqbuf: ioctl::V4l2Buffer = match ioctl::dqbuf(&self.inner, self.inner.type_) {
             Ok(dqbuf) => dqbuf,
             Err(DqBufError::Eos) => return Err(DqBufError::Eos),
             Err(DqBufError::NotReady) => return Err(DqBufError::NotReady),
diff --git a/lib/src/device/queue/dqbuf.rs b/lib/src/device/queue/dqbuf.rs
index 8c64858..01bac86 100644
--- a/lib/src/device/queue/dqbuf.rs
+++ b/lib/src/device/queue/dqbuf.rs
@@ -22,7 +22,7 @@
 /// return their ownership to the user.
 pub struct DqBuffer<D: Direction, P: BufferHandles> {
     /// Dequeued buffer information as reported by V4L2.
-    pub data: ioctl::DqBuffer,
+    pub data: ioctl::V4l2Buffer,
     /// The backing memory that has been provided for this buffer.
     plane_handles: Option<P>,
 
@@ -47,7 +47,7 @@
         queue: &Queue<D, BuffersAllocated<P>>,
         buffer: &Arc<BufferInfo<P>>,
         plane_handles: P,
-        data: ioctl::DqBuffer,
+        data: ioctl::V4l2Buffer,
         fuse: BufferStateFuse<P>,
     ) -> Self {
         DqBuffer {
diff --git a/lib/src/device/queue/qbuf.rs b/lib/src/device/queue/qbuf.rs
index d7653a5..dfd7027 100644
--- a/lib/src/device/queue/qbuf.rs
+++ b/lib/src/device/queue/qbuf.rs
@@ -124,7 +124,7 @@
             self.index,
             qbuffer,
         ) {
-            Ok(_) => (),
+            Ok(()) => (),
             Err(error) => {
                 return Err(QueueError {
                     error,
diff --git a/lib/src/ioctl.rs b/lib/src/ioctl.rs
index 3db9f0b..f07457e 100644
--- a/lib/src/ioctl.rs
+++ b/lib/src/ioctl.rs
@@ -46,6 +46,8 @@
 pub use streamon::*;
 pub use subscribe_event::*;
 
+use std::fmt::Debug;
+
 use crate::bindings;
 use crate::QueueType;
 use std::{
@@ -102,17 +104,6 @@
     }
 }
 
-/// A memory area we can pass to ioctls in order to get/set plane information
-/// with the multi-planar API.
-type PlaneData = [bindings::v4l2_plane; bindings::VIDEO_MAX_PLANES as usize];
-
-/// For simple initialization of `PlaneData`.
-impl Default for bindings::v4l2_plane {
-    fn default() -> Self {
-        unsafe { mem::zeroed() }
-    }
-}
-
 /// Returns whether the given queue type can handle multi-planar formats.
 fn is_multi_planar(queue: QueueType) -> bool {
     matches!(
@@ -134,3 +125,137 @@
         self.into() as i32
     }
 }
+
+/// A memory area we can pass to ioctls in order to get/set plane information
+/// with the multi-planar API.
+type V4l2BufferPlanes = [bindings::v4l2_plane; bindings::VIDEO_MAX_PLANES as usize];
+
+/// For simple initialization of `V4l2BufferPlanes`.
+impl Default for bindings::v4l2_plane {
+    fn default() -> Self {
+        unsafe { mem::zeroed() }
+    }
+}
+
+/// Information about a single plane of a V4L2 buffer.
+pub struct V4l2BufferPlane<'a> {
+    plane: &'a bindings::v4l2_plane,
+}
+
+impl<'a> Debug for V4l2BufferPlane<'a> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("V4l2BufferPlane")
+            .field("length", &self.length())
+            .field("bytesused", &self.bytesused())
+            .field("data_offset", &self.data_offset())
+            .finish()
+    }
+}
+
+impl<'a> V4l2BufferPlane<'a> {
+    pub fn length(&self) -> u32 {
+        self.plane.length
+    }
+
+    pub fn bytesused(&self) -> u32 {
+        self.plane.bytesused
+    }
+
+    pub fn data_offset(&self) -> u32 {
+        self.plane.data_offset
+    }
+}
+
+/// A completely owned v4l2_buffer, where the pointer to planes is meaningless and fixed up when
+/// needed.
+///
+/// If the buffer is single-planar, it is modified to use `planes` anyway for the information of
+/// its unique plane.
+#[derive(Clone)]
+#[repr(C)]
+pub struct V4l2Buffer {
+    buffer: bindings::v4l2_buffer,
+    planes: V4l2BufferPlanes,
+}
+
+/// V4l2Buffer is safe to send across threads. `v4l2_buffer` is !Send because it
+/// contains a pointer, but we are making sure to use it safely here.
+unsafe impl Send for V4l2Buffer {}
+
+impl Debug for V4l2Buffer {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("V4l2Buffer")
+            .field("index", &self.index())
+            .field("flags", &self.flags())
+            .field("sequence", &self.sequence())
+            .finish()
+    }
+}
+
+impl V4l2Buffer {
+    pub fn index(&self) -> u32 {
+        self.buffer.index
+    }
+
+    pub fn queue_type(&self) -> u32 {
+        self.buffer.type_
+    }
+
+    pub fn flags(&self) -> BufferFlags {
+        BufferFlags::from_bits_truncate(self.buffer.flags)
+    }
+
+    pub fn is_last(&self) -> bool {
+        self.flags().contains(BufferFlags::LAST)
+    }
+
+    pub fn timestamp(&self) -> bindings::timeval {
+        self.buffer.timestamp
+    }
+
+    pub fn sequence(&self) -> u32 {
+        self.buffer.sequence
+    }
+
+    pub fn is_multi_planar(&self) -> bool {
+        matches!(
+            self.buffer.type_,
+            bindings::v4l2_buf_type_V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
+                | bindings::v4l2_buf_type_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+        )
+    }
+
+    pub fn num_planes(&self) -> usize {
+        if self.is_multi_planar() {
+            self.buffer.length as usize
+        } else {
+            1
+        }
+    }
+
+    /// Returns the first plane of the buffer. This method is guaranteed to
+    /// succeed because every buffer has at least one plane.
+    pub fn get_first_plane(&self) -> V4l2BufferPlane {
+        V4l2BufferPlane {
+            plane: &self.planes[0],
+        }
+    }
+
+    /// Returns plane `index` of the buffer, or `None` if `index` is larger than
+    /// the number of planes in this buffer.
+    pub fn get_plane(&self, index: usize) -> Option<V4l2BufferPlane> {
+        if index < self.num_planes() {
+            Some(V4l2BufferPlane {
+                plane: &self.planes[index],
+            })
+        } else {
+            None
+        }
+    }
+
+    /// Returns the raw v4l2_buffer as a pointer. Useful to pass to unsafe
+    /// non-Rust code.
+    pub fn as_raw_v4l2_buffer(&self) -> *const bindings::v4l2_buffer {
+        &self.buffer
+    }
+}
diff --git a/lib/src/ioctl/dqbuf.rs b/lib/src/ioctl/dqbuf.rs
index 1e3f3f7..63b7275 100644
--- a/lib/src/ioctl/dqbuf.rs
+++ b/lib/src/ioctl/dqbuf.rs
@@ -1,208 +1,16 @@
-use super::{is_multi_planar, BufferFlags, PlaneData};
 use crate::bindings;
+use crate::ioctl::is_multi_planar;
+use crate::ioctl::QueryBuf;
+use crate::ioctl::V4l2BufferPlanes;
 use crate::QueueType;
 
-use nix::{self, errno::Errno};
+use std::fmt::Debug;
 use std::mem;
 use std::os::unix::io::AsRawFd;
-use std::{fmt::Debug, pin::Pin};
+
+use nix::errno::Errno;
 use thiserror::Error;
 
-/// Implementors can receive the result from the `dqbuf` ioctl.
-pub trait DqBuf: Sized {
-    /// Try to retrieve the data from `v4l2_buf`. If `v4l2_planes` is `None`,
-    /// then the buffer is single-planar. If it has data, the buffer is
-    /// multi-planar and `v4l2_planes` shall be used to retrieve the plane data.
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, v4l2_planes: Option<PlaneData>) -> Self;
-}
-
-impl DqBuf for bindings::v4l2_buffer {
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, _v4l2_planes: Option<PlaneData>) -> Self {
-        v4l2_buf
-    }
-}
-
-/// Allows to dequeue a buffer without caring for any of its data.
-impl DqBuf for () {
-    fn from_v4l2_buffer(_v4l2_buf: bindings::v4l2_buffer, _v4l2_planes: Option<PlaneData>) -> Self {
-    }
-}
-
-/// Useful for the case where we are only interested in the index of a dequeued
-/// buffer
-impl DqBuf for u32 {
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, _v4l2_planes: Option<PlaneData>) -> Self {
-        v4l2_buf.index
-    }
-}
-
-/// Information about a single plane of a dequeued buffer.
-pub struct DqBufPlane<'a> {
-    plane: &'a bindings::v4l2_plane,
-}
-
-impl<'a> Debug for DqBufPlane<'a> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("DQBufPlane")
-            .field("length", &self.length())
-            .field("bytesused", &self.bytesused())
-            .field("data_offset", &self.data_offset())
-            .finish()
-    }
-}
-
-impl<'a> DqBufPlane<'a> {
-    pub fn length(&self) -> u32 {
-        self.plane.length
-    }
-
-    pub fn bytesused(&self) -> u32 {
-        self.plane.bytesused
-    }
-
-    pub fn data_offset(&self) -> u32 {
-        self.plane.data_offset
-    }
-}
-
-/// Information for a dequeued buffer. Safe variant of `struct v4l2_buffer`.
-pub struct DqBuffer {
-    v4l2_buffer: bindings::v4l2_buffer,
-    // The `m.planes` pointer of `v4l2_buffer` points here and must stay stable
-    // as we move this object around.
-    v4l2_planes: Pin<Box<PlaneData>>,
-}
-
-impl Clone for DqBuffer {
-    fn clone(&self) -> Self {
-        let mut ret = Self {
-            v4l2_buffer: self.v4l2_buffer,
-            v4l2_planes: self.v4l2_planes.clone(),
-        };
-        // Make the planes pointer of the cloned data point to the right copy.
-        if self.is_multi_planar() {
-            ret.v4l2_buffer.m.planes = ret.v4l2_planes.as_mut_ptr();
-        }
-        ret
-    }
-}
-
-/// DQBuffer is safe to send across threads. `v4l2_buffer` is !Send because it
-/// contains a pointer, but we are making sure to use it safely here.
-unsafe impl Send for DqBuffer {}
-
-impl Debug for DqBuffer {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("DQBuffer")
-            .field("index", &self.index())
-            .field("flags", &self.flags())
-            .field("sequence", &self.sequence())
-            .finish()
-    }
-}
-
-impl DqBuffer {
-    pub fn index(&self) -> u32 {
-        self.v4l2_buffer.index
-    }
-
-    pub fn flags(&self) -> BufferFlags {
-        BufferFlags::from_bits_truncate(self.v4l2_buffer.flags)
-    }
-
-    pub fn is_last(&self) -> bool {
-        self.flags().contains(BufferFlags::LAST)
-    }
-
-    pub fn timestamp(&self) -> bindings::timeval {
-        self.v4l2_buffer.timestamp
-    }
-
-    pub fn sequence(&self) -> u32 {
-        self.v4l2_buffer.sequence
-    }
-
-    pub fn is_multi_planar(&self) -> bool {
-        matches!(
-            self.v4l2_buffer.type_,
-            bindings::v4l2_buf_type_V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
-                | bindings::v4l2_buf_type_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-        )
-    }
-
-    pub fn num_planes(&self) -> usize {
-        if self.is_multi_planar() {
-            self.v4l2_buffer.length as usize
-        } else {
-            1
-        }
-    }
-
-    /// Returns the first plane of the buffer. This method is guaranteed to
-    /// succeed because every buffer has at least one plane.
-    pub fn get_first_plane(&self) -> DqBufPlane {
-        DqBufPlane {
-            plane: &self.v4l2_planes[0],
-        }
-    }
-
-    /// Returns plane `index` of the buffer, or `None` if `index` is larger than
-    /// the number of planes in this buffer.
-    pub fn get_plane(&self, index: usize) -> Option<DqBufPlane> {
-        if index < self.num_planes() {
-            Some(DqBufPlane {
-                plane: &self.v4l2_planes[index],
-            })
-        } else {
-            None
-        }
-    }
-
-    /// Returns the raw v4l2_buffer as a pointer. Useful to pass to unsafe
-    /// non-Rust code.
-    pub fn as_raw_v4l2_buffer(&self) -> *const bindings::v4l2_buffer {
-        &self.v4l2_buffer
-    }
-}
-
-impl DqBuf for DqBuffer {
-    fn from_v4l2_buffer(
-        v4l2_buffer: bindings::v4l2_buffer,
-        v4l2_planes: Option<PlaneData>,
-    ) -> Self {
-        let mut dqbuf = DqBuffer {
-            v4l2_buffer,
-            v4l2_planes: Box::pin(match v4l2_planes {
-                Some(planes) => planes,
-                // In single-plane mode, reproduce the buffer information into
-                // a v4l2_plane in order to present a unified interface.
-                None => {
-                    let mut pdata: PlaneData = Default::default();
-                    pdata[0] = bindings::v4l2_plane {
-                        bytesused: v4l2_buffer.bytesused,
-                        length: v4l2_buffer.length,
-                        data_offset: 0,
-                        reserved: Default::default(),
-                        // Safe because both unions have the same members and
-                        // layout in single-plane mode.
-                        m: unsafe { std::mem::transmute(v4l2_buffer.m) },
-                    };
-
-                    pdata
-                }
-            }),
-        };
-
-        // Since the planes have moved, update the planes pointer if we are
-        // using multi-planar.
-        if dqbuf.is_multi_planar() {
-            dqbuf.v4l2_buffer.m.planes = dqbuf.v4l2_planes.as_mut_ptr()
-        }
-
-        dqbuf
-    }
-}
-
 #[doc(hidden)]
 mod ioctl {
     use crate::bindings::v4l2_buffer;
@@ -242,14 +50,14 @@
 pub type DqBufResult<T> = Result<T, DqBufError>;
 
 /// Safe wrapper around the `VIDIOC_DQBUF` ioctl.
-pub fn dqbuf<T: DqBuf + Debug>(fd: &impl AsRawFd, queue: QueueType) -> DqBufResult<T> {
+pub fn dqbuf<T: QueryBuf>(fd: &impl AsRawFd, queue: QueueType) -> DqBufResult<T> {
     let mut v4l2_buf = bindings::v4l2_buffer {
         type_: queue as u32,
         ..unsafe { mem::zeroed() }
     };
 
     let dequeued_buffer = if is_multi_planar(queue) {
-        let mut plane_data: PlaneData = Default::default();
+        let mut plane_data: V4l2BufferPlanes = Default::default();
         v4l2_buf.m.planes = plane_data.as_mut_ptr();
         v4l2_buf.length = plane_data.len() as u32;
 
diff --git a/lib/src/ioctl/qbuf.rs b/lib/src/ioctl/qbuf.rs
index 2b36422..683d846 100644
--- a/lib/src/ioctl/qbuf.rs
+++ b/lib/src/ioctl/qbuf.rs
@@ -1,5 +1,6 @@
 //! Safe wrapper for the VIDIOC_(D)QBUF and VIDIOC_QUERYBUF ioctls.
-use super::{is_multi_planar, PlaneData};
+use super::{is_multi_planar, V4l2BufferPlanes};
+use crate::ioctl::{QueryBuf, V4l2Buffer};
 use crate::memory::{Memory, PlaneHandle};
 use crate::{bindings, QueueType};
 
@@ -66,10 +67,34 @@
     fn fill_mplane_v4l2_buffer(
         self,
         v4l2_buf: &mut bindings::v4l2_buffer,
-        v4l2_planes: &mut PlaneData,
+        v4l2_planes: &mut V4l2BufferPlanes,
     ) -> Result<(), QBufError>;
 }
 
+impl QBuf for V4l2Buffer {
+    fn fill_splane_v4l2_buffer(
+        self,
+        v4l2_buf: &mut bindings::v4l2_buffer,
+    ) -> Result<(), QBufError> {
+        *v4l2_buf = self.buffer;
+
+        Ok(())
+    }
+
+    fn fill_mplane_v4l2_buffer(
+        self,
+        v4l2_buf: &mut bindings::v4l2_buffer,
+        v4l2_planes: &mut V4l2BufferPlanes,
+    ) -> Result<(), QBufError> {
+        *v4l2_buf = self.buffer;
+        for (dest, src) in v4l2_planes.iter_mut().zip(self.planes.iter()) {
+            *dest = *src;
+        }
+
+        Ok(())
+    }
+}
+
 /// Representation of a single plane of a V4L2 buffer.
 pub struct QBufPlane(pub bindings::v4l2_plane);
 
@@ -167,7 +192,7 @@
     fn fill_mplane_v4l2_buffer(
         self,
         v4l2_buf: &mut bindings::v4l2_buffer,
-        v4l2_planes: &mut PlaneData,
+        v4l2_planes: &mut V4l2BufferPlanes,
     ) -> Result<(), QBufError> {
         if self.planes.is_empty() || self.planes.len() > v4l2_planes.len() {
             return Err(QBufError::NumPlanesMismatch(
@@ -212,12 +237,12 @@
 /// accessed by anyone else, the caller also needs to guarantee that the backing
 /// memory won't be freed until the corresponding buffer is returned by either
 /// `dqbuf` or `streamoff`.
-pub fn qbuf<T: QBuf>(
+pub fn qbuf<I: QBuf, O: QueryBuf>(
     fd: &impl AsRawFd,
     queue: QueueType,
     index: usize,
-    buf_data: T,
-) -> Result<(), QBufError> {
+    buf_data: I,
+) -> Result<O, QBufError> {
     let mut v4l2_buf = bindings::v4l2_buffer {
         index: index as u32,
         type_: queue as u32,
@@ -225,15 +250,15 @@
     };
 
     if is_multi_planar(queue) {
-        let mut plane_data: PlaneData = Default::default();
+        let mut plane_data: V4l2BufferPlanes = Default::default();
+        buf_data.fill_mplane_v4l2_buffer(&mut v4l2_buf, &mut plane_data)?;
         v4l2_buf.m.planes = plane_data.as_mut_ptr();
 
-        buf_data.fill_mplane_v4l2_buffer(&mut v4l2_buf, &mut plane_data)?;
         unsafe { ioctl::vidioc_qbuf(fd.as_raw_fd(), &mut v4l2_buf) }?;
-        Ok(())
+        Ok(O::from_v4l2_buffer(v4l2_buf, Some(plane_data)))
     } else {
         buf_data.fill_splane_v4l2_buffer(&mut v4l2_buf)?;
         unsafe { ioctl::vidioc_qbuf(fd.as_raw_fd(), &mut v4l2_buf) }?;
-        Ok(())
+        Ok(O::from_v4l2_buffer(v4l2_buf, None))
     }
 }
diff --git a/lib/src/ioctl/querybuf.rs b/lib/src/ioctl/querybuf.rs
index b02b92f..3b1a25f 100644
--- a/lib/src/ioctl/querybuf.rs
+++ b/lib/src/ioctl/querybuf.rs
@@ -1,5 +1,6 @@
-use super::{is_multi_planar, BufferFlags, PlaneData};
+use super::{is_multi_planar, BufferFlags, V4l2BufferPlanes};
 use crate::bindings;
+use crate::ioctl::V4l2Buffer;
 use crate::QueueType;
 use nix::errno::Errno;
 use thiserror::Error;
@@ -13,12 +14,44 @@
     /// then the buffer is single-planar. If it has data, the buffer is
     /// multi-planar and the array of `struct v4l2_plane` shall be used to
     /// retrieve the plane data.
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, v4l2_planes: Option<PlaneData>) -> Self;
+    fn from_v4l2_buffer(
+        v4l2_buf: bindings::v4l2_buffer,
+        v4l2_planes: Option<V4l2BufferPlanes>,
+    ) -> Self;
 }
 
-impl QueryBuf for bindings::v4l2_buffer {
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, _v4l2_planes: Option<PlaneData>) -> Self {
-        v4l2_buf
+/// For cases where we are not interested in the result of `qbuf`
+impl QueryBuf for () {
+    fn from_v4l2_buffer(
+        _v4l2_buf: bindings::v4l2_buffer,
+        _v4l2_planes: Option<V4l2BufferPlanes>,
+    ) -> Self {
+    }
+}
+
+impl QueryBuf for V4l2Buffer {
+    fn from_v4l2_buffer(
+        v4l2_buf: bindings::v4l2_buffer,
+        v4l2_planes: Option<V4l2BufferPlanes>,
+    ) -> Self {
+        Self {
+            buffer: v4l2_buf,
+            planes: v4l2_planes.unwrap_or_else(|| {
+                let mut pdata: V4l2BufferPlanes = Default::default();
+                // Duplicate information for the first plane so our methods can work.
+                pdata[0] = bindings::v4l2_plane {
+                    bytesused: v4l2_buf.bytesused,
+                    length: v4l2_buf.length,
+                    data_offset: 0,
+                    reserved: Default::default(),
+                    // Safe because both unions have the same members and
+                    // layout in single-plane mode.
+                    m: unsafe { std::mem::transmute(v4l2_buf.m) },
+                };
+
+                pdata
+            }),
+        }
     }
 }
 
@@ -39,7 +72,10 @@
 }
 
 impl QueryBuf for QueryBuffer {
-    fn from_v4l2_buffer(v4l2_buf: bindings::v4l2_buffer, v4l2_planes: Option<PlaneData>) -> Self {
+    fn from_v4l2_buffer(
+        v4l2_buf: bindings::v4l2_buffer,
+        v4l2_planes: Option<V4l2BufferPlanes>,
+    ) -> Self {
         let planes = match v4l2_planes {
             None => vec![QueryBufPlane {
                 mem_offset: unsafe { v4l2_buf.m.offset },
@@ -96,7 +132,7 @@
     };
 
     if is_multi_planar(queue) {
-        let mut plane_data: PlaneData = Default::default();
+        let mut plane_data: V4l2BufferPlanes = Default::default();
         v4l2_buf.m.planes = plane_data.as_mut_ptr();
         v4l2_buf.length = plane_data.len() as u32;