Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit 22846d8

Browse files
author
rainliu
committed
fix clippy warning and upgrade to v0.1.1
1 parent 8b7e43b commit 22846d8

File tree

6 files changed

+611
-630
lines changed

6 files changed

+611
-630
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "webrtc-rtp"
33
version = "0.1.0"
4-
authors = ["Rain Liu <yuliu@outlook.com>", "Michael Uti <utimichael9@gmail.com>"]
4+
authors = ["Rain Liu <yliu@webrtc.rs>", "Michael Uti <utimichael9@gmail.com>"]
55
edition = "2018"
66
description = "A pure Rust implementation of RTP"
77
license = "MIT"

src/codecs/h264/h264_def.rs

Lines changed: 0 additions & 172 deletions
This file was deleted.

src/codecs/h264/h264_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[cfg(test)]
22
mod tests {
33
use crate::{
4-
codecs::h264::h264_def::*,
4+
codecs::h264::*,
55
errors::RTPError,
66
packetizer::{Depacketizer, Payloader},
77
};

src/codecs/h264/mod.rs

Lines changed: 171 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
mod h264_def;
21
mod h264_test;
32

4-
pub use h264_def::{H264Packet, H264Payloader};
3+
use std::vec;
4+
5+
use byteorder::BigEndian;
6+
use byteorder::ByteOrder;
7+
8+
use crate::{
9+
errors::RTPError,
10+
packetizer::{Depacketizer, Payloader},
11+
};
512

613
const STAPA_NALU_TYPE: u8 = 24;
714
const FUA_NALU_TYPE: u8 = 28;
@@ -51,3 +58,165 @@ fn emit_nalus(nals: &[u8], mut emit: impl FnMut(&[u8])) {
5158
}
5259
}
5360
}
61+
62+
pub struct H264Payloader;
63+
64+
/// Payload fragments a H264 packet across one or more byte arrays
65+
impl Payloader for H264Payloader {
66+
fn payload(&self, mtu: u16, payload: &[u8]) -> Vec<Vec<u8>> {
67+
let mut payloads = vec![];
68+
69+
if payload.is_empty() {
70+
return payloads;
71+
}
72+
73+
emit_nalus(payload, |nalu| {
74+
if nalu.is_empty() {
75+
return;
76+
}
77+
78+
let nalu_type = nalu[0] & NALU_TYPE_BITMASK;
79+
let nalu_ref_idc = nalu[0] & NALU_REF_IDC_BITMASK;
80+
81+
if nalu_type == 9 || nalu_type == 12 {
82+
return;
83+
}
84+
85+
// Single NALU
86+
if nalu.len() <= mtu as usize {
87+
let mut out = vec![0u8; nalu.len()];
88+
out.copy_from_slice(&nalu);
89+
payloads.push(out);
90+
return;
91+
}
92+
93+
// FU-A
94+
let max_fragment_size = mtu as isize - FUA_HEADER_SIZE as isize;
95+
96+
// The FU payload consists of fragments of the payload of the fragmented
97+
// NAL unit so that if the fragmentation unit payloads of consecutive
98+
// FUs are sequentially concatenated, the payload of the fragmented NAL
99+
// unit can be reconstructed. The NAL unit type octet of the fragmented
100+
// NAL unit is not included as such in the fragmentation unit payload,
101+
// but rather the information of the NAL unit type octet of the
102+
// fragmented NAL unit is conveyed in the F and NRI fields of the FU
103+
// indicator octet of the fragmentation unit and in the type field of
104+
// the FU header. An FU payload MAY have any number of octets and MAY
105+
// be empty.
106+
107+
// According to the RFC, the first octet is skipped due to redundant information
108+
let mut nalu_data_index = 1;
109+
let nalu_data_length = nalu.len() - nalu_data_index;
110+
let mut nalu_data_remaining = nalu_data_length;
111+
112+
if (max_fragment_size).min(nalu_data_remaining as isize) < 0 {
113+
return;
114+
}
115+
116+
while nalu_data_remaining > 0 {
117+
let current_fragment_size = (max_fragment_size as usize).min(nalu_data_remaining);
118+
let mut out = vec![0u8; FUA_HEADER_SIZE + current_fragment_size];
119+
120+
// +---------------+
121+
// |0|1|2|3|4|5|6|7|
122+
// +-+-+-+-+-+-+-+-+
123+
// |F|NRI| Type |
124+
// +---------------+
125+
out[0] = FUA_NALU_TYPE;
126+
out[0] |= nalu_ref_idc;
127+
128+
// +---------------+
129+
// |0|1|2|3|4|5|6|7|
130+
// +-+-+-+-+-+-+-+-+
131+
// |S|E|R| Type |
132+
// +---------------+
133+
134+
out[1] = nalu_type;
135+
if nalu_data_remaining == nalu_data_length {
136+
// Set start bit
137+
out[1] |= 1 << 7;
138+
} else if nalu_data_remaining - current_fragment_size == 0 {
139+
// Set end bit
140+
out[1] |= 1 << 6;
141+
}
142+
143+
out[FUA_HEADER_SIZE as usize..FUA_HEADER_SIZE as usize + current_fragment_size]
144+
.copy_from_slice(
145+
&nalu[nalu_data_index..nalu_data_index + current_fragment_size],
146+
);
147+
148+
payloads.push(out);
149+
150+
nalu_data_remaining -= current_fragment_size;
151+
nalu_data_index += current_fragment_size;
152+
}
153+
});
154+
155+
payloads
156+
}
157+
}
158+
159+
#[derive(Debug, Default)]
160+
pub struct H264Packet {}
161+
162+
impl Depacketizer for H264Packet {
163+
fn depacketize(&mut self, payload: &[u8]) -> Result<Vec<u8>, RTPError> {
164+
if payload.len() <= 2 {
165+
return Err(RTPError::ShortPacket);
166+
}
167+
168+
// NALU Types
169+
// https://tools.ietf.org/html/rfc6184#section-5.4
170+
let nalu_type = payload[0] & NALU_TYPE_BITMASK;
171+
172+
if nalu_type > 0 && nalu_type < 24 {
173+
let a = [&ANNEXB_NALUSTART_CODE[..], payload].concat();
174+
return Ok(a);
175+
} else if nalu_type == STAPA_NALU_TYPE {
176+
let mut current_offset = STAPA_HEADER_SIZE;
177+
let mut result = vec![];
178+
179+
while current_offset < payload.len() {
180+
let nalu_size = BigEndian::read_u16(&payload[current_offset..]);
181+
current_offset += STAPA_NALU_LENGTH_SIZE;
182+
183+
if payload.len() < current_offset + nalu_size as usize {
184+
return Err(RTPError::ShortPacket);
185+
}
186+
187+
result.extend_from_slice(&ANNEXB_NALUSTART_CODE);
188+
result.extend_from_slice(
189+
&payload[current_offset..current_offset + nalu_size as usize],
190+
);
191+
current_offset += nalu_size as usize;
192+
}
193+
194+
return Ok(result);
195+
} else if nalu_type == FUA_NALU_TYPE {
196+
if payload.len() < FUA_HEADER_SIZE {
197+
return Err(RTPError::ShortPacket);
198+
}
199+
200+
if payload[1] & FUA_START_BITMASK != 0 {
201+
let nalu_ref_idc = payload[0] & NALU_REF_IDC_BITMASK;
202+
let fragmented_nalu_type = payload[1] & NALU_TYPE_BITMASK;
203+
204+
// Take a copy of payload since we are mutating it.
205+
let mut payload_copy = payload.to_owned();
206+
payload_copy[FUA_HEADER_SIZE - 1] = nalu_ref_idc | fragmented_nalu_type;
207+
208+
let a = [
209+
&ANNEXB_NALUSTART_CODE[..],
210+
&payload_copy[FUA_HEADER_SIZE - 1..],
211+
]
212+
.concat();
213+
214+
return Ok(a);
215+
}
216+
217+
return Ok(payload[FUA_HEADER_SIZE..].to_vec());
218+
}
219+
220+
Err(RTPError::UnhandledNALUType(nalu_type))
221+
}
222+
}

0 commit comments

Comments
 (0)