diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 8f6e69fb6d..9d6c4d7768 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -26,8 +26,6 @@ namespace shaka { namespace media { namespace { -} // namespace - std::unique_ptr CreateSigner(const WidevineSigner& signer) { std::unique_ptr request_signer; switch (signer.signing_key_type) { @@ -47,6 +45,8 @@ std::unique_ptr CreateSigner(const WidevineSigner& signer) { return request_signer; } +} // namespace + std::unique_ptr CreateEncryptionKeySource( FourCC protection_scheme, const EncryptionParams& encryption_params) { @@ -179,12 +179,7 @@ MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params) { (on_demand_profile || mpd_params.generate_static_live_mpd) ? MpdType::kStatic : MpdType::kDynamic; - mpd_options.minimum_update_period = mpd_params.minimum_update_period; - mpd_options.min_buffer_time = mpd_params.min_buffer_time; - mpd_options.time_shift_buffer_depth = mpd_params.time_shift_buffer_depth; - mpd_options.suggested_presentation_delay = - mpd_params.suggested_presentation_delay; - mpd_options.default_language = mpd_params.default_language; + mpd_options.mpd_params = mpd_params; return mpd_options; } diff --git a/packager/app/packager_util.h b/packager/app/packager_util.h index a08a0b17de..d6bff916f9 100644 --- a/packager/app/packager_util.h +++ b/packager/app/packager_util.h @@ -10,18 +10,15 @@ #define PACKAGER_APP_PACKAGER_UTIL_H_ #include +#include -#include "packager/base/optional.h" #include "packager/media/base/fourccs.h" -#include "packager/packager.h" namespace shaka { -// TODO(kqyang): Should we consolidate XxxParams and XxxOptions? -struct ChunkingParams; +class Status; struct DecryptionParams; struct EncryptionParams; -struct Mp4OutputParams; struct MpdOptions; struct MpdParams; @@ -29,12 +26,9 @@ namespace media { class MediaHandler; class KeySource; -struct ChunkingOptions; -struct EncryptionOptions; -struct MuxerOptions; -/// Create KeySource based on provided command line options for content -/// encryption. Also fetches keys. +/// Create KeySource based on provided params for content encryption. Also +/// fetches keys. /// @param protection_scheme specifies the protection scheme to be used for /// encryption. /// @return A std::unique_ptr containing a new KeySource, or nullptr if @@ -43,14 +37,14 @@ std::unique_ptr CreateEncryptionKeySource( FourCC protection_scheme, const EncryptionParams& encryption_params); -/// Create KeySource based on provided command line options for content -/// decryption. Does not fetch keys. +/// Create KeySource based on provided params for content decryption. Does not +/// fetch keys. /// @return A std::unique_ptr containing a new KeySource, or nullptr if /// decryption is not required. std::unique_ptr CreateDecryptionKeySource( const DecryptionParams& decryption_params); -/// @return MpdOptions from provided command line options. +/// @return MpdOptions from provided inputs. MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params); /// Connect handlers in the vector. diff --git a/packager/mpd/base/dash_iop_mpd_notifier.cc b/packager/mpd/base/dash_iop_mpd_notifier.cc index c28df2070f..af59b95675 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier.cc +++ b/packager/mpd/base/dash_iop_mpd_notifier.cc @@ -38,15 +38,12 @@ std::set GetUUIDs( } // namespace -DashIopMpdNotifier::DashIopMpdNotifier( - const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) +DashIopMpdNotifier::DashIopMpdNotifier(const MpdOptions& mpd_options) : MpdNotifier(mpd_options), - output_path_(output_path), + output_path_(mpd_options.mpd_params.mpd_output), mpd_builder_(new MpdBuilder(mpd_options)) { - for (size_t i = 0; i < base_urls.size(); ++i) - mpd_builder_->AddBaseUrl(base_urls[i]); + for (const std::string& base_url : mpd_options.mpd_params.base_urls) + mpd_builder_->AddBaseUrl(base_url); } DashIopMpdNotifier::~DashIopMpdNotifier() {} diff --git a/packager/mpd/base/dash_iop_mpd_notifier.h b/packager/mpd/base/dash_iop_mpd_notifier.h index 75d7347fd0..6338e11a58 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier.h +++ b/packager/mpd/base/dash_iop_mpd_notifier.h @@ -29,9 +29,7 @@ namespace shaka { /// All video Adaptation Sets have Role set to "main". class DashIopMpdNotifier : public MpdNotifier { public: - DashIopMpdNotifier(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path); + explicit DashIopMpdNotifier(const MpdOptions& mpd_options); ~DashIopMpdNotifier() override; /// None of the methods write out the MPD file until Flush() is called. diff --git a/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc b/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc index 1122498d6f..9c144390e0 100644 --- a/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc +++ b/packager/mpd/base/dash_iop_mpd_notifier_unittest.cc @@ -101,7 +101,7 @@ class DashIopMpdNotifierTest : public ::testing::Test { void SetUp() override { ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_)); - output_path_ = temp_file_path_.AsUTF8Unsafe(); + empty_mpd_option_.mpd_params.mpd_output = temp_file_path_.AsUTF8Unsafe(); } void TearDown() override { @@ -113,11 +113,9 @@ class DashIopMpdNotifierTest : public ::testing::Test { notifier->SetMpdBuilderForTesting(std::move(mpd_builder)); } - // Use output_path_ for specifying the MPD output path so that + // Empty mpd options except with output path specified, so that // WriteMpdToFile() doesn't crash. - std::string output_path_; - const MpdOptions empty_mpd_option_; - const std::vector empty_base_urls_; + MpdOptions empty_mpd_option_; // Default mocks that can be used for the tests. // IOW, if a test only requires one instance of @@ -132,8 +130,7 @@ class DashIopMpdNotifierTest : public ::testing::Test { // Verify that basic VOD NotifyNewContainer() operation works. // No encrypted contents. TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -170,8 +167,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerForTrickPlay) { " playback_rate: 10\n" "}\n" "container_type: 1\n"; - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -228,8 +224,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) { " language: 'en'\n" "}\n" "container_type: CONTAINER_TEXT\n"; - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -257,8 +252,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) { // AdaptationSets with different DRM won't be switchable. TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithDifferentProtectedContent) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); // Note they both have different (bogus) pssh, like real use case. @@ -375,8 +369,7 @@ TEST_F(DashIopMpdNotifierTest, // MediaInfo::ProtectedContent. Only one AdaptationSet should be // created. TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); // These have the same default key ID and PSSH. @@ -477,8 +470,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) { // AddContentProtection() should not work and should always return false. TEST_F(DashIopMpdNotifierTest, AddContentProtection) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -508,8 +500,7 @@ TEST_F(DashIopMpdNotifierTest, AddContentProtection) { // 3. Add a 4k protected content. This should also make a new AdaptationSet. // It should be switchable with SD/HD AdaptationSet. TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); // These have the same default key ID and PSSH. @@ -645,8 +636,7 @@ TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) { // switchable. TEST_F(DashIopMpdNotifierTest, DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); // These have the same default key ID and PSSH. @@ -752,8 +742,7 @@ TEST_F(DashIopMpdNotifierTest, UpdateEncryption) { "}\n" "container_type: 1\n"; - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -792,8 +781,7 @@ TEST_F(DashIopMpdNotifierTest, UpdateEncryption) { // This issue identified a bug where using SimpleMpdNotifier with multiple // threads causes a deadlock. This tests with DashIopMpdNotifier. TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) { - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); uint32_t container_id; EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo), &container_id)); @@ -856,8 +844,7 @@ TEST_F(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) { "container_type: CONTAINER_WEBM\n" "media_duration_seconds: 10.5\n"; - DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, - output_path_); + DashIopMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); std::unique_ptr adaptation_set1(new MockAdaptationSet(1)); diff --git a/packager/mpd/base/mpd_builder.cc b/packager/mpd/base/mpd_builder.cc index 2d7b005803..684e577afe 100644 --- a/packager/mpd/base/mpd_builder.cc +++ b/packager/mpd/base/mpd_builder.cc @@ -385,7 +385,7 @@ AdaptationSet* MpdBuilder::AddAdaptationSet(const std::string& lang) { &representation_counter_)); DCHECK(adaptation_set); - if (!lang.empty() && lang == mpd_options_.default_language) { + if (!lang.empty() && lang == mpd_options_.mpd_params.default_language) { adaptation_set->AddRole(AdaptationSet::kRoleMain); } @@ -503,9 +503,10 @@ xmlDocPtr MpdBuilder::GenerateMpd() { } void MpdBuilder::AddCommonMpdInfo(XmlNode* mpd_node) { - if (Positive(mpd_options_.min_buffer_time)) { + if (Positive(mpd_options_.mpd_params.min_buffer_time)) { mpd_node->SetStringAttribute( - "minBufferTime", SecondsToXmlDuration(mpd_options_.min_buffer_time)); + "minBufferTime", + SecondsToXmlDuration(mpd_options_.mpd_params.min_buffer_time)); } else { LOG(ERROR) << "minBufferTime value not specified."; // TODO(tinskip): Propagate error. @@ -551,19 +552,19 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) { mpd_node->SetStringAttribute("availabilityStartTime", availability_start_time_); - if (Positive(mpd_options_.minimum_update_period)) { + if (Positive(mpd_options_.mpd_params.minimum_update_period)) { mpd_node->SetStringAttribute( "minimumUpdatePeriod", - SecondsToXmlDuration(mpd_options_.minimum_update_period)); + SecondsToXmlDuration(mpd_options_.mpd_params.minimum_update_period)); } else { LOG(WARNING) << "The profile is dynamic but no minimumUpdatePeriod " "specified."; } - SetIfPositive("timeShiftBufferDepth", mpd_options_.time_shift_buffer_depth, - mpd_node); + SetIfPositive("timeShiftBufferDepth", + mpd_options_.mpd_params.time_shift_buffer_depth, mpd_node); SetIfPositive("suggestedPresentationDelay", - mpd_options_.suggested_presentation_delay, mpd_node); + mpd_options_.mpd_params.suggested_presentation_delay, mpd_node); } float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) { @@ -1287,15 +1288,15 @@ bool Representation::IsContiguous(uint64_t start_time, void Representation::SlideWindow() { DCHECK(!segment_infos_.empty()); - if (mpd_options_.time_shift_buffer_depth <= 0.0 || + if (mpd_options_.mpd_params.time_shift_buffer_depth <= 0.0 || mpd_options_.mpd_type == MpdType::kStatic) return; const uint32_t time_scale = GetTimeScale(media_info_); DCHECK_GT(time_scale, 0u); - uint64_t time_shift_buffer_depth = - static_cast(mpd_options_.time_shift_buffer_depth * time_scale); + uint64_t time_shift_buffer_depth = static_cast( + mpd_options_.mpd_params.time_shift_buffer_depth * time_scale); // The start time of the latest segment is considered the current_play_time, // and this should guarantee that the latest segment will stay in the list. diff --git a/packager/mpd/base/mpd_builder_unittest.cc b/packager/mpd/base/mpd_builder_unittest.cc index ebd3c7a013..67a4ddd4f0 100644 --- a/packager/mpd/base/mpd_builder_unittest.cc +++ b/packager/mpd/base/mpd_builder_unittest.cc @@ -2196,7 +2196,8 @@ TEST_F(SegmentTemplateTest, OverlappingSegmentsWithinErrorRange) { // All segments have the same duration and size. TEST_F(TimeShiftBufferDepthTest, Normal) { const int kTimeShiftBufferDepth = 10; // 10 sec. - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; // Trick to make every segment 1 second long. @@ -2233,7 +2234,8 @@ TEST_F(TimeShiftBufferDepthTest, Normal) { // removed from the MPD. TEST_F(TimeShiftBufferDepthTest, TimeShiftBufferDepthShorterThanSegmentLength) { const int kTimeShiftBufferDepth = 10; // 10 sec. - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; // Each duration is a second longer than timeShiftBufferDepth. @@ -2254,7 +2256,8 @@ TEST_F(TimeShiftBufferDepthTest, TimeShiftBufferDepthShorterThanSegmentLength) { // More generic version the normal test. TEST_F(TimeShiftBufferDepthTest, Generic) { const int kTimeShiftBufferDepth = 30; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 123; const uint64_t kDuration = DefaultTimeScale(); @@ -2296,7 +2299,8 @@ TEST_F(TimeShiftBufferDepthTest, Generic) { // the most recent segment added does not count TEST_F(TimeShiftBufferDepthTest, MoreThanOneS) { const int kTimeShiftBufferDepth = 100; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; const uint64_t kSize = 20000; @@ -2346,7 +2350,8 @@ TEST_F(TimeShiftBufferDepthTest, MoreThanOneS) { // Then the first S element's last segment should still be in the MPD. TEST_F(TimeShiftBufferDepthTest, UseLastSegmentInS) { const int kTimeShiftBufferDepth = 9; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 1; const uint64_t kDuration1 = static_cast(DefaultTimeScale() * 1.5); @@ -2382,7 +2387,8 @@ TEST_F(TimeShiftBufferDepthTest, UseLastSegmentInS) { // Gap between S elements but both should be included. TEST_F(TimeShiftBufferDepthTest, NormalGap) { const int kTimeShiftBufferDepth = 10; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; const uint64_t kDuration = DefaultTimeScale(); @@ -2413,7 +2419,8 @@ TEST_F(TimeShiftBufferDepthTest, NormalGap) { // Case where there is a huge gap so the first S element is removed. TEST_F(TimeShiftBufferDepthTest, HugeGap) { const int kTimeShiftBufferDepth = 10; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; const uint64_t kDuration = DefaultTimeScale(); @@ -2448,7 +2455,8 @@ TEST_F(TimeShiftBufferDepthTest, HugeGap) { // Check if startNumber is working correctly. TEST_F(TimeShiftBufferDepthTest, ManySegments) { const int kTimeShiftBufferDepth = 1; - mutable_mpd_options()->time_shift_buffer_depth = kTimeShiftBufferDepth; + mutable_mpd_options()->mpd_params.time_shift_buffer_depth = + kTimeShiftBufferDepth; const uint64_t kInitialStartTime = 0; const uint64_t kDuration = DefaultTimeScale(); diff --git a/packager/mpd/base/mpd_options.h b/packager/mpd/base/mpd_options.h index 5195eaf3be..dc261d9718 100644 --- a/packager/mpd/base/mpd_options.h +++ b/packager/mpd/base/mpd_options.h @@ -9,6 +9,8 @@ #include +#include "packager/mpd/public/mpd_params.h" + namespace shaka { enum class DashProfile { @@ -23,12 +25,7 @@ enum class MpdType { kStatic, kDynamic }; struct MpdOptions { DashProfile dash_profile = DashProfile::kOnDemand; MpdType mpd_type = MpdType::kStatic; - double minimum_update_period = 0; - // TODO(tinskip): Set min_buffer_time in unit tests rather than here. - double min_buffer_time = 2.0; - double time_shift_buffer_depth = 0; - double suggested_presentation_delay = 0; - std::string default_language; + MpdParams mpd_params; }; } // namespace shaka diff --git a/packager/mpd/base/simple_mpd_notifier.cc b/packager/mpd/base/simple_mpd_notifier.cc index 8b148c4d00..3e9e04a8cc 100644 --- a/packager/mpd/base/simple_mpd_notifier.cc +++ b/packager/mpd/base/simple_mpd_notifier.cc @@ -14,14 +14,12 @@ namespace shaka { -SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) +SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options) : MpdNotifier(mpd_options), - output_path_(output_path), + output_path_(mpd_options.mpd_params.mpd_output), mpd_builder_(new MpdBuilder(mpd_options)) { - for (size_t i = 0; i < base_urls.size(); ++i) - mpd_builder_->AddBaseUrl(base_urls[i]); + for (const std::string& base_url : mpd_options.mpd_params.base_urls) + mpd_builder_->AddBaseUrl(base_url); } SimpleMpdNotifier::~SimpleMpdNotifier() { diff --git a/packager/mpd/base/simple_mpd_notifier.h b/packager/mpd/base/simple_mpd_notifier.h index 5871be239c..1ceba2981a 100644 --- a/packager/mpd/base/simple_mpd_notifier.h +++ b/packager/mpd/base/simple_mpd_notifier.h @@ -30,9 +30,7 @@ struct MpdOptions; /// generates an Mpd file. class SimpleMpdNotifier : public MpdNotifier { public: - SimpleMpdNotifier(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path); + explicit SimpleMpdNotifier(const MpdOptions& mpd_options); ~SimpleMpdNotifier() override; /// @name MpdNotifier implemetation overrides. diff --git a/packager/mpd/base/simple_mpd_notifier_unittest.cc b/packager/mpd/base/simple_mpd_notifier_unittest.cc index 471c774bd2..7723398884 100644 --- a/packager/mpd/base/simple_mpd_notifier_unittest.cc +++ b/packager/mpd/base/simple_mpd_notifier_unittest.cc @@ -43,7 +43,7 @@ class SimpleMpdNotifierTest : public ::testing::Test { void SetUp() override { ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_)); - output_path_ = temp_file_path_.AsUTF8Unsafe(); + empty_mpd_option_.mpd_params.mpd_output = temp_file_path_.AsUTF8Unsafe(); } void TearDown() override { @@ -55,10 +55,9 @@ class SimpleMpdNotifierTest : public ::testing::Test { notifier->SetMpdBuilderForTesting(std::move(mpd_builder)); } - // Use output_path_ for specifying the MPD output path so that + // Empty mpd options except with output path specified, so that // WriteMpdToFile() doesn't crash. - std::string output_path_; - const MpdOptions empty_mpd_option_; + MpdOptions empty_mpd_option_; const std::vector empty_base_urls_; // Default AdaptationSet mock. @@ -70,7 +69,7 @@ class SimpleMpdNotifierTest : public ::testing::Test { // Verify NotifyNewContainer() works as expected for VOD. TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) { - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); const uint32_t kRepresentationId = 1u; std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -94,7 +93,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) { } TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) { - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); const uint32_t kRepresentationId = 8u; std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -124,7 +123,7 @@ TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) { // This issue identified a bug where using SimpleMpdNotifier with multiple // threads causes a deadlock. TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) { - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); uint32_t container_id; EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo), &container_id)); @@ -134,7 +133,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) { } TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) { - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); const uint32_t kRepresentationId = 447834u; std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -163,7 +162,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) { } TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) { - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); const uint32_t kRepresentationId = 0u; std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); @@ -206,7 +205,7 @@ TEST_F(SimpleMpdNotifierTest, UpdateEncryption) { " default_key_id: '_default_key_id_'\n" "}\n" "container_type: 1\n"; - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); const uint32_t kRepresentationId = 447834u; std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); std::unique_ptr mock_representation( @@ -294,7 +293,7 @@ TEST_F(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) { "container_type: CONTAINER_WEBM\n" "media_duration_seconds: 10.5\n"; - SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_); + SimpleMpdNotifier notifier(empty_mpd_option_); std::unique_ptr mock_mpd_builder(new MockMpdBuilder()); std::unique_ptr adaptation_set1(new MockAdaptationSet(1)); diff --git a/packager/mpd/mpd.gyp b/packager/mpd/mpd.gyp index af1256f1ae..990ee15f87 100644 --- a/packager/mpd/mpd.gyp +++ b/packager/mpd/mpd.gyp @@ -47,6 +47,7 @@ 'base/xml/scoped_xml_ptr.h', 'base/xml/xml_node.cc', 'base/xml/xml_node.h', + 'public/mpd_params.h', ], 'dependencies': [ '../base/base.gyp:base', diff --git a/packager/mpd/public/mpd_params.h b/packager/mpd/public/mpd_params.h new file mode 100644 index 0000000000..459e632305 --- /dev/null +++ b/packager/mpd/public/mpd_params.h @@ -0,0 +1,53 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#ifndef PACKAGER_MPD_PUBLIC_MPD_PARAMS_H_ +#define PACKAGER_MPD_PUBLIC_MPD_PARAMS_H_ + +#include +#include + +namespace shaka { + +/// DASH MPD related parameters. +struct MpdParams { + /// MPD output file path. + std::string mpd_output; + /// BaseURLs for the MPD. The values will be added as element(s) + /// under the element. + std::vector base_urls; + /// Set MPD@minBufferTime attribute, which specifies, in seconds, a common + /// duration used in the definition of the MPD representation data rate. A + /// client can be assured of having enough data for continous playout + /// providing playout begins at min_buffer_time after the first bit is + /// received. + double min_buffer_time = 2.0; + /// Generate static MPD for live profile. Note that this flag has no effect + /// for on-demand profile, in which case static MPD is always used. + bool generate_static_live_mpd = false; + /// Set MPD@timeShiftBufferDepth attribute, which is the guaranteed duration + /// of the time shifting buffer for 'dynamic' media presentations, in seconds. + double time_shift_buffer_depth = 0; + /// Set MPD@suggestedPresentationDelay attribute. For 'dynamic' media + /// presentations, it specifies a delay, in seconds, to be added to the media + /// presentation time. The attribute is not set if the value is 0; the client + /// is expected to choose a suitable value in this case. + static constexpr double kSuggestedPresentationDelayNotSet = 0; + double suggested_presentation_delay = kSuggestedPresentationDelayNotSet; + /// Set MPD@minimumUpdatePeriod attribute, which indicates to the player how + /// often to refresh the MPD in seconds. For dynamic MPD only. + double minimum_update_period = 0; + /// The tracks tagged with this language will have + /// in the manifest. This allows the player to choose the correct default + /// language for the content. + std::string default_language; + /// Try to generate DASH-IF IOP compliant MPD. + bool generate_dash_if_iop_compliant_mpd = true; +}; + +} // namespace shaka + +#endif // PACKAGER_MPD_PUBLIC_MPD_PARAMS_H_ diff --git a/packager/mpd/util/mpd_writer.cc b/packager/mpd/util/mpd_writer.cc index 159070b936..cd1a83f7fd 100644 --- a/packager/mpd/util/mpd_writer.cc +++ b/packager/mpd/util/mpd_writer.cc @@ -35,11 +35,8 @@ class DashIopMpdNotifierFactory : public MpdNotifierFactory { DashIopMpdNotifierFactory() {} ~DashIopMpdNotifierFactory() override {} - std::unique_ptr Create(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) override { - return std::unique_ptr( - new DashIopMpdNotifier(mpd_options, base_urls, output_path)); + std::unique_ptr Create(const MpdOptions& mpd_options) override { + return std::unique_ptr(new DashIopMpdNotifier(mpd_options)); } }; @@ -49,11 +46,8 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory { SimpleMpdNotifierFactory() {} ~SimpleMpdNotifierFactory() override {} - std::unique_ptr Create(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) override { - return std::unique_ptr( - new SimpleMpdNotifier(mpd_options, base_urls, output_path)); + std::unique_ptr Create(const MpdOptions& mpd_options) override { + return std::unique_ptr(new SimpleMpdNotifier(mpd_options)); } }; @@ -93,8 +87,11 @@ void MpdWriter::AddBaseUrl(const std::string& base_url) { bool MpdWriter::WriteMpdToFile(const char* file_name) { CHECK(file_name); + MpdOptions mpd_options; + mpd_options.mpd_params.base_urls = base_urls_; + mpd_options.mpd_params.mpd_output = file_name; std::unique_ptr notifier = - notifier_factory_->Create(MpdOptions(), base_urls_, file_name); + notifier_factory_->Create(mpd_options); if (!notifier->Init()) { LOG(ERROR) << "failed to initialize MpdNotifier."; return false; diff --git a/packager/mpd/util/mpd_writer.h b/packager/mpd/util/mpd_writer.h index 6ea9e62c0f..a0244c7ce5 100644 --- a/packager/mpd/util/mpd_writer.h +++ b/packager/mpd/util/mpd_writer.h @@ -35,9 +35,7 @@ class MpdNotifierFactory { virtual ~MpdNotifierFactory() {} virtual std::unique_ptr Create( - const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) = 0; + const MpdOptions& mpd_options) = 0; }; // An instance of this class takes a set of MediaInfo files and generates an diff --git a/packager/mpd/util/mpd_writer_unittest.cc b/packager/mpd/util/mpd_writer_unittest.cc index a0128a879e..49a47baf2d 100644 --- a/packager/mpd/util/mpd_writer_unittest.cc +++ b/packager/mpd/util/mpd_writer_unittest.cc @@ -33,10 +33,8 @@ class TestMpdNotifierFactory : public MpdNotifierFactory { // std::unique_ptr. // For now we only need to return MockMpdNotifier() with these set of // expectations for all the tests. - std::unique_ptr Create(const MpdOptions& mpd_options, - const std::vector& base_urls, - const std::string& output_path) override { - EXPECT_EQ(expected_base_urls_, base_urls); + std::unique_ptr Create(const MpdOptions& mpd_options) override { + EXPECT_EQ(expected_base_urls_, mpd_options.mpd_params.base_urls); std::unique_ptr mock_notifier( new MockMpdNotifier(mpd_options)); diff --git a/packager/packager.cc b/packager/packager.cc index 746dd8fc52..a18cd34881 100644 --- a/packager/packager.cc +++ b/packager/packager.cc @@ -43,9 +43,7 @@ namespace shaka { // TODO(kqyang): Clean up namespaces. -using media::ChunkingOptions; using media::Demuxer; -using media::EncryptionOptions; using media::KeySource; using media::MuxerOptions; @@ -602,11 +600,9 @@ Status Packager::Initialize( const MpdParams& mpd_params = packaging_params.mpd_params; if (!mpd_params.mpd_output.empty()) { if (mpd_params.generate_dash_if_iop_compliant_mpd) { - internal->mpd_notifier.reset(new DashIopMpdNotifier( - mpd_options, mpd_params.base_urls, mpd_params.mpd_output)); + internal->mpd_notifier.reset(new DashIopMpdNotifier(mpd_options)); } else { - internal->mpd_notifier.reset(new SimpleMpdNotifier( - mpd_options, mpd_params.base_urls, mpd_params.mpd_output)); + internal->mpd_notifier.reset(new SimpleMpdNotifier(mpd_options)); } if (!internal->mpd_notifier->Init()) { LOG(ERROR) << "MpdNotifier failed to initialize."; diff --git a/packager/packager.h b/packager/packager.h index a89300561d..d599c3bab6 100644 --- a/packager/packager.h +++ b/packager/packager.h @@ -15,46 +15,11 @@ #include "packager/media/public/chunking_params.h" #include "packager/media/public/crypto_params.h" #include "packager/media/public/mp4_output_params.h" +#include "packager/mpd/public/mpd_params.h" #include "packager/status.h" namespace shaka { -/// DASH MPD related parameters. -struct MpdParams { - /// MPD output file path. - std::string mpd_output; - /// BaseURLs for the MPD. The values will be added as element(s) - /// under the element. - std::vector base_urls; - /// Set MPD@minBufferTime attribute, which specifies, in seconds, a common - /// duration used in the definition of the MPD representation data rate. A - /// client can be assured of having enough data for continous playout - /// providing playout begins at min_buffer_time after the first bit is - /// received. - double min_buffer_time = 2.0; - /// Generate static MPD for live profile. Note that this flag has no effect - /// for on-demand profile, in which case static MPD is always used. - bool generate_static_live_mpd = false; - /// Set MPD@timeShiftBufferDepth attribute, which is the guaranteed duration - /// of the time shifting buffer for 'dynamic' media presentations, in seconds. - double time_shift_buffer_depth = 0; - /// Set MPD@suggestedPresentationDelay attribute. For 'dynamic' media - /// presentations, it specifies a delay, in seconds, to be added to the media - /// presentation time. The attribute is not set if the value is 0; the client - /// is expected to choose a suitable value in this case. - const double kSuggestedPresentationDelayNotSet = 0; - double suggested_presentation_delay = kSuggestedPresentationDelayNotSet; - /// Set MPD@minimumUpdatePeriod attribute, which indicates to the player how - /// often to refresh the MPD in seconds. For dynamic MPD only. - double minimum_update_period = 0; - /// The tracks tagged with this language will have - /// in the manifest. This allows the player to choose the correct default - /// language for the content. - std::string default_language; - /// Try to generate DASH-IF IOP compliant MPD. - bool generate_dash_if_iop_compliant_mpd = true; -}; - /// HLS related parameters. struct HlsParams { /// HLS playlist type. See HLS specification for details.