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:
59  enum MpdType {
60  kStatic = 0,
61  kDynamic
62  };
63 
67  MpdBuilder(MpdType type, const MpdOptions& mpd_options);
68  virtual ~MpdBuilder();
69 
72  void AddBaseUrl(const std::string& base_url);
73 
78  virtual AdaptationSet* AddAdaptationSet(const std::string& lang);
79 
84  bool WriteMpdToFile(media::File* output_file);
85 
89  virtual bool ToString(std::string* output);
90 
92  MpdType type() const { return type_; }
93 
99  static void MakePathsRelativeToMpd(const std::string& mpd_path,
100  MediaInfo* media_info);
101 
102  // Inject a |clock| that returns the current time.
104  void InjectClockForTesting(std::unique_ptr<base::Clock> clock) {
105  clock_ = std::move(clock);
106  }
107 
108  private:
109  // DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
110  // doesn't need to depend on current time.
111  friend class DynamicMpdBuilderTest;
112 
113  bool ToStringImpl(std::string* output);
114 
115  // This is a helper method for writing out MPDs, called from WriteMpdToFile()
116  // and ToString().
117  template <typename OutputType>
118  bool WriteMpdToOutput(OutputType* output);
119 
120  // Returns the document pointer to the MPD. This must be freed by the caller
121  // using appropriate xmlDocPtr freeing function.
122  // On failure, this returns NULL.
123  xmlDocPtr GenerateMpd();
124 
125  // Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
126  // set attributes for the MPD.
127  void AddCommonMpdInfo(xml::XmlNode* mpd_node);
128 
129  // Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
130  // the first child element is a Period element.
131  void AddStaticMpdInfo(xml::XmlNode* mpd_node);
132 
133  // Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
134  void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
135 
136  float GetStaticMpdDuration(xml::XmlNode* mpd_node);
137 
138  // Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
139  // well as various calculations to set attributes for the MPD.
140  void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
141 
142  // Gets the earliest, normalized segment timestamp. Returns true if
143  // successful, false otherwise.
144  bool GetEarliestTimestamp(double* timestamp_seconds);
145 
146  MpdType type_;
147  MpdOptions mpd_options_;
148  std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
149 
150  std::list<std::string> base_urls_;
151  std::string availability_start_time_;
152 
153  base::AtomicSequenceNumber adaptation_set_counter_;
154  base::AtomicSequenceNumber representation_counter_;
155 
156  // By default, this returns the current time. This can be injected for
157  // testing.
158  std::unique_ptr<base::Clock> clock_;
159 
160  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
161 };
162 
166  public:
167  // The role for this AdaptationSet. These values are used to add a Role
168  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
169  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
170  enum Role {
171  kRoleCaption,
172  kRoleSubtitle,
173  kRoleMain,
174  kRoleAlternate,
175  kRoleSupplementary,
176  kRoleCommentary,
177  kRoleDub
178  };
179 
180  virtual ~AdaptationSet();
181 
188  virtual Representation* AddRepresentation(const MediaInfo& media_info);
189 
199  virtual void AddContentProtectionElement(
200  const ContentProtectionElement& element);
201 
213  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
214  const std::string& pssh);
215 
220  virtual void AddRole(Role role);
221 
226  xml::scoped_xml_ptr<xmlNode> GetXml();
227 
233  virtual void ForceSetSegmentAlignment(bool segment_alignment);
234 
240  virtual void SetGroup(int group_number);
241 
243  virtual int Group() const;
244 
245  // Must be unique in the Period.
246  uint32_t id() const { return id_; }
247 
259  void OnNewSegmentForRepresentation(uint32_t representation_id,
260  uint64_t start_time,
261  uint64_t duration);
262 
275  void OnSetFrameRateForRepresentation(uint32_t representation_id,
276  uint32_t frame_duration,
277  uint32_t timescale);
278 
279  protected:
287  AdaptationSet(uint32_t adaptation_set_id,
288  const std::string& lang,
289  const MpdOptions& mpd_options,
290  MpdBuilder::MpdType mpd_type,
291  base::AtomicSequenceNumber* representation_counter);
292 
293  private:
294  friend class MpdBuilder;
295  template <MpdBuilder::MpdType type>
296  friend class MpdBuilderTest;
297 
298  // kSegmentAlignmentUnknown means that it is uncertain if the
299  // (sub)segments are aligned or not.
300  // kSegmentAlignmentTrue means that it is certain that the all the (current)
301  // segments added to the adaptation set are aligned.
302  // kSegmentAlignmentFalse means that it is it is certain that some segments
303  // are not aligned. This is useful to disable the computation for
304  // segment alignment, once it is certain that some segments are not aligned.
305  enum SegmentAligmentStatus {
306  kSegmentAlignmentUnknown,
307  kSegmentAlignmentTrue,
308  kSegmentAlignmentFalse
309  };
310 
311  // This maps Representations (IDs) to a list of start times of the segments.
312  // e.g.
313  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
314  // start times 0, 200, 400, then the map contains:
315  // 1 -> [0, 100, 200]
316  // 2 -> [0, 200, 400]
317  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
318 
319  // Gets the earliest, normalized segment timestamp. Returns true if
320  // successful, false otherwise.
321  bool GetEarliestTimestamp(double* timestamp_seconds);
322 
330  void CheckLiveSegmentAlignment(uint32_t representation_id,
331  uint64_t start_time,
332  uint64_t duration);
333 
334  // Checks representation_segment_start_times_ and sets segments_aligned_.
335  // Use this for VOD, do not use for Live.
336  void CheckVodSegmentAlignment();
337 
338  // Records the framerate of a Representation.
339  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
340 
341  std::list<ContentProtectionElement> content_protection_elements_;
342  std::list<std::unique_ptr<Representation>> representations_;
343 
344  base::AtomicSequenceNumber* const representation_counter_;
345 
346  const uint32_t id_;
347  const std::string lang_;
348  const MpdOptions& mpd_options_;
349  const MpdBuilder::MpdType mpd_type_;
350 
351  // The group attribute for the AdaptationSet. If the value is negative,
352  // no group number is specified.
353  // Note that group 0 is a special group number.
354  int group_;
355 
356  // Video widths and heights of Representations. Note that this is a set; if
357  // there is only 1 resolution, then @width & @height should be set, otherwise
358  // @maxWidth & @maxHeight should be set for DASH IOP.
359  std::set<uint32_t> video_widths_;
360  std::set<uint32_t> video_heights_;
361 
362  // Video representations' frame rates.
363  // The frame rate notation for MPD is <integer>/<integer> (where the
364  // denominator is optional). This means the frame rate could be non-whole
365  // rational value, therefore the key is of type double.
366  // Value is <integer>/<integer> in string form.
367  // So, key == CalculatedValue(value)
368  std::map<double, std::string> video_frame_rates_;
369 
370  // contentType attribute of AdaptationSet.
371  // Determined by examining the MediaInfo passed to AddRepresentation().
372  std::string content_type_;
373 
374  // This does not have to be a set, it could be a list or vector because all we
375  // really care is whether there is more than one entry.
376  // Contains one entry if all the Representations have the same picture aspect
377  // ratio (@par attribute for AdaptationSet).
378  // There will be more than one entry if there are multiple picture aspect
379  // ratios.
380  // The @par attribute should only be set if there is exactly one entry
381  // in this set.
382  std::set<std::string> picture_aspect_ratio_;
383 
384  // The roles of this AdaptationSet.
385  std::set<Role> roles_;
386 
387  // True iff all the segments are aligned.
388  SegmentAligmentStatus segments_aligned_;
389  bool force_set_segment_alignment_;
390 
391  // Keeps track of segment start times of Representations.
392  // For VOD, this will not be cleared, all the segment start times are
393  // stored in this. This should not out-of-memory for a reasonable length
394  // video and reasonable subsegment length.
395  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
396  // implementation comment) because storing the entire timeline is not
397  // reasonable and may cause an out-of-memory problem.
398  RepresentationTimeline representation_segment_start_times_;
399 
400  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
401 };
402 
404  public:
407 
412  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
413  uint64_t duration) = 0;
414 
419  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
420  uint32_t timescale) = 0;
421 };
422 
426  public:
427  enum SuppressFlag {
428  kSuppressWidth = 1,
429  kSuppressHeight = 2,
430  kSuppressFrameRate = 4,
431  };
432 
433  virtual ~Representation();
434 
438  bool Init();
439 
450  virtual void AddContentProtectionElement(
451  const ContentProtectionElement& element);
452 
464  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
465  const std::string& pssh);
466 
475  virtual void AddNewSegment(uint64_t start_time,
476  uint64_t duration,
477  uint64_t size);
478 
484  virtual void SetSampleDuration(uint32_t sample_duration);
485 
487  xml::scoped_xml_ptr<xmlNode> GetXml();
488 
497  void SuppressOnce(SuppressFlag flag);
498 
500  uint32_t id() const { return id_; }
501 
502  protected:
512  const MediaInfo& media_info,
513  const MpdOptions& mpd_options,
514  uint32_t representation_id,
515  std::unique_ptr<RepresentationStateChangeListener> state_change_listener);
516 
517  private:
518  friend class AdaptationSet;
519  template <MpdBuilder::MpdType type>
520  friend class MpdBuilderTest;
521 
522  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
523 
524  // Returns true if |media_info_| has required fields to generate a valid
525  // Representation. Otherwise returns false.
526  bool HasRequiredMediaInfoFields();
527 
528  // Return false if the segment should be considered a new segment. True if the
529  // segment is contiguous.
530  bool IsContiguous(uint64_t start_time,
531  uint64_t duration,
532  uint64_t size) const;
533 
534  // Remove elements from |segment_infos_| if
535  // mpd_options_.time_shift_buffer_depth is specified. Increments
536  // |start_number_| by the number of segments removed.
537  void SlideWindow();
538 
539  // Note: Because 'mimeType' is a required field for a valid MPD, these return
540  // strings.
541  std::string GetVideoMimeType() const;
542  std::string GetAudioMimeType() const;
543  std::string GetTextMimeType() const;
544 
545  // Gets the earliest, normalized segment timestamp. Returns true if
546  // successful, false otherwise.
547  bool GetEarliestTimestamp(double* timestamp_seconds);
548 
549  // Init() checks that only one of VideoInfo, AudioInfo, or TextInfo is set. So
550  // any logic using this can assume only one set.
551  MediaInfo media_info_;
552  std::list<ContentProtectionElement> content_protection_elements_;
553  std::list<SegmentInfo> segment_infos_;
554 
555  const uint32_t id_;
556  std::string mime_type_;
557  std::string codecs_;
558  BandwidthEstimator bandwidth_estimator_;
559  const MpdOptions& mpd_options_;
560 
561  // startNumber attribute for SegmentTemplate.
562  // Starts from 1.
563  uint32_t start_number_;
564 
565  // If this is not null, then Representation is responsible for calling the
566  // right methods at right timings.
567  std::unique_ptr<RepresentationStateChangeListener> state_change_listener_;
568 
569  // Bit vector for tracking witch attributes should not be output.
570  int output_suppression_flags_;
571 
572  DISALLOW_COPY_AND_ASSIGN(Representation);
573 };
574 
575 } // namespace shaka
576 
577 #endif // MPD_BASE_MPD_BUILDER_H_
void OnSetFrameRateForRepresentation(uint32_t representation_id, uint32_t frame_duration, uint32_t timescale)
Definition: mpd_builder.cc:869
RepresentationType in MPD.
Definition: xml_node.h:129
virtual void AddNewSegment(uint64_t start_time, uint64_t duration, uint64_t size)
virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration, uint32_t timescale)=0
bool WriteMpdToFile(media::File *output_file)
Definition: mpd_builder.cc:426
Representation(const MediaInfo &media_info, const MpdOptions &mpd_options, uint32_t representation_id, std::unique_ptr< RepresentationStateChangeListener > state_change_listener)
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:675
virtual void SetSampleDuration(uint32_t sample_duration)
virtual Representation * AddRepresentation(const MediaInfo &media_info)
Definition: mpd_builder.cc:693
This class generates DASH MPDs (Media Presentation Descriptions).
Definition: mpd_builder.h:57
uint32_t id() const
Definition: mpd_builder.h:500
Define an abstract file interface.
Definition: file.h:24
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
Definition: mpd_builder.cc:737
virtual void AddRole(Role role)
Definition: mpd_builder.cc:749
void AddBaseUrl(const std::string &base_url)
Definition: mpd_builder.cc:408
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Definition: mpd_builder.cc:743
MpdType type() const
Definition: mpd_builder.h:92
virtual void SetGroup(int group_number)
Definition: mpd_builder.cc:843
xml::scoped_xml_ptr< xmlNode > GetXml()
virtual bool ToString(std::string *output)
Definition: mpd_builder.cc:431
virtual void ForceSetSegmentAlignment(bool segment_alignment)
Definition: mpd_builder.cc:837
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:647
MpdBuilder(MpdType type, const MpdOptions &mpd_options)
Definition: mpd_builder.cc:401
xml::scoped_xml_ptr< xmlNode > GetXml()
Definition: mpd_builder.cc:759
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
virtual AdaptationSet * AddAdaptationSet(const std::string &lang)
Definition: mpd_builder.cc:412
virtual int Group() const
Definition: mpd_builder.cc:847
Defines Mpd Options.
Definition: mpd_options.h:15
void OnNewSegmentForRepresentation(uint32_t representation_id, uint64_t start_time, uint64_t duration)
Definition: mpd_builder.cc:858
void InjectClockForTesting(std::unique_ptr< base::Clock > clock)
This is for testing.
Definition: mpd_builder.h:104
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)