use onix::Onix;
use std::fs::File;
use std::io::{Read, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let args: Vec<_> = std::env::args().collect();
if args.len() != 7 {
eprintln!(
"Usage: {} <image.raw> <width> <height> <format> <compression-quality> <output.jpeg>",
args[0]
);
std::process::exit(1);
}
let mut input = std::fs::File::open(&args[1])?;
let width: u32 = args[2].parse()?;
let height: u32 = args[3].parse()?;
let format = match args[4].as_str() {
"YUYV" => onix::DrmFormats::YUYV,
"UYVY" => onix::DrmFormats::UYVY,
"NV12" => onix::DrmFormats::NM12,
"YU12" => onix::DrmFormats::YM12,
format => panic!("Unknown format {format}"),
};
let compression_quality: i32 = args[5].parse()?;
let decoder = Onix::find_devices()
.expect("Unable to find a V4L2 M2M decoder corresponding to our criteria");
let mut encoder = decoder
.jpeg_encoder()
.expect("No available JPEG encoder on this system");
println!(
"Encoding with {} ({})",
encoder.video_path().display(),
encoder.video_querycap()?.driver(),
);
let mut image = encoder
.prepare(width, height, format, compression_quality)
.expect("Unable to encode to JPEG");
match format {
onix::DrmFormats::YUYV | onix::DrmFormats::UYVY => {
let buf = image.out_mut();
let size = width as usize * height as usize;
let map = encoder.mmap(buf, 0)?;
input.read_exact(&mut map.as_mut_slice()[..size])?;
buf.set_bytesused(0, size);
}
onix::DrmFormats::NM12 => {
let buf = image.out_mut();
let size = width as usize * height as usize;
{
let map = encoder.mmap(buf, 0)?;
input.read_exact(&mut map.as_mut_slice()[..size])?;
buf.set_bytesused(0, size);
}
{
let map = encoder.mmap(buf, 1)?;
input.read_exact(&mut map.as_mut_slice()[..size / 2])?;
buf.set_bytesused(1, size / 2);
}
}
onix::DrmFormats::YM12 => {
let buf = image.out_mut();
let size = width as usize * height as usize;
{
let map = encoder.mmap(buf, 0)?;
input.read_exact(&mut map.as_mut_slice()[..size])?;
buf.set_bytesused(0, size);
}
{
let map = encoder.mmap(buf, 1)?;
input.read_exact(&mut map.as_mut_slice()[..size / 4])?;
buf.set_bytesused(1, size / 4);
}
{
let map = encoder.mmap(buf, 2)?;
input.read_exact(&mut map.as_mut_slice()[..size / 4])?;
buf.set_bytesused(2, size / 4);
}
}
_ => panic!("TODO: Add support for format {format}"),
}
encoder
.queue(&mut image)
.expect("Error while queuing buffers");
encoder
.dequeue(&mut image)
.expect("Error while dequeuing buffers");
encoder.stop().expect("Error while stopping the encoding");
{
let buf = image.cap_mut();
let map = encoder.mmap(buf, 0)?;
let mut output = File::create(&args[6])?;
let slice = &map.as_slice()[..buf.bytesused(0) as usize];
output.write_all(slice)?;
}
Ok(())
}