Skip to content

Commit 33ddb43

Browse files
chihchiachenadelva1984
authored andcommitted
simple_device: Switch to YUV420 pixel format
In practice, it is more common for a video capture device to support YUV420 than RGB888. So let's switch over to YUV420. Test: `v4l2-compliance -d1 -s` passes 59/59 Test: `v4l2-ctl -d1 --info` shows ``` Driver Info: Driver name : virtio_media Card type : simple_device Bus info : platform:virtio-media0 Driver version : 6.12.52 Capabilities : 0x84201000 Video Capture Multiplanar Streaming Extended Pix Format Device Capabilities Device Caps : 0x04201000 Video Capture Multiplanar Streaming Extended Pix Format ```
1 parent c6cc93a commit 33ddb43

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

device/src/devices/simple_device.rs

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,18 @@ impl SimpleCaptureDeviceSession {
142142
.seek(SeekFrom::Start(0))
143143
.map_err(|_| libc::EIO)?;
144144
let mut writer = BufWriter::new(buffer.fd.as_file());
145-
let color = [
146-
0xffu8 * (sequence as u8 % 2),
147-
0x55u8 * (sequence as u8 % 3),
148-
0x10u8 * (sequence as u8 % 16),
149-
];
145+
let y = (sequence % 256) as u8;
146+
let u = ((sequence + 64) % 256) as u8;
147+
let v = ((sequence + 128) % 256) as u8;
148+
150149
for _ in 0..(WIDTH * HEIGHT) {
151-
let _ = writer.write(&color).map_err(|_| libc::EIO)?;
150+
writer.write_all(&[y]).map_err(|_| libc::EIO)?;
151+
}
152+
for _ in 0..(WIDTH * HEIGHT / 4) {
153+
writer.write_all(&[u]).map_err(|_| libc::EIO)?;
154+
}
155+
for _ in 0..(WIDTH * HEIGHT / 4) {
156+
writer.write_all(&[v]).map_err(|_| libc::EIO)?;
152157
}
153158
drop(writer);
154159

@@ -275,11 +280,10 @@ where
275280
}
276281
}
277282

278-
const PIXELFORMAT: u32 = PixelFormat::from_fourcc(b"RGB3").to_u32();
283+
const PIXELFORMAT: u32 = PixelFormat::from_fourcc(b"YU12").to_u32();
279284
const WIDTH: u32 = 640;
280285
const HEIGHT: u32 = 480;
281-
const BYTES_PER_LINE: u32 = WIDTH * 3;
282-
const BUFFER_SIZE: u32 = BYTES_PER_LINE * HEIGHT;
286+
const BUFFER_SIZE: u32 = WIDTH * HEIGHT * 3 / 2;
283287

