diff --git a/include/rtc/h264rtpdepacketizer.hpp b/include/rtc/h264rtpdepacketizer.hpp index bf4505687..d36a043bc 100644 --- a/include/rtc/h264rtpdepacketizer.hpp +++ b/include/rtc/h264rtpdepacketizer.hpp @@ -15,6 +15,7 @@ #include "common.hpp" #include "mediahandler.hpp" #include "message.hpp" +#include "nalunit.hpp" #include "rtp.hpp" #include @@ -24,14 +25,18 @@ namespace rtc { /// RTP depacketization for H264 class RTC_CPP_EXPORT H264RtpDepacketizer : public MediaHandler { public: - H264RtpDepacketizer() = default; + using Separator = NalUnit::Separator; + + H264RtpDepacketizer(Separator separator = Separator::LongStartSequence); virtual ~H264RtpDepacketizer() = default; void incoming(message_vector &messages, const message_callback &send) override; private: std::vector mRtpBuffer; + const NalUnit::Separator separator; + void addSeparator(binary& accessUnit); message_vector buildFrames(message_vector::iterator firstPkt, message_vector::iterator lastPkt, uint32_t timestamp); }; diff --git a/src/h264rtpdepacketizer.cpp b/src/h264rtpdepacketizer.cpp index 79e554478..977a010ea 100644 --- a/src/h264rtpdepacketizer.cpp +++ b/src/h264rtpdepacketizer.cpp @@ -15,11 +15,44 @@ namespace rtc { -const binary naluStartCode = {byte{0}, byte{0}, byte{1}}; +const binary naluLongStartCode = {byte{0}, byte{0}, byte{0}, byte{1}}; +const binary naluShortStartCode = {byte{0}, byte{0}, byte{1}}; const uint8_t naluTypeSTAPA = 24; const uint8_t naluTypeFUA = 28; +H264RtpDepacketizer::H264RtpDepacketizer(Separator separator) : separator(separator) { + switch (separator) { + case Separator::StartSequence: [[fallthrough]]; + case Separator::LongStartSequence: [[fallthrough]]; + case Separator::ShortStartSequence: + break; + case Separator::Length: [[fallthrough]]; + default: + throw std::invalid_argument("Invalid separator"); + } +} + +void H264RtpDepacketizer::addSeparator(binary& accessUnit) +{ + switch (separator) { + case Separator::StartSequence: [[fallthrough]]; + case Separator::LongStartSequence: + accessUnit.insert(accessUnit.end(), + naluLongStartCode.begin(), + naluLongStartCode.end()); + break; + case Separator::ShortStartSequence: + accessUnit.insert(accessUnit.end(), + naluShortStartCode.begin(), + naluShortStartCode.end()); + break; + case Separator::Length: [[fallthrough]]; + default: + throw std::invalid_argument("Invalid separator"); + } +} + message_vector H264RtpDepacketizer::buildFrames(message_vector::iterator begin, message_vector::iterator end, uint32_t timestamp) { message_vector out = {}; @@ -49,8 +82,7 @@ message_vector H264RtpDepacketizer::buildFrames(message_vector::iterator begin, std::to_integer(pkt->at(rtpHeaderSize + sizeof(NalUnitHeader)))}; if (nFrags++ == 0) { - accessUnit.insert(accessUnit.end(), naluStartCode.begin(), naluStartCode.end()); - + addSeparator(accessUnit); accessUnit.emplace_back( byte(nalUnitHeader.idc() | nalUnitFragmentHeader.unitType())); } @@ -60,7 +92,7 @@ message_vector H264RtpDepacketizer::buildFrames(message_vector::iterator begin, sizeof(NalUnitFragmentHeader), pkt->end()); } else if (nalUnitHeader.unitType() > 0 && nalUnitHeader.unitType() < 24) { - accessUnit.insert(accessUnit.end(), naluStartCode.begin(), naluStartCode.end()); + addSeparator(accessUnit); accessUnit.insert(accessUnit.end(), pkt->begin() + rtpHeaderSize, pkt->end()); } else if (nalUnitHeader.unitType() == naluTypeSTAPA) { auto currOffset = rtpHeaderSize + sizeof(NalUnitHeader); @@ -75,7 +107,7 @@ message_vector H264RtpDepacketizer::buildFrames(message_vector::iterator begin, throw std::runtime_error("H264 STAP-A declared size is larger than buffer"); } - accessUnit.insert(accessUnit.end(), naluStartCode.begin(), naluStartCode.end()); + addSeparator(accessUnit); accessUnit.insert(accessUnit.end(), pkt->begin() + currOffset, pkt->begin() + currOffset + naluSize);