From 33a87aa84bc8bcf2ad282d6332a6e1912e126340 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Tue, 10 Jun 2014 17:20:00 -0700 Subject: [PATCH] Support MediaInfo dump in packager app VodMediaInfoDumpMuxerListener is also changed to manage the file internally rather than take an opened file pointer. This change simplifies the caller as the caller does not need to manage the media info dump files any more. Change-Id: Id9dcaf367c96ed13603b13b1e3705c687c948b07 --- app/mpd_flags.cc | 7 +++- app/packager_main.cc | 37 ++++++++++++++++--- .../vod_media_info_dump_muxer_listener.cc | 26 +++++++++---- .../vod_media_info_dump_muxer_listener.h | 25 ++++++------- ...media_info_dump_muxer_listener_unittest.cc | 11 ++---- 5 files changed, 68 insertions(+), 38 deletions(-) diff --git a/app/mpd_flags.cc b/app/mpd_flags.cc index 78ca76a715..f2693c0234 100644 --- a/app/mpd_flags.cc +++ b/app/mpd_flags.cc @@ -8,12 +8,15 @@ #include "app/mpd_flags.h" +// TODO(rkuroiwa, kqyang): Remove the 'Exclusive' statements once +// --output_media_info can work together with --mpd_output. DEFINE_bool(output_media_info, false, "Create a human readable format of MediaInfo. The output file name " "will be the name specified by output flag, suffixed with " - "'.media_info'."); -DEFINE_string(mpd_output, "", "MPD output file name."); + "'.media_info'. Exclusive with --mpd_output."); +DEFINE_string(mpd_output, "", + "MPD output file name. Exclusive with --output_media_info."); DEFINE_string(scheme_id_uri, "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed", "This flag only applies if output_media_info is true. This value " diff --git a/app/packager_main.cc b/app/packager_main.cc index 283dcaecd7..d022a54fc0 100644 --- a/app/packager_main.cc +++ b/app/packager_main.cc @@ -22,6 +22,7 @@ #include "media/base/muxer_options.h" #include "media/base/muxer_util.h" #include "media/event/mpd_notify_muxer_listener.h" +#include "media/event/vod_media_info_dump_muxer_listener.h" #include "media/formats/mp4/mp4_muxer.h" #include "mpd/base/mpd_builder.h" #include "mpd/base/simple_mpd_notifier.h" @@ -54,6 +55,7 @@ using dash_packager::MpdOptions; using dash_packager::SimpleMpdNotifier; using event::MpdNotifyMuxerListener; using event::MuxerListener; +using event::VodMediaInfoDumpMuxerListener; // Demux, Mux(es) and worker thread used to remux a source file/stream. class RemuxJob : public base::SimpleThread { @@ -155,12 +157,28 @@ bool CreateRemuxJobs(const StringVector& stream_descriptors, FLAGS_crypto_period_duration); } + scoped_ptr muxer_listener; + DCHECK(!(FLAGS_output_media_info && mpd_notifier)); + if (FLAGS_output_media_info) { + const std::string output_mpd_file_name = + stream_muxer_options.output_file_name + ".media_info"; + scoped_ptr + vod_media_info_dump_muxer_listener( + new VodMediaInfoDumpMuxerListener(output_mpd_file_name)); + vod_media_info_dump_muxer_listener->SetContentProtectionSchemeIdUri( + FLAGS_scheme_id_uri); + muxer_listener = vod_media_info_dump_muxer_listener.Pass(); + } if (mpd_notifier) { scoped_ptr mpd_notify_muxer_listener( new MpdNotifyMuxerListener(mpd_notifier)); mpd_notify_muxer_listener->SetContentProtectionSchemeIdUri( FLAGS_scheme_id_uri); - muxer_listeners->push_back(mpd_notify_muxer_listener.release()); + muxer_listener = mpd_notify_muxer_listener.Pass(); + } + + if (muxer_listener) { + muxer_listeners->push_back(muxer_listener.release()); muxer->SetMuxerListener(muxer_listeners->back()); } @@ -205,14 +223,21 @@ Status RunRemuxJobs(const std::vector& remux_jobs) { } bool RunPackager(const StringVector& stream_descriptors) { - if (FLAGS_output_media_info) { - NOTIMPLEMENTED() << "ERROR: --output_media_info is not supported yet."; - return false; - } - if (!AssignFlagsFromProfile()) return false; + if (FLAGS_output_media_info && !FLAGS_mpd_output.empty()) { + NOTIMPLEMENTED() << "ERROR: --output_media_info and --mpd_output do not " + "work together."; + return false; + } + if (FLAGS_output_media_info && !FLAGS_single_segment) { + // TODO(rkuroiwa, kqyang): Support partial media info dump for live. + NOTIMPLEMENTED() << "ERROR: --output_media_info is only supported if " + "--single_segment is true."; + return false; + } + // Get basic muxer options. MuxerOptions muxer_options; if (!GetMuxerOptions(&muxer_options)) diff --git a/media/event/vod_media_info_dump_muxer_listener.cc b/media/event/vod_media_info_dump_muxer_listener.cc index 7612004358..e4c5a9380e 100644 --- a/media/event/vod_media_info_dump_muxer_listener.cc +++ b/media/event/vod_media_info_dump_muxer_listener.cc @@ -19,8 +19,9 @@ namespace event { using dash_packager::MediaInfo; -VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener(File* output_file) - : file_(output_file) {} +VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener( + const std::string& output_file_name) + : output_file_name_(output_file_name) {} VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {} @@ -85,20 +86,29 @@ void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time, NOTIMPLEMENTED(); } -void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() { +bool VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() { std::string output_string; if (!google::protobuf::TextFormat::PrintToString(*media_info_, &output_string)) { LOG(ERROR) << "Failed to serialize MediaInfo to string."; - return; + return false; } - if (file_->Write(output_string.data(), output_string.size()) <= 0) { + media::File* file = File::Open(output_file_name_.c_str(), "w"); + if (!file) { + LOG(ERROR) << "Failed to open " << output_file_name_; + return false; + } + if (file->Write(output_string.data(), output_string.size()) <= 0) { LOG(ERROR) << "Failed to write MediaInfo to file."; - return; + file->Close(); + return false; } - - file_->Flush(); + if (!file->Close()) { + LOG(ERROR) << "Failed to close " << output_file_name_; + return false; + } + return true; } } // namespace event diff --git a/media/event/vod_media_info_dump_muxer_listener.h b/media/event/vod_media_info_dump_muxer_listener.h index 421a1caec0..1f4c3baa6e 100644 --- a/media/event/vod_media_info_dump_muxer_listener.h +++ b/media/event/vod_media_info_dump_muxer_listener.h @@ -24,24 +24,19 @@ class MediaInfo; } // namespace dash_packager namespace media { - -class File; - namespace event { class VodMediaInfoDumpMuxerListener : public MuxerListener { public: - // This object does not own |output_file|. The file has to be open and be - // ready for Write(). This will Flush() the file on write but it does not - // Close() the file. - VodMediaInfoDumpMuxerListener(File* output_file); + VodMediaInfoDumpMuxerListener(const std::string& output_file_name); virtual ~VodMediaInfoDumpMuxerListener(); - // If the stream is encrypted use this as 'schemeIdUri' attribute for - // ContentProtection element. + /// If the stream is encrypted use this as 'schemeIdUri' attribute for + /// ContentProtection element. void SetContentProtectionSchemeIdUri(const std::string& scheme_id_uri); - // MuxerListener implementation. + /// @name MuxerListener implementation overrides. + /// @{ virtual void OnMediaStart(const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, @@ -60,11 +55,13 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener { virtual void OnNewSegment(uint64 start_time, uint64 duration, uint64 segment_file_size) OVERRIDE; - private: - // Write |media_info_| to |file_|. - void SerializeMediaInfoToFile(); + /// @} - File* file_; + private: + // Write |media_info_| to |output_file_name_|. + bool SerializeMediaInfoToFile(); + + std::string output_file_name_; std::string scheme_id_uri_; scoped_ptr media_info_; diff --git a/media/event/vod_media_info_dump_muxer_listener_unittest.cc b/media/event/vod_media_info_dump_muxer_listener_unittest.cc index 7296510904..6842f67144 100644 --- a/media/event/vod_media_info_dump_muxer_listener_unittest.cc +++ b/media/event/vod_media_info_dump_muxer_listener_unittest.cc @@ -152,16 +152,14 @@ void ExpectTextFormatMediaInfoEqual(const std::string& expect, class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { public: - VodMediaInfoDumpMuxerListenerTest() : temp_file_(NULL) {} + VodMediaInfoDumpMuxerListenerTest() {} virtual ~VodMediaInfoDumpMuxerListenerTest() {} virtual void SetUp() OVERRIDE { ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_)); DLOG(INFO) << "Created temp file: " << temp_file_path_.value(); - temp_file_ = File::Open(temp_file_path_.value().c_str(), "w"); - ASSERT_TRUE(temp_file_); - listener_.reset(new VodMediaInfoDumpMuxerListener(temp_file_)); + listener_.reset(new VodMediaInfoDumpMuxerListener(temp_file_path_.value())); } virtual void TearDown() OVERRIDE { @@ -182,7 +180,7 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { } void FireOnMediaEndWithParams(const OnMediaEndParameters& params) { - // On success, this writes the result to |temp_file_|. + // On success, this writes the result to |temp_file_path_|. listener_->OnMediaEnd(params.has_init_range, params.init_range_start, params.init_range_end, @@ -204,7 +202,6 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { } protected: - File* temp_file_; base::FilePath temp_file_path_; scoped_ptr listener_; @@ -221,7 +218,6 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, UnencryptedStream_Normal) { FireOnMediaStartWithDefaultMuxerOptions(stream_infos, !kEnableEncryption); OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams(); FireOnMediaEndWithParams(media_end_param); - ASSERT_TRUE(temp_file_->Close()); const char kExpectedProtobufOutput[] = "bandwidth: 7620\n" @@ -258,7 +254,6 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) { OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams(); FireOnMediaEndWithParams(media_end_param); - ASSERT_TRUE(temp_file_->Close()); const char kExpectedProtobufOutput[] = "bandwidth: 7620\n"