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 #include "talk/media/base/streamparams.h" | |
29 | |
30 #include <list> | |
31 #include <sstream> | |
32 | |
33 namespace cricket { | |
34 namespace { | |
35 // NOTE: There is no check here for duplicate streams, so check before | |
36 // adding. | |
37 void AddStream(std::vector<StreamParams>* streams, const StreamParams& stream) { | |
38 streams->push_back(stream); | |
39 } | |
40 } | |
41 | |
42 const char kFecSsrcGroupSemantics[] = "FEC"; | |
43 const char kFidSsrcGroupSemantics[] = "FID"; | |
44 const char kSimSsrcGroupSemantics[] = "SIM"; | |
45 | |
46 bool GetStream(const StreamParamsVec& streams, | |
47 const StreamSelector& selector, | |
48 StreamParams* stream_out) { | |
49 const StreamParams* found = GetStream(streams, selector); | |
50 if (found && stream_out) | |
51 *stream_out = *found; | |
52 return found != nullptr; | |
53 } | |
54 | |
55 bool MediaStreams::GetAudioStream( | |
56 const StreamSelector& selector, StreamParams* stream) { | |
57 return GetStream(audio_, selector, stream); | |
58 } | |
59 | |
60 bool MediaStreams::GetVideoStream( | |
61 const StreamSelector& selector, StreamParams* stream) { | |
62 return GetStream(video_, selector, stream); | |
63 } | |
64 | |
65 bool MediaStreams::GetDataStream( | |
66 const StreamSelector& selector, StreamParams* stream) { | |
67 return GetStream(data_, selector, stream); | |
68 } | |
69 | |
70 void MediaStreams::CopyFrom(const MediaStreams& streams) { | |
71 audio_ = streams.audio_; | |
72 video_ = streams.video_; | |
73 data_ = streams.data_; | |
74 } | |
75 | |
76 void MediaStreams::AddAudioStream(const StreamParams& stream) { | |
77 AddStream(&audio_, stream); | |
78 } | |
79 | |
80 void MediaStreams::AddVideoStream(const StreamParams& stream) { | |
81 AddStream(&video_, stream); | |
82 } | |
83 | |
84 void MediaStreams::AddDataStream(const StreamParams& stream) { | |
85 AddStream(&data_, stream); | |
86 } | |
87 | |
88 bool MediaStreams::RemoveAudioStream( | |
89 const StreamSelector& selector) { | |
90 return RemoveStream(&audio_, selector); | |
91 } | |
92 | |
93 bool MediaStreams::RemoveVideoStream( | |
94 const StreamSelector& selector) { | |
95 return RemoveStream(&video_, selector); | |
96 } | |
97 | |
98 bool MediaStreams::RemoveDataStream( | |
99 const StreamSelector& selector) { | |
100 return RemoveStream(&data_, selector); | |
101 } | |
102 | |
103 static std::string SsrcsToString(const std::vector<uint32_t>& ssrcs) { | |
104 std::ostringstream ost; | |
105 ost << "ssrcs:["; | |
106 for (std::vector<uint32_t>::const_iterator it = ssrcs.begin(); | |
107 it != ssrcs.end(); ++it) { | |
108 if (it != ssrcs.begin()) { | |
109 ost << ","; | |
110 } | |
111 ost << *it; | |
112 } | |
113 ost << "]"; | |
114 return ost.str(); | |
115 } | |
116 | |
117 bool SsrcGroup::has_semantics(const std::string& semantics_in) const { | |
118 return (semantics == semantics_in && ssrcs.size() > 0); | |
119 } | |
120 | |
121 std::string SsrcGroup::ToString() const { | |
122 std::ostringstream ost; | |
123 ost << "{"; | |
124 ost << "semantics:" << semantics << ";"; | |
125 ost << SsrcsToString(ssrcs); | |
126 ost << "}"; | |
127 return ost.str(); | |
128 } | |
129 | |
130 std::string StreamParams::ToString() const { | |
131 std::ostringstream ost; | |
132 ost << "{"; | |
133 if (!groupid.empty()) { | |
134 ost << "groupid:" << groupid << ";"; | |
135 } | |
136 if (!id.empty()) { | |
137 ost << "id:" << id << ";"; | |
138 } | |
139 ost << SsrcsToString(ssrcs) << ";"; | |
140 ost << "ssrc_groups:"; | |
141 for (std::vector<SsrcGroup>::const_iterator it = ssrc_groups.begin(); | |
142 it != ssrc_groups.end(); ++it) { | |
143 if (it != ssrc_groups.begin()) { | |
144 ost << ","; | |
145 } | |
146 ost << it->ToString(); | |
147 } | |
148 ost << ";"; | |
149 if (!type.empty()) { | |
150 ost << "type:" << type << ";"; | |
151 } | |
152 if (!display.empty()) { | |
153 ost << "display:" << display << ";"; | |
154 } | |
155 if (!cname.empty()) { | |
156 ost << "cname:" << cname << ";"; | |
157 } | |
158 if (!sync_label.empty()) { | |
159 ost << "sync_label:" << sync_label; | |
160 } | |
161 ost << "}"; | |
162 return ost.str(); | |
163 } | |
164 void StreamParams::GetPrimarySsrcs(std::vector<uint32_t>* ssrcs) const { | |
165 const SsrcGroup* sim_group = get_ssrc_group(kSimSsrcGroupSemantics); | |
166 if (sim_group == NULL) { | |
167 ssrcs->push_back(first_ssrc()); | |
168 } else { | |
169 for (size_t i = 0; i < sim_group->ssrcs.size(); ++i) { | |
170 ssrcs->push_back(sim_group->ssrcs[i]); | |
171 } | |
172 } | |
173 } | |
174 | |
175 void StreamParams::GetFidSsrcs(const std::vector<uint32_t>& primary_ssrcs, | |
176 std::vector<uint32_t>* fid_ssrcs) const { | |
177 for (size_t i = 0; i < primary_ssrcs.size(); ++i) { | |
178 uint32_t fid_ssrc; | |
179 if (GetFidSsrc(primary_ssrcs[i], &fid_ssrc)) { | |
180 fid_ssrcs->push_back(fid_ssrc); | |
181 } | |
182 } | |
183 } | |
184 | |
185 bool StreamParams::AddSecondarySsrc(const std::string& semantics, | |
186 uint32_t primary_ssrc, | |
187 uint32_t secondary_ssrc) { | |
188 if (!has_ssrc(primary_ssrc)) { | |
189 return false; | |
190 } | |
191 | |
192 ssrcs.push_back(secondary_ssrc); | |
193 std::vector<uint32_t> ssrc_vector; | |
194 ssrc_vector.push_back(primary_ssrc); | |
195 ssrc_vector.push_back(secondary_ssrc); | |
196 SsrcGroup ssrc_group = SsrcGroup(semantics, ssrc_vector); | |
197 ssrc_groups.push_back(ssrc_group); | |
198 return true; | |
199 } | |
200 | |
201 bool StreamParams::GetSecondarySsrc(const std::string& semantics, | |
202 uint32_t primary_ssrc, | |
203 uint32_t* secondary_ssrc) const { | |
204 for (std::vector<SsrcGroup>::const_iterator it = ssrc_groups.begin(); | |
205 it != ssrc_groups.end(); ++it) { | |
206 if (it->has_semantics(semantics) && | |
207 it->ssrcs.size() >= 2 && | |
208 it->ssrcs[0] == primary_ssrc) { | |
209 *secondary_ssrc = it->ssrcs[1]; | |
210 return true; | |
211 } | |
212 } | |
213 return false; | |
214 } | |
215 | |
216 bool IsOneSsrcStream(const StreamParams& sp) { | |
217 if (sp.ssrcs.size() == 1 && sp.ssrc_groups.empty()) { | |
218 return true; | |
219 } | |
220 if (sp.ssrcs.size() == 2) { | |
221 const SsrcGroup* fid_group = sp.get_ssrc_group(kFidSsrcGroupSemantics); | |
222 if (fid_group != NULL) { | |
223 return (sp.ssrcs == fid_group->ssrcs); | |
224 } | |
225 } | |
226 return false; | |
227 } | |
228 | |
229 static void RemoveFirst(std::list<uint32_t>* ssrcs, uint32_t value) { | |
230 std::list<uint32_t>::iterator it = | |
231 std::find(ssrcs->begin(), ssrcs->end(), value); | |
232 if (it != ssrcs->end()) { | |
233 ssrcs->erase(it); | |
234 } | |
235 } | |
236 | |
237 bool IsSimulcastStream(const StreamParams& sp) { | |
238 const SsrcGroup* const sg = sp.get_ssrc_group(kSimSsrcGroupSemantics); | |
239 if (sg == NULL || sg->ssrcs.size() < 2) { | |
240 return false; | |
241 } | |
242 // Start with all StreamParams SSRCs. Remove simulcast SSRCs (from sg) and | |
243 // RTX SSRCs. If we still have SSRCs left, we don't know what they're for. | |
244 // Also we remove first-found SSRCs only. So duplicates should lead to errors. | |
245 std::list<uint32_t> sp_ssrcs(sp.ssrcs.begin(), sp.ssrcs.end()); | |
246 for (size_t i = 0; i < sg->ssrcs.size(); ++i) { | |
247 RemoveFirst(&sp_ssrcs, sg->ssrcs[i]); | |
248 } | |
249 for (size_t i = 0; i < sp.ssrc_groups.size(); ++i) { | |
250 const SsrcGroup& group = sp.ssrc_groups[i]; | |
251 if (group.semantics.compare(kFidSsrcGroupSemantics) != 0 || | |
252 group.ssrcs.size() != 2) { | |
253 continue; | |
254 } | |
255 RemoveFirst(&sp_ssrcs, group.ssrcs[1]); | |
256 } | |
257 // If there's SSRCs left that we don't know how to handle, we bail out. | |
258 return sp_ssrcs.size() == 0; | |
259 } | |
260 | |
261 } // namespace cricket | |
OLD | NEW |