Implement MpdNotifyMuxerListener
Change-Id: I08742839c2be5e5da104914ec841b8c5dd57f0b7
This commit is contained in:
parent
1899d5c3b0
commit
6837ac45b7
|
@ -15,44 +15,72 @@
|
||||||
#include "mpd/base/media_info.pb.h"
|
#include "mpd/base/media_info.pb.h"
|
||||||
#include "mpd/base/mpd_notifier.h"
|
#include "mpd/base/mpd_notifier.h"
|
||||||
|
|
||||||
|
using dash_packager::MediaInfo;
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
namespace event {
|
namespace event {
|
||||||
|
|
||||||
MpdNotifyMuxerListener::MpdNotifyMuxerListener(
|
MpdNotifyMuxerListener::MpdNotifyMuxerListener(
|
||||||
dash_packager::MpdNotifier* mpd_notifier)
|
dash_packager::MpdNotifier* mpd_notifier)
|
||||||
: mpd_notifier_(mpd_notifier),
|
: mpd_notifier_(mpd_notifier),
|
||||||
reference_time_scale_(0),
|
notification_id_(0) {
|
||||||
container_type_(kContainerUnknown) {
|
|
||||||
DCHECK(mpd_notifier);
|
DCHECK(mpd_notifier);
|
||||||
|
DCHECK(mpd_notifier->dash_profile() == dash_packager::kOnDemandProfile ||
|
||||||
|
mpd_notifier->dash_profile() == dash_packager::kLiveProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {}
|
MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {}
|
||||||
|
|
||||||
|
void MpdNotifyMuxerListener::SetContentProtectionSchemeIdUri(
|
||||||
|
const std::string& scheme_id_uri) {
|
||||||
|
scheme_id_uri_ = scheme_id_uri;
|
||||||
|
}
|
||||||
|
|
||||||
void MpdNotifyMuxerListener::OnMediaStart(
|
void MpdNotifyMuxerListener::OnMediaStart(
|
||||||
const MuxerOptions& muxer_options,
|
const MuxerOptions& muxer_options,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
const std::vector<StreamInfo*>& stream_infos,
|
||||||
uint32 time_scale,
|
uint32 time_scale,
|
||||||
ContainerType container_type) {
|
ContainerType container_type,
|
||||||
muxer_options_ = muxer_options;
|
bool is_encrypted) {
|
||||||
reference_time_scale_ = time_scale;
|
scoped_ptr<MediaInfo> media_info(new MediaInfo());
|
||||||
container_type_ = container_type;
|
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(
|
void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
|
||||||
bool has_init_range,
|
|
||||||
uint64 init_range_start,
|
uint64 init_range_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
uint64 index_range_start,
|
uint64 index_range_start,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size) {
|
||||||
bool is_encrypted) {
|
if (mpd_notifier_->dash_profile() == dash_packager::kLiveProfile)
|
||||||
dash_packager::MediaInfo media_info;
|
return;
|
||||||
if (!internal::GenerateMediaInfo(muxer_options_,
|
|
||||||
stream_infos,
|
DCHECK(media_info_);
|
||||||
has_init_range,
|
if (!internal::SetVodInformation(has_init_range,
|
||||||
init_range_start,
|
init_range_start,
|
||||||
init_range_end,
|
init_range_end,
|
||||||
has_index_range,
|
has_index_range,
|
||||||
|
@ -60,20 +88,24 @@ void MpdNotifyMuxerListener::OnMediaEnd(
|
||||||
index_range_end,
|
index_range_end,
|
||||||
duration_seconds,
|
duration_seconds,
|
||||||
file_size,
|
file_size,
|
||||||
reference_time_scale_,
|
media_info_.get())) {
|
||||||
container_type_,
|
LOG(ERROR) << "Failed to generate VOD information from input.";
|
||||||
&media_info)) {
|
|
||||||
LOG(ERROR) << "Failed to generate MediaInfo from input.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 id; // Result unused.
|
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,
|
void MpdNotifyMuxerListener::OnNewSegment(uint64 start_time,
|
||||||
uint64 duration,
|
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 event
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
|
|
@ -12,10 +12,12 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "media/base/muxer_options.h"
|
#include "media/base/muxer_options.h"
|
||||||
#include "media/event/muxer_listener.h"
|
#include "media/event/muxer_listener.h"
|
||||||
|
|
||||||
namespace dash_packager {
|
namespace dash_packager {
|
||||||
|
class MediaInfo;
|
||||||
class MpdNotifier;
|
class MpdNotifier;
|
||||||
} // namespace dash_packager
|
} // namespace dash_packager
|
||||||
|
|
||||||
|
@ -24,37 +26,42 @@ namespace event {
|
||||||
|
|
||||||
class MpdNotifyMuxerListener : public MuxerListener {
|
class MpdNotifyMuxerListener : public MuxerListener {
|
||||||
public:
|
public:
|
||||||
// |mpd_notifier| must be initialized, i.e mpd_notifier->Init() must be
|
/// @param mpd_notifier must be initialized, i.e mpd_notifier->Init() must be
|
||||||
// called.
|
/// called.
|
||||||
MpdNotifyMuxerListener(dash_packager::MpdNotifier* mpd_notifier);
|
MpdNotifyMuxerListener(dash_packager::MpdNotifier* mpd_notifier);
|
||||||
virtual ~MpdNotifyMuxerListener();
|
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,
|
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,
|
||||||
ContainerType container_type) OVERRIDE;
|
ContainerType container_type,
|
||||||
|
bool is_encrypted) OVERRIDE;
|
||||||
|
|
||||||
virtual void OnMediaEnd(const std::vector<StreamInfo*>& stream_infos,
|
virtual void OnMediaEnd(bool has_init_range,
|
||||||
bool has_init_range,
|
|
||||||
uint64 init_range_start,
|
uint64 init_range_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
uint64 index_range_start,
|
uint64 index_range_start,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size) OVERRIDE;
|
||||||
bool is_encrypted) OVERRIDE;
|
|
||||||
|
|
||||||
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:
|
private:
|
||||||
dash_packager::MpdNotifier* const mpd_notifier_;
|
dash_packager::MpdNotifier* const mpd_notifier_;
|
||||||
MuxerOptions muxer_options_;
|
uint32 notification_id_;
|
||||||
uint32 reference_time_scale_;
|
scoped_ptr<dash_packager::MediaInfo> media_info_;
|
||||||
ContainerType container_type_;
|
std::string scheme_id_uri_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(MpdNotifyMuxerListener);
|
DISALLOW_COPY_AND_ASSIGN(MpdNotifyMuxerListener);
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,8 @@ class MuxerListener {
|
||||||
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,
|
||||||
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
|
// Called when all files are written out and the muxer object does not output
|
||||||
// any more files.
|
// any more files.
|
||||||
|
@ -51,16 +52,14 @@ class MuxerListener {
|
||||||
// Both ranges are inclusive.
|
// Both ranges are inclusive.
|
||||||
// Media length of |duration_seconds|.
|
// Media length of |duration_seconds|.
|
||||||
// |file_size| of the media in bytes.
|
// |file_size| of the media in bytes.
|
||||||
virtual void OnMediaEnd(const std::vector<StreamInfo*>& stream_infos,
|
virtual void OnMediaEnd(bool has_init_range,
|
||||||
bool has_init_range,
|
|
||||||
uint64 init_range_start,
|
uint64 init_range_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
uint64 index_range_start,
|
uint64 index_range_start,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size) = 0;
|
||||||
bool is_encrypted) = 0;
|
|
||||||
|
|
||||||
// Called when a segment has been muxed and the file has been written.
|
// Called when a segment has been muxed and the file has been written.
|
||||||
// Note: For video on demand (VOD), this would be for subsegments.
|
// Note: For video on demand (VOD), this would be for subsegments.
|
||||||
|
|
|
@ -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,
|
void AddVideoInfo(const VideoStreamInfo* video_stream_info,
|
||||||
MediaInfo* media_info) {
|
MediaInfo* media_info) {
|
||||||
DCHECK(video_stream_info);
|
DCHECK(video_stream_info);
|
||||||
|
@ -160,14 +143,32 @@ void SetMediaInfoStreamInfo(const std::vector<StreamInfo*>& stream_infos,
|
||||||
void SetMediaInfoMuxerOptions(const MuxerOptions& muxer_options,
|
void SetMediaInfoMuxerOptions(const MuxerOptions& muxer_options,
|
||||||
MediaInfo* media_info) {
|
MediaInfo* media_info) {
|
||||||
DCHECK(media_info);
|
DCHECK(media_info);
|
||||||
|
if (muxer_options.single_segment) {
|
||||||
media_info->set_media_file_name(muxer_options.output_file_name);
|
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
|
} // namespace
|
||||||
|
|
||||||
bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
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_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
|
@ -175,8 +176,6 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size,
|
||||||
uint32 reference_time_scale,
|
|
||||||
MuxerListener::ContainerType container_type,
|
|
||||||
MediaInfo* media_info) {
|
MediaInfo* media_info) {
|
||||||
DCHECK(media_info);
|
DCHECK(media_info);
|
||||||
if (file_size == 0) {
|
if (file_size == 0) {
|
||||||
|
@ -187,10 +186,9 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
if (duration_seconds <= 0.0f) {
|
if (duration_seconds <= 0.0f) {
|
||||||
// Non positive second media must be invalid media.
|
// Non positive second media must be invalid media.
|
||||||
LOG(ERROR) << "Duration is not positive: " << duration_seconds;
|
LOG(ERROR) << "Duration is not positive: " << duration_seconds;
|
||||||
return false;;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMediaInfoMuxerOptions(muxer_options, media_info);
|
|
||||||
SetMediaInfoRanges(has_init_range,
|
SetMediaInfoRanges(has_init_range,
|
||||||
init_range_start,
|
init_range_start,
|
||||||
init_range_end,
|
init_range_end,
|
||||||
|
@ -198,14 +196,48 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
index_range_start,
|
index_range_start,
|
||||||
index_range_end,
|
index_range_end,
|
||||||
media_info);
|
media_info);
|
||||||
SetMediaInfoCommonInfo(duration_seconds,
|
|
||||||
file_size,
|
media_info->set_media_duration_seconds(duration_seconds);
|
||||||
reference_time_scale,
|
media_info->set_bandwidth(
|
||||||
container_type,
|
EstimateRequiredBandwidth(file_size, duration_seconds));
|
||||||
media_info);
|
|
||||||
SetMediaInfoStreamInfo(stream_infos, media_info);
|
|
||||||
return true;
|
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 internal
|
||||||
} // namespace event
|
} // namespace event
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
|
#ifndef MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
|
||||||
#define MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
|
#define MEDIA_EVENT_MUXER_LISTENER_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
@ -24,11 +25,17 @@ struct MuxerOptions;
|
||||||
namespace event {
|
namespace event {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// On success fill |media_info| with input data and return true, otherwise
|
/// @param[out] media_info points to the MediaInfo object to be filled.
|
||||||
// return false.
|
/// @return true on success, false otherwise.
|
||||||
bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
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_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
|
@ -36,8 +43,15 @@ bool GenerateMediaInfo(const MuxerOptions& muxer_options,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size,
|
||||||
uint32 reference_time_scale_,
|
dash_packager::MediaInfo* media_info);
|
||||||
MuxerListener::ContainerType container_type,
|
|
||||||
|
/// @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);
|
dash_packager::MediaInfo* media_info);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -19,54 +19,8 @@ namespace event {
|
||||||
|
|
||||||
using dash_packager::MediaInfo;
|
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)
|
VodMediaInfoDumpMuxerListener::VodMediaInfoDumpMuxerListener(File* output_file)
|
||||||
: file_(output_file),
|
: file_(output_file) {}
|
||||||
reference_time_scale_(0),
|
|
||||||
container_type_(kContainerUnknown) {}
|
|
||||||
|
|
||||||
VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {}
|
VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {}
|
||||||
|
|
||||||
|
@ -79,27 +33,38 @@ void VodMediaInfoDumpMuxerListener::OnMediaStart(
|
||||||
const MuxerOptions& muxer_options,
|
const MuxerOptions& muxer_options,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
const std::vector<StreamInfo*>& stream_infos,
|
||||||
uint32 time_scale,
|
uint32 time_scale,
|
||||||
ContainerType container_type) {
|
ContainerType container_type,
|
||||||
muxer_options_ = muxer_options;
|
bool is_encrypted) {
|
||||||
reference_time_scale_ = time_scale;
|
DCHECK(muxer_options.single_segment);
|
||||||
container_type_ = container_type;
|
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(
|
void VodMediaInfoDumpMuxerListener::OnMediaEnd(bool has_init_range,
|
||||||
const std::vector<StreamInfo*>& stream_infos,
|
|
||||||
bool has_init_range,
|
|
||||||
uint64 init_range_start,
|
uint64 init_range_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
uint64 index_range_start,
|
uint64 index_range_start,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size) {
|
||||||
bool is_encrypted) {
|
DCHECK(media_info_);
|
||||||
MediaInfo media_info;
|
if (!internal::SetVodInformation(has_init_range,
|
||||||
if (!internal::GenerateMediaInfo(muxer_options_,
|
|
||||||
stream_infos,
|
|
||||||
has_init_range,
|
|
||||||
init_range_start,
|
init_range_start,
|
||||||
init_range_end,
|
init_range_end,
|
||||||
has_index_range,
|
has_index_range,
|
||||||
|
@ -107,22 +72,11 @@ void VodMediaInfoDumpMuxerListener::OnMediaEnd(
|
||||||
index_range_end,
|
index_range_end,
|
||||||
duration_seconds,
|
duration_seconds,
|
||||||
file_size,
|
file_size,
|
||||||
reference_time_scale_,
|
media_info_.get())) {
|
||||||
container_type_,
|
LOG(ERROR) << "Failed to generate VOD information from input.";
|
||||||
&media_info)) {
|
|
||||||
LOG(ERROR) << "Failed to generate MediaInfo from input.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SerializeMediaInfoToFile();
|
||||||
if (is_encrypted) {
|
|
||||||
if (!AddContentProtectionElements(
|
|
||||||
container_type_, scheme_id_uri_, &media_info)) {
|
|
||||||
LOG(ERROR) << "Failed to add content protection elements.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializeMediaInfoToFile(media_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time,
|
void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time,
|
||||||
|
@ -131,10 +85,9 @@ void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64 start_time,
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile(
|
void VodMediaInfoDumpMuxerListener::SerializeMediaInfoToFile() {
|
||||||
const MediaInfo& media_info) {
|
|
||||||
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;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "media/base/muxer_options.h"
|
#include "media/base/muxer_options.h"
|
||||||
#include "media/event/muxer_listener.h"
|
#include "media/event/muxer_listener.h"
|
||||||
|
|
||||||
|
@ -44,31 +45,28 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
||||||
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,
|
||||||
ContainerType container_type) OVERRIDE;
|
ContainerType container_type,
|
||||||
|
bool is_encrypted) OVERRIDE;
|
||||||
|
|
||||||
virtual void OnMediaEnd(const std::vector<StreamInfo*>& stream_infos,
|
virtual void OnMediaEnd(bool has_init_range,
|
||||||
bool has_init_range,
|
|
||||||
uint64 init_range_start,
|
uint64 init_range_start,
|
||||||
uint64 init_range_end,
|
uint64 init_range_end,
|
||||||
bool has_index_range,
|
bool has_index_range,
|
||||||
uint64 index_range_start,
|
uint64 index_range_start,
|
||||||
uint64 index_range_end,
|
uint64 index_range_end,
|
||||||
float duration_seconds,
|
float duration_seconds,
|
||||||
uint64 file_size,
|
uint64 file_size) OVERRIDE;
|
||||||
bool is_encrypted) OVERRIDE;
|
|
||||||
|
|
||||||
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:
|
private:
|
||||||
// Write |media_info| to |file_|.
|
// Write |media_info_| to |file_|.
|
||||||
void SerializeMediaInfoToFile(const dash_packager::MediaInfo& media_info);
|
void SerializeMediaInfoToFile();
|
||||||
|
|
||||||
File* file_;
|
File* file_;
|
||||||
std::string scheme_id_uri_;
|
std::string scheme_id_uri_;
|
||||||
MuxerOptions muxer_options_;
|
scoped_ptr<dash_packager::MediaInfo> media_info_;
|
||||||
uint32 reference_time_scale_;
|
|
||||||
ContainerType container_type_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(VodMediaInfoDumpMuxerListener);
|
DISALLOW_COPY_AND_ASSIGN(VodMediaInfoDumpMuxerListener);
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
|
|
||||||
using dash_packager::MediaInfo;
|
using dash_packager::MediaInfo;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const bool kEnableEncryption = true;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
namespace event {
|
namespace event {
|
||||||
|
|
||||||
|
@ -47,7 +51,6 @@ struct OnMediaEndParameters {
|
||||||
uint64 index_range_end;
|
uint64 index_range_end;
|
||||||
float duration_seconds;
|
float duration_seconds;
|
||||||
uint64 file_size;
|
uint64 file_size;
|
||||||
bool is_encrypted;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
scoped_refptr<StreamInfo> CreateVideoStreamInfo(
|
scoped_refptr<StreamInfo> CreateVideoStreamInfo(
|
||||||
|
@ -109,7 +112,7 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) {
|
void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) {
|
||||||
muxer_options->single_segment = false;
|
muxer_options->single_segment = true;
|
||||||
muxer_options->segment_duration = 10.0;
|
muxer_options->segment_duration = 10.0;
|
||||||
muxer_options->fragment_duration = 10.0;
|
muxer_options->fragment_duration = 10.0;
|
||||||
muxer_options->segment_sap_aligned = true;
|
muxer_options->segment_sap_aligned = true;
|
||||||
|
@ -149,7 +152,7 @@ void ExpectTextFormatMediaInfoEqual(const std::string& expect,
|
||||||
|
|
||||||
class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
VodMediaInfoDumpMuxerListenerTest() {}
|
VodMediaInfoDumpMuxerListenerTest() : temp_file_(NULL) {}
|
||||||
virtual ~VodMediaInfoDumpMuxerListenerTest() {}
|
virtual ~VodMediaInfoDumpMuxerListenerTest() {}
|
||||||
|
|
||||||
virtual void SetUp() OVERRIDE {
|
virtual void SetUp() OVERRIDE {
|
||||||
|
@ -165,30 +168,29 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
|
||||||
base::DeleteFile(temp_file_path_, false);
|
base::DeleteFile(temp_file_path_, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FireOnMediaStartWithDefaultValues(
|
void FireOnMediaStartWithDefaultMuxerOptions(
|
||||||
const std::vector<StreamInfo*> stream_infos) {
|
const std::vector<StreamInfo*> stream_infos,
|
||||||
|
bool enable_encryption) {
|
||||||
MuxerOptions muxer_options;
|
MuxerOptions muxer_options;
|
||||||
SetDefaultMuxerOptionsValues(&muxer_options);
|
SetDefaultMuxerOptionsValues(&muxer_options);
|
||||||
const uint32 kReferenceTimeScale = 1000;
|
const uint32 kReferenceTimeScale = 1000;
|
||||||
listener_->OnMediaStart(muxer_options,
|
listener_->OnMediaStart(muxer_options,
|
||||||
stream_infos,
|
stream_infos,
|
||||||
kReferenceTimeScale,
|
kReferenceTimeScale,
|
||||||
MuxerListener::kContainerMp4);
|
MuxerListener::kContainerMp4,
|
||||||
|
enable_encryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FireOnMediaEndWithParams(const std::vector<StreamInfo*> stream_infos,
|
void FireOnMediaEndWithParams(const OnMediaEndParameters& params) {
|
||||||
const OnMediaEndParameters& params) {
|
|
||||||
// On success, this writes the result to |temp_file_|.
|
// On success, this writes the result to |temp_file_|.
|
||||||
listener_->OnMediaEnd(stream_infos,
|
listener_->OnMediaEnd(params.has_init_range,
|
||||||
params.has_init_range,
|
|
||||||
params.init_range_start,
|
params.init_range_start,
|
||||||
params.init_range_end,
|
params.init_range_end,
|
||||||
params.has_index_range,
|
params.has_index_range,
|
||||||
params.index_range_start,
|
params.index_range_start,
|
||||||
params.index_range_end,
|
params.index_range_end,
|
||||||
params.duration_seconds,
|
params.duration_seconds,
|
||||||
params.file_size,
|
params.file_size);
|
||||||
params.is_encrypted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpectTempFileToEqual(const std::string& expected_protobuf) {
|
void ExpectTempFileToEqual(const std::string& expected_protobuf) {
|
||||||
|
@ -216,10 +218,9 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, UnencryptedStream_Normal) {
|
||||||
std::vector<StreamInfo*> stream_infos;
|
std::vector<StreamInfo*> stream_infos;
|
||||||
stream_infos.push_back(stream_info.get());
|
stream_infos.push_back(stream_info.get());
|
||||||
|
|
||||||
FireOnMediaStartWithDefaultValues(stream_infos);
|
FireOnMediaStartWithDefaultMuxerOptions(stream_infos, !kEnableEncryption);
|
||||||
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
||||||
media_end_param.is_encrypted = false;
|
FireOnMediaEndWithParams(media_end_param);
|
||||||
FireOnMediaEndWithParams(stream_infos, media_end_param);
|
|
||||||
ASSERT_TRUE(temp_file_->Close());
|
ASSERT_TRUE(temp_file_->Close());
|
||||||
|
|
||||||
const char kExpectedProtobufOutput[] =
|
const char kExpectedProtobufOutput[] =
|
||||||
|
@ -253,11 +254,10 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) {
|
||||||
std::vector<StreamInfo*> stream_infos;
|
std::vector<StreamInfo*> stream_infos;
|
||||||
stream_infos.push_back(stream_info.get());
|
stream_infos.push_back(stream_info.get());
|
||||||
|
|
||||||
FireOnMediaStartWithDefaultValues(stream_infos);
|
FireOnMediaStartWithDefaultMuxerOptions(stream_infos, kEnableEncryption);
|
||||||
|
|
||||||
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
OnMediaEndParameters media_end_param = GetDefaultOnMediaEndParams();
|
||||||
media_end_param.is_encrypted = true;
|
FireOnMediaEndWithParams(media_end_param);
|
||||||
FireOnMediaEndWithParams(stream_infos, media_end_param);
|
|
||||||
ASSERT_TRUE(temp_file_->Close());
|
ASSERT_TRUE(temp_file_->Close());
|
||||||
|
|
||||||
const char kExpectedProtobufOutput[] =
|
const char kExpectedProtobufOutput[] =
|
||||||
|
|
|
@ -241,16 +241,14 @@ void MP4Muxer::FireOnMediaStartEvent() {
|
||||||
muxer_listener()->OnMediaStart(options(),
|
muxer_listener()->OnMediaStart(options(),
|
||||||
stream_info_vec,
|
stream_info_vec,
|
||||||
timescale,
|
timescale,
|
||||||
event::MuxerListener::kContainerMp4);
|
event::MuxerListener::kContainerMp4,
|
||||||
|
encryption_key_source());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4Muxer::FireOnMediaEndEvent() {
|
void MP4Muxer::FireOnMediaEndEvent() {
|
||||||
if (!muxer_listener())
|
if (!muxer_listener())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<StreamInfo*> stream_info_vec;
|
|
||||||
GetStreamInfo(&stream_info_vec);
|
|
||||||
|
|
||||||
uint32 init_range_start = 0;
|
uint32 init_range_start = 0;
|
||||||
uint32 init_range_end = 0;
|
uint32 init_range_end = 0;
|
||||||
const bool has_init_range =
|
const bool has_init_range =
|
||||||
|
@ -269,16 +267,14 @@ void MP4Muxer::FireOnMediaEndEvent() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
muxer_listener()->OnMediaEnd(stream_info_vec,
|
muxer_listener()->OnMediaEnd(has_init_range,
|
||||||
has_init_range,
|
|
||||||
init_range_start,
|
init_range_start,
|
||||||
init_range_end,
|
init_range_end,
|
||||||
has_index_range,
|
has_index_range,
|
||||||
index_range_start,
|
index_range_start,
|
||||||
index_range_end,
|
index_range_end,
|
||||||
duration_seconds,
|
duration_seconds,
|
||||||
file_size,
|
file_size);
|
||||||
encryption_key_source());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 MP4Muxer::IsoTimeNow() {
|
uint64 MP4Muxer::IsoTimeNow() {
|
||||||
|
|
|
@ -17,11 +17,17 @@ namespace dash_packager {
|
||||||
class MediaInfo;
|
class MediaInfo;
|
||||||
struct ContentProtectionElement;
|
struct ContentProtectionElement;
|
||||||
|
|
||||||
|
enum DashProfile {
|
||||||
|
kUnknownProfile,
|
||||||
|
kOnDemandProfile,
|
||||||
|
kLiveProfile,
|
||||||
|
};
|
||||||
|
|
||||||
/// Interface for publish/subscribe publisher class which notifies MpdBuilder
|
/// Interface for publish/subscribe publisher class which notifies MpdBuilder
|
||||||
/// of media-related events.
|
/// of media-related events.
|
||||||
class MpdNotifier {
|
class MpdNotifier {
|
||||||
public:
|
public:
|
||||||
MpdNotifier() {};
|
MpdNotifier(DashProfile dash_profile) : dash_profile_(dash_profile) {};
|
||||||
virtual ~MpdNotifier() {};
|
virtual ~MpdNotifier() {};
|
||||||
|
|
||||||
/// Initializes the notifier. For example, if this notifier uses a network for
|
/// Initializes the notifier. For example, if this notifier uses a network for
|
||||||
|
@ -62,6 +68,14 @@ class MpdNotifier {
|
||||||
virtual bool AddContentProtectionElement(
|
virtual bool AddContentProtectionElement(
|
||||||
uint32 container_id,
|
uint32 container_id,
|
||||||
const ContentProtectionElement& content_protection_element) = 0;
|
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
|
} // namespace dash_packager
|
||||||
|
|
|
@ -25,9 +25,17 @@ bool AtLeastOneTrue(bool b1, bool b2, bool b3) {
|
||||||
|
|
||||||
namespace dash_packager {
|
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)
|
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() {
|
SimpleMpdNotifier::~SimpleMpdNotifier() {
|
||||||
|
@ -45,35 +53,9 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
||||||
if (content_type == kUnknown)
|
if (content_type == kUnknown)
|
||||||
return false;
|
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_);
|
base::AutoLock auto_lock(lock_);
|
||||||
// TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation.
|
// TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation.
|
||||||
// Most of the codes here can be moved inside.
|
// 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];
|
AdaptationSet** adaptation_set = &adaptation_set_map_[content_type];
|
||||||
if (*adaptation_set == NULL)
|
if (*adaptation_set == NULL)
|
||||||
*adaptation_set = mpd_builder_->AddAdaptationSet();
|
*adaptation_set = mpd_builder_->AddAdaptationSet();
|
||||||
|
@ -86,7 +68,7 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
||||||
|
|
||||||
*container_id = representation->id();
|
*container_id = representation->id();
|
||||||
|
|
||||||
if (has_vod_only_fields)
|
if (mpd_builder_->type() == MpdBuilder::kStatic)
|
||||||
return WriteMpdToFile();
|
return WriteMpdToFile();
|
||||||
|
|
||||||
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
||||||
|
|
|
@ -25,7 +25,8 @@ class Representation;
|
||||||
/// generates an Mpd file.
|
/// generates an Mpd file.
|
||||||
class SimpleMpdNotifier : public MpdNotifier {
|
class SimpleMpdNotifier : public MpdNotifier {
|
||||||
public:
|
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);
|
const std::string& output_path);
|
||||||
virtual ~SimpleMpdNotifier();
|
virtual ~SimpleMpdNotifier();
|
||||||
|
|
||||||
|
@ -52,7 +53,6 @@ class SimpleMpdNotifier : public MpdNotifier {
|
||||||
ContentType GetContentType(const MediaInfo& media_info);
|
ContentType GetContentType(const MediaInfo& media_info);
|
||||||
bool WriteMpdToFile();
|
bool WriteMpdToFile();
|
||||||
|
|
||||||
std::vector<std::string> base_urls_;
|
|
||||||
std::string output_path_;
|
std::string output_path_;
|
||||||
|
|
||||||
scoped_ptr<MpdBuilder> mpd_builder_;
|
scoped_ptr<MpdBuilder> mpd_builder_;
|
||||||
|
|
Loading…
Reference in New Issue