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
//! What the muxer needs to write one track, and one packet.
use crate::matroska::MatroskaTrack;
use crate::metadata::MetadataItem;
use crate::track::{Timebase, TrackKind};
/// An output track, as [`Muxer::add_track`] returns it.
///
/// [`Muxer::add_track`]: crate::mkv::Muxer::add_track
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TrackId(pub(crate) u32);
impl TrackId {
/// The `TrackNumber` of the output track.
pub const fn get(self) -> u32 {
self.0
}
}
/// Everything the muxer needs to write one `TrackEntry`.
#[derive(Clone, Debug, PartialEq)]
pub struct TrackSpec {
/// The tick of [`PacketIn`] timestamps and durations. The muxer converts
/// them to `TimestampScale` ticks exactly, or refuses them.
pub timebase: Timebase,
/// The `TrackEntry` facts. A `uid` of `None` gets a UID derived from the
/// track number and `CodecID`.
pub matroska: MatroskaTrack,
/// Track tags. Each is written with a target of this track's `TrackUID`.
/// Each needs `MetadataScope::Tag` and a named key.
pub metadata: Vec<MetadataItem>,
}
impl TrackSpec {
/// A spec for `codec_id` with the defaults: language `und`, the track
/// enabled and default, no lacing, and no codec configuration. A video
/// track also needs [`MatroskaTrack::video`].
pub fn new(kind: TrackKind, codec_id: impl Into<String>, timebase: Timebase) -> Self {
let track_type = match kind {
TrackKind::Video => 1,
TrackKind::Audio => 2,
TrackKind::Subtitle => 17,
TrackKind::Data | TrackKind::Other => 33,
};
Self {
timebase,
matroska: MatroskaTrack {
uid: None,
track_type,
codec_id: codec_id.into(),
codec_private: None,
codec_name: None,
name: None,
language: "und".to_owned(),
language_bcp47: None,
default_duration: None,
codec_delay: 0,
seek_pre_roll: 0,
enabled: true,
default: true,
forced: false,
lacing: false,
content_encodings: Vec::new(),
video: None,
audio: None,
extra: Vec::new(),
},
metadata: Vec::new(),
}
}
}
/// One packet to write. Timestamps count in [`TrackSpec::timebase`].
///
/// Send each track's packets in decode order. The muxer writes blocks in the
/// order they arrive, and `pts` is free to reorder inside a track. Matroska
/// stores no decode timestamp.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PacketIn<'a> {
/// The packet bytes.
pub data: &'a [u8],
/// Presentation timestamp. It must be 0 or more: a Matroska block
/// timestamp is never negative.
pub pts: i64,
/// Duration. `None` means the track's `DefaultDuration`. The last packet
/// of a track needs one or the other.
pub duration: Option<u64>,
/// True for a keyframe (a random access point).
pub sync: bool,
/// True when a decoder can skip the frame.
pub discardable: bool,
/// The `DiscardPadding` in nanoseconds: positive trims the block end,
/// negative trims its start.
pub discard_padding: Option<i64>,
}