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;
48 double start_time_in_seconds,
50 uint32_t* representation_counter)
52 start_time_in_seconds_(start_time_in_seconds),
53 mpd_options_(mpd_options),
54 representation_counter_(representation_counter) {}
57 const MediaInfo& media_info,
58 bool content_protection_in_adaptation_set) {
61 if (duration_seconds_ == 0)
62 duration_seconds_ = media_info.media_duration_seconds();
67 const std::string key = GetAdaptationSetKey(media_info);
68 std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
69 if (content_protection_in_adaptation_set) {
71 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info))
72 return adaptation_set;
75 if (!adaptation_sets.empty()) {
76 DCHECK_EQ(adaptation_sets.size(), 1u);
77 return adaptation_sets.front();
82 const std::string language = GetLanguage(media_info);
83 std::unique_ptr<AdaptationSet> new_adaptation_set =
84 NewAdaptationSet(language, mpd_options_, representation_counter_);
85 if (!SetNewAdaptationSetAttributes(language, media_info, adaptation_sets,
86 new_adaptation_set.get())) {
90 if (content_protection_in_adaptation_set &&
91 media_info.has_protected_content()) {
92 protected_adaptation_set_map_.Register(*new_adaptation_set, media_info);
96 if (protected_adaptation_set_map_.Switchable(*adaptation_set,
97 *new_adaptation_set)) {
98 adaptation_set->AddAdaptationSetSwitching(new_adaptation_set.get());
99 new_adaptation_set->AddAdaptationSetSwitching(adaptation_set);
103 AdaptationSet* adaptation_set_ptr = new_adaptation_set.get();
104 adaptation_sets.push_back(adaptation_set_ptr);
105 adaptation_sets_.emplace_back(std::move(new_adaptation_set));
106 return adaptation_set_ptr;
110 adaptation_sets_.sort(
111 [](
const std::unique_ptr<AdaptationSet>& adaptation_set_a,
112 const std::unique_ptr<AdaptationSet>& adaptation_set_b) {
113 if (!adaptation_set_a->has_id())
115 if (!adaptation_set_b->has_id())
117 return adaptation_set_a->id() < adaptation_set_b->id();
125 for (
const auto& adaptation_set : adaptation_sets_) {
126 xml::scoped_xml_ptr<xmlNode> child(adaptation_set->GetXml());
127 if (!child || !period.
AddChild(std::move(child)))
131 if (output_period_duration) {
133 SecondsToXmlDuration(duration_seconds_));
134 }
else if (mpd_options_.mpd_type == MpdType::kDynamic) {
136 SecondsToXmlDuration(start_time_in_seconds_));
142 std::list<AdaptationSet*> adaptation_sets;
143 for (
const auto& adaptation_set : adaptation_sets_) {
144 adaptation_sets.push_back(adaptation_set.get());
146 return adaptation_sets;
149 std::unique_ptr<AdaptationSet> Period::NewAdaptationSet(
150 const std::string& language,
152 uint32_t* representation_counter) {
153 return std::unique_ptr<AdaptationSet>(
154 new AdaptationSet(language, options, representation_counter));
157 bool Period::SetNewAdaptationSetAttributes(
158 const std::string& language,
159 const MediaInfo& media_info,
160 const std::list<AdaptationSet*>& adaptation_sets,
162 if (!language.empty()) {
163 const bool is_main_role =
164 language == (media_info.has_audio_info()
165 ? GetDefaultAudioLanguage(mpd_options_)
166 : GetDefaultTextLanguage(mpd_options_));
168 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
171 if (media_info.has_video_info()) {
174 if (adaptation_sets.size() > 1) {
175 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
176 }
else if (adaptation_sets.size() == 1) {
177 (*adaptation_sets.begin())->AddRole(AdaptationSet::kRoleMain);
178 new_adaptation_set->
AddRole(AdaptationSet::kRoleMain);
181 if (media_info.video_info().has_playback_rate()) {
183 FindOriginalAdaptationSetForTrickPlay(media_info);
184 if (!trick_play_reference_adaptation_set) {
185 LOG(ERROR) <<
"Failed to find original AdaptationSet for trick play.";
189 trick_play_reference_adaptation_set);
191 }
else if (media_info.has_text_info()) {
200 const AdaptationSet* Period::FindOriginalAdaptationSetForTrickPlay(
201 const MediaInfo& media_info) {
202 MediaInfo media_info_no_trickplay = media_info;
203 media_info_no_trickplay.mutable_video_info()->clear_playback_rate();
205 std::string key = GetAdaptationSetKey(media_info_no_trickplay);
206 const std::list<AdaptationSet*>& adaptation_sets =
207 adaptation_set_list_map_[key];
209 if (protected_adaptation_set_map_.Match(*adaptation_set, media_info)) {
210 return adaptation_set;
216 void Period::ProtectedAdaptationSetMap::Register(
218 const MediaInfo& media_info) {
219 DCHECK(!ContainsKey(protected_content_map_, &adaptation_set));
220 protected_content_map_[&adaptation_set] = media_info.protected_content();
223 bool Period::ProtectedAdaptationSetMap::Match(
225 const MediaInfo& media_info) {
226 const auto protected_content_it =
227 protected_content_map_.find(&adaptation_set);
230 if (protected_content_it == protected_content_map_.end())
231 return !media_info.has_protected_content();
232 if (!media_info.has_protected_content())
234 return ProtectedContentEq(protected_content_it->second,
235 media_info.protected_content());
238 bool Period::ProtectedAdaptationSetMap::Switchable(
241 const auto protected_content_it_a =
242 protected_content_map_.find(&adaptation_set_a);
243 const auto protected_content_it_b =
244 protected_content_map_.find(&adaptation_set_b);
246 if (protected_content_it_a == protected_content_map_.end())
247 return protected_content_it_b == protected_content_map_.end();
248 if (protected_content_it_b == protected_content_map_.end())
252 return GetUUIDs(protected_content_it_a->second) ==
253 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)
const std::list< AdaptationSet * > GetAdaptationSets() const
virtual void AddTrickPlayReference(const AdaptationSet *adaptation_set)