Consolidate MpdParams into MpdOptions
Change-Id: I7f37277ef87597548c2fbf219963cd8725ae4c05
This commit is contained in:
parent
4e82ab13bd
commit
556ff56559
|
@ -26,8 +26,6 @@ namespace shaka {
|
||||||
namespace media {
|
namespace media {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
||||||
std::unique_ptr<RequestSigner> request_signer;
|
std::unique_ptr<RequestSigner> request_signer;
|
||||||
switch (signer.signing_key_type) {
|
switch (signer.signing_key_type) {
|
||||||
|
@ -47,6 +45,8 @@ std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
||||||
return request_signer;
|
return request_signer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<KeySource> CreateEncryptionKeySource(
|
std::unique_ptr<KeySource> CreateEncryptionKeySource(
|
||||||
FourCC protection_scheme,
|
FourCC protection_scheme,
|
||||||
const EncryptionParams& encryption_params) {
|
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)
|
(on_demand_profile || mpd_params.generate_static_live_mpd)
|
||||||
? MpdType::kStatic
|
? MpdType::kStatic
|
||||||
: MpdType::kDynamic;
|
: MpdType::kDynamic;
|
||||||
mpd_options.minimum_update_period = mpd_params.minimum_update_period;
|
mpd_options.mpd_params = mpd_params;
|
||||||
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;
|
|
||||||
return mpd_options;
|
return mpd_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,15 @@
|
||||||
#define PACKAGER_APP_PACKAGER_UTIL_H_
|
#define PACKAGER_APP_PACKAGER_UTIL_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "packager/base/optional.h"
|
|
||||||
#include "packager/media/base/fourccs.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/packager.h"
|
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
// TODO(kqyang): Should we consolidate XxxParams and XxxOptions?
|
class Status;
|
||||||
struct ChunkingParams;
|
|
||||||
struct DecryptionParams;
|
struct DecryptionParams;
|
||||||
struct EncryptionParams;
|
struct EncryptionParams;
|
||||||
struct Mp4OutputParams;
|
|
||||||
struct MpdOptions;
|
struct MpdOptions;
|
||||||
struct MpdParams;
|
struct MpdParams;
|
||||||
|
|
||||||
|
@ -29,12 +26,9 @@ namespace media {
|
||||||
|
|
||||||
class MediaHandler;
|
class MediaHandler;
|
||||||
class KeySource;
|
class KeySource;
|
||||||
struct ChunkingOptions;
|
|
||||||
struct EncryptionOptions;
|
|
||||||
struct MuxerOptions;
|
|
||||||
|
|
||||||
/// Create KeySource based on provided command line options for content
|
/// Create KeySource based on provided params for content encryption. Also
|
||||||
/// encryption. Also fetches keys.
|
/// fetches keys.
|
||||||
/// @param protection_scheme specifies the protection scheme to be used for
|
/// @param protection_scheme specifies the protection scheme to be used for
|
||||||
/// encryption.
|
/// encryption.
|
||||||
/// @return A std::unique_ptr containing a new KeySource, or nullptr if
|
/// @return A std::unique_ptr containing a new KeySource, or nullptr if
|
||||||
|
@ -43,14 +37,14 @@ std::unique_ptr<KeySource> CreateEncryptionKeySource(
|
||||||
FourCC protection_scheme,
|
FourCC protection_scheme,
|
||||||
const EncryptionParams& encryption_params);
|
const EncryptionParams& encryption_params);
|
||||||
|
|
||||||
/// Create KeySource based on provided command line options for content
|
/// Create KeySource based on provided params for content decryption. Does not
|
||||||
/// decryption. Does not fetch keys.
|
/// fetch keys.
|
||||||
/// @return A std::unique_ptr containing a new KeySource, or nullptr if
|
/// @return A std::unique_ptr containing a new KeySource, or nullptr if
|
||||||
/// decryption is not required.
|
/// decryption is not required.
|
||||||
std::unique_ptr<KeySource> CreateDecryptionKeySource(
|
std::unique_ptr<KeySource> CreateDecryptionKeySource(
|
||||||
const DecryptionParams& decryption_params);
|
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);
|
MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params);
|
||||||
|
|
||||||
/// Connect handlers in the vector.
|
/// Connect handlers in the vector.
|
||||||
|
|
|
@ -38,15 +38,12 @@ std::set<std::string> GetUUIDs(
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
DashIopMpdNotifier::DashIopMpdNotifier(
|
DashIopMpdNotifier::DashIopMpdNotifier(const MpdOptions& mpd_options)
|
||||||
const MpdOptions& mpd_options,
|
|
||||||
const std::vector<std::string>& base_urls,
|
|
||||||
const std::string& output_path)
|
|
||||||
: MpdNotifier(mpd_options),
|
: MpdNotifier(mpd_options),
|
||||||
output_path_(output_path),
|
output_path_(mpd_options.mpd_params.mpd_output),
|
||||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
mpd_builder_(new MpdBuilder(mpd_options)) {
|
||||||
for (size_t i = 0; i < base_urls.size(); ++i)
|
for (const std::string& base_url : mpd_options.mpd_params.base_urls)
|
||||||
mpd_builder_->AddBaseUrl(base_urls[i]);
|
mpd_builder_->AddBaseUrl(base_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
DashIopMpdNotifier::~DashIopMpdNotifier() {}
|
DashIopMpdNotifier::~DashIopMpdNotifier() {}
|
||||||
|
|
|
@ -29,9 +29,7 @@ namespace shaka {
|
||||||
/// All video Adaptation Sets have Role set to "main".
|
/// All video Adaptation Sets have Role set to "main".
|
||||||
class DashIopMpdNotifier : public MpdNotifier {
|
class DashIopMpdNotifier : public MpdNotifier {
|
||||||
public:
|
public:
|
||||||
DashIopMpdNotifier(const MpdOptions& mpd_options,
|
explicit DashIopMpdNotifier(const MpdOptions& mpd_options);
|
||||||
const std::vector<std::string>& base_urls,
|
|
||||||
const std::string& output_path);
|
|
||||||
~DashIopMpdNotifier() override;
|
~DashIopMpdNotifier() override;
|
||||||
|
|
||||||
/// None of the methods write out the MPD file until Flush() is called.
|
/// None of the methods write out the MPD file until Flush() is called.
|
||||||
|
|
|
@ -101,7 +101,7 @@ class DashIopMpdNotifierTest : public ::testing::Test {
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
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 {
|
void TearDown() override {
|
||||||
|
@ -113,11 +113,9 @@ class DashIopMpdNotifierTest : public ::testing::Test {
|
||||||
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
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.
|
// WriteMpdToFile() doesn't crash.
|
||||||
std::string output_path_;
|
MpdOptions empty_mpd_option_;
|
||||||
const MpdOptions empty_mpd_option_;
|
|
||||||
const std::vector<std::string> empty_base_urls_;
|
|
||||||
|
|
||||||
// Default mocks that can be used for the tests.
|
// Default mocks that can be used for the tests.
|
||||||
// IOW, if a test only requires one instance of
|
// 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.
|
// Verify that basic VOD NotifyNewContainer() operation works.
|
||||||
// No encrypted contents.
|
// No encrypted contents.
|
||||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
|
TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
|
@ -170,8 +167,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerForTrickPlay) {
|
||||||
" playback_rate: 10\n"
|
" playback_rate: 10\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: 1\n";
|
"container_type: 1\n";
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
|
@ -228,8 +224,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) {
|
||||||
" language: 'en'\n"
|
" language: 'en'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: CONTAINER_TEXT\n";
|
"container_type: CONTAINER_TEXT\n";
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
|
@ -257,8 +252,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) {
|
||||||
// AdaptationSets with different DRM won't be switchable.
|
// AdaptationSets with different DRM won't be switchable.
|
||||||
TEST_F(DashIopMpdNotifierTest,
|
TEST_F(DashIopMpdNotifierTest,
|
||||||
NotifyNewContainersWithDifferentProtectedContent) {
|
NotifyNewContainersWithDifferentProtectedContent) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
// Note they both have different (bogus) pssh, like real use case.
|
// 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
|
// MediaInfo::ProtectedContent. Only one AdaptationSet should be
|
||||||
// created.
|
// created.
|
||||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
|
TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
// These have the same default key ID and PSSH.
|
// 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.
|
// AddContentProtection() should not work and should always return false.
|
||||||
TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
|
TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> 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.
|
// 3. Add a 4k protected content. This should also make a new AdaptationSet.
|
||||||
// It should be switchable with SD/HD AdaptationSet.
|
// It should be switchable with SD/HD AdaptationSet.
|
||||||
TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
// These have the same default key ID and PSSH.
|
// These have the same default key ID and PSSH.
|
||||||
|
@ -645,8 +636,7 @@ TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
||||||
// switchable.
|
// switchable.
|
||||||
TEST_F(DashIopMpdNotifierTest,
|
TEST_F(DashIopMpdNotifierTest,
|
||||||
DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) {
|
DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
// These have the same default key ID and PSSH.
|
// These have the same default key ID and PSSH.
|
||||||
|
@ -752,8 +742,7 @@ TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: 1\n";
|
"container_type: 1\n";
|
||||||
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
|
@ -792,8 +781,7 @@ TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
|
||||||
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
||||||
// threads causes a deadlock. This tests with DashIopMpdNotifier.
|
// threads causes a deadlock. This tests with DashIopMpdNotifier.
|
||||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
uint32_t container_id;
|
uint32_t container_id;
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
||||||
&container_id));
|
&container_id));
|
||||||
|
@ -856,8 +844,7 @@ TEST_F(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||||
"container_type: CONTAINER_WEBM\n"
|
"container_type: CONTAINER_WEBM\n"
|
||||||
"media_duration_seconds: 10.5\n";
|
"media_duration_seconds: 10.5\n";
|
||||||
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
||||||
output_path_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||||
|
|
|
@ -385,7 +385,7 @@ AdaptationSet* MpdBuilder::AddAdaptationSet(const std::string& lang) {
|
||||||
&representation_counter_));
|
&representation_counter_));
|
||||||
DCHECK(adaptation_set);
|
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);
|
adaptation_set->AddRole(AdaptationSet::kRoleMain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,9 +503,10 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MpdBuilder::AddCommonMpdInfo(XmlNode* mpd_node) {
|
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(
|
mpd_node->SetStringAttribute(
|
||||||
"minBufferTime", SecondsToXmlDuration(mpd_options_.min_buffer_time));
|
"minBufferTime",
|
||||||
|
SecondsToXmlDuration(mpd_options_.mpd_params.min_buffer_time));
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "minBufferTime value not specified.";
|
LOG(ERROR) << "minBufferTime value not specified.";
|
||||||
// TODO(tinskip): Propagate error.
|
// TODO(tinskip): Propagate error.
|
||||||
|
@ -551,19 +552,19 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
||||||
mpd_node->SetStringAttribute("availabilityStartTime",
|
mpd_node->SetStringAttribute("availabilityStartTime",
|
||||||
availability_start_time_);
|
availability_start_time_);
|
||||||
|
|
||||||
if (Positive(mpd_options_.minimum_update_period)) {
|
if (Positive(mpd_options_.mpd_params.minimum_update_period)) {
|
||||||
mpd_node->SetStringAttribute(
|
mpd_node->SetStringAttribute(
|
||||||
"minimumUpdatePeriod",
|
"minimumUpdatePeriod",
|
||||||
SecondsToXmlDuration(mpd_options_.minimum_update_period));
|
SecondsToXmlDuration(mpd_options_.mpd_params.minimum_update_period));
|
||||||
} else {
|
} else {
|
||||||
LOG(WARNING) << "The profile is dynamic but no minimumUpdatePeriod "
|
LOG(WARNING) << "The profile is dynamic but no minimumUpdatePeriod "
|
||||||
"specified.";
|
"specified.";
|
||||||
}
|
}
|
||||||
|
|
||||||
SetIfPositive("timeShiftBufferDepth", mpd_options_.time_shift_buffer_depth,
|
SetIfPositive("timeShiftBufferDepth",
|
||||||
mpd_node);
|
mpd_options_.mpd_params.time_shift_buffer_depth, mpd_node);
|
||||||
SetIfPositive("suggestedPresentationDelay",
|
SetIfPositive("suggestedPresentationDelay",
|
||||||
mpd_options_.suggested_presentation_delay, mpd_node);
|
mpd_options_.mpd_params.suggested_presentation_delay, mpd_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
||||||
|
@ -1287,15 +1288,15 @@ bool Representation::IsContiguous(uint64_t start_time,
|
||||||
|
|
||||||
void Representation::SlideWindow() {
|
void Representation::SlideWindow() {
|
||||||
DCHECK(!segment_infos_.empty());
|
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)
|
mpd_options_.mpd_type == MpdType::kStatic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const uint32_t time_scale = GetTimeScale(media_info_);
|
const uint32_t time_scale = GetTimeScale(media_info_);
|
||||||
DCHECK_GT(time_scale, 0u);
|
DCHECK_GT(time_scale, 0u);
|
||||||
|
|
||||||
uint64_t time_shift_buffer_depth =
|
uint64_t time_shift_buffer_depth = static_cast<uint64_t>(
|
||||||
static_cast<uint64_t>(mpd_options_.time_shift_buffer_depth * time_scale);
|
mpd_options_.mpd_params.time_shift_buffer_depth * time_scale);
|
||||||
|
|
||||||
// The start time of the latest segment is considered the current_play_time,
|
// 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.
|
// and this should guarantee that the latest segment will stay in the list.
|
||||||
|
|
|
@ -2196,7 +2196,8 @@ TEST_F(SegmentTemplateTest, OverlappingSegmentsWithinErrorRange) {
|
||||||
// All segments have the same duration and size.
|
// All segments have the same duration and size.
|
||||||
TEST_F(TimeShiftBufferDepthTest, Normal) {
|
TEST_F(TimeShiftBufferDepthTest, Normal) {
|
||||||
const int kTimeShiftBufferDepth = 10; // 10 sec.
|
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;
|
const uint64_t kInitialStartTime = 0;
|
||||||
// Trick to make every segment 1 second long.
|
// Trick to make every segment 1 second long.
|
||||||
|
@ -2233,7 +2234,8 @@ TEST_F(TimeShiftBufferDepthTest, Normal) {
|
||||||
// removed from the MPD.
|
// removed from the MPD.
|
||||||
TEST_F(TimeShiftBufferDepthTest, TimeShiftBufferDepthShorterThanSegmentLength) {
|
TEST_F(TimeShiftBufferDepthTest, TimeShiftBufferDepthShorterThanSegmentLength) {
|
||||||
const int kTimeShiftBufferDepth = 10; // 10 sec.
|
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;
|
const uint64_t kInitialStartTime = 0;
|
||||||
// Each duration is a second longer than timeShiftBufferDepth.
|
// Each duration is a second longer than timeShiftBufferDepth.
|
||||||
|
@ -2254,7 +2256,8 @@ TEST_F(TimeShiftBufferDepthTest, TimeShiftBufferDepthShorterThanSegmentLength) {
|
||||||
// More generic version the normal test.
|
// More generic version the normal test.
|
||||||
TEST_F(TimeShiftBufferDepthTest, Generic) {
|
TEST_F(TimeShiftBufferDepthTest, Generic) {
|
||||||
const int kTimeShiftBufferDepth = 30;
|
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 kInitialStartTime = 123;
|
||||||
const uint64_t kDuration = DefaultTimeScale();
|
const uint64_t kDuration = DefaultTimeScale();
|
||||||
|
@ -2296,7 +2299,8 @@ TEST_F(TimeShiftBufferDepthTest, Generic) {
|
||||||
// the most recent segment added does not count
|
// the most recent segment added does not count
|
||||||
TEST_F(TimeShiftBufferDepthTest, MoreThanOneS) {
|
TEST_F(TimeShiftBufferDepthTest, MoreThanOneS) {
|
||||||
const int kTimeShiftBufferDepth = 100;
|
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 kInitialStartTime = 0;
|
||||||
const uint64_t kSize = 20000;
|
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.
|
// Then the first S element's last segment should still be in the MPD.
|
||||||
TEST_F(TimeShiftBufferDepthTest, UseLastSegmentInS) {
|
TEST_F(TimeShiftBufferDepthTest, UseLastSegmentInS) {
|
||||||
const int kTimeShiftBufferDepth = 9;
|
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 kInitialStartTime = 1;
|
||||||
const uint64_t kDuration1 = static_cast<uint64_t>(DefaultTimeScale() * 1.5);
|
const uint64_t kDuration1 = static_cast<uint64_t>(DefaultTimeScale() * 1.5);
|
||||||
|
@ -2382,7 +2387,8 @@ TEST_F(TimeShiftBufferDepthTest, UseLastSegmentInS) {
|
||||||
// Gap between S elements but both should be included.
|
// Gap between S elements but both should be included.
|
||||||
TEST_F(TimeShiftBufferDepthTest, NormalGap) {
|
TEST_F(TimeShiftBufferDepthTest, NormalGap) {
|
||||||
const int kTimeShiftBufferDepth = 10;
|
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 kInitialStartTime = 0;
|
||||||
const uint64_t kDuration = DefaultTimeScale();
|
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.
|
// Case where there is a huge gap so the first S element is removed.
|
||||||
TEST_F(TimeShiftBufferDepthTest, HugeGap) {
|
TEST_F(TimeShiftBufferDepthTest, HugeGap) {
|
||||||
const int kTimeShiftBufferDepth = 10;
|
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 kInitialStartTime = 0;
|
||||||
const uint64_t kDuration = DefaultTimeScale();
|
const uint64_t kDuration = DefaultTimeScale();
|
||||||
|
@ -2448,7 +2455,8 @@ TEST_F(TimeShiftBufferDepthTest, HugeGap) {
|
||||||
// Check if startNumber is working correctly.
|
// Check if startNumber is working correctly.
|
||||||
TEST_F(TimeShiftBufferDepthTest, ManySegments) {
|
TEST_F(TimeShiftBufferDepthTest, ManySegments) {
|
||||||
const int kTimeShiftBufferDepth = 1;
|
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 kInitialStartTime = 0;
|
||||||
const uint64_t kDuration = DefaultTimeScale();
|
const uint64_t kDuration = DefaultTimeScale();
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "packager/mpd/public/mpd_params.h"
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
enum class DashProfile {
|
enum class DashProfile {
|
||||||
|
@ -23,12 +25,7 @@ enum class MpdType { kStatic, kDynamic };
|
||||||
struct MpdOptions {
|
struct MpdOptions {
|
||||||
DashProfile dash_profile = DashProfile::kOnDemand;
|
DashProfile dash_profile = DashProfile::kOnDemand;
|
||||||
MpdType mpd_type = MpdType::kStatic;
|
MpdType mpd_type = MpdType::kStatic;
|
||||||
double minimum_update_period = 0;
|
MpdParams mpd_params;
|
||||||
// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -14,14 +14,12 @@
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options,
|
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options)
|
||||||
const std::vector<std::string>& base_urls,
|
|
||||||
const std::string& output_path)
|
|
||||||
: MpdNotifier(mpd_options),
|
: MpdNotifier(mpd_options),
|
||||||
output_path_(output_path),
|
output_path_(mpd_options.mpd_params.mpd_output),
|
||||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
mpd_builder_(new MpdBuilder(mpd_options)) {
|
||||||
for (size_t i = 0; i < base_urls.size(); ++i)
|
for (const std::string& base_url : mpd_options.mpd_params.base_urls)
|
||||||
mpd_builder_->AddBaseUrl(base_urls[i]);
|
mpd_builder_->AddBaseUrl(base_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleMpdNotifier::~SimpleMpdNotifier() {
|
SimpleMpdNotifier::~SimpleMpdNotifier() {
|
||||||
|
|
|
@ -30,9 +30,7 @@ struct MpdOptions;
|
||||||
/// generates an Mpd file.
|
/// generates an Mpd file.
|
||||||
class SimpleMpdNotifier : public MpdNotifier {
|
class SimpleMpdNotifier : public MpdNotifier {
|
||||||
public:
|
public:
|
||||||
SimpleMpdNotifier(const MpdOptions& mpd_options,
|
explicit SimpleMpdNotifier(const MpdOptions& mpd_options);
|
||||||
const std::vector<std::string>& base_urls,
|
|
||||||
const std::string& output_path);
|
|
||||||
~SimpleMpdNotifier() override;
|
~SimpleMpdNotifier() override;
|
||||||
|
|
||||||
/// @name MpdNotifier implemetation overrides.
|
/// @name MpdNotifier implemetation overrides.
|
||||||
|
|
|
@ -43,7 +43,7 @@ class SimpleMpdNotifierTest : public ::testing::Test {
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
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 {
|
void TearDown() override {
|
||||||
|
@ -55,10 +55,9 @@ class SimpleMpdNotifierTest : public ::testing::Test {
|
||||||
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
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.
|
// WriteMpdToFile() doesn't crash.
|
||||||
std::string output_path_;
|
MpdOptions empty_mpd_option_;
|
||||||
const MpdOptions empty_mpd_option_;
|
|
||||||
const std::vector<std::string> empty_base_urls_;
|
const std::vector<std::string> empty_base_urls_;
|
||||||
|
|
||||||
// Default AdaptationSet mock.
|
// Default AdaptationSet mock.
|
||||||
|
@ -70,7 +69,7 @@ class SimpleMpdNotifierTest : public ::testing::Test {
|
||||||
|
|
||||||
// Verify NotifyNewContainer() works as expected for VOD.
|
// Verify NotifyNewContainer() works as expected for VOD.
|
||||||
TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
|
TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
SimpleMpdNotifier notifier(empty_mpd_option_);
|
||||||
|
|
||||||
const uint32_t kRepresentationId = 1u;
|
const uint32_t kRepresentationId = 1u;
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
@ -94,7 +93,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) {
|
TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) {
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
SimpleMpdNotifier notifier(empty_mpd_option_);
|
||||||
|
|
||||||
const uint32_t kRepresentationId = 8u;
|
const uint32_t kRepresentationId = 8u;
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
@ -124,7 +123,7 @@ TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) {
|
||||||
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
||||||
// threads causes a deadlock.
|
// threads causes a deadlock.
|
||||||
TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
SimpleMpdNotifier notifier(empty_mpd_option_);
|
||||||
uint32_t container_id;
|
uint32_t container_id;
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
||||||
&container_id));
|
&container_id));
|
||||||
|
@ -134,7 +133,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
|
TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
SimpleMpdNotifier notifier(empty_mpd_option_);
|
||||||
|
|
||||||
const uint32_t kRepresentationId = 447834u;
|
const uint32_t kRepresentationId = 447834u;
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
@ -163,7 +162,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
|
TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
SimpleMpdNotifier notifier(empty_mpd_option_);
|
||||||
|
|
||||||
const uint32_t kRepresentationId = 0u;
|
const uint32_t kRepresentationId = 0u;
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
@ -206,7 +205,7 @@ TEST_F(SimpleMpdNotifierTest, UpdateEncryption) {
|
||||||
" default_key_id: '_default_key_id_'\n"
|
" default_key_id: '_default_key_id_'\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"container_type: 1\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;
|
const uint32_t kRepresentationId = 447834u;
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
std::unique_ptr<MockRepresentation> mock_representation(
|
std::unique_ptr<MockRepresentation> mock_representation(
|
||||||
|
@ -294,7 +293,7 @@ TEST_F(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||||
"container_type: CONTAINER_WEBM\n"
|
"container_type: CONTAINER_WEBM\n"
|
||||||
"media_duration_seconds: 10.5\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<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
|
||||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
'base/xml/scoped_xml_ptr.h',
|
'base/xml/scoped_xml_ptr.h',
|
||||||
'base/xml/xml_node.cc',
|
'base/xml/xml_node.cc',
|
||||||
'base/xml/xml_node.h',
|
'base/xml/xml_node.h',
|
||||||
|
'public/mpd_params.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../base/base.gyp:base',
|
'../base/base.gyp:base',
|
||||||
|
|
|
@ -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 <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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 <BaseURL> element(s)
|
||||||
|
/// under the <MPD> element.
|
||||||
|
std::vector<std::string> 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 <Role ... value=\"main\" />
|
||||||
|
/// 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_
|
|
@ -35,11 +35,8 @@ class DashIopMpdNotifierFactory : public MpdNotifierFactory {
|
||||||
DashIopMpdNotifierFactory() {}
|
DashIopMpdNotifierFactory() {}
|
||||||
~DashIopMpdNotifierFactory() override {}
|
~DashIopMpdNotifierFactory() override {}
|
||||||
|
|
||||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||||
const std::vector<std::string>& base_urls,
|
return std::unique_ptr<MpdNotifier>(new DashIopMpdNotifier(mpd_options));
|
||||||
const std::string& output_path) override {
|
|
||||||
return std::unique_ptr<MpdNotifier>(
|
|
||||||
new DashIopMpdNotifier(mpd_options, base_urls, output_path));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,11 +46,8 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
||||||
SimpleMpdNotifierFactory() {}
|
SimpleMpdNotifierFactory() {}
|
||||||
~SimpleMpdNotifierFactory() override {}
|
~SimpleMpdNotifierFactory() override {}
|
||||||
|
|
||||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||||
const std::vector<std::string>& base_urls,
|
return std::unique_ptr<MpdNotifier>(new SimpleMpdNotifier(mpd_options));
|
||||||
const std::string& output_path) override {
|
|
||||||
return std::unique_ptr<MpdNotifier>(
|
|
||||||
new SimpleMpdNotifier(mpd_options, base_urls, output_path));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,8 +87,11 @@ void MpdWriter::AddBaseUrl(const std::string& base_url) {
|
||||||
|
|
||||||
bool MpdWriter::WriteMpdToFile(const char* file_name) {
|
bool MpdWriter::WriteMpdToFile(const char* file_name) {
|
||||||
CHECK(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<MpdNotifier> notifier =
|
std::unique_ptr<MpdNotifier> notifier =
|
||||||
notifier_factory_->Create(MpdOptions(), base_urls_, file_name);
|
notifier_factory_->Create(mpd_options);
|
||||||
if (!notifier->Init()) {
|
if (!notifier->Init()) {
|
||||||
LOG(ERROR) << "failed to initialize MpdNotifier.";
|
LOG(ERROR) << "failed to initialize MpdNotifier.";
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -35,9 +35,7 @@ class MpdNotifierFactory {
|
||||||
virtual ~MpdNotifierFactory() {}
|
virtual ~MpdNotifierFactory() {}
|
||||||
|
|
||||||
virtual std::unique_ptr<MpdNotifier> Create(
|
virtual std::unique_ptr<MpdNotifier> Create(
|
||||||
const MpdOptions& mpd_options,
|
const MpdOptions& mpd_options) = 0;
|
||||||
const std::vector<std::string>& base_urls,
|
|
||||||
const std::string& output_path) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// An instance of this class takes a set of MediaInfo files and generates an
|
// An instance of this class takes a set of MediaInfo files and generates an
|
||||||
|
|
|
@ -33,10 +33,8 @@ class TestMpdNotifierFactory : public MpdNotifierFactory {
|
||||||
// std::unique_ptr.
|
// std::unique_ptr.
|
||||||
// For now we only need to return MockMpdNotifier() with these set of
|
// For now we only need to return MockMpdNotifier() with these set of
|
||||||
// expectations for all the tests.
|
// expectations for all the tests.
|
||||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||||
const std::vector<std::string>& base_urls,
|
EXPECT_EQ(expected_base_urls_, mpd_options.mpd_params.base_urls);
|
||||||
const std::string& output_path) override {
|
|
||||||
EXPECT_EQ(expected_base_urls_, base_urls);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdNotifier> mock_notifier(
|
std::unique_ptr<MockMpdNotifier> mock_notifier(
|
||||||
new MockMpdNotifier(mpd_options));
|
new MockMpdNotifier(mpd_options));
|
||||||
|
|
|
@ -43,9 +43,7 @@
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
// TODO(kqyang): Clean up namespaces.
|
// TODO(kqyang): Clean up namespaces.
|
||||||
using media::ChunkingOptions;
|
|
||||||
using media::Demuxer;
|
using media::Demuxer;
|
||||||
using media::EncryptionOptions;
|
|
||||||
using media::KeySource;
|
using media::KeySource;
|
||||||
using media::MuxerOptions;
|
using media::MuxerOptions;
|
||||||
|
|
||||||
|
@ -602,11 +600,9 @@ Status Packager::Initialize(
|
||||||
const MpdParams& mpd_params = packaging_params.mpd_params;
|
const MpdParams& mpd_params = packaging_params.mpd_params;
|
||||||
if (!mpd_params.mpd_output.empty()) {
|
if (!mpd_params.mpd_output.empty()) {
|
||||||
if (mpd_params.generate_dash_if_iop_compliant_mpd) {
|
if (mpd_params.generate_dash_if_iop_compliant_mpd) {
|
||||||
internal->mpd_notifier.reset(new DashIopMpdNotifier(
|
internal->mpd_notifier.reset(new DashIopMpdNotifier(mpd_options));
|
||||||
mpd_options, mpd_params.base_urls, mpd_params.mpd_output));
|
|
||||||
} else {
|
} else {
|
||||||
internal->mpd_notifier.reset(new SimpleMpdNotifier(
|
internal->mpd_notifier.reset(new SimpleMpdNotifier(mpd_options));
|
||||||
mpd_options, mpd_params.base_urls, mpd_params.mpd_output));
|
|
||||||
}
|
}
|
||||||
if (!internal->mpd_notifier->Init()) {
|
if (!internal->mpd_notifier->Init()) {
|
||||||
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
||||||
|
|
|
@ -15,46 +15,11 @@
|
||||||
#include "packager/media/public/chunking_params.h"
|
#include "packager/media/public/chunking_params.h"
|
||||||
#include "packager/media/public/crypto_params.h"
|
#include "packager/media/public/crypto_params.h"
|
||||||
#include "packager/media/public/mp4_output_params.h"
|
#include "packager/media/public/mp4_output_params.h"
|
||||||
|
#include "packager/mpd/public/mpd_params.h"
|
||||||
#include "packager/status.h"
|
#include "packager/status.h"
|
||||||
|
|
||||||
namespace shaka {
|
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 <BaseURL> element(s)
|
|
||||||
/// under the <MPD> element.
|
|
||||||
std::vector<std::string> 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 <Role ... value=\"main\" />
|
|
||||||
/// 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.
|
/// HLS related parameters.
|
||||||
struct HlsParams {
|
struct HlsParams {
|
||||||
/// HLS playlist type. See HLS specification for details.
|
/// HLS playlist type. See HLS specification for details.
|
||||||
|
|
Loading…
Reference in New Issue