7 #include "packager/mpd/base/period.h" 9 #include "packager/base/stl_util.h" 10 #include "packager/mpd/base/adaptation_set.h" 11 #include "packager/mpd/base/mpd_options.h" 12 #include "packager/mpd/base/mpd_utils.h" 13 #include "packager/mpd/base/xml/xml_node.h" 20 bool ProtectedContentEq(
21 const MediaInfo::ProtectedContent& content_protection1,
22 const MediaInfo::ProtectedContent& content_protection2) {
23 return content_protection1.SerializeAsString() ==
24 content_protection2.SerializeAsString();
27 std::set<std::string> GetUUIDs(
28 const MediaInfo::ProtectedContent& protected_content) {
29 std::set<std::string> uuids;
30 for (
const auto& entry : protected_content.content_protection_entry())
31 uuids.insert(entry.uuid());
38 double start_time_in_seconds,
40 base::AtomicSequenceNumber* representation_counter)
42 start_time_in_seconds_(start_time_in_seconds),
43 mpd_options_(mpd_options),
44 representation_counter_(representation_counter) {}
47 const MediaInfo& media_info,
48 bool content_protection_in_adaptation_set) {
51 if (duration_seconds_ == 0)
52 duration_seconds_ = media_info.media_duration_seconds();
57 const std::string key = GetAdaptationSetKey(media_info);
58 std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
59 if (content_protection_in_adaptation_set) {
61 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info))
62 return adaptation_set;
65 if (!adaptation_sets.empty()) {
66 DCHECK_EQ(adaptation_sets.size(), 1u);
67 return adaptation_sets.front();
72 const std::string language = GetLanguage(media_info);
73 std::unique_ptr<AdaptationSet> new_adaptation_set =
74 NewAdaptationSet(language, mpd_options_, representation_counter_);
75 if (!SetNewAdaptationSetAttributes(language, media_info, adaptation_sets,
76 new_adaptation_set.get())) {
80 if (content_protection_in_adaptation_set &&
81 media_info.has_protected_content()) {
82 protected_adaptation_set_map_.Register(*new_adaptation_set, media_info);
86 if (protected_adaptation_set_map_.Switchable(*adaptation_set,
87 *new_adaptation_set)) {
88 adaptation_set->AddAdaptationSetSwitching(new_adaptation_set.get());
89 new_adaptation_set->AddAdaptationSetSwitching(adaptation_set);
94 adaptation_sets.push_back(adaptation_set_ptr);
95 adaptation_sets_.emplace_back(std::move(new_adaptation_set));
96 return adaptation_set_ptr;
100 adaptation_sets_.sort(
101 [](
const std::unique_ptr<AdaptationSet>& adaptation_set_a,
102 const std::unique_ptr<AdaptationSet>& adaptation_set_b) {
103 if (!adaptation_set_a->has_id())
105 if (!adaptation_set_b->has_id())
107 return adaptation_set_a->id() < adaptation_set_b->id();
115 for (
const auto& adaptation_set : adaptation_sets_) {
116 xml::scoped_xml_ptr<xmlNode> child(adaptation_set->GetXml());
117 if (!child || !period.
AddChild(std::move(child)))
121 if (output_period_duration) {
123 SecondsToXmlDuration(duration_seconds_));
124 }
else if (mpd_options_.mpd_type == MpdType::kDynamic) {
126 SecondsToXmlDuration(start_time_in_seconds_));
132 std::list<AdaptationSet*> adaptation_sets;
133 for (
const auto& adaptation_set : adaptation_sets_) {
134 adaptation_sets.push_back(adaptation_set.get());
136 return adaptation_sets;
139 std::unique_ptr<AdaptationSet> Period::NewAdaptationSet(
140 const std::string& language,
142 base::AtomicSequenceNumber* representation_counter) {
143 return std::unique_ptr<AdaptationSet>(
144 new AdaptationSet(language, options, representation_counter));
147 bool Period::SetNewAdaptationSetAttributes(
148 const std::string& language,
149 const MediaInfo& media_info,
150 const std::list<AdaptationSet*>& adaptation_sets,
152 if (!language.empty() && language == mpd_options_.mpd_params.
default_language)
153 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
155 if (media_info.has_video_info()) {
158 if (adaptation_sets.size() > 1) {
159 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
160 }
else if (adaptation_sets.size() == 1) {
161 (*adaptation_sets.begin())->AddRole(AdaptationSet::kRoleMain);
162 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
165 if (media_info.video_info().has_playback_rate()) {
167 FindOriginalAdaptationSetForTrickPlay(media_info);
168 if (!trick_play_reference_adaptation_set) {
169 LOG(ERROR) <<
"Failed to find original AdaptationSet for trick play.";
173 trick_play_reference_adaptation_set);
175 }
else if (media_info.has_text_info()) {
184 const AdaptationSet* Period::FindOriginalAdaptationSetForTrickPlay(
185 const MediaInfo& media_info) {
186 MediaInfo media_info_no_trickplay = media_info;
187 media_info_no_trickplay.mutable_video_info()->clear_playback_rate();
189 std::string key = GetAdaptationSetKey(media_info_no_trickplay);
190 const std::list<AdaptationSet*>& adaptation_sets =
191 adaptation_set_list_map_[key];
193 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info)) {
194 return adaptation_set;
200 void Period::ProtectedAdaptationSetMap::Register(
202 const MediaInfo& media_info) {
203 DCHECK(!ContainsKey(protected_content_map_, &adaptation_set));
204 protected_content_map_[&adaptation_set] = media_info.protected_content();
207 bool Period::ProtectedAdaptationSetMap::Match(
209 const MediaInfo& media_info) {
210 const auto protected_content_it =
211 protected_content_map_.find(&adaptation_set);
214 if (protected_content_it == protected_content_map_.end())
215 return !media_info.has_protected_content();
216 if (!media_info.has_protected_content())
218 return ProtectedContentEq(protected_content_it->second,
219 media_info.protected_content());
222 bool Period::ProtectedAdaptationSetMap::Switchable(
225 const auto protected_content_it_a =
226 protected_content_map_.find(&adaptation_set_a);
227 const auto protected_content_it_b =
228 protected_content_map_.find(&adaptation_set_b);
230 if (protected_content_it_a == protected_content_map_.end())
231 return protected_content_it_b == protected_content_map_.end();
232 if (protected_content_it_b == protected_content_map_.end())
236 return GetUUIDs(protected_content_it_a->second) ==
237 GetUUIDs(protected_content_it_b->second);
std::string default_language
virtual AdaptationSet * GetOrCreateAdaptationSet(const MediaInfo &media_info, bool content_protection_in_adaptation_set)
scoped_xml_ptr< xmlNode > PassScopedPtr()
All the methods that are virtual are virtual for mocking.
void SetStringAttribute(const char *attribute_name, const std::string &attribute)
bool AddChild(scoped_xml_ptr< xmlNode > child)
virtual void AddRole(Role role)
xml::scoped_xml_ptr< xmlNode > GetXml(bool output_period_duration)
void AddContentProtectionElements(const MediaInfo &media_info, Representation *parent)
virtual void ForceSetSegmentAlignment(bool segment_alignment)
const std::list< AdaptationSet * > GetAdaptationSets() const
Period(uint32_t period_id, double start_time_in_seconds, const MpdOptions &mpd_options, base::AtomicSequenceNumber *representation_counter)
virtual void AddTrickPlayReference(const AdaptationSet *adaptation_set)