mirror of https://github.com/wayvr-org/wayvr.git
wgui: use dav1d (wip)
This commit is contained in:
parent
3c2ac4b5f1
commit
5c929c4fee
|
|
@ -43,7 +43,7 @@ dependencies = [
|
|||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy 0.8.50",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -312,12 +312,6 @@ dependencies = [
|
|||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_matches"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.7.2"
|
||||
|
|
@ -495,26 +489,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a"
|
||||
|
||||
[[package]]
|
||||
name = "atomig"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd0f41f4bb89f5c6450325e283fb78c4a3d042181b54f3855ee2f872919f9863"
|
||||
dependencies = [
|
||||
"atomig-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomig-macro"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49c98dba06b920588de7d63f6acc23f1e6a9fade5fd6198e564506334fb5a4f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
|
@ -635,19 +609,6 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "av-data"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca67ba5d317924c02180c576157afd54babe48a76ebc66ce6d34bb8ba08308e"
|
||||
dependencies = [
|
||||
"byte-slice-cast",
|
||||
"bytes",
|
||||
"num-derive",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "av-scenechange"
|
||||
version = "0.14.1"
|
||||
|
|
@ -810,12 +771,6 @@ version = "3.20.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.25.0"
|
||||
|
|
@ -1514,6 +1469,15 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376"
|
||||
|
||||
[[package]]
|
||||
name = "dav1d-sys"
|
||||
version = "0.8.3"
|
||||
source = "git+https://github.com/rust-av/dav1d-rs.git?rev=03477a36c3de4f2aacbab81a8951150ffdb9c4c3#03477a36c3de4f2aacbab81a8951150ffdb9c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.9.11"
|
||||
|
|
@ -2267,7 +2231,7 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
"zerocopy 0.8.50",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3282,16 +3246,6 @@ version = "0.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
|
||||
|
||||
[[package]]
|
||||
name = "nasm-rs"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "706bf8a5e8c8ddb99128c3291d31bd21f4bcde17f0f4c20ec678d85c74faa149"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.18"
|
||||
|
|
@ -4256,7 +4210,7 @@ version = "0.2.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy 0.8.50",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4600,28 +4554,6 @@ version = "1.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
|
||||
|
||||
[[package]]
|
||||
name = "rav1d"
|
||||
version = "1.1.0"
|
||||
source = "git+https://github.com/memorysafety/rav1d.git?rev=2a734dc9cd52190146796fb24b29a8c7e3d2af1e#2a734dc9cd52190146796fb24b29a8c7e3d2af1e"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"atomig",
|
||||
"av-data",
|
||||
"bitflags 2.12.1",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"nasm-rs",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"raw-cpuid",
|
||||
"static_assertions",
|
||||
"strum",
|
||||
"to_method",
|
||||
"zerocopy 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rav1e"
|
||||
version = "0.8.1"
|
||||
|
|
@ -4672,15 +4604,6 @@ dependencies = [
|
|||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
|
||||
dependencies = [
|
||||
"bitflags 2.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.6.2"
|
||||
|
|
@ -5888,12 +5811,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "to_method"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.52.3"
|
||||
|
|
@ -6734,6 +6651,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bytes",
|
||||
"cosmic-text",
|
||||
"dav1d-sys",
|
||||
"etagere",
|
||||
"flate2",
|
||||
"glam",
|
||||
|
|
@ -6742,7 +6660,6 @@ dependencies = [
|
|||
"lru",
|
||||
"ouroboros",
|
||||
"parking_lot",
|
||||
"rav1d",
|
||||
"regex",
|
||||
"resvg",
|
||||
"roxmltree 0.21.1",
|
||||
|
|
@ -7561,34 +7478,13 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -42,14 +42,12 @@ vulkano-shaders.workspace = true
|
|||
|
||||
# `video` wgui feature
|
||||
bytes = { workspace = true, optional = true }
|
||||
rav1d = {
|
||||
git = "https://github.com/memorysafety/rav1d.git",
|
||||
rev = "2a734dc9cd52190146796fb24b29a8c7e3d2af1e",
|
||||
default-features = false,
|
||||
features = ["bitdepth_8"],
|
||||
dav1d-sys = {
|
||||
git = "https://github.com/rust-av/dav1d-rs.git",
|
||||
rev = "03477a36c3de4f2aacbab81a8951150ffdb9c4c3",
|
||||
optional = true
|
||||
}
|
||||
|
||||
[features]
|
||||
default = ["video"]
|
||||
video = ["dep:bytes", "dep:rav1d"]
|
||||
video = ["dep:bytes", "dep:dav1d-sys"]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
use bytes::{Buf, Bytes};
|
||||
use rav1d::include::dav1d::dav1d::{Dav1dContext, Dav1dSettings};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
struct IvfReader {
|
||||
file_data: Vec<u8>,
|
||||
reader: Bytes, // uses &file_data ptr
|
||||
use bytes::{Buf, Bytes};
|
||||
use dav1d_sys::{
|
||||
Dav1dContext, Dav1dData, Dav1dPicture, Dav1dSettings, dav1d_close, dav1d_data_unref, dav1d_default_settings,
|
||||
dav1d_get_picture, dav1d_open, dav1d_picture_unref, dav1d_send_data,
|
||||
};
|
||||
|
||||
pub struct IvfReader {
|
||||
_file_data: Vec<u8>, // Used by `reader`, do not remove!
|
||||
reader: Bytes,
|
||||
pub cur_frame: u32,
|
||||
pub num_frames: u32,
|
||||
pub framerate: f32,
|
||||
|
|
@ -76,7 +81,7 @@ impl IvfReader {
|
|||
log::info!("IvfReader: width {header_width}, height {header_height}, framerate {framerate}");
|
||||
|
||||
Ok(IvfReader {
|
||||
file_data,
|
||||
_file_data: file_data,
|
||||
reader,
|
||||
cur_frame: 0,
|
||||
width: header_width,
|
||||
|
|
@ -87,9 +92,9 @@ impl IvfReader {
|
|||
}
|
||||
|
||||
// Read demuxed video packet to a chunk
|
||||
pub fn read_frame(&mut self) -> anyhow::Result<&[u8]> {
|
||||
pub fn read_frame(&mut self) -> anyhow::Result<(&[u8], u64 /* pts */)> {
|
||||
let frame_size = self.reader.try_get_u32_le()? as usize;
|
||||
let _frame_pts = self.reader.try_get_u64_le()?;
|
||||
let frame_pts = self.reader.try_get_u64_le()?;
|
||||
|
||||
if frame_size > 8 * 1024 * 1024 {
|
||||
// something went really wrong
|
||||
|
|
@ -108,7 +113,7 @@ impl IvfReader {
|
|||
|
||||
self.cur_frame += 1;
|
||||
|
||||
Ok(chunk_a)
|
||||
Ok((chunk_a, frame_pts))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,90 +123,140 @@ pub struct RgbFrame {
|
|||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct YuvFrame {
|
||||
width: u16,
|
||||
height: u16,
|
||||
stride_luma: u32,
|
||||
stride_chroma: u32,
|
||||
data_y: Vec<u8>,
|
||||
data_u: Vec<u8>,
|
||||
data_v: Vec<u8>,
|
||||
}
|
||||
|
||||
fn clamp_u8(v: i32) -> u8 {
|
||||
v.max(0).min(255) as u8
|
||||
}
|
||||
|
||||
fn yuv_to_rgb(y: u8, u: u8, v: u8) -> (u8, u8, u8) {
|
||||
let y_i = y as i32;
|
||||
let u_i = u as i32 - 128;
|
||||
let v_i = v as i32 - 128;
|
||||
let y_i = i32::from(y);
|
||||
let u_i = i32::from(u) - 128;
|
||||
let v_i = i32::from(v) - 128;
|
||||
let c = (1192 * (y_i - 16)).max(0);
|
||||
let out_r = (c + 1634 * v_i) >> 10;
|
||||
let out_g = (c - 401 * u_i - 834 * v_i) >> 10;
|
||||
let out_b = (c + 2066 * u_i) >> 10;
|
||||
(clamp_u8(out_r), clamp_u8(out_g), clamp_u8(out_b))
|
||||
(
|
||||
out_r.clamp(0, 255) as u8,
|
||||
out_g.clamp(0, 255) as u8,
|
||||
out_b.clamp(0, 255) as u8,
|
||||
)
|
||||
}
|
||||
|
||||
impl YuvFrame {
|
||||
impl RgbFrame {
|
||||
// Simple, temporary, best-effort yuv420->rgb converter. Not performant at all, but at least it works.
|
||||
// Temporary till we get native YUV support in shaders (as 3 vulkan textures).
|
||||
// SAFETY: this function expects YUV420 data only.
|
||||
fn to_rgb(&self) -> RgbFrame {
|
||||
#[allow(clippy::uninit_vec)]
|
||||
fn from_yuv(
|
||||
width: u16,
|
||||
height: u16,
|
||||
data_y: *const u8,
|
||||
data_u: *const u8,
|
||||
data_v: *const u8,
|
||||
stride_luma: usize,
|
||||
stride_chroma: usize,
|
||||
) -> RgbFrame {
|
||||
unsafe {
|
||||
let channels = 3; // rgb
|
||||
|
||||
let rgb_size = self.width as usize * self.height as usize * channels;
|
||||
let rgb_size = width as usize * height as usize * channels;
|
||||
let mut rgb = Vec::<u8>::with_capacity(rgb_size);
|
||||
rgb.set_len(rgb_size);
|
||||
|
||||
let ptr_rgb = rgb.as_mut_ptr();
|
||||
let ptr_y = self.data_y.as_ptr();
|
||||
let ptr_u = self.data_u.as_ptr();
|
||||
let ptr_v = self.data_v.as_ptr();
|
||||
|
||||
let stride_luma = self.stride_luma as usize;
|
||||
let stride_chroma = self.stride_chroma as usize;
|
||||
let width = self.width as usize;
|
||||
let height = self.height as usize;
|
||||
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let val_y = *ptr_y.offset((y * stride_luma + x) as isize);
|
||||
let val_u = *ptr_u.offset(((y / 2) * stride_chroma + (x / 2)) as isize);
|
||||
let val_v = *ptr_v.offset(((y / 2) * stride_chroma + (x / 2)) as isize);
|
||||
for y in 0..height as usize {
|
||||
for x in 0..width as usize {
|
||||
let val_y = *data_y.add(y * stride_luma + x);
|
||||
let val_u = *data_u.add((y / 2) * stride_chroma + (x / 2));
|
||||
let val_v = *data_v.add((y / 2) * stride_chroma + (x / 2));
|
||||
let (r, g, b) = yuv_to_rgb(val_y, val_u, val_v);
|
||||
|
||||
let pos = y * (width * channels) + x * channels;
|
||||
*ptr_rgb.offset((pos + 0) as isize) = r;
|
||||
*ptr_rgb.offset((pos + 1) as isize) = g;
|
||||
*ptr_rgb.offset((pos + 2) as isize) = b;
|
||||
let pos = y * (width as usize * channels) + x * channels;
|
||||
*ptr_rgb.add(pos) = r;
|
||||
*ptr_rgb.add(pos + 1) = g;
|
||||
*ptr_rgb.add(pos + 2) = b;
|
||||
}
|
||||
}
|
||||
|
||||
RgbFrame {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
width,
|
||||
height,
|
||||
data: rgb,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Av1Decoder {}
|
||||
pub struct Av1Decoder {
|
||||
ctx: *mut Dav1dContext,
|
||||
}
|
||||
|
||||
impl Drop for Av1Decoder {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dav1d_close(&raw mut self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Av1Decoder {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
pub fn new() -> anyhow::Result<Self> {
|
||||
unsafe {
|
||||
let mut set: Dav1dSettings = std::mem::zeroed();
|
||||
dav1d_default_settings(&raw mut set);
|
||||
|
||||
let mut ctx = null_mut();
|
||||
let ret = dav1d_open(&raw mut ctx, &raw mut set);
|
||||
if ret < 0 {
|
||||
anyhow::bail!("dav1d_open failed: {ret}");
|
||||
}
|
||||
Ok(Self { ctx })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_frame(&mut self, reader: &mut IvfReader) -> anyhow::Result<RgbFrame> {
|
||||
let packet = reader.read_frame()?;
|
||||
let (packet, pts) = reader.read_frame()?;
|
||||
|
||||
let mut decoder = rav1d::Decoder::new()?;
|
||||
let mut ret;
|
||||
|
||||
todo!();
|
||||
unsafe {
|
||||
let mut data: Dav1dData = std::mem::zeroed();
|
||||
data.data = packet.as_ptr();
|
||||
data.sz = packet.len();
|
||||
data.m.timestamp = pts as i64;
|
||||
data.m.size = packet.len();
|
||||
data.m.offset = -1;
|
||||
data.m.duration = 0;
|
||||
|
||||
// rav1d::Ok(RgbFrame {})
|
||||
ret = dav1d_send_data(self.ctx, &raw mut data);
|
||||
dav1d_data_unref(&raw mut data);
|
||||
if ret < 0 {
|
||||
anyhow::bail!("dav1d_send_data failed: {ret}");
|
||||
}
|
||||
|
||||
let mut picture: Dav1dPicture = std::mem::zeroed();
|
||||
ret = dav1d_get_picture(self.ctx, &raw mut picture);
|
||||
if ret < 0 {
|
||||
dav1d_picture_unref(&raw mut picture);
|
||||
anyhow::bail!("dav1d_get_picture failure: {ret}")
|
||||
}
|
||||
|
||||
let pic_y = picture.data[0]; // luma Y
|
||||
let pic_u = picture.data[1]; // chroma U
|
||||
let pic_v = picture.data[2]; // chroma V
|
||||
let stride_luma = picture.stride[0];
|
||||
let stride_chroma = picture.stride[1];
|
||||
|
||||
let rgb = RgbFrame::from_yuv(
|
||||
reader.width,
|
||||
reader.height,
|
||||
pic_y as *const u8,
|
||||
pic_u as *const u8,
|
||||
pic_v as *const u8,
|
||||
stride_luma as usize,
|
||||
stride_chroma as usize,
|
||||
);
|
||||
|
||||
dav1d_picture_unref(&raw mut picture);
|
||||
|
||||
Ok(rgb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue