ebml_webm/types.rs
1//! Freestanding `WebM` track/frame types (no Mediaway dependency).
2
3#![forbid(unsafe_code)]
4
5pub use bytes::Bytes;
6
7/// Integer rational timebase (`num / den` seconds).
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct Rational {
10 /// Numerator.
11 pub num: u64,
12 /// Denominator (non-zero for valid timebases).
13 pub den: u32,
14}
15
16impl Rational {
17 /// Construct a rational.
18 #[must_use]
19 pub const fn new(num: u64, den: u32) -> Self {
20 Self { num, den }
21 }
22}
23
24/// Track metadata from `Tracks\TrackEntry` (v1 subset — see crate `adr/0001`).
25#[derive(Debug, Clone, PartialEq)]
26pub struct TrackInfo {
27 /// `TrackNumber` — referenced by `SimpleBlock`'s track number field.
28 pub track_number: u64,
29 /// Raw `TrackType` (1 = video, 2 = audio; other values pass through
30 /// unmapped in v1).
31 pub track_type: u8,
32 /// Raw `WebM` `CodecID` string (e.g. `"V_VP9"`, `"A_OPUS"`). Mapping to a
33 /// Mediaway `CodecKind` is the facade's job, not this crate's.
34 pub codec_id: String,
35 /// Video width in pixels (`0` for non-video tracks or if absent).
36 pub width: u32,
37 /// Video height in pixels (`0` for non-video tracks or if absent).
38 pub height: u32,
39 /// `Audio\SamplingFrequency` in Hz (spec default `8000.0` when absent; `0.0`
40 /// only ever appears if a file explicitly encodes it, which spec forbids).
41 pub sample_rate: f64,
42 /// `Audio\Channels` (spec default `1` when absent).
43 pub channels: u32,
44}
45
46impl TrackInfo {
47 /// `TrackType == 1` (video), per the Matroska/`WebM` `TrackType` enum.
48 #[must_use]
49 pub const fn is_video(&self) -> bool {
50 self.track_type == 1
51 }
52}
53
54/// One demuxed `SimpleBlock`/`Block` frame.
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct Frame {
57 /// Owning track's `TrackNumber`.
58 pub track_number: u64,
59 /// Absolute timecode in `TimecodeScale` ticks (`Cluster` timecode +
60 /// the block's signed relative timecode). Laced sub-frames within one
61 /// block share this same timecode — Matroska lacing does not encode a
62 /// distinct timecode per sub-frame (a real spec property, not a gap here).
63 pub timecode: i64,
64 /// Keyframe flag: `SimpleBlock`'s own flag bit, or (for a `BlockGroup`'s
65 /// `Block`) the *absence* of a sibling `ReferenceBlock`.
66 pub is_keyframe: bool,
67 /// `BlockGroup\BlockDuration` in `TimecodeScale` ticks, if present
68 /// (`None` for a bare `SimpleBlock`, which carries no duration).
69 pub duration_ticks: Option<u64>,
70 /// Frame payload bytes.
71 pub payload: Bytes,
72}
73
74/// One `Segment\Cues\CuePoint` entry — informational seek index; this crate
75/// does no seeking itself (sans-io: I/O and seeking belong to the adapter).
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub struct CuePoint {
78 /// `CueTime` in `TimecodeScale` ticks.
79 pub time_ticks: u64,
80 /// `CueClusterPosition` — byte offset from `Segment`'s data start.
81 pub cluster_position: u64,
82}
83
84/// One `Segment\SeekHead\Seek` entry.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub struct SeekEntry {
87 /// The referenced element's raw ID (same representation as [`crate::vint::decode_id`]).
88 pub id: u32,
89 /// Byte offset from `Segment`'s data start.
90 pub position: u64,
91}