Skip to content

Commit 178e759

Browse files
committed
H264RtpDepacketizer: De-packetize access units rather than individual NALUs
This commit updates the `H264RtpDepacketizer` to accumulate the NALUs for a particular RTP timestamp into a single output message, rather than returning each NALU as an individual message. This helps decoders which may want to see the non-VCL SPS/PPS/etc. NALUs in the same access unit as a VCL NALU rather than as standalone messages. Each NALU in the access unit buffer is prepended with an H.264 Annex B start code 0x00, 0x00, 0x01.
1 parent 8296892 commit 178e759

File tree

1 file changed

+38
-45
lines changed

1 file changed

+38
-45
lines changed

src/h264rtpdepacketizer.cpp

+38-45
Original file line numberDiff line numberDiff line change
@@ -10,85 +10,78 @@
1010

1111
#include "h264rtpdepacketizer.hpp"
1212
#include "nalunit.hpp"
13-
#include "track.hpp"
1413

15-
#include "impl/logcounter.hpp"
16-
17-
#include <cmath>
18-
#include <utility>
19-
20-
#ifdef _WIN32
21-
#include <winsock2.h>
22-
#else
23-
#include <arpa/inet.h>
24-
#endif
14+
#include "impl/internals.hpp"
2515

2616
namespace rtc {
2717

28-
const unsigned long stapaHeaderSize = 1;
29-
const auto fuaHeaderSize = 2;
18+
const binary naluStartCode = {byte{0}, byte{0}, byte{1}};
3019

3120
const uint8_t naluTypeSTAPA = 24;
3221
const uint8_t naluTypeFUA = 28;
3322

3423
message_vector H264RtpDepacketizer::buildFrames(message_vector::iterator begin,
3524
message_vector::iterator end, uint32_t timestamp) {
3625
message_vector out = {};
37-
auto fua_buffer = std::vector<std::byte>{};
26+
auto accessUnit = binary{};
3827
auto frameInfo = std::make_shared<FrameInfo>(timestamp);
28+
auto nFrags = 0;
3929

40-
for (auto it = begin; it != end; it++) {
30+
for (auto it = begin; it != end; ++it) {
4131
auto pkt = it->get();
4232
auto pktParsed = reinterpret_cast<const rtc::RtpHeader *>(pkt->data());
43-
auto headerSize =
44-
sizeof(rtc::RtpHeader) + pktParsed->csrcCount() + pktParsed->getExtensionHeaderSize();
45-
auto nalUnitHeader = NalUnitHeader{std::to_integer<uint8_t>(pkt->at(headerSize))};
46-
47-
if (fua_buffer.size() != 0 || nalUnitHeader.unitType() == naluTypeFUA) {
48-
if (fua_buffer.size() == 0) {
49-
fua_buffer.push_back(std::byte(0));
50-
}
51-
52-
auto nalUnitFragmentHeader =
53-
NalUnitFragmentHeader{std::to_integer<uint8_t>(pkt->at(headerSize + 1))};
33+
auto rtpHeaderSize = pktParsed->getSize() + pktParsed->getExtensionHeaderSize();
34+
auto nalUnitHeader = NalUnitHeader{std::to_integer<uint8_t>(pkt->at(rtpHeaderSize))};
5435

55-
std::copy(pkt->begin() + headerSize + fuaHeaderSize, pkt->end(),
56-
std::back_inserter(fua_buffer));
36+
if (nalUnitHeader.unitType() == naluTypeFUA) {
37+
auto nalUnitFragmentHeader = NalUnitFragmentHeader{
38+
std::to_integer<uint8_t>(pkt->at(rtpHeaderSize + sizeof(NalUnitHeader)))};
5739

58-
if (nalUnitFragmentHeader.isEnd()) {
59-
fua_buffer.at(0) =
60-
std::byte(nalUnitHeader.idc() | nalUnitFragmentHeader.unitType());
40+
if (nFrags++ == 0) {
41+
std::copy(naluStartCode.begin(), naluStartCode.end(),
42+
std::back_inserter(accessUnit));
6143

62-
out.push_back(
63-
make_message(std::move(fua_buffer), Message::Binary, 0, nullptr, frameInfo));
64-
fua_buffer.clear();
44+
accessUnit.emplace_back(
45+
byte(nalUnitHeader.idc() | nalUnitFragmentHeader.unitType()));
6546
}
47+
48+
std::copy(pkt->begin() + rtpHeaderSize + sizeof(NalUnitHeader) +
49+
sizeof(NalUnitFragmentHeader),
50+
pkt->end(), std::back_inserter(accessUnit));
6651
} else if (nalUnitHeader.unitType() > 0 && nalUnitHeader.unitType() < 24) {
67-
out.push_back(make_message(pkt->begin() + headerSize, pkt->end(), Message::Binary, 0,
68-
nullptr, frameInfo));
52+
std::copy(naluStartCode.begin(), naluStartCode.end(), std::back_inserter(accessUnit));
53+
std::copy(pkt->begin() + rtpHeaderSize, pkt->end(), std::back_inserter(accessUnit));
6954
} else if (nalUnitHeader.unitType() == naluTypeSTAPA) {
70-
auto currOffset = stapaHeaderSize + headerSize;
55+
auto currOffset = rtpHeaderSize + sizeof(NalUnitHeader);
7156

72-
while (currOffset < pkt->size()) {
73-
auto naluSize =
74-
uint16_t(pkt->at(currOffset)) << 8 | uint8_t(pkt->at(currOffset + 1));
57+
while (currOffset + sizeof(uint16_t) < pkt->size()) {
58+
auto naluSize = std::to_integer<uint16_t>(pkt->at(currOffset)) << 8 |
59+
std::to_integer<uint16_t>(pkt->at(currOffset + 1));
7560

76-
currOffset += 2;
61+
currOffset += sizeof(uint16_t);
7762

7863
if (pkt->size() < currOffset + naluSize) {
79-
throw std::runtime_error("STAP-A declared size is larger then buffer");
64+
throw std::runtime_error("H264 STAP-A declared size is larger than buffer");
8065
}
8166

82-
out.push_back(make_message(pkt->begin() + currOffset,
83-
pkt->begin() + currOffset + naluSize, Message::Binary, 0,
84-
nullptr, frameInfo));
67+
std::copy(naluStartCode.begin(), naluStartCode.end(),
68+
std::back_inserter(accessUnit));
69+
70+
std::copy(pkt->begin() + currOffset, pkt->begin() + currOffset + naluSize,
71+
std::back_inserter(accessUnit));
72+
8573
currOffset += naluSize;
8674
}
8775
} else {
8876
throw std::runtime_error("Unknown H264 RTP Packetization");
8977
}
9078
}
9179

80+
if (!accessUnit.empty()) {
81+
out.emplace_back(make_message(accessUnit.begin(), accessUnit.end(), Message::Binary, 0,
82+
nullptr, frameInfo));
83+
}
84+
9285
return out;
9386
}
9487

0 commit comments

Comments
 (0)