DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations 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/callback.h"
27 #include "packager/base/gtest_prod_util.h"
28 #include "packager/base/time/clock.h"
29 #include "packager/base/time/time.h"
30 #include "packager/mpd/base/bandwidth_estimator.h"
31 #include "packager/mpd/base/content_protection_element.h"
32 #include "packager/mpd/base/media_info.pb.h"
33 #include "packager/mpd/base/mpd_options.h"
34 #include "packager/mpd/base/segment_info.h"
35 #include "packager/mpd/base/xml/scoped_xml_ptr.h"
36 
37 // TODO(rkuroiwa): For classes with |id_|, consider removing the field and let
38 // the MPD (XML) generation functions take care of assigning an ID to each
39 // element.
40 namespace shaka {
41 
42 class AdaptationSet;
43 class File;
44 class Representation;
45 
46 namespace xml {
47 
48 class XmlNode;
49 class RepresentationXmlNode;
50 
51 } // namespace xml
52 
54 class MpdBuilder {
55  public:
58  explicit MpdBuilder(const MpdOptions& mpd_options);
59  virtual ~MpdBuilder();
60 
63  void AddBaseUrl(const std::string& base_url);
64 
69  virtual AdaptationSet* AddAdaptationSet(const std::string& lang);
70 
74  // TODO(kqyang): Handle file IO in this class as in HLS media_playlist?
75  virtual bool ToString(std::string* output);
76 
82  static void MakePathsRelativeToMpd(const std::string& mpd_path,
83  MediaInfo* media_info);
84 
85  // Inject a |clock| that returns the current time.
87  void InjectClockForTesting(std::unique_ptr<base::Clock> clock) {
88  clock_ = std::move(clock);
89  }
90 
91  private:
92  // LiveMpdBuilderTest needs to set availabilityStartTime so that the test
93  // doesn't need to depend on current time.
94  friend class LiveMpdBuilderTest;
95  template <DashProfile profile>
96  friend class MpdBuilderTest;
97 
98  // Returns the document pointer to the MPD. This must be freed by the caller
99  // using appropriate xmlDocPtr freeing function.
100  // On failure, this returns NULL.
101  xmlDocPtr GenerateMpd();
102 
103  // Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
104  // set attributes for the MPD.
105  void AddCommonMpdInfo(xml::XmlNode* mpd_node);
106 
107  // Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
108  // the first child element is a Period element.
109  void AddStaticMpdInfo(xml::XmlNode* mpd_node);
110 
111  // Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
112  void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
113 
114  float GetStaticMpdDuration(xml::XmlNode* mpd_node);
115 
116  // Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
117  // well as various calculations to set attributes for the MPD.
118  void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
119 
120  // Gets the earliest, normalized segment timestamp. Returns true if
121  // successful, false otherwise.
122  bool GetEarliestTimestamp(double* timestamp_seconds);
123 
124  MpdOptions mpd_options_;
125  std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
126 
127  std::list<std::string> base_urls_;
128  std::string availability_start_time_;
129 
130  base::AtomicSequenceNumber adaptation_set_counter_;
131  base::AtomicSequenceNumber representation_counter_;
132 
133  // By default, this returns the current time. This can be injected for
134  // testing.
135  std::unique_ptr<base::Clock> clock_;
136 
137  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
138 };
139 
143  public:
144  // The role for this AdaptationSet. These values are used to add a Role
145  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
146  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
147  enum Role {
148  kRoleCaption,
149  kRoleSubtitle,
150  kRoleMain,
151  kRoleAlternate,
152  kRoleSupplementary,
153  kRoleCommentary,
154  kRoleDub
155  };
156 
157  virtual ~AdaptationSet();
158 
165  virtual Representation* AddRepresentation(const MediaInfo& media_info);
166 
176  virtual void AddContentProtectionElement(
177  const ContentProtectionElement& element);
178 
190  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
191  const std::string& pssh);
192 
197  virtual void AddRole(Role role);
198 
203  xml::scoped_xml_ptr<xmlNode> GetXml();
204 
210  virtual void ForceSetSegmentAlignment(bool segment_alignment);
211 
214  void AddAdaptationSetSwitching(uint32_t adaptation_set_id);
215 
217  const std::vector<uint32_t>& adaptation_set_switching_ids() const {
218  return adaptation_set_switching_ids_;
219  }
220 
221  // Must be unique in the Period.
222  uint32_t id() const { return id_; }
223 
235  void OnNewSegmentForRepresentation(uint32_t representation_id,
236  uint64_t start_time,
237  uint64_t duration);
238 
251  void OnSetFrameRateForRepresentation(uint32_t representation_id,
252  uint32_t frame_duration,
253  uint32_t timescale);
254 
258  virtual void AddTrickPlayReferenceId(uint32_t id);
259 
260  protected:
268  AdaptationSet(uint32_t adaptation_set_id,
269  const std::string& lang,
270  const MpdOptions& mpd_options,
271  base::AtomicSequenceNumber* representation_counter);
272 
273  private:
274  friend class MpdBuilder;
275  template <DashProfile profile>
276  friend class MpdBuilderTest;
277 
278  // kSegmentAlignmentUnknown means that it is uncertain if the
279  // (sub)segments are aligned or not.
280  // kSegmentAlignmentTrue means that it is certain that the all the (current)
281  // segments added to the adaptation set are aligned.
282  // kSegmentAlignmentFalse means that it is it is certain that some segments
283  // are not aligned. This is useful to disable the computation for
284  // segment alignment, once it is certain that some segments are not aligned.
285  enum SegmentAligmentStatus {
286  kSegmentAlignmentUnknown,
287  kSegmentAlignmentTrue,
288  kSegmentAlignmentFalse
289  };
290 
291  // This maps Representations (IDs) to a list of start times of the segments.
292  // e.g.
293  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
294  // start times 0, 200, 400, then the map contains:
295  // 1 -> [0, 100, 200]
296  // 2 -> [0, 200, 400]
297  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
298 
299  // Gets the earliest, normalized segment timestamp. Returns true if
300  // successful, false otherwise.
301  bool GetEarliestTimestamp(double* timestamp_seconds);
302 
310  void CheckLiveSegmentAlignment(uint32_t representation_id,
311  uint64_t start_time,
312  uint64_t duration);
313 
314  // Checks representation_segment_start_times_ and sets segments_aligned_.
315  // Use this for VOD, do not use for Live.
316  void CheckVodSegmentAlignment();
317 
318  // Records the framerate of a Representation.
319  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
320 
321  std::list<ContentProtectionElement> content_protection_elements_;
322  std::list<std::unique_ptr<Representation>> representations_;
323 
324  base::AtomicSequenceNumber* const representation_counter_;
325 
326  const uint32_t id_;
327  const std::string lang_;
328  const MpdOptions& mpd_options_;
329 
330  // The ids of the adaptation sets this adaptation set can switch to.
331  std::vector<uint32_t> adaptation_set_switching_ids_;
332 
333  // Video widths and heights of Representations. Note that this is a set; if
334  // there is only 1 resolution, then @width & @height should be set, otherwise
335  // @maxWidth & @maxHeight should be set for DASH IOP.
336  std::set<uint32_t> video_widths_;
337  std::set<uint32_t> video_heights_;
338 
339  // Video representations' frame rates.
340  // The frame rate notation for MPD is <integer>/<integer> (where the
341  // denominator is optional). This means the frame rate could be non-whole
342  // rational value, therefore the key is of type double.
343  // Value is <integer>/<integer> in string form.
344  // So, key == CalculatedValue(value)
345  std::map<double, std::string> video_frame_rates_;
346 
347  // contentType attribute of AdaptationSet.
348  // Determined by examining the MediaInfo passed to AddRepresentation().
349  std::string content_type_;
350 
351  // This does not have to be a set, it could be a list or vector because all we
352  // really care is whether there is more than one entry.
353  // Contains one entry if all the Representations have the same picture aspect
354  // ratio (@par attribute for AdaptationSet).
355  // There will be more than one entry if there are multiple picture aspect
356  // ratios.
357  // The @par attribute should only be set if there is exactly one entry
358  // in this set.
359  std::set<std::string> picture_aspect_ratio_;
360 
361  // The roles of this AdaptationSet.
362  std::set<Role> roles_;
363 
364  // True iff all the segments are aligned.
365  SegmentAligmentStatus segments_aligned_;
366  bool force_set_segment_alignment_;
367 
368  // Keeps track of segment start times of Representations.
369  // For VOD, this will not be cleared, all the segment start times are
370  // stored in this. This should not out-of-memory for a reasonable length
371  // video and reasonable subsegment length.
372  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
373  // implementation comment) because storing the entire timeline is not
374  // reasonable and may cause an out-of-memory problem.
375  RepresentationTimeline representation_segment_start_times_;
376 
377  // Record the reference id for the original adaptation sets the trick play
378  // stream belongs to. This is a set because the trick play streams may be for
379  // multiple AdaptationSets (e.g. SD and HD videos in different AdaptationSets
380  // can share the same trick play stream.)
381  std::set<uint32_t> trick_play_reference_ids_;
382 
383  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
384 };
385 
387  public:
390 
395  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
396  uint64_t duration) = 0;
397 
402  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
403  uint32_t timescale) = 0;
404 };
405 
409  public:
410  enum SuppressFlag {
411  kSuppressWidth = 1,
412  kSuppressHeight = 2,
413  kSuppressFrameRate = 4,
414  };
415 
416  virtual ~Representation();
417 
421  bool Init();
422 
433  virtual void AddContentProtectionElement(
434  const ContentProtectionElement& element);
435 
447  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
448  const std::string& pssh);
449 
458  virtual void AddNewSegment(uint64_t start_time,
459  uint64_t duration,
460  uint64_t size);
461 
467  virtual void SetSampleDuration(uint32_t sample_duration);
468 
470  xml::scoped_xml_ptr<xmlNode> GetXml();
471 
480  void SuppressOnce(SuppressFlag flag);
481 
483  uint32_t id() const { return id_; }
484 
485  protected:
495  const MediaInfo& media_info,
496  const MpdOptions& mpd_options,
497  uint32_t representation_id,
498  std::unique_ptr<RepresentationStateChangeListener> state_change_listener);
499 
500  private:
501  friend class AdaptationSet;
502  template <DashProfile profile>
503  friend class MpdBuilderTest;
504 
505  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
506 
507  // Returns true if |media_info_| has required fields to generate a valid
508  // Representation. Otherwise returns false.
509  bool HasRequiredMediaInfoFields();
510 
511  // Return false if the segment should be considered a new segment. True if the
512  // segment is contiguous.
513  bool IsContiguous(uint64_t start_time,
514  uint64_t duration,
515  uint64_t size) const;
516 
517  // Remove elements from |segment_infos_| for dynamic live profile. Increments
518  // |start_number_| by the number of segments removed.
519  void SlideWindow();
520 
521  // Note: Because 'mimeType' is a required field for a valid MPD, these return
522  // strings.
523  std::string GetVideoMimeType() const;
524  std::string GetAudioMimeType() const;
525  std::string GetTextMimeType() const;
526 
527  // Gets the earliest, normalized segment timestamp. Returns true if
528  // successful, false otherwise.
529  bool GetEarliestTimestamp(double* timestamp_seconds);
530 
531  // Init() checks that only one of VideoInfo, AudioInfo, or TextInfo is set. So
532  // any logic using this can assume only one set.
533  MediaInfo media_info_;
534  std::list<ContentProtectionElement> content_protection_elements_;
535  std::list<SegmentInfo> segment_infos_;
536 
537  const uint32_t id_;
538  std::string mime_type_;
539  std::string codecs_;
540  BandwidthEstimator bandwidth_estimator_;
541  const MpdOptions& mpd_options_;
542 
543  // startNumber attribute for SegmentTemplate.
544  // Starts from 1.
545  uint32_t start_number_;
546 
547  // If this is not null, then Representation is responsible for calling the
548  // right methods at right timings.
549  std::unique_ptr<RepresentationStateChangeListener> state_change_listener_;
550 
551  // Bit vector for tracking witch attributes should not be output.
552  int output_suppression_flags_;
553 
554  DISALLOW_COPY_AND_ASSIGN(Representation);
555 };
556 
557 } // namespace shaka
558 
559 #endif // MPD_BASE_MPD_BUILDER_H_
void OnSetFrameRateForRepresentation(uint32_t representation_id, uint32_t frame_duration, uint32_t timescale)
Definition: mpd_builder.cc:858
RepresentationType in MPD.
Definition: xml_node.h:139
virtual void AddNewSegment(uint64_t start_time, uint64_t duration, uint64_t size)
virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration, uint32_t timescale)=0
Representation(const MediaInfo &media_info, const MpdOptions &mpd_options, uint32_t representation_id, std::unique_ptr< RepresentationStateChangeListener > state_change_listener)
virtual void SetSampleDuration(uint32_t sample_duration)
virtual Representation * AddRepresentation(const MediaInfo &media_info)
Definition: mpd_builder.cc:663
This class generates DASH MPDs (Media Presentation Descriptions).
Definition: mpd_builder.h:54
uint32_t id() const
Definition: mpd_builder.h:483
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
Definition: mpd_builder.cc:709
virtual void AddTrickPlayReferenceId(uint32_t id)
Definition: mpd_builder.cc:865
MpdBuilder(const MpdOptions &mpd_options)
Definition: mpd_builder.cc:373
virtual void AddRole(Role role)
Definition: mpd_builder.cc:721
void AddBaseUrl(const std::string &base_url)
Definition: mpd_builder.cc:378
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Definition: mpd_builder.cc:715
AdaptationSet(uint32_t adaptation_set_id, const std::string &lang, const MpdOptions &mpd_options, base::AtomicSequenceNumber *representation_counter)
Definition: mpd_builder.cc:648
xml::scoped_xml_ptr< xmlNode > GetXml()
virtual bool ToString(std::string *output)
Definition: mpd_builder.cc:396
void AddAdaptationSetSwitching(uint32_t adaptation_set_id)
Definition: mpd_builder.cc:836
const std::vector< uint32_t > & adaptation_set_switching_ids() const
Definition: mpd_builder.h:217
virtual void ForceSetSegmentAlignment(bool segment_alignment)
Definition: mpd_builder.cc:830
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:620
xml::scoped_xml_ptr< xmlNode > GetXml()
Definition: mpd_builder.cc:731
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
virtual AdaptationSet * AddAdaptationSet(const std::string &lang)
Definition: mpd_builder.cc:382
Defines Mpd Options.
Definition: mpd_options.h:23
void OnNewSegmentForRepresentation(uint32_t representation_id, uint64_t start_time, uint64_t duration)
Definition: mpd_builder.cc:847
void InjectClockForTesting(std::unique_ptr< base::Clock > clock)
This is for testing.
Definition: mpd_builder.h:87
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
virtual void OnNewSegmentForRepresentation(uint64_t start_time, uint64_t duration)=0
void SuppressOnce(SuppressFlag flag)