8
9
10
11
12
13
21 uint32_t ssrc = 0x12345678)
28 if (!data || len < 5)
return 0;
29 ESP_LOGI(TAG,
"Packetizing frame of size %u bytes", (
unsigned)len);
35 std::vector<std::pair<
const uint8_t*, size_t>> nals;
36 extractNALs(data, len, nals);
37 if (nals.empty())
return 0;
41 for (
auto& n : nals) {
42 uint8_t type = n.first[0] & 0x1F;
43 if (type == 5) is_idr =
true;
44 if (type == 7) sps_.assign(n.first, n.first + n.second);
45 if (type == 8) pps_.assign(n.first, n.first + n.second);
49 std::vector<std::pair<
const uint8_t*, size_t>> send_list;
51 if (is_idr && !sps_.empty() && !pps_.empty()) {
52 send_list.emplace_back(sps_.data(), sps_.size());
53 send_list.emplace_back(pps_.data(), pps_.size());
56 for (
auto& n : nals) {
57 send_list.push_back(n);
61 for (size_t i = 0; i < send_list.size(); ++i) {
62 bool last_nal = (i == send_list.size() - 1);
63 sendNAL(send_list[i].first, send_list[i].second, last_nal);
70 ESP_LOGE(
"RTPPacketizer",
"write(uint8_t) is not implemented, use write() instead");
77 std::vector<uint8_t> buffer_;
79 uint16_t sequence_number_ = 0;
80 uint32_t timestamp_ = 0;
83 std::vector<uint8_t> sps_;
84 std::vector<uint8_t> pps_;
85 const char* TAG =
"RDPPacketizer";
91 void sendPacket(
const uint8_t* payload, size_t payload_len,
bool marker) {
92 ESP_LOGD(TAG,
"sendPacket: %u bytes", (
unsigned)payload_len);
94 buildHeader(rtp, marker);
96 buffer_.insert(buffer_.end(), rtp, rtp + 12);
97 buffer_.insert(buffer_.end(), payload, payload + payload_len);
98 out_.write(buffer_.data(), buffer_.size());
103 void sendNAL(
const uint8_t* data, size_t len,
bool last_nal_of_frame) {
104 ESP_LOGD(TAG,
"sendNAL: size=%u bytes, last_nal_of_frame=%d", (
unsigned)len, last_nal_of_frame);
105 if (len <= MTU - 12) {
106 sendPacket(data, len, last_nal_of_frame);
111 uint8_t nal_header = data[0];
112 uint8_t nal_type = nal_header & 0x1F;
114 size_t payload_max = MTU - 12 - 2;
119 size_t frag_len = std::min(payload_max, len - pos);
120 bool end = (pos + frag_len) >= len;
123 fua[0] = (nal_header & 0xE0) | 28;
124 fua[1] = (start ? 0x80 : 0x00) | (end ? 0x40 : 0x00) | nal_type;
127 memcpy(buffer, fua, 2);
128 memcpy(buffer + 2, data + pos, frag_len);
130 bool marker = last_nal_of_frame && end;
131 sendPacket(buffer, frag_len + 2, marker);
138 void buildHeader(uint8_t* hdr,
bool marker) {
139 hdr[0] = (RTP_VERSION << 6);
140 hdr[1] = (marker ? 0x80 : 0x00) | (RTP_PAYLOAD_TYPE & 0x7F);
142 hdr[2] = sequence_number_ >> 8;
143 hdr[3] = sequence_number_ & 0xFF;
145 hdr[4] = (timestamp_ >> 24) & 0xFF;
146 hdr[5] = (timestamp_ >> 16) & 0xFF;
147 hdr[6] = (timestamp_ >> 8) & 0xFF;
148 hdr[7] = (timestamp_) & 0xFF;
150 hdr[8] = (ssrc_ >> 24) & 0xFF;
151 hdr[9] = (ssrc_ >> 16) & 0xFF;
152 hdr[10] = (ssrc_ >> 8) & 0xFF;
153 hdr[11] = (ssrc_) & 0xFF;
160 void extractNALs(
const uint8_t* data, size_t len,
161 std::vector<std::pair<
const uint8_t*, size_t>>& out) {
164 while (i + 4 < len) {
167 while (start + 3 < len &&
168 !(data[start] == 0 && data[start + 1] == 0 &&
169 (data[start + 2] == 1 ||
170 (data[start + 2] == 0 && data[start + 3] == 1)))) {
174 if (start + 3 >= len)
break;
176 size_t sc_size = (data[start + 2] == 1) ? 3 : 4;
177 size_t nal_start = start + sc_size;
179 size_t next = nal_start;
180 while (next + 3 < len &&
181 !(data[next] == 0 && data[next + 1] == 0 &&
182 (data[next + 2] == 1 ||
183 (data[next + 2] == 0 && data[next + 3] == 1)))) {
187 size_t nal_len = next - nal_start;
189 out.emplace_back(data + nal_start, nal_len);
RDPPacketizer class to packetize H.264 NAL units into RTP packets. This class takes raw H....
Definition: RDPPacketizer.h:14
virtual size_t write(uint8_t)
Definition: RDPPacketizer.h:68
static constexpr uint8_t RTP_PAYLOAD_TYPE
Definition: RDPPacketizer.h:18
static constexpr size_t MTU
Definition: RDPPacketizer.h:16
static constexpr uint8_t RTP_VERSION
Definition: RDPPacketizer.h:17
RDPPacketizer(Print &out, uint32_t ssrc=0x12345678)
Definition: RDPPacketizer.h:20
size_t write(const uint8_t *data, size_t len)
Definition: RDPPacketizer.h:27
Definition: H264Decoder.h:31