Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sendFrame() and refactor packetization #1265

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 4 additions & 17 deletions examples/streamer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "helpers.hpp"
#include "ArgParser.hpp"

#include <chrono>

using namespace rtc;
using namespace std;
using namespace std::chrono_literals;
Expand Down Expand Up @@ -208,7 +210,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 Expand Up @@ -351,26 +353,11 @@ shared_ptr<Stream> createStream(const string h264Samples, const unsigned fps, co
for (auto clientTrack: tracks) {
auto client = clientTrack.id;
auto trackData = clientTrack.trackData;
auto rtpConfig = trackData->sender->rtpConfig;

// sample time is in us, we need to convert it to seconds
auto elapsedSeconds = double(sampleTime) / (1000 * 1000);
// get elapsed time in clock rate
uint32_t elapsedTimestamp = rtpConfig->secondsToTimestamp(elapsedSeconds);
// set new timestamp
rtpConfig->timestamp = rtpConfig->startTimestamp + elapsedTimestamp;

// get elapsed time in clock rate from last RTCP sender report
auto reportElapsedTimestamp = rtpConfig->timestamp - trackData->sender->lastReportedTimestamp();
// check if last report was at least 1 second ago
if (rtpConfig->timestampToSeconds(reportElapsedTimestamp) > 1) {
trackData->sender->setNeedsToReport();
}

cout << "Sending " << streamType << " sample with size: " << to_string(sample.size()) << " to " << client << endl;
try {
// send sample
trackData->track->send(sample);
trackData->track->sendFrame(sample, std::chrono::duration<double, std::micro>(sampleTime));
} catch (const std::exception &e) {
cerr << "Unable to send "<< streamType << " packet: " << e.what() << endl;
}
Expand Down
21 changes: 11 additions & 10 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,18 @@ 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 Packetization mPacketization;
const size_t mMaxFragmentSize;

const uint16_t maxFragmentSize;
const Packetization packetization;
std::shared_ptr<binary> sequenceHeader;
std::unique_ptr<binary> mSequenceHeader;
};

// 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
17 changes: 8 additions & 9 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 Separator mSeparator;
const size_t mMaxFragmentSize;
};

// For backward compatibility, do not use
Expand Down
16 changes: 12 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 Down Expand Up @@ -104,6 +110,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 +124,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 +179,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
19 changes: 9 additions & 10 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 NalUnit::Separator mSeparator;
const size_t mMaxFragmentSize;
};

// 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
Loading
Loading