mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-24 01:58:19 -06:00
security(mxf): share resolved descriptor metadata (#2949)
* security(mxf): share resolved descriptor metadata * mxf: keep every source-package track in the no-material-package fallback Two packages may reuse a track id and number; comparing only those dropped a real track. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <brandon@storyteller.ai> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
0b99bafcc4
commit
1c40c48289
+19
-8
@@ -1,6 +1,7 @@
|
||||
//! Opening an MXF file: KLV walk, partitions, metadata resolution, sample tables.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::essence::{Codec, PictureInfo, SoundFormat, SoundInfo, decode_pcm, identify_picture, sniff_picture};
|
||||
use crate::index::{IndexEntry, IndexSegment};
|
||||
@@ -544,8 +545,8 @@ struct TrackRef {
|
||||
origin: i64,
|
||||
start_position: i64,
|
||||
duration: Option<i64>,
|
||||
descriptor: Option<Set>,
|
||||
sub_descriptors: Vec<Set>,
|
||||
descriptor: Option<Arc<Set>>,
|
||||
sub_descriptors: Vec<Arc<Set>>,
|
||||
body_sid: u32,
|
||||
index_sid: u32,
|
||||
}
|
||||
@@ -567,9 +568,13 @@ fn resolve_tracks(md: &Metadata, warnings: &mut Vec<String>) -> (Vec<TrackRef>,
|
||||
}
|
||||
let material = md.of_kind(st::MATERIAL_PACKAGE).next();
|
||||
let mut out = Vec::new();
|
||||
let mut descriptor_cache: HashMap<[u8; 16], Arc<Set>> = HashMap::new();
|
||||
let intern_descriptor = |set: &Set, cache: &mut HashMap<[u8; 16], Arc<Set>>| {
|
||||
if set.instance_uid == [0; 16] { Arc::new(set.clone()) } else { cache.entry(set.instance_uid).or_insert_with(|| Arc::new(set.clone())).clone() }
|
||||
};
|
||||
let mut timecode = material.and_then(|m| package_timecode(md, m));
|
||||
let name = material.and_then(|m| m.string(tag::PACKAGE_NAME));
|
||||
let file_track = |pkg: &Set, kind: Option<TrackKind>, id: Option<u32>, start: i64, duration: Option<i64>, name: Option<String>| -> Option<TrackRef> {
|
||||
let mut file_track = |pkg: &Set, kind: Option<TrackKind>, id: Option<u32>, start: i64, duration: Option<i64>, name: Option<String>| -> Option<TrackRef> {
|
||||
let umid = umid_of(pkg, tag::PACKAGE_UID).unwrap_or([0; 32]);
|
||||
for r in pkg.references(tag::PACKAGE_TRACKS) {
|
||||
let Some(t) = md.get(&r) else { continue };
|
||||
@@ -588,10 +593,16 @@ fn resolve_tracks(md: &Metadata, warnings: &mut Vec<String>) -> (Vec<TrackRef>,
|
||||
continue;
|
||||
}
|
||||
let desc = descriptor_for(md, pkg, tid, tk);
|
||||
let subs: Vec<Set> = desc
|
||||
let descriptor = desc.map(|d| intern_descriptor(d, &mut descriptor_cache));
|
||||
let subs: Vec<Arc<Set>> = desc
|
||||
.and_then(|d| d.dynamic_item(&SUB_DESCRIPTORS_ITEM))
|
||||
.map(|v| {
|
||||
crate::klv::batch_of(v).into_iter().filter_map(|b| b.get(..16)).filter_map(|b| md.get(&b.try_into().unwrap_or([0; 16]))).cloned().collect()
|
||||
crate::klv::batch_of(v)
|
||||
.into_iter()
|
||||
.filter_map(|b| b.get(..16))
|
||||
.filter_map(|b| md.get(&b.try_into().unwrap_or([0; 16])))
|
||||
.map(|s| intern_descriptor(s, &mut descriptor_cache))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let (body_sid, index_sid) = sids.get(&umid).copied().unwrap_or((0, 0));
|
||||
@@ -604,7 +615,7 @@ fn resolve_tracks(md: &Metadata, warnings: &mut Vec<String>) -> (Vec<TrackRef>,
|
||||
origin: t.i(tag::ORIGIN).unwrap_or(0),
|
||||
start_position: start,
|
||||
duration,
|
||||
descriptor: desc.cloned(),
|
||||
descriptor,
|
||||
sub_descriptors: subs,
|
||||
body_sid,
|
||||
index_sid,
|
||||
@@ -807,7 +818,7 @@ fn build_track(
|
||||
};
|
||||
match r.kind {
|
||||
TrackKind::Picture => {
|
||||
let pi = desc.map(picture_info).unwrap_or_default();
|
||||
let pi = desc.map(|d| picture_info(d)).unwrap_or_default();
|
||||
let mpeg_desc = desc.is_some_and(|d| d.kind() == Some(st::MPEG2_VIDEO_DESCRIPTOR));
|
||||
let mut codec = identify_picture(pi.picture_coding, container, mpeg_desc);
|
||||
if r.sub_descriptors.iter().any(|s| s.kind() == Some(st::AVC_SUBDESCRIPTOR)) && !matches!(codec, Codec::Avc { .. }) {
|
||||
@@ -828,7 +839,7 @@ fn build_track(
|
||||
build_pictures(src, &mut t, elements, index, warnings)?;
|
||||
}
|
||||
TrackKind::Sound => {
|
||||
let si = desc.map(sound_info).unwrap_or(SoundInfo { channels: 1, bits: 16, ..Default::default() });
|
||||
let si = desc.map(|d| sound_info(d)).unwrap_or(SoundInfo { channels: 1, bits: 16, ..Default::default() });
|
||||
let d10 = container.is_some_and(|c| c.item_starts_with(&[0x0D, 0x01, 0x03, 0x01, 0x02, 0x01]));
|
||||
let aes_element = d10 || key4[0] == 0x06 && key4[2] == 0x10;
|
||||
let pcm_desc = desc.is_some_and(|d| matches!(d.kind(), Some(st::AES3_DESCRIPTOR) | Some(st::WAVE_DESCRIPTOR)));
|
||||
|
||||
Reference in New Issue
Block a user