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 (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 (!id.empty()) {
126 sb << "id:" << id << ";";
127 }
128 AppendSsrcs(ssrcs, &sb);
129 sb << ";";
130 AppendSsrcGroups(ssrc_groups, &sb);
131 sb << ";";
132 if (!cname.empty()) {
133 sb << "cname:" << cname << ";";
134 }
135 AppendStreamIds(stream_ids_, &sb);
136 sb << ";";
137 if (!rids_.empty()) {
138 AppendRids(rids_, &sb);
139 sb << ";";
140 }
141 sb << "}";
142 return sb.str();
143 }
144
GenerateSsrcs(int num_layers,bool generate_fid,bool generate_fec_fr,rtc::UniqueRandomIdGenerator * ssrc_generator)145 void StreamParams::GenerateSsrcs(int num_layers,
146 bool generate_fid,
147 bool generate_fec_fr,
148 rtc::UniqueRandomIdGenerator* ssrc_generator) {
149 RTC_DCHECK_GE(num_layers, 0);
150 RTC_DCHECK(ssrc_generator);
151 std::vector<uint32_t> primary_ssrcs;
152 for (int i = 0; i < num_layers; ++i) {
153 uint32_t ssrc = ssrc_generator->GenerateId();
154 primary_ssrcs.push_back(ssrc);
155 add_ssrc(ssrc);
156 }
157
158 if (num_layers > 1) {
159 SsrcGroup simulcast(kSimSsrcGroupSemantics, primary_ssrcs);
160 ssrc_groups.push_back(simulcast);
161 }
162
163 if (generate_fid) {
164 for (uint32_t ssrc : primary_ssrcs) {
165 AddFidSsrc(ssrc, ssrc_generator->GenerateId());
166 }
167 }
168
169 if (generate_fec_fr) {
170 for (uint32_t ssrc : primary_ssrcs) {
171 AddFecFrSsrc(ssrc, ssrc_generator->GenerateId());
172 }
173 }
174 }
175
GetPrimarySsrcs(std::vector<uint32_t> * ssrcs) const176 void StreamParams::GetPrimarySsrcs(std::vector<uint32_t>* ssrcs) const {
177 const SsrcGroup* sim_group = get_ssrc_group(kSimSsrcGroupSemantics);
178 if (sim_group == NULL) {
179 ssrcs->push_back(first_ssrc());
180 } else {
181 ssrcs->insert(ssrcs->end(), sim_group->ssrcs.begin(),
182 sim_group->ssrcs.end());
183 }
184 }
185
GetFidSsrcs(const std::vector<uint32_t> & primary_ssrcs,std::vector<uint32_t> * fid_ssrcs) const186 void StreamParams::GetFidSsrcs(const std::vector<uint32_t>& primary_ssrcs,
187 std::vector<uint32_t>* fid_ssrcs) const {
188 for (uint32_t primary_ssrc : primary_ssrcs) {
189 uint32_t fid_ssrc;
190 if (GetFidSsrc(primary_ssrc, &fid_ssrc)) {
191 fid_ssrcs->push_back(fid_ssrc);
192 }
193 }
194 }
195
AddSecondarySsrc(const std::string & semantics,uint32_t primary_ssrc,uint32_t secondary_ssrc)196 bool StreamParams::AddSecondarySsrc(const std::string& semantics,
197 uint32_t primary_ssrc,
198 uint32_t secondary_ssrc) {
199 if (!has_ssrc(primary_ssrc)) {
200 return false;
201 }
202
203 ssrcs.push_back(secondary_ssrc);
204 ssrc_groups.push_back(SsrcGroup(semantics, {primary_ssrc, secondary_ssrc}));
205 return true;
206 }
207
GetSecondarySsrc(const std::string & semantics,uint32_t primary_ssrc,uint32_t * secondary_ssrc) const208 bool StreamParams::GetSecondarySsrc(const std::string& semantics,
209 uint32_t primary_ssrc,
210 uint32_t* secondary_ssrc) const {
211 for (const SsrcGroup& ssrc_group : ssrc_groups) {
212 if (ssrc_group.has_semantics(semantics) && ssrc_group.ssrcs.size() >= 2 &&
213 ssrc_group.ssrcs[0] == primary_ssrc) {
214 *secondary_ssrc = ssrc_group.ssrcs[1];
215 return true;
216 }
217 }
218 return false;
219 }
220
stream_ids() const221 std::vector<std::string> StreamParams::stream_ids() const {
222 return stream_ids_;
223 }
224
set_stream_ids(const std::vector<std::string> & stream_ids)225 void StreamParams::set_stream_ids(const std::vector<std::string>& stream_ids) {
226 stream_ids_ = stream_ids;
227 }
228
first_stream_id() const229 std::string StreamParams::first_stream_id() const {
230 return stream_ids_.empty() ? "" : stream_ids_[0];
231 }
232
233 } // namespace cricket
234