blob: e3dc57d9da7f22fa7e0c8bdf8db29812b9fa4f71 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000030#include <list>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#include <sstream>
32
pthatcher@webrtc.orge2b75852014-12-16 21:09:08 +000033namespace {
34
35// NOTE: There is no check here for duplicate streams, so check before
36// adding.
37void AddStream(std::vector<cricket::StreamParams>* streams,
38 const cricket::StreamParams& stream) {
39 streams->push_back(stream);
40}
41
42}
43
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044namespace cricket {
45
46const char kFecSsrcGroupSemantics[] = "FEC";
47const char kFidSsrcGroupSemantics[] = "FID";
wu@webrtc.orgcecfd182013-10-30 05:18:12 +000048const char kSimSsrcGroupSemantics[] = "SIM";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049
pthatcher@webrtc.orge2b75852014-12-16 21:09:08 +000050bool MediaStreams::GetAudioStream(
51 const StreamSelector& selector, StreamParams* stream) {
52 return GetStream(audio_, selector, stream);
53}
54
55bool MediaStreams::GetVideoStream(
56 const StreamSelector& selector, StreamParams* stream) {
57 return GetStream(video_, selector, stream);
58}
59
60bool MediaStreams::GetDataStream(
61 const StreamSelector& selector, StreamParams* stream) {
62 return GetStream(data_, selector, stream);
63}
64
65void MediaStreams::CopyFrom(const MediaStreams& streams) {
66 audio_ = streams.audio_;
67 video_ = streams.video_;
68 data_ = streams.data_;
69}
70
71void MediaStreams::AddAudioStream(const StreamParams& stream) {
72 AddStream(&audio_, stream);
73}
74
75void MediaStreams::AddVideoStream(const StreamParams& stream) {
76 AddStream(&video_, stream);
77}
78
79void MediaStreams::AddDataStream(const StreamParams& stream) {
80 AddStream(&data_, stream);
81}
82
83bool MediaStreams::RemoveAudioStream(
84 const StreamSelector& selector) {
85 return RemoveStream(&audio_, selector);
86}
87
88bool MediaStreams::RemoveVideoStream(
89 const StreamSelector& selector) {
90 return RemoveStream(&video_, selector);
91}
92
93bool MediaStreams::RemoveDataStream(
94 const StreamSelector& selector) {
95 return RemoveStream(&data_, selector);
96}
97
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098static std::string SsrcsToString(const std::vector<uint32>& ssrcs) {
99 std::ostringstream ost;
100 ost << "ssrcs:[";
101 for (std::vector<uint32>::const_iterator it = ssrcs.begin();
102 it != ssrcs.end(); ++it) {
103 if (it != ssrcs.begin()) {
104 ost << ",";
105 }
106 ost << *it;
107 }
108 ost << "]";
109 return ost.str();
110}
111
112bool SsrcGroup::has_semantics(const std::string& semantics_in) const {
113 return (semantics == semantics_in && ssrcs.size() > 0);
114}
115
116std::string SsrcGroup::ToString() const {
117 std::ostringstream ost;
118 ost << "{";
119 ost << "semantics:" << semantics << ";";
120 ost << SsrcsToString(ssrcs);
121 ost << "}";
122 return ost.str();
123}
124
125std::string StreamParams::ToString() const {
126 std::ostringstream ost;
127 ost << "{";
128 if (!groupid.empty()) {
129 ost << "groupid:" << groupid << ";";
130 }
131 if (!id.empty()) {
132 ost << "id:" << id << ";";
133 }
134 ost << SsrcsToString(ssrcs) << ";";
135 ost << "ssrc_groups:";
136 for (std::vector<SsrcGroup>::const_iterator it = ssrc_groups.begin();
137 it != ssrc_groups.end(); ++it) {
138 if (it != ssrc_groups.begin()) {
139 ost << ",";
140 }
141 ost << it->ToString();
142 }
143 ost << ";";
144 if (!type.empty()) {
145 ost << "type:" << type << ";";
146 }
147 if (!display.empty()) {
148 ost << "display:" << display << ";";
149 }
150 if (!cname.empty()) {
151 ost << "cname:" << cname << ";";
152 }
153 if (!sync_label.empty()) {
154 ost << "sync_label:" << sync_label;
155 }
156 ost << "}";
157 return ost.str();
158}
pbos@webrtc.org5301b0f2014-07-17 08:51:46 +0000159void StreamParams::GetPrimarySsrcs(std::vector<uint32>* ssrcs) const {
160 const SsrcGroup* sim_group = get_ssrc_group(kSimSsrcGroupSemantics);
161 if (sim_group == NULL) {
162 ssrcs->push_back(first_ssrc());
163 } else {
164 for (size_t i = 0; i < sim_group->ssrcs.size(); ++i) {
165 ssrcs->push_back(sim_group->ssrcs[i]);
166 }
167 }
168}
169
170void StreamParams::GetFidSsrcs(const std::vector<uint32>& primary_ssrcs,
171 std::vector<uint32>* fid_ssrcs) const {
172 for (size_t i = 0; i < primary_ssrcs.size(); ++i) {
173 uint32 fid_ssrc;
174 if (GetFidSsrc(primary_ssrcs[i], &fid_ssrc)) {
175 fid_ssrcs->push_back(fid_ssrc);
176 }
177 }
178}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179
180bool StreamParams::AddSecondarySsrc(const std::string& semantics,
181 uint32 primary_ssrc,
182 uint32 secondary_ssrc) {
183 if (!has_ssrc(primary_ssrc)) {
184 return false;
185 }
186
187 ssrcs.push_back(secondary_ssrc);
188 std::vector<uint32> ssrc_vector;
189 ssrc_vector.push_back(primary_ssrc);
190 ssrc_vector.push_back(secondary_ssrc);
191 SsrcGroup ssrc_group = SsrcGroup(semantics, ssrc_vector);
192 ssrc_groups.push_back(ssrc_group);
193 return true;
194}
195
196bool StreamParams::GetSecondarySsrc(const std::string& semantics,
197 uint32 primary_ssrc,
198 uint32* secondary_ssrc) const {
199 for (std::vector<SsrcGroup>::const_iterator it = ssrc_groups.begin();
200 it != ssrc_groups.end(); ++it) {
201 if (it->has_semantics(semantics) &&
202 it->ssrcs.size() >= 2 &&
203 it->ssrcs[0] == primary_ssrc) {
204 *secondary_ssrc = it->ssrcs[1];
205 return true;
206 }
207 }
208 return false;
209}
210
211bool GetStream(const StreamParamsVec& streams,
212 const StreamSelector& selector,
213 StreamParams* stream_out) {
214 for (StreamParamsVec::const_iterator stream = streams.begin();
215 stream != streams.end(); ++stream) {
216 if (selector.Matches(*stream)) {
217 if (stream_out != NULL) {
218 *stream_out = *stream;
219 }
220 return true;
221 }
222 }
223 return false;
224}
225
226bool GetStreamBySsrc(const StreamParamsVec& streams, uint32 ssrc,
227 StreamParams* stream_out) {
228 return GetStream(streams, StreamSelector(ssrc), stream_out);
229}
230
231bool GetStreamByIds(const StreamParamsVec& streams,
232 const std::string& groupid,
233 const std::string& id,
234 StreamParams* stream_out) {
235 return GetStream(streams, StreamSelector(groupid, id), stream_out);
236}
237
238bool RemoveStream(StreamParamsVec* streams,
239 const StreamSelector& selector) {
240 bool ret = false;
241 for (StreamParamsVec::iterator stream = streams->begin();
242 stream != streams->end(); ) {
243 if (selector.Matches(*stream)) {
244 stream = streams->erase(stream);
245 ret = true;
246 } else {
247 ++stream;
248 }
249 }
250 return ret;
251}
252
253bool RemoveStreamBySsrc(StreamParamsVec* streams, uint32 ssrc) {
254 return RemoveStream(streams, StreamSelector(ssrc));
255}
256
257bool RemoveStreamByIds(StreamParamsVec* streams,
258 const std::string& groupid,
259 const std::string& id) {
260 return RemoveStream(streams, StreamSelector(groupid, id));
261}
262
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000263bool IsOneSsrcStream(const StreamParams& sp) {
264 if (sp.ssrcs.size() == 1 && sp.ssrc_groups.empty()) {
265 return true;
266 }
267 if (sp.ssrcs.size() == 2) {
268 const SsrcGroup* fid_group = sp.get_ssrc_group(kFidSsrcGroupSemantics);
269 if (fid_group != NULL) {
270 return (sp.ssrcs == fid_group->ssrcs);
271 }
272 }
273 return false;
274}
275
276static void RemoveFirst(std::list<uint32>* ssrcs, uint32 value) {
277 std::list<uint32>::iterator it =
278 std::find(ssrcs->begin(), ssrcs->end(), value);
279 if (it != ssrcs->end()) {
280 ssrcs->erase(it);
281 }
282}
283
284bool IsSimulcastStream(const StreamParams& sp) {
285 const SsrcGroup* const sg = sp.get_ssrc_group(kSimSsrcGroupSemantics);
286 if (sg == NULL || sg->ssrcs.size() < 2) {
287 return false;
288 }
289 // Start with all StreamParams SSRCs. Remove simulcast SSRCs (from sg) and
290 // RTX SSRCs. If we still have SSRCs left, we don't know what they're for.
291 // Also we remove first-found SSRCs only. So duplicates should lead to errors.
292 std::list<uint32> sp_ssrcs(sp.ssrcs.begin(), sp.ssrcs.end());
293 for (size_t i = 0; i < sg->ssrcs.size(); ++i) {
294 RemoveFirst(&sp_ssrcs, sg->ssrcs[i]);
295 }
296 for (size_t i = 0; i < sp.ssrc_groups.size(); ++i) {
297 const SsrcGroup& group = sp.ssrc_groups[i];
298 if (group.semantics.compare(kFidSsrcGroupSemantics) != 0 ||
299 group.ssrcs.size() != 2) {
300 continue;
301 }
302 RemoveFirst(&sp_ssrcs, group.ssrcs[1]);
303 }
304 // If there's SSRCs left that we don't know how to handle, we bail out.
305 return sp_ssrcs.size() == 0;
306}
307
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308} // namespace cricket