Implement MpdNotifyMuxerListener

Change-Id: I08742839c2be5e5da104914ec841b8c5dd57f0b7
This commit is contained in:
KongQun Yang 2014-05-16 16:32:10 -07:00 committed by Kongqun Yang
parent 1899d5c3b0
commit 6837ac45b7
12 changed files with 256 additions and 229 deletions

View File

@ -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<StreamInfo*>& 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<MediaInfo> 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;
}
void MpdNotifyMuxerListener::OnMediaEnd(
const std::vector<StreamInfo*>& stream_infos,
bool has_init_range,
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, &notification_id_);
} else {
media_info_ = media_info.Pass();
}
}
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,
bool is_encrypted) {
dash_packager::MediaInfo media_info;
if (!internal::GenerateMediaInfo(muxer_options_,
stream_infos,
has_init_range,
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

View File

@ -12,10 +12,12 @@
#include <vector>
#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<StreamInfo*>& stream_infos,
uint32 time_scale,
ContainerType container_type) OVERRIDE;
ContainerType container_type,
bool is_encrypted) OVERRIDE;
virtual void OnMediaEnd(const std::vector<StreamInfo*>& 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<dash_packager::MediaInfo> media_info_;
std::string scheme_id_uri_;
DISALLOW_COPY_AND_ASSIGN(MpdNotifyMuxerListener);
};

View File

@ -39,7 +39,8 @@ class MuxerListener {
virtual void OnMediaStart(const MuxerOptions& muxer_options,
const std::vector<StreamInfo*>& 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<StreamInfo*>& 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.

View File

@ -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<StreamInfo*>& stream_infos,
void SetMediaInfoMuxerOptions(const MuxerOptions& muxer_options,
MediaInfo* media_info) {
DCHECK(media_info);
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<StreamInfo*>& 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

View File

@ -7,6 +7,7 @@
#ifndef MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
#define MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
#include <string>
#include <vector>
#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<StreamInfo*>& 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,8 +43,15 @@ 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

View File

@ -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<StreamInfo*>& 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;
}
void VodMediaInfoDumpMuxerListener::OnMediaEnd(
const std::vector<StreamInfo*>& stream_infos,
bool has_init_range,
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(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,
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;

View File

@ -15,6 +15,7 @@
#include <vector>
#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<StreamInfo*>& stream_infos,
uint32 time_scale,
ContainerType container_type) OVERRIDE;
ContainerType container_type,
bool is_encrypted) OVERRIDE;
virtual void OnMediaEnd(const std::vector<StreamInfo*>& 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<dash_packager::MediaInfo> media_info_;
DISALLOW_COPY_AND_ASSIGN(VodMediaInfoDumpMuxerListener);
};

View File

@ -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<StreamInfo> 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<StreamInfo*> stream_infos) {
void FireOnMediaStartWithDefaultMuxerOptions(
const std::vector<StreamInfo*> 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<StreamInfo*> 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<StreamInfo*> 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<StreamInfo*> 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[] =

View File

@ -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<StreamInfo*> 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() {

View File

@ -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

View File

@ -25,9 +25,17 @@ bool AtLeastOneTrue(bool b1, bool b2, bool b3) {
namespace dash_packager {
SimpleMpdNotifier::SimpleMpdNotifier(const std::vector<std::string>& base_urls,
SimpleMpdNotifier::SimpleMpdNotifier(DashProfile dash_profile,
const std::vector<std::string>& 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()));

View File

@ -25,7 +25,8 @@ class Representation;
/// generates an Mpd file.
class SimpleMpdNotifier : public MpdNotifier {
public:
SimpleMpdNotifier(const std::vector<std::string>& base_urls,
SimpleMpdNotifier(DashProfile dash_profile,
const std::vector<std::string>& 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<std::string> base_urls_;
std::string output_path_;
scoped_ptr<MpdBuilder> mpd_builder_;