MpdBuilder should be able to write to File instance

Change interface of MpdBuilder so that it can write to a File instance
directly.

Change-Id: I4007deed4d0246a7c75fbc7c5aca3ece374c1224
This commit is contained in:
Rintaro Kuroiwa 2014-01-31 11:02:30 -08:00
parent 05db9e02b9
commit d04ae592cd
4 changed files with 82 additions and 7 deletions

View File

@ -15,6 +15,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "media/file/file.h"
#include "mpd/base/content_protection_element.h"
#include "mpd/base/mpd_utils.h"
#include "mpd/base/xml/xml_node.h"
@ -156,6 +157,29 @@ int SearchTimedOutRepeatIndex(uint64 timeshift_limit,
return (timeshift_limit - segment_info.start_time) / segment_info.duration;
}
// Overload this function to support different types of |output|.
// Note that this could be done by call MpdBuilder::ToString() and use the
// result to write to a file, it requires an extra copy.
bool WriteXmlCharArrayToOutput(xmlChar* doc,
int doc_size,
std::string* output) {
DCHECK(doc);
DCHECK(output);
output->assign(doc, doc + doc_size);
return true;
}
bool WriteXmlCharArrayToOutput(xmlChar* doc,
int doc_size,
media::File* output) {
DCHECK(doc);
DCHECK(output);
if (output->Write(doc, doc_size) < doc_size)
return false;
return output->Flush();
}
} // namespace
MpdOptions::MpdOptions()
@ -190,12 +214,20 @@ AdaptationSet* MpdBuilder::AddAdaptationSet() {
return adaptation_set.release();
}
bool MpdBuilder::ToString(std::string* output) {
bool MpdBuilder::WriteMpdToFile(media::File* output_file) {
base::AutoLock scoped_lock(lock_);
return ToStringImpl(output);
DCHECK(output_file);
return WriteMpdToOutput(output_file);
}
bool MpdBuilder::ToStringImpl(std::string* output) {
bool MpdBuilder::ToString(std::string* output) {
base::AutoLock scoped_lock(lock_);
DCHECK(output);
return WriteMpdToOutput(output);
}
template <typename OutputType>
bool MpdBuilder::WriteMpdToOutput(OutputType* output) {
xmlInitParser();
xml::ScopedXmlPtr<xmlDoc>::type doc(GenerateMpd());
if (!doc.get())
@ -207,15 +239,13 @@ bool MpdBuilder::ToStringImpl(std::string* output) {
xmlDocDumpFormatMemoryEnc(
doc.get(), &doc_str, &doc_str_size, "UTF-8", kNiceFormat);
output->assign(doc_str, doc_str + doc_str_size);
bool result = WriteXmlCharArrayToOutput(doc_str, doc_str_size, output);
xmlFree(doc_str);
DLOG(INFO) << *output;
// Cleanup, free the doc then cleanup parser.
doc.reset();
xmlCleanupParser();
return true;
return result;
}
xmlDocPtr MpdBuilder::GenerateMpd() {

View File

@ -25,6 +25,13 @@
#include "mpd/base/segment_info.h"
#include "mpd/base/xml/scoped_xml_ptr.h"
namespace media {
class File;
}
// TODO(rkuroiwa): For classes with |id_|, consider removing the field and let
// the MPD (XML) generation functions take care of assigning an ID to each
// element.
namespace dash_packager {
class AdaptationSet;
@ -70,6 +77,12 @@ class MpdBuilder {
/// @return The new adaptation set, which is owned by this instance.
AdaptationSet* AddAdaptationSet();
/// Write the MPD to specified file.
/// @param[out] output_file is MPD destination. output_file will be
/// flushed but not closed.
/// @return true on success, false otherwise.
bool WriteMpdToFile(media::File* output_file);
/// Writes the MPD to the given string.
/// @param[out] output is an output string where the MPD gets written.
/// @return true on success, false otherwise.
@ -85,6 +98,11 @@ class MpdBuilder {
bool ToStringImpl(std::string* output);
// This is a helper method for writing out MPDs, called from WriteMpdToFile()
// and ToString().
template <typename OutputType>
bool WriteMpdToOutput(OutputType* output);
// Returns the document pointer to the MPD. This must be freed by the caller
// using appropriate xmlDocPtr freeing function.
// On failure, this returns NULL.

View File

@ -11,6 +11,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "media/file/file.h"
#include "mpd/base/mpd_builder.h"
#include "mpd/base/mpd_utils.h"
#include "mpd/test/mpd_builder_test_helper.h"
@ -362,6 +363,31 @@ TEST_F(StaticMpdBuilderTest, MediaInfoMissingBandwidth) {
ASSERT_FALSE(mpd_.ToString(&mpd_doc));
}
TEST_F(StaticMpdBuilderTest, WriteToFile) {
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet();
ASSERT_TRUE(video_adaptation_set);
Representation* video_representation =
video_adaptation_set->AddRepresentation(video_media_info);
ASSERT_TRUE(video_representation);
base::FilePath file_path;
ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
media::File* file = media::File::Open(file_path.value().data(), "w");
ASSERT_TRUE(file);
ASSERT_TRUE(mpd_.WriteMpdToFile(file));
ASSERT_TRUE(file->Close());
std::string file_content;
ASSERT_TRUE(base::ReadFileToString(file_path, &file_content));
ASSERT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile(
file_content, kFileNameExpectedMpdOutputVideo1));
const bool kNonRecursive = false;
EXPECT_TRUE(DeleteFile(file_path, kNonRecursive));
}
// Check whether the attributes are set correctly for dynamic <MPD> element.
TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) {
static const char kExpectedOutput[] =

View File

@ -51,6 +51,7 @@
],
'dependencies': [
'../base/base.gyp:base',
'../media/file/file.gyp:file',
'../third_party/libxml/libxml.gyp:libxml',
'media_info_proto',
],