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 {
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
||||
std::unique_ptr<RequestSigner> request_signer;
|
||||
switch (signer.signing_key_type) {
|
||||
|
@ -47,6 +45,8 @@ std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
|
|||
return request_signer;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<KeySource> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,18 +10,15 @@
|
|||
#define PACKAGER_APP_PACKAGER_UTIL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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<KeySource> 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<KeySource> 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.
|
||||
|
|
|
@ -38,15 +38,12 @@ std::set<std::string> GetUUIDs(
|
|||
|
||||
} // namespace
|
||||
|
||||
DashIopMpdNotifier::DashIopMpdNotifier(
|
||||
const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& 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() {}
|
||||
|
|
|
@ -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<std::string>& 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.
|
||||
|
|
|
@ -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<std::string> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<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.
|
||||
// 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||
|
|
|
@ -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<uint64_t>(mpd_options_.time_shift_buffer_depth * time_scale);
|
||||
uint64_t time_shift_buffer_depth = static_cast<uint64_t>(
|
||||
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.
|
||||
|
|
|
@ -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<uint64_t>(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();
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
|
|
|
@ -14,14 +14,12 @@
|
|||
|
||||
namespace shaka {
|
||||
|
||||
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& 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() {
|
||||
|
|
|
@ -30,9 +30,7 @@ struct MpdOptions;
|
|||
/// generates an Mpd file.
|
||||
class SimpleMpdNotifier : public MpdNotifier {
|
||||
public:
|
||||
SimpleMpdNotifier(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path);
|
||||
explicit SimpleMpdNotifier(const MpdOptions& mpd_options);
|
||||
~SimpleMpdNotifier() override;
|
||||
|
||||
/// @name MpdNotifier implemetation overrides.
|
||||
|
|
|
@ -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<std::string> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> 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<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> 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<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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() override {}
|
||||
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
return std::unique_ptr<MpdNotifier>(
|
||||
new DashIopMpdNotifier(mpd_options, base_urls, output_path));
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||
return std::unique_ptr<MpdNotifier>(new DashIopMpdNotifier(mpd_options));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -49,11 +46,8 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
|||
SimpleMpdNotifierFactory() {}
|
||||
~SimpleMpdNotifierFactory() override {}
|
||||
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
return std::unique_ptr<MpdNotifier>(
|
||||
new SimpleMpdNotifier(mpd_options, base_urls, output_path));
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||
return std::unique_ptr<MpdNotifier>(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<MpdNotifier> 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;
|
||||
|
|
|
@ -35,9 +35,7 @@ class MpdNotifierFactory {
|
|||
virtual ~MpdNotifierFactory() {}
|
||||
|
||||
virtual std::unique_ptr<MpdNotifier> Create(
|
||||
const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& 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
|
||||
|
|
|
@ -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<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
EXPECT_EQ(expected_base_urls_, base_urls);
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
||||
EXPECT_EQ(expected_base_urls_, mpd_options.mpd_params.base_urls);
|
||||
|
||||
std::unique_ptr<MockMpdNotifier> mock_notifier(
|
||||
new MockMpdNotifier(mpd_options));
|
||||
|
|
|
@ -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.";
|
||||
|
|
|
@ -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 <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.
|
||||
struct HlsParams {
|
||||
/// HLS playlist type. See HLS specification for details.
|
||||
|
|
Loading…
Reference in New Issue