Skip to content

Commit 56a9031

Browse files
author
Mr.Panda
authored
Merge pull request #20 from quasipaas/dev
睡觉,暂时更新部分;
2 parents 4cdfd23 + 01c3273 commit 56a9031

File tree

8 files changed

+841
-0
lines changed

8 files changed

+841
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
### 版本
2424
开发阶段 </br>
25+
项目进度更新在 [项目看板](https://github.com/quasipaas/Quasipaa/projects/1),可以随时跟踪.</br>
2526

2627

2728
### 支持的编码器

lib/flv/src/audio.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use bytes::{Bytes, BytesMut};
2+
use super::Metadata;
3+
4+
/// 解析音频帧
5+
///
6+
/// 注意: 只支持AAC.
7+
/// 输入音频帧获得音频帧信息.
8+
pub fn decoder(data: BytesMut) -> Metadata {
9+
let audio_object_type = data[2] >> 3;
10+
let sampling_index = ((data[2] & 0x07) << 1) | (data[3] >> 7);
11+
let sampling_frequence = match sampling_index {
12+
0 => 96000,
13+
1 => 88200,
14+
2 => 64000,
15+
3 => 48000,
16+
4 => 44100,
17+
5 => 32000,
18+
6 => 24000,
19+
7 => 22050,
20+
8 => 16000,
21+
9 => 12000,
22+
10 => 11025,
23+
11 => 8000,
24+
_ => 7350
25+
};
26+
27+
let channel_config = (data[3] & 0x78) >> 3;
28+
let mut extension_sampling = sampling_index;
29+
if sampling_index >= 6 {
30+
extension_sampling = sampling_index - 3;
31+
}
32+
33+
let mut config = [0u8; 4];
34+
config[0] = audio_object_type << 3;
35+
config[0] |= (sampling_index & 0x0F) >> 1;
36+
config[1] = (sampling_index & 0x0F) << 7;
37+
config[1] |= (channel_config & 0x0F) << 3;
38+
config[1] |= (extension_sampling & 0x0F) >> 1;
39+
config[2] |= (extension_sampling & 0x01) << 7;
40+
config[2] |= 2 << 2;
41+
42+
Metadata {
43+
track_id: 2,
44+
duration: 0,
45+
timescale: 1000,
46+
audio_sample_rate: sampling_frequence,
47+
channel_count: channel_config,
48+
codec: "mp4a.40.5".to_string(),
49+
original_codec: "mp4a.40.5".to_string(),
50+
config: Bytes::from(config.to_vec()),
51+
ref_sample_duration: 1024 / sampling_frequence * 1000
52+
}
53+
}

lib/flv/src/exp_golomb.rs

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use bytes::{BytesMut, BufMut, Buf};
2+
use std::cmp;
3+
4+
pub struct ExpGolomb {
5+
buffer: BytesMut,
6+
index: usize,
7+
total_bits: usize,
8+
total_bytes: usize,
9+
current_word: usize,
10+
current_word_bits_left: usize
11+
}
12+
13+
impl ExpGolomb {
14+
pub fn new(data: &[u8]) -> Self {
15+
let total_bytes = data.len();
16+
Self {
17+
index: 0,
18+
total_bytes,
19+
current_word: 0,
20+
current_word_bits_left: 0,
21+
total_bits: total_bytes * 8,
22+
buffer: BytesMut::from(data),
23+
}
24+
}
25+
26+
#[rustfmt::skip]
27+
fn fill_current_word(&mut self) {
28+
let buffer_bytes_left = self.total_bytes - self.index;
29+
let bytes_read = cmp::min(4, buffer_bytes_left);
30+
let mut word = BytesMut::from(&self.buffer[self.index..self.index + bytes_read]);
31+
self.current_word = word.get_u32() as usize;
32+
self.current_word_bits_left = bytes_read * 8;
33+
self.index = bytes_read;
34+
}
35+
36+
#[rustfmt::skip]
37+
fn skip_leading_zero(&mut self) -> usize {
38+
let mut zero_count = 0;
39+
for _ in zero_count..(self.current_word_bits_left - 1) {
40+
if self.current_word & (0x80000000 >> zero_count) != 0 {
41+
self.current_word <<= zero_count;
42+
self.current_word_bits_left -= zero_count;
43+
return zero_count;
44+
}
45+
46+
zero_count += 1;
47+
}
48+
49+
self.fill_current_word();
50+
return zero_count + self.skip_leading_zero();
51+
}
52+
53+
#[rustfmt::skip]
54+
pub fn read_bits(&mut self, bits: usize) -> usize {
55+
if bits <= self.current_word_bits_left {
56+
let result = self.current_word >> (32 - bits);
57+
self.current_word_bits_left -= bits;
58+
self.current_word <<= bits;
59+
return result;
60+
}
61+
62+
let mut result = if self.current_word_bits_left > 0 { self.current_word } else { 0 };
63+
result = result >> (32 - self.current_word_bits_left);
64+
let bits_need_left = bits - self.current_word_bits_left;
65+
self.fill_current_word();
66+
let bits_read_next = cmp::min(bits_need_left, self.current_word_bits_left);
67+
let result2 = self.current_word >> (32 - bits_read_next);
68+
self.current_word_bits_left -= bits_read_next;
69+
self.current_word <<= bits_read_next;
70+
result = (result << bits_read_next) | result2;
71+
result
72+
}
73+
74+
#[rustfmt::skip]
75+
pub fn read_bool(&mut self) -> bool {
76+
self.read_bits(1) == 1
77+
}
78+
79+
#[rustfmt::skip]
80+
pub fn read_byte(&mut self) -> usize {
81+
self.read_bits(8)
82+
}
83+
84+
#[rustfmt::skip]
85+
pub fn read_ueg(&mut self) -> usize {
86+
let leading_zeros = self.skip_leading_zero();
87+
self.read_bits(leading_zeros + 1) - 1
88+
}
89+
90+
#[rustfmt::skip]
91+
pub fn read_seg(&mut self) -> usize {
92+
let value = self.read_ueg();
93+
match value & 0x01 > 0 {
94+
true => (value + 1) >> 1,
95+
false => 0 - (value >> 1)
96+
}
97+
}
98+
}

lib/flv/src/lib.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
mod exp_golomb;
2+
mod audio;
3+
mod video;
4+
mod sps;
5+
16
use bytes::BytesMut;
27
use bytes::BufMut;
38
use bytes::Bytes;
@@ -22,6 +27,20 @@ pub enum Tag {
2227
Video
2328
}
2429

30+
/// 媒体信息
31+
#[derive(Debug)]
32+
pub struct Metadata {
33+
pub track_id: u8,
34+
pub timescale: u32,
35+
pub duration: u32,
36+
pub audio_sample_rate: u32,
37+
pub channel_count: u8,
38+
pub codec: String,
39+
pub original_codec: String,
40+
pub config: Bytes,
41+
pub ref_sample_duration: u32
42+
}
43+
2544
/// Create FLV frame
2645
///
2746
/// Timestamp and TimestampExtended form the

lib/flv/src/sps.rs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use bytes::{BytesMut, BufMut, Buf};
2+
use super::exp_golomb::ExpGolomb;
3+
4+
pub fn ebsp2rbsp(data: &[u8]) -> BytesMut {
5+
let mut dst = BytesMut::new();
6+
for i in 0..data.len() {
7+
if i >= 2 {
8+
let bit_1 = data[i] == 0x03;
9+
let bit_2 = data[i - 1] == 0x00;
10+
let bit_3 = data[i - 2] == 0x00;
11+
if bit_1 && bit_2 && bit_3 {
12+
continue;
13+
}
14+
}
15+
16+
dst.put_u8(data[i]);
17+
}
18+
19+
dst
20+
}
21+
22+
pub fn parse(mut data: BytesMut) {
23+
let rbsp = ebsp2rbsp(&data);
24+
let mut gb = ExpGolomb::new(&rbsp);
25+
26+
gb.read_byte();
27+
let profile_idc = gb.read_byte(); // profile_idc
28+
gb.read_byte(); // constraint_set_flags[5] + reserved_zero[3]
29+
let level_idc = gb.read_byte(); // level_idc
30+
gb.read_ueg(); // seq_parameter_set_id
31+
32+
let profile_string = get_profile_string(profile_idc);
33+
}
34+
35+
pub fn get_profile_string(profile_idc: usize) -> &'static str {
36+
match profile_idc {
37+
66 => "Baseline",
38+
77 => "Main",
39+
88 => "Extended",
40+
100 => "High",
41+
110 => "High10",
42+
122 => "High422",
43+
244 => "High444",
44+
_ => "Unknown"
45+
}
46+
}

lib/flv/src/video.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use bytes::{Bytes, BytesMut, Buf};
2+
use super::Metadata;
3+
4+
/// 解析视频帧
5+
///
6+
/// 注意: 只支持H264
7+
pub fn decoder(mut data: BytesMut) {
8+
let video_spec = data.get_u8();
9+
let video_frame = (video_spec & 240) >> 4;
10+
let codec_id = video_spec & 15;
11+
let packet_type = data.get_u8();
12+
let cts_unsigned = data.get_u32() & 0x00FFFFFF;
13+
let cts = (cts_unsigned << 8) >> 8;
14+
let version = data.get_u8();
15+
let avc_profile = data.get_u8();
16+
let profile_compatibility = data.get_u8();
17+
let avclevel = data.get_u8();
18+
let nalu_length_size = (data.get_u8() & 3) + 1;
19+
let sps_count = data.get_u8() & 31;
20+
21+
for _ in 0..sps_count {
22+
let len = data.get_u16();
23+
if len == 0 {
24+
continue;
25+
}
26+
27+
28+
}
29+
}

lib/fmp4/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "fmp4"
3+
version = "0.1.0"
4+
authors = ["Mr.Panda <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
bytes = "0.5.4"

0 commit comments

Comments
 (0)