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/base/synchronization/lock.h"
29 #include "packager/mpd/base/bandwidth_estimator.h"
30 #include "packager/mpd/base/content_protection_element.h"
31 #include "packager/mpd/base/media_info.pb.h"
32 #include "packager/mpd/base/mpd_options.h"
33 #include "packager/mpd/base/segment_info.h"
34 #include "packager/mpd/base/xml/scoped_xml_ptr.h"
35 
36 // TODO(rkuroiwa): For classes with |id_|, consider removing the field and let
37 // the MPD (XML) generation functions take care of assigning an ID to each
38 // element.
39 namespace edash_packager {
40 
41 namespace media {
42 class File;
43 } // namespace media
44 
45 class AdaptationSet;
46 class Representation;
47 
48 namespace xml {
49 
50 class XmlNode;
51 class RepresentationXmlNode;
52 
53 } // namespace xml
54 
56 class MpdBuilder {
57  public:
58  enum MpdType {
59  kStatic = 0,
60  kDynamic
61  };
62 
66  MpdBuilder(MpdType type, const MpdOptions& mpd_options);
67  virtual ~MpdBuilder();
68 
71  void AddBaseUrl(const std::string& base_url);
72 
77  virtual AdaptationSet* AddAdaptationSet(const std::string& lang);
78 
83  bool WriteMpdToFile(media::File* output_file);
84 
88  virtual bool ToString(std::string* output);
89 
91  MpdType type() const { return type_; }
92 
98  static void MakePathsRelativeToMpd(const std::string& mpd_path,
99  MediaInfo* media_info);
100 
101  private:
102  // DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
103  // doesn't need to depend on current time.
104  friend class DynamicMpdBuilderTest;
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  MpdType type_;
140  MpdOptions mpd_options_;
141  std::list<AdaptationSet*> adaptation_sets_;
142  ::STLElementDeleter<std::list<AdaptationSet*> > adaptation_sets_deleter_;
143 
144  std::list<std::string> base_urls_;
145  std::string availability_start_time_;
146 
147  base::Lock lock_;
148  base::AtomicSequenceNumber adaptation_set_counter_;
149  base::AtomicSequenceNumber representation_counter_;
150 
151  DISALLOW_COPY_AND_ASSIGN(MpdBuilder);
152 };
153 
157  public:
158  // The role for this AdaptationSet. These values are used to add a Role
159  // element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
160  // See ISO/IEC 23009-1:2012 section 5.8.5.5.
161  enum Role {
162  kRoleCaption,
163  kRoleSubtitle,
164  kRoleMain,
165  kRoleAlternate,
166  kRoleSupplementary,
167  kRoleCommentary,
168  kRoleDub
169  };
170 
171  virtual ~AdaptationSet();
172 
178  virtual Representation* AddRepresentation(const MediaInfo& media_info);
179 
189  virtual void AddContentProtectionElement(
190  const ContentProtectionElement& element);
191 
203  virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
204  const std::string& pssh);
205 
210  virtual void AddRole(Role role);
211 
216  xml::ScopedXmlPtr<xmlNode>::type GetXml();
217 
223  void ForceSetSegmentAlignment(bool segment_alignment);
224 
230  virtual void SetGroup(int group_number);
231 
233  virtual int Group() const;
234 
235  // Must be unique in the Period.
236  uint32_t id() const { return id_; }
237 
249  void OnNewSegmentForRepresentation(uint32_t representation_id,
250  uint64_t start_time,
251  uint64_t duration);
252 
265  void OnSetFrameRateForRepresentation(uint32_t representation_id,
266  uint32_t frame_duration,
267  uint32_t timescale);
268 
269  protected:
277  AdaptationSet(uint32_t adaptation_set_id,
278  const std::string& lang,
279  const MpdOptions& mpd_options,
280  MpdBuilder::MpdType mpd_type,
281  base::AtomicSequenceNumber* representation_counter);
282 
283  private:
284  // kSegmentAlignmentUnknown means that it is uncertain if the
285  // (sub)segments are aligned or not.
286  // kSegmentAlignmentTrue means that it is certain that the all the (current)
287  // segments added to the adaptation set are aligned.
288  // kSegmentAlignmentFalse means that it is it is certain that some segments
289  // are not aligned. This is useful to disable the computation for
290  // segment alignment, once it is certain that some segments are not aligned.
291  enum SegmentAligmentStatus {
292  kSegmentAlignmentUnknown,
293  kSegmentAlignmentTrue,
294  kSegmentAlignmentFalse
295  };
296 
297  // This maps Representations (IDs) to a list of start times of the segments.
298  // e.g.
299  // If Representation 1 has start time 0, 100, 200 and Representation 2 has
300  // start times 0, 200, 400, then the map contains:
301  // 1 -> [0, 100, 200]
302  // 2 -> [0, 200, 400]
303  typedef std::map<uint32_t, std::list<uint64_t> > RepresentationTimeline;
304 
305  friend class MpdBuilder;
306 
307  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, CheckAdaptationSetId);
308  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest,
309  CheckAdaptationSetVideoContentType);
310  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest,
311  CheckAdaptationSetAudioContentType);
312  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest,
313  CheckAdaptationSetTextContentType);
314  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, SetAdaptationSetGroup);
315  FRIEND_TEST_ALL_PREFIXES(StaticMpdBuilderTest, SubSegmentAlignment);
316  FRIEND_TEST_ALL_PREFIXES(StaticMpdBuilderTest, ForceSetSubSegmentAlignment);
317  FRIEND_TEST_ALL_PREFIXES(DynamicMpdBuilderTest, SegmentAlignment);
318  FRIEND_TEST_ALL_PREFIXES(
319  CommonMpdBuilderTest,
320  SetAdaptationFrameRateUsingRepresentationSetSampleDuration);
321 
322  // Gets the earliest, normalized segment timestamp. Returns true if
323  // successful, false otherwise.
324  bool GetEarliestTimestamp(double* timestamp_seconds);
325 
333  void CheckLiveSegmentAlignment(uint32_t representation_id,
334  uint64_t start_time,
335  uint64_t duration);
336 
337  // Checks representation_segment_start_times_ and sets segments_aligned_.
338  // Use this for VOD, do not use for Live.
339  void CheckVodSegmentAlignment();
340 
341  // Records the framerate of a Representation.
342  void RecordFrameRate(uint32_t frame_duration, uint32_t timescale);
343 
344  std::list<ContentProtectionElement> content_protection_elements_;
345  std::list<Representation*> representations_;
346  ::STLElementDeleter<std::list<Representation*> > representations_deleter_;
347 
348  base::Lock lock_;
349 
350  base::AtomicSequenceNumber* const representation_counter_;
351 
352  const uint32_t id_;
353  const std::string lang_;
354  const MpdOptions& mpd_options_;
355  const MpdBuilder::MpdType mpd_type_;
356 
357  // The group attribute for the AdaptationSet. If the value is negative,
358  // no group number is specified.
359  // Note that group 0 is a special group number.
360  int group_;
361 
362  // Video widths and heights of Representations. Note that this is a set; if
363  // there is only 1 resolution, then @width & @height should be set, otherwise
364  // @maxWidth & @maxHeight should be set for DASH IOP.
365  std::set<uint32_t> video_widths_;
366  std::set<uint32_t> video_heights_;
367 
368  // Video representations' frame rates.
369  // The frame rate notation for MPD is <integer>/<integer> (where the
370  // denominator is optional). This means the frame rate could be non-whole
371  // rational value, therefore the key is of type double.
372  // Value is <integer>/<integer> in string form.
373  // So, key == CalculatedValue(value)
374  std::map<double, std::string> video_frame_rates_;
375 
376  // contentType attribute of AdaptationSet.
377  // Determined by examining the MediaInfo passed to AddRepresentation().
378  std::string content_type_;
379 
380  // This does not have to be a set, it could be a list or vector because all we
381  // really care is whether there is more than one entry.
382  // Contains one entry if all the Representations have the same picture aspect
383  // ratio (@par attribute for AdaptationSet).
384  // There will be more than one entry if there are multiple picture aspect
385  // ratios.
386  // The @par attribute should only be set if there is exactly one entry
387  // in this set.
388  std::set<std::string> picture_aspect_ratio_;
389 
390  // The roles of this AdaptationSet.
391  std::set<Role> roles_;
392 
393  // True iff all the segments are aligned.
394  SegmentAligmentStatus segments_aligned_;
395  bool force_set_segment_alignment_;
396 
397  // Keeps track of segment start times of Representations.
398  // For VOD, this will not be cleared, all the segment start times are
399  // stored in this. This should not out-of-memory for a reasonable length
400  // video and reasonable subsegment length.
401  // For Live, the entries are deleted (see CheckLiveSegmentAlignment()
402  // implementation comment) because storing the entire timeline is not
403  // reasonable and may cause an out-of-memory problem.
404  RepresentationTimeline representation_segment_start_times_;
405 
406  DISALLOW_COPY_AND_ASSIGN(AdaptationSet);
407 };
408 
410  public:
413 
418  virtual void OnNewSegmentForRepresentation(uint64_t start_time,
419  uint64_t duration) = 0;
420 
425  virtual void OnSetFrameRateForRepresentation(uint32_t frame_duration,
426  uint32_t timescale) = 0;
427 };
428 
432  public:
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::ScopedXmlPtr<xmlNode>::type GetXml();
488 
490  uint32_t id() const { return id_; }
491 
492  protected:
502  const MediaInfo& media_info,
503  const MpdOptions& mpd_options,
504  uint32_t representation_id,
505  scoped_ptr<RepresentationStateChangeListener> state_change_listener);
506 
507  private:
508  friend class AdaptationSet;
509 
510  // TODO(rkuroiwa): Consider defining a public factory method that constructs
511  // and Init()s, at least for testing.
512  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, ValidMediaInfo);
513  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, InvalidMediaInfo);
514  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, CheckVideoInfoReflectedInXml);
515  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, CheckRepresentationId);
516  FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, SetSampleDuration);
517  FRIEND_TEST_ALL_PREFIXES(
518  CommonMpdBuilderTest,
519  RepresentationStateChangeListenerOnNewSegmentForRepresentation);
520  FRIEND_TEST_ALL_PREFIXES(
521  CommonMpdBuilderTest,
522  RepresentationStateChangeListenerOnSetFrameRateForRepresentation);
523 
524  bool AddLiveInfo(xml::RepresentationXmlNode* representation);
525 
526  // Returns true if |media_info_| has required fields to generate a valid
527  // Representation. Otherwise returns false.
528  bool HasRequiredMediaInfoFields();
529 
530  // Return false if the segment should be considered a new segment. True if the
531  // segment is contiguous.
532  bool IsContiguous(uint64_t start_time,
533  uint64_t duration,
534  uint64_t size) const;
535 
536  // Remove elements from |segment_infos_| if
537  // mpd_options_.time_shift_buffer_depth is specified. Increments
538  // |start_number_| by the number of segments removed.
539  void SlideWindow();
540 
541  // Note: Because 'mimeType' is a required field for a valid MPD, these return
542  // strings.
543  std::string GetVideoMimeType() const;
544  std::string GetAudioMimeType() const;
545 
546  // Gets the earliest, normalized segment timestamp. Returns true if
547  // successful, false otherwise.
548  bool GetEarliestTimestamp(double* timestamp_seconds);
549 
550  MediaInfo media_info_;
551  std::list<ContentProtectionElement> content_protection_elements_;
552  std::list<SegmentInfo> segment_infos_;
553 
554  base::Lock lock_;
555 
556  const uint32_t id_;
557  std::string mime_type_;
558  std::string codecs_;
559  BandwidthEstimator bandwidth_estimator_;
560  const MpdOptions& mpd_options_;
561 
562  // startNumber attribute for SegmentTemplate.
563  // Starts from 1.
564  uint32_t start_number_;
565 
566  // If this is not null, then Representation is responsible for calling the
567  // right methods at right timings.
568  scoped_ptr<RepresentationStateChangeListener> state_change_listener_;
569 
570  DISALLOW_COPY_AND_ASSIGN(Representation);
571 };
572 
573 } // namespace edash_packager
574 
575 #endif // MPD_BASE_MPD_BUILDER_H_
MpdType type() const
Definition: mpd_builder.h:91
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:636
Defines Mpd Options.
Definition: mpd_options.h:13
virtual int Group() const
Definition: mpd_builder.cc:793
virtual AdaptationSet * AddAdaptationSet(const std::string &lang)
Definition: mpd_builder.cc:392
Define an abstract file interface.
Definition: file.h:22
xml::ScopedXmlPtr< xmlNode >::type GetXml()
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:608
This class generates DASH MPDs (Media Presentation Descriptions).
Definition: mpd_builder.h:56
void ForceSetSegmentAlignment(bool segment_alignment)
Definition: mpd_builder.cc:783
virtual void SetSampleDuration(uint32_t sample_duration)
void AddBaseUrl(const std::string &base_url)
Definition: mpd_builder.cc:387
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:986
virtual void SetGroup(int group_number)
Definition: mpd_builder.cc:789
virtual void OnNewSegmentForRepresentation(uint64_t start_time, uint64_t duration)=0
xml::ScopedXmlPtr< xmlNode >::type GetXml()
Definition: mpd_builder.cc:713
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:404
void OnSetFrameRateForRepresentation(uint32_t representation_id, uint32_t frame_duration, uint32_t timescale)
Definition: mpd_builder.cc:817
virtual Representation * AddRepresentation(const MediaInfo &media_info)
Definition: mpd_builder.cc:655
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
Definition: mpd_builder.cc:700
virtual bool ToString(std::string *output)
Definition: mpd_builder.cc:410
virtual void AddRole(Role role)
Definition: mpd_builder.cc:707
MpdBuilder(MpdType type, const MpdOptions &mpd_options)
Definition: mpd_builder.cc:380
virtual void AddContentProtectionElement(const ContentProtectionElement &element)
Definition: mpd_builder.cc:693
void OnNewSegmentForRepresentation(uint32_t representation_id, uint64_t start_time, uint64_t duration)
Definition: mpd_builder.cc:804