mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-24 10:10:05 -06:00
security(codecs): deduplicate hardware parameter-set checks (#2890)
This commit is contained in:
+21
-4
@@ -8,6 +8,7 @@
|
|||||||
//! decode, and a hardware decoder that fails mid-stream switches to
|
//! decode, and a hardware decoder that fails mid-stream switches to
|
||||||
//! [`crate::software_video_decoder`], so registering one never makes a file undecodable.
|
//! [`crate::software_video_decoder`], so registering one never makes a file undecodable.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||||
|
|
||||||
use filmcraft_isobmff::{CodecConfig, SampleEntry};
|
use filmcraft_isobmff::{CodecConfig, SampleEntry};
|
||||||
@@ -175,10 +176,14 @@ impl StreamInfo {
|
|||||||
/// with (parameter sets, a sequence header, a key frame of another format).
|
/// with (parameter sets, a sequence header, a key frame of another format).
|
||||||
pub fn parameters_changed(&self, sample: &[u8]) -> bool {
|
pub fn parameters_changed(&self, sample: &[u8]) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Nal(i) => i.nals(sample).into_iter().any(|n| {
|
Self::Nal(i) => {
|
||||||
n.first().is_some_and(|&h| i.is_parameter_set(i.nal_type(h)))
|
let configured: HashSet<&[u8]> = i.parameter_sets.iter().map(|p| without_trailing_zeros(p)).collect();
|
||||||
&& !i.parameter_sets.iter().any(|p| without_trailing_zeros(p) == without_trailing_zeros(n))
|
let mut checked = HashSet::new();
|
||||||
}),
|
i.nals(sample).into_iter().any(|n| {
|
||||||
|
let n = without_trailing_zeros(n);
|
||||||
|
n.first().is_some_and(|&h| i.is_parameter_set(i.nal_type(h))) && checked.insert(n) && !configured.contains(n)
|
||||||
|
})
|
||||||
|
}
|
||||||
Self::Frame(i) => i.parameters_changed(sample),
|
Self::Frame(i) => i.parameters_changed(sample),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,4 +461,16 @@ mod tests {
|
|||||||
assert!(info.parameters_changed(&sample(&hvcc_pps[..6])), "a missing byte that is not zero is a change");
|
assert!(info.parameters_changed(&sample(&hvcc_pps[..6])), "a missing byte that is not zero is a change");
|
||||||
assert!(info.parameters_changed(&sample(&[0x44, 0x01, 0xe0, 0xf7, 0xc0, 0x4c, 0x91])), "another PPS is a change");
|
assert!(info.parameters_changed(&sample(&[0x44, 0x01, 0xe0, 0xf7, 0xc0, 0x4c, 0x91])), "another PPS is a change");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn repeated_parameter_sets_are_checked_once_per_distinct_nal() {
|
||||||
|
let pps = vec![0x44, 0x01, 0xe0, 0xf7, 0xc0, 0x4c, 0x90];
|
||||||
|
let info = StreamInfo::Nal(hevc_info(std::iter::repeat_n(pps.clone(), 256).collect()));
|
||||||
|
let mut sample = Vec::new();
|
||||||
|
for _ in 0..256 {
|
||||||
|
sample.extend_from_slice(&(pps.len() as u32).to_be_bytes());
|
||||||
|
sample.extend_from_slice(&pps);
|
||||||
|
}
|
||||||
|
assert!(!info.parameters_changed(&sample));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user