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) {
52 const std::string key = GetAdaptationSetKey(media_info);
53 std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
54 if (content_protection_in_adaptation_set) {
56 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info))
57 return adaptation_set;
60 if (!adaptation_sets.empty()) {
61 DCHECK_EQ(adaptation_sets.size(), 1u);
62 return adaptation_sets.front();
67 const std::string language = GetLanguage(media_info);
68 std::unique_ptr<AdaptationSet> new_adaptation_set =
69 NewAdaptationSet(language, mpd_options_, representation_counter_);
70 if (!SetNewAdaptationSetAttributes(language, media_info, adaptation_sets,
71 new_adaptation_set.get())) {
75 if (content_protection_in_adaptation_set &&
76 media_info.has_protected_content()) {
77 protected_adaptation_set_map_.Register(*new_adaptation_set, media_info);
81 if (protected_adaptation_set_map_.Switchable(*adaptation_set,
82 *new_adaptation_set)) {
83 adaptation_set->AddAdaptationSetSwitching(new_adaptation_set.get());
84 new_adaptation_set->AddAdaptationSetSwitching(adaptation_set);
89 adaptation_sets.push_back(adaptation_set_ptr);
90 adaptation_sets_.emplace_back(std::move(new_adaptation_set));
91 return adaptation_set_ptr;
95 adaptation_sets_.sort(
96 [](
const std::unique_ptr<AdaptationSet>& adaptation_set_a,
97 const std::unique_ptr<AdaptationSet>& adaptation_set_b) {
98 if (!adaptation_set_a->has_id())
100 if (!adaptation_set_b->has_id())
102 return adaptation_set_a->id() < adaptation_set_b->id();
110 for (
const auto& adaptation_set : adaptation_sets_) {
111 xml::scoped_xml_ptr<xmlNode> child(adaptation_set->GetXml());
112 if (!child || !period.
AddChild(std::move(child)))
116 if (output_period_duration) {
118 SecondsToXmlDuration(duration_seconds_));
119 }
else if (mpd_options_.mpd_type == MpdType::kDynamic) {
121 SecondsToXmlDuration(start_time_in_seconds_));
127 std::list<AdaptationSet*> adaptation_sets;
128 for (
const auto& adaptation_set : adaptation_sets_) {
129 adaptation_sets.push_back(adaptation_set.get());
131 return adaptation_sets;
134 std::unique_ptr<AdaptationSet> Period::NewAdaptationSet(
135 const std::string& language,
137 base::AtomicSequenceNumber* representation_counter) {
138 return std::unique_ptr<AdaptationSet>(
139 new AdaptationSet(language, options, representation_counter));
142 bool Period::SetNewAdaptationSetAttributes(
143 const std::string& language,
144 const MediaInfo& media_info,
145 const std::list<AdaptationSet*>& adaptation_sets,
147 if (!language.empty() && language == mpd_options_.mpd_params.
default_language)
148 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
150 if (media_info.has_video_info()) {
153 if (adaptation_sets.size() > 1) {
154 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
155 }
else if (adaptation_sets.size() == 1) {
156 (*adaptation_sets.begin())->AddRole(AdaptationSet::kRoleMain);
157 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
160 if (media_info.video_info().has_playback_rate()) {
162 FindOriginalAdaptationSetForTrickPlay(media_info);
163 if (!trick_play_reference_adaptation_set) {
164 LOG(ERROR) <<
"Failed to find original AdaptationSet for trick play.";
168 trick_play_reference_adaptation_set);
170 }
else if (media_info.has_text_info()) {
179 const AdaptationSet* Period::FindOriginalAdaptationSetForTrickPlay(
180 const MediaInfo& media_info) {
181 MediaInfo media_info_no_trickplay = media_info;
182 media_info_no_trickplay.mutable_video_info()->clear_playback_rate();
184 std::string key = GetAdaptationSetKey(media_info_no_trickplay);
185 const std::list<AdaptationSet*>& adaptation_sets =
186 adaptation_set_list_map_[key];
188 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info)) {
189 return adaptation_set;
195 void Period::ProtectedAdaptationSetMap::Register(
197 const MediaInfo& media_info) {
198 DCHECK(!ContainsKey(protected_content_map_, &adaptation_set));
199 protected_content_map_[&adaptation_set] = media_info.protected_content();
202 bool Period::ProtectedAdaptationSetMap::Match(
204 const MediaInfo& media_info) {
205 const auto protected_content_it =
206 protected_content_map_.find(&adaptation_set);
209 if (protected_content_it == protected_content_map_.end())
210 return !media_info.has_protected_content();
211 if (!media_info.has_protected_content())
213 return ProtectedContentEq(protected_content_it->second,
214 media_info.protected_content());
217 bool Period::ProtectedAdaptationSetMap::Switchable(
220 const auto protected_content_it_a =
221 protected_content_map_.find(&adaptation_set_a);
222 const auto protected_content_it_b =
223 protected_content_map_.find(&adaptation_set_b);
225 if (protected_content_it_a == protected_content_map_.end())
226 return protected_content_it_b == protected_content_map_.end();
227 if (protected_content_it_b == protected_content_map_.end())
231 return GetUUIDs(protected_content_it_a->second) ==
232 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)