Shaka Packager SDK
simple_mpd_notifier.cc
1 // Copyright 2015 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 #include "packager/mpd/base/simple_mpd_notifier.h"
8 
9 #include "packager/base/logging.h"
10 #include "packager/base/stl_util.h"
11 #include "packager/mpd/base/adaptation_set.h"
12 #include "packager/mpd/base/mpd_builder.h"
13 #include "packager/mpd/base/mpd_notifier_util.h"
14 #include "packager/mpd/base/mpd_utils.h"
15 #include "packager/mpd/base/period.h"
16 #include "packager/mpd/base/representation.h"
17 
18 namespace shaka {
19 
20 SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options)
21  : MpdNotifier(mpd_options),
22  output_path_(mpd_options.mpd_params.mpd_output),
23  mpd_builder_(new MpdBuilder(mpd_options)),
24  content_protection_in_adaptation_set_(
25  mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd) {
26  for (const std::string& base_url : mpd_options.mpd_params.base_urls)
27  mpd_builder_->AddBaseUrl(base_url);
28 }
29 
30 SimpleMpdNotifier::~SimpleMpdNotifier() {}
31 
33  return true;
34 }
35 
36 bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
37  uint32_t* container_id) {
38  DCHECK(container_id);
39 
40  ContentType content_type = GetContentType(media_info);
41  if (content_type == kContentTypeUnknown)
42  return false;
43 
44  MediaInfo adjusted_media_info(media_info);
45  MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
46 
47  base::AutoLock auto_lock(lock_);
48  const double kPeriodStartTimeSeconds = 0.0;
49  Period* period = mpd_builder_->GetOrCreatePeriod(kPeriodStartTimeSeconds);
50  DCHECK(period);
51  AdaptationSet* adaptation_set = period->GetOrCreateAdaptationSet(
52  media_info, content_protection_in_adaptation_set_);
53  DCHECK(adaptation_set);
54  if (!adaptation_set->has_id())
55  adaptation_set->set_id(next_adaptation_set_id_++);
56  Representation* representation =
57  adaptation_set->AddRepresentation(adjusted_media_info);
58  if (!representation)
59  return false;
60 
61  *container_id = representation->id();
62  if (content_protection_in_adaptation_set_) {
63  // ContentProtection elements are already added to AdaptationSet above.
64  // Use RepresentationId to AdaptationSet map to update ContentProtection
65  // in AdaptationSet in NotifyEncryptionUpdate.
66  representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
67  } else {
68  AddContentProtectionElements(media_info, representation);
69  }
70  representation_map_[representation->id()] = representation;
71  return true;
72 }
73 
74 bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
75  uint32_t sample_duration) {
76  base::AutoLock auto_lock(lock_);
77  auto it = representation_map_.find(container_id);
78  if (it == representation_map_.end()) {
79  LOG(ERROR) << "Unexpected container_id: " << container_id;
80  return false;
81  }
82  it->second->SetSampleDuration(sample_duration);
83  return true;
84 }
85 
86 bool SimpleMpdNotifier::NotifyNewSegment(uint32_t container_id,
87  uint64_t start_time,
88  uint64_t duration,
89  uint64_t size) {
90  base::AutoLock auto_lock(lock_);
91  auto it = representation_map_.find(container_id);
92  if (it == representation_map_.end()) {
93  LOG(ERROR) << "Unexpected container_id: " << container_id;
94  return false;
95  }
96  it->second->AddNewSegment(start_time, duration, size);
97  return true;
98 }
99 
100 bool SimpleMpdNotifier::NotifyCueEvent(uint32_t container_id,
101  uint64_t timestamp) {
102  base::AutoLock auto_lock(lock_);
103  auto it = representation_map_.find(container_id);
104  if (it == representation_map_.end()) {
105  LOG(ERROR) << "Unexpected container_id: " << container_id;
106  return false;
107  }
108  Representation* original_representation = it->second;
109  AdaptationSet* original_adaptation_set =
110  representation_id_to_adaptation_set_[container_id];
111 
112  const MediaInfo& media_info = original_representation->GetMediaInfo();
113  const double period_start_time_seconds =
114  static_cast<double>(timestamp) / media_info.reference_time_scale();
115 
116  Period* period = mpd_builder_->GetOrCreatePeriod(period_start_time_seconds);
117  DCHECK(period);
118  AdaptationSet* adaptation_set = period->GetOrCreateAdaptationSet(
119  media_info, content_protection_in_adaptation_set_);
120  DCHECK(adaptation_set);
121  if (!adaptation_set->has_id()) {
122  adaptation_set->set_id(original_adaptation_set->id());
123  } else {
124  DCHECK_EQ(adaptation_set->id(), original_adaptation_set->id());
125  }
126 
127  Representation* representation =
128  adaptation_set->CopyRepresentation(*original_representation);
129  if (!representation)
130  return false;
131 
132  if (content_protection_in_adaptation_set_) {
133  // ContentProtection elements are already added to AdaptationSet above.
134  // Use RepresentationId to AdaptationSet map to update ContentProtection
135  // in AdaptationSet in NotifyEncryptionUpdate.
136  representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
137  } else {
138  AddContentProtectionElements(media_info, representation);
139  }
140  representation_map_[representation->id()] = representation;
141  return true;
142 }
143 
145  uint32_t container_id,
146  const std::string& drm_uuid,
147  const std::vector<uint8_t>& new_key_id,
148  const std::vector<uint8_t>& new_pssh) {
149  base::AutoLock auto_lock(lock_);
150  auto it = representation_map_.find(container_id);
151  if (it == representation_map_.end()) {
152  LOG(ERROR) << "Unexpected container_id: " << container_id;
153  return false;
154  }
155 
156  if (content_protection_in_adaptation_set_) {
157  AdaptationSet* adaptation_set_for_representation =
158  representation_id_to_adaptation_set_[it->second->id()];
159  adaptation_set_for_representation->UpdateContentProtectionPssh(
160  drm_uuid, Uint8VectorToBase64(new_pssh));
161  } else {
162  it->second->UpdateContentProtectionPssh(drm_uuid,
163  Uint8VectorToBase64(new_pssh));
164  }
165  return true;
166 }
167 
168 bool SimpleMpdNotifier::NotifyMediaInfoUpdate(uint32_t container_id,
169  const MediaInfo& media_info) {
170  base::AutoLock auto_lock(lock_);
171  auto it = representation_map_.find(container_id);
172  if (it == representation_map_.end()) {
173  LOG(ERROR) << "Unexpected container_id: " << container_id;
174  return false;
175  }
176 
177  MediaInfo adjusted_media_info(media_info);
178  MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
179 
180  it->second->set_media_info(adjusted_media_info);
181  return true;
182 }
183 
185  base::AutoLock auto_lock(lock_);
186  return WriteMpdToFile(output_path_, mpd_builder_.get());
187 }
188 
189 } // namespace shaka
virtual const MediaInfo & GetMediaInfo() const
virtual AdaptationSet * GetOrCreateAdaptationSet(const MediaInfo &media_info, bool content_protection_in_adaptation_set)
Definition: period.cc:56
virtual Representation * AddRepresentation(const MediaInfo &media_info)
uint32_t id() const
All the methods that are virtual are virtual for mocking.
virtual Representation * CopyRepresentation(const Representation &representation)
bool NotifyCueEvent(uint32_t container_id, uint64_t timestamp) override
void AddContentProtectionElements(const MediaInfo &media_info, Representation *parent)
Definition: mpd_utils.cc:424
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
std::string Uint8VectorToBase64(const std::vector< uint8_t > &input)
Converts uint8 vector into base64 encoded string.
bool NotifySampleDuration(uint32_t container_id, uint32_t sample_duration) override
bool NotifyEncryptionUpdate(uint32_t container_id, const std::string &drm_uuid, const std::vector< uint8_t > &new_key_id, const std::vector< uint8_t > &new_pssh) override
static void MakePathsRelativeToMpd(const std::string &mpd_path, MediaInfo *media_info)
Definition: mpd_builder.cc:420
bool NotifyMediaInfoUpdate(uint32_t container_id, const MediaInfo &media_info) override
ContentType GetContentType(const MediaInfo &media_info)
bool NotifyNewSegment(uint32_t container_id, uint64_t start_time, uint64_t duration, uint64_t size) override
bool WriteMpdToFile(const std::string &output_path, MpdBuilder *mpd_builder)
void set_id(uint32_t id)
bool NotifyNewContainer(const MediaInfo &media_info, uint32_t *id) override