use std::time::Instant;
fn main() {
let path = std::env::args()
.nth(1)
.unwrap_or_else(|| "/mnt/v/heic/22BB086F-C17C-4A9D-897B-4AE72FB2B9A0.HEIC".to_string());
let heic_data = std::fs::read(&path).expect("read heic");
let container = heic::heif::parse(&heic_data, &heic::Unstoppable).expect("parse heic");
let mut config = None;
let mut image_data_vec: Vec<u8> = Vec::new();
for info in &container.item_infos {
let Some(item) = container.get_item(info.item_id) else {
continue;
};
if let Some(cfg) = item.hevc_config.as_ref() {
let data = container.get_item_data(item.id).expect("item data");
config = Some(cfg.clone());
image_data_vec = data.into_owned();
eprintln!(
"Using item id={} type={:?} size={}",
item.id,
item.item_type,
image_data_vec.len()
);
break;
}
}
let config = config.expect("no item with hvcC in container");
let image_data = &image_data_vec[..];
let mut annexb: Vec<u8> = Vec::new();
for nal_data in &config.nal_units {
annexb.extend_from_slice(&[0, 0, 0, 1]);
annexb.extend_from_slice(nal_data);
}
let length_size = (config.length_size_minus_one + 1) as usize;
let mut pos = 0usize;
while pos + length_size <= image_data.len() {
let mut nal_len = 0u32;
for i in 0..length_size {
nal_len = (nal_len << 8) | image_data[pos + i] as u32;
}
pos += length_size;
let nal_len = nal_len as usize;
if pos + nal_len > image_data.len() {
break;
}
annexb.extend_from_slice(&[0, 0, 0, 1]);
annexb.extend_from_slice(&image_data[pos..pos + nal_len]);
pos += nal_len;
}
eprintln!("Annex-B stream: {} bytes", annexb.len());
for _ in 0..20 {
let _ = heic::hevc::get_info(&annexb);
}
let iters = 500u32;
let t0 = Instant::now();
let mut sink = 0usize;
for _ in 0..iters {
let info = heic::hevc::get_info(&annexb).expect("get_info");
sink = sink.wrapping_add(info.width as usize);
}
let elapsed = t0.elapsed();
let per = elapsed / iters;
println!(
"get_info (parses Annex-B NALs + parses SPS) over {} bytes: {:?}/iter ({} iters total {:?}), sink={}",
annexb.len(),
per,
iters,
elapsed,
sink
);
let throughput_gib_s =
(annexb.len() as f64 * iters as f64) / elapsed.as_secs_f64() / (1024.0 * 1024.0 * 1024.0);
println!("Throughput: {:.2} GiB/s", throughput_gib_s);
}