1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//! SMPTE ST 377-1:2019 "Material Exchange Format (MXF) — File Format
//! Specification".
//!
//! This crate implements exactly the wire structure described in the
//! curated spec transcription at `st377-1/docs/st377-1.md` (fetched
//! directly from `https://pub.smpte.org/latest/st377-1/st377-1-2019.pdf`) —
//! cite that file, not this doc comment, as the field-semantics oracle. It
//! also documents in detail this crate's scope decision: MXF is a huge
//! ecosystem spec (Operational Patterns, Essence Container mappings, DM/
//! Application Metadata plug-ins, per-essence-kind Descriptors all live in
//! sibling documents this crate does not attempt to anticipate), so this
//! first pass fully types the format's own backbone and the four Root
//! Metadata Sets every real MXF file has, and falls back to an identified-
//! but-generic passthrough for everything else — see `docs/st377-1.md`'s
//! "Scope decision for this crate" section for the full breakdown with
//! spec citations.
//!
//! - [`KlvItem`] — the generic KLV (Key-Length-Value) triplet (§6.3) every
//! other structure in an MXF file rides on; [`walk_klv_items`] /
//! [`collect_klv_items`] walk a sequence of them.
//! - [`PartitionPack`] — the Header/Body/Footer Partition Pack (§7.1-§7.4,
//! Tables 4-8): [`PartitionKind`] + [`PartitionStatus`] plus every Table 5
//! field.
//! - [`PrimerPack`] — the per-Partition local-tag lookup table (§9.2).
//! - [`LocalSet`] — the generic "local set" KLV-lite framing (§9.3) used by
//! every Header Metadata Set; [`StructuralSetKind`] identifies which Set
//! a given instance is (Table 17), even for the many Sets this crate does
//! not deeply type.
//! - [`Preface`], [`Identification`], [`ContentStorage`],
//! [`EssenceContainerData`] — the four Root Metadata Sets (Annex A) every
//! real MXF file has exactly one/more of, decoded field-by-field.
//! - [`MaterialPackage`], [`SourcePackage`] — the two concrete Package
//! kinds (Annex E / B.1), carrying Package UID, dates, and Track
//! references.
//! - [`TimelineTrack`], [`EventTrack`], [`StaticTrack`] — the three Track
//! kinds (B.12/B.13/B.14), wrapping a Sequence reference plus timing
//! properties.
//! - [`Sequence`] — the ordered component collection inside every Track
//! (B.9).
//! - [`SourceClip`] — a component referencing a span of Source Package
//! essence (B.10).
//! - [`TimecodeComponent`] — a component carrying a timecode reference
//! (B.17).
//! - [`FillerComponent`] — a gap placeholder inside a Sequence (B.11).
//! - [`op1a`] — OP1a Operational Pattern UL helpers (ST 378).
//! - [`RandomIndexPack`] — the optional file-trailer Partition index (§12).
//!
//! **Out of scope entirely**: Essence Container payload bytes (the actual
//! audio/video/data samples) — carried opaquely via [`KlvItem`], never
//! decoded, the same boundary as `st337`'s `burst_payload`/`rdd29`'s
//! `AudioDataDLC`. Index Table *contents*, Descriptors (F.*), DM Segments/
//! Source Clips (B.32-B.33), and Application Metadata Sets (C.*) are
//! identified via [`StructuralSetKind`] but not individually typed — see
//! `docs/st377-1.md`.
//!
//! ## OP1a support is structural-metadata-only (issue #937)
//!
//! [`op1a`] plus [`MaterialPackage`]/[`SourcePackage`]/[`TimelineTrack`]/
//! [`EventTrack`]/[`StaticTrack`]/[`Sequence`]/[`SourceClip`]/
//! [`TimecodeComponent`]/[`FillerComponent`] parse and byte-losslessly
//! round-trip every OP1a Header Metadata Set this crate types (see
//! `docs/st378-op1a.md`), and are validated against a real `ffmpeg`-muxed
//! OP1a file in `tests/fixture_real_op1a.rs`. Two things this does **not**
//! add up to:
//!
//! - **No Essence Descriptor type.** `docs/st378-op1a.md`'s minimum OP1a
//! file requires the File Package to carry an `EssenceDescriptor`
//! (§6.5/§8), but this crate has no typed representation of any
//! Descriptor (F.2-F.6) — [`SourcePackage::descriptor`] is a bare
//! [`StrongRef`], a 16-byte Instance UID this crate can neither resolve
//! nor build a target for. Doing so properly would mean typing not just
//! ST 377-1's own generic Descriptor Sets but the per-essence-kind
//! registrations that actually appear on the wire (this crate's real
//! fixture carries an MPEG Video Descriptor and a Wave Audio Descriptor,
//! both defined by *sibling* essence-container-mapping specs, not
//! ST 377-1 itself) — exactly the ecosystem-anticipation problem the
//! Scope section above already declines to take on.
//! - **No file assembler.** Nothing in this crate computes cross-Partition
//! byte offsets (`ThisPartition`/`PreviousPartition`/`FooterPartition`),
//! `HeaderByteCount`/`IndexByteCount`, or builds a [`RandomIndexPack`]
//! that actually points at the Partitions it describes.
//! [`PartitionPack`], [`PrimerPack`], the typed Header Metadata Sets, and
//! [`RandomIndexPack`] each parse and serialize correctly in isolation,
//! but nothing stitches them into one valid, playable OP1a file —
//! confirm this yourself in `tests/round_trip.rs`'s
//! `full_op1a_structure_builds_and_round_trips`: every offset/byte-count
//! field there is a hardcoded placeholder (`0`, or `9999` for the
//! `RandomIndexPack` byte offset), not a computed value.
//!
//! A full implementation would need, at minimum: a typed `EssenceDescriptor`
//! family (File/Generic Picture/CDCI/RGBA/Generic Sound/Generic Data/
//! Multiple, F.2-F.6) plus a way to plug in essence-kind-specific
//! descriptors from sibling specs; and a writer that lays out Partitions in
//! order, tracks running byte offsets as it serializes each one, backpatches
//! `HeaderByteCount`/`IndexByteCount`/`ThisPartition`/`PreviousPartition`/
//! `FooterPartition`, and emits a `RandomIndexPack` from the real offsets.
//! That is a second, comparably-sized project; tracked separately rather
//! than attempted here.
//!
//! Depends only on `broadcast-common`. `#![no_std]` + `alloc` when the
//! `std` feature is disabled.
//!
//! # Examples
//!
//! Parse a Partition Pack and walk its Header Metadata:
//!
//! ```
//! use broadcast_common::{Parse, Serialize};
//! use st377_1::{PartitionKind, PartitionPack, PartitionStatus};
//!
//! let pack = PartitionPack {
//! kind: PartitionKind::Header,
//! status: PartitionStatus::ClosedComplete,
//! major_version: 1,
//! minor_version: 3,
//! kag_size: 512,
//! this_partition: 0,
//! previous_partition: 0,
//! footer_partition: 0,
//! header_byte_count: 0,
//! index_byte_count: 0,
//! index_sid: 0,
//! body_offset: 0,
//! body_sid: 0,
//! operational_pattern: [0u8; 16],
//! essence_containers: Vec::new(),
//! };
//! let bytes = pack.to_bytes();
//! assert_eq!(PartitionPack::parse(&bytes).unwrap(), pack);
//! ```
// Runnable examples, embedded so they render on docs.rs and stay in sync
// with the actual `examples/*.rs` files (shown, not compiled).
extern crate alloc;
pub use ContentStorage;
pub use ;
pub use EssenceContainerData;
pub use FillerComponent;
pub use Identification;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Preface;
pub use VERSION_1_3;
pub use PrimerPack;
pub use ;
pub use Sequence;
pub use InterchangeObjectFields;
pub use SourceClip;
pub use TimecodeComponent;
pub use ;
pub use ;
// Re-exported so downstream code can build owned local-set item lists for
// dark/private extensions without depending on this crate's internal
// module layout.
pub use LocalSetOwnedItem;