284288
const INPUTS: [bindings::v4l2_input; 1] = [bindings::v4l2_input {
285289
index: 0,
@@ -298,20 +302,41 @@ fn default_fmtdesc(queue: QueueType) -> v4l2_fmtdesc {
298302
}
299303

300304
fn default_fmt(queue: QueueType) -> v4l2_format {
301-
let pix = v4l2_pix_format {
305+
let pix_mp = bindings::v4l2_pix_format_mplane {
302306
width: WIDTH,
303307
height: HEIGHT,
304308
pixelformat: PIXELFORMAT,
305309
field: bindings::v4l2_field_V4L2_FIELD_NONE,
306-
bytesperline: BYTES_PER_LINE,
307-
sizeimage: BUFFER_SIZE,
308310
colorspace: bindings::v4l2_colorspace_V4L2_COLORSPACE_SRGB,
311+
num_planes: 3,
312+
plane_fmt: [
313+
bindings::v4l2_plane_pix_format {
314+
sizeimage: WIDTH * HEIGHT,
315+
bytesperline: WIDTH,
316+
..Default::default()
317+
},
318+
bindings::v4l2_plane_pix_format {
319+
sizeimage: WIDTH * HEIGHT / 4,
320+
bytesperline: WIDTH / 2,
321+
..Default::default()
322+
},
323+
bindings::v4l2_plane_pix_format {
324+
sizeimage: WIDTH * HEIGHT / 4,
325+
bytesperline: WIDTH / 2,
326+
..Default::default()
327+
},
328+
Default::default(),
329+
Default::default(),
330+
Default::default(),
331+
Default::default(),
332+
Default::default(),
333+
],
309334
..Default::default()
310335
};
311336

312337
v4l2_format {
313338
type_: queue as u32,
314-
fmt: bindings::v4l2_format__bindgen_ty_1 { pix },
339+
fmt: bindings::v4l2_format__bindgen_ty_1 { pix_mp },
315340
}
316341
}
317342

@@ -329,7 +354,7 @@ where
329354
queue: QueueType,
330355
index: u32,
331356
) -> IoctlResult<v4l2_fmtdesc> {
332-
if queue != QueueType::VideoCapture {
357+
if queue != QueueType::VideoCaptureMplane {
333358
return Err(libc::EINVAL);
334359
}
335360
if index > 0 {
@@ -340,10 +365,9 @@ where
340365
}
341366

342367
fn g_fmt(&mut self, _session: &Self::Session, queue: QueueType) -> IoctlResult<v4l2_format> {
343-
if queue != QueueType::VideoCapture {
368+
if queue != QueueType::VideoCaptureMplane {
344369
return Err(libc::EINVAL);
345370
}
346-
347371
Ok(default_fmt(queue))
348372
}
349373

@@ -353,10 +377,9 @@ where
353377
queue: QueueType,
354378
_format: v4l2_format,
355379
) -> IoctlResult<v4l2_format> {
356-
if queue != QueueType::VideoCapture {
380+
if queue != QueueType::VideoCaptureMplane {
357381
return Err(libc::EINVAL);
358382
}
359-
360383
Ok(default_fmt(queue))
361384
}
362385

@@ -366,10 +389,9 @@ where
366389
queue: QueueType,
367390
_format: v4l2_format,
368391
) -> IoctlResult<v4l2_format> {
369-
if queue != QueueType::VideoCapture {
392+
if queue != QueueType::VideoCaptureMplane {
370393
return Err(libc::EINVAL);
371394
}
372-
373395
Ok(default_fmt(queue))
374396
}
375397

@@ -429,8 +451,7 @@ where
429451
.register_buffer(None, BUFFER_SIZE)
430452
.map_err(|_| libc::EINVAL)?;
431453

432-
let mut v4l2_buffer =
433-
V4l2Buffer::new(QueueType::VideoCapture, i, MemoryType::Mmap);
454+
let mut v4l2_buffer = V4l2Buffer::new(queue, i, MemoryType::Mmap);
434455
if let V4l2PlanesWithBackingMut::Mmap(mut planes) =
435456
v4l2_buffer.planes_with_backing_iter_mut()
436457
{
@@ -474,7 +495,7 @@ where
474495
queue: QueueType,
475496
index: u32,
476497
) -> IoctlResult<v4l2r::ioctl::V4l2Buffer> {
477-
if queue != QueueType::VideoCapture {
498+
if queue != QueueType::VideoCaptureMplane {
478499
return Err(libc::EINVAL);
479500
}
480501
let buffer = session.buffers.get(index as usize).ok_or(libc::EINVAL)?;
@@ -510,7 +531,7 @@ where
510531
}
511532

512533
fn streamon(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()> {
513-
if queue != QueueType::VideoCapture || session.buffers.is_empty() {
534+
if queue != QueueType::VideoCaptureMplane || session.buffers.is_empty() {
514535
return Err(libc::EINVAL);
515536
}
516537
session.streaming = true;
@@ -521,7 +542,7 @@ where
521542
}
522543

523544
fn streamoff(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()> {
524-
if queue != QueueType::VideoCapture {
545+
if queue != QueueType::VideoCaptureMplane {
525546
return Err(libc::EINVAL);
526547
}
527548
session.streaming = false;

0 commit comments

Comments
 (0)