Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2399,6 +2399,15 @@ dependencies = [
"simd-adler32",
]

[[package]]
name = "ffmpeg-sidecar"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd1e249e0ceeb0f5c9f84a3c6941c3bde3ebc2815f4b94531a7e806af61c4c0"
dependencies = [
"anyhow",
]

[[package]]
name = "filetime"
version = "0.2.23"
Expand Down Expand Up @@ -6183,6 +6192,7 @@ dependencies = [
"criterion",
"crossbeam",
"econtext",
"ffmpeg-sidecar",
"indicatif",
"itertools 0.13.0",
"parking_lot",
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ econtext = "0.2" # Prints error contexts on crashes
ehttp = "0.5.0"
enumset = "1.0.12"
env_logger = { version = "0.10", default-features = false }
ffmpeg-sidecar = "1.1.2"
fixed = { version = "<1.28", default-features = false } # 1.28+ is MSRV 1.79+
flatbuffers = "23.0"
futures-channel = "0.3"
Expand Down
9 changes: 8 additions & 1 deletion crates/store/re_video/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ features = ["all"]


[features]
default = ["av1"]
default = ["av1", "ffmpeg"]

## Native AV1 decoding.
av1 = ["dep:dav1d"]

## Decode H.264 using ffmpeg over CLI.
ffmpeg = ["dep:ffmpeg-sidecar"]

## Enable faster native video decoding with assembly.
## You need to install [nasm](https://nasm.us/) to compile with this feature.
nasm = [
Expand Down Expand Up @@ -61,7 +64,11 @@ dav1d = { workspace = true, optional = true, default-features = false, features
"bitdepth_8",
] }

ffmpeg-sidecar = { workspace = true, optional = true }


[dev-dependencies]
# For the `frames` example:
indicatif.workspace = true
criterion.workspace = true

Expand Down
35 changes: 32 additions & 3 deletions crates/store/re_video/examples/frames.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use indicatif::ProgressBar;
use parking_lot::Mutex;

fn main() {
re_log::setup_logging();

// frames <video.mp4>
let args: Vec<_> = std::env::args().collect();
let Some(video_path) = args.get(1) else {
Expand Down Expand Up @@ -88,8 +90,18 @@ fn write_video_frames(
.create(true)
.truncate(true)
.open(output_dir.join(format!("{i:0width$}.ppm")))
.expect("failed to open file");
write_binary_ppm(&mut file, frame.width, frame.height, &frame.data);
.expect("failed to oformatpen file");
match frame.format {
re_video::PixelFormat::Rgb8Unorm => {
write_ppm_rgb24(&mut file, frame.width, frame.height, &frame.data);
}
re_video::PixelFormat::Rgba8Unorm => {
write_ppm_rgba32(&mut file, frame.width, frame.height, &frame.data);
}
re_video::PixelFormat::Yuv { .. } => {
re_log::error_once!("YUV frame writing is not not supported");
}
}
}
}
}
Expand All @@ -98,7 +110,24 @@ fn num_digits(n: usize) -> usize {
(n as f64).log10().floor() as usize + 1
}

fn write_binary_ppm(file: &mut File, width: u32, height: u32, rgba: &[u8]) {
fn write_ppm_rgb24(file: &mut File, width: u32, height: u32, rgb: &[u8]) {
assert_eq!(width as usize * height as usize * 3, rgb.len());

let header = format!("P6\n{width} {height}\n255\n");

let mut data = Vec::with_capacity(header.len() + width as usize * height as usize * 3);
data.extend_from_slice(header.as_bytes());

for rgb in rgb.chunks(3) {
data.extend_from_slice(&[rgb[0], rgb[1], rgb[2]]);
}

file.write_all(&data).expect("failed to write frame data");
}

fn write_ppm_rgba32(file: &mut File, width: u32, height: u32, rgba: &[u8]) {
assert_eq!(width as usize * height as usize * 4, rgba.len());

let header = format!("P6\n{width} {height}\n255\n");

let mut data = Vec::with_capacity(header.len() + width as usize * height as usize * 3);
Expand Down
2 changes: 1 addition & 1 deletion crates/store/re_video/src/decode/async_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl AsyncDecoder {
let comms = Comms::default();

let thread = std::thread::Builder::new()
.name("av1_decoder".into())
.name(format!("decoer thread for {debug_name}"))
.spawn({
let comms = comms.clone();
move || {
Expand Down
2 changes: 1 addition & 1 deletion crates/store/re_video/src/decode/av1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ fn output_picture(
width: picture.width(),
height: picture.height(),
format,
timestamp: Time(picture.timestamp().unwrap_or(0)),
composition_timestamp: Time(picture.timestamp().unwrap_or(0)),
duration: Time(picture.duration()),
};
on_output(Ok(frame));
Expand Down
Loading