Skip to main content

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}