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

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

Issue 2006093004: Motown: Convert MediaSink to expose MediaTimelineControlSite (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 6 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/timeline.h"
7 #include "mojo/services/media/common/cpp/timeline_function.h"
8 #include "services/media/factory_service/media_sink_impl.h" 6 #include "services/media/factory_service/media_sink_impl.h"
9 #include "services/media/framework/util/conversion_pipeline_builder.h" 7 #include "services/media/framework/util/conversion_pipeline_builder.h"
10 #include "services/media/framework_mojo/mojo_type_conversions.h" 8 #include "services/media/framework_mojo/mojo_type_conversions.h"
11 9
12 namespace mojo { 10 namespace mojo {
13 namespace media { 11 namespace media {
14 12
15 // static 13 // static
16 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create( 14 std::shared_ptr<MediaSinkImpl> MediaSinkImpl::Create(
17 const String& destination_url, 15 const String& destination_url,
18 MediaTypePtr media_type, 16 MediaTypePtr media_type,
19 InterfaceRequest<MediaSink> request, 17 InterfaceRequest<MediaSink> request,
20 MediaFactoryService* owner) { 18 MediaFactoryService* owner) {
21 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl( 19 return std::shared_ptr<MediaSinkImpl>(new MediaSinkImpl(
22 destination_url, media_type.Pass(), request.Pass(), owner)); 20 destination_url, media_type.Pass(), request.Pass(), owner));
23 } 21 }
24 22
25 MediaSinkImpl::MediaSinkImpl(const String& destination_url, 23 MediaSinkImpl::MediaSinkImpl(const String& destination_url,
26 MediaTypePtr media_type, 24 MediaTypePtr media_type,
27 InterfaceRequest<MediaSink> request, 25 InterfaceRequest<MediaSink> request,
28 MediaFactoryService* owner) 26 MediaFactoryService* owner)
29 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner), 27 : MediaFactoryService::Product<MediaSink>(this, request.Pass(), owner),
30 consumer_(MojoConsumer::Create()), 28 consumer_(MojoConsumer::Create()),
31 producer_(MojoProducer::Create()) { 29 producer_(MojoProducer::Create()) {
32 DCHECK(destination_url); 30 DCHECK(destination_url);
33 DCHECK(media_type); 31 DCHECK(media_type);
34 32
35 status_publisher_.SetCallbackRunner([this](const GetStatusCallback& callback,
36 uint64_t version) {
37 MediaSinkStatusPtr status = MediaSinkStatus::New();
38 status->state = (producer_state_ == MediaState::PAUSED && rate_ != 0.0)
39 ? MediaState::PLAYING
40 : producer_state_;
41 status->timeline_transform = TimelineTransform::From(timeline_function_);
42 callback.Run(version, status.Pass());
43 });
44
45 PartRef consumer_ref = graph_.Add(consumer_); 33 PartRef consumer_ref = graph_.Add(consumer_);
46 PartRef producer_ref = graph_.Add(producer_); 34 PartRef producer_ref = graph_.Add(producer_);
47 35
48 consumer_->SetPrimeRequestedCallback( 36 consumer_->SetPrimeRequestedCallback(
49 [this](const MediaConsumer::PrimeCallback& callback) { 37 [this](const MediaConsumer::PrimeCallback& callback) {
50 ready_.When([this, callback]() { 38 ready_.When([this, callback]() {
51 DCHECK(producer_); 39 DCHECK(producer_);
52 producer_->PrimeConnection(callback); 40 producer_->PrimeConnection(callback);
53 }); 41 });
54 }); 42 });
55 consumer_->SetFlushRequestedCallback( 43 consumer_->SetFlushRequestedCallback(
56 [this, consumer_ref](const MediaConsumer::FlushCallback& callback) { 44 [this, consumer_ref](const MediaConsumer::FlushCallback& callback) {
57 ready_.When([this, consumer_ref, callback]() { 45 ready_.When([this, consumer_ref, callback]() {
58 DCHECK(producer_); 46 DCHECK(producer_);
59 graph_.FlushOutput(consumer_ref.output()); 47 graph_.FlushOutput(consumer_ref.output());
60 producer_->FlushConnection(callback); 48 producer_->FlushConnection(callback);
61 flushed_ = true;
62 }); 49 });
63 }); 50 });
64 51
65 producer_->SetStatusCallback([this](MediaState state) {
66 producer_state_ = state;
67 status_publisher_.SendUpdates();
68 if (state == MediaState::ENDED) {
69 Pause();
70 }
71 });
72
73 // TODO(dalesat): Temporary, remove. 52 // TODO(dalesat): Temporary, remove.
74 if (destination_url == "nowhere") { 53 if (destination_url == "nowhere") {
75 // Throwing away the content. 54 // Throwing away the content.
76 graph_.ConnectParts(consumer_ref, producer_ref); 55 graph_.ConnectParts(consumer_ref, producer_ref);
77 graph_.Prepare(); 56 graph_.Prepare();
78 ready_.Occur(); 57 ready_.Occur();
79 return; 58 return;
80 } 59 }
81 60
82 RCHECK(destination_url == "mojo:audio_server"); 61 RCHECK(destination_url == "mojo:audio_server");
(...skipping 14 matching lines...) Expand all
97 std::unique_ptr<StreamType> producer_stream_type; 76 std::unique_ptr<StreamType> producer_stream_type;
98 77
99 // Add transforms to the pipeline to convert from stream_type to a 78 // Add transforms to the pipeline to convert from stream_type to a
100 // type supported by the track. 79 // type supported by the track.
101 OutputRef out = consumer_ref.output(); 80 OutputRef out = consumer_ref.output();
102 bool result = 81 bool result =
103 BuildConversionPipeline(*captured_stream_type, *supported_stream_types, 82 BuildConversionPipeline(*captured_stream_type, *supported_stream_types,
104 &graph_, &out, &producer_stream_type); 83 &graph_, &out, &producer_stream_type);
105 if (!result) { 84 if (!result) {
106 // Failed to build conversion pipeline. 85 // Failed to build conversion pipeline.
107 producer_state_ = MediaState::FAULT; 86 LOG(WARNING) << "failed to build conversion pipeline";
108 status_publisher_.SendUpdates(); 87 // TODO(dalesat): Add problem reporting.
109 return; 88 return;
110 } 89 }
111 90
112 graph_.ConnectOutputToPart(out, producer_ref); 91 graph_.ConnectOutputToPart(out, producer_ref);
113 92
114 if (producer_stream_type->medium() == StreamType::Medium::kAudio) { 93 controller_->Configure(std::move(producer_stream_type),
115 frames_per_ns_ = 94 [this](MediaConsumerPtr consumer) {
116 TimelineRate(producer_stream_type->audio()->frames_per_second(), 95 DCHECK(consumer);
117 Timeline::ns_from_seconds(1)); 96 producer_->Connect(consumer.Pass(), [this]() {
118 97 graph_.Prepare();
119 } else { 98 ready_.Occur();
120 // Unsupported producer stream type. 99 });
121 LOG(ERROR) << "unsupported producer stream type"; 100 });
122 abort();
123 }
124
125 controller_->Configure(
126 std::move(producer_stream_type),
127 [this](MediaConsumerPtr consumer,
128 MediaTimelineControlSitePtr timeline_control_site) {
129 DCHECK(consumer);
130 DCHECK(timeline_control_site);
131 timeline_control_site->GetTimelineConsumer(
132 GetProxy(&timeline_consumer_));
133 producer_->Connect(consumer.Pass(), [this]() {
134 graph_.Prepare();
135 ready_.Occur();
136 MaybeSetRate();
137 });
138 });
139 }); 101 });
140 } 102 }
141 103
142 MediaSinkImpl::~MediaSinkImpl() {} 104 MediaSinkImpl::~MediaSinkImpl() {}
143 105
144 void MediaSinkImpl::GetConsumer(InterfaceRequest<MediaConsumer> consumer) { 106 void MediaSinkImpl::GetConsumer(InterfaceRequest<MediaConsumer> consumer) {
145 consumer_->AddBinding(consumer.Pass()); 107 consumer_->AddBinding(consumer.Pass());
146 } 108 }
147 109
148 void MediaSinkImpl::GetStatus(uint64_t version_last_seen, 110 void MediaSinkImpl::GetTimelineControlSite(
149 const GetStatusCallback& callback) { 111 InterfaceRequest<MediaTimelineControlSite> req) {
150 status_publisher_.Get(version_last_seen, callback); 112 if (!controller_) {
151 } 113 LOG(ERROR) << "GetTimelineControlSite not implemented for 'nowhere' case";
152 114 abort();
153 void MediaSinkImpl::Play() {
154 target_rate_ = 1.0;
155 MaybeSetRate();
156 }
157
158 void MediaSinkImpl::Pause() {
159 target_rate_ = 0.0;
160 MaybeSetRate();
161 }
162
163 void MediaSinkImpl::MaybeSetRate() {
164 if (producer_state_ < MediaState::PAUSED || rate_ == target_rate_) {
165 return;
166 } 115 }
167 116 controller_->GetTimelineControlSite(req.Pass());
168 if (!timeline_consumer_) {
169 rate_ = target_rate_;
170 status_publisher_.SendUpdates();
171 return;
172 }
173
174 // TODO(dalesat): start_local_time and start_presentation_time should be
175 // supplied via the mojo interface. For now, start_local_time is hard-coded
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.
179
180 // The local time when we want the rate to change.
181 int64_t start_local_time = Timeline::local_now() + Timeline::ns_from_ms(30);
182
183 // The media time corresponding to start_local_time.
184 int64_t start_presentation_time;
185 if (flushed_ && producer_->GetFirstPtsSinceFlush() != Packet::kUnknownPts) {
186 // We're getting started initially or after a flush/prime, so the media
187 // time corresponding to start_local_time should be the PTS of
188 // the first packet converted to ns (rather than frame) units.
189 start_presentation_time =
190 producer_->GetFirstPtsSinceFlush() / frames_per_ns_;
191 } else {
192 // We're resuming, so the media time corresponding to start_local_time can
193 // be calculated using the existing transform.
194 start_presentation_time = timeline_function_(start_local_time);
195 }
196
197 flushed_ = false;
198
199 // Update the transform.
200 timeline_function_ = TimelineFunction(
201 start_local_time, start_presentation_time, TimelineRate(target_rate_));
202
203 // Set the rate.
204 timeline_consumer_->SetTimelineTransform(
205 timeline_function_.subject_time(), timeline_function_.reference_delta(),
206 timeline_function_.subject_delta(), timeline_function_.reference_time(),
207 kUnspecifiedTime, [](bool completed) {});
208
209 rate_ = target_rate_;
210 status_publisher_.SendUpdates();
211 } 117 }
212 118
213 } // namespace media 119 } // namespace media
214 } // namespace mojo 120 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698