1 /*
2  *  Copyright (c) 2013 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 #ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_
12 #define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_
13 
14 #include <map>
15 
16 #include "webrtc/base/scoped_ptr.h"
17 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
19 
20 namespace webrtc {
21 
22 // This strategy deals with the audio/video-specific aspects
23 // of payload handling.
24 class RTPPayloadStrategy {
25  public:
~RTPPayloadStrategy()26   virtual ~RTPPayloadStrategy() {}
27 
28   virtual bool CodecsMustBeUnique() const = 0;
29 
30   virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
31                                    const uint32_t frequency,
32                                    const size_t channels,
33                                    const uint32_t rate) const = 0;
34 
35   virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
36                                  const uint32_t rate) const = 0;
37 
38   virtual RtpUtility::Payload* CreatePayloadType(
39       const char payloadName[RTP_PAYLOAD_NAME_SIZE],
40       const int8_t payloadType,
41       const uint32_t frequency,
42       const size_t channels,
43       const uint32_t rate) const = 0;
44 
45   virtual int GetPayloadTypeFrequency(
46       const RtpUtility::Payload& payload) const = 0;
47 
48   static RTPPayloadStrategy* CreateStrategy(const bool handling_audio);
49 
50  protected:
RTPPayloadStrategy()51   RTPPayloadStrategy() {}
52 };
53 
54 class RTPPayloadRegistry {
55  public:
56   // The registry takes ownership of the strategy.
57   explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy);
58   ~RTPPayloadRegistry();
59 
60   int32_t RegisterReceivePayload(
61       const char payload_name[RTP_PAYLOAD_NAME_SIZE],
62       const int8_t payload_type,
63       const uint32_t frequency,
64       const size_t channels,
65       const uint32_t rate,
66       bool* created_new_payload_type);
67 
68   int32_t DeRegisterReceivePayload(
69       const int8_t payload_type);
70 
71   int32_t ReceivePayloadType(
72       const char payload_name[RTP_PAYLOAD_NAME_SIZE],
73       const uint32_t frequency,
74       const size_t channels,
75       const uint32_t rate,
76       int8_t* payload_type) const;
77 
78   bool RtxEnabled() const;
79 
80   void SetRtxSsrc(uint32_t ssrc);
81 
82   bool GetRtxSsrc(uint32_t* ssrc) const;
83 
84   void SetRtxPayloadType(int payload_type, int associated_payload_type);
85 
86   bool IsRtx(const RTPHeader& header) const;
87 
88   // DEPRECATED. Use RestoreOriginalPacket below that takes a uint8_t*
89   // restored_packet, instead of a uint8_t**.
90   // TODO(noahric): Remove this when all callers have been updated.
91   bool RestoreOriginalPacket(uint8_t** restored_packet,
92                              const uint8_t* packet,
93                              size_t* packet_length,
94                              uint32_t original_ssrc,
95                              const RTPHeader& header) const;
96 
97   bool RestoreOriginalPacket(uint8_t* restored_packet,
98                              const uint8_t* packet,
99                              size_t* packet_length,
100                              uint32_t original_ssrc,
101                              const RTPHeader& header) const;
102 
103   bool IsRed(const RTPHeader& header) const;
104 
105   // Returns true if the media of this RTP packet is encapsulated within an
106   // extra header, such as RTX or RED.
107   bool IsEncapsulated(const RTPHeader& header) const;
108 
109   bool GetPayloadSpecifics(uint8_t payload_type, PayloadUnion* payload) const;
110 
111   int GetPayloadTypeFrequency(uint8_t payload_type) const;
112 
113   // DEPRECATED. Use PayloadTypeToPayload below that returns const Payload*
114   // instead of taking output parameter.
115   // TODO(danilchap): Remove this when all callers have been updated.
PayloadTypeToPayload(const uint8_t payload_type,RtpUtility::Payload * & payload)116   bool PayloadTypeToPayload(const uint8_t payload_type,
117                             RtpUtility::Payload*& payload) const {  // NOLINT
118     payload =
119         const_cast<RtpUtility::Payload*>(PayloadTypeToPayload(payload_type));
120     return payload != nullptr;
121   }
122   const RtpUtility::Payload* PayloadTypeToPayload(uint8_t payload_type) const;
123 
ResetLastReceivedPayloadTypes()124   void ResetLastReceivedPayloadTypes() {
125     CriticalSectionScoped cs(crit_sect_.get());
126     last_received_payload_type_ = -1;
127     last_received_media_payload_type_ = -1;
128   }
129 
130   // This sets the payload type of the packets being received from the network
131   // on the media SSRC. For instance if packets are encapsulated with RED, this
132   // payload type will be the RED payload type.
133   void SetIncomingPayloadType(const RTPHeader& header);
134 
135   // Returns true if the new media payload type has not changed.
136   bool ReportMediaPayloadType(uint8_t media_payload_type);
137 
red_payload_type()138   int8_t red_payload_type() const {
139     CriticalSectionScoped cs(crit_sect_.get());
140     return red_payload_type_;
141   }
ulpfec_payload_type()142   int8_t ulpfec_payload_type() const {
143     CriticalSectionScoped cs(crit_sect_.get());
144     return ulpfec_payload_type_;
145   }
last_received_payload_type()146   int8_t last_received_payload_type() const {
147     CriticalSectionScoped cs(crit_sect_.get());
148     return last_received_payload_type_;
149   }
set_last_received_payload_type(int8_t last_received_payload_type)150   void set_last_received_payload_type(int8_t last_received_payload_type) {
151     CriticalSectionScoped cs(crit_sect_.get());
152     last_received_payload_type_ = last_received_payload_type;
153   }
154 
last_received_media_payload_type()155   int8_t last_received_media_payload_type() const {
156     CriticalSectionScoped cs(crit_sect_.get());
157     return last_received_media_payload_type_;
158   }
159 
use_rtx_payload_mapping_on_restore()160   bool use_rtx_payload_mapping_on_restore() const {
161     CriticalSectionScoped cs(crit_sect_.get());
162     return use_rtx_payload_mapping_on_restore_;
163   }
164 
set_use_rtx_payload_mapping_on_restore(bool val)165   void set_use_rtx_payload_mapping_on_restore(bool val) {
166     CriticalSectionScoped cs(crit_sect_.get());
167     use_rtx_payload_mapping_on_restore_ = val;
168   }
169 
170  private:
171   // Prunes the payload type map of the specific payload type, if it exists.
172   void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
173       const char payload_name[RTP_PAYLOAD_NAME_SIZE],
174       const size_t payload_name_length,
175       const uint32_t frequency,
176       const size_t channels,
177       const uint32_t rate);
178 
179   bool IsRtxInternal(const RTPHeader& header) const;
180 
181   rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
182   RtpUtility::PayloadTypeMap payload_type_map_;
183   rtc::scoped_ptr<RTPPayloadStrategy> rtp_payload_strategy_;
184   int8_t  red_payload_type_;
185   int8_t ulpfec_payload_type_;
186   int8_t incoming_payload_type_;
187   int8_t  last_received_payload_type_;
188   int8_t  last_received_media_payload_type_;
189   bool rtx_;
190   // TODO(changbin): Remove rtx_payload_type_ once interop with old clients that
191   // only understand one RTX PT is no longer needed.
192   int rtx_payload_type_;
193   // Mapping rtx_payload_type_map_[rtx] = associated.
194   std::map<int, int> rtx_payload_type_map_;
195   // When true, use rtx_payload_type_map_ when restoring RTX packets to get the
196   // correct payload type.
197   bool use_rtx_payload_mapping_on_restore_;
198   uint32_t ssrc_rtx_;
199 };
200 
201 }  // namespace webrtc
202 
203 #endif  // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_
204