diff --git a/CMakeLists.txt b/CMakeLists.txt index d4d29eb1f..2f3cd787b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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/plihandler.cpp ) set(LIBDATACHANNEL_HEADERS @@ -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/plihandler.hpp ) set(LIBDATACHANNEL_IMPL_SOURCES diff --git a/include/rtc/plihandler.hpp b/include/rtc/plihandler.hpp new file mode 100644 index 000000000..356b54cd5 --- /dev/null +++ b/include/rtc/plihandler.hpp @@ -0,0 +1,36 @@ +/** + * 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 + +#if RTC_ENABLE_MEDIA + +#include "mediahandlerelement.hpp" +#include "utils.hpp" +#include + +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 PliHandler final : public MediaHandlerElement { + rtc::synchronized_callback<> mOnPli; + +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 + PliHandler(std::function onPli); + ChainedIncomingControlProduct processIncomingControlMessage(message_ptr) override; +}; + +} + +#endif // RTC_ENABLE_MEDIA + +#endif // RTC_PLI_RESPONDER_H diff --git a/include/rtc/rtc.hpp b/include/rtc/rtc.hpp index 5fdb7fcd7..951d63304 100644 --- a/include/rtc/rtc.hpp +++ b/include/rtc/rtc.hpp @@ -33,6 +33,8 @@ #include "rtcpreceivingsession.hpp" #include "rtcpsrreporter.hpp" +#include "plihandler.hpp" + // Opus/AAC/h264/h265/AV1 streaming #include "aacrtppacketizer.hpp" #include "av1packetizationhandler.hpp" diff --git a/src/plihandler.cpp b/src/plihandler.cpp new file mode 100644 index 000000000..cf2b01820 --- /dev/null +++ b/src/plihandler.cpp @@ -0,0 +1,44 @@ +/** + * 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 "plihandler.hpp" + +#if RTC_ENABLE_MEDIA + +namespace rtc { + +ChainedIncomingControlProduct PliHandler::processIncomingControlMessage(message_ptr message) { + size_t offset = 0; + + while ((sizeof(RtcpHeader) + offset) <= message->size()) { + auto header = reinterpret_cast(message->data() + offset); + uint8_t payload_type = header->payloadType(); + + if (payload_type == 196) { + // FIR message, call pli handler anyway + mOnPli(); + 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) { + mOnPli(); + break; + } + } + offset += header->lengthInBytes(); + } + return { message, std::nullopt }; +} + +PliHandler::PliHandler(std::function onPli) : mOnPli(onPli) { } + +} + +#endif // RTC_ENABLE_MEDIA