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());
35 const std::string& GetDefaultAudioLanguage(
const MpdOptions& mpd_options) {
36 return mpd_options.mpd_params.default_language;
39 const std::string& GetDefaultTextLanguage(
const MpdOptions& mpd_options) {
40 return mpd_options.mpd_params.default_text_language.empty()
41 ? mpd_options.mpd_params.default_language
42 : mpd_options.mpd_params.default_text_language;
45 AdaptationSet::Role RoleFromString(
const std::string& role_str) {
46 if (role_str ==
"caption")
47 return AdaptationSet::Role::kRoleCaption;
48 if (role_str ==
"subtitle")
49 return AdaptationSet::Role::kRoleSubtitle;
50 if (role_str ==
"main")
51 return AdaptationSet::Role::kRoleMain;
52 if (role_str ==
"alternate")
53 return AdaptationSet::Role::kRoleAlternate;
54 if (role_str ==
"supplementary")
55 return AdaptationSet::Role::kRoleSupplementary;
56 if (role_str ==
"commentary")
57 return AdaptationSet::Role::kRoleCommentary;
58 if (role_str ==
"dub")
59 return AdaptationSet::Role::kRoleDub;
60 return AdaptationSet::Role::kRoleUnknown;
66 double start_time_in_seconds,
68 uint32_t* representation_counter)
70 start_time_in_seconds_(start_time_in_seconds),
71 mpd_options_(mpd_options),
72 representation_counter_(representation_counter) {}
75 const MediaInfo& media_info,
76 bool content_protection_in_adaptation_set) {
79 if (duration_seconds_ == 0)
80 duration_seconds_ = media_info.media_duration_seconds();
85 const std::string key = GetAdaptationSetKey(media_info);
86 std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
87 if (content_protection_in_adaptation_set) {
89 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info))
90 return adaptation_set;
93 if (!adaptation_sets.empty()) {
94 DCHECK_EQ(adaptation_sets.size(), 1u);
95 return adaptation_sets.front();
100 const std::string language = GetLanguage(media_info);
101 std::unique_ptr<AdaptationSet> new_adaptation_set =
102 NewAdaptationSet(language, mpd_options_, representation_counter_);
103 if (!SetNewAdaptationSetAttributes(language, media_info, adaptation_sets,
104 new_adaptation_set.get())) {
108 if (content_protection_in_adaptation_set &&
109 media_info.has_protected_content()) {
110 protected_adaptation_set_map_.Register(*new_adaptation_set, media_info);
114 if (protected_adaptation_set_map_.Switchable(*adaptation_set,
115 *new_adaptation_set)) {
116 adaptation_set->AddAdaptationSetSwitching(new_adaptation_set.get());
117 new_adaptation_set->AddAdaptationSetSwitching(adaptation_set);
121 AdaptationSet* adaptation_set_ptr = new_adaptation_set.get();
122 adaptation_sets.push_back(adaptation_set_ptr);
123 adaptation_sets_.emplace_back(std::move(new_adaptation_set));
124 return adaptation_set_ptr;
128 adaptation_sets_.sort(
129 [](
const std::unique_ptr<AdaptationSet>& adaptation_set_a,
130 const std::unique_ptr<AdaptationSet>& adaptation_set_b) {
131 if (!adaptation_set_a->has_id())
133 if (!adaptation_set_b->has_id())
135 return adaptation_set_a->id() < adaptation_set_b->id();
143 for (
const auto& adaptation_set : adaptation_sets_) {
144 xml::scoped_xml_ptr<xmlNode> child(adaptation_set->GetXml());
145 if (!child || !period.
AddChild(std::move(child)))
149 if (output_period_duration) {
151 SecondsToXmlDuration(duration_seconds_));
152 }
else if (mpd_options_.mpd_type == MpdType::kDynamic) {
154 SecondsToXmlDuration(start_time_in_seconds_));
160 std::list<AdaptationSet*> adaptation_sets;
161 for (
const auto& adaptation_set : adaptation_sets_) {
162 adaptation_sets.push_back(adaptation_set.get());
164 return adaptation_sets;
167 std::unique_ptr<AdaptationSet> Period::NewAdaptationSet(
168 const std::string& language,
170 uint32_t* representation_counter) {
171 return std::unique_ptr<AdaptationSet>(
172 new AdaptationSet(language, options, representation_counter));
175 bool Period::SetNewAdaptationSetAttributes(
176 const std::string& language,
177 const MediaInfo& media_info,
178 const std::list<AdaptationSet*>& adaptation_sets,
180 if (!media_info.dash_roles().empty()) {
181 for (
const std::string& role_str : media_info.dash_roles()) {
182 AdaptationSet::Role role = RoleFromString(role_str);
183 if (role == AdaptationSet::kRoleUnknown) {
184 LOG(ERROR) <<
"Unrecognized role '" << role_str <<
"'.";
187 new_adaptation_set->
AddRole(role);
189 }
else if (!language.empty()) {
190 const bool is_main_role =
191 language == (media_info.has_audio_info()
192 ? GetDefaultAudioLanguage(mpd_options_)
193 : GetDefaultTextLanguage(mpd_options_));
195 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
197 for (
const std::string& accessibility : media_info.dash_accessibilities()) {
198 size_t pos = accessibility.find(
'=');
199 if (pos == std::string::npos) {
201 <<
"Accessibility should be in scheme=value format, but seeing " 206 accessibility.substr(pos + 1));
209 if (media_info.has_video_info()) {
212 if (adaptation_sets.size() > 1) {
213 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
214 }
else if (adaptation_sets.size() == 1) {
215 (*adaptation_sets.begin())->AddRole(AdaptationSet::kRoleMain);
216 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
219 if (media_info.video_info().has_playback_rate()) {
221 FindOriginalAdaptationSetForTrickPlay(media_info);
222 if (!trick_play_reference_adaptation_set) {
223 LOG(ERROR) <<
"Failed to find original AdaptationSet for trick play.";
227 trick_play_reference_adaptation_set);
229 }
else if (media_info.has_text_info()) {
238 const AdaptationSet* Period::FindOriginalAdaptationSetForTrickPlay(
239 const MediaInfo& media_info) {
240 MediaInfo media_info_no_trickplay = media_info;
241 media_info_no_trickplay.mutable_video_info()->clear_playback_rate();
243 std::string key = GetAdaptationSetKey(media_info_no_trickplay);
244 const std::list<AdaptationSet*>& adaptation_sets =
245 adaptation_set_list_map_[key];
247 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info)) {
248 return adaptation_set;
254 void Period::ProtectedAdaptationSetMap::Register(
256 const MediaInfo& media_info) {
257 DCHECK(!ContainsKey(protected_content_map_, &adaptation_set));
258 protected_content_map_[&adaptation_set] = media_info.protected_content();
261 bool Period::ProtectedAdaptationSetMap::Match(
263 const MediaInfo& media_info) {
264 const auto protected_content_it =
265 protected_content_map_.find(&adaptation_set);
268 if (protected_content_it == protected_content_map_.end())
269 return !media_info.has_protected_content();
270 if (!media_info.has_protected_content())
272 return ProtectedContentEq(protected_content_it->second,
273 media_info.protected_content());
276 bool Period::ProtectedAdaptationSetMap::Switchable(
279 const auto protected_content_it_a =
280 protected_content_map_.find(&adaptation_set_a);
281 const auto protected_content_it_b =
282 protected_content_map_.find(&adaptation_set_b);
284 if (protected_content_it_a == protected_content_map_.end())
285 return protected_content_it_b == protected_content_map_.end();
286 if (protected_content_it_b == protected_content_map_.end())
290 return GetUUIDs(protected_content_it_a->second) ==
291 GetUUIDs(protected_content_it_b->second);
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)
Period(uint32_t period_id, double start_time_in_seconds, const MpdOptions &mpd_options, uint32_t *representation_counter)
virtual void AddAccessibility(const std::string &scheme, const std::string &value)
const std::list< AdaptationSet * > GetAdaptationSets() const
virtual void AddTrickPlayReference(const AdaptationSet *adaptation_set)