Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: services/media/factory_service/media_sink_impl.cc

Issue 1986303002: Motown: Use new TimelineTransform and related definitions (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Fixes per feedback. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "mojo/services/media/common/cpp/linear_transform.h" 6 #include "mojo/services/media/common/cpp/timeline.h"
7 #include "mojo/services/media/common/cpp/local_time.h" 7 #include "mojo/services/media/common/cpp/timeline_function.h"
8 #include "services/media/factory_service/media_sink_impl.h" 8 #include "services/media/factory_service/media_sink_impl.h"
9 #include "services/media/framework/util/conversion_pipeline_builder.h" 9 #include "services/media/framework/util/conversion_pipeline_builder.h"
10 #include "services/media/framework_mojo/mojo_type_conversions.h" 10 #include "services/media/framework_mojo/mojo_type_conversions.h"
11 11
12 namespace mojo { 12 namespace mojo {
13 namespace media { 13 namespace media {
14 14
15 // static 15 // static
16 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create( 16 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create(
17 const String& destination_url, 17 const String& destination_url,
18 MediaTypePtr media_type, 18 MediaTypePtr media_type,
19 InterfaceRequest<MediaSink> request, 19 InterfaceRequest<MediaSink> request,
20 MediaFactoryService* owner) { 20 MediaFactoryService* owner) {
21 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl( 21 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl(
22 destination_url, media_type.Pass(), request.Pass(), owner)); 22 destination_url, media_type.Pass(), request.Pass(), owner));
23 } 23 }
24 24
25 MediaSinkImpl::MediaSinkImpl(const String& destination_url, 25 MediaSinkImpl::MediaSinkImpl(const String& destination_url,
26 MediaTypePtr media_type, 26 MediaTypePtr media_type,
27 InterfaceRequest<MediaSink> request, 27 InterfaceRequest<MediaSink> request,
28 MediaFactoryService* owner) 28 MediaFactoryService* owner)
29 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner), 29 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner),
30 consumer_(MojoConsumer::Create()), 30 consumer_(MojoConsumer::Create()),
31 producer_(MojoProducer::Create()) { 31 producer_(MojoProducer::Create()) {
32 DCHECK(destination_url); 32 DCHECK(destination_url);
33 DCHECK(media_type); 33 DCHECK(media_type);
34 34
35 status_publisher_.SetCallbackRunner( 35 status_publisher_.SetCallbackRunner([this](const GetStatusCallback& callback,
36 [this](const GetStatusCallback& callback, uint64_t version) { 36 uint64_t version) {
37 MediaSinkStatusPtr status = MediaSinkStatus::New(); 37 MediaSinkStatusPtr status = MediaSinkStatus::New();
38 status->state = (producer_state_ == MediaState::PAUSED && rate_ != 0.0) 38 status->state = (producer_state_ == MediaState::PAUSED && rate_ != 0.0)
39 ? MediaState::PLAYING 39 ? MediaState::PLAYING
40 : producer_state_; 40 : producer_state_;
41 status->timeline_transform = status_transform_.Clone(); 41 status->timeline_transform = TimelineTransform::From(timeline_function_);
42 callback.Run(version, status.Pass()); 42 callback.Run(version, status.Pass());
43 }); 43 });
44 44
45 PartRef consumer_ref = graph_.Add(consumer_); 45 PartRef consumer_ref = graph_.Add(consumer_);
46 PartRef producer_ref = graph_.Add(producer_); 46 PartRef producer_ref = graph_.Add(producer_);
47 47
48 consumer_->SetPrimeRequestedCallback( 48 consumer_->SetPrimeRequestedCallback(
49 [this](const MediaConsumer::PrimeCallback& callback) { 49 [this](const MediaConsumer::PrimeCallback& callback) {
50 ready_.When([this, callback]() { 50 ready_.When([this, callback]() {
51 DCHECK(producer_); 51 DCHECK(producer_);
52 producer_->PrimeConnection(callback); 52 producer_->PrimeConnection(callback);
53 }); 53 });
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 if (!result) { 105 if (!result) {
106 // Failed to build conversion pipeline. 106 // Failed to build conversion pipeline.
107 producer_state_ = MediaState::FAULT; 107 producer_state_ = MediaState::FAULT;
108 status_publisher_.SendUpdates(); 108 status_publisher_.SendUpdates();
109 return; 109 return;
110 } 110 }
111 111
112 graph_.ConnectOutputToPart(out, producer_ref); 112 graph_.ConnectOutputToPart(out, producer_ref);
113 113
114 if (producer_stream_type->medium() == StreamType::Medium::kAudio) { 114 if (producer_stream_type->medium() == StreamType::Medium::kAudio) {
115 frames_per_second_ = producer_stream_type->audio()->frames_per_second(); 115 frames_per_ns_ =
116 TimelineRate(producer_stream_type->audio()->frames_per_second(),
117 Timeline::ns_from_seconds(1));
118
116 } else { 119 } else {
117 // Unsupported producer stream type. 120 // Unsupported producer stream type.
118 LOG(ERROR) << "unsupported producer stream type"; 121 LOG(ERROR) << "unsupported producer stream type";
119 abort(); 122 abort();
120 } 123 }
121 124
122 controller_->Configure( 125 controller_->Configure(
123 std::move(producer_stream_type), 126 std::move(producer_stream_type),
124 [this](MediaConsumerPtr consumer, RateControlPtr rate_control) { 127 [this](MediaConsumerPtr consumer,
128 MediaTimelineControlSitePtr timeline_control_site) {
125 DCHECK(consumer); 129 DCHECK(consumer);
126 DCHECK(rate_control); 130 DCHECK(timeline_control_site);
127 rate_control_ = rate_control.Pass(); 131 timeline_control_site->GetTimelineConsumer(
132 GetProxy(&timeline_consumer_));
128 producer_->Connect(consumer.Pass(), [this]() { 133 producer_->Connect(consumer.Pass(), [this]() {
129 graph_.Prepare(); 134 graph_.Prepare();
130 ready_.Occur(); 135 ready_.Occur();
131 MaybeSetRate(); 136 MaybeSetRate();
132 }); 137 });
133 }); 138 });
134 }); 139 });
135 } 140 }
136 141
137 MediaSinkImpl::~MediaSinkImpl() {} 142 MediaSinkImpl::~MediaSinkImpl() {}
(...skipping 15 matching lines...) Expand all
153 void MediaSinkImpl::Pause() { 158 void MediaSinkImpl::Pause() {
154 target_rate_ = 0.0; 159 target_rate_ = 0.0;
155 MaybeSetRate(); 160 MaybeSetRate();
156 } 161 }
157 162
158 void MediaSinkImpl::MaybeSetRate() { 163 void MediaSinkImpl::MaybeSetRate() {
159 if (producer_state_ < MediaState::PAUSED || rate_ == target_rate_) { 164 if (producer_state_ < MediaState::PAUSED || rate_ == target_rate_) {
160 return; 165 return;
161 } 166 }
162 167
163 if (!rate_control_) { 168 if (!timeline_consumer_) {
164 rate_ = target_rate_; 169 rate_ = target_rate_;
165 status_publisher_.SendUpdates(); 170 status_publisher_.SendUpdates();
166 return; 171 return;
167 } 172 }
168 173
169 // Desired rate in frames per second. 174 // TODO(dalesat): start_local_time and start_presentation_time should be
170 LinearTransform::Ratio rate_frames_per_second( 175 // supplied via the mojo interface. For now, start_local_time is hard-coded
171 static_cast<uint32_t>(frames_per_second_ * target_rate_), 1); 176 // to be 30ms in the future, and start_presentation_time is grabbed from the
177 // first primed packet or is calculated from start_local_time based on the
178 // previous timeline function.
172 179
173 // Local time rate in seconds_per_tick.
174 LinearTransform::Ratio local_seconds_per_tick(LocalDuration::period::num,
175 LocalDuration::period::den);
176
177 // Desired rate in frames per local tick.
178 LinearTransform::Ratio rate_frames_per_tick;
179 bool success = LinearTransform::Ratio::Compose(
180 local_seconds_per_tick, rate_frames_per_second, &rate_frames_per_tick);
181 DCHECK(success)
182 << "LinearTransform::Ratio::Compose reports loss of precision";
183
184 // TODO(dalesat): start_local_time should be supplied via the mojo interface.
185 // For now, it's hard-coded to be 30ms in the future.
186 // The local time when we want the rate to change. 180 // The local time when we want the rate to change.
187 int64_t start_local_time = 181 int64_t start_local_time = Timeline::local_now() + Timeline::ns_from_ms(30);
188 (LocalClock::now().time_since_epoch() + std::chrono::milliseconds(30))
189 .count();
190 182
191 // The media time corresponding to start_local_time. 183 // The media time corresponding to start_local_time.
192 int64_t start_media_time; 184 int64_t start_presentation_time;
193 if (flushed_ && producer_->GetFirstPtsSinceFlush() != Packet::kUnknownPts) { 185 if (flushed_ && producer_->GetFirstPtsSinceFlush() != Packet::kUnknownPts) {
194 // We're getting started initially or after a flush/prime, so the media 186 // We're getting started initially or after a flush/prime, so the media
195 // time corresponding to start_local_time should be the PTS of 187 // time corresponding to start_local_time should be the PTS of
196 // the first packet. 188 // the first packet converted to ns (rather than frame) units.
197 start_media_time = producer_->GetFirstPtsSinceFlush(); 189 start_presentation_time =
190 producer_->GetFirstPtsSinceFlush() / frames_per_ns_;
198 } else { 191 } else {
199 // We're resuming, so the media time corresponding to start_local_time can 192 // We're resuming, so the media time corresponding to start_local_time can
200 // be calculated using the existing transform. 193 // be calculated using the existing transform.
201 success = 194 start_presentation_time = timeline_function_(start_local_time);
202 transform_.DoForwardTransform(start_local_time, &start_media_time);
203 DCHECK(success)
204 << "LinearTransform::DoForwardTransform reports loss of precision";
205 } 195 }
206 196
207 flushed_ = false; 197 flushed_ = false;
208 198
209 // Update the transform. 199 // Update the transform.
210 transform_ = 200 timeline_function_ = TimelineFunction(
211 LinearTransform(start_local_time, rate_frames_per_tick, start_media_time); 201 start_local_time, start_presentation_time, TimelineRate(target_rate_));
212 202
213 // Set the rate. 203 // Set the rate.
214 TimelineQuadPtr rate_quad = TimelineQuad::New(); 204 timeline_consumer_->SetTimelineTransform(
215 rate_quad->reference_offset = start_media_time; 205 timeline_function_.subject_time(), timeline_function_.reference_delta(),
216 rate_quad->target_offset = start_local_time; 206 timeline_function_.subject_delta(), timeline_function_.reference_time(),
217 rate_quad->reference_delta = rate_frames_per_tick.numerator; 207 kUnspecifiedTime, [](bool completed) {});
218 rate_quad->target_delta = rate_frames_per_tick.denominator;
219
220 rate_control_->SetCurrentQuad(rate_quad.Pass());
221
222 // Get the frame rate in frames per local tick.
223 LinearTransform::Ratio frame_rate_frames_per_second(frames_per_second_, 1);
224 LinearTransform::Ratio frame_rate_frames_per_tick;
225 success = LinearTransform::Ratio::Compose(local_seconds_per_tick,
226 frame_rate_frames_per_second,
227 &frame_rate_frames_per_tick);
228 DCHECK(success)
229 << "LinearTransform::Ratio::Compose reports loss of precision";
230
231 // Create a LinearTransform to translate from presentation units to
232 // local duration units.
233 LinearTransform local_to_presentation(0, frame_rate_frames_per_tick, 0);
234
235 status_transform_ = TimelineTransform::New();
236 status_transform_->quad = TimelineQuad::New();
237
238 // Translate the current transform quad so the presentation time units
239 // are the same as the local time units.
240 success = local_to_presentation.DoReverseTransform(
241 start_media_time, &status_transform_->quad->reference_offset);
242 DCHECK(success)
243 << "LinearTransform::DoReverseTransform reports loss of precision";
244 status_transform_->quad->target_offset = start_local_time;
245 int64_t presentation_delta;
246 success = local_to_presentation.DoReverseTransform(
247 static_cast<int64_t>(rate_frames_per_tick.numerator),
248 &presentation_delta);
249 DCHECK(success)
250 << "LinearTransform::DoReverseTransform reports loss of precision";
251 status_transform_->quad->reference_delta =
252 static_cast<uint32_t>(presentation_delta);
253 status_transform_->quad->target_delta = rate_frames_per_tick.denominator;
254 LinearTransform::Ratio::Reduce(&status_transform_->quad->reference_delta,
255 &status_transform_->quad->target_delta);
256 208
257 rate_ = target_rate_; 209 rate_ = target_rate_;
258 status_publisher_.SendUpdates(); 210 status_publisher_.SendUpdates();
259 } 211 }
260 212
261 } // namespace media 213 } // namespace media
262 } // namespace mojo 214 } // namespace mojo
OLDNEW
« no previous file with comments | « services/media/factory_service/media_sink_impl.h ('k') | services/media/factory_service/media_source_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698