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
54namespace cricket {
55
56extern const char kFecSsrcGroupSemantics[];
57extern const char kFidSsrcGroupSemantics[];
58extern const char kSimSsrcGroupSemantics[];
59
60struct 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
79struct 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.
179struct 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
202typedef 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
210struct 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// A request for a specific format of a specific stream.
251struct StaticVideoView {
252  StaticVideoView(const StreamSelector& selector,
253                  int width, int height, int framerate)
254      : selector(selector),
255        width(width),
256        height(height),
257        framerate(framerate),
258        preference(0) {
259  }
260
261  StreamSelector selector;
262  int width;
263  int height;
264  int framerate;
265  int preference;
266};
267
268typedef std::vector<StaticVideoView> StaticVideoViews;
269
270// A request for several streams in various formats.
271struct ViewRequest {
272  StaticVideoViews static_video_views;
273};
274
275template <class Condition>
276const StreamParams* GetStream(const StreamParamsVec& streams,
277                              Condition condition) {
278  StreamParamsVec::const_iterator found =
279      std::find_if(streams.begin(), streams.end(), condition);
280  return found == streams.end() ? nullptr : &(*found);
281}
282
283inline const StreamParams* GetStreamBySsrc(const StreamParamsVec& streams,
284                                           uint32_t ssrc) {
285  return GetStream(streams,
286      [&ssrc](const StreamParams& sp) { return sp.has_ssrc(ssrc); });
287}
288
289inline const StreamParams* GetStreamByIds(const StreamParamsVec& streams,
290                                          const std::string& groupid,
291                                          const std::string& id) {
292  return GetStream(streams,
293      [&groupid, &id](const StreamParams& sp) {
294        return sp.groupid == groupid && sp.id == id;
295      });
296}
297
298inline const StreamParams* GetStream(const StreamParamsVec& streams,
299                                     const StreamSelector& selector) {
300  return GetStream(streams,
301      [&selector](const StreamParams& sp) { return selector.Matches(sp); });
302}
303
304template <class Condition>
305bool RemoveStream(StreamParamsVec* streams, Condition condition) {
306  auto iter(std::remove_if(streams->begin(), streams->end(), condition));
307  if (iter == streams->end())
308    return false;
309  streams->erase(iter, streams->end());
310  return true;
311}
312
313// Removes the stream from streams. Returns true if a stream is
314// found and removed.
315inline bool RemoveStream(StreamParamsVec* streams,
316                  const StreamSelector& selector) {
317  return RemoveStream(streams,
318      [&selector](const StreamParams& sp) { return selector.Matches(sp); });
319}
320inline bool RemoveStreamBySsrc(StreamParamsVec* streams, uint32_t ssrc) {
321  return RemoveStream(streams,
322      [&ssrc](const StreamParams& sp) { return sp.has_ssrc(ssrc); });
323}
324inline bool RemoveStreamByIds(StreamParamsVec* streams,
325                              const std::string& groupid,
326                              const std::string& id) {
327  return RemoveStream(streams,
328      [&groupid, &id](const StreamParams& sp) {
329        return sp.groupid == groupid && sp.id == id;
330      });
331}
332
333// Checks if |sp| defines parameters for a single primary stream. There may
334// be an RTX stream associated with the primary stream. Leaving as non-static so
335// we can test this function.
336bool IsOneSsrcStream(const StreamParams& sp);
337
338// Checks if |sp| defines parameters for one Simulcast stream. There may be RTX
339// streams associated with the simulcast streams. Leaving as non-static so we
340// can test this function.
341bool IsSimulcastStream(const StreamParams& sp);
342
343}  // namespace cricket
344
345#endif  // TALK_MEDIA_BASE_STREAMPARAMS_H_
346