DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerator
mpd_builder.h
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 //
7 // This file contains the MpdBuilder, AdaptationSet, and Representation class
8 // declarations.
9 // http://goo.gl/UrsSlF
10 //
14 
15 #ifndef MPD_BASE_MPD_BUILDER_H_
16 #define MPD_BASE_MPD_BUILDER_H_
17 
18 #include <stdint.h>
19 
20 #include <list>
21 #include <map>
22 #include <set>
23 #include <string>
24 
25 #include "packager/base/atomic_sequence_num.h"
26 #include "packager/base/gtest_prod_util.h"
27 #include "packager/base/stl_util.h"
28 #include "packager/mpd/base/bandwidth_estimator.h"
29 #include "packager/mpd/base/content_protection_element.h"
30 #include "packager/mpd/base/media_info.pb.h"
31 #include "packager/mpd/base/mpd_options.h"
32 #include "packager/mpd/base/segment_info.h"
33 #include "packager/mpd/base/xml/scoped_xml_ptr.h"
34 
35 // TODO(rkuroiwa): For classes with |id_|, consider removing the field and let
36 // the MPD (XML) generation functions take care of assigning an ID to each
37 // element.
38 namespace edash_packager {
39 
40 namespace media {
41 class File;
42 } // namespace media
43 
44 class AdaptationSet;
45 class Representation;
46 
47 namespace xml {
48 
49 class XmlNode;
50 class RepresentationXmlNode;
51 
52 } // namespace xml
53 
55 class MpdBuilder {
56  public:
57  enum MpdType {
58  kStatic = 0,
59  kDynamic
60  };
61 
65  MpdBuilder(MpdType type, const MpdOptions& mpd_options);
66  virtual ~MpdBuilder();
67 
70  void AddBaseUrl(const std::string& base_url);
71 
76  virtual AdaptationSet* AddAdaptationSet(const std::string& lang);
77 
82  bool WriteMpdToFile(media::File* output_file);
83 
87  virtual bool ToString(std::string* output);
88 
90  MpdType type() const { return type_; }
91 
97  static void MakePathsRelativeToMpd(const std::string& mpd_path,
98  MediaInfo* media_info);
99 
100  private:
101  // DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
102  // doesn't need to depend on current time.
103  friend class DynamicMpdBuilderTest;
104 
105  bool ToStringImpl(std::string* output);
106 
107  // This is a helper method for writing out MPDs, called from WriteMpdToFile()
108  // and ToString().
109  template <typename OutputType>
110  bool WriteMpdToOutput(OutputType* output);
111 
112  // Returns the document pointer to the MPD. This must be freed by the caller
113  // using appropriate xmlDocPtr freeing function.
114  // On failure, this returns NULL.
115  xmlDocPtr GenerateMpd();
116 
117  // Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
118  // set attributes for the MPD.
119  void AddCommonMpdInfo(xml::XmlNode* mpd_node);
120 
121  // Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
122  // the first child element is a Period element.
123  void AddStaticMpdInfo(xml::XmlNode* mpd_node);
124 
125  // Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
126  void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
127 
128  float GetStaticMpdDuration(xml::XmlNode* mpd_node);
129 
130  // Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
131  // well as various calculations to set attributes for the MPD.
132  void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
133 
134  // Gets the earliest, normalized segment timestamp. Returns true if
135  // successful, false otherwise.
136  bool GetEarliestTimestamp(double* timestamp_seconds);
137 
138  MpdType type_;
139  MpdOptions mpd_options_;
140  std::list<AdaptationSet*> adaptation_sets_;
141  STLElementDeleter<std::list<AdaptationSet*> > adaptation_sets_deleter_;
142 
143  std::list<std::string> base_urls_;
144  std::string availability_start_time_;
145 
146  base::AtomicSequenceNumber adaptation_set_counter_;
147  base::AtomicSequenceNumber representation_counter_;
148 
149  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
150 };
151 
155  public:
156  // The role for this AdaptationSet. These values are used to add a Role
157  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
158  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
159  enum Role {
160  kRoleCaption,
161  kRoleSubtitle,
162  kRoleMain,
163  kRoleAlternate,
164  kRoleSupplementary,
165  kRoleCommentary,
166  kRoleDub
167  };
168 
169  virtual ~AdaptationSet();
170 
177  virtual Representation* AddRepresentation(const MediaInfo& media_info);
178 
188  virtual void AddContentProtectionElement(
189  const ContentProtectionElement& element);
190 
202  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
203  const std::string& pssh);
204 
209  virtual void AddRole(Role role);
210 
215  xml::scoped_xml_ptr<xmlNode> GetXml();
216 
222  virtual void ForceSetSegmentAlignment(bool segment_alignment);
223 
229  virtual void SetGroup(int group_number);
230 
232  virtual int Group() const;
233 
234  // Must be unique in the Period.
235  uint32_t id() const { return id_; }
236 
248  void OnNewSegmentForRepresentation(uint32_t representation_id,
249  uint64_t start_time,
250  uint64_t duration);
251 
264  void OnSetFrameRateForRepresentation(uint32_t representation_id,
265  uint32_t frame_duration,
266  uint32_t timescale);
267 
268  protected:
276  AdaptationSet(uint32_t adaptation_set_id,
277  const std::string& lang,
278  const MpdOptions& mpd_options,
279  MpdBuilder::MpdType mpd_type,
280  base::AtomicSequenceNumber* representation_counter);
281 
282  private:
283  friend class MpdBuilder;
284  template <MpdBuilder::MpdType type>
285  friend class MpdBuilderTest;
286 
287  // kSegmentAlignmentUnknown means that it is uncertain if the
288  // (sub)segments are aligned or not.
289  // kSegmentAlignmentTrue means that it is certain that the all the (current)
290  // segments added to the adaptation set are aligned.
291  // kSegmentAlignmentFalse means that it is it is certain that some segments
292  // are not aligned. This is useful to disable the computation for
293  // segment alignment, once it is certain that some segments are not aligned.
294  enum SegmentAligmentStatus {
295  kSegmentAlignmentUnknown,
296  kSegmentAlignmentTrue,
297  kSegmentAlignmentFalse
298  };
299 
300  // This maps Representations (IDs) to a list of start times of the segments.
301  // e.g.
302  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
303  // start times 0, 200, 400, then the map contains:
304  // 1 -> [0, 100, 200]
305  // 2 -> [0, 200, 400]
306  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
307 
308  // Gets the earliest, normalized segment timestamp. Returns true if
309  // successful, false otherwise.
310  bool GetEarliestTimestamp(double* timestamp_seconds);
311 
319  void CheckLiveSegmentAlignment(uint32_t representation_id,
320  uint64_t start_time,
321  uint64_t duration);
322 
323  // Checks representation_segment_start_times_ and sets segments_aligned_.
324  // Use this for VOD, do not use for Live.
325  void CheckVodSegmentAlignment();
326 
327  // Records the framerate of a Representation.
328  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
329 
330  std::list<ContentProtectionElement> content_protection_elements_;
331  std::list<Representation*> representations_;
332  STLElementDeleter<std::list<Representation*> > representations_deleter_;
333 
334  base::AtomicSequenceNumber* const representation_counter_;
335 
336  const uint32_t id_;
337  const std::string lang_;
338  const MpdOptions& mpd_options_;
339  const MpdBuilder::MpdType mpd_type_;
340 
341  // The group attribute for the AdaptationSet. If the value is negative,
342  // no group number is specified.
343  // Note that group 0 is a special group number.
344  int group_;
345 
346  // Video widths and heights of Representations. Note that this is a set; if
347  // there is only 1 resolution, then @width & @height should be set, otherwise
348  // @maxWidth & @maxHeight should be set for DASH IOP.
349  std::set<uint32_t> video_widths_;
350  std::set<uint32_t> video_heights_;
351 
352  // Video representations' frame rates.
353  // The frame rate notation for MPD is <integer>/<integer> (where the
354  // denominator is optional). This means the frame rate could be non-whole
355  // rational value, therefore the key is of type double.
356  // Value is <integer>/<integer> in string form.
357  // So, key == CalculatedValue(value)
358  std::map<double, std::string> video_frame_rates_;
359 
360  // contentType attribute of AdaptationSet.
361  // Determined by examining the MediaInfo passed to AddRepresentation().
362  std::string content_type_;
363 
364  // This does not have to be a set, it could be a list or vector because all we
365  // really care is whether there is more than one entry.
366  // Contains one entry if all the Representations have the same picture aspect
367  // ratio (@par attribute for AdaptationSet).
368  // There will be more than one entry if there are multiple picture aspect
369  // ratios.
370  // The @par attribute should only be set if there is exactly one entry
371  // in this set.
372  std::set<std::string> picture_aspect_ratio_;
373 
374  // The roles of this AdaptationSet.
375  std::set<Role> roles_;
376 
377  // True iff all the segments are aligned.
378  SegmentAligmentStatus segments_aligned_;
379  bool force_set_segment_alignment_;
380 
381  // Keeps track of segment start times of Representations.
382  // For VOD, this will not be cleared, all the segment start times are
383  // stored in this. This should not out-of-memory for a reasonable length
384  // video and reasonable subsegment length.
385  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
386  // implementation comment) because storing the entire timeline is not
387  // reasonable and may cause an out-of-memory problem.
388  RepresentationTimeline representation_segment_start_times_;
389 
390  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
391 };
392 
394  public:
397 
402  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
403  uint64_t duration) = 0;
404 
409  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
410  uint32_t timescale) = 0;
411 };
412 
416  public:
417  virtual ~Representation();
418 
422  bool Init();
423 
434  virtual void AddContentProtectionElement(
435  const ContentProtectionElement& element);
436 
448  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
449  const std::string& pssh);
450 
459  virtual void AddNewSegment(uint64_t start_time,
460  uint64_t duration,
461  uint64_t size);
462 
468  virtual void SetSampleDuration(uint32_t sample_duration);
469 
471  xml::scoped_xml_ptr<xmlNode> GetXml();
472 
474  uint32_t id() const { return id_; }
475 
476  protected:
486  const MediaInfo& media_info,
487  const MpdOptions& mpd_options,
488  uint32_t representation_id,
489  scoped_ptr<RepresentationStateChangeListener> state_change_listener);
490 
491  private:
492  friend class AdaptationSet;
493  template <MpdBuilder::MpdType type>
494  friend class MpdBuilderTest;
495 
496  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
497 
498  // Returns true if |media_info_| has required fields to generate a valid
499  // Representation. Otherwise returns false.
500  bool HasRequiredMediaInfoFields();
501 
502  // Return false if the segment should be considered a new segment. True if the
503  // segment is contiguous.
504  bool IsContiguous(uint64_t start_time,
505  uint64_t duration,
506  uint64_t size) const;
507 
508  // Remove elements from |segment_infos_| if
509  // mpd_options_.time_shift_buffer_depth is specified. Increments
510  // |start_number_| by the number of segments removed.
511  void SlideWindow();
512 
513  // Note: Because 'mimeType' is a required field for a valid MPD, these return
514  // strings.
515  std::string GetVideoMimeType() const;
516  std::string GetAudioMimeType() const;
517  std::string GetTextMimeType() const;
518 
519  // Gets the earliest, normalized segment timestamp. Returns true if
520  // successful, false otherwise.
521  bool GetEarliestTimestamp(double* timestamp_seconds);
522 
523  // Init() checks that only one of VideoInfo, AudioInfo, or TextInfo is set. So
524  // any logic using this can assume only one set.
525  MediaInfo media_info_;
526  std::list<ContentProtectionElement> content_protection_elements_;
527  std::list<SegmentInfo> segment_infos_;
528 
529  const uint32_t id_;
530  std::string mime_type_;
531  std::string codecs_;
532  BandwidthEstimator bandwidth_estimator_;
533  const MpdOptions& mpd_options_;
534 
535  // startNumber attribute for SegmentTemplate.
536  // Starts from 1.
537  uint32_t start_number_;
538 
539  // If this is not null, then Representation is responsible for calling the
540  // right methods at right timings.
541  scoped_ptr<RepresentationStateChangeListener> state_change_listener_;
542 
543  DISALLOW_COPY_AND_ASSIGN(Representation);
544 };
545 
546 } // namespace edash_packager
547 
548 #endif // MPD_BASE_MPD_BUILDER_H_
MpdType type() const
Definition: mpd_builder.h:90
virtual void AddNewSegment(uint64_t start_time, uint64_t duration, uint64_t size)
AdaptationSet(uint32_t adaptation_set_id, const std::string &lang, const MpdOptions &mpd_options, MpdBuilder::MpdType mpd_type, base::AtomicSequenceNumber *representation_counter)
Definition: mpd_builder.cc:647
Defines Mpd Options.
Definition: mpd_options.h:13
virtual int Group() const
Definition: mpd_builder.cc:807
virtual AdaptationSet * AddAdaptationSet(const std::string &lang)
Definition: mpd_builder.cc:407
xml::scoped_xml_ptr< xmlNode > GetXml()
Define an abstract file interface.
Definition: file.h:23
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:619
This class generates DASH MPDs (Media Presentation Descriptions).
Definition: mpd_builder.h:55
virtual void ForceSetSegmentAlignment(bool segment_alignment)
Definition: mpd_builder.cc:797
virtual void SetSampleDuration(uint32_t sample_duration)
void AddBaseUrl(const std::string &base_url)
Definition: mpd_builder.cc:403
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Representation(const MediaInfo &media_info, const MpdOptions &mpd_options, uint32_t representation_id, scoped_ptr< RepresentationStateChangeListener > state_change_listener)
Definition: mpd_builder.cc:996
virtual void SetGroup(int group_number)
Definition: mpd_builder.cc:803
virtual void OnNewSegmentForRepresentation(uint64_t start_time, uint64_t duration)=0
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration, uint32_t timescale)=0
RepresentationType in MPD.
Definition: xml_node.h:128
bool WriteMpdToFile(media::File *output_file)
Definition: mpd_builder.cc:417
void OnSetFrameRateForRepresentation(uint32_t representation_id, uint32_t frame_duration, uint32_t timescale)
Definition: mpd_builder.cc:829
virtual Representation * AddRepresentation(const MediaInfo &media_info)
Definition: mpd_builder.cc:666
xml::scoped_xml_ptr< xmlNode > GetXml()
Definition: mpd_builder.cc:728
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Definition: mpd_builder.cc:716
virtual bool ToString(std::string *output)
Definition: mpd_builder.cc:422
virtual void AddRole(Role role)
Definition: mpd_builder.cc:722
MpdBuilder(MpdType type, const MpdOptions &mpd_options)
Definition: mpd_builder.cc:396
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
Definition: mpd_builder.cc:710
void OnNewSegmentForRepresentation(uint32_t representation_id, uint64_t start_time, uint64_t duration)
Definition: mpd_builder.cc:818