| Index: webrtc/modules/rtp_rtcp/source/sample_rtcp_parser4.h
|
| diff --git a/webrtc/modules/rtp_rtcp/source/sample_rtcp_parser4.h b/webrtc/modules/rtp_rtcp/source/sample_rtcp_parser4.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..46fa65250f5b46c42f8365d22b53be227b2a243b
|
| --- /dev/null
|
| +++ b/webrtc/modules/rtp_rtcp/source/sample_rtcp_parser4.h
|
| @@ -0,0 +1,108 @@
|
| +/*
|
| + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + *
|
| + */
|
| +
|
| +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_SAMPLE_RTCP_PARSER4_H_
|
| +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_SAMPLE_RTCP_PARSER4_H_
|
| +
|
| +#include <functional>
|
| +#include <map>
|
| +
|
| +#include "webrtc/base/array_view.h"
|
| +#include "webrtc/base/checks.h"
|
| +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
|
| +
|
| +namespace webrtc {
|
| +namespace rtcp {
|
| +// Parser that use functor as a callback. Has no knowledge about individual
|
| +// packets, including how many are there.
|
| +// std::function is not allowed though... too bad.
|
| +
|
| +class Parser4 {
|
| + public:
|
| + void Parse(rtc::ArrayView<const uint8_t> packet) { ParseInternal(packet); }
|
| +
|
| + template <typename Packet>
|
| + Parser4& Handle(std::function<void(const Packet&)> handler) {
|
| + RegisterHandler<Packet>(std::move(handler));
|
| + return *this;
|
| + }
|
| +
|
| + private:
|
| + using Handlers = std::map<uint8_t, std::function<void(const CommonHeader&)>>;
|
| + template <typename Packet>
|
| + struct IsFeedback {
|
| + private:
|
| + template <typename C>
|
| + static std::true_type test(decltype(C::kFeedbackMessageType));
|
| + template <typename C>
|
| + static std::false_type test(...);
|
| +
|
| + public:
|
| + static constexpr bool value = decltype(test<Packet>(42))::value;
|
| + };
|
| +
|
| + template <typename Packet>
|
| + static void AddHandler(Handlers* handlers,
|
| + uint8_t key,
|
| + std::function<void(const Packet&)> handler) {
|
| + RTC_DCHECK(handlers->find(key) == handlers->end())
|
| + << "There is already " << static_cast<int>(key) << " in that map.";
|
| + (*handlers)[key] = [handler](const CommonHeader& h) {
|
| + Packet packet;
|
| + if (packet.Parse(h))
|
| + handler(packet);
|
| + };
|
| + }
|
| +
|
| + template <
|
| + typename Packet,
|
| + typename std::enable_if<!IsFeedback<Packet>::value>::type* = nullptr>
|
| + void RegisterHandler(std::function<void(const Packet&)> handler) {
|
| + AddHandler(&handlers_, Packet::kPacketType, std::move(handler));
|
| + }
|
| +
|
| + template <typename Packet,
|
| + typename std::enable_if<IsFeedback<Packet>::value>::type* = nullptr>
|
| + void RegisterHandler(std::function<void(const Packet&)> handler) {
|
| + RTC_DCHECK_EQ(fb_handlers_.find(Packet::kPacketType) == fb_handlers_.end(),
|
| + handlers_.find(Packet::kPacketType) == handlers_.end());
|
| + Handlers* fb_handlers = &fb_handlers_[Packet::kPacketType];
|
| + AddHandler(fb_handlers, Packet::kFeedbackMessageType, std::move(handler));
|
| + if (handlers_.find(Packet::kPacketType) == handlers_.end()) {
|
| + handlers_[Packet::kPacketType] =
|
| + [fb_handlers](const CommonHeader& header) {
|
| + auto it = fb_handlers->find(header.fmt());
|
| + if (it != fb_handlers->end())
|
| + it->second(header);
|
| + };
|
| + }
|
| + }
|
| +
|
| + Handlers handlers_;
|
| + std::map<uint8_t, Handlers> fb_handlers_;
|
| +
|
| + private: // Move to .cc
|
| + void ParseInternal(rtc::ArrayView<const uint8_t> packet) {
|
| + CommonHeader header;
|
| + for (const uint8_t *next_packet = packet.begin();
|
| + RTC_DCHECK(next_packet <= packet.end()), next_packet != packet.end();
|
| + next_packet = header.NextPacket()) {
|
| + if (!header.Parse(next_packet, packet.end() - next_packet))
|
| + break;
|
| + auto it = handlers_.find(header.type());
|
| + if (it != handlers_.end())
|
| + it->second(header);
|
| + }
|
| + }
|
| +};
|
| +} // namespace rtcp
|
| +} // namespace webrtc
|
| +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_SAMPLE_RTCP_PARSER4_H_
|
|
|