1 /*
2  *  Copyright (c) 2011 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 "media/base/stream_params.h"
12 
13 #include <stdint.h>
14 
15 #include <list>
16 
17 #include "absl/algorithm/container.h"
18 #include "api/array_view.h"
19 #include "rtc_base/strings/string_builder.h"
20 
21 namespace cricket {
22 namespace {
23 
AppendSsrcs(rtc::ArrayView<const uint32_t> ssrcs,rtc::SimpleStringBuilder * sb)24 void AppendSsrcs(rtc::ArrayView<const uint32_t> ssrcs,
25                  rtc::SimpleStringBuilder* sb) {
26   *sb << "ssrcs:[";
27   const char* delimiter = "";
28   for (uint32_t ssrc : ssrcs) {
29     *sb << delimiter << ssrc;
30     delimiter = ",";
31   }
32   *sb << "]";
33 }
34 
AppendSsrcGroups(rtc::ArrayView<const SsrcGroup> ssrc_groups,rtc::SimpleStringBuilder * sb)35 void AppendSsrcGroups(rtc::ArrayView<const SsrcGroup> ssrc_groups,
36                       rtc::SimpleStringBuilder* sb) {
37   *sb << "ssrc_groups:";
38   const char* delimiter = "";
39   for (const SsrcGroup& ssrc_group : ssrc_groups) {
40     *sb << delimiter << ssrc_group.ToString();
41     delimiter = ",";
42   }
43 }
44 
AppendStreamIds(rtc::ArrayView<const std::string> stream_ids,rtc::SimpleStringBuilder * sb)45 void AppendStreamIds(rtc::ArrayView<const std::string> stream_ids,
46                      rtc::SimpleStringBuilder* sb) {
47   *sb << "stream_ids:";
48   const char* delimiter = "";
49   for (const std::string& stream_id : stream_ids) {
50     *sb << delimiter << stream_id;
51     delimiter = ",";
52   }
53 }
54 
AppendRids(rtc::ArrayView<const RidDescription> rids,rtc::SimpleStringBuilder * sb)55 void AppendRids(rtc::ArrayView<const RidDescription> rids,
56                 rtc::SimpleStringBuilder* sb) {
57   *sb << "rids:[";
58   const char* delimiter = "";
59   for (const RidDescription& rid : rids) {
60     *sb << delimiter << rid.rid;
61     delimiter = ",";
62   }
63   *sb << "]";
64 }
65 
66 }  // namespace
67 
68 const char kFecSsrcGroupSemantics[] = "FEC";
69 const char kFecFrSsrcGroupSemantics[] = "FEC-FR";
70 const char kFidSsrcGroupSemantics[] = "FID";
71 const char kSimSsrcGroupSemantics[] = "SIM";
72 
GetStream(const StreamParamsVec & streams,const StreamSelector & selector,StreamParams * stream_out)73 bool GetStream(const StreamParamsVec& streams,
74                const StreamSelector& selector,
75                StreamParams* stream_out) {
76   const StreamParams* found = GetStream(streams, selector);
77   if (found && stream_out)
78     *stream_out = *found;
79   return found != nullptr;
80 }
81 
SsrcGroup(const std::string & usage,const std::vector<uint32_t> & ssrcs)82 SsrcGroup::SsrcGroup(const std::string& usage,
83                      const std::vector<uint32_t>& ssrcs)
84     : semantics(usage), ssrcs(ssrcs) {}
85 SsrcGroup::SsrcGroup(const SsrcGroup&) = default;
86 SsrcGroup::SsrcGroup(SsrcGroup&&) = default;
87 SsrcGroup::~SsrcGroup() = default;
88 
89 SsrcGroup& SsrcGroup::operator=(const SsrcGroup&) = default;
90 SsrcGroup& SsrcGroup::operator=(SsrcGroup&&) = default;
91 
has_semantics(const std::string & semantics_in) const92 bool SsrcGroup::has_semantics(const std::string& semantics_in) const {
93   return (semantics == semantics_in && ssrcs.size() > 0);
94 }
95 
ToString() const96 std::string SsrcGroup::ToString() const {
97   char buf[1024];
98   rtc::SimpleStringBuilder sb(buf);
99   sb << "{";
100   sb << "semantics:" << semantics << ";";
101   AppendSsrcs(ssrcs, &sb);
102   sb << "}";
103   return sb.str();
104 }
105 
106 StreamParams::StreamParams() = default;
107 StreamParams::StreamParams(const StreamParams&) = default;
108 StreamParams::StreamParams(StreamParams&&) = default;
109 StreamParams::~StreamParams() = default;
110 StreamParams& StreamParams::operator=(const StreamParams&) = default;
111 StreamParams& StreamParams::operator=(StreamParams&&) = default;
112 
operator ==(const StreamParams & other) const113 bool StreamParams::operator==(const StreamParams& other) const {
114   return (groupid == other.groupid && id == other.id && ssrcs == other.ssrcs &&
115           ssrc_groups == other.ssrc_groups && cname == other.cname &&
116           stream_ids_ == other.stream_ids_ &&
117           // RIDs are not required to be in the same order for equality.
118           absl::c_is_permutation(rids_, other.rids_));
119 }
120 
ToString() const121 std::string StreamParams::ToString() const {
122   char buf[2 * 1024];
123   rtc::SimpleStringBuilder sb(buf);
124   sb << "{";
125   if (!groupid.empty()) {
126     sb << "groupid:" << groupid << ";";
127   }
128   if (!id.empty()) {
129     sb << "id:" << id << ";";
130   }
131   AppendSsrcs(ssrcs, &sb);
132   sb << ";";
133   AppendSsrcGroups(ssrc_groups, &sb);
134   sb << ";";
135   if (!cname.empty()) {
136     sb << "cname:" << cname << ";";
137   }
138   AppendStreamIds(stream_ids_, &sb);
139   sb << ";";
140   if (!rids_.empty()) {
141     AppendRids(rids_, &sb);
142     sb << ";";
143   }
144   sb << "}";
145   return sb.str();
146 }
147 
GenerateSsrcs(int num_layers,bool generate_fid,bool generate_fec_fr,rtc::UniqueRandomIdGenerator * ssrc_generator)148 void StreamParams::GenerateSsrcs(int num_layers,
149                                  bool generate_fid,
150                                  bool generate_fec_fr,
151                                  rtc::UniqueRandomIdGenerator* ssrc_generator) {
152   RTC_DCHECK_GE(num_layers, 0);
153   RTC_DCHECK(ssrc_generator);
154   std::vector<uint32_t> primary_ssrcs;
155   for (int i = 0; i < num_layers; ++i) {
156     uint32_t ssrc = ssrc_generator->GenerateId();
157     primary_ssrcs.push_back(ssrc);
158     add_ssrc(ssrc);
159   }
160 
161   if (num_layers > 1) {
162     SsrcGroup simulcast(kSimSsrcGroupSemantics, primary_ssrcs);
163     ssrc_groups.push_back(simulcast);
164   }
165 
166   if (generate_fid) {
167     for (uint32_t ssrc : primary_ssrcs) {
168       AddFidSsrc(ssrc, ssrc_generator->GenerateId());
169     }
170   }
171 
172   if (generate_fec_fr) {
173     for (uint32_t ssrc : primary_ssrcs) {
174       AddFecFrSsrc(ssrc, ssrc_generator->GenerateId());
175     }
176   }
177 }
178 
GetPrimarySsrcs(std::vector<uint32_t> * ssrcs) const179 void StreamParams::GetPrimarySsrcs(std::vector<uint32_t>* ssrcs) const {
180   const SsrcGroup* sim_group = get_ssrc_group(kSimSsrcGroupSemantics);
181   if (sim_group == NULL) {
182     ssrcs->push_back(first_ssrc());
183   } else {
184     ssrcs->insert(ssrcs->end(), sim_group->ssrcs.begin(),
185                   sim_group->ssrcs.end());
186   }
187 }
188 
GetFidSsrcs(const std::vector<uint32_t> & primary_ssrcs,std::vector<uint32_t> * fid_ssrcs) const189 void StreamParams::GetFidSsrcs(const std::vector<uint32_t>& primary_ssrcs,
190                                std::vector<uint32_t>* fid_ssrcs) const {
191   for (uint32_t primary_ssrc : primary_ssrcs) {
192     uint32_t fid_ssrc;
193     if (GetFidSsrc(primary_ssrc, &fid_ssrc)) {
194       fid_ssrcs->push_back(fid_ssrc);
195     }
196   }
197 }
198 
AddSecondarySsrc(const std::string & semantics,uint32_t primary_ssrc,uint32_t secondary_ssrc)199 bool StreamParams::AddSecondarySsrc(const std::string& semantics,
200                                     uint32_t primary_ssrc,
201                                     uint32_t secondary_ssrc) {
202   if (!has_ssrc(primary_ssrc)) {
203     return false;
204   }
205 
206   ssrcs.push_back(secondary_ssrc);
207   ssrc_groups.push_back(SsrcGroup(semantics, {primary_ssrc, secondary_ssrc}));
208   return true;
209 }
210 
GetSecondarySsrc(const std::string & semantics,uint32_t primary_ssrc,uint32_t * secondary_ssrc) const211 bool StreamParams::GetSecondarySsrc(const std::string& semantics,
212                                     uint32_t primary_ssrc,
213                                     uint32_t* secondary_ssrc) const {
214   for (const SsrcGroup& ssrc_group : ssrc_groups) {
215     if (ssrc_group.has_semantics(semantics) && ssrc_group.ssrcs.size() >= 2 &&
216         ssrc_group.ssrcs[0] == primary_ssrc) {
217       *secondary_ssrc = ssrc_group.ssrcs[1];
218       return true;
219     }
220   }
221   return false;
222 }
223 
stream_ids() const224 std::vector<std::string> StreamParams::stream_ids() const {
225   return stream_ids_;
226 }
227 
set_stream_ids(const std::vector<std::string> & stream_ids)228 void StreamParams::set_stream_ids(const std::vector<std::string>& stream_ids) {
229   stream_ids_ = stream_ids;
230 }
231 
first_stream_id() const232 std::string StreamParams::first_stream_id() const {
233   return stream_ids_.empty() ? "" : stream_ids_[0];
234 }
235 
236 }  // namespace cricket
237