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
use super::*;
pub fn ebml_header(webm : bool) -> Element {
use super::database::Class::*;
el(EBML, vec![
el_uns(EBMLVersion, 1),
el_uns(EBMLReadVersion, 1),
el_uns(EBMLMaxIDLength, 4),
el_uns(EBMLMaxSizeLength, 8),
el_txt(DocType, String::from(if webm { "webm" } else {"matroska"} )),
el_uns(DocTypeVersion, 2),
el_uns(DocTypeReadVersion, 2),
])
}
pub fn cluster_with_one_simple_block(cluster_timecode: u64, block_content: Vec<u8>) -> Element {
use super::database::Class::*;
el(Cluster, vec![
el_uns(Timecode, cluster_timecode),
el_bin(SimpleBlock, block_content),
])
}
pub fn cluster_with_block_duration(cluster_timecode: u64, duration: u64, block_content: Vec<u8>) -> Element {
use super::database::Class::*;
el(Cluster, vec![
el_uns(Timecode, cluster_timecode),
el(BlockGroup, vec![
el_uns(BlockDuration, duration),
el_bin(Block, block_content),
]),
])
}
pub fn video_track_entry(
track_number:u64,
track_uid:u64,
codec_id:String,
codec_private:Option<Vec<u8>>,
default_duration:Option<u64>,
width:u64,
height:u64,
display_width:u64,
display_height:u64) -> Element {
use super::database::Class::*;
el(TrackEntry, vec![
el_uns(TrackNumber, track_number),
el_uns(TrackUID, track_uid),
el_uns(TrackType, 1),
el_txt(CodecID, codec_id),
match codec_private { Some(x) => el_bin(CodecPrivate, x), None => el_bin(Void, vec![]) },
match default_duration { Some(x) => el_uns(DefaultDuration, x), None=> el_bin(Void, vec![]) },
el(Video, vec![
el_uns(PixelWidth, width),
el_uns(PixelHeight, height),
el_uns(DisplayWidth, display_width),
el_uns(DisplayHeight, display_height),
]),
])
}
pub fn audio_track_entry(
track_number:u64,
track_uid:u64,
codec_id:String,
codec_private:Option<Vec<u8>>,
default_duration:Option<u64>,
sampling_frequency:u64,
channels:u64) -> Element {
use super::database::Class::*;
el(TrackEntry, vec![
el_uns(TrackNumber, track_number),
el_uns(TrackUID, track_uid),
el_uns(TrackType, 2),
el_txt(CodecID, codec_id),
match codec_private { Some(x) => el_bin(CodecPrivate, x), None => el_bin(Void, vec![]) },
match default_duration { Some(x) => el_uns(DefaultDuration, x), None=> el_bin(Void, vec![]) },
el(Audio, vec![
el_uns(SamplingFrequency, sampling_frequency),
el_uns(Channels, channels),
]),
])
}
pub fn segment_info(
timecode_scale : u64,
muxing_app : String,
writing_app : String,
title : Option<String>,
duration: Option<f64>,
date: Option<i64>,
segment_uid: Option<Vec<u8>>) -> Element {
use super::database::Class::*;
el(Info, vec![
el_uns(TimecodeScale, timecode_scale),
el_txt(MuxingApp, muxing_app),
el_txt(WritingApp, writing_app),
match title { Some(x) => el_txt(Title, x), None => el_bin(Void, vec![]) },
match segment_uid { Some(x) => el_bin(SegmentUID, x), None => el_bin(Void, vec![]) },
match duration { Some(x) => el_flo(Duration, x), None => el_bin(Void, vec![]) },
match date { Some(x) => el_date(DateUTC, x), None => el_bin(Void, vec![]) },
])
}
pub fn matroska_file( segment_info: Element, tracks: Vec<Element>, clusters: Vec<Element> ) -> Vec<u8>
{
use super::database::Class::*;
let mut v = vec![];
v.append(&mut super::generator::generate(&ebml_header(false)));
v.append(&mut super::generator::generate(
&mut el(Segment, {let mut x = vec![segment_info, el(Tracks, tracks)]; x.extend(clusters); x})
));
v
}