Merge SimpleMpdNotifier and DashIopMpdNotifier
Also removed MpdNotifier::AddContentProtectionElement which is not used anywhere. Change-Id: I69eb596ec377c601bb3e45bbef30c248c1d03e86
This commit is contained in:
parent
82842407cb
commit
66f713fd23
|
@ -1,126 +0,0 @@
|
||||||
// Copyright 2015 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
|
|
||||||
|
|
||||||
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
||||||
|
|
||||||
#include "packager/base/stl_util.h"
|
|
||||||
#include "packager/mpd/base/adaptation_set.h"
|
|
||||||
#include "packager/mpd/base/media_info.pb.h"
|
|
||||||
#include "packager/mpd/base/mpd_notifier_util.h"
|
|
||||||
#include "packager/mpd/base/period.h"
|
|
||||||
#include "packager/mpd/base/representation.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
const bool kContentProtectionInAdaptationSet = true;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace shaka {
|
|
||||||
|
|
||||||
DashIopMpdNotifier::DashIopMpdNotifier(const MpdOptions& mpd_options)
|
|
||||||
: MpdNotifier(mpd_options),
|
|
||||||
output_path_(mpd_options.mpd_params.mpd_output),
|
|
||||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
|
||||||
for (const std::string& base_url : mpd_options.mpd_params.base_urls)
|
|
||||||
mpd_builder_->AddBaseUrl(base_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
DashIopMpdNotifier::~DashIopMpdNotifier() {}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::Init() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
|
||||||
uint32_t* container_id) {
|
|
||||||
DCHECK(container_id);
|
|
||||||
|
|
||||||
ContentType content_type = GetContentType(media_info);
|
|
||||||
if (content_type == kContentTypeUnknown)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
base::AutoLock auto_lock(lock_);
|
|
||||||
if (!period_)
|
|
||||||
period_ = mpd_builder_->AddPeriod();
|
|
||||||
AdaptationSet* adaptation_set = period_->GetOrCreateAdaptationSet(
|
|
||||||
media_info, kContentProtectionInAdaptationSet);
|
|
||||||
DCHECK(adaptation_set);
|
|
||||||
|
|
||||||
MediaInfo adjusted_media_info(media_info);
|
|
||||||
MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
|
|
||||||
Representation* representation =
|
|
||||||
adaptation_set->AddRepresentation(adjusted_media_info);
|
|
||||||
if (!representation)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
|
|
||||||
|
|
||||||
*container_id = representation->id();
|
|
||||||
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
|
||||||
representation_map_[representation->id()] = representation;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::NotifySampleDuration(uint32_t container_id,
|
|
||||||
uint32_t sample_duration) {
|
|
||||||
base::AutoLock auto_lock(lock_);
|
|
||||||
auto it = representation_map_.find(container_id);
|
|
||||||
if (it == representation_map_.end()) {
|
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
it->second->SetSampleDuration(sample_duration);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::NotifyNewSegment(uint32_t container_id,
|
|
||||||
uint64_t start_time,
|
|
||||||
uint64_t duration,
|
|
||||||
uint64_t size) {
|
|
||||||
base::AutoLock auto_lock(lock_);
|
|
||||||
auto it = representation_map_.find(container_id);
|
|
||||||
if (it == representation_map_.end()) {
|
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
it->second->AddNewSegment(start_time, duration, size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::NotifyEncryptionUpdate(
|
|
||||||
uint32_t container_id,
|
|
||||||
const std::string& drm_uuid,
|
|
||||||
const std::vector<uint8_t>& new_key_id,
|
|
||||||
const std::vector<uint8_t>& new_pssh) {
|
|
||||||
base::AutoLock auto_lock(lock_);
|
|
||||||
auto it = representation_map_.find(container_id);
|
|
||||||
if (it == representation_map_.end()) {
|
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdaptationSet* adaptation_set_for_representation =
|
|
||||||
representation_id_to_adaptation_set_[it->second->id()];
|
|
||||||
adaptation_set_for_representation->UpdateContentProtectionPssh(
|
|
||||||
drm_uuid, Uint8VectorToBase64(new_pssh));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::AddContentProtectionElement(
|
|
||||||
uint32_t container_id,
|
|
||||||
const ContentProtectionElement& content_protection_element) {
|
|
||||||
// Intentionally not implemented because if a Representation gets a new
|
|
||||||
// <ContentProtection> element, then it might require moving the
|
|
||||||
// Representation out of the AdaptationSet. There's no logic to do that
|
|
||||||
// yet.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DashIopMpdNotifier::Flush() {
|
|
||||||
base::AutoLock auto_lock(lock_);
|
|
||||||
return WriteMpdToFile(output_path_, mpd_builder_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace shaka
|
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright 2015 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 MPD_BASE_DASH_IOP_MPD_NOTIFIER_H_
|
|
||||||
#define MPD_BASE_DASH_IOP_MPD_NOTIFIER_H_
|
|
||||||
|
|
||||||
#include "packager/mpd/base/mpd_notifier.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "packager/base/synchronization/lock.h"
|
|
||||||
#include "packager/mpd/base/mpd_notifier_util.h"
|
|
||||||
#include "packager/mpd/base/mpd_options.h"
|
|
||||||
|
|
||||||
namespace shaka {
|
|
||||||
|
|
||||||
class AdaptationSet;
|
|
||||||
class MpdBuilder;
|
|
||||||
class Period;
|
|
||||||
class Representation;
|
|
||||||
|
|
||||||
/// This class is an MpdNotifier which will try its best to generate a
|
|
||||||
/// DASH IF IOPv3 compliant MPD.
|
|
||||||
/// e.g.
|
|
||||||
/// All <ContentProtection> elements must be right under
|
|
||||||
/// <AdaptationSet> and cannot be under <Representation>.
|
|
||||||
/// All video Adaptation Sets have Role set to "main".
|
|
||||||
class DashIopMpdNotifier : public MpdNotifier {
|
|
||||||
public:
|
|
||||||
explicit DashIopMpdNotifier(const MpdOptions& mpd_options);
|
|
||||||
~DashIopMpdNotifier() override;
|
|
||||||
|
|
||||||
/// None of the methods write out the MPD file until Flush() is called.
|
|
||||||
/// @name MpdNotifier implemetation overrides.
|
|
||||||
/// @{
|
|
||||||
bool Init() override;
|
|
||||||
bool NotifyNewContainer(const MediaInfo& media_info, uint32_t* id) override;
|
|
||||||
bool NotifySampleDuration(uint32_t container_id,
|
|
||||||
uint32_t sample_duration) override;
|
|
||||||
bool NotifyNewSegment(uint32_t id,
|
|
||||||
uint64_t start_time,
|
|
||||||
uint64_t duration,
|
|
||||||
uint64_t size) override;
|
|
||||||
bool NotifyEncryptionUpdate(uint32_t container_id,
|
|
||||||
const std::string& drm_uuid,
|
|
||||||
const std::vector<uint8_t>& new_key_id,
|
|
||||||
const std::vector<uint8_t>& new_pssh) override;
|
|
||||||
bool AddContentProtectionElement(
|
|
||||||
uint32_t id,
|
|
||||||
const ContentProtectionElement& content_protection_element) override;
|
|
||||||
bool Flush() override;
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class DashIopMpdNotifierTest;
|
|
||||||
|
|
||||||
// Testing only method. Returns a pointer to MpdBuilder.
|
|
||||||
MpdBuilder* MpdBuilderForTesting() const {
|
|
||||||
return mpd_builder_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing only method. Sets mpd_builder_.
|
|
||||||
void SetMpdBuilderForTesting(std::unique_ptr<MpdBuilder> mpd_builder) {
|
|
||||||
mpd_builder_ = std::move(mpd_builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MPD output path.
|
|
||||||
std::string output_path_;
|
|
||||||
std::unique_ptr<MpdBuilder> mpd_builder_;
|
|
||||||
Period* period_ = nullptr; // owned by |mpd_builder_|.
|
|
||||||
base::Lock lock_;
|
|
||||||
|
|
||||||
// Maps representation ID to Representation.
|
|
||||||
std::map<uint32_t, Representation*> representation_map_;
|
|
||||||
// Maps Representation ID to AdaptationSet. This is for updating the PSSH.
|
|
||||||
std::map<uint32_t, AdaptationSet*> representation_id_to_adaptation_set_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace shaka
|
|
||||||
|
|
||||||
#endif // MPD_BASE_DASH_IOP_MPD_NOTIFIER_H_
|
|
|
@ -1,252 +0,0 @@
|
||||||
// Copyright 2015 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
|
|
||||||
|
|
||||||
#include <gmock/gmock.h>
|
|
||||||
#include <google/protobuf/util/message_differencer.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include "packager/base/files/file_path.h"
|
|
||||||
#include "packager/base/files/file_util.h"
|
|
||||||
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
||||||
#include "packager/mpd/base/mock_mpd_builder.h"
|
|
||||||
#include "packager/mpd/base/mpd_builder.h"
|
|
||||||
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
|
||||||
|
|
||||||
namespace shaka {
|
|
||||||
|
|
||||||
using ::testing::_;
|
|
||||||
using ::testing::AnyOf;
|
|
||||||
using ::testing::Eq;
|
|
||||||
using ::testing::Return;
|
|
||||||
using ::testing::StrEq;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const uint32_t kDefaultAdaptationSetId = 0u;
|
|
||||||
const uint32_t kDefaultRepresentationId = 1u;
|
|
||||||
const bool kContentProtectionInAdaptationSet = true;
|
|
||||||
|
|
||||||
MATCHER_P(EqualsProto, message, "") {
|
|
||||||
return ::google::protobuf::util::MessageDifferencer::Equals(arg, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// TODO(rkuroiwa): This is almost exactly the same as SimpleMpdNotifierTest but
|
|
||||||
// replaced all SimpleMpd with DashIopMpd,
|
|
||||||
// use typed tests
|
|
||||||
// (https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests);
|
|
||||||
// also because SimpleMpdNotifier and DashIopMpdNotifier have common behavior
|
|
||||||
// for most of the public functions.
|
|
||||||
class DashIopMpdNotifierTest : public ::testing::Test {
|
|
||||||
protected:
|
|
||||||
DashIopMpdNotifierTest()
|
|
||||||
: default_mock_period_(new MockPeriod),
|
|
||||||
default_mock_adaptation_set_(
|
|
||||||
new MockAdaptationSet(kDefaultAdaptationSetId)),
|
|
||||||
default_mock_representation_(
|
|
||||||
new MockRepresentation(kDefaultRepresentationId)) {}
|
|
||||||
|
|
||||||
void SetUp() override {
|
|
||||||
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
|
||||||
empty_mpd_option_.mpd_params.mpd_output = temp_file_path_.AsUTF8Unsafe();
|
|
||||||
|
|
||||||
// Three valid media info. The actual data does not matter.
|
|
||||||
const char kValidMediaInfo[] =
|
|
||||||
"video_info {\n"
|
|
||||||
" codec: 'avc1'\n"
|
|
||||||
" width: 1280\n"
|
|
||||||
" height: 720\n"
|
|
||||||
" time_scale: 10\n"
|
|
||||||
" frame_duration: 10\n"
|
|
||||||
" pixel_width: 1\n"
|
|
||||||
" pixel_height: 1\n"
|
|
||||||
"}\n"
|
|
||||||
"container_type: 1\n";
|
|
||||||
valid_media_info1_ = ConvertToMediaInfo(kValidMediaInfo);
|
|
||||||
valid_media_info2_ = valid_media_info1_;
|
|
||||||
valid_media_info2_.mutable_video_info()->set_width(960);
|
|
||||||
valid_media_info3_ = valid_media_info1_;
|
|
||||||
valid_media_info3_.mutable_video_info()->set_width(480);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TearDown() override {
|
|
||||||
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMpdBuilder(DashIopMpdNotifier* notifier,
|
|
||||||
std::unique_ptr<MpdBuilder> mpd_builder) {
|
|
||||||
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Empty mpd options except with output path specified, so that
|
|
||||||
// WriteMpdToFile() doesn't crash.
|
|
||||||
MpdOptions empty_mpd_option_;
|
|
||||||
|
|
||||||
// Default mocks that can be used for the tests.
|
|
||||||
// IOW, if a test only requires one instance of
|
|
||||||
// Mock{Period,AdaptationSet,Representation}, these can be used.
|
|
||||||
std::unique_ptr<MockPeriod> default_mock_period_;
|
|
||||||
std::unique_ptr<MockAdaptationSet> default_mock_adaptation_set_;
|
|
||||||
std::unique_ptr<MockRepresentation> default_mock_representation_;
|
|
||||||
|
|
||||||
// Three valid media info. The actual content does not matter.
|
|
||||||
MediaInfo valid_media_info1_;
|
|
||||||
MediaInfo valid_media_info2_;
|
|
||||||
MediaInfo valid_media_info3_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
base::FilePath temp_file_path_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that basic VOD NotifyNewContainer() operation works.
|
|
||||||
// No encrypted contents.
|
|
||||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_period_,
|
|
||||||
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_),
|
|
||||||
Eq(kContentProtectionInAdaptationSet)))
|
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
||||||
.WillOnce(Return(default_mock_representation_.get()));
|
|
||||||
|
|
||||||
// This is for the Flush() below but adding expectation here because the next
|
|
||||||
// std::move(lines) the pointer.
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, ToString(_)).WillOnce(Return(true));
|
|
||||||
|
|
||||||
uint32_t unused_container_id;
|
|
||||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
|
||||||
EXPECT_TRUE(
|
|
||||||
notifier.NotifyNewContainer(valid_media_info1_, &unused_container_id));
|
|
||||||
EXPECT_TRUE(notifier.Flush());
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddContentProtection() should not work and should always return false.
|
|
||||||
TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
||||||
.WillOnce(Return(default_mock_representation_.get()));
|
|
||||||
|
|
||||||
uint32_t container_id;
|
|
||||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
|
||||||
|
|
||||||
ContentProtectionElement empty_content_protection_element;
|
|
||||||
EXPECT_FALSE(notifier.AddContentProtectionElement(
|
|
||||||
container_id, empty_content_protection_element));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_);
|
|
||||||
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
||||||
.WillOnce(Return(default_mock_representation_.get()));
|
|
||||||
|
|
||||||
uint32_t container_id;
|
|
||||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
|
||||||
|
|
||||||
::testing::Mock::VerifyAndClearExpectations(
|
|
||||||
default_mock_adaptation_set_.get());
|
|
||||||
|
|
||||||
const uint8_t kBogusNewPssh[] = {// "psshsomethingelse" as uint8 array.
|
|
||||||
0x70, 0x73, 0x73, 0x68, 0x73, 0x6f,
|
|
||||||
0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e,
|
|
||||||
0x67, 0x65, 0x6c, 0x73, 0x65};
|
|
||||||
const std::vector<uint8_t> kBogusNewPsshVector(
|
|
||||||
kBogusNewPssh, kBogusNewPssh + arraysize(kBogusNewPssh));
|
|
||||||
const char kBogusNewPsshInBase64[] = "cHNzaHNvbWV0aGluZ2Vsc2U=";
|
|
||||||
|
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_,
|
|
||||||
UpdateContentProtectionPssh(StrEq("myuuid"),
|
|
||||||
StrEq(kBogusNewPsshInBase64)));
|
|
||||||
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
|
||||||
container_id, "myuuid", std::vector<uint8_t>(), kBogusNewPsshVector));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This test is mainly for tsan. Using both the notifier and the MpdBuilder.
|
|
||||||
// Although locks in MpdBuilder have been removed,
|
|
||||||
// https://github.com/google/shaka-packager/issues/45
|
|
||||||
// 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_);
|
|
||||||
uint32_t container_id;
|
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
|
||||||
const uint32_t kAnySampleDuration = 1000;
|
|
||||||
EXPECT_TRUE(notifier.NotifySampleDuration(container_id, kAnySampleDuration));
|
|
||||||
EXPECT_TRUE(notifier.Flush());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test multiple media info with some belongs to the same AdaptationSets.
|
|
||||||
TEST_F(DashIopMpdNotifierTest, MultipleMediaInfo) {
|
|
||||||
DashIopMpdNotifier notifier(empty_mpd_option_);
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
|
||||||
|
|
||||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
|
||||||
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
|
|
||||||
|
|
||||||
std::unique_ptr<MockRepresentation> representation1(
|
|
||||||
new MockRepresentation(1));
|
|
||||||
std::unique_ptr<MockRepresentation> representation2(
|
|
||||||
new MockRepresentation(2));
|
|
||||||
std::unique_ptr<MockRepresentation> representation3(
|
|
||||||
new MockRepresentation(3));
|
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
|
||||||
|
|
||||||
EXPECT_CALL(*default_mock_period_,
|
|
||||||
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_), _))
|
|
||||||
.WillOnce(Return(adaptation_set1.get()));
|
|
||||||
EXPECT_CALL(*adaptation_set1,
|
|
||||||
AddRepresentation(EqualsProto(valid_media_info1_)))
|
|
||||||
.WillOnce(Return(representation1.get()));
|
|
||||||
// Return the same adaptation set for |valid_media_info2_| and
|
|
||||||
// |valid_media_info3_|. This results in AddRepresentation to be called twice
|
|
||||||
// on |adaptation_set2|.
|
|
||||||
EXPECT_CALL(*default_mock_period_,
|
|
||||||
GetOrCreateAdaptationSet(AnyOf(EqualsProto(valid_media_info2_),
|
|
||||||
EqualsProto(valid_media_info3_)),
|
|
||||||
_))
|
|
||||||
.WillOnce(Return(adaptation_set2.get()))
|
|
||||||
.WillOnce(Return(adaptation_set2.get()));
|
|
||||||
EXPECT_CALL(*adaptation_set2,
|
|
||||||
AddRepresentation(AnyOf(EqualsProto(valid_media_info2_),
|
|
||||||
EqualsProto(valid_media_info3_))))
|
|
||||||
.WillOnce(Return(representation2.get()))
|
|
||||||
.WillOnce(Return(representation3.get()));
|
|
||||||
|
|
||||||
uint32_t unused_container_id;
|
|
||||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
|
||||||
EXPECT_TRUE(
|
|
||||||
notifier.NotifyNewContainer(valid_media_info1_, &unused_container_id));
|
|
||||||
EXPECT_TRUE(
|
|
||||||
notifier.NotifyNewContainer(valid_media_info2_, &unused_container_id));
|
|
||||||
EXPECT_TRUE(
|
|
||||||
notifier.NotifyNewContainer(valid_media_info3_, &unused_container_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace shaka
|
|
|
@ -85,16 +85,6 @@ class MpdNotifier {
|
||||||
const std::vector<uint8_t>& new_key_id,
|
const std::vector<uint8_t>& new_key_id,
|
||||||
const std::vector<uint8_t>& new_pssh) = 0;
|
const std::vector<uint8_t>& new_pssh) = 0;
|
||||||
|
|
||||||
/// Adds content protection information to the MPD.
|
|
||||||
/// @param container_id is the nummeric container ID obtained from calling
|
|
||||||
/// NotifyNewContainer().
|
|
||||||
/// @param content_protection_element New ContentProtection element
|
|
||||||
/// specification.
|
|
||||||
/// @return true on success, false otherwise.
|
|
||||||
virtual bool AddContentProtectionElement(
|
|
||||||
uint32_t container_id,
|
|
||||||
const ContentProtectionElement& content_protection_element) = 0;
|
|
||||||
|
|
||||||
/// Call this method to force a flush. Implementations might not write out
|
/// Call this method to force a flush. Implementations might not write out
|
||||||
/// the MPD to a stream (file, stdout, etc.) when the MPD is updated, this
|
/// the MPD to a stream (file, stdout, etc.) when the MPD is updated, this
|
||||||
/// forces a flush.
|
/// forces a flush.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 Google Inc. All rights reserved.
|
// Copyright 2015 Google Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file or at
|
// license that can be found in the LICENSE file or at
|
||||||
|
@ -15,22 +15,19 @@
|
||||||
#include "packager/mpd/base/period.h"
|
#include "packager/mpd/base/period.h"
|
||||||
#include "packager/mpd/base/representation.h"
|
#include "packager/mpd/base/representation.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
const bool kContentProtectionInAdaptationSet = true;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options)
|
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options)
|
||||||
: MpdNotifier(mpd_options),
|
: MpdNotifier(mpd_options),
|
||||||
output_path_(mpd_options.mpd_params.mpd_output),
|
output_path_(mpd_options.mpd_params.mpd_output),
|
||||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
mpd_builder_(new MpdBuilder(mpd_options)),
|
||||||
|
content_protection_in_adaptation_set_(
|
||||||
|
mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd) {
|
||||||
for (const std::string& base_url : mpd_options.mpd_params.base_urls)
|
for (const std::string& base_url : mpd_options.mpd_params.base_urls)
|
||||||
mpd_builder_->AddBaseUrl(base_url);
|
mpd_builder_->AddBaseUrl(base_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleMpdNotifier::~SimpleMpdNotifier() {
|
SimpleMpdNotifier::~SimpleMpdNotifier() {}
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleMpdNotifier::Init() {
|
bool SimpleMpdNotifier::Init() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -48,19 +45,25 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
||||||
if (!period_)
|
if (!period_)
|
||||||
period_ = mpd_builder_->AddPeriod();
|
period_ = mpd_builder_->AddPeriod();
|
||||||
AdaptationSet* adaptation_set = period_->GetOrCreateAdaptationSet(
|
AdaptationSet* adaptation_set = period_->GetOrCreateAdaptationSet(
|
||||||
media_info, !kContentProtectionInAdaptationSet);
|
media_info, content_protection_in_adaptation_set_);
|
||||||
DCHECK(adaptation_set);
|
DCHECK(adaptation_set);
|
||||||
|
|
||||||
MediaInfo adjusted_media_info(media_info);
|
MediaInfo adjusted_media_info(media_info);
|
||||||
MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
|
MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
|
||||||
Representation* representation =
|
Representation* representation =
|
||||||
adaptation_set->AddRepresentation(adjusted_media_info);
|
adaptation_set->AddRepresentation(adjusted_media_info);
|
||||||
if (representation == NULL)
|
if (!representation)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// For SimpleMpdNotifier, just put it in Representation. It should still
|
if (content_protection_in_adaptation_set_) {
|
||||||
// generate a valid MPD.
|
// ContentProtection elements are already added to AdaptationSet above.
|
||||||
|
// Use RepresentationId to AdaptationSet map to update ContentProtection
|
||||||
|
// in AdaptationSet in NotifyEncryptionUpdate.
|
||||||
|
representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
|
||||||
|
} else {
|
||||||
AddContentProtectionElements(media_info, representation);
|
AddContentProtectionElements(media_info, representation);
|
||||||
|
}
|
||||||
|
|
||||||
*container_id = representation->id();
|
*container_id = representation->id();
|
||||||
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
||||||
representation_map_[representation->id()] = representation;
|
representation_map_[representation->id()] = representation;
|
||||||
|
@ -70,7 +73,7 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
||||||
bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
|
bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
|
||||||
uint32_t sample_duration) {
|
uint32_t sample_duration) {
|
||||||
base::AutoLock auto_lock(lock_);
|
base::AutoLock auto_lock(lock_);
|
||||||
RepresentationMap::iterator it = representation_map_.find(container_id);
|
auto it = representation_map_.find(container_id);
|
||||||
if (it == representation_map_.end()) {
|
if (it == representation_map_.end()) {
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
||||||
return false;
|
return false;
|
||||||
|
@ -84,7 +87,7 @@ bool SimpleMpdNotifier::NotifyNewSegment(uint32_t container_id,
|
||||||
uint64_t duration,
|
uint64_t duration,
|
||||||
uint64_t size) {
|
uint64_t size) {
|
||||||
base::AutoLock auto_lock(lock_);
|
base::AutoLock auto_lock(lock_);
|
||||||
RepresentationMap::iterator it = representation_map_.find(container_id);
|
auto it = representation_map_.find(container_id);
|
||||||
if (it == representation_map_.end()) {
|
if (it == representation_map_.end()) {
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
||||||
return false;
|
return false;
|
||||||
|
@ -99,26 +102,21 @@ bool SimpleMpdNotifier::NotifyEncryptionUpdate(
|
||||||
const std::vector<uint8_t>& new_key_id,
|
const std::vector<uint8_t>& new_key_id,
|
||||||
const std::vector<uint8_t>& new_pssh) {
|
const std::vector<uint8_t>& new_pssh) {
|
||||||
base::AutoLock auto_lock(lock_);
|
base::AutoLock auto_lock(lock_);
|
||||||
RepresentationMap::iterator it = representation_map_.find(container_id);
|
auto it = representation_map_.find(container_id);
|
||||||
if (it == representation_map_.end()) {
|
if (it == representation_map_.end()) {
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
it->second->UpdateContentProtectionPssh(drm_uuid,
|
|
||||||
Uint8VectorToBase64(new_pssh));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleMpdNotifier::AddContentProtectionElement(
|
if (content_protection_in_adaptation_set_) {
|
||||||
uint32_t container_id,
|
AdaptationSet* adaptation_set_for_representation =
|
||||||
const ContentProtectionElement& content_protection_element) {
|
representation_id_to_adaptation_set_[it->second->id()];
|
||||||
base::AutoLock auto_lock(lock_);
|
adaptation_set_for_representation->UpdateContentProtectionPssh(
|
||||||
RepresentationMap::iterator it = representation_map_.find(container_id);
|
drm_uuid, Uint8VectorToBase64(new_pssh));
|
||||||
if (it == representation_map_.end()) {
|
} else {
|
||||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
it->second->UpdateContentProtectionPssh(drm_uuid,
|
||||||
return false;
|
Uint8VectorToBase64(new_pssh));
|
||||||
}
|
}
|
||||||
it->second->AddContentProtectionElement(content_protection_element);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "packager/base/gtest_prod_util.h"
|
|
||||||
#include "packager/base/synchronization/lock.h"
|
#include "packager/base/synchronization/lock.h"
|
||||||
#include "packager/mpd/base/mpd_notifier.h"
|
#include "packager/mpd/base/mpd_notifier.h"
|
||||||
#include "packager/mpd/base/mpd_notifier_util.h"
|
#include "packager/mpd/base/mpd_notifier_util.h"
|
||||||
|
@ -23,7 +22,6 @@ class AdaptationSet;
|
||||||
class MpdBuilder;
|
class MpdBuilder;
|
||||||
class Period;
|
class Period;
|
||||||
class Representation;
|
class Representation;
|
||||||
class SimpleMpdNotifierTest;
|
|
||||||
|
|
||||||
struct MpdOptions;
|
struct MpdOptions;
|
||||||
|
|
||||||
|
@ -34,6 +32,7 @@ class SimpleMpdNotifier : public MpdNotifier {
|
||||||
explicit SimpleMpdNotifier(const MpdOptions& mpd_options);
|
explicit SimpleMpdNotifier(const MpdOptions& mpd_options);
|
||||||
~SimpleMpdNotifier() override;
|
~SimpleMpdNotifier() override;
|
||||||
|
|
||||||
|
/// None of the methods write out the MPD file until Flush() is called.
|
||||||
/// @name MpdNotifier implemetation overrides.
|
/// @name MpdNotifier implemetation overrides.
|
||||||
/// @{
|
/// @{
|
||||||
bool Init() override;
|
bool Init() override;
|
||||||
|
@ -48,19 +47,17 @@ class SimpleMpdNotifier : public MpdNotifier {
|
||||||
const std::string& drm_uuid,
|
const std::string& drm_uuid,
|
||||||
const std::vector<uint8_t>& new_key_id,
|
const std::vector<uint8_t>& new_key_id,
|
||||||
const std::vector<uint8_t>& new_pssh) override;
|
const std::vector<uint8_t>& new_pssh) override;
|
||||||
bool AddContentProtectionElement(
|
|
||||||
uint32_t id,
|
|
||||||
const ContentProtectionElement& content_protection_element) override;
|
|
||||||
bool Flush() override;
|
bool Flush() override;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SimpleMpdNotifier(const SimpleMpdNotifier&) = delete;
|
||||||
|
SimpleMpdNotifier& operator=(const SimpleMpdNotifier&) = delete;
|
||||||
|
|
||||||
friend class SimpleMpdNotifierTest;
|
friend class SimpleMpdNotifierTest;
|
||||||
|
|
||||||
// Testing only method. Returns a pointer to MpdBuilder.
|
// Testing only method. Returns a pointer to MpdBuilder.
|
||||||
MpdBuilder* MpdBuilderForTesting() const {
|
MpdBuilder* MpdBuilderForTesting() const { return mpd_builder_.get(); }
|
||||||
return mpd_builder_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing only method. Sets mpd_builder_.
|
// Testing only method. Sets mpd_builder_.
|
||||||
void SetMpdBuilderForTesting(std::unique_ptr<MpdBuilder> mpd_builder) {
|
void SetMpdBuilderForTesting(std::unique_ptr<MpdBuilder> mpd_builder) {
|
||||||
|
@ -70,16 +67,14 @@ class SimpleMpdNotifier : public MpdNotifier {
|
||||||
// MPD output path.
|
// MPD output path.
|
||||||
std::string output_path_;
|
std::string output_path_;
|
||||||
std::unique_ptr<MpdBuilder> mpd_builder_;
|
std::unique_ptr<MpdBuilder> mpd_builder_;
|
||||||
Period* period_ = nullptr;
|
Period* period_ = nullptr; // owned by |mpd_builder_|.
|
||||||
|
bool content_protection_in_adaptation_set_ = true;
|
||||||
base::Lock lock_;
|
base::Lock lock_;
|
||||||
|
|
||||||
typedef std::map<std::string, AdaptationSet*> AdaptationSetMap;
|
// Maps Representation ID to Representation.
|
||||||
AdaptationSetMap adaptation_set_map_;
|
std::map<uint32_t, Representation*> representation_map_;
|
||||||
|
// Maps Representation ID to AdaptationSet. This is for updating the PSSH.
|
||||||
typedef std::map<uint32_t, Representation*> RepresentationMap;
|
std::map<uint32_t, AdaptationSet*> representation_id_to_adaptation_set_;
|
||||||
RepresentationMap representation_map_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(SimpleMpdNotifier);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -103,8 +103,7 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
.WillOnce(Return(default_mock_period_.get()));
|
||||||
EXPECT_CALL(*default_mock_period_,
|
EXPECT_CALL(*default_mock_period_,
|
||||||
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_),
|
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_), _))
|
||||||
Eq(!kContentProtectionInAdaptationSet)))
|
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_,
|
EXPECT_CALL(*default_mock_adaptation_set_,
|
||||||
AddRepresentation(EqualsProto(valid_media_info1_)))
|
AddRepresentation(EqualsProto(valid_media_info1_)))
|
||||||
|
@ -191,33 +190,13 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
|
||||||
kSegmentDuration, kSegmentSize));
|
kSegmentDuration, kSegmentSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
|
TEST_F(SimpleMpdNotifierTest,
|
||||||
SimpleMpdNotifier notifier(empty_mpd_option_);
|
ContentProtectionInAdaptationSetUpdateEncryption) {
|
||||||
|
MpdOptions mpd_options = empty_mpd_option_;
|
||||||
|
mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd =
|
||||||
|
kContentProtectionInAdaptationSet;
|
||||||
|
SimpleMpdNotifier notifier(mpd_options);
|
||||||
|
|
||||||
const uint32_t kRepresentationId = 0u;
|
|
||||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
|
||||||
std::unique_ptr<MockRepresentation> mock_representation(
|
|
||||||
new MockRepresentation(kRepresentationId));
|
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
||||||
.WillOnce(Return(mock_representation.get()));
|
|
||||||
|
|
||||||
uint32_t container_id;
|
|
||||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
|
||||||
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
|
||||||
EXPECT_EQ(kRepresentationId, container_id);
|
|
||||||
|
|
||||||
ContentProtectionElement element;
|
|
||||||
EXPECT_CALL(*mock_representation, AddContentProtectionElement(_));
|
|
||||||
EXPECT_TRUE(notifier.AddContentProtectionElement(kRepresentationId, element));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(SimpleMpdNotifierTest, UpdateEncryption) {
|
|
||||||
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(
|
||||||
|
@ -225,7 +204,52 @@ TEST_F(SimpleMpdNotifierTest, UpdateEncryption) {
|
||||||
|
|
||||||
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
||||||
.WillOnce(Return(default_mock_period_.get()));
|
.WillOnce(Return(default_mock_period_.get()));
|
||||||
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
EXPECT_CALL(
|
||||||
|
*default_mock_period_,
|
||||||
|
GetOrCreateAdaptationSet(_, Eq(kContentProtectionInAdaptationSet)))
|
||||||
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||||
|
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
||||||
|
.WillOnce(Return(mock_representation.get()));
|
||||||
|
|
||||||
|
uint32_t container_id;
|
||||||
|
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
||||||
|
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
||||||
|
|
||||||
|
::testing::Mock::VerifyAndClearExpectations(
|
||||||
|
default_mock_adaptation_set_.get());
|
||||||
|
|
||||||
|
// "psshsomethingelse" as uint8 array.
|
||||||
|
const uint8_t kBogusNewPssh[] = {0x70, 0x73, 0x73, 0x68, 0x73, 0x6f,
|
||||||
|
0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e,
|
||||||
|
0x67, 0x65, 0x6c, 0x73, 0x65};
|
||||||
|
const std::vector<uint8_t> kBogusNewPsshVector(
|
||||||
|
kBogusNewPssh, kBogusNewPssh + arraysize(kBogusNewPssh));
|
||||||
|
const char kBogusNewPsshInBase64[] = "cHNzaHNvbWV0aGluZ2Vsc2U=";
|
||||||
|
|
||||||
|
EXPECT_CALL(*default_mock_adaptation_set_,
|
||||||
|
UpdateContentProtectionPssh(StrEq("myuuid"),
|
||||||
|
StrEq(kBogusNewPsshInBase64)));
|
||||||
|
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
||||||
|
container_id, "myuuid", std::vector<uint8_t>(), kBogusNewPsshVector));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SimpleMpdNotifierTest,
|
||||||
|
ContentProtectionNotInAdaptationSetUpdateEncryption) {
|
||||||
|
MpdOptions mpd_options = empty_mpd_option_;
|
||||||
|
mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd =
|
||||||
|
!kContentProtectionInAdaptationSet;
|
||||||
|
SimpleMpdNotifier notifier(mpd_options);
|
||||||
|
|
||||||
|
const uint32_t kRepresentationId = 447834u;
|
||||||
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||||
|
std::unique_ptr<MockRepresentation> mock_representation(
|
||||||
|
new MockRepresentation(kRepresentationId));
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
||||||
|
.WillOnce(Return(default_mock_period_.get()));
|
||||||
|
EXPECT_CALL(
|
||||||
|
*default_mock_period_,
|
||||||
|
GetOrCreateAdaptationSet(_, Eq(!kContentProtectionInAdaptationSet)))
|
||||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
||||||
.WillOnce(Return(mock_representation.get()));
|
.WillOnce(Return(mock_representation.get()));
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
'base/bandwidth_estimator.h',
|
'base/bandwidth_estimator.h',
|
||||||
'base/content_protection_element.cc',
|
'base/content_protection_element.cc',
|
||||||
'base/content_protection_element.h',
|
'base/content_protection_element.h',
|
||||||
'base/dash_iop_mpd_notifier.cc',
|
|
||||||
'base/dash_iop_mpd_notifier.h',
|
|
||||||
'base/mpd_builder.cc',
|
'base/mpd_builder.cc',
|
||||||
'base/mpd_builder.h',
|
'base/mpd_builder.h',
|
||||||
'base/mpd_notifier_util.cc',
|
'base/mpd_notifier_util.cc',
|
||||||
|
@ -88,7 +86,6 @@
|
||||||
'sources': [
|
'sources': [
|
||||||
'base/adaptation_set_unittest.cc',
|
'base/adaptation_set_unittest.cc',
|
||||||
'base/bandwidth_estimator_unittest.cc',
|
'base/bandwidth_estimator_unittest.cc',
|
||||||
'base/dash_iop_mpd_notifier_unittest.cc',
|
|
||||||
'base/mpd_builder_unittest.cc',
|
'base/mpd_builder_unittest.cc',
|
||||||
'base/period_unittest.cc',
|
'base/period_unittest.cc',
|
||||||
'base/representation_unittest.cc',
|
'base/representation_unittest.cc',
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "packager/base/files/file_path.h"
|
#include "packager/base/files/file_path.h"
|
||||||
#include "packager/base/files/file_util.h"
|
#include "packager/base/files/file_util.h"
|
||||||
#include "packager/file/file.h"
|
#include "packager/file/file.h"
|
||||||
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
||||||
#include "packager/mpd/base/mpd_builder.h"
|
#include "packager/mpd/base/mpd_builder.h"
|
||||||
#include "packager/mpd/base/mpd_notifier.h"
|
#include "packager/mpd/base/mpd_notifier.h"
|
||||||
#include "packager/mpd/base/mpd_utils.h"
|
#include "packager/mpd/base/mpd_utils.h"
|
||||||
|
@ -29,17 +28,6 @@ namespace shaka {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Factory that creates DashIopMpdNotifier instances.
|
|
||||||
class DashIopMpdNotifierFactory : public MpdNotifierFactory {
|
|
||||||
public:
|
|
||||||
DashIopMpdNotifierFactory() {}
|
|
||||||
~DashIopMpdNotifierFactory() override {}
|
|
||||||
|
|
||||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options) override {
|
|
||||||
return std::unique_ptr<MpdNotifier>(new DashIopMpdNotifier(mpd_options));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Factory that creates SimpleMpdNotifier instances.
|
// Factory that creates SimpleMpdNotifier instances.
|
||||||
class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
||||||
public:
|
public:
|
||||||
|
@ -53,12 +41,7 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MpdWriter::MpdWriter()
|
MpdWriter::MpdWriter() : notifier_factory_(new SimpleMpdNotifierFactory()) {}
|
||||||
: notifier_factory_(FLAGS_generate_dash_if_iop_compliant_mpd
|
|
||||||
? static_cast<MpdNotifierFactory*>(
|
|
||||||
new DashIopMpdNotifierFactory())
|
|
||||||
: static_cast<MpdNotifierFactory*>(
|
|
||||||
new SimpleMpdNotifierFactory())) {}
|
|
||||||
MpdWriter::~MpdWriter() {}
|
MpdWriter::~MpdWriter() {}
|
||||||
|
|
||||||
bool MpdWriter::AddFile(const std::string& media_info_path,
|
bool MpdWriter::AddFile(const std::string& media_info_path,
|
||||||
|
@ -90,6 +73,8 @@ bool MpdWriter::WriteMpdToFile(const char* file_name) {
|
||||||
MpdOptions mpd_options;
|
MpdOptions mpd_options;
|
||||||
mpd_options.mpd_params.base_urls = base_urls_;
|
mpd_options.mpd_params.base_urls = base_urls_;
|
||||||
mpd_options.mpd_params.mpd_output = file_name;
|
mpd_options.mpd_params.mpd_output = file_name;
|
||||||
|
mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd =
|
||||||
|
FLAGS_generate_dash_if_iop_compliant_mpd;
|
||||||
std::unique_ptr<MpdNotifier> notifier =
|
std::unique_ptr<MpdNotifier> notifier =
|
||||||
notifier_factory_->Create(mpd_options);
|
notifier_factory_->Create(mpd_options);
|
||||||
if (!notifier->Init()) {
|
if (!notifier->Init()) {
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include "packager/base/files/file_util.h"
|
#include "packager/base/files/file_util.h"
|
||||||
#include "packager/base/path_service.h"
|
#include "packager/base/path_service.h"
|
||||||
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
||||||
#include "packager/mpd/base/mock_mpd_notifier.h"
|
#include "packager/mpd/base/mock_mpd_notifier.h"
|
||||||
#include "packager/mpd/base/mpd_options.h"
|
#include "packager/mpd/base/mpd_options.h"
|
||||||
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "packager/media/formats/webm/webm_muxer.h"
|
#include "packager/media/formats/webm/webm_muxer.h"
|
||||||
#include "packager/media/replicator/replicator.h"
|
#include "packager/media/replicator/replicator.h"
|
||||||
#include "packager/media/trick_play/trick_play_handler.h"
|
#include "packager/media/trick_play/trick_play_handler.h"
|
||||||
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
||||||
#include "packager/mpd/base/media_info.pb.h"
|
#include "packager/mpd/base/media_info.pb.h"
|
||||||
#include "packager/mpd/base/mpd_builder.h"
|
#include "packager/mpd/base/mpd_builder.h"
|
||||||
#include "packager/mpd/base/simple_mpd_notifier.h"
|
#include "packager/mpd/base/simple_mpd_notifier.h"
|
||||||
|
@ -702,13 +701,9 @@ Status Packager::Initialize(
|
||||||
if (!mpd_params.mpd_output.empty()) {
|
if (!mpd_params.mpd_output.empty()) {
|
||||||
const bool on_demand_dash_profile =
|
const bool on_demand_dash_profile =
|
||||||
stream_descriptors.begin()->segment_template.empty();
|
stream_descriptors.begin()->segment_template.empty();
|
||||||
MpdOptions mpd_options =
|
const MpdOptions mpd_options =
|
||||||
media::GetMpdOptions(on_demand_dash_profile, mpd_params);
|
media::GetMpdOptions(on_demand_dash_profile, mpd_params);
|
||||||
if (mpd_params.generate_dash_if_iop_compliant_mpd) {
|
|
||||||
internal->mpd_notifier.reset(new DashIopMpdNotifier(mpd_options));
|
|
||||||
} else {
|
|
||||||
internal->mpd_notifier.reset(new SimpleMpdNotifier(mpd_options));
|
internal->mpd_notifier.reset(new SimpleMpdNotifier(mpd_options));
|
||||||
}
|
|
||||||
if (!internal->mpd_notifier->Init()) {
|
if (!internal->mpd_notifier->Init()) {
|
||||||
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
||||||
return Status(error::INVALID_ARGUMENT,
|
return Status(error::INVALID_ARGUMENT,
|
||||||
|
|
Loading…
Reference in New Issue