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 
78  bool WriteMpdToFile(media::File* output_file);
79 
83  virtual bool ToString(std::string* output);
84 
90  static void MakePathsRelativeToMpd(const std::string& mpd_path,
91  MediaInfo* media_info);
92 
93  // Inject a |clock| that returns the current time.
95  void InjectClockForTesting(std::unique_ptr<base::Clock> clock) {
96  clock_ = std::move(clock);
97  }
98 
99  private:
100  // LiveMpdBuilderTest needs to set availabilityStartTime so that the test
101  // doesn't need to depend on current time.
102  friend class LiveMpdBuilderTest;
103  template <DashProfile profile>
104  friend class MpdBuilderTest;
105 
106  bool ToStringImpl(std::string* output);
107 
108  // This is a helper method for writing out MPDs, called from WriteMpdToFile()
109  // and ToString().
110  template <typename OutputType>
111  bool WriteMpdToOutput(OutputType* output);
112 
113  // Returns the document pointer to the MPD. This must be freed by the caller
114  // using appropriate xmlDocPtr freeing function.
115  // On failure, this returns NULL.
116  xmlDocPtr GenerateMpd();
117 
118  // Set MPD attributes common to all profiles. Uses non-zero |mpd_options_| to
119  // set attributes for the MPD.
120  void AddCommonMpdInfo(xml::XmlNode* mpd_node);
121 
122  // Adds 'static' MPD attributes and elements to |mpd_node|. This assumes that
123  // the first child element is a Period element.
124  void AddStaticMpdInfo(xml::XmlNode* mpd_node);
125 
126  // Same as AddStaticMpdInfo() but for 'dynamic' MPDs.
127  void AddDynamicMpdInfo(xml::XmlNode* mpd_node);
128 
129  float GetStaticMpdDuration(xml::XmlNode* mpd_node);
130 
131  // Set MPD attributes for dynamic profile MPD. Uses non-zero |mpd_options_| as
132  // well as various calculations to set attributes for the MPD.
133  void SetDynamicMpdAttributes(xml::XmlNode* mpd_node);
134 
135  // Gets the earliest, normalized segment timestamp. Returns true if
136  // successful, false otherwise.
137  bool GetEarliestTimestamp(double* timestamp_seconds);
138 
139  MpdOptions mpd_options_;
140  std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
141 
142  std::list<std::string> base_urls_;
143  std::string availability_start_time_;
144 
145  base::AtomicSequenceNumber adaptation_set_counter_;
146  base::AtomicSequenceNumber representation_counter_;
147 
148  // By default, this returns the current time. This can be injected for
149  // testing.
150  std::unique_ptr<base::Clock> clock_;
151 
152  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
153 };
154 
158  public:
159  // The role for this AdaptationSet. These values are used to add a Role
160  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
161  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
162  enum Role {
163  kRoleCaption,
164  kRoleSubtitle,
165  kRoleMain,
166  kRoleAlternate,
167  kRoleSupplementary,
168  kRoleCommentary,
169  kRoleDub
170  };
171 
172  virtual ~AdaptationSet();
173 
180  virtual Representation* AddRepresentation(const MediaInfo& media_info);
181 
191  virtual void AddContentProtectionElement(
192  const ContentProtectionElement& element);
193 
205  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
206  const std::string& pssh);
207 
212  virtual void AddRole(Role role);
213 
218  xml::scoped_xml_ptr<xmlNode> GetXml();
219 
225  virtual void ForceSetSegmentAlignment(bool segment_alignment);
226 
229  void AddAdaptationSetSwitching(uint32_t adaptation_set_id);
230 
232  const std::vector<uint32_t>& adaptation_set_switching_ids() const {
233  return adaptation_set_switching_ids_;
234  }
235 
236  // Must be unique in the Period.
237  uint32_t id() const { return id_; }
238 
250  void OnNewSegmentForRepresentation(uint32_t representation_id,
251  uint64_t start_time,
252  uint64_t duration);
253 
266  void OnSetFrameRateForRepresentation(uint32_t representation_id,
267  uint32_t frame_duration,
268  uint32_t timescale);
269 
273  virtual void AddTrickPlayReferenceId(uint32_t id);
274 
275  protected:
283  AdaptationSet(uint32_t adaptation_set_id,
284  const std::string& lang,
285  const MpdOptions& mpd_options,
286  base::AtomicSequenceNumber* representation_counter);
287 
288  private:
289  friend class MpdBuilder;
290  template <DashProfile profile>
291  friend class MpdBuilderTest;
292 
293  // kSegmentAlignmentUnknown means that it is uncertain if the
294  // (sub)segments are aligned or not.
295  // kSegmentAlignmentTrue means that it is certain that the all the (current)
296  // segments added to the adaptation set are aligned.
297  // kSegmentAlignmentFalse means that it is it is certain that some segments
298  // are not aligned. This is useful to disable the computation for
299  // segment alignment, once it is certain that some segments are not aligned.
300  enum SegmentAligmentStatus {
301  kSegmentAlignmentUnknown,
302  kSegmentAlignmentTrue,
303  kSegmentAlignmentFalse
304  };
305 
306  // This maps Representations (IDs) to a list of start times of the segments.
307  // e.g.
308  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
309  // start times 0, 200, 400, then the map contains:
310  // 1 -> [0, 100, 200]
311  // 2 -> [0, 200, 400]
312  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
313 
314  // Gets the earliest, normalized segment timestamp. Returns true if
315  // successful, false otherwise.
316  bool GetEarliestTimestamp(double* timestamp_seconds);
317 
325  void CheckLiveSegmentAlignment(uint32_t representation_id,
326  uint64_t start_time,
327  uint64_t duration);
328 
329  // Checks representation_segment_start_times_ and sets segments_aligned_.
330  // Use this for VOD, do not use for Live.
331  void CheckVodSegmentAlignment();
332 
333  // Records the framerate of a Representation.
334  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
335 
336  std::list<ContentProtectionElement> content_protection_elements_;
337  std::list<std::unique_ptr<Representation>> representations_;
338 
339  base::AtomicSequenceNumber* const representation_counter_;
340 
341  const uint32_t id_;
342  const std::string lang_;
343  const MpdOptions& mpd_options_;
344 
345  // The ids of the adaptation sets this adaptation set can switch to.
346  std::vector<uint32_t> adaptation_set_switching_ids_;
347 
348  // Video widths and heights of Representations. Note that this is a set; if
349  // there is only 1 resolution, then @width & @height should be set, otherwise
350  // @maxWidth & @maxHeight should be set for DASH IOP.
351  std::set<uint32_t> video_widths_;
352  std::set<uint32_t> video_heights_;
353 
354  // Video representations' frame rates.
355  // The frame rate notation for MPD is <integer>/<integer> (where the
356  // denominator is optional). This means the frame rate could be non-whole
357  // rational value, therefore the key is of type double.
358  // Value is <integer>/<integer> in string form.
359  // So, key == CalculatedValue(value)
360  std::map<double, std::string> video_frame_rates_;
361 
362  // contentType attribute of AdaptationSet.
363  // Determined by examining the MediaInfo passed to AddRepresentation().
364  std::string content_type_;
365 
366  // This does not have to be a set, it could be a list or vector because all we
367  // really care is whether there is more than one entry.
368  // Contains one entry if all the Representations have the same picture aspect
369  // ratio (@par attribute for AdaptationSet).
370  // There will be more than one entry if there are multiple picture aspect
371  // ratios.
372  // The @par attribute should only be set if there is exactly one entry
373  // in this set.
374  std::set<std::string> picture_aspect_ratio_;
375 
376  // The roles of this AdaptationSet.
377  std::set<Role> roles_;
378 
379  // True iff all the segments are aligned.
380  SegmentAligmentStatus segments_aligned_;
381  bool force_set_segment_alignment_;
382 
383  // Keeps track of segment start times of Representations.
384  // For VOD, this will not be cleared, all the segment start times are
385  // stored in this. This should not out-of-memory for a reasonable length
386  // video and reasonable subsegment length.
387  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
388  // implementation comment) because storing the entire timeline is not
389  // reasonable and may cause an out-of-memory problem.
390  RepresentationTimeline representation_segment_start_times_;
391 
392  // Record the reference id for the original adaptation sets the trick play
393  // stream belongs to. This is a set because the trick play streams may be for
394  // multiple AdaptationSets (e.g. SD and HD videos in different AdaptationSets
395  // can share the same trick play stream.)
396  std::set<uint32_t> trick_play_reference_ids_;
397 
398  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
399 };
400 
402  public:
405 
410  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
411  uint64_t duration) = 0;
412 
417  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
418  uint32_t timescale) = 0;
419 };
420 
424  public:
425  enum SuppressFlag {
426  kSuppressWidth = 1,
427  kSuppressHeight = 2,
428  kSuppressFrameRate = 4,
429  };
430 
431  virtual ~Representation();
432 
436  bool Init();
437 
448  virtual void AddContentProtectionElement(
449  const ContentProtectionElement& element);
450 
462  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
463  const std::string& pssh);
464 
473  virtual void AddNewSegment(uint64_t start_time,
474  uint64_t duration,
475  uint64_t size);
476 
482  virtual void SetSampleDuration(uint32_t sample_duration);
483 
485  xml::scoped_xml_ptr<xmlNode> GetXml();
486 
495  void SuppressOnce(SuppressFlag flag);
496 
498  uint32_t id() const { return id_; }
499 
500  protected:
510  const MediaInfo& media_info,
511  const MpdOptions& mpd_options,
512  uint32_t representation_id,
513  std::unique_ptr<RepresentationStateChangeListener> state_change_listener);
514 
515  private:
516  friend class AdaptationSet;
517  template <DashProfile profile>
518  friend class MpdBuilderTest;
519 
520  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
521 
522  // Returns true if |media_info_| has required fields to generate a valid
523  // Representation. Otherwise returns false.
524  bool HasRequiredMediaInfoFields();
525 
526  // Return false if the segment should be considered a new segment. True if the
527  // segment is contiguous.
528  bool IsContiguous(uint64_t start_time,
529  uint64_t duration,
530  uint64_t size) const;
531 
532  // Remove elements from |segment_infos_| if
533  // mpd_options_.time_shift_buffer_depth is specified. Increments
534  // |start_number_| by the number of segments removed.
535  void SlideWindow();
536 
537  // Note: Because 'mimeType' is a required field for a valid MPD, these return
538  // strings.
539  std::string GetVideoMimeType() const;
540  std::string GetAudioMimeType() const;
541  std::string GetTextMimeType() const;
542 
543  // Gets the earliest, normalized segment timestamp. Returns true if
544  // successful, false otherwise.
545  bool GetEarliestTimestamp(double* timestamp_seconds);
546 
547  // Init() checks that only one of VideoInfo, AudioInfo, or TextInfo is set. So
548  // any logic using this can assume only one set.
549  MediaInfo media_info_;
550  std::list<ContentProtectionElement> content_protection_elements_;
551  std::list<SegmentInfo> segment_infos_;
552 
553  const uint32_t id_;
554  std::string mime_type_;
555  std::string codecs_;
556  BandwidthEstimator bandwidth_estimator_;
557  const MpdOptions& mpd_options_;
558 
559  // startNumber attribute for SegmentTemplate.
560  // Starts from 1.
561  uint32_t start_number_;
562 
563  // If this is not null, then Representation is responsible for calling the
564  // right methods at right timings.
565  std::unique_ptr<RepresentationStateChangeListener> state_change_listener_;
566 
567  // Bit vector for tracking witch attributes should not be output.
568  int output_suppression_flags_;
569 
570  DISALLOW_COPY_AND_ASSIGN(Representation);
571 };
572 
573 } // namespace shaka
574 
575 #endif // MPD_BASE_MPD_BUILDER_H_
void OnSetFrameRateForRepresentation(uint32_t representation_id, uint32_t frame_duration, uint32_t timescale)
Definition: mpd_builder.cc:891
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
bool WriteMpdToFile(media::File *output_file)
Definition: mpd_builder.cc:419
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:696
This class generates DASH MPDs (Media Presentation Descriptions).
Definition: mpd_builder.h:57
uint32_t id() const
Definition: mpd_builder.h:498
Define an abstract file interface.
Definition: file.h:24
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
Definition: mpd_builder.cc:742
virtual void AddTrickPlayReferenceId(uint32_t id)
Definition: mpd_builder.cc:898
MpdBuilder(const MpdOptions &mpd_options)
Definition: mpd_builder.cc:396
virtual void AddRole(Role role)
Definition: mpd_builder.cc:754
void AddBaseUrl(const std::string &base_url)
Definition: mpd_builder.cc:401
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Definition: mpd_builder.cc:748
AdaptationSet(uint32_t adaptation_set_id, const std::string &lang, const MpdOptions &mpd_options, base::AtomicSequenceNumber *representation_counter)
Definition: mpd_builder.cc:681
xml::scoped_xml_ptr< xmlNode > GetXml()
virtual bool ToString(std::string *output)
Definition: mpd_builder.cc:424
void AddAdaptationSetSwitching(uint32_t adaptation_set_id)
Definition: mpd_builder.cc:869
const std::vector< uint32_t > & adaptation_set_switching_ids() const
Definition: mpd_builder.h:232
virtual void ForceSetSegmentAlignment(bool segment_alignment)
Definition: mpd_builder.cc:863
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:653
xml::scoped_xml_ptr< xmlNode > GetXml()
Definition: mpd_builder.cc:764
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
virtual AdaptationSet * AddAdaptationSet(const std::string &lang)
Definition: mpd_builder.cc:405
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:880
void InjectClockForTesting(std::unique_ptr< base::Clock > clock)
This is for testing.
Definition: mpd_builder.h:95
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)