Shaka Packager SDK
Loading...
Searching...
No Matches
simple_mpd_notifier.cc
1// Copyright 2015 Google LLC. 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 <cstdint>
10#include <string>
11#include <vector>
12
13#include <absl/log/check.h>
14#include <absl/log/log.h>
15#include <absl/synchronization/mutex.h>
16
17#include <packager/mpd/base/adaptation_set.h>
18#include <packager/mpd/base/mpd_builder.h>
19#include <packager/mpd/base/mpd_notifier.h>
20#include <packager/mpd/base/mpd_notifier_util.h>
21#include <packager/mpd/base/mpd_utils.h>
22#include <packager/mpd/base/period.h>
23#include <packager/mpd/base/representation.h>
24
25namespace shaka {
26
27SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options)
28 : MpdNotifier(mpd_options),
29 output_path_(mpd_options.mpd_params.mpd_output),
30 mpd_builder_(new MpdBuilder(mpd_options)),
31 content_protection_in_adaptation_set_(
32 mpd_options.mpd_params.generate_dash_if_iop_compliant_mpd) {
33 for (const std::string& base_url : mpd_options.mpd_params.base_urls)
34 mpd_builder_->AddBaseUrl(base_url);
35}
36
37SimpleMpdNotifier::~SimpleMpdNotifier() {}
38
39bool SimpleMpdNotifier::Init() {
40 return true;
41}
42
43bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
44 uint32_t* container_id) {
45 DCHECK(container_id);
46
47 ContentType content_type = GetContentType(media_info);
48 if (content_type == kContentTypeUnknown)
49 return false;
50
51 MediaInfo adjusted_media_info(media_info);
52 MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
53
54 absl::MutexLock auto_lock(lock_);
55 const double kPeriodStartTimeSeconds = 0.0;
56 Period* period = mpd_builder_->GetOrCreatePeriod(kPeriodStartTimeSeconds);
57 DCHECK(period);
58 AdaptationSet* adaptation_set = period->GetOrCreateAdaptationSet(
59 media_info, content_protection_in_adaptation_set_);
60 DCHECK(adaptation_set);
61 if (!adaptation_set->has_id())
62 adaptation_set->set_id(next_adaptation_set_id_++);
63 Representation* representation =
64 adaptation_set->AddRepresentation(adjusted_media_info);
65 if (!representation)
66 return false;
67
68 *container_id = representation->id();
69 if (content_protection_in_adaptation_set_) {
70 // ContentProtection elements are already added to AdaptationSet above.
71 // Use RepresentationId to AdaptationSet map to update ContentProtection
72 // in AdaptationSet in NotifyEncryptionUpdate.
73 representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
74 } else {
75 AddContentProtectionElements(media_info, representation);
76 }
77 representation_map_[representation->id()] = representation;
78 return true;
79}
80
81bool SimpleMpdNotifier::NotifyAvailabilityTimeOffset(uint32_t container_id) {
82 absl::MutexLock lock(lock_);
83 auto it = representation_map_.find(container_id);
84 if (it == representation_map_.end()) {
85 LOG(ERROR) << "Unexpected container_id: " << container_id;
86 return false;
87 }
88 it->second->SetAvailabilityTimeOffset();
89 return true;
90}
91
92bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
93 int32_t sample_duration) {
94 absl::MutexLock lock(lock_);
95 auto it = representation_map_.find(container_id);
96 if (it == representation_map_.end()) {
97 LOG(ERROR) << "Unexpected container_id: " << container_id;
98 return false;
99 }
100 it->second->SetSampleDuration(sample_duration);
101 return true;
102}
103
104bool SimpleMpdNotifier::NotifySegmentDuration(uint32_t container_id) {
105 absl::MutexLock lock(lock_);
106 auto it = representation_map_.find(container_id);
107 if (it == representation_map_.end()) {
108 LOG(ERROR) << "Unexpected container_id: " << container_id;
109 return false;
110 }
111 it->second->SetSegmentDuration();
112 return true;
113}
114
115bool SimpleMpdNotifier::NotifyNewSegment(uint32_t container_id,
116 int64_t start_time,
117 int64_t duration,
118 uint64_t size,
119 int64_t segment_number) {
120 absl::MutexLock lock(lock_);
121 auto it = representation_map_.find(container_id);
122 if (it == representation_map_.end()) {
123 LOG(ERROR) << "Unexpected container_id: " << container_id;
124 return false;
125 }
126 it->second->AddNewSegment(start_time, duration, size, segment_number);
127 return true;
128}
129
130bool SimpleMpdNotifier::NotifyCompletedSegment(uint32_t container_id,
131 int64_t duration,
132 uint64_t size) {
133 absl::MutexLock lock(lock_);
134 auto it = representation_map_.find(container_id);
135 if (it == representation_map_.end()) {
136 LOG(ERROR) << "Unexpected container_id: " << container_id;
137 return false;
138 }
139 it->second->UpdateCompletedSegment(duration, size);
140 return true;
141}
142
143bool SimpleMpdNotifier::NotifyCueEvent(uint32_t container_id,
144 int64_t timestamp) {
145 absl::MutexLock lock(lock_);
146 auto it = representation_map_.find(container_id);
147 if (it == representation_map_.end()) {
148 LOG(ERROR) << "Unexpected container_id: " << container_id;
149 return false;
150 }
151 Representation* original_representation = it->second;
152 AdaptationSet* original_adaptation_set =
153 representation_id_to_adaptation_set_[container_id];
154
155 const MediaInfo& media_info = original_representation->GetMediaInfo();
156 const double period_start_time_seconds =
157 static_cast<double>(timestamp) / media_info.reference_time_scale();
158
159 Period* period = mpd_builder_->GetOrCreatePeriod(period_start_time_seconds);
160 DCHECK(period);
161 AdaptationSet* adaptation_set = period->GetOrCreateAdaptationSet(
162 media_info, content_protection_in_adaptation_set_);
163 DCHECK(adaptation_set);
164 if (!adaptation_set->has_id()) {
165 adaptation_set->set_id(original_adaptation_set->id());
166 } else {
167 DCHECK_EQ(adaptation_set->id(), original_adaptation_set->id());
168 }
169
170 Representation* representation =
171 adaptation_set->CopyRepresentation(*original_representation);
172 if (!representation)
173 return false;
174
175 if (content_protection_in_adaptation_set_) {
176 // ContentProtection elements are already added to AdaptationSet above.
177 // Use RepresentationId to AdaptationSet map to update ContentProtection
178 // in AdaptationSet in NotifyEncryptionUpdate.
179 representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
180 } else {
181 AddContentProtectionElements(media_info, representation);
182 }
183 representation_map_[representation->id()] = representation;
184 return true;
185}
186
187bool SimpleMpdNotifier::NotifyEncryptionUpdate(
188 uint32_t container_id,
189 const std::string& drm_uuid,
190 const std::vector<uint8_t>& new_key_id,
191 const std::vector<uint8_t>& new_pssh) {
192 absl::MutexLock lock(lock_);
193 auto it = representation_map_.find(container_id);
194 if (it == representation_map_.end()) {
195 LOG(ERROR) << "Unexpected container_id: " << container_id;
196 return false;
197 }
198
199 if (content_protection_in_adaptation_set_) {
200 AdaptationSet* adaptation_set_for_representation =
201 representation_id_to_adaptation_set_[it->second->id()];
202 adaptation_set_for_representation->UpdateContentProtectionPssh(
203 drm_uuid, Uint8VectorToBase64(new_pssh));
204 } else {
205 it->second->UpdateContentProtectionPssh(drm_uuid,
206 Uint8VectorToBase64(new_pssh));
207 }
208 return true;
209}
210
211bool SimpleMpdNotifier::NotifyEndOfStream() {
212 absl::MutexLock lock(lock_);
213 mpd_builder_->FinalizeDynamicMpd();
214 return true;
215}
216
217bool SimpleMpdNotifier::NotifyMediaInfoUpdate(uint32_t container_id,
218 const MediaInfo& media_info) {
219 absl::MutexLock lock(lock_);
220 auto it = representation_map_.find(container_id);
221 if (it == representation_map_.end()) {
222 LOG(ERROR) << "Unexpected container_id: " << container_id;
223 return false;
224 }
225
226 MediaInfo adjusted_media_info(media_info);
227 MpdBuilder::MakePathsRelativeToMpd(output_path_, &adjusted_media_info);
228
229 it->second->set_media_info(adjusted_media_info);
230 return true;
231}
232
233bool SimpleMpdNotifier::Flush() {
234 absl::MutexLock lock(lock_);
235 return WriteMpdToFile(output_path_, mpd_builder_.get());
236}
237
238} // namespace shaka
virtual Representation * AddRepresentation(const MediaInfo &media_info)
virtual Representation * CopyRepresentation(const Representation &representation)
virtual void UpdateContentProtectionPssh(const std::string &drm_uuid, const std::string &pssh)
void set_id(uint32_t id)
virtual AdaptationSet * GetOrCreateAdaptationSet(const MediaInfo &media_info, bool content_protection_in_adaptation_set)
Definition period.cc:84
virtual const MediaInfo & GetMediaInfo() const
uint32_t id() const
All the methods that are virtual are virtual for mocking.
std::string Uint8VectorToBase64(const std::vector< uint8_t > &input)
Converts uint8 vector into base64 encoded string.
ContentType GetContentType(const MediaInfo &media_info)
bool WriteMpdToFile(const std::string &output_path, MpdBuilder *mpd_builder)
void AddContentProtectionElements(const MediaInfo &media_info, Representation *parent)
Definition mpd_utils.cc:534