Use relative paths for files referenced in the MPD (2nd round).
Change-Id: I929b777dc3353fb868489b42e11578d2aa075510
This commit is contained in:
parent
7798a1b845
commit
a1ce657a06
|
@ -63,7 +63,7 @@ ExitStatus RunMpdGenerator() {
|
||||||
mpd_writer.AddBaseUrl(*it);
|
mpd_writer.AddBaseUrl(*it);
|
||||||
|
|
||||||
for (Iterator it = input_files.begin(); it != input_files.end(); ++it) {
|
for (Iterator it = input_files.begin(); it != input_files.end(); ++it) {
|
||||||
if (!mpd_writer.AddFile(it->c_str())) {
|
if (!mpd_writer.AddFile(it->c_str(), FLAGS_output)) {
|
||||||
LOG(WARNING) << "MpdWriter failed to read " << *it << ", skipping.";
|
LOG(WARNING) << "MpdWriter failed to read " << *it << ", skipping.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "packager/base/files/file_path.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
|
||||||
|
using base::FilePath;
|
||||||
using xml::XmlNode;
|
using xml::XmlNode;
|
||||||
using xml::RepresentationXmlNode;
|
using xml::RepresentationXmlNode;
|
||||||
using xml::AdaptationSetXmlNode;
|
using xml::AdaptationSetXmlNode;
|
||||||
|
@ -181,6 +183,10 @@ bool WriteXmlCharArrayToOutput(xmlChar* doc,
|
||||||
return output->Flush();
|
return output->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string MakePathRelative(const std::string& path, const std::string& mpd_dir) {
|
||||||
|
return (path.find(mpd_dir) == 0) ? path.substr(mpd_dir.size()) : path;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MpdBuilder::MpdBuilder(MpdType type, const MpdOptions& mpd_options)
|
MpdBuilder::MpdBuilder(MpdType type, const MpdOptions& mpd_options)
|
||||||
|
@ -413,6 +419,33 @@ bool MpdBuilder::GetEarliestTimestamp(double* timestamp_seconds) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MpdBuilder::MakePathsRelativeToMpd(const std::string& mpd_path,
|
||||||
|
MediaInfo* media_info) {
|
||||||
|
DCHECK(media_info);
|
||||||
|
const std::string kFileProtocol("file://");
|
||||||
|
std::string mpd_file_path = (mpd_path.find(kFileProtocol) == 0) ?
|
||||||
|
mpd_path.substr(kFileProtocol.size()) : mpd_path;
|
||||||
|
|
||||||
|
if (!mpd_file_path.empty()) {
|
||||||
|
std::string mpd_dir(
|
||||||
|
FilePath(mpd_file_path).DirName().AsEndingWithSeparator().value());
|
||||||
|
if (!mpd_dir.empty()) {
|
||||||
|
if (media_info->has_media_file_name()) {
|
||||||
|
media_info->set_media_file_name(
|
||||||
|
MakePathRelative(media_info->media_file_name(), mpd_dir));
|
||||||
|
}
|
||||||
|
if (media_info->has_init_segment_name()) {
|
||||||
|
media_info->set_init_segment_name(
|
||||||
|
MakePathRelative(media_info->init_segment_name(), mpd_dir));
|
||||||
|
}
|
||||||
|
if (media_info->has_segment_template()) {
|
||||||
|
media_info->set_segment_template(
|
||||||
|
MakePathRelative(media_info->segment_template(), mpd_dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AdaptationSet::AdaptationSet(uint32_t adaptation_set_id,
|
AdaptationSet::AdaptationSet(uint32_t adaptation_set_id,
|
||||||
const MpdOptions& mpd_options,
|
const MpdOptions& mpd_options,
|
||||||
base::AtomicSequenceNumber* counter)
|
base::AtomicSequenceNumber* counter)
|
||||||
|
|
|
@ -82,6 +82,14 @@ class MpdBuilder {
|
||||||
/// @return The mpd type.
|
/// @return The mpd type.
|
||||||
MpdType type() { return type_; }
|
MpdType type() { return type_; }
|
||||||
|
|
||||||
|
/// Adjusts the fields of MediaInfo so that paths are relative to the
|
||||||
|
/// specified MPD path.
|
||||||
|
/// @param mpd_path is the file path of the MPD file.
|
||||||
|
/// @param media_info is the MediaInfo object to be updated with relative
|
||||||
|
/// paths.
|
||||||
|
static void MakePathsRelativeToMpd(const std::string& mpd_path,
|
||||||
|
MediaInfo* media_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
|
// DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
|
||||||
// doesn't need to depend on current time.
|
// doesn't need to depend on current time.
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
|
||||||
|
using base::FilePath;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char kSElementTemplate[] =
|
const char kSElementTemplate[] =
|
||||||
"<S t=\"%" PRIu64 "\" d=\"%" PRIu64 "\" r=\"%" PRIu64 "\"/>\n";
|
"<S t=\"%" PRIu64 "\" d=\"%" PRIu64 "\" r=\"%" PRIu64 "\"/>\n";
|
||||||
|
@ -816,4 +818,51 @@ TEST_F(TimeShiftBufferDepthTest, ManySegments) {
|
||||||
kDefaultStartNumber + kExpectedRemovedSegments));
|
kDefaultStartNumber + kExpectedRemovedSegments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RelativePaths, PathsModified) {
|
||||||
|
const std::string kCommonPath(FilePath("foo").Append("bar").value());
|
||||||
|
const std::string kMediaFileBase("media.mp4");
|
||||||
|
const std::string kInitSegmentBase("init.mp4");
|
||||||
|
const std::string kSegmentTemplateBase("segment-$Number$.mp4");
|
||||||
|
const std::string kMediaFile(
|
||||||
|
FilePath(kCommonPath).Append(kMediaFileBase).value());
|
||||||
|
const std::string kInitSegment(
|
||||||
|
FilePath(kCommonPath).Append(kInitSegmentBase).value());
|
||||||
|
const std::string kSegmentTemplate(
|
||||||
|
FilePath(kCommonPath).Append(kSegmentTemplateBase).value());
|
||||||
|
const std::string kMpd(FilePath(kCommonPath).Append("media.mpd").value());
|
||||||
|
MediaInfo media_info;
|
||||||
|
|
||||||
|
media_info.set_media_file_name(kMediaFile);
|
||||||
|
media_info.set_init_segment_name(kInitSegment);
|
||||||
|
media_info.set_segment_template(kSegmentTemplate);
|
||||||
|
MpdBuilder::MakePathsRelativeToMpd(kMpd, &media_info);
|
||||||
|
EXPECT_EQ(kMediaFileBase, media_info.media_file_name());
|
||||||
|
EXPECT_EQ(kInitSegmentBase, media_info.init_segment_name());
|
||||||
|
EXPECT_EQ(kSegmentTemplateBase, media_info.segment_template());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RelativePaths, PathsNotModified) {
|
||||||
|
const std::string kMediaCommon(FilePath("foo").Append("bar").value());
|
||||||
|
const std::string kMediaFileBase("media.mp4");
|
||||||
|
const std::string kInitSegmentBase("init.mp4");
|
||||||
|
const std::string kSegmentTemplateBase("segment-$Number$.mp4");
|
||||||
|
const std::string kMediaFile(
|
||||||
|
FilePath(kMediaCommon).Append(kMediaFileBase).value());
|
||||||
|
const std::string kInitSegment(
|
||||||
|
FilePath(kMediaCommon).Append(kInitSegmentBase).value());
|
||||||
|
const std::string kSegmentTemplate(
|
||||||
|
FilePath(kMediaCommon).Append(kSegmentTemplateBase).value());
|
||||||
|
const std::string kMpd(
|
||||||
|
FilePath("foo").Append("baz").Append("media.mpd").value());
|
||||||
|
MediaInfo media_info;
|
||||||
|
|
||||||
|
media_info.set_media_file_name(kMediaFile);
|
||||||
|
media_info.set_init_segment_name(kInitSegment);
|
||||||
|
media_info.set_segment_template(kSegmentTemplate);
|
||||||
|
MpdBuilder::MakePathsRelativeToMpd(kMpd, &media_info);
|
||||||
|
EXPECT_EQ(kMediaFile, media_info.media_file_name());
|
||||||
|
EXPECT_EQ(kInitSegment, media_info.init_segment_name());
|
||||||
|
EXPECT_EQ(kSegmentTemplate, media_info.segment_template());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace edash_packager
|
} // namespace edash_packager
|
||||||
|
|
|
@ -53,8 +53,10 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
||||||
*adaptation_set = mpd_builder_->AddAdaptationSet();
|
*adaptation_set = mpd_builder_->AddAdaptationSet();
|
||||||
|
|
||||||
DCHECK(*adaptation_set);
|
DCHECK(*adaptation_set);
|
||||||
|
MediaInfo adjusted_media_info(media_info);
|
||||||
|
MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
|
||||||
Representation* representation =
|
Representation* representation =
|
||||||
(*adaptation_set)->AddRepresentation(media_info);
|
(*adaptation_set)->AddRepresentation(adjusted_media_info);
|
||||||
if (representation == NULL)
|
if (representation == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -125,12 +125,12 @@ bool SetMediaInfosToMpdBuilder(const std::list<MediaInfo>& media_infos,
|
||||||
MpdWriter::MpdWriter() {}
|
MpdWriter::MpdWriter() {}
|
||||||
MpdWriter::~MpdWriter() {}
|
MpdWriter::~MpdWriter() {}
|
||||||
|
|
||||||
bool MpdWriter::AddFile(const char* file_name) {
|
bool MpdWriter::AddFile(const std::string& media_info_path,
|
||||||
CHECK(file_name);
|
const std::string& mpd_path) {
|
||||||
|
|
||||||
std::string file_content;
|
std::string file_content;
|
||||||
if (!media::File::ReadFileToString(file_name, &file_content)) {
|
if (!media::File::ReadFileToString(media_info_path.c_str(),
|
||||||
LOG(ERROR) << "Failed to read " << file_name << " to string.";
|
&file_content)) {
|
||||||
|
LOG(ERROR) << "Failed to read " << media_info_path << " to string.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ bool MpdWriter::AddFile(const char* file_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MpdBuilder::MakePathsRelativeToMpd(mpd_path, &media_info);
|
||||||
media_infos_.push_back(media_info);
|
media_infos_.push_back(media_info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,13 @@ class MpdWriter {
|
||||||
MpdWriter();
|
MpdWriter();
|
||||||
~MpdWriter();
|
~MpdWriter();
|
||||||
|
|
||||||
// Add |file_name| for MPD generation. |file_name| should not be NULL.
|
// Add |media_info_path| for MPD generation.
|
||||||
// The content of |media_info_file| should be a string representation of
|
// The content of |media_info_path| should be a string representation of
|
||||||
// MediaInfo, i.e. the content should be a result of using
|
// MediaInfo, i.e. the content should be a result of using
|
||||||
// google::protobuf::TestFormat::Print*() methods.
|
// google::protobuf::TestFormat::Print*() methods.
|
||||||
// If necessary, this method can be called after WriteMpd*() methods.
|
// If necessary, this method can be called after WriteMpd*() methods.
|
||||||
bool AddFile(const char* file_name);
|
bool AddFile(const std::string& media_info_path,
|
||||||
|
const std::string& mpd_path);
|
||||||
|
|
||||||
// |base_url| will be used for <BaseURL> element for the MPD. The BaseURL
|
// |base_url| will be used for <BaseURL> element for the MPD. The BaseURL
|
||||||
// element will be a direct child element of the <MPD> element.
|
// element will be a direct child element of the <MPD> element.
|
||||||
|
|
|
@ -19,7 +19,7 @@ TEST(MpdWriterTest, VideoMediaInfo) {
|
||||||
MpdWriter mpd_writer;
|
MpdWriter mpd_writer;
|
||||||
base::FilePath media_info_file = GetTestDataFilePath(kFileNameVideoMediaInfo1);
|
base::FilePath media_info_file = GetTestDataFilePath(kFileNameVideoMediaInfo1);
|
||||||
|
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str(), ""));
|
||||||
std::string generated_mpd;
|
std::string generated_mpd;
|
||||||
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
||||||
ASSERT_TRUE(ValidateMpdSchema(generated_mpd));
|
ASSERT_TRUE(ValidateMpdSchema(generated_mpd));
|
||||||
|
@ -36,8 +36,8 @@ TEST(MpdWriterTest, TwoVideoMediaInfo) {
|
||||||
base::FilePath media_info_file2 =
|
base::FilePath media_info_file2 =
|
||||||
GetTestDataFilePath(kFileNameVideoMediaInfo2);
|
GetTestDataFilePath(kFileNameVideoMediaInfo2);
|
||||||
|
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(media_info_file1.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(media_info_file1.value().c_str(), ""));
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(media_info_file2.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(media_info_file2.value().c_str(), ""));
|
||||||
|
|
||||||
std::string generated_mpd;
|
std::string generated_mpd;
|
||||||
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
||||||
|
@ -52,7 +52,7 @@ TEST(MpdWriterTest, AudioMediaInfo) {
|
||||||
MpdWriter mpd_writer;
|
MpdWriter mpd_writer;
|
||||||
base::FilePath media_info_file = GetTestDataFilePath(kFileNameAudioMediaInfo1);
|
base::FilePath media_info_file = GetTestDataFilePath(kFileNameAudioMediaInfo1);
|
||||||
|
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str(), ""));
|
||||||
std::string generated_mpd;
|
std::string generated_mpd;
|
||||||
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
||||||
ASSERT_TRUE(ValidateMpdSchema(generated_mpd));
|
ASSERT_TRUE(ValidateMpdSchema(generated_mpd));
|
||||||
|
@ -69,8 +69,8 @@ TEST(MpdWriterTest, VideoAudioMediaInfo) {
|
||||||
base::FilePath video_media_info =
|
base::FilePath video_media_info =
|
||||||
GetTestDataFilePath(kFileNameVideoMediaInfo1);
|
GetTestDataFilePath(kFileNameVideoMediaInfo1);
|
||||||
|
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(audio_media_info.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(audio_media_info.value().c_str(), ""));
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(video_media_info.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(video_media_info.value().c_str(), ""));
|
||||||
|
|
||||||
std::string generated_mpd;
|
std::string generated_mpd;
|
||||||
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
||||||
|
@ -86,7 +86,8 @@ TEST(MpdWriterTest, EncryptedAudioMediaInfo) {
|
||||||
base::FilePath encrypted_audio_media_info =
|
base::FilePath encrypted_audio_media_info =
|
||||||
GetTestDataFilePath(kFileNameEncytpedAudioMediaInfo);
|
GetTestDataFilePath(kFileNameEncytpedAudioMediaInfo);
|
||||||
|
|
||||||
ASSERT_TRUE(mpd_writer.AddFile(encrypted_audio_media_info.value().c_str()));
|
ASSERT_TRUE(mpd_writer.AddFile(encrypted_audio_media_info.value().c_str(),
|
||||||
|
""));
|
||||||
|
|
||||||
std::string generated_mpd;
|
std::string generated_mpd;
|
||||||
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd));
|
||||||
|
|
Loading…
Reference in New Issue