OLD | NEW |
| (Empty) |
1 /* | |
2 * libjingle | |
3 * Copyright 2011 Google Inc. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright notice, | |
9 * this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 * this list of conditions and the following disclaimer in the documentation | |
12 * and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 // This file contains structures for describing SSRCs from a media source such | |
29 // as a MediaStreamTrack when it is sent across an RTP session. Multiple media | |
30 // sources may be sent across the same RTP session, each of them will be | |
31 // described by one StreamParams object | |
32 // SsrcGroup is used to describe the relationship between the SSRCs that | |
33 // are used for this media source. | |
34 // E.x: Consider a source that is sent as 3 simulcast streams | |
35 // Let the simulcast elements have SSRC 10, 20, 30. | |
36 // Let each simulcast element use FEC and let the protection packets have | |
37 // SSRC 11,21,31. | |
38 // To describe this 4 SsrcGroups are needed, | |
39 // StreamParams would then contain ssrc = {10,11,20,21,30,31} and | |
40 // ssrc_groups = {{SIM,{10,20,30}, {FEC,{10,11}, {FEC, {20,21}, {FEC {30,31}}} | |
41 // Please see RFC 5576. | |
42 | |
43 #ifndef TALK_MEDIA_BASE_STREAMPARAMS_H_ | |
44 #define TALK_MEDIA_BASE_STREAMPARAMS_H_ | |
45 | |
46 #include <algorithm> | |
47 #include <set> | |
48 #include <string> | |
49 #include <vector> | |
50 | |
51 #include "webrtc/base/basictypes.h" | |
52 #include "webrtc/base/constructormagic.h" | |
53 | |
54 namespace cricket { | |
55 | |
56 extern const char kFecSsrcGroupSemantics[]; | |
57 extern const char kFidSsrcGroupSemantics[]; | |
58 extern const char kSimSsrcGroupSemantics[]; | |
59 | |
60 struct SsrcGroup { | |
61 SsrcGroup(const std::string& usage, const std::vector<uint32_t>& ssrcs) | |
62 : semantics(usage), ssrcs(ssrcs) {} | |
63 | |
64 bool operator==(const SsrcGroup& other) const { | |
65 return (semantics == other.semantics && ssrcs == other.ssrcs); | |
66 } | |
67 bool operator!=(const SsrcGroup &other) const { | |
68 return !(*this == other); | |
69 } | |
70 | |
71 bool has_semantics(const std::string& semantics) const; | |
72 | |
73 std::string ToString() const; | |
74 | |
75 std::string semantics; // e.g FIX, FEC, SIM. | |
76 std::vector<uint32_t> ssrcs; // SSRCs of this type. | |
77 }; | |
78 | |
79 struct StreamParams { | |
80 static StreamParams CreateLegacy(uint32_t ssrc) { | |
81 StreamParams stream; | |
82 stream.ssrcs.push_back(ssrc); | |
83 return stream; | |
84 } | |
85 | |
86 bool operator==(const StreamParams& other) const { | |
87 return (groupid == other.groupid && | |
88 id == other.id && | |
89 ssrcs == other.ssrcs && | |
90 ssrc_groups == other.ssrc_groups && | |
91 type == other.type && | |
92 display == other.display && | |
93 cname == other.cname && | |
94 sync_label == other.sync_label); | |
95 } | |
96 bool operator!=(const StreamParams &other) const { | |
97 return !(*this == other); | |
98 } | |
99 | |
100 uint32_t first_ssrc() const { | |
101 if (ssrcs.empty()) { | |
102 return 0; | |
103 } | |
104 | |
105 return ssrcs[0]; | |
106 } | |
107 bool has_ssrcs() const { | |
108 return !ssrcs.empty(); | |
109 } | |
110 bool has_ssrc(uint32_t ssrc) const { | |
111 return std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end(); | |
112 } | |
113 void add_ssrc(uint32_t ssrc) { ssrcs.push_back(ssrc); } | |
114 bool has_ssrc_groups() const { | |
115 return !ssrc_groups.empty(); | |
116 } | |
117 bool has_ssrc_group(const std::string& semantics) const { | |
118 return (get_ssrc_group(semantics) != NULL); | |
119 } | |
120 const SsrcGroup* get_ssrc_group(const std::string& semantics) const { | |
121 for (std::vector<SsrcGroup>::const_iterator it = ssrc_groups.begin(); | |
122 it != ssrc_groups.end(); ++it) { | |
123 if (it->has_semantics(semantics)) { | |
124 return &(*it); | |
125 } | |
126 } | |
127 return NULL; | |
128 } | |
129 | |
130 // Convenience function to add an FID ssrc for a primary_ssrc | |
131 // that's already been added. | |
132 inline bool AddFidSsrc(uint32_t primary_ssrc, uint32_t fid_ssrc) { | |
133 return AddSecondarySsrc(kFidSsrcGroupSemantics, primary_ssrc, fid_ssrc); | |
134 } | |
135 | |
136 // Convenience function to lookup the FID ssrc for a primary_ssrc. | |
137 // Returns false if primary_ssrc not found or FID not defined for it. | |
138 inline bool GetFidSsrc(uint32_t primary_ssrc, uint32_t* fid_ssrc) const { | |
139 return GetSecondarySsrc(kFidSsrcGroupSemantics, primary_ssrc, fid_ssrc); | |
140 } | |
141 | |
142 // Convenience to get all the SIM SSRCs if there are SIM ssrcs, or | |
143 // the first SSRC otherwise. | |
144 void GetPrimarySsrcs(std::vector<uint32_t>* ssrcs) const; | |
145 | |
146 // Convenience to get all the FID SSRCs for the given primary ssrcs. | |
147 // If a given primary SSRC does not have a FID SSRC, the list of FID | |
148 // SSRCS will be smaller than the list of primary SSRCs. | |
149 void GetFidSsrcs(const std::vector<uint32_t>& primary_ssrcs, | |
150 std::vector<uint32_t>* fid_ssrcs) const; | |
151 | |
152 std::string ToString() const; | |
153 | |
154 // Resource of the MUC jid of the participant of with this stream. | |
155 // For 1:1 calls, should be left empty (which means remote streams | |
156 // and local streams should not be mixed together). | |
157 std::string groupid; | |
158 // Unique per-groupid, not across all groupids | |
159 std::string id; | |
160 std::vector<uint32_t> ssrcs; // All SSRCs for this source | |
161 std::vector<SsrcGroup> ssrc_groups; // e.g. FID, FEC, SIM | |
162 // Examples: "camera", "screencast" | |
163 std::string type; | |
164 // Friendly name describing stream | |
165 std::string display; | |
166 std::string cname; // RTCP CNAME | |
167 std::string sync_label; // Friendly name of cname. | |
168 | |
169 private: | |
170 bool AddSecondarySsrc(const std::string& semantics, | |
171 uint32_t primary_ssrc, | |
172 uint32_t secondary_ssrc); | |
173 bool GetSecondarySsrc(const std::string& semantics, | |
174 uint32_t primary_ssrc, | |
175 uint32_t* secondary_ssrc) const; | |
176 }; | |
177 | |
178 // A Stream can be selected by either groupid+id or ssrc. | |
179 struct StreamSelector { | |
180 explicit StreamSelector(uint32_t ssrc) : ssrc(ssrc) {} | |
181 | |
182 StreamSelector(const std::string& groupid, | |
183 const std::string& streamid) : | |
184 ssrc(0), | |
185 groupid(groupid), | |
186 streamid(streamid) { | |
187 } | |
188 | |
189 bool Matches(const StreamParams& stream) const { | |
190 if (ssrc == 0) { | |
191 return stream.groupid == groupid && stream.id == streamid; | |
192 } else { | |
193 return stream.has_ssrc(ssrc); | |
194 } | |
195 } | |
196 | |
197 uint32_t ssrc; | |
198 std::string groupid; | |
199 std::string streamid; | |
200 }; | |
201 | |
202 typedef std::vector<StreamParams> StreamParamsVec; | |
203 | |
204 // A collection of audio and video and data streams. Most of the | |
205 // methods are merely for convenience. Many of these methods are keyed | |
206 // by ssrc, which is the source identifier in the RTP spec | |
207 // (http://tools.ietf.org/html/rfc3550). | |
208 // TODO(pthatcher): Add basic unit test for these. | |
209 // See https://code.google.com/p/webrtc/issues/detail?id=4107 | |
210 struct MediaStreams { | |
211 public: | |
212 MediaStreams() {} | |
213 void CopyFrom(const MediaStreams& sources); | |
214 | |
215 bool empty() const { | |
216 return audio_.empty() && video_.empty() && data_.empty(); | |
217 } | |
218 | |
219 std::vector<StreamParams>* mutable_audio() { return &audio_; } | |
220 std::vector<StreamParams>* mutable_video() { return &video_; } | |
221 std::vector<StreamParams>* mutable_data() { return &data_; } | |
222 const std::vector<StreamParams>& audio() const { return audio_; } | |
223 const std::vector<StreamParams>& video() const { return video_; } | |
224 const std::vector<StreamParams>& data() const { return data_; } | |
225 | |
226 // Gets a stream, returning true if found. | |
227 bool GetAudioStream( | |
228 const StreamSelector& selector, StreamParams* stream); | |
229 bool GetVideoStream( | |
230 const StreamSelector& selector, StreamParams* stream); | |
231 bool GetDataStream( | |
232 const StreamSelector& selector, StreamParams* stream); | |
233 // Adds a stream. | |
234 void AddAudioStream(const StreamParams& stream); | |
235 void AddVideoStream(const StreamParams& stream); | |
236 void AddDataStream(const StreamParams& stream); | |
237 // Removes a stream, returning true if found and removed. | |
238 bool RemoveAudioStream(const StreamSelector& selector); | |
239 bool RemoveVideoStream(const StreamSelector& selector); | |
240 bool RemoveDataStream(const StreamSelector& selector); | |
241 | |
242 private: | |
243 std::vector<StreamParams> audio_; | |
244 std::vector<StreamParams> video_; | |
245 std::vector<StreamParams> data_; | |
246 | |
247 RTC_DISALLOW_COPY_AND_ASSIGN(MediaStreams); | |
248 }; | |
249 | |
250 template <class Condition> | |
251 const StreamParams* GetStream(const StreamParamsVec& streams, | |
252 Condition condition) { | |
253 StreamParamsVec::const_iterator found = | |
254 std::find_if(streams.begin(), streams.end(), condition); | |
255 return found == streams.end() ? nullptr : &(*found); | |
256 } | |
257 | |
258 inline const StreamParams* GetStreamBySsrc(const StreamParamsVec& streams, | |
259 uint32_t ssrc) { | |
260 return GetStream(streams, | |
261 [&ssrc](const StreamParams& sp) { return sp.has_ssrc(ssrc); }); | |
262 } | |
263 | |
264 inline const StreamParams* GetStreamByIds(const StreamParamsVec& streams, | |
265 const std::string& groupid, | |
266 const std::string& id) { | |
267 return GetStream(streams, | |
268 [&groupid, &id](const StreamParams& sp) { | |
269 return sp.groupid == groupid && sp.id == id; | |
270 }); | |
271 } | |
272 | |
273 inline const StreamParams* GetStream(const StreamParamsVec& streams, | |
274 const StreamSelector& selector) { | |
275 return GetStream(streams, | |
276 [&selector](const StreamParams& sp) { return selector.Matches(sp); }); | |
277 } | |
278 | |
279 template <class Condition> | |
280 bool RemoveStream(StreamParamsVec* streams, Condition condition) { | |
281 auto iter(std::remove_if(streams->begin(), streams->end(), condition)); | |
282 if (iter == streams->end()) | |
283 return false; | |
284 streams->erase(iter, streams->end()); | |
285 return true; | |
286 } | |
287 | |
288 // Removes the stream from streams. Returns true if a stream is | |
289 // found and removed. | |
290 inline bool RemoveStream(StreamParamsVec* streams, | |
291 const StreamSelector& selector) { | |
292 return RemoveStream(streams, | |
293 [&selector](const StreamParams& sp) { return selector.Matches(sp); }); | |
294 } | |
295 inline bool RemoveStreamBySsrc(StreamParamsVec* streams, uint32_t ssrc) { | |
296 return RemoveStream(streams, | |
297 [&ssrc](const StreamParams& sp) { return sp.has_ssrc(ssrc); }); | |
298 } | |
299 inline bool RemoveStreamByIds(StreamParamsVec* streams, | |
300 const std::string& groupid, | |
301 const std::string& id) { | |
302 return RemoveStream(streams, | |
303 [&groupid, &id](const StreamParams& sp) { | |
304 return sp.groupid == groupid && sp.id == id; | |
305 }); | |
306 } | |
307 | |
308 // Checks if |sp| defines parameters for a single primary stream. There may | |
309 // be an RTX stream associated with the primary stream. Leaving as non-static so | |
310 // we can test this function. | |
311 bool IsOneSsrcStream(const StreamParams& sp); | |
312 | |
313 // Checks if |sp| defines parameters for one Simulcast stream. There may be RTX | |
314 // streams associated with the simulcast streams. Leaving as non-static so we | |
315 // can test this function. | |
316 bool IsSimulcastStream(const StreamParams& sp); | |
317 | |
318 } // namespace cricket | |
319 | |
320 #endif // TALK_MEDIA_BASE_STREAMPARAMS_H_ | |
OLD | NEW |