| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "media/base/stream_params.h" |
| |
| #include <stdint.h> |
| |
| #include <list> |
| |
| #include "absl/algorithm/container.h" |
| #include "api/array_view.h" |
| #include "rtc_base/strings/string_builder.h" |
| |
| namespace cricket { |
| namespace { |
| |
| void AppendSsrcs(rtc::ArrayView<const uint32_t> ssrcs, |
| rtc::SimpleStringBuilder* sb) { |
| *sb << "ssrcs:["; |
| const char* delimiter = ""; |
| for (uint32_t ssrc : ssrcs) { |
| *sb << delimiter << ssrc; |
| delimiter = ","; |
| } |
| *sb << "]"; |
| } |
| |
| void AppendSsrcGroups(rtc::ArrayView<const SsrcGroup> ssrc_groups, |
| rtc::SimpleStringBuilder* sb) { |
| *sb << "ssrc_groups:"; |
| const char* delimiter = ""; |
| for (const SsrcGroup& ssrc_group : ssrc_groups) { |
| *sb << delimiter << ssrc_group.ToString(); |
| delimiter = ","; |
| } |
| } |
| |
| void AppendStreamIds(rtc::ArrayView<const std::string> stream_ids, |
| rtc::SimpleStringBuilder* sb) { |
| *sb << "stream_ids:"; |
| const char* delimiter = ""; |
| for (const std::string& stream_id : stream_ids) { |
| *sb << delimiter << stream_id; |
| delimiter = ","; |
| } |
| } |
| |
| void AppendRids(rtc::ArrayView<const RidDescription> rids, |
| rtc::SimpleStringBuilder* sb) { |
| *sb << "rids:["; |
| const char* delimiter = ""; |
| for (const RidDescription& rid : rids) { |
| *sb << delimiter << rid.rid; |
| delimiter = ","; |
| } |
| *sb << "]"; |
| } |
| |
| } // namespace |
| |
| const char kFecSsrcGroupSemantics[] = "FEC"; |
| const char kFecFrSsrcGroupSemantics[] = "FEC-FR"; |
| const char kFidSsrcGroupSemantics[] = "FID"; |
| const char kSimSsrcGroupSemantics[] = "SIM"; |
| |
| bool GetStream(const StreamParamsVec& streams, |
| const StreamSelector& selector, |
| StreamParams* stream_out) { |
| const StreamParams* found = GetStream(streams, selector); |
| if (found && stream_out) |
| *stream_out = *found; |
| return found != nullptr; |
| } |
| |
| SsrcGroup::SsrcGroup(const std::string& usage, |
| const std::vector<uint32_t>& ssrcs) |
| : semantics(usage), ssrcs(ssrcs) {} |
| SsrcGroup::SsrcGroup(const SsrcGroup&) = default; |
| SsrcGroup::SsrcGroup(SsrcGroup&&) = default; |
| SsrcGroup::~SsrcGroup() = default; |
| |
| SsrcGroup& SsrcGroup::operator=(const SsrcGroup&) = default; |
| SsrcGroup& SsrcGroup::operator=(SsrcGroup&&) = default; |
| |
| bool SsrcGroup::has_semantics(const std::string& semantics_in) const { |
| return (semantics == semantics_in && ssrcs.size() > 0); |
| } |
| |
| std::string SsrcGroup::ToString() const { |
| char buf[1024]; |
| rtc::SimpleStringBuilder sb(buf); |
| sb << "{"; |
| sb << "semantics:" << semantics << ";"; |
| AppendSsrcs(ssrcs, &sb); |
| sb << "}"; |
| return sb.str(); |
| } |
| |
| StreamParams::StreamParams() = default; |
| StreamParams::StreamParams(const StreamParams&) = default; |
| StreamParams::StreamParams(StreamParams&&) = default; |
| StreamParams::~StreamParams() = default; |
| StreamParams& StreamParams::operator=(const StreamParams&) = default; |
| StreamParams& StreamParams::operator=(StreamParams&&) = default; |
| |
| bool StreamParams::operator==(const StreamParams& other) const { |
| return (groupid == other.groupid && id == other.id && ssrcs == other.ssrcs && |
| ssrc_groups == other.ssrc_groups && cname == other.cname && |
| stream_ids_ == other.stream_ids_ && |
| // RIDs are not required to be in the same order for equality. |
| absl::c_is_permutation(rids_, other.rids_)); |
| } |
| |
| std::string StreamParams::ToString() const { |
| char buf[2 * 1024]; |
| rtc::SimpleStringBuilder sb(buf); |
| sb << "{"; |
| if (!groupid.empty()) { |
| sb << "groupid:" << groupid << ";"; |
| } |
| if (!id.empty()) { |
| sb << "id:" << id << ";"; |
| } |
| AppendSsrcs(ssrcs, &sb); |
| sb << ";"; |
| AppendSsrcGroups(ssrc_groups, &sb); |
| sb << ";"; |
| if (!cname.empty()) { |
| sb << "cname:" << cname << ";"; |
| } |
| AppendStreamIds(stream_ids_, &sb); |
| sb << ";"; |
| if (!rids_.empty()) { |
| AppendRids(rids_, &sb); |
| sb << ";"; |
| } |
| sb << "}"; |
| return sb.str(); |
| } |
| |
| void StreamParams::GenerateSsrcs(int num_layers, |
| bool generate_fid, |
| bool generate_fec_fr, |
| rtc::UniqueRandomIdGenerator* ssrc_generator) { |
| RTC_DCHECK_GE(num_layers, 0); |
| RTC_DCHECK(ssrc_generator); |
| std::vector<uint32_t> primary_ssrcs; |
| for (int i = 0; i < num_layers; ++i) { |
| uint32_t ssrc = ssrc_generator->GenerateId(); |
| primary_ssrcs.push_back(ssrc); |
| add_ssrc(ssrc); |
| } |
| |
| if (num_layers > 1) { |
| SsrcGroup simulcast(kSimSsrcGroupSemantics, primary_ssrcs); |
| ssrc_groups.push_back(simulcast); |
| } |
| |
| if (generate_fid) { |
| for (uint32_t ssrc : primary_ssrcs) { |
| AddFidSsrc(ssrc, ssrc_generator->GenerateId()); |
| } |
| } |
| |
| if (generate_fec_fr) { |
| for (uint32_t ssrc : primary_ssrcs) { |
| AddFecFrSsrc(ssrc, ssrc_generator->GenerateId()); |
| } |
| } |
| } |
| |
| void StreamParams::GetPrimarySsrcs(std::vector<uint32_t>* ssrcs) const { |
| const SsrcGroup* sim_group = get_ssrc_group(kSimSsrcGroupSemantics); |
| if (sim_group == NULL) { |
| ssrcs->push_back(first_ssrc()); |
| } else { |
| ssrcs->insert(ssrcs->end(), sim_group->ssrcs.begin(), |
| sim_group->ssrcs.end()); |
| } |
| } |
| |
| void StreamParams::GetFidSsrcs(const std::vector<uint32_t>& primary_ssrcs, |
| std::vector<uint32_t>* fid_ssrcs) const { |
| for (uint32_t primary_ssrc : primary_ssrcs) { |
| uint32_t fid_ssrc; |
| if (GetFidSsrc(primary_ssrc, &fid_ssrc)) { |
| fid_ssrcs->push_back(fid_ssrc); |
| } |
| } |
| } |
| |
| bool StreamParams::AddSecondarySsrc(const std::string& semantics, |
| uint32_t primary_ssrc, |
| uint32_t secondary_ssrc) { |
| if (!has_ssrc(primary_ssrc)) { |
| return false; |
| } |
| |
| ssrcs.push_back(secondary_ssrc); |
| ssrc_groups.push_back(SsrcGroup(semantics, {primary_ssrc, secondary_ssrc})); |
| return true; |
| } |
| |
| bool StreamParams::GetSecondarySsrc(const std::string& semantics, |
| uint32_t primary_ssrc, |
| uint32_t* secondary_ssrc) const { |
| for (const SsrcGroup& ssrc_group : ssrc_groups) { |
| if (ssrc_group.has_semantics(semantics) && ssrc_group.ssrcs.size() >= 2 && |
| ssrc_group.ssrcs[0] == primary_ssrc) { |
| *secondary_ssrc = ssrc_group.ssrcs[1]; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| std::vector<std::string> StreamParams::stream_ids() const { |
| return stream_ids_; |
| } |
| |
| void StreamParams::set_stream_ids(const std::vector<std::string>& stream_ids) { |
| stream_ids_ = stream_ids; |
| } |
| |
| std::string StreamParams::first_stream_id() const { |
| return stream_ids_.empty() ? "" : stream_ids_[0]; |
| } |
| |
| } // namespace cricket |