| 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 |