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
This commit is contained in:
parent
e60156a3dd
commit
33a87aa84b
|
@ -8,12 +8,15 @@
|
||||||
|
|
||||||
#include "app/mpd_flags.h"
|
#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,
|
DEFINE_bool(output_media_info,
|
||||||
false,
|
false,
|
||||||
"Create a human readable format of MediaInfo. The output file name "
|
"Create a human readable format of MediaInfo. The output file name "
|
||||||
"will be the name specified by output flag, suffixed with "
|
"will be the name specified by output flag, suffixed with "
|
||||||
"'.media_info'.");
|
"'.media_info'. Exclusive with --mpd_output.");
|
||||||
DEFINE_string(mpd_output, "", "MPD output file name.");
|
DEFINE_string(mpd_output, "",
|
||||||
|
"MPD output file name. Exclusive with --output_media_info.");
|
||||||
DEFINE_string(scheme_id_uri,
|
DEFINE_string(scheme_id_uri,
|
||||||
"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed",
|
"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed",
|
||||||
"This flag only applies if output_media_info is true. This value "
|
"This flag only applies if output_media_info is true. This value "
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "media/base/muxer_options.h"
|
#include "media/base/muxer_options.h"
|
||||||
#include "media/base/muxer_util.h"
|
#include "media/base/muxer_util.h"
|
||||||
#include "media/event/mpd_notify_muxer_listener.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 "media/formats/mp4/mp4_muxer.h"
|
||||||
#include "mpd/base/mpd_builder.h"
|
#include "mpd/base/mpd_builder.h"
|
||||||
#include "mpd/base/simple_mpd_notifier.h"
|
#include "mpd/base/simple_mpd_notifier.h"
|
||||||
|
@ -54,6 +55,7 @@ using dash_packager::MpdOptions;
|
||||||
using dash_packager::SimpleMpdNotifier;
|
using dash_packager::SimpleMpdNotifier;
|
||||||
using event::MpdNotifyMuxerListener;
|
using event::MpdNotifyMuxerListener;
|
||||||
using event::MuxerListener;
|
using event::MuxerListener;
|
||||||
|
using event::VodMediaInfoDumpMuxerListener;
|
||||||
|
|
||||||
// Demux, Mux(es) and worker thread used to remux a source file/stream.
|
// Demux, Mux(es) and worker thread used to remux a source file/stream.
|
||||||
class RemuxJob : public base::SimpleThread {
|
class RemuxJob : public base::SimpleThread {
|
||||||
|
@ -155,12 +157,28 @@ bool CreateRemuxJobs(const StringVector& stream_descriptors,
|
||||||
FLAGS_crypto_period_duration);
|
FLAGS_crypto_period_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scoped_ptr<MuxerListener> 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<VodMediaInfoDumpMuxerListener>
|
||||||
|
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) {
|
if (mpd_notifier) {
|
||||||
scoped_ptr<MpdNotifyMuxerListener> mpd_notify_muxer_listener(
|
scoped_ptr<MpdNotifyMuxerListener> mpd_notify_muxer_listener(
|
||||||
new MpdNotifyMuxerListener(mpd_notifier));
|
new MpdNotifyMuxerListener(mpd_notifier));
|
||||||
mpd_notify_muxer_listener->SetContentProtectionSchemeIdUri(
|
mpd_notify_muxer_listener->SetContentProtectionSchemeIdUri(
|
||||||
FLAGS_scheme_id_uri);
|
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());
|
muxer->SetMuxerListener(muxer_listeners->back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,14 +223,21 @@ Status RunRemuxJobs(const std::vector<RemuxJob*>& remux_jobs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunPackager(const StringVector& stream_descriptors) {
|
bool RunPackager(const StringVector& stream_descriptors) {
|
||||||
if (FLAGS_output_media_info) {
|
|
||||||
NOTIMPLEMENTED() << "ERROR: --output_media_info is not supported yet.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AssignFlagsFromProfile())
|
if (!AssignFlagsFromProfile())
|
||||||
return false;
|
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.
|
// Get basic muxer options.
|
||||||
MuxerOptions muxer_options;
|
MuxerOptions muxer_options;
|
||||||
if (!GetMuxerOptions(&muxer_options))
|
if (!GetMuxerOptions(&muxer_options))
|
||||||
|
|
|
@ -19,8 +19,9 @@ namespace event {
|
||||||
|
|
||||||
using dash_packager::MediaInfo;
|
using dash_packager::MediaInfo;
|
||||||
|
|
||||||
VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener(File* output_file)
|
VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener(
|
||||||
: file_(output_file) {}
|
const std::string& output_file_name)
|
||||||
|
: output_file_name_(output_file_name) {}
|
||||||
|
|
||||||
VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {}
|
VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {}
|
||||||
|
|
||||||
|
@ -85,20 +86,29 @@ void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time,
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() {
|
bool VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() {
|
||||||
std::string output_string;
|
std::string output_string;
|
||||||
if (!google::protobuf::TextFormat::PrintToString(*media_info_,
|
if (!google::protobuf::TextFormat::PrintToString(*media_info_,
|
||||||
&output_string)) {
|
&output_string)) {
|
||||||
LOG(ERROR) << "Failed to serialize MediaInfo to 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.";
|
LOG(ERROR) << "Failed to write MediaInfo to file.";
|
||||||
return;
|
file->Close();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!file->Close()) {
|
||||||
file_->Flush();
|
LOG(ERROR) << "Failed to close " << output_file_name_;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace event
|
} // namespace event
|
||||||
|
|
|
@ -24,24 +24,19 @@ class MediaInfo;
|
||||||
} // namespace dash_packager
|
} // namespace dash_packager
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class File;
|
|
||||||
|
|
||||||
namespace event {
|
namespace event {
|
||||||
|
|
||||||
class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
||||||
public:
|
public:
|
||||||
// This object does not own |output_file|. The file has to be open and be
|
VodMediaInfoDumpMuxerListener(const std::string& output_file_name);
|
||||||
// ready for Write(). This will Flush() the file on write but it does not
|
|
||||||
// Close() the file.
|
|
||||||
VodMediaInfoDumpMuxerListener(File* output_file);
|
|
||||||
virtual ~VodMediaInfoDumpMuxerListener();
|
virtual ~VodMediaInfoDumpMuxerListener();
|
||||||
|
|
||||||
// If the stream is encrypted use this as 'schemeIdUri' attribute for
|
/// If the stream is encrypted use this as 'schemeIdUri' attribute for
|
||||||
// ContentProtection element.
|
/// ContentProtection element.
|
||||||
void SetContentProtectionSchemeIdUri(const std::string& scheme_id_uri);
|
void SetContentProtectionSchemeIdUri(const std::string& scheme_id_uri);
|
||||||
|
|
||||||
// MuxerListener implementation.
|
/// @name MuxerListener implementation overrides.
|
||||||
|
/// @{
|
||||||
virtual void OnMediaStart(const MuxerOptions& muxer_options,
|
virtual void OnMediaStart(const MuxerOptions& muxer_options,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
const std::vector<StreamInfo*>& stream_infos,
|
||||||
uint32 time_scale,
|
uint32 time_scale,
|
||||||
|
@ -60,11 +55,13 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
||||||
virtual void OnNewSegment(uint64 start_time,
|
virtual void OnNewSegment(uint64 start_time,
|
||||||
uint64 duration,
|
uint64 duration,
|
||||||
uint64 segment_file_size) OVERRIDE;
|
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_;
|
std::string scheme_id_uri_;
|
||||||
scoped_ptr<dash_packager::MediaInfo> media_info_;
|
scoped_ptr<dash_packager::MediaInfo> media_info_;
|
||||||
|
|
||||||
|
|
|
@ -152,16 +152,14 @@ void ExpectTextFormatMediaInfoEqual(const std::string& expect,
|
||||||
|
|
||||||
class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
VodMediaInfoDumpMuxerListenerTest() : temp_file_(NULL) {}
|
VodMediaInfoDumpMuxerListenerTest() {}
|
||||||
virtual ~VodMediaInfoDumpMuxerListenerTest() {}
|
virtual ~VodMediaInfoDumpMuxerListenerTest() {}
|
||||||
|
|
||||||
virtual void SetUp() OVERRIDE {
|
virtual void SetUp() OVERRIDE {
|
||||||
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
||||||
DLOG(INFO) << "Created temp file: " << temp_file_path_.value();
|
DLOG(INFO) << "Created temp file: " << temp_file_path_.value();
|
||||||
|
|
||||||
temp_file_ = File::Open(temp_file_path_.value().c_str(), "w");
|
listener_.reset(new VodMediaInfoDumpMuxerListener(temp_file_path_.value()));
|
||||||
ASSERT_TRUE(temp_file_);
|
|
||||||
listener_.reset(new VodMediaInfoDumpMuxerListener(temp_file_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void TearDown() OVERRIDE {
|
virtual void TearDown() OVERRIDE {
|
||||||
|
@ -182,7 +180,7 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FireOnMediaEndWithParams(const OnMediaEndParameters& params) {
|
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,
|
listener_->OnMediaEnd(params.has_init_range,
|
||||||
params.init_range_start,
|
params.init_range_start,
|
||||||
params.init_range_end,
|
params.init_range_end,
|
||||||
|
@ -204,7 +202,6 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
File* temp_file_;
|
|
||||||
base::FilePath temp_file_path_;
|
base::FilePath temp_file_path_;
|
||||||
scoped_ptr<VodMediaInfoDumpMuxerListener> listener_;
|
scoped_ptr<VodMediaInfoDumpMuxerListener> listener_;
|
||||||
|
|
||||||
|
@ -221,7 +218,6 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, UnencryptedStream_Normal) {
|
||||||
FireOnMediaStartWithDefaultMuxerOptions(stream_infos, !kEnableEncryption);
|
FireOnMediaStartWithDefaultMuxerOptions(stream_infos, !kEnableEncryption);
|
||||||
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
||||||
FireOnMediaEndWithParams(media_end_param);
|
FireOnMediaEndWithParams(media_end_param);
|
||||||
ASSERT_TRUE(temp_file_->Close());
|
|
||||||
|
|
||||||
const char kExpectedProtobufOutput[] =
|
const char kExpectedProtobufOutput[] =
|
||||||
"bandwidth: 7620\n"
|
"bandwidth: 7620\n"
|
||||||
|
@ -258,7 +254,6 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) {
|
||||||
|
|
||||||
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
||||||
FireOnMediaEndWithParams(media_end_param);
|
FireOnMediaEndWithParams(media_end_param);
|
||||||
ASSERT_TRUE(temp_file_->Close());
|
|
||||||
|
|
||||||
const char kExpectedProtobufOutput[] =
|
const char kExpectedProtobufOutput[] =
|
||||||
"bandwidth: 7620\n"
|
"bandwidth: 7620\n"
|
||||||
|
|
Loading…
Reference in New Issue