7 #include "packager/mpd/base/xml/xml_node.h"
12 #include "packager/base/logging.h"
13 #include "packager/base/macros.h"
14 #include "packager/base/strings/string_number_conversions.h"
15 #include "packager/base/sys_byteorder.h"
16 #include "packager/mpd/base/media_info.pb.h"
17 #include "packager/mpd/base/mpd_utils.h"
18 #include "packager/mpd/base/segment_info.h"
23 typedef MediaInfo::AudioInfo AudioInfo;
24 typedef MediaInfo::VideoInfo VideoInfo;
27 const char kEC3Codec[] =
"ec-3";
29 std::string RangeToString(
const Range& range) {
30 return base::Uint64ToString(range.begin()) +
"-" +
31 base::Uint64ToString(range.end());
34 bool PopulateSegmentTimeline(
const std::list<SegmentInfo>& segment_infos,
35 XmlNode* segment_timeline) {
36 for (std::list<SegmentInfo>::const_iterator it = segment_infos.begin();
37 it != segment_infos.end();
39 XmlNode s_element(
"S");
40 s_element.SetIntegerAttribute(
"t", it->start_time);
41 s_element.SetIntegerAttribute(
"d", it->duration);
43 s_element.SetIntegerAttribute(
"r", it->repeat);
45 CHECK(segment_timeline->AddChild(s_element.PassScopedPtr()));
60 XmlNode::~XmlNode() {}
65 if (!xmlAddChild(node_.get(), child.get()))
70 ignore_result(child.release());
75 for (
size_t element_index = 0; element_index < elements.size();
77 const Element& child_element = elements[element_index];
78 XmlNode child_node(child_element.name.c_str());
79 for (std::map<std::string, std::string>::const_iterator attribute_it =
80 child_element.attributes.begin();
81 attribute_it != child_element.attributes.end(); ++attribute_it) {
83 attribute_it->second);
86 if (!child_node.AddElements(child_element.subelements))
89 child_node.SetContent(child_element.content);
91 if (!xmlAddChild(node_.get(), child_node.GetRawPtr())) {
92 LOG(ERROR) <<
"Failed to set child " << child_element.name
93 <<
" to parent element "
94 <<
reinterpret_cast<const char*
>(node_->name);
99 ignore_result(child_node.Release());
105 const std::string& attribute) {
107 DCHECK(attribute_name);
108 xmlSetProp(node_.get(), BAD_CAST attribute_name, BAD_CAST attribute.c_str());
113 DCHECK(attribute_name);
114 xmlSetProp(node_.get(),
115 BAD_CAST attribute_name,
116 BAD_CAST (base::Uint64ToString(number).c_str()));
122 DCHECK(attribute_name);
123 xmlSetProp(node_.get(), BAD_CAST attribute_name,
133 xmlNodeSetContent(node_.get(), BAD_CAST content.c_str());
137 DVLOG(2) <<
"Passing node_.";
139 return std::move(node_);
143 DVLOG(2) <<
"Releasing node_.";
145 return node_.release();
152 RepresentationBaseXmlNode::RepresentationBaseXmlNode(
const char* name)
154 RepresentationBaseXmlNode::~RepresentationBaseXmlNode() {}
156 bool RepresentationBaseXmlNode::AddContentProtectionElements(
157 const std::list<ContentProtectionElement>& content_protection_elements) {
158 std::list<ContentProtectionElement>::const_iterator content_protection_it =
159 content_protection_elements.begin();
160 for (; content_protection_it != content_protection_elements.end();
161 ++content_protection_it) {
162 if (!AddContentProtectionElement(*content_protection_it))
170 const std::string& scheme_id_uri,
171 const std::string& value) {
172 XmlNode supplemental_property(
"SupplementalProperty");
179 const std::string& scheme_id_uri,
180 const std::string& value) {
181 XmlNode essential_property(
"EssentialProperty");
187 bool RepresentationBaseXmlNode::AddContentProtectionElement(
189 XmlNode content_protection_node(
"ContentProtection");
192 if (!content_protection_element.value.empty()) {
193 content_protection_node.SetStringAttribute(
194 "value", content_protection_element.value);
196 content_protection_node.SetStringAttribute(
197 "schemeIdUri", content_protection_element.scheme_id_uri);
199 typedef std::map<std::string, std::string> AttributesMapType;
200 const AttributesMapType& additional_attributes =
201 content_protection_element.additional_attributes;
203 AttributesMapType::const_iterator attributes_it =
204 additional_attributes.begin();
205 for (; attributes_it != additional_attributes.end(); ++attributes_it) {
206 content_protection_node.SetStringAttribute(attributes_it->first.c_str(),
207 attributes_it->second);
210 if (!content_protection_node.AddElements(
211 content_protection_element.subelements)) {
214 return AddChild(content_protection_node.PassScopedPtr());
217 AdaptationSetXmlNode::AdaptationSetXmlNode()
218 : RepresentationBaseXmlNode(
"AdaptationSet") {}
219 AdaptationSetXmlNode::~AdaptationSetXmlNode() {}
222 const std::string& value) {
229 RepresentationXmlNode::RepresentationXmlNode()
231 RepresentationXmlNode::~RepresentationXmlNode() {}
236 bool set_frame_rate) {
237 if (!video_info.has_width() || !video_info.has_height()) {
238 LOG(ERROR) <<
"Missing width or height for adding a video info.";
242 if (video_info.has_pixel_width() && video_info.has_pixel_height()) {
245 base::IntToString(video_info.pixel_height()));
252 if (set_frame_rate) {
254 base::IntToString(video_info.time_scale()) +
"/" +
255 base::IntToString(video_info.frame_duration()));
258 if (video_info.has_playback_rate()) {
260 base::IntToString(video_info.playback_rate()));
271 if (!AddAudioChannelInfo(audio_info))
274 AddAudioSamplingRateInfo(audio_info);
279 if (media_info.has_media_file_name()) {
281 base_url.
SetContent(media_info.media_file_name());
287 const bool need_segment_base = media_info.has_index_range() ||
288 media_info.has_init_range() ||
289 media_info.has_reference_time_scale();
291 if (need_segment_base) {
292 XmlNode segment_base(
"SegmentBase");
293 if (media_info.has_index_range()) {
295 RangeToString(media_info.index_range()));
298 if (media_info.has_reference_time_scale()) {
300 media_info.reference_time_scale());
303 if (media_info.has_init_range()) {
304 XmlNode initialization(
"Initialization");
306 RangeToString(media_info.init_range()));
320 const MediaInfo& media_info,
321 const std::list<SegmentInfo>& segment_infos,
322 uint32_t start_number) {
323 XmlNode segment_template(
"SegmentTemplate");
324 if (media_info.has_reference_time_scale()) {
326 media_info.reference_time_scale());
329 if (media_info.has_init_segment_name()) {
334 const std::string& init_segment_name = media_info.init_segment_name();
335 if (init_segment_name.find(
"$Number$") != std::string::npos ||
336 init_segment_name.find(
"$Time$") != std::string::npos) {
337 LOG(ERROR) <<
"$Number$ and $Time$ cannot be used for "
338 "SegmentTemplate@initialization";
342 media_info.init_segment_name());
345 if (media_info.has_segment_template()) {
350 if (media_info.segment_template().find(
"$Number") != std::string::npos) {
351 DCHECK_GE(start_number, 1u);
357 XmlNode segment_timeline(
"SegmentTimeline");
359 return PopulateSegmentTimeline(segment_infos, &segment_timeline) &&
364 bool RepresentationXmlNode::AddAudioChannelInfo(
const AudioInfo& audio_info) {
365 std::string audio_channel_config_scheme;
366 std::string audio_channel_config_value;
368 if (audio_info.codec() == kEC3Codec) {
371 const uint16_t ec3_channel_map =
372 base::HostToNet16(audio_info.codec_specific_data().ec3_channel_map());
373 audio_channel_config_value =
374 base::HexEncode(&ec3_channel_map,
sizeof(ec3_channel_map));
375 audio_channel_config_scheme =
376 "tag:dolby.com,2014:dash:audio_channel_configuration:2011";
378 audio_channel_config_value = base::UintToString(audio_info.num_channels());
379 audio_channel_config_scheme =
380 "urn:mpeg:dash:23003:3:audio_channel_configuration:2011";
383 XmlNode audio_channel_config(
"AudioChannelConfiguration");
384 audio_channel_config.SetStringAttribute(
"schemeIdUri",
385 audio_channel_config_scheme);
386 audio_channel_config.SetStringAttribute(
"value", audio_channel_config_value);
388 return AddChild(audio_channel_config.PassScopedPtr());
393 void RepresentationXmlNode::AddAudioSamplingRateInfo(
394 const AudioInfo& audio_info) {
395 if (audio_info.has_sampling_frequency())
bool AddVideoInfo(const MediaInfo::VideoInfo &video_info, bool set_width, bool set_height, bool set_frame_rate)
void SetFloatingPointAttribute(const char *attribute_name, double number)
scoped_xml_ptr< xmlNode > PassScopedPtr()
XmlNode(const char *name)
bool AddVODOnlyInfo(const MediaInfo &media_info)
void AddEssentialProperty(const std::string &scheme_id_uri, const std::string &value)
void SetStringAttribute(const char *attribute_name, const std::string &attribute)
bool AddChild(scoped_xml_ptr< xmlNode > child)
bool AddLiveOnlyInfo(const MediaInfo &media_info, const std::list< SegmentInfo > &segment_infos, uint32_t start_number)
bool AddElements(const std::vector< Element > &elements)
Adds Elements to this node using the Element struct.
std::string DoubleToString(double value)
void AddSupplementalProperty(const std::string &scheme_id_uri, const std::string &value)
void SetIntegerAttribute(const char *attribute_name, uint64_t number)
void AddRoleElement(const std::string &scheme_id_uri, const std::string &value)
void SetContent(const std::string &content)
bool AddAudioInfo(const MediaInfo::AudioInfo &audio_info)