diff --git a/packager/mpd/base/dash_iop_mpd_notifier.cc b/packager/mpd/base/dash_iop_mpd_notifier.cc index 2b3daa5f62..25900c06fd 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier.cc +++ b/packager/mpd/base/dash_iop_mpd_notifier.cc @@ -248,6 +248,18 @@ AdaptationSet* DashIopMpdNotifier::NewAdaptationSet( AddContentProtectionElements(media_info, new_adaptation_set); } adaptation_sets->push_back(new_adaptation_set); + + if (media_info.has_video_info()) { + // Because 'lang' is ignored for videos, |adaptation_sets| must have + // all the video AdaptationSets. + if (adaptation_sets->size() > 2) { + new_adaptation_set->AddRole(AdaptationSet::kRoleMain); + } else if (adaptation_sets->size() == 2) { + // Set "main" Role for both AdaptatoinSets. + (*adaptation_sets->begin())->AddRole(AdaptationSet::kRoleMain); + new_adaptation_set->AddRole(AdaptationSet::kRoleMain); + } + } return new_adaptation_set; } diff --git a/packager/mpd/base/dash_iop_mpd_notifier.h b/packager/mpd/base/dash_iop_mpd_notifier.h index 7d4c00cc8c..859f21d5b9 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier.h +++ b/packager/mpd/base/dash_iop_mpd_notifier.h @@ -22,8 +22,10 @@ namespace edash_packager { /// This class is an MpdNotifier which will try its best to generate a /// DASH IF IOPv3 compliant MPD. -/// For example, all elements must be right under +/// e.g. +/// All elements must be right under /// and cannot be under . +/// All video Adaptation Sets have Role set to "main". class DashIopMpdNotifier : public MpdNotifier { public: DashIopMpdNotifier(DashProfile dash_profile, diff --git a/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc b/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc index b25bc4ba30..39c559f648 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc +++ b/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc @@ -165,6 +165,7 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainer) { EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) .WillOnce(Return(default_mock_adaptation_set_.get())); + EXPECT_CALL(*default_mock_adaptation_set_, AddRole(_)).Times(0); EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_)) .WillOnce(Return(default_mock_representation_.get())); @@ -286,6 +287,11 @@ TEST_P(DashIopMpdNotifierTest, .WillOnce(Return(hd_adaptation_set.get())); // Called twice for the same reason as above. EXPECT_CALL(*hd_adaptation_set, AddContentProtectionElement(_)).Times(2); + + // Add main Role here for both. + EXPECT_CALL(*sd_adaptation_set, AddRole(AdaptationSet::kRoleMain)); + EXPECT_CALL(*hd_adaptation_set, AddRole(AdaptationSet::kRoleMain)); + EXPECT_CALL(*hd_adaptation_set, AddRepresentation(_)) .WillOnce(Return(hd_representation.get())); @@ -382,6 +388,7 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) { AddContentProtectionElement(ContentProtectionElementEq(mp4_protection))); EXPECT_CALL(*default_mock_adaptation_set_, AddContentProtectionElement(ContentProtectionElementEq(my_drm))); + EXPECT_CALL(*default_mock_adaptation_set_, AddRole(_)).Times(0); EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_)) .WillOnce(Return(sd_representation.get())); if (mpd_type() == MpdBuilder::kStatic) @@ -392,6 +399,7 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) { EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)).Times(0); EXPECT_CALL(*default_mock_adaptation_set_, AddContentProtectionElement(_)) .Times(0); + EXPECT_CALL(*default_mock_adaptation_set_, AddRole(_)).Times(0); EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_)) .WillOnce(Return(hd_representation.get())); if (mpd_type() == MpdBuilder::kStatic) @@ -635,12 +643,12 @@ TEST_P(DashIopMpdNotifierTest, DoNotSetGroupIfContentTypesDifferent) { "container_type: 1\n" "media_duration_seconds: 10.5\n"; - const uint32_t kSdAdaptationSetId = 6u; - const uint32_t kHdAdaptationSetId = 7u; + const uint32_t kVideoAdaptationSetId = 6u; + const uint32_t kAudioAdaptationSetId = 7u; scoped_ptr video_adaptation_set( - new MockAdaptationSet(kSdAdaptationSetId)); + new MockAdaptationSet(kVideoAdaptationSetId)); scoped_ptr audio_adaptation_set( - new MockAdaptationSet(kHdAdaptationSetId)); + new MockAdaptationSet(kAudioAdaptationSetId)); ON_CALL(*video_adaptation_set, Group()) .WillByDefault(Return(kDefaultGroupId)); @@ -651,27 +659,29 @@ TEST_P(DashIopMpdNotifierTest, DoNotSetGroupIfContentTypesDifferent) { EXPECT_CALL(*video_adaptation_set, SetGroup(_)).Times(0); EXPECT_CALL(*audio_adaptation_set, SetGroup(_)).Times(0); - const uint32_t kSdRepresentation = 8u; - const uint32_t kHdRepresentation = 9u; - scoped_ptr sd_representation( - new MockRepresentation(kSdRepresentation)); - scoped_ptr hd_representation( - new MockRepresentation(kHdRepresentation)); + const uint32_t kVideoRepresentation = 8u; + const uint32_t kAudioRepresentation = 9u; + scoped_ptr video_representation( + new MockRepresentation(kVideoRepresentation)); + scoped_ptr audio_representation( + new MockRepresentation(kAudioRepresentation)); InSequence in_sequence; EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) .WillOnce(Return(video_adaptation_set.get())); EXPECT_CALL(*video_adaptation_set, AddContentProtectionElement(_)).Times(2); + EXPECT_CALL(*video_adaptation_set, AddRole(_)).Times(0); EXPECT_CALL(*video_adaptation_set, AddRepresentation(_)) - .WillOnce(Return(sd_representation.get())); + .WillOnce(Return(video_representation.get())); if (mpd_type() == MpdBuilder::kStatic) EXPECT_CALL(*mock_mpd_builder, ToString(_)).WillOnce(Return(true)); EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) .WillOnce(Return(audio_adaptation_set.get())); EXPECT_CALL(*audio_adaptation_set, AddContentProtectionElement(_)).Times(2); + EXPECT_CALL(*audio_adaptation_set, AddRole(_)).Times(0); EXPECT_CALL(*audio_adaptation_set, AddRepresentation(_)) - .WillOnce(Return(hd_representation.get())); + .WillOnce(Return(audio_representation.get())); if (mpd_type() == MpdBuilder::kStatic) EXPECT_CALL(*mock_mpd_builder, ToString(_)).WillOnce(Return(true)); diff --git a/packager/mpd/base/mock_mpd_builder.h b/packager/mpd/base/mock_mpd_builder.h index 76e66d3d46..eed8bde477 100644 --- a/packager/mpd/base/mock_mpd_builder.h +++ b/packager/mpd/base/mock_mpd_builder.h @@ -35,6 +35,7 @@ class MockAdaptationSet : public AdaptationSet { MOCK_METHOD1(AddRepresentation, Representation*(const MediaInfo& media_info)); MOCK_METHOD1(AddContentProtectionElement, void(const ContentProtectionElement& element)); + MOCK_METHOD1(AddRole, void(AdaptationSet::Role role)); MOCK_METHOD1(SetGroup, void(int group_number)); MOCK_CONST_METHOD0(Group, int()); diff --git a/packager/mpd/base/mpd_builder.h b/packager/mpd/base/mpd_builder.h index 359d83711f..dca550c9fb 100644 --- a/packager/mpd/base/mpd_builder.h +++ b/packager/mpd/base/mpd_builder.h @@ -194,7 +194,7 @@ class AdaptationSet { /// The Role element's is schemeIdUri='urn:mpeg:dash:role:2011'. /// See ISO/IEC 23009-1:2012 section 5.8.5.5. /// @param role of this AdaptationSet. - void AddRole(Role role); + virtual void AddRole(Role role); /// Makes a copy of AdaptationSet xml element with its child Representation /// and ContentProtection elements.