OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include <map> |
| 12 #include <utility> |
| 13 #include <vector> |
| 14 |
| 15 #include "webrtc/call/rtp_transport_controller_receive.h" |
| 16 |
| 17 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
| 18 |
| 19 namespace webrtc { |
| 20 |
| 21 class RtpTransportControllerReceive |
| 22 : public RtpTransportControllerReceiveInterface { |
| 23 public: |
| 24 // ImplementRtpTransportControllerReceiveInterface |
| 25 bool AddReceiver(uint32_t ssrc, |
| 26 MediaType media_type, |
| 27 const Config& config, |
| 28 RtpPacketReceiverInterface* receiver) override; |
| 29 bool RemoveReceiver(const RtpPacketReceiverInterface* receiver) override; |
| 30 |
| 31 bool AddSink(uint32_t ssrc, |
| 32 MediaType media_type, |
| 33 RtpPacketSinkInterface* sink) override; |
| 34 bool RemoveSink(const RtpPacketSinkInterface* sink) override; |
| 35 |
| 36 #if 0 |
| 37 bool RegisterPayload(uint8_t payload_type, MediaType media_type, |
| 38 RtpPacketReceiverInterface *receiver) override; |
| 39 #endif |
| 40 PacketReceiver::DeliveryStatus OnRtpPacket( |
| 41 MediaType media_type, |
| 42 rtc::ArrayView<const uint8_t> packet) override; |
| 43 |
| 44 private: |
| 45 struct Stream { |
| 46 MediaType media_type = MediaType::ANY; |
| 47 Config config; |
| 48 RtpPacketReceiverInterface* receiver = nullptr; |
| 49 std::vector<RtpPacketSinkInterface*> auxillary_sinks; |
| 50 |
| 51 Stream(MediaType media_type, |
| 52 Config config, |
| 53 RtpPacketReceiverInterface* receiver) |
| 54 : media_type(media_type), config(config), receiver(receiver) {} |
| 55 }; |
| 56 |
| 57 Stream* LookupStream(uint32_t ssrc, MediaType media_type); |
| 58 |
| 59 // Indexed by ssrc. We could use a map indexed by pairs (media_type, ssrc), |
| 60 // except that we want special handling of MediaType:ANY specially. |
| 61 std::multimap<uint32_t, Stream> streams_; |
| 62 RtpPacketObserverInterface* observer_; |
| 63 }; |
| 64 |
| 65 RtpTransportControllerReceive::Stream* |
| 66 RtpTransportControllerReceive::LookupStream(uint32_t ssrc, |
| 67 MediaType media_type) { |
| 68 auto range = streams_.equal_range(ssrc); |
| 69 for (auto it = range.first; it != range.second; ++it) { |
| 70 if (media_type == MediaType::ANY || media_type == it->second.media_type) |
| 71 return &it->second; |
| 72 } |
| 73 return nullptr; |
| 74 } |
| 75 |
| 76 bool RtpTransportControllerReceive::AddReceiver( |
| 77 uint32_t ssrc, |
| 78 MediaType media_type, |
| 79 const Config& config, |
| 80 RtpPacketReceiverInterface* receiver) { |
| 81 if (LookupStream(ssrc, media_type)) { |
| 82 return false; |
| 83 } |
| 84 streams_.insert( |
| 85 std::pair<uint32_t, Stream>(ssrc, Stream(media_type, config, receiver))); |
| 86 return true; |
| 87 } |
| 88 |
| 89 bool RtpTransportControllerReceive::RemoveReceiver( |
| 90 const RtpPacketReceiverInterface* receiver) { |
| 91 for (auto it = streams_.begin(); it != streams_.end(); ++it) { |
| 92 if (it->second.receiver == receiver) { |
| 93 streams_.erase(it); |
| 94 return true; |
| 95 } |
| 96 } |
| 97 return false; |
| 98 } |
| 99 |
| 100 bool RtpTransportControllerReceive::AddSink(uint32_t ssrc, |
| 101 MediaType media_type, |
| 102 RtpPacketSinkInterface* sink) { |
| 103 Stream* stream = LookupStream(ssrc, media_type); |
| 104 if (stream) { |
| 105 stream->auxillary_sinks.push_back(sink); |
| 106 return true; |
| 107 } |
| 108 return false; |
| 109 } |
| 110 |
| 111 bool RtpTransportControllerReceive::RemoveSink( |
| 112 const RtpPacketSinkInterface* sink) { |
| 113 bool found = false; |
| 114 for (auto it : streams_) { |
| 115 auto sinks_end = it.second.auxillary_sinks.end(); |
| 116 auto sinks_it = |
| 117 std::remove(it.second.auxillary_sinks.begin(), sinks_end, sink); |
| 118 if (sinks_it != sinks_end) { |
| 119 it.second.auxillary_sinks.erase(sinks_it, sinks_end); |
| 120 found = true; |
| 121 } |
| 122 } |
| 123 return found; |
| 124 } |
| 125 |
| 126 PacketReceiver::DeliveryStatus RtpTransportControllerReceive::OnRtpPacket( |
| 127 MediaType media_type, |
| 128 rtc::ArrayView<const uint8_t> raw_packet) { |
| 129 RtpPacketReceived parsed_packet; |
| 130 if (!parsed_packet.Parse(raw_packet.data(), raw_packet.size())) |
| 131 return PacketReceiver::DELIVERY_PACKET_ERROR; |
| 132 Stream* stream = LookupStream(parsed_packet.Ssrc(), media_type); |
| 133 if (!stream) { |
| 134 // TODO(nisse): Lookup payload, for unsignalled streams. |
| 135 return PacketReceiver::DELIVERY_UNKNOWN_SSRC; |
| 136 } |
| 137 if (!stream->receiver->OnRtpPacketReceive(&parsed_packet)) |
| 138 return PacketReceiver::DELIVERY_PACKET_ERROR; |
| 139 for (auto it : stream->auxillary_sinks) { |
| 140 it->OnRtpPacket(parsed_packet); |
| 141 } |
| 142 if (observer_) |
| 143 observer_->OnRtpPacket(media_type, stream->config, parsed_packet); |
| 144 return PacketReceiver::DELIVERY_OK; |
| 145 } |
| 146 |
| 147 } // namespace webrtc |
OLD | NEW |