-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.rs
More file actions
127 lines (119 loc) · 4.04 KB
/
main.rs
File metadata and controls
127 lines (119 loc) · 4.04 KB
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
use std::{
fs::File,
io::{BufReader, Read},
path::PathBuf,
};
use anyhow::{Result, anyhow};
use clap::Parser;
use comfy_table::{Attribute, Cell, ContentArrangement, Table, presets};
use flvparse::{FlvFile, FlvTagType};
#[derive(Debug, Parser)]
#[command(author, about)]
struct Cli {
/// The input FLV file to parse.
#[arg(short, long)]
input: PathBuf,
/// Prints all tables about FLV File info.
#[arg(short, long)]
print: bool,
}
fn main() -> Result<()> {
let cli: Cli = Cli::parse();
let file = File::open(cli.input)?;
let mut reader = BufReader::new(file);
let mut input = vec![];
reader.read_to_end(&mut input)?;
let (_, flv) = FlvFile::parse(&input).map_err(|e| anyhow!("failed to parse: {e:?}"))?;
if cli.print {
print_table(&flv, true);
} else {
print_table(&flv, false);
}
Ok(())
}
fn print_table(flv_file: &FlvFile, print_body: bool) {
println!("FLV File Header");
let mut header = Table::new();
header.load_preset(presets::UTF8_BORDERS_ONLY);
header.set_content_arrangement(ContentArrangement::Dynamic);
header.set_header(vec![
Cell::new("Field").add_attribute(Attribute::Bold),
Cell::new("Value").add_attribute(Attribute::Bold),
]);
header.add_row(vec![
Cell::new("Signature (3B)"),
Cell::new(format!(
"{:x} {:x} {:x}",
flv_file.header.signature[0],
flv_file.header.signature[1],
flv_file.header.signature[2]
)),
]);
header.add_row(vec![
Cell::new("Version (1B)"),
Cell::new(format!("{}", flv_file.header.version)),
]);
header.add_row(vec![
Cell::new("Flags (1B)"),
Cell::new(format!(
"{:04b} {:04b}",
flv_file.header.flags & 0xf0,
flv_file.header.flags & 0x0f
)),
]);
header.add_row(vec![
Cell::new("DataOffset (4B)"),
Cell::new(format!("{}", flv_file.header.data_offset)),
]);
println!("{header}");
let mut body = Table::new();
body.load_preset(presets::UTF8_BORDERS_ONLY);
body.set_content_arrangement(ContentArrangement::Dynamic);
body.set_header(vec![
Cell::new("Index").add_attribute(Attribute::Bold),
Cell::new("TagType (1B)").add_attribute(Attribute::Bold),
Cell::new("DataSize (3B)").add_attribute(Attribute::Bold),
Cell::new("Timestamp (4B)").add_attribute(Attribute::Bold),
Cell::new("StreamID (3B)").add_attribute(Attribute::Bold),
]);
let mut index = 0usize;
let mut script_tag_num = 0usize;
let mut video_tag_num = 0usize;
let mut audio_tag_num = 0usize;
for (tag, _) in &flv_file.body.tags {
index += 1;
match tag.header.tag_type {
FlvTagType::Script => script_tag_num += 1,
FlvTagType::Video => video_tag_num += 1,
FlvTagType::Audio => audio_tag_num += 1,
}
body.add_row(vec![
Cell::new(format!("{}", index)),
Cell::new(format!("{:?}", tag.header.tag_type)),
Cell::new(format!("{}", tag.header.data_size)),
Cell::new(format!("{}", tag.header.timestamp)),
Cell::new(format!("{}", tag.header.stream_id)),
]);
}
if print_body {
println!("FLV File Body");
println!("{body}");
}
println!("Tag Summary");
let mut result = Table::new();
result.load_preset(presets::UTF8_BORDERS_ONLY);
result.set_content_arrangement(ContentArrangement::Dynamic);
result.set_header(vec![
Cell::new("Total tag number").add_attribute(Attribute::Bold),
Cell::new("Script tag number").add_attribute(Attribute::Bold),
Cell::new("Video tag number").add_attribute(Attribute::Bold),
Cell::new("Audio tag number").add_attribute(Attribute::Bold),
]);
result.add_row(vec![
Cell::new(format!("{}", index)),
Cell::new(format!("{}", script_tag_num)),
Cell::new(format!("{}", video_tag_num)),
Cell::new(format!("{}", audio_tag_num)),
]);
println!("{result}");
}