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 namespace media {
43 class File;
44 } // namespace media
45 
46 class AdaptationSet;
47 class Representation;
48 
49 namespace xml {
50 
51 class XmlNode;
52 class RepresentationXmlNode;
53 
54 } // namespace xml
55 
57 class MpdBuilder {
58  public:
61  explicit MpdBuilder(const MpdOptions& mpd_options);
62  virtual ~MpdBuilder();
63 
66  void AddBaseUrl(const std::string& base_url);
67 
72  virtual AdaptationSet* AddAdaptationSet(const std::string& lang);
73 
77  // TODO(kqyang): Handle file IO in this class as in HLS media_playlist?
78  virtual bool ToString(std::string* output);
79 
85  static void MakePathsRelativeToMpd(const std::string& mpd_path,
86  MediaInfo* media_info);
87 
88  // Inject a |clock| that returns the current time.
90  void InjectClockForTesting(std::unique_ptr<base::Clock> clock) {
91  clock_ = std::move(clock);
92  }
93 
94  private:
95  // LiveMpdBuilderTest needs to set availabilityStartTime so that the test
96  // doesn't need to depend on current time.
97  friend class LiveMpdBuilderTest;
98  template <DashProfile profile>
99  friend class MpdBuilderTest;
100 
101  // Returns the document pointer to the MPD. This must be freed by the caller
102  // using appropriate xmlDocPtr freeing function.
103  // On failure, this returns NULL.
104  xmlDocPtr GenerateMpd();
105 
106  // Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
107  // set attributes for the MPD.
108  void AddCommonMpdInfo(xml::XmlNode* mpd_node);
109 
110  // Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
111  // the first child element is a Period element.
112  void AddStaticMpdInfo(xml::XmlNode* mpd_node);
113 
114  // Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
115  void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
116 
117  float GetStaticMpdDuration(xml::XmlNode* mpd_node);
118 
119  // Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
120  // well as various calculations to set attributes for the MPD.
121  void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
122 
123  // Gets the earliest, normalized segment timestamp. Returns true if
124  // successful, false otherwise.
125  bool GetEarliestTimestamp(double* timestamp_seconds);
126 
127  MpdOptions mpd_options_;
128  std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
129 
130  std::list<std::string> base_urls_;
131  std::string availability_start_time_;
132 
133  base::AtomicSequenceNumber adaptation_set_counter_;
134  base::AtomicSequenceNumber representation_counter_;
135 
136  // By default, this returns the current time. This can be injected for
137  // testing.
138  std::unique_ptr<base::Clock> clock_;
139 
140  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
141 };
142 
146  public:
147  // The role for this AdaptationSet. These values are used to add a Role
148  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
149  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
150  enum Role {
151  kRoleCaption,
152  kRoleSubtitle,
153  kRoleMain,
154  kRoleAlternate,
155  kRoleSupplementary,
156  kRoleCommentary,
157  kRoleDub
158  };
159 
160  virtual ~AdaptationSet();
161 
168  virtual Representation* AddRepresentation(const MediaInfo& media_info);
169 
179  virtual void AddContentProtectionElement(
180  const ContentProtectionElement& element);
181 
193  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
194  const std::string& pssh);
195 
200  virtual void AddRole(Role role);
201 
206  xml::scoped_xml_ptr<xmlNode> GetXml();
207 
213  virtual void ForceSetSegmentAlignment(bool segment_alignment);
214 
217  void AddAdaptationSetSwitching(uint32_t adaptation_set_id);
218 
220  const std::vector<uint32_t>& adaptation_set_switching_ids() const {
221  return adaptation_set_switching_ids_;
222  }
223 
224  // Must be unique in the Period.
225  uint32_t id() const { return id_; }
226 
238  void OnNewSegmentForRepresentation(uint32_t representation_id,
239  uint64_t start_time,
240  uint64_t duration);
241 
254  void OnSetFrameRateForRepresentation(uint32_t representation_id,
255  uint32_t frame_duration,
256  uint32_t timescale);
257 
261  virtual void AddTrickPlayReferenceId(uint32_t id);
262 
263  protected:
271  AdaptationSet(uint32_t adaptation_set_id,
272  const std::string& lang,
273  const MpdOptions& mpd_options,
274  base::AtomicSequenceNumber* representation_counter);
275 
276  private:
277  friend class MpdBuilder;
278  template <DashProfile profile>
279  friend class MpdBuilderTest;
280 
281  // kSegmentAlignmentUnknown means that it is uncertain if the
282  // (sub)segments are aligned or not.
283  // kSegmentAlignmentTrue means that it is certain that the all the (current)
284  // segments added to the adaptation set are aligned.
285  // kSegmentAlignmentFalse means that it is it is certain that some segments
286  // are not aligned. This is useful to disable the computation for
287  // segment alignment, once it is certain that some segments are not aligned.
288  enum SegmentAligmentStatus {
289  kSegmentAlignmentUnknown,
290  kSegmentAlignmentTrue,
291  kSegmentAlignmentFalse
292  };
293 
294  // This maps Representations (IDs) to a list of start times of the segments.
295  // e.g.
296  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
297  // start times 0, 200, 400, then the map contains:
298  // 1 -> [0, 100, 200]
299  // 2 -> [0, 200, 400]
300  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
301 
302  // Gets the earliest, normalized segment timestamp. Returns true if
303  // successful, false otherwise.
304  bool GetEarliestTimestamp(double* timestamp_seconds);
305 
313  void CheckLiveSegmentAlignment(uint32_t representation_id,
314  uint64_t start_time,
315  uint64_t duration);
316 
317  // Checks representation_segment_start_times_ and sets segments_aligned_.
318  // Use this for VOD, do not use for Live.
319  void CheckVodSegmentAlignment();
320 
321  // Records the framerate of a Representation.
322  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
323 
324  std::list<ContentProtectionElement> content_protection_elements_;
325  std::list<std::unique_ptr<Representation>> representations_;
326 
327  base::AtomicSequenceNumber* const representation_counter_;
328 
329  const uint32_t id_;
330  const std::string lang_;
331  const MpdOptions& mpd_options_;
332 
333  // The ids of the adaptation sets this adaptation set can switch to.
334  std::vector<uint32_t> adaptation_set_switching_ids_;
335 
336  // Video widths and heights of Representations. Note that this is a set; if
337  // there is only 1 resolution, then @width & @height should be set, otherwise
338  // @maxWidth & @maxHeight should be set for DASH IOP.
339  std::set<uint32_t> video_widths_;
340  std::set<uint32_t> video_heights_;
341 
342  // Video representations' frame rates.
343  // The frame rate notation for MPD is <integer>/<integer> (where the
344  // denominator is optional). This means the frame rate could be non-whole
345  // rational value, therefore the key is of type double.
346  // Value is <integer>/<integer> in string form.
347  // So, key == CalculatedValue(value)
348  std::map<double, std::string> video_frame_rates_;
349 
350  // contentType attribute of AdaptationSet.
351  // Determined by examining the MediaInfo passed to AddRepresentation().
352  std::string content_type_;
353 
354  // This does not have to be a set, it could be a list or vector because all we
355  // really care is whether there is more than one entry.
356  // Contains one entry if all the Representations have the same picture aspect
357  // ratio (@par attribute for AdaptationSet).
358  // There will be more than one entry if there are multiple picture aspect
359  // ratios.
360  // The @par attribute should only be set if there is exactly one entry
361  // in this set.
362  std::set<std::string> picture_aspect_ratio_;
363 
364  // The roles of this AdaptationSet.
365  std::set<Role> roles_;
366 
367  // True iff all the segments are aligned.
368  SegmentAligmentStatus segments_aligned_;
369  bool force_set_segment_alignment_;
370 
371  // Keeps track of segment start times of Representations.
372  // For VOD, this will not be cleared, all the segment start times are
373  // stored in this. This should not out-of-memory for a reasonable length
374  // video and reasonable subsegment length.
375  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
376  // implementation comment) because storing the entire timeline is not
377  // reasonable and may cause an out-of-memory problem.
378  RepresentationTimeline representation_segment_start_times_;
379 
380  // Record the reference id for the original adaptation sets the trick play
381  // stream belongs to. This is a set because the trick play streams may be for
382  // multiple AdaptationSets (e.g. SD and HD videos in different AdaptationSets
383  // can share the same trick play stream.)
384  std::set<uint32_t> trick_play_reference_ids_;
385 
386  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
387 };
388 
390  public:
393 
398  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
399  uint64_t duration) = 0;
400 
405  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
406  uint32_t timescale) = 0;
407 };
408 
412  public:
413  enum SuppressFlag {
414  kSuppressWidth = 1,
415  kSuppressHeight = 2,
416  kSuppressFrameRate = 4,
417  };
418 
419  virtual ~Representation();
420 
424  bool Init();
425 
436  virtual void AddContentProtectionElement(
437  const ContentProtectionElement& element);
438 
450  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
451  const std::string& pssh);
452 
461  virtual void AddNewSegment(uint64_t start_time,
462  uint64_t duration,
463  uint64_t size);
464 
470  virtual void SetSampleDuration(uint32_t sample_duration);
471 
473  xml::scoped_xml_ptr<xmlNode> GetXml();
474 
483  void SuppressOnce(SuppressFlag flag);
484 
486  uint32_t id() const { return id_; }
487 
488  protected:
498  const MediaInfo& media_info,
499  const MpdOptions& mpd_options,
500  uint32_t representation_id,
501  std::unique_ptr<RepresentationStateChangeListener> state_change_listener);
502 
503  private:
504  friend class AdaptationSet;
505  template <DashProfile profile>
506  friend class MpdBuilderTest;
507 
508  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
509 
510  // Returns true if |media_info_| has required fields to generate a valid
511  // Representation. Otherwise returns false.
512  bool HasRequiredMediaInfoFields();
513 
514  // Return false if the segment should be considered a new segment. True if the
515  // segment is contiguous.
516  bool IsContiguous(uint64_t start_time,
517  uint64_t duration,
518  uint64_t size) const;
519 
520  // Remove elements from |segment_infos_| for dynamic live profile. Increments
521  // |start_number_| by the number of segments removed.
522  void SlideWindow();
523 
524  // Note: Because 'mimeType' is a required field for a valid MPD, these return
525  // strings.
526  std::string GetVideoMimeType() const;
527  std::string GetAudioMimeType() const;
528  std::string GetTextMimeType() const;
529 
530  // Gets the earliest, normalized segment timestamp. Returns true if
531  // successful, false otherwise.
532  bool GetEarliestTimestamp(double* timestamp_seconds);
533 
534  // Init() checks that only one of VideoInfo, AudioInfo, or TextInfo is set. So
535  // any logic using this can assume only one set.
536  MediaInfo media_info_;
537  std::list<ContentProtectionElement> content_protection_elements_;
538  std::list<SegmentInfo> segment_infos_;
539 
540  const uint32_t id_;
541  std::string mime_type_;
542  std::string codecs_;
543  BandwidthEstimator bandwidth_estimator_;
544  const MpdOptions& mpd_options_;
545 
546  // startNumber attribute for SegmentTemplate.
547  // Starts from 1.
548  uint32_t start_number_;
549 
550  // If this is not null, then Representation is responsible for calling the
551  // right methods at right timings.
552  std::unique_ptr<RepresentationStateChangeListener> state_change_listener_;
553 
554  // Bit vector for tracking witch attributes should not be output.
555  int output_suppression_flags_;
556 
557  DISALLOW_COPY_AND_ASSIGN(Representation);
558 };
559 
560 } // namespace shaka
561 
562 #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:57
uint32_t id() const
Definition: mpd_builder.h:486
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:220
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:90
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)