From 6837ac45b7cbc7e450dbd12fac5e900874ef7c33 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Fri, 16 May 2014 16:32:10 -0700 Subject: [PATCH] Implement MpdNotifyMuxerListener Change-Id: I08742839c2be5e5da104914ec841b8c5dd57f0b7 --- media/event/mpd_notify_muxer_listener.cc | 86 +++++++++---- media/event/mpd_notify_muxer_listener.h | 29 +++-- media/event/muxer_listener.h | 9 +- media/event/muxer_listener_internal.cc | 92 +++++++++----- media/event/muxer_listener_internal.h | 24 +++- .../vod_media_info_dump_muxer_listener.cc | 119 ++++++------------ .../vod_media_info_dump_muxer_listener.h | 18 ++- ...media_info_dump_muxer_listener_unittest.cc | 36 +++--- media/formats/mp4/mp4_muxer.cc | 12 +- mpd/base/mpd_notifier.h | 16 ++- mpd/base/simple_mpd_notifier.cc | 40 ++---- mpd/base/simple_mpd_notifier.h | 4 +- 12 files changed, 256 insertions(+), 229 deletions(-) diff --git a/media/event/mpd_notify_muxer_listener.cc b/media/event/mpd_notify_muxer_listener.cc index 192b307128..be4f69f755 100644 --- a/media/event/mpd_notify_muxer_listener.cc +++ b/media/event/mpd_notify_muxer_listener.cc @@ -15,44 +15,72 @@ #include "mpd/base/media_info.pb.h" #include "mpd/base/mpd_notifier.h" +using dash_packager::MediaInfo; + namespace media { namespace event { MpdNotifyMuxerListener::MpdNotifyMuxerListener( dash_packager::MpdNotifier* mpd_notifier) : mpd_notifier_(mpd_notifier), - reference_time_scale_(0), - container_type_(kContainerUnknown) { + notification_id_(0) { DCHECK(mpd_notifier); + DCHECK(mpd_notifier->dash_profile() == dash_packager::kOnDemandProfile || + mpd_notifier->dash_profile() == dash_packager::kLiveProfile); } MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {} +void MpdNotifyMuxerListener::SetContentProtectionSchemeIdUri( + const std::string& scheme_id_uri) { + scheme_id_uri_ = scheme_id_uri; +} + void MpdNotifyMuxerListener::OnMediaStart( const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, - ContainerType container_type) { - muxer_options_ = muxer_options; - reference_time_scale_ = time_scale; - container_type_ = container_type; + ContainerType container_type, + bool is_encrypted) { + scoped_ptr media_info(new MediaInfo()); + if (!internal::GenerateMediaInfo(muxer_options, + stream_infos, + time_scale, + container_type, + media_info.get())) { + LOG(ERROR) << "Failed to generate MediaInfo from input."; + return; + } + + if (is_encrypted) { + if (!internal::AddContentProtectionElements( + container_type, scheme_id_uri_, media_info.get())) { + LOG(ERROR) << "Failed to add content protection elements."; + return; + } + } + + if (mpd_notifier_->dash_profile() == dash_packager::kLiveProfile) { + // TODO(kqyang): Check return result. + mpd_notifier_->NotifyNewContainer(*media_info, ¬ification_id_); + } else { + media_info_ = media_info.Pass(); + } } -void MpdNotifyMuxerListener::OnMediaEnd( - const std::vector& stream_infos, - bool has_init_range, - uint64 init_range_start, - uint64 init_range_end, - bool has_index_range, - uint64 index_range_start, - uint64 index_range_end, - float duration_seconds, - uint64 file_size, - bool is_encrypted) { - dash_packager::MediaInfo media_info; - if (!internal::GenerateMediaInfo(muxer_options_, - stream_infos, - has_init_range, +void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range, + uint64 init_range_start, + uint64 init_range_end, + bool has_index_range, + uint64 index_range_start, + uint64 index_range_end, + float duration_seconds, + uint64 file_size) { + if (mpd_notifier_->dash_profile() == dash_packager::kLiveProfile) + return; + + DCHECK(media_info_); + if (!internal::SetVodInformation(has_init_range, init_range_start, init_range_end, has_index_range, @@ -60,20 +88,24 @@ void MpdNotifyMuxerListener::OnMediaEnd( index_range_end, duration_seconds, file_size, - reference_time_scale_, - container_type_, - &media_info)) { - LOG(ERROR) << "Failed to generate MediaInfo from input."; + media_info_.get())) { + LOG(ERROR) << "Failed to generate VOD information from input."; return; } uint32 id; // Result unused. - mpd_notifier_->NotifyNewContainer(media_info, &id); + // TODO(kqyang): Check return result. + mpd_notifier_->NotifyNewContainer(*media_info_, &id); } void MpdNotifyMuxerListener::OnNewSegment(uint64 start_time, uint64 duration, - uint64 segment_file_size) {} + uint64 segment_file_size) { + if (mpd_notifier_->dash_profile() != dash_packager::kLiveProfile) + return; + // TODO(kqyang): Check return result. + mpd_notifier_->NotifyNewSegment(notification_id_, start_time, duration); +} } // namespace event } // namespace media diff --git a/media/event/mpd_notify_muxer_listener.h b/media/event/mpd_notify_muxer_listener.h index b5ab010cd1..2580e1db95 100644 --- a/media/event/mpd_notify_muxer_listener.h +++ b/media/event/mpd_notify_muxer_listener.h @@ -12,10 +12,12 @@ #include #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "media/base/muxer_options.h" #include "media/event/muxer_listener.h" namespace dash_packager { +class MediaInfo; class MpdNotifier; } // namespace dash_packager @@ -24,37 +26,42 @@ namespace event { class MpdNotifyMuxerListener : public MuxerListener { public: - // |mpd_notifier| must be initialized, i.e mpd_notifier->Init() must be - // called. + /// @param mpd_notifier must be initialized, i.e mpd_notifier->Init() must be + /// called. MpdNotifyMuxerListener(dash_packager::MpdNotifier* mpd_notifier); virtual ~MpdNotifyMuxerListener(); - // MuxerListener implementation. + /// If the stream is encrypted use this as 'schemeIdUri' attribute for + /// ContentProtection element. + void SetContentProtectionSchemeIdUri(const std::string& scheme_id_uri); + + /// @name MuxerListener implementation overrides. + /// @{ virtual void OnMediaStart(const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, - ContainerType container_type) OVERRIDE; + ContainerType container_type, + bool is_encrypted) OVERRIDE; - virtual void OnMediaEnd(const std::vector& stream_infos, - bool has_init_range, + virtual void OnMediaEnd(bool has_init_range, uint64 init_range_start, uint64 init_range_end, bool has_index_range, uint64 index_range_start, uint64 index_range_end, float duration_seconds, - uint64 file_size, - bool is_encrypted) OVERRIDE; + uint64 file_size) OVERRIDE; virtual void OnNewSegment(uint64 start_time, uint64 duration, uint64 segment_file_size) OVERRIDE; + /// @} private: dash_packager::MpdNotifier* const mpd_notifier_; - MuxerOptions muxer_options_; - uint32 reference_time_scale_; - ContainerType container_type_; + uint32 notification_id_; + scoped_ptr media_info_; + std::string scheme_id_uri_; DISALLOW_COPY_AND_ASSIGN(MpdNotifyMuxerListener); }; diff --git a/media/event/muxer_listener.h b/media/event/muxer_listener.h index dc4fa75b41..4c1ff2e153 100644 --- a/media/event/muxer_listener.h +++ b/media/event/muxer_listener.h @@ -39,7 +39,8 @@ class MuxerListener { virtual void OnMediaStart(const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, - ContainerType container_type) = 0; + ContainerType container_type, + bool is_encrypted) = 0; // Called when all files are written out and the muxer object does not output // any more files. @@ -51,16 +52,14 @@ class MuxerListener { // Both ranges are inclusive. // Media length of |duration_seconds|. // |file_size| of the media in bytes. - virtual void OnMediaEnd(const std::vector& stream_infos, - bool has_init_range, + virtual void OnMediaEnd(bool has_init_range, uint64 init_range_start, uint64 init_range_end, bool has_index_range, uint64 index_range_start, uint64 index_range_end, float duration_seconds, - uint64 file_size, - bool is_encrypted) = 0; + uint64 file_size) = 0; // Called when a segment has been muxed and the file has been written. // Note: For video on demand (VOD), this would be for subsegments. diff --git a/media/event/muxer_listener_internal.cc b/media/event/muxer_listener_internal.cc index 10bfe4083c..e41a0940d9 100644 --- a/media/event/muxer_listener_internal.cc +++ b/media/event/muxer_listener_internal.cc @@ -81,23 +81,6 @@ void SetMediaInfoContainerType(MuxerListener::ContainerType container_type, } } -void SetMediaInfoCommonInfo(float duration_seconds, - uint64 file_size, - uint32 reference_time_scale, - MuxerListener::ContainerType container_type, - MediaInfo* media_info) { - DCHECK(media_info); - DCHECK_GT(file_size, 0u); - DCHECK_GT(duration_seconds, 0.0f); - - media_info->set_media_duration_seconds(duration_seconds); - media_info->set_bandwidth( - EstimateRequiredBandwidth(file_size, duration_seconds)); - - media_info->set_reference_time_scale(reference_time_scale); - SetMediaInfoContainerType(container_type, media_info); -} - void AddVideoInfo(const VideoStreamInfo* video_stream_info, MediaInfo* media_info) { DCHECK(video_stream_info); @@ -160,14 +143,32 @@ void SetMediaInfoStreamInfo(const std::vector& stream_infos, void SetMediaInfoMuxerOptions(const MuxerOptions& muxer_options, MediaInfo* media_info) { DCHECK(media_info); - media_info->set_media_file_name(muxer_options.output_file_name); + if (muxer_options.single_segment) { + media_info->set_media_file_name(muxer_options.output_file_name); + DCHECK(muxer_options.segment_template.empty()); + } else { + media_info->set_init_segment_name(muxer_options.output_file_name); + media_info->set_segment_template(muxer_options.segment_template); + } } } // namespace bool GenerateMediaInfo(const MuxerOptions& muxer_options, const std::vector& stream_infos, - bool has_init_range, + uint32 reference_time_scale, + MuxerListener::ContainerType container_type, + MediaInfo* media_info) { + DCHECK(media_info); + + SetMediaInfoMuxerOptions(muxer_options, media_info); + SetMediaInfoStreamInfo(stream_infos, media_info); + media_info->set_reference_time_scale(reference_time_scale); + SetMediaInfoContainerType(container_type, media_info); + return true; +} + +bool SetVodInformation(bool has_init_range, uint64 init_range_start, uint64 init_range_end, bool has_index_range, @@ -175,8 +176,6 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options, uint64 index_range_end, float duration_seconds, uint64 file_size, - uint32 reference_time_scale, - MuxerListener::ContainerType container_type, MediaInfo* media_info) { DCHECK(media_info); if (file_size == 0) { @@ -187,10 +186,9 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options, if (duration_seconds <= 0.0f) { // Non positive second media must be invalid media. LOG(ERROR) << "Duration is not positive: " << duration_seconds; - return false;; + return false; } - SetMediaInfoMuxerOptions(muxer_options, media_info); SetMediaInfoRanges(has_init_range, init_range_start, init_range_end, @@ -198,14 +196,48 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options, index_range_start, index_range_end, media_info); - SetMediaInfoCommonInfo(duration_seconds, - file_size, - reference_time_scale, - container_type, - media_info); - SetMediaInfoStreamInfo(stream_infos, media_info); + + media_info->set_media_duration_seconds(duration_seconds); + media_info->set_bandwidth( + EstimateRequiredBandwidth(file_size, duration_seconds)); return true; -}; +} + +bool AddContentProtectionElements(MuxerListener::ContainerType container_type, + const std::string& user_scheme_id_uri, + MediaInfo* media_info) { + DCHECK(media_info); + + const char kEncryptedMp4Uri[] = "urn:mpeg:dash:mp4protection:2011"; + const char kEncryptedMp4Value[] = "cenc"; + + // DASH MPD spec specifies a default ContentProtection element for ISO BMFF + // (MP4) files. + const bool is_mp4_container = container_type == MuxerListener::kContainerMp4; + if (is_mp4_container) { + MediaInfo::ContentProtectionXml* mp4_protection = + media_info->add_content_protections(); + mp4_protection->set_scheme_id_uri(kEncryptedMp4Uri); + mp4_protection->set_value(kEncryptedMp4Value); + } + + if (!user_scheme_id_uri.empty()) { + MediaInfo::ContentProtectionXml* content_protection = + media_info->add_content_protections(); + content_protection->set_scheme_id_uri(user_scheme_id_uri); + } else if (is_mp4_container) { + LOG(WARNING) << "schemeIdUri is not specified. Added default " + "ContentProtection only."; + } + + if (media_info->content_protections_size() == 0) { + LOG(ERROR) << "The stream is encrypted but no schemeIdUri specified for " + "ContentProtection."; + return false; + } + + return true; +} } // namespace internal } // namespace event diff --git a/media/event/muxer_listener_internal.h b/media/event/muxer_listener_internal.h index 0c730c0c15..dfd3b74671 100644 --- a/media/event/muxer_listener_internal.h +++ b/media/event/muxer_listener_internal.h @@ -7,6 +7,7 @@ #ifndef MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_ #define MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_ +#include #include #include "base/basictypes.h" @@ -24,11 +25,17 @@ struct MuxerOptions; namespace event { namespace internal { -// On success fill |media_info| with input data and return true, otherwise -// return false. +/// @param[out] media_info points to the MediaInfo object to be filled. +/// @return true on success, false otherwise. bool GenerateMediaInfo(const MuxerOptions& muxer_options, const std::vector& stream_infos, - bool has_init_range, + uint32 reference_time_scale_, + MuxerListener::ContainerType container_type, + dash_packager::MediaInfo* media_info); + +/// @param[in,out] media_info points to the MediaInfo object to be filled. +/// @return true on success, false otherwise. +bool SetVodInformation(bool has_init_range, uint64 init_range_start, uint64 init_range_end, bool has_index_range, @@ -36,10 +43,17 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options, uint64 index_range_end, float duration_seconds, uint64 file_size, - uint32 reference_time_scale_, - MuxerListener::ContainerType container_type, dash_packager::MediaInfo* media_info); +/// @param container_type specifies container type. A default ContentProtection +/// element will be added if the container is MP4. +/// @param user_scheme_id_uri is the user specified schemeIdUri for +/// ContentProtection. +/// @return true if a ContentProtectionXml is added, false otherwise. +bool AddContentProtectionElements(MuxerListener::ContainerType container_type, + const std::string& user_scheme_id_uri, + dash_packager::MediaInfo* media_info); + } // namespace internal } // namespace event } // namespace media diff --git a/media/event/vod_media_info_dump_muxer_listener.cc b/media/event/vod_media_info_dump_muxer_listener.cc index 7c11cb049a..7612004358 100644 --- a/media/event/vod_media_info_dump_muxer_listener.cc +++ b/media/event/vod_media_info_dump_muxer_listener.cc @@ -19,54 +19,8 @@ namespace event { using dash_packager::MediaInfo; -namespace { - -const char kEncryptedMp4Uri[] = "urn:mpeg:dash:mp4protection:2011"; -const char kEncryptedMp4Value[] = "cenc"; - -// |user_scheme_id_uri| is the user specified schemeIdUri for ContentProtection. -// This adds a default ContentProtection element if the container is MP4. -// Returns true if a ContentProtectionXml is added to |media_info|, otherwise -// false. -bool AddContentProtectionElements(MuxerListener::ContainerType container_type, - const std::string& user_scheme_id_uri, - MediaInfo* media_info) { - DCHECK(media_info); - - // DASH MPD spec specifies a default ContentProtection element for ISO BMFF - // (MP4) files. - const bool is_mp4_container = container_type == MuxerListener::kContainerMp4; - if (is_mp4_container) { - MediaInfo::ContentProtectionXml* mp4_protection = - media_info->add_content_protections(); - mp4_protection->set_scheme_id_uri(kEncryptedMp4Uri); - mp4_protection->set_value(kEncryptedMp4Value); - } - - if (!user_scheme_id_uri.empty()) { - MediaInfo::ContentProtectionXml* content_protection = - media_info->add_content_protections(); - content_protection->set_scheme_id_uri(user_scheme_id_uri); - } else if (is_mp4_container) { - LOG(WARNING) << "schemeIdUri is not specified. Added default " - "ContentProtection only."; - } - - if (media_info->content_protections_size() == 0) { - LOG(ERROR) << "The stream is encrypted but no schemeIdUri specified for " - "ContentProtection."; - return false; - } - - return true; -} - -} // namespace - VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener(File* output_file) - : file_(output_file), - reference_time_scale_(0), - container_type_(kContainerUnknown) {} + : file_(output_file) {} VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {} @@ -79,27 +33,38 @@ void VodMediaInfoDumpMuxerListener::OnMediaStart( const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, - ContainerType container_type) { - muxer_options_ = muxer_options; - reference_time_scale_ = time_scale; - container_type_ = container_type; + ContainerType container_type, + bool is_encrypted) { + DCHECK(muxer_options.single_segment); + media_info_.reset(new MediaInfo()); + if (!internal::GenerateMediaInfo(muxer_options, + stream_infos, + time_scale, + container_type, + media_info_.get())) { + LOG(ERROR) << "Failed to generate MediaInfo from input."; + return; + } + + if (is_encrypted) { + if (!internal::AddContentProtectionElements( + container_type, scheme_id_uri_, media_info_.get())) { + LOG(ERROR) << "Failed to add content protection elements."; + return; + } + } } -void VodMediaInfoDumpMuxerListener::OnMediaEnd( - const std::vector& stream_infos, - bool has_init_range, - uint64 init_range_start, - uint64 init_range_end, - bool has_index_range, - uint64 index_range_start, - uint64 index_range_end, - float duration_seconds, - uint64 file_size, - bool is_encrypted) { - MediaInfo media_info; - if (!internal::GenerateMediaInfo(muxer_options_, - stream_infos, - has_init_range, +void VodMediaInfoDumpMuxerListener::OnMediaEnd(bool has_init_range, + uint64 init_range_start, + uint64 init_range_end, + bool has_index_range, + uint64 index_range_start, + uint64 index_range_end, + float duration_seconds, + uint64 file_size) { + DCHECK(media_info_); + if (!internal::SetVodInformation(has_init_range, init_range_start, init_range_end, has_index_range, @@ -107,22 +72,11 @@ void VodMediaInfoDumpMuxerListener::OnMediaEnd( index_range_end, duration_seconds, file_size, - reference_time_scale_, - container_type_, - &media_info)) { - LOG(ERROR) << "Failed to generate MediaInfo from input."; + media_info_.get())) { + LOG(ERROR) << "Failed to generate VOD information from input."; return; } - - if (is_encrypted) { - if (!AddContentProtectionElements( - container_type_, scheme_id_uri_, &media_info)) { - LOG(ERROR) << "Failed to add content protection elements."; - return; - } - } - - SerializeMediaInfoToFile(media_info); + SerializeMediaInfoToFile(); } void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time, @@ -131,10 +85,9 @@ void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time, NOTIMPLEMENTED(); } -void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile( - const MediaInfo& media_info) { +void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() { std::string output_string; - if (!google::protobuf::TextFormat::PrintToString(media_info, + if (!google::protobuf::TextFormat::PrintToString(*media_info_, &output_string)) { LOG(ERROR) << "Failed to serialize MediaInfo to string."; return; diff --git a/media/event/vod_media_info_dump_muxer_listener.h b/media/event/vod_media_info_dump_muxer_listener.h index b3a14fb76e..421a1caec0 100644 --- a/media/event/vod_media_info_dump_muxer_listener.h +++ b/media/event/vod_media_info_dump_muxer_listener.h @@ -15,6 +15,7 @@ #include #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "media/base/muxer_options.h" #include "media/event/muxer_listener.h" @@ -44,31 +45,28 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener { virtual void OnMediaStart(const MuxerOptions& muxer_options, const std::vector& stream_infos, uint32 time_scale, - ContainerType container_type) OVERRIDE; + ContainerType container_type, + bool is_encrypted) OVERRIDE; - virtual void OnMediaEnd(const std::vector& stream_infos, - bool has_init_range, + virtual void OnMediaEnd(bool has_init_range, uint64 init_range_start, uint64 init_range_end, bool has_index_range, uint64 index_range_start, uint64 index_range_end, float duration_seconds, - uint64 file_size, - bool is_encrypted) OVERRIDE; + uint64 file_size) OVERRIDE; virtual void OnNewSegment(uint64 start_time, uint64 duration, uint64 segment_file_size) OVERRIDE; private: - // Write |media_info| to |file_|. - void SerializeMediaInfoToFile(const dash_packager::MediaInfo& media_info); + // Write |media_info_| to |file_|. + void SerializeMediaInfoToFile(); File* file_; std::string scheme_id_uri_; - MuxerOptions muxer_options_; - uint32 reference_time_scale_; - ContainerType container_type_; + scoped_ptr media_info_; DISALLOW_COPY_AND_ASSIGN(VodMediaInfoDumpMuxerListener); }; 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 24451331ad..7296510904 100644 --- a/media/event/vod_media_info_dump_muxer_listener_unittest.cc +++ b/media/event/vod_media_info_dump_muxer_listener_unittest.cc @@ -19,6 +19,10 @@ using dash_packager::MediaInfo; +namespace { +const bool kEnableEncryption = true; +} // namespace + namespace media { namespace event { @@ -47,7 +51,6 @@ struct OnMediaEndParameters { uint64 index_range_end; float duration_seconds; uint64 file_size; - bool is_encrypted; }; scoped_refptr CreateVideoStreamInfo( @@ -109,7 +112,7 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() { } void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) { - muxer_options->single_segment = false; + muxer_options->single_segment = true; muxer_options->segment_duration = 10.0; muxer_options->fragment_duration = 10.0; muxer_options->segment_sap_aligned = true; @@ -149,7 +152,7 @@ void ExpectTextFormatMediaInfoEqual(const std::string& expect, class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { public: - VodMediaInfoDumpMuxerListenerTest() {} + VodMediaInfoDumpMuxerListenerTest() : temp_file_(NULL) {} virtual ~VodMediaInfoDumpMuxerListenerTest() {} virtual void SetUp() OVERRIDE { @@ -165,30 +168,29 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { base::DeleteFile(temp_file_path_, false); } - void FireOnMediaStartWithDefaultValues( - const std::vector stream_infos) { + void FireOnMediaStartWithDefaultMuxerOptions( + const std::vector stream_infos, + bool enable_encryption) { MuxerOptions muxer_options; SetDefaultMuxerOptionsValues(&muxer_options); const uint32 kReferenceTimeScale = 1000; listener_->OnMediaStart(muxer_options, stream_infos, kReferenceTimeScale, - MuxerListener::kContainerMp4); + MuxerListener::kContainerMp4, + enable_encryption); } - void FireOnMediaEndWithParams(const std::vector stream_infos, - const OnMediaEndParameters& params) { + void FireOnMediaEndWithParams(const OnMediaEndParameters& params) { // On success, this writes the result to |temp_file_|. - listener_->OnMediaEnd(stream_infos, - params.has_init_range, + listener_->OnMediaEnd(params.has_init_range, params.init_range_start, params.init_range_end, params.has_index_range, params.index_range_start, params.index_range_end, params.duration_seconds, - params.file_size, - params.is_encrypted); + params.file_size); } void ExpectTempFileToEqual(const std::string& expected_protobuf) { @@ -216,10 +218,9 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, UnencryptedStream_Normal) { std::vector stream_infos; stream_infos.push_back(stream_info.get()); - FireOnMediaStartWithDefaultValues(stream_infos); + FireOnMediaStartWithDefaultMuxerOptions(stream_infos, !kEnableEncryption); OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams(); - media_end_param.is_encrypted = false; - FireOnMediaEndWithParams(stream_infos, media_end_param); + FireOnMediaEndWithParams(media_end_param); ASSERT_TRUE(temp_file_->Close()); const char kExpectedProtobufOutput[] = @@ -253,11 +254,10 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) { std::vector stream_infos; stream_infos.push_back(stream_info.get()); - FireOnMediaStartWithDefaultValues(stream_infos); + FireOnMediaStartWithDefaultMuxerOptions(stream_infos, kEnableEncryption); OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams(); - media_end_param.is_encrypted = true; - FireOnMediaEndWithParams(stream_infos, media_end_param); + FireOnMediaEndWithParams(media_end_param); ASSERT_TRUE(temp_file_->Close()); const char kExpectedProtobufOutput[] = diff --git a/media/formats/mp4/mp4_muxer.cc b/media/formats/mp4/mp4_muxer.cc index e1b00e5586..b0bd46f199 100644 --- a/media/formats/mp4/mp4_muxer.cc +++ b/media/formats/mp4/mp4_muxer.cc @@ -241,16 +241,14 @@ void MP4Muxer::FireOnMediaStartEvent() { muxer_listener()->OnMediaStart(options(), stream_info_vec, timescale, - event::MuxerListener::kContainerMp4); + event::MuxerListener::kContainerMp4, + encryption_key_source()); } void MP4Muxer::FireOnMediaEndEvent() { if (!muxer_listener()) return; - std::vector stream_info_vec; - GetStreamInfo(&stream_info_vec); - uint32 init_range_start = 0; uint32 init_range_end = 0; const bool has_init_range = @@ -269,16 +267,14 @@ void MP4Muxer::FireOnMediaEndEvent() { return; } - muxer_listener()->OnMediaEnd(stream_info_vec, - has_init_range, + muxer_listener()->OnMediaEnd(has_init_range, init_range_start, init_range_end, has_index_range, index_range_start, index_range_end, duration_seconds, - file_size, - encryption_key_source()); + file_size); } uint64 MP4Muxer::IsoTimeNow() { diff --git a/mpd/base/mpd_notifier.h b/mpd/base/mpd_notifier.h index 77c3ed6352..ec8c635b3d 100644 --- a/mpd/base/mpd_notifier.h +++ b/mpd/base/mpd_notifier.h @@ -17,11 +17,17 @@ namespace dash_packager { class MediaInfo; struct ContentProtectionElement; +enum DashProfile { + kUnknownProfile, + kOnDemandProfile, + kLiveProfile, +}; + /// Interface for publish/subscribe publisher class which notifies MpdBuilder /// of media-related events. class MpdNotifier { public: - MpdNotifier() {}; + MpdNotifier(DashProfile dash_profile) : dash_profile_(dash_profile) {}; virtual ~MpdNotifier() {}; /// Initializes the notifier. For example, if this notifier uses a network for @@ -62,6 +68,14 @@ class MpdNotifier { virtual bool AddContentProtectionElement( uint32 container_id, const ContentProtectionElement& content_protection_element) = 0; + + /// @return The dash profile for this object. + DashProfile dash_profile() const { return dash_profile_; } + + private: + const DashProfile dash_profile_; + + DISALLOW_COPY_AND_ASSIGN(MpdNotifier); }; } // namespace dash_packager diff --git a/mpd/base/simple_mpd_notifier.cc b/mpd/base/simple_mpd_notifier.cc index e0e3ee4fff..992c3f612f 100644 --- a/mpd/base/simple_mpd_notifier.cc +++ b/mpd/base/simple_mpd_notifier.cc @@ -25,9 +25,17 @@ bool AtLeastOneTrue(bool b1, bool b2, bool b3) { namespace dash_packager { -SimpleMpdNotifier::SimpleMpdNotifier(const std::vector& base_urls, +SimpleMpdNotifier::SimpleMpdNotifier(DashProfile dash_profile, + const std::vector& base_urls, const std::string& output_path) - : base_urls_(base_urls), output_path_(output_path) { + : MpdNotifier(dash_profile), + output_path_(output_path), + mpd_builder_(new MpdBuilder(dash_profile == kLiveProfile + ? MpdBuilder::kDynamic + : MpdBuilder::kStatic)) { + DCHECK(dash_profile == kLiveProfile || dash_profile == kOnDemandProfile); + for (size_t i = 0; i < base_urls.size(); ++i) + mpd_builder_->AddBaseUrl(base_urls[i]); } SimpleMpdNotifier::~SimpleMpdNotifier() { @@ -45,35 +53,9 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info, if (content_type == kUnknown) return false; - // Determine whether the media_info is for VOD or live. - bool has_vod_only_fields = HasVODOnlyFields(media_info); - bool has_live_only_fields = HasLiveOnlyFields(media_info); - if (has_vod_only_fields && has_live_only_fields) { - LOG(ERROR) << "MediaInfo with both VOD fields and Live fields is invalid."; - return false; - } - if (!has_vod_only_fields && !has_live_only_fields) { - LOG(ERROR) << "MediaInfo should contain either VOD fields or Live fields."; - return false; - } - MpdBuilder::MpdType mpd_type = - has_vod_only_fields ? MpdBuilder::kStatic : MpdBuilder::kDynamic; - base::AutoLock auto_lock(lock_); // TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation. // Most of the codes here can be moved inside. - if (!mpd_builder_) { - mpd_builder_.reset(new MpdBuilder(mpd_type)); - for (size_t i = 0; i < base_urls_.size(); ++i) - mpd_builder_->AddBaseUrl(base_urls_[i]); - } else { - if (mpd_builder_->type() != mpd_type) { - LOG(ERROR) << "Expecting MediaInfo with '" - << (has_vod_only_fields ? "Live" : "VOD") << "' fields."; - return false; - } - } - AdaptationSet** adaptation_set = &adaptation_set_map_[content_type]; if (*adaptation_set == NULL) *adaptation_set = mpd_builder_->AddAdaptationSet(); @@ -86,7 +68,7 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info, *container_id = representation->id(); - if (has_vod_only_fields) + if (mpd_builder_->type() == MpdBuilder::kStatic) return WriteMpdToFile(); DCHECK(!ContainsKey(representation_map_, representation->id())); diff --git a/mpd/base/simple_mpd_notifier.h b/mpd/base/simple_mpd_notifier.h index 20bf55fd22..d50b66dfdd 100644 --- a/mpd/base/simple_mpd_notifier.h +++ b/mpd/base/simple_mpd_notifier.h @@ -25,7 +25,8 @@ class Representation; /// generates an Mpd file. class SimpleMpdNotifier : public MpdNotifier { public: - SimpleMpdNotifier(const std::vector& base_urls, + SimpleMpdNotifier(DashProfile dash_profile, + const std::vector& base_urls, const std::string& output_path); virtual ~SimpleMpdNotifier(); @@ -52,7 +53,6 @@ class SimpleMpdNotifier : public MpdNotifier { ContentType GetContentType(const MediaInfo& media_info); bool WriteMpdToFile(); - std::vector base_urls_; std::string output_path_; scoped_ptr mpd_builder_;