Skip to content

Commit

Permalink
Add a media handler to respond to intra frame requests
Browse files Browse the repository at this point in the history
This introduces a PLIResponder class, which can be used for responding
back with an intra frame after the receiver requests one with an FIR
(Full Intra Request) or a PLI (Picture Loss Indicator) message.

This is useful when a video is being streamed live and we can control
the behavior of the video encoder. PLIResponder simply notifies its
caller when a new intra frame is requested, which passes this request
onto its video frame source.
  • Loading branch information
kuzux committed Oct 4, 2023
1 parent 3adaadb commit 10711cb
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ set(LIBDATACHANNEL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/rtcpnackresponder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rtp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/capi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pliresponder.cpp
)

set(LIBDATACHANNEL_HEADERS
Expand Down Expand Up @@ -132,6 +133,7 @@ set(LIBDATACHANNEL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/mediahandlerrootelement.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/rtcpnackresponder.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/utils.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/pliresponder.hpp
)

set(LIBDATACHANNEL_IMPL_SOURCES
Expand Down
31 changes: 31 additions & 0 deletions include/rtc/pliresponder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2023 Arda Cinar
*
* 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_PLI_RESPONDER_H
#define RTC_PLI_RESPONDER_H

#include "mediahandlerelement.hpp"
#include <functional>

namespace rtc {

/// Responds to PLI and FIR messages sent by the receiver. The sender should respond to these
/// messages by sending an intra.
class RTC_CPP_EXPORT PliResponder final : public MediaHandlerElement {
std::function<void(void)> onPli;

public:
/// Constructs the PLIResponder object to notify whenever a new intra frame is requested
/// @param onPli The callback that gets called whenever an intra frame is requested by the receiver
PliResponder(std::function<void(void)> onPli);
ChainedIncomingControlProduct processIncomingControlMessage(message_ptr) override;
};

}

#endif // RTC_PLI_RESPONDER_H
40 changes: 40 additions & 0 deletions src/pliresponder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2023 Arda Cinar
*
* 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 "pliresponder.hpp"

namespace rtc {

ChainedIncomingControlProduct PliResponder::processIncomingControlMessage(message_ptr message) {
size_t offset = 0;

while ((sizeof(RtcpHeader) + offset) <= message->size()) {
auto header = reinterpret_cast<rtc::RtcpHeader*>(message->data() + offset);
uint8_t payload_type = header->payloadType();

if (payload_type == 196) {
// FIR message, call pli handler anyway
onPli();
break;
} else if (payload_type == 206) {
// On a payload specific fb message, there is a "feedback message type" (FMT) in the
// header instead of a report count. PT = 206, FMT = 1 means a PLI message
uint8_t feedback_message_type = header->reportCount();
if (feedback_message_type == 1) {
onPli();
break;
}
}
offset += header->lengthInBytes();
}
return { message, std::nullopt };
}

PliResponder::PliResponder(std::function<void(void)> onPli) : onPli(onPli) { }

}

0 comments on commit 10711cb

Please sign in to comment.