diff --git a/packager/mpd/base/adaptation_set.cc b/packager/mpd/base/adaptation_set.cc index 4c9802dca0..52ef7f5569 100644 --- a/packager/mpd/base/adaptation_set.cc +++ b/packager/mpd/base/adaptation_set.cc @@ -189,11 +189,73 @@ AdaptationSet::AdaptationSet(const std::string& language, uint32_t* counter) : representation_counter_(counter), language_(language), - mpd_options_(mpd_options) { + mpd_options_(mpd_options), + protected_content_(nullptr) { DCHECK(counter); } -AdaptationSet::~AdaptationSet() {} +AdaptationSet::~AdaptationSet() { + delete protected_content_; +} + +void AdaptationSet::set_protected_content(const MediaInfo& media_info) { + DCHECK(!protected_content_); + protected_content_ = + new MediaInfo::ProtectedContent(media_info.protected_content()); +} + +// The easiest way to check whether two protobufs are equal, is to compare the +// serialized version. +bool ProtectedContentEq( + const MediaInfo::ProtectedContent& content_protection1, + const MediaInfo::ProtectedContent& content_protection2) { + return content_protection1.SerializeAsString() == + content_protection2.SerializeAsString(); +} + +bool AdaptationSet::MatchAdaptationSet( + const MediaInfo& media_info, + bool content_protection_in_adaptation_set) { + if (codec_ != GetBaseCodec(media_info)) + return false; + + if (!content_protection_in_adaptation_set) + return true; + + if (!protected_content_) + return !media_info.has_protected_content(); + + if (!media_info.has_protected_content()) + return false; + + return ProtectedContentEq(*protected_content_, + media_info.protected_content()); +} + +std::set GetUUIDs( + const MediaInfo::ProtectedContent* protected_content) { + std::set uuids; + for (const auto& entry : protected_content->content_protection_entry()) + uuids.insert(entry.uuid()); + return uuids; +} + +bool AdaptationSet::SwitchableAdaptationSet( + const AdaptationSet& adaptation_set) { + + // adaptation sets are switchable if both are not protected + if (!protected_content_ && !adaptation_set.protected_content()) { + return true; + } + + // or if both are protected and have the same UUID + if (protected_content_ && adaptation_set.protected_content()) { + return GetUUIDs(protected_content_) == + GetUUIDs(adaptation_set.protected_content()); + } + + return false; +} Representation* AdaptationSet::AddRepresentation(const MediaInfo& media_info) { const uint32_t representation_id = media_info.has_index() diff --git a/packager/mpd/base/adaptation_set.h b/packager/mpd/base/adaptation_set.h index 7401254c72..d2bf228a0a 100644 --- a/packager/mpd/base/adaptation_set.h +++ b/packager/mpd/base/adaptation_set.h @@ -18,6 +18,7 @@ #include #include +#include "packager/mpd/base/media_info.pb.h" namespace shaka { @@ -208,6 +209,29 @@ class AdaptationSet { transfer_characteristics_ = transfer_characteristics; }; + /// Return ProtectedContent. + const MediaInfo::ProtectedContent* protected_content() const { + return protected_content_; + }; + + /// Set AdaptationSet@protected_content. + /// @param media_info to extract the ProtectedContent from. + void set_protected_content(const MediaInfo& media_info); + + /// Check if the protected content associated with this AdaptationSet matches + /// with the one in |media_info|. + /// @param media_info to extract ProtectedContent from. + /// @param content_protection_in_adaptation_set to indicate if there is + /// protected content in AdaptationSet. + /// @return true if there is a match. + bool MatchAdaptationSet(const MediaInfo& media_info, + bool content_protection_in_adaptation_set); + + /// Check if the adaptation sets are switchable. + /// @param adaptation_set to compare this AdaptationSet with. + /// @return true if AdaptationSets are switchable. + bool SwitchableAdaptationSet(const AdaptationSet& adaptation_set); + protected: /// @param language is the language of this AdaptationSet. Mainly relevant for /// audio. @@ -357,6 +381,9 @@ class AdaptationSet { // The label of this AdaptationSet. std::string label_; + + // ProtectedContent of this AdaptationSet. + MediaInfo::ProtectedContent* protected_content_; }; } // namespace shaka diff --git a/packager/mpd/base/period.cc b/packager/mpd/base/period.cc index 6c9033fa29..249bbdb961 100644 --- a/packager/mpd/base/period.cc +++ b/packager/mpd/base/period.cc @@ -17,23 +17,6 @@ namespace shaka { namespace { -// The easiest way to check whether two protobufs are equal, is to compare the -// serialized version. -bool ProtectedContentEq( - const MediaInfo::ProtectedContent& content_protection1, - const MediaInfo::ProtectedContent& content_protection2) { - return content_protection1.SerializeAsString() == - content_protection2.SerializeAsString(); -} - -std::set GetUUIDs( - const MediaInfo::ProtectedContent& protected_content) { - std::set uuids; - for (const auto& entry : protected_content.content_protection_entry()) - uuids.insert(entry.uuid()); - return uuids; -} - const std::string& GetDefaultAudioLanguage(const MpdOptions& mpd_options) { return mpd_options.mpd_params.default_language; } @@ -91,8 +74,8 @@ AdaptationSet* Period::GetOrCreateAdaptationSet( std::list& adaptation_sets = adaptation_set_list_map_[key]; for (AdaptationSet* adaptation_set : adaptation_sets) { - if (protected_adaptation_set_map_.Match( - *adaptation_set, media_info, content_protection_in_adaptation_set)) + if (adaptation_set->MatchAdaptationSet( + media_info, content_protection_in_adaptation_set)) return adaptation_set; } @@ -107,14 +90,8 @@ AdaptationSet* Period::GetOrCreateAdaptationSet( return nullptr; } - if (content_protection_in_adaptation_set && - media_info.has_protected_content()) { - protected_adaptation_set_map_.Register(*new_adaptation_set, media_info); - AddContentProtectionElements(media_info, new_adaptation_set.get()); - } for (AdaptationSet* adaptation_set : adaptation_sets) { - if (protected_adaptation_set_map_.Switchable(*adaptation_set, - *new_adaptation_set)) { + if (adaptation_set->SwitchableAdaptationSet(*new_adaptation_set)) { adaptation_set->AddAdaptationSetSwitching(new_adaptation_set.get()); new_adaptation_set->AddAdaptationSetSwitching(adaptation_set); } @@ -307,6 +284,13 @@ bool Period::SetNewAdaptationSetAttributes( // In practice it doesn't really make sense to adapt between text tracks. new_adaptation_set->ForceSetSegmentAlignment(true); } + + if (content_protection_in_adaptation_set && + media_info.has_protected_content()) { + new_adaptation_set->set_protected_content(media_info); + AddContentProtectionElements(media_info, new_adaptation_set); + } + return true; } @@ -331,11 +315,9 @@ AdaptationSet* Period::FindMatchingAdaptationSetForTrickPlay( adaptation_sets = &trickplay_cache_[*adaptation_set_key]; } for (AdaptationSet* adaptation_set : *adaptation_sets) { - if (protected_adaptation_set_map_.Match( - *adaptation_set, media_info, - content_protection_in_adaptation_set)) { + if (adaptation_set->MatchAdaptationSet( + media_info, content_protection_in_adaptation_set)) return adaptation_set; - } } return nullptr; @@ -349,55 +331,6 @@ std::string Period::GetAdaptationSetKeyForTrickPlay( mpd_options_.mpd_params.allow_codec_switching); } -void Period::ProtectedAdaptationSetMap::Register( - const AdaptationSet& adaptation_set, - const MediaInfo& media_info) { - CHECK(protected_content_map_.find(&adaptation_set) == - protected_content_map_.end()); - protected_content_map_[&adaptation_set] = media_info.protected_content(); -} - -bool Period::ProtectedAdaptationSetMap::Match( - const AdaptationSet& adaptation_set, - const MediaInfo& media_info, - bool content_protection_in_adaptation_set) { - if (adaptation_set.codec() != GetBaseCodec(media_info)) - return false; - - if (!content_protection_in_adaptation_set) - return true; - - const auto protected_content_it = - protected_content_map_.find(&adaptation_set); - // If the AdaptationSet ID is not registered in the map, then it is clear - // content. - if (protected_content_it == protected_content_map_.end()) - return !media_info.has_protected_content(); - if (!media_info.has_protected_content()) - return false; - - return ProtectedContentEq(protected_content_it->second, - media_info.protected_content()); -} - -bool Period::ProtectedAdaptationSetMap::Switchable( - const AdaptationSet& adaptation_set_a, - const AdaptationSet& adaptation_set_b) { - const auto protected_content_it_a = - protected_content_map_.find(&adaptation_set_a); - const auto protected_content_it_b = - protected_content_map_.find(&adaptation_set_b); - - if (protected_content_it_a == protected_content_map_.end()) - return protected_content_it_b == protected_content_map_.end(); - if (protected_content_it_b == protected_content_map_.end()) - return false; - // Get all the UUIDs of the AdaptationSet. If another AdaptationSet has the - // same UUIDs then those are switchable. - return GetUUIDs(protected_content_it_a->second) == - GetUUIDs(protected_content_it_b->second); -} - Period::~Period() { if (!trickplay_cache_.empty()) { LOG(WARNING) << "Trickplay adaptation set did not get a valid adaptation " diff --git a/packager/mpd/base/period.h b/packager/mpd/base/period.h index fb505766e6..7eae7705f3 100644 --- a/packager/mpd/base/period.h +++ b/packager/mpd/base/period.h @@ -133,33 +133,6 @@ class Period { // grouping key. These AdaptationSets still have not found reference // AdaptationSet. std::map> trickplay_cache_; - - // Tracks ProtectedContent in AdaptationSet. - class ProtectedAdaptationSetMap { - public: - ProtectedAdaptationSetMap() = default; - // Register the |adaptation_set| with associated |media_info| in the map. - void Register(const AdaptationSet& adaptation_set, - const MediaInfo& media_info); - // Check if the protected content associated with |adaptation_set| matches - // with the one in |media_info|. - bool Match(const AdaptationSet& adaptation_set, - const MediaInfo& media_info, - bool content_protection_in_adaptation_set); - // Check if the two adaptation sets are switchable. - bool Switchable(const AdaptationSet& adaptation_set_a, - const AdaptationSet& adaptation_set_b); - - private: - ProtectedAdaptationSetMap(const ProtectedAdaptationSetMap&) = delete; - ProtectedAdaptationSetMap& operator=(const ProtectedAdaptationSetMap&) = - delete; - - // AdaptationSet => ProtectedContent map. - std::map - protected_content_map_; - }; - ProtectedAdaptationSetMap protected_adaptation_set_map_; }; } // namespace shaka