Skip to content

Commit

Permalink
Refactoring to add sendFrame()
Browse files Browse the repository at this point in the history
  • Loading branch information
paullouisageneau committed Oct 1, 2024
1 parent 4bf08fd commit f7a6a3f
Show file tree
Hide file tree
Showing 31 changed files with 555 additions and 427 deletions.
2 changes: 1 addition & 1 deletion examples/streamer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ shared_ptr<ClientTrackData> addVideo(const shared_ptr<PeerConnection> pc, const
video.addSSRC(ssrc, cname, msid, cname);
auto track = pc->addTrack(video);
// create RTP configuration
auto rtpConfig = make_shared<RtpPacketizationConfig>(ssrc, cname, payloadType, H264RtpPacketizer::defaultClockRate);
auto rtpConfig = make_shared<RtpPacketizationConfig>(ssrc, cname, payloadType, H264RtpPacketizer::ClockRate);
// create packetizer
auto packetizer = make_shared<H264RtpPacketizer>(NalUnit::Separator::Length, rtpConfig);
// add RTCP SR handler
Expand Down
20 changes: 11 additions & 9 deletions include/rtc/av1rtppacketizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ namespace rtc {
// RTP packetization of AV1 payload
class RTC_CPP_EXPORT AV1RtpPacketizer final : public RtpPacketizer {
public:
// Default clock rate for AV1 in RTP
inline static const uint32_t defaultClockRate = 90 * 1000;
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;

// Define how OBUs are seperated in a AV1 Sample
enum class Packetization {
Expand All @@ -33,17 +33,19 @@ class RTC_CPP_EXPORT AV1RtpPacketizer final : public RtpPacketizer {
// @note RTP configuration is used in packetization process which may change some configuration
// properties such as sequence number.
AV1RtpPacketizer(Packetization packetization, shared_ptr<RtpPacketizationConfig> rtpConfig,
uint16_t maxFragmentSize = NalUnits::defaultMaximumFragmentSize);

void outgoing(message_vector &messages, const message_callback &send) override;
size_t maxFragmentSize = DefaultMaxFragmentSize);

private:
shared_ptr<NalUnits> splitMessage(binary_ptr message);
std::vector<shared_ptr<binary>> packetizeObu(binary_ptr message, uint16_t maxFragmentSize);
static std::vector<binary> extractTemporalUnitObus(const binary &data);

std::vector<binary> fragment(binary data) override;
std::vector<binary> fragmentObu(const binary &data);

const uint16_t maxFragmentSize;
// TODO: prefixes
const Packetization packetization;
std::shared_ptr<binary> sequenceHeader;
const size_t maxFragmentSize;

std::unique_ptr<binary> sequenceHeader;
};

// For backward compatibility, do not use
Expand Down
1 change: 0 additions & 1 deletion include/rtc/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ using std::variant;
using std::weak_ptr;

using binary = std::vector<byte>;
using binary_ptr = shared_ptr<binary>;
using message_variant = variant<binary, string>;

using std::int16_t;
Expand Down
14 changes: 11 additions & 3 deletions include/rtc/frameinfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@

#include "common.hpp"

#include <chrono>

namespace rtc {

struct RTC_CPP_EXPORT FrameInfo {
FrameInfo(uint8_t payloadType, uint32_t timestamp) : payloadType(payloadType), timestamp(timestamp){};
uint8_t payloadType; // Indicates codec of the frame
uint32_t timestamp = 0; // RTP Timestamp
FrameInfo(uint32_t timestamp) : timestamp(timestamp) {};
template<typename Period = std::ratio<1>> FrameInfo(std::chrono::duration<double, Period> timestamp) : timestampSeconds(timestamp) {};

[[deprecated]] FrameInfo(uint8_t payloadType, uint32_t timestamp) : timestamp(timestamp), payloadType(payloadType) {};

uint32_t timestamp = 0;
uint8_t payloadType = 0;

optional<std::chrono::duration<double>> timestampSeconds;
};

} // namespace rtc
Expand Down
2 changes: 2 additions & 0 deletions include/rtc/h264rtpdepacketizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class RTC_CPP_EXPORT H264RtpDepacketizer : public MediaHandler {
public:
using Separator = NalUnit::Separator;

inline static const uint32_t ClockRate = 90 * 1000;

H264RtpDepacketizer(Separator separator = Separator::LongStartSequence);
virtual ~H264RtpDepacketizer() = default;

Expand Down
15 changes: 7 additions & 8 deletions include/rtc/h264rtppacketizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class RTC_CPP_EXPORT H264RtpPacketizer final : public RtpPacketizer {
public:
using Separator = NalUnit::Separator;

/// Default clock rate for H264 in RTP
inline static const uint32_t defaultClockRate = 90 * 1000;
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;

/// Constructs h264 payload packetizer with given RTP configuration.
/// @note RTP configuration is used in packetization process which may change some configuration
Expand All @@ -32,20 +32,19 @@ class RTC_CPP_EXPORT H264RtpPacketizer final : public RtpPacketizer {
/// @param rtpConfig RTP configuration
/// @param maxFragmentSize maximum size of one NALU fragment
H264RtpPacketizer(Separator separator, shared_ptr<RtpPacketizationConfig> rtpConfig,
uint16_t maxFragmentSize = NalUnits::defaultMaximumFragmentSize);
size_t maxFragmentSize = DefaultMaxFragmentSize);

// For backward compatibility, do not use
[[deprecated]] H264RtpPacketizer(
shared_ptr<RtpPacketizationConfig> rtpConfig,
uint16_t maxFragmentSize = NalUnits::defaultMaximumFragmentSize);

void outgoing(message_vector &messages, const message_callback &send) override;
size_t maxFragmentSize = DefaultMaxFragmentSize);

private:
shared_ptr<NalUnits> splitMessage(binary_ptr message);
std::vector<binary> fragment(binary data) override;
std::vector<NalUnit> splitFrame(const binary &frame);

const uint16_t maxFragmentSize;
const Separator separator;
const size_t maxFragmentSize;
};

// For backward compatibility, do not use
Expand Down
17 changes: 13 additions & 4 deletions include/rtc/h265nalunit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "nalunit.hpp"

#include <cassert>
#include <vector>

namespace rtc {

Expand Down Expand Up @@ -72,8 +73,13 @@ struct RTC_CPP_EXPORT H265NalUnitFragmentHeader {

#pragma pack(pop)

/// Nal unit
struct H265NalUnitFragment;

/// NAL unit
struct RTC_CPP_EXPORT H265NalUnit : NalUnit {
static std::vector<binary> GenerateFragments(const std::vector<H265NalUnit> &nalus,
size_t maxFragmentSize);

H265NalUnit(const H265NalUnit &unit) = default;
H265NalUnit(size_t size, bool includingHeader = true)
: NalUnit(size, includingHeader, NalUnit::Type::H265) {}
Expand All @@ -83,6 +89,7 @@ struct RTC_CPP_EXPORT H265NalUnit : NalUnit {
template <typename Iterator>
H265NalUnit(Iterator begin_, Iterator end_) : NalUnit(begin_, end_) {}

// TODO: duplicate
bool forbiddenBit() const { return header()->forbiddenBit(); }
uint8_t unitType() const { return header()->unitType(); }
uint8_t nuhLayerId() const { return header()->nuhLayerId(); }
Expand All @@ -104,6 +111,8 @@ struct RTC_CPP_EXPORT H265NalUnit : NalUnit {
insert(end(), payload.begin(), payload.end());
}

std::vector<H265NalUnitFragment> generateFragments(size_t maxFragmentSize) const;

protected:
const H265NalUnitHeader *header() const {
assert(size() >= H265_NAL_HEADER_SIZE);
Expand All @@ -116,9 +125,9 @@ struct RTC_CPP_EXPORT H265NalUnit : NalUnit {
}
};

/// Nal unit fragment A
/// NAL unit fragment
struct RTC_CPP_EXPORT H265NalUnitFragment : H265NalUnit {
static std::vector<shared_ptr<H265NalUnitFragment>> fragmentsFrom(shared_ptr<H265NalUnit> nalu,
[[deprecated]] static std::vector<shared_ptr<H265NalUnitFragment>> fragmentsFrom(shared_ptr<H265NalUnit> nalu,
uint16_t maxFragmentSize);

enum class FragmentType { Start, Middle, End };
Expand Down Expand Up @@ -171,7 +180,7 @@ struct RTC_CPP_EXPORT H265NalUnitFragment : H265NalUnit {
}
};

class RTC_CPP_EXPORT H265NalUnits : public std::vector<shared_ptr<H265NalUnit>> {
class [[deprecated]] RTC_CPP_EXPORT H265NalUnits : public std::vector<shared_ptr<H265NalUnit>> {
public:
static const uint16_t defaultMaximumFragmentSize =
uint16_t(RTC_DEFAULT_MTU - 12 - 8 - 40); // SRTP/UDP/IPv6
Expand Down
17 changes: 8 additions & 9 deletions include/rtc/h265rtppacketizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class RTC_CPP_EXPORT H265RtpPacketizer final : public RtpPacketizer {
public:
using Separator = NalUnit::Separator;

// Default clock rate for H265 in RTP
inline static const uint32_t defaultClockRate = 90 * 1000;
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;

// Constructs h265 payload packetizer with given RTP configuration.
// @note RTP configuration is used in packetization process which may change some configuration
Expand All @@ -31,19 +31,18 @@ class RTC_CPP_EXPORT H265RtpPacketizer final : public RtpPacketizer {
// @param rtpConfig RTP configuration
// @param maxFragmentSize maximum size of one NALU fragment
H265RtpPacketizer(Separator separator, shared_ptr<RtpPacketizationConfig> rtpConfig,
uint16_t maxFragmentSize = H265NalUnits::defaultMaximumFragmentSize);
size_t maxFragmentSize = DefaultMaxFragmentSize);

// for backward compatibility
// For backward compatibility, do not use
[[deprecated]] H265RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig,
uint16_t maxFragmentSize = H265NalUnits::defaultMaximumFragmentSize);

void outgoing(message_vector &messages, const message_callback &send) override;
size_t maxFragmentSize = DefaultMaxFragmentSize);

private:
shared_ptr<H265NalUnits> splitMessage(binary_ptr message);
std::vector<binary> fragment(binary data) override;
std::vector<H265NalUnit> splitFrame(const binary &frame);

const uint16_t maxFragmentSize;
const NalUnit::Separator separator;
const size_t maxFragmentSize;
};

// For backward compatibility, do not use
Expand Down
24 changes: 20 additions & 4 deletions include/rtc/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,26 @@ inline size_t message_size_func(const message_ptr &m) {

template <typename Iterator>
message_ptr make_message(Iterator begin, Iterator end, Message::Type type = Message::Binary,
unsigned int stream = 0, shared_ptr<Reliability> reliability = nullptr,
shared_ptr<FrameInfo> frameInfo = nullptr) {
unsigned int stream = 0, shared_ptr<Reliability> reliability = nullptr) {
auto message = std::make_shared<Message>(begin, end, type);
message->stream = stream;
message->reliability = reliability;
return message;
}

template <typename Iterator>
message_ptr make_message(Iterator begin, Iterator end, shared_ptr<FrameInfo> frameInfo) {
auto message = std::make_shared<Message>(begin, end);
message->frameInfo = frameInfo;
return message;
}

// For backward compatibiity, do not use
template <typename Iterator>
[[deprecated]] message_ptr make_message(Iterator begin, Iterator end, Message::Type type,
unsigned int stream, shared_ptr<FrameInfo> frameInfo) {
auto message = std::make_shared<Message>(begin, end, type);
message->stream = stream;
message->frameInfo = frameInfo;
return message;
}
Expand All @@ -61,8 +76,9 @@ RTC_CPP_EXPORT message_ptr make_message(size_t size, Message::Type type = Messag

RTC_CPP_EXPORT message_ptr make_message(binary &&data, Message::Type type = Message::Binary,
unsigned int stream = 0,
shared_ptr<Reliability> reliability = nullptr,
shared_ptr<FrameInfo> frameInfo = nullptr);
shared_ptr<Reliability> reliability = nullptr);

RTC_CPP_EXPORT message_ptr make_message(binary &&data, shared_ptr<FrameInfo> frameInfo);

RTC_CPP_EXPORT message_ptr make_message(size_t size, message_ptr orig);

Expand Down
84 changes: 27 additions & 57 deletions include/rtc/nalunit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "common.hpp"

#include <vector>
#include <cassert>

namespace rtc {
Expand Down Expand Up @@ -61,15 +62,31 @@ enum NalUnitStartSequenceMatch {

static const size_t H264_NAL_HEADER_SIZE = 1;
static const size_t H265_NAL_HEADER_SIZE = 2;
/// Nal unit

struct NalUnitFragmentA;

/// NAL unit
struct RTC_CPP_EXPORT NalUnit : binary {
static std::vector<binary> GenerateFragments(const std::vector<NalUnit> &nalus,
size_t maxFragmentSize);

enum class Separator {
Length = RTC_NAL_SEPARATOR_LENGTH, // first 4 bytes are NAL unit length
LongStartSequence = RTC_NAL_SEPARATOR_LONG_START_SEQUENCE, // 0x00, 0x00, 0x00, 0x01
ShortStartSequence = RTC_NAL_SEPARATOR_SHORT_START_SEQUENCE, // 0x00, 0x00, 0x01
StartSequence = RTC_NAL_SEPARATOR_START_SEQUENCE, // LongStartSequence or ShortStartSequence
};

static NalUnitStartSequenceMatch StartSequenceMatchSucc(NalUnitStartSequenceMatch match,
std::byte _byte, Separator separator);

enum class Type { H264, H265 };

NalUnit(const NalUnit &unit) = default;
NalUnit(size_t size, bool includingHeader = true, Type type = Type::H264)
: binary(size + (includingHeader
? 0
: (type == Type::H264 ? H264_NAL_HEADER_SIZE : H265_NAL_HEADER_SIZE))) {}
: binary(size + (includingHeader ? 0
: (type == Type::H264 ? H264_NAL_HEADER_SIZE
: H265_NAL_HEADER_SIZE))) {}
NalUnit(binary &&data) : binary(std::move(data)) {}
NalUnit(Type type = Type::H264)
: binary(type == Type::H264 ? H264_NAL_HEADER_SIZE : H265_NAL_HEADER_SIZE) {}
Expand All @@ -94,56 +111,7 @@ struct RTC_CPP_EXPORT NalUnit : binary {
insert(end(), payload.begin(), payload.end());
}

/// NAL unit separator
enum class Separator {
Length = RTC_NAL_SEPARATOR_LENGTH, // first 4 bytes are NAL unit length
LongStartSequence = RTC_NAL_SEPARATOR_LONG_START_SEQUENCE, // 0x00, 0x00, 0x00, 0x01
ShortStartSequence = RTC_NAL_SEPARATOR_SHORT_START_SEQUENCE, // 0x00, 0x00, 0x01
StartSequence = RTC_NAL_SEPARATOR_START_SEQUENCE, // LongStartSequence or ShortStartSequence
};

static NalUnitStartSequenceMatch StartSequenceMatchSucc(NalUnitStartSequenceMatch match,
std::byte _byte, Separator separator) {
assert(separator != Separator::Length);
auto byte = (uint8_t)_byte;
auto detectShort =
separator == Separator::ShortStartSequence || separator == Separator::StartSequence;
auto detectLong =
separator == Separator::LongStartSequence || separator == Separator::StartSequence;
switch (match) {
case NUSM_noMatch:
if (byte == 0x00) {
return NUSM_firstZero;
}
break;
case NUSM_firstZero:
if (byte == 0x00) {
return NUSM_secondZero;
}
break;
case NUSM_secondZero:
if (byte == 0x00 && detectLong) {
return NUSM_thirdZero;
} else if (byte == 0x00 && detectShort) {
return NUSM_secondZero;
} else if (byte == 0x01 && detectShort) {
return NUSM_shortMatch;
}
break;
case NUSM_thirdZero:
if (byte == 0x00 && detectLong) {
return NUSM_thirdZero;
} else if (byte == 0x01 && detectLong) {
return NUSM_longMatch;
}
break;
case NUSM_shortMatch:
return NUSM_shortMatch;
case NUSM_longMatch:
return NUSM_longMatch;
}
return NUSM_noMatch;
}
std::vector<NalUnitFragmentA> generateFragments(size_t maxFragmentSize) const;

protected:
const NalUnitHeader *header() const {
Expand All @@ -159,8 +127,9 @@ struct RTC_CPP_EXPORT NalUnit : binary {

/// Nal unit fragment A
struct RTC_CPP_EXPORT NalUnitFragmentA : NalUnit {
static std::vector<shared_ptr<NalUnitFragmentA>> fragmentsFrom(shared_ptr<NalUnit> nalu,
uint16_t maxFragmentSize);
// For backward compatibility, do not use
[[deprecated]] static std::vector<shared_ptr<NalUnitFragmentA>>
fragmentsFrom(shared_ptr<NalUnit> nalu, uint16_t maxFragmentSize);

enum class FragmentType { Start, Middle, End };

Expand Down Expand Up @@ -212,7 +181,8 @@ struct RTC_CPP_EXPORT NalUnitFragmentA : NalUnit {
}
};

class RTC_CPP_EXPORT NalUnits : public std::vector<shared_ptr<NalUnit>> {
// For backward compatibility, do not use
class [[deprecated]] RTC_CPP_EXPORT NalUnits : public std::vector<shared_ptr<NalUnit>> {
public:
static const uint16_t defaultMaximumFragmentSize =
uint16_t(RTC_DEFAULT_MTU - 12 - 8 - 40); // SRTP/UDP/IPv6
Expand Down
Loading

0 comments on commit f7a6a3f

Please sign in to comment.