Skip to content

Commit eec049f

Browse files
Merge pull request #1185 from evaldemar/master
Add a media handler to respond to remb bitrate
2 parents 541d646 + 8df6f1c commit eec049f

File tree

8 files changed

+112
-1
lines changed

8 files changed

+112
-1
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ set(LIBDATACHANNEL_SOURCES
8787
${CMAKE_CURRENT_SOURCE_DIR}/src/capi.cpp
8888
${CMAKE_CURRENT_SOURCE_DIR}/src/plihandler.cpp
8989
${CMAKE_CURRENT_SOURCE_DIR}/src/pacinghandler.cpp
90+
${CMAKE_CURRENT_SOURCE_DIR}/src/rembhandler.cpp
9091
)
9192

9293
set(LIBDATACHANNEL_HEADERS
@@ -123,6 +124,7 @@ set(LIBDATACHANNEL_HEADERS
123124
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/utils.hpp
124125
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/plihandler.hpp
125126
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/pacinghandler.hpp
127+
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/rembhandler.hpp
126128
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/version.h
127129
)
128130

include/rtc/rembhandler.hpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright (c) 2024 Vladimir Voronin
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
#ifndef RTC_REMB_RESPONDER_H
10+
#define RTC_REMB_RESPONDER_H
11+
12+
#if RTC_ENABLE_MEDIA
13+
14+
#include "mediahandler.hpp"
15+
#include "utils.hpp"
16+
17+
namespace rtc {
18+
19+
/// Responds to REMB messages sent by the receiver.
20+
class RTC_CPP_EXPORT RembHandler final : public MediaHandler {
21+
rtc::synchronized_callback<unsigned int> mOnRemb;
22+
23+
public:
24+
/// Constructs the RembResponder object to notify whenever a bitrate
25+
/// @param onRemb The callback that gets called whenever a bitrate by the receiver
26+
RembHandler(std::function<void(unsigned int)> onRemb);
27+
28+
void incoming(message_vector &messages, const message_callback &send) override;
29+
};
30+
31+
}
32+
33+
#endif // RTC_ENABLE_MEDIA
34+
35+
#endif // RTC_REMB_RESPONDER_H

include/rtc/rtc.h

+4
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ typedef void *(RTC_API *rtcInterceptorCallbackFunc)(int pc, const char *message,
170170
typedef void(RTC_API *rtcBufferedAmountLowCallbackFunc)(int id, void *ptr);
171171
typedef void(RTC_API *rtcAvailableCallbackFunc)(int id, void *ptr);
172172
typedef void(RTC_API *rtcPliHandlerCallbackFunc)(int tr, void *ptr);
173+
typedef void(RTC_API *rtcRembHandlerCallbackFunc)(int tr, unsigned int bitrate, void *ptr);
173174

174175
// Log
175176

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

413+
// Chain RembHandler on track
414+
RTC_C_EXPORT int rtcChainRembHandler(int tr, rtcRembHandlerCallbackFunc cb);
415+
412416
// Transform seconds to timestamp using track's clock rate, result is written to timestamp
413417
RTC_C_EXPORT int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);
414418

include/rtc/rtc.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "h265rtppacketizer.hpp"
3535
#include "mediahandler.hpp"
3636
#include "plihandler.hpp"
37+
#include "rembhandler.hpp"
3738
#include "pacinghandler.hpp"
3839
#include "rtcpnackresponder.hpp"
3940
#include "rtcpreceivingsession.hpp"

include/rtc/rtp.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ struct RTC_CPP_EXPORT RtcpRemb {
274274
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int in_bitrate);
275275
void setBitrate(unsigned int numSSRC, unsigned int in_bitrate);
276276
void setSsrc(int iterator, SSRC newSssrc);
277+
unsigned int getNumSSRC();
278+
unsigned int getBitrate();
277279
};
278280

279281
struct RTC_CPP_EXPORT RtcpPli {

src/capi.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,18 @@ int rtcChainPliHandler(int tr, rtcPliHandlerCallbackFunc cb) {
13311331
});
13321332
}
13331333

1334+
int rtcChainRembHandler(int tr, rtcRembHandlerCallbackFunc cb) {
1335+
return wrap([&] {
1336+
auto track = getTrack(tr);
1337+
auto handler = std::make_shared<RembHandler>([tr, cb](unsigned int bitrate) {
1338+
if (auto ptr = getUserPointer(tr))
1339+
cb(tr, bitrate, *ptr);
1340+
});
1341+
track->chainMediaHandler(handler);
1342+
return RTC_ERR_SUCCESS;
1343+
});
1344+
}
1345+
13341346
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp) {
13351347
return wrap([&] {
13361348
auto config = getRtpConfig(id);

src/rembhandler.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2024 Vladimir Voronin
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
#include "rembhandler.hpp"
10+
#include "rtp.hpp"
11+
12+
#ifdef _WIN32
13+
#include <winsock2.h>
14+
#else
15+
#include <arpa/inet.h>
16+
#endif
17+
18+
#if RTC_ENABLE_MEDIA
19+
20+
namespace rtc {
21+
22+
RembHandler::RembHandler(std::function<void(unsigned int)> onRemb) : mOnRemb(onRemb) {}
23+
24+
void RembHandler::incoming(message_vector &messages, [[maybe_unused]] const message_callback &send) {
25+
for (const auto &message : messages) {
26+
size_t offset = 0;
27+
while ((sizeof(RtcpHeader) + offset) <= message->size()) {
28+
auto header = reinterpret_cast<RtcpHeader *>(message->data() + offset);
29+
uint8_t payload_type = header->payloadType();
30+
31+
if (payload_type == 206 && header->reportCount() == 15 && header->lengthInBytes() == sizeof(RtcpRemb)) {
32+
auto remb = reinterpret_cast<RtcpRemb *>(message->data() + offset);
33+
34+
if (remb->_id[0] == 'R' && remb->_id[1] == 'E' && remb->_id[2] == 'M' && remb->_id[3] == 'B') {
35+
mOnRemb(remb->getBitrate());
36+
break;
37+
}
38+
}
39+
40+
offset += header->lengthInBytes();
41+
}
42+
}
43+
}
44+
45+
} // namespace rtc
46+
47+
#endif // RTC_ENABLE_MEDIA

src/rtp.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ void RtcpRemb::preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int
545545

546546
void RtcpRemb::setBitrate(unsigned int numSSRC, unsigned int in_bitrate) {
547547
unsigned int exp = 0;
548-
while (in_bitrate > pow(2, 18) - 1) {
548+
while (in_bitrate > 0x3FFFF) {
549549
exp++;
550550
in_bitrate /= 2;
551551
}
@@ -558,6 +558,14 @@ void RtcpRemb::setBitrate(unsigned int numSSRC, unsigned int in_bitrate) {
558558

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

561+
unsigned int RtcpRemb::getNumSSRC() { return ntohl(_bitrate) >> 24u; }
562+
563+
unsigned int RtcpRemb::getBitrate() {
564+
uint32_t br = ntohl(_bitrate);
565+
uint8_t exp = (br << 8u) >> 26u;
566+
return (br & 0x3FFFF) * static_cast<unsigned int>(pow(exp, 2));
567+
}
568+
561569
unsigned int RtcpPli::Size() { return sizeof(RtcpFbHeader); }
562570

563571
void RtcpPli::preparePacket(SSRC messageSSRC) {

0 commit comments

Comments
 (0)