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 a media handler to respond to remb bitrate #1185

Merged
merged 4 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ set(LIBDATACHANNEL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/capi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/plihandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pacinghandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rembhandler.cpp
)

set(LIBDATACHANNEL_HEADERS
Expand Down Expand Up @@ -123,6 +124,7 @@ set(LIBDATACHANNEL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/utils.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/plihandler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/pacinghandler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/rembhandler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/version.h
)

Expand Down
35 changes: 35 additions & 0 deletions include/rtc/rembhandler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2024 Vladimir Voronin
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

#ifndef RTC_REMB_RESPONDER_H
#define RTC_REMB_RESPONDER_H

#if RTC_ENABLE_MEDIA

#include "mediahandler.hpp"
#include "utils.hpp"

namespace rtc {

/// Responds to REMB messages sent by the receiver.
class RTC_CPP_EXPORT RembHandler final : public MediaHandler {
rtc::synchronized_callback<unsigned int> mOnRemb;

public:
/// Constructs the RembResponder object to notify whenever a bitrate
/// @param onRemb The callback that gets called whenever a bitrate by the receiver
RembHandler(std::function<void(unsigned int)> onRemb);

void incoming(message_vector &messages, const message_callback &send) override;
};

}

#endif // RTC_ENABLE_MEDIA

#endif // RTC_REMB_RESPONDER_H
4 changes: 4 additions & 0 deletions include/rtc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ typedef void *(RTC_API *rtcInterceptorCallbackFunc)(int pc, const char *message,
typedef void(RTC_API *rtcBufferedAmountLowCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcAvailableCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcPliHandlerCallbackFunc)(int tr, void *ptr);
typedef void(RTC_API *rtcRembHandlerCallbackFunc)(int tr, unsigned int bitrate, void *ptr);

// Log

Expand Down Expand Up @@ -409,6 +410,9 @@ RTC_C_EXPORT int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPackets
// Chain PliHandler on track
RTC_C_EXPORT int rtcChainPliHandler(int tr, rtcPliHandlerCallbackFunc cb);

// Chain RembHandler on track
RTC_C_EXPORT int rtcChainRembHandler(int tr, rtcRembHandlerCallbackFunc cb);

// Transform seconds to timestamp using track's clock rate, result is written to timestamp
RTC_C_EXPORT int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);

Expand Down
1 change: 1 addition & 0 deletions include/rtc/rtc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "h265rtppacketizer.hpp"
#include "mediahandler.hpp"
#include "plihandler.hpp"
#include "rembhandler.hpp"
#include "pacinghandler.hpp"
#include "rtcpnackresponder.hpp"
#include "rtcpreceivingsession.hpp"
Expand Down
2 changes: 2 additions & 0 deletions include/rtc/rtp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ struct RTC_CPP_EXPORT RtcpRemb {
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int in_bitrate);
void setBitrate(unsigned int numSSRC, unsigned int in_bitrate);
void setSsrc(int iterator, SSRC newSssrc);
unsigned int getNumSSRC();
unsigned int getBitrate();
};

struct RTC_CPP_EXPORT RtcpPli {
Expand Down
12 changes: 12 additions & 0 deletions src/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,18 @@ int rtcChainPliHandler(int tr, rtcPliHandlerCallbackFunc cb) {
});
}

int rtcChainRembHandler(int tr, rtcRembHandlerCallbackFunc cb) {
return wrap([&] {
auto track = getTrack(tr);
auto handler = std::make_shared<RembHandler>([tr, cb](unsigned int bitrate) {
if (auto ptr = getUserPointer(tr))
cb(tr, bitrate, *ptr);
});
track->chainMediaHandler(handler);
return RTC_ERR_SUCCESS;
});
}

int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp) {
return wrap([&] {
auto config = getRtpConfig(id);
Expand Down
47 changes: 47 additions & 0 deletions src/rembhandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2024 Vladimir Voronin
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

#include "rembhandler.hpp"
#include "rtp.hpp"

#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif

#if RTC_ENABLE_MEDIA

namespace rtc {

RembHandler::RembHandler(std::function<void(unsigned int)> onRemb) : mOnRemb(onRemb) {}

void RembHandler::incoming(message_vector &messages, [[maybe_unused]] const message_callback &send) {
for (const auto &message : messages) {
size_t offset = 0;
while ((sizeof(RtcpHeader) + offset) <= message->size()) {
auto header = reinterpret_cast<RtcpHeader *>(message->data() + offset);
uint8_t payload_type = header->payloadType();

if (payload_type == 206 && header->reportCount() == 15 && header->lengthInBytes() == sizeof(RtcpRemb)) {
auto remb = reinterpret_cast<RtcpRemb *>(message->data() + offset);

if (remb->_id[0] == 'R' && remb->_id[1] == 'E' && remb->_id[2] == 'M' && remb->_id[3] == 'B') {
mOnRemb(remb->getBitrate());
break;
}
}

offset += header->lengthInBytes();
}
}
}

} // namespace rtc

#endif // RTC_ENABLE_MEDIA
10 changes: 9 additions & 1 deletion src/rtp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ void RtcpRemb::preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int

void RtcpRemb::setBitrate(unsigned int numSSRC, unsigned int in_bitrate) {
unsigned int exp = 0;
while (in_bitrate > pow(2, 18) - 1) {
while (in_bitrate > 0x3FFFF) {
exp++;
in_bitrate /= 2;
}
Expand All @@ -558,6 +558,14 @@ void RtcpRemb::setBitrate(unsigned int numSSRC, unsigned int in_bitrate) {

void RtcpRemb::setSsrc(int iterator, SSRC newSssrc) { _ssrc[iterator] = htonl(newSssrc); }

unsigned int RtcpRemb::getNumSSRC() { return ntohl(_bitrate) >> 24u; }

unsigned int RtcpRemb::getBitrate() {
uint32_t br = ntohl(_bitrate);
uint8_t exp = (br << 8u) >> 26u;
return (br & 0x3FFFF) * (unsigned int)pow(exp, 2);
evaldemar marked this conversation as resolved.
Show resolved Hide resolved
paullouisageneau marked this conversation as resolved.
Show resolved Hide resolved
}

unsigned int RtcpPli::Size() { return sizeof(RtcpFbHeader); }

void RtcpPli::preparePacket(SSRC messageSSRC) {
Expand Down
Loading