Skip to content

Commit

Permalink
Cleanup: make load_mp4 a member function
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Oct 8, 2024
1 parent f0c5430 commit 77001ce
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 74 deletions.
4 changes: 1 addition & 3 deletions crates/store/re_video/examples/frames.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ use std::{
use indicatif::ProgressBar;
use parking_lot::Mutex;

use re_video::demux::mp4::load_mp4;

fn main() {
// frames <video.mp4>
let args: Vec<_> = std::env::args().collect();
Expand All @@ -27,7 +25,7 @@ fn main() {
println!("Decoding {video_path}");

let video = std::fs::read(video_path).expect("failed to read video");
let video = load_mp4(&video).expect("failed to load video");
let video = re_video::VideoData::load_mp4(&video).expect("failed to load video");

println!(
"{} {}x{}",
Expand Down
3 changes: 2 additions & 1 deletion crates/store/re_video/src/demux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ impl VideoData {
/// at the very least the should be a way to extract only metadata.
pub fn load_from_bytes(data: &[u8], media_type: &str) -> Result<Self, VideoLoadError> {
match media_type {
"video/mp4" => mp4::load_mp4(data),
"video/mp4" => Self::load_mp4(data),

media_type => {
if media_type.starts_with("video/") {
Err(VideoLoadError::UnsupportedMimeType {
Expand Down
142 changes: 72 additions & 70 deletions crates/store/re_video/src/demux/mp4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,86 +4,88 @@ use super::{Config, GroupOfPictures, Sample, VideoData, VideoLoadError};

use crate::{Time, Timescale};

pub fn load_mp4(bytes: &[u8]) -> Result<VideoData, VideoLoadError> {
let mp4 = re_mp4::Mp4::read_bytes(bytes)?;

let mp4_tracks = mp4.tracks().iter().map(|(k, t)| (*k, t.kind)).collect();

let track = mp4
.tracks()
.values()
.find(|t| t.kind == Some(re_mp4::TrackKind::Video))
.ok_or_else(|| VideoLoadError::NoVideoTrack)?;

let codec = track
.codec_string(&mp4)
.ok_or_else(|| VideoLoadError::UnsupportedCodec(unknown_codec_fourcc(&mp4, track)))?;
let description = track
.raw_codec_config(&mp4)
.ok_or_else(|| VideoLoadError::UnsupportedCodec(unknown_codec_fourcc(&mp4, track)))?;

let coded_height = track.height;
let coded_width = track.width;

let config = Config {
codec,
description,
coded_height,
coded_width,
};

let timescale = Timescale::new(track.timescale);
let duration = Time::new(track.duration as i64);
let mut samples = Vec::<Sample>::new();
let mut gops = Vec::<GroupOfPictures>::new();
let mut gop_sample_start_index = 0;
let data = track.data.clone();

for sample in &track.samples {
if sample.is_sync && !samples.is_empty() {
impl VideoData {
pub fn load_mp4(bytes: &[u8]) -> Result<Self, VideoLoadError> {
let mp4 = re_mp4::Mp4::read_bytes(bytes)?;

let mp4_tracks = mp4.tracks().iter().map(|(k, t)| (*k, t.kind)).collect();

let track = mp4
.tracks()
.values()
.find(|t| t.kind == Some(re_mp4::TrackKind::Video))
.ok_or_else(|| VideoLoadError::NoVideoTrack)?;

let codec = track
.codec_string(&mp4)
.ok_or_else(|| VideoLoadError::UnsupportedCodec(unknown_codec_fourcc(&mp4, track)))?;
let description = track
.raw_codec_config(&mp4)
.ok_or_else(|| VideoLoadError::UnsupportedCodec(unknown_codec_fourcc(&mp4, track)))?;

let coded_height = track.height;
let coded_width = track.width;

let config = Config {
codec,
description,
coded_height,
coded_width,
};

let timescale = Timescale::new(track.timescale);
let duration = Time::new(track.duration as i64);
let mut samples = Vec::<Sample>::new();
let mut gops = Vec::<GroupOfPictures>::new();
let mut gop_sample_start_index = 0;
let data = track.data.clone();

for sample in &track.samples {
if sample.is_sync && !samples.is_empty() {
let start = samples[gop_sample_start_index].decode_timestamp;
let sample_range = gop_sample_start_index as u32..samples.len() as u32;
gops.push(GroupOfPictures {
start,
sample_range,
});
gop_sample_start_index = samples.len();
}

let decode_timestamp = Time::new(sample.decode_timestamp as i64);
let composition_timestamp = Time::new(sample.composition_timestamp as i64);
let duration = Time::new(sample.duration as i64);

let byte_offset = sample.offset as u32;
let byte_length = sample.size as u32;

samples.push(Sample {
decode_timestamp,
composition_timestamp,
duration,
byte_offset,
byte_length,
});
}

if !samples.is_empty() {
let start = samples[gop_sample_start_index].decode_timestamp;
let sample_range = gop_sample_start_index as u32..samples.len() as u32;
gops.push(GroupOfPictures {
start,
sample_range,
});
gop_sample_start_index = samples.len();
}

let decode_timestamp = Time::new(sample.decode_timestamp as i64);
let composition_timestamp = Time::new(sample.composition_timestamp as i64);
let duration = Time::new(sample.duration as i64);

let byte_offset = sample.offset as u32;
let byte_length = sample.size as u32;

samples.push(Sample {
decode_timestamp,
composition_timestamp,
Ok(Self {
config,
timescale,
duration,
byte_offset,
byte_length,
});
}

if !samples.is_empty() {
let start = samples[gop_sample_start_index].decode_timestamp;
let sample_range = gop_sample_start_index as u32..samples.len() as u32;
gops.push(GroupOfPictures {
start,
sample_range,
});
gops,
samples,
data,
mp4_tracks,
})
}

Ok(VideoData {
config,
timescale,
duration,
gops,
samples,
data,
mp4_tracks,
})
}

fn unknown_codec_fourcc(mp4: &re_mp4::Mp4, track: &re_mp4::Track) -> re_mp4::FourCC {
Expand Down

0 comments on commit 77001ce

Please sign in to comment.