Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "services/media/framework/engine.h" | |
| 6 | |
| 7 namespace mojo { | |
| 8 namespace media { | |
| 9 | |
| 10 uint32_t Engine::Part::input_count() { | |
|
johngro
2016/01/20 00:25:32
Would it be a good idea to inline most of these ac
dalesat
2016/01/25 23:29:37
These are only used for graph building, so they ar
johngro
2016/01/27 22:35:22
Acknowledged.
| |
| 11 DCHECK(stage_ != nullptr); | |
| 12 return stage_->input_count(); | |
| 13 } | |
| 14 | |
| 15 Engine::Input Engine::Part::input(uint32_t index) { | |
| 16 DCHECK(stage_ != nullptr && index < stage_->input_count()); | |
|
johngro
2016/01/20 00:25:32
FWIW, the 2 parameter form of the Input constructo
dalesat
2016/01/28 18:49:15
Acknowledged.
| |
| 17 return Input(stage_, index); | |
| 18 } | |
| 19 | |
| 20 Engine::Input Engine::Part::input() { | |
| 21 DCHECK(stage_ != nullptr && stage_->input_count() == 1); | |
| 22 return Input(stage_, 0); | |
| 23 } | |
| 24 | |
| 25 uint32_t Engine::Part::output_count() { | |
| 26 DCHECK(stage_ != nullptr); | |
| 27 return stage_->output_count(); | |
| 28 } | |
| 29 | |
| 30 Engine::Output Engine::Part::output(uint32_t index) { | |
| 31 DCHECK(stage_ != nullptr && index < stage_->output_count()); | |
| 32 return Output(stage_, index); | |
| 33 } | |
| 34 | |
| 35 Engine::Output Engine::Part::output() { | |
| 36 DCHECK(stage_ != nullptr && stage_->output_count() == 1); | |
| 37 return Output(stage_, 0); | |
| 38 } | |
| 39 | |
| 40 Engine::Part Engine::Part::upstream_part(uint32_t index) { | |
| 41 DCHECK(stage_ != nullptr && index < stage_->input_count()); | |
| 42 return Part(stage_->input(index).upstream_stage()); | |
| 43 } | |
| 44 | |
| 45 Engine::Part Engine::Part::upstream_part() { | |
| 46 DCHECK(stage_ != nullptr && stage_->input_count() == 1); | |
| 47 return Part(stage_->input(0).upstream_stage()); | |
| 48 } | |
| 49 | |
| 50 Engine::Part Engine::Part::downstream_part(uint32_t index) { | |
| 51 DCHECK(stage_ != nullptr && index < stage_->output_count()); | |
| 52 return Part(stage_->output(index).downstream_stage()); | |
| 53 } | |
| 54 | |
| 55 Engine::Part Engine::Part::downstream_part() { | |
| 56 DCHECK(stage_ != nullptr && stage_->output_count() == 1); | |
| 57 return Part(stage_->output(0).downstream_stage()); | |
| 58 } | |
| 59 | |
| 60 Engine::Engine() { | |
| 61 update_function_ = [this](Stage* stage) { | |
| 62 // TODO(dalesat): Correct thread and synchronization. | |
| 63 DCHECK(stage); | |
| 64 Update(stage); | |
| 65 Update(); | |
| 66 }; | |
| 67 } | |
| 68 | |
| 69 Engine::~Engine() {} | |
| 70 | |
| 71 void Engine::Remove(Part part) { | |
| 72 DCHECK(part); | |
| 73 | |
| 74 Stage* stage = part.stage_; | |
| 75 | |
| 76 uint32_t input_count = stage->input_count(); | |
| 77 for (uint32_t input_index = 0; input_index < input_count; input_index++) { | |
| 78 if (stage->input(input_index).connected()) { | |
| 79 Disconnect(Input(stage, input_index)); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 uint32_t output_count = stage->output_count(); | |
| 84 for (uint32_t output_index = 0; output_index < output_count; output_index++) { | |
| 85 if (stage->output(output_index).connected()) { | |
| 86 Disconnect(Output(stage, output_index)); | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 sources_.remove(stage); | |
| 91 sinks_.remove(stage); | |
| 92 | |
| 93 std::unique_ptr<Stage> to_remove(stage); // Release this duplicate unique_ptr! | |
|
johngro
2016/01/20 00:25:32
something feel wrong about this...
if stages_ is
dalesat
2016/01/25 23:29:37
A good analogy is that engine is a container like
johngro
2016/01/27 22:35:22
Acknowledged.
| |
| 94 stages_.remove(to_remove); | |
| 95 to_remove.release(); // OK, it's released! | |
| 96 } | |
| 97 | |
| 98 Engine::Part Engine::Connect( | |
| 99 Output output, | |
| 100 Input input) { | |
| 101 DCHECK(output); | |
| 102 DCHECK(input); | |
| 103 | |
| 104 if (output.connected()) { | |
| 105 Disconnect(output); | |
| 106 } | |
| 107 if (input.connected()) { | |
| 108 Disconnect(input); | |
| 109 } | |
| 110 | |
| 111 output.stage_output().connect( | |
| 112 input.stage_, | |
| 113 input.index_); | |
| 114 | |
| 115 input.stage_input().connect( | |
| 116 output.stage_, | |
| 117 output.index_); | |
| 118 | |
| 119 return input.part(); | |
| 120 } | |
| 121 | |
| 122 Engine::Part Engine::Connect(Part upstream_part, Part downstream_part) { | |
| 123 DCHECK(upstream_part); | |
| 124 DCHECK(downstream_part); | |
| 125 Connect(upstream_part.output(), downstream_part.input()); | |
| 126 return downstream_part; | |
| 127 } | |
| 128 | |
| 129 Engine::Part Engine::Connect( | |
| 130 Output output, | |
| 131 Part downstream_part) { | |
| 132 DCHECK(output); | |
| 133 DCHECK(downstream_part); | |
| 134 Connect(output, downstream_part.input()); | |
| 135 return downstream_part; | |
| 136 } | |
| 137 | |
| 138 Engine::Part Engine::Connect( | |
| 139 Part upstream_part, | |
| 140 Input input) { | |
| 141 DCHECK(upstream_part); | |
| 142 DCHECK(input); | |
| 143 Connect(upstream_part.output(), input); | |
| 144 return input.part(); | |
| 145 } | |
| 146 | |
| 147 void Engine::Disconnect(Output output) { | |
| 148 DCHECK(output); | |
| 149 | |
| 150 if (!output.connected()) { | |
| 151 return; | |
| 152 } | |
| 153 | |
| 154 StageOutput& stage_output = output.stage_output(); | |
| 155 stage_output.mate().connect(nullptr, 0); | |
| 156 stage_output.connect(nullptr, 0); | |
| 157 } | |
| 158 | |
| 159 void Engine::Disconnect(Input input) { | |
| 160 DCHECK(input); | |
| 161 | |
| 162 if (!input.connected()) { | |
| 163 return; | |
| 164 } | |
| 165 | |
| 166 StageInput& stage_input = input.stage_input(); | |
| 167 stage_input.mate().connect(nullptr, 0); | |
| 168 stage_input.connect(nullptr, 0); | |
| 169 } | |
| 170 | |
| 171 void Engine::RemoveAll(Part part) { | |
| 172 std::deque<Part> to_remove { part }; | |
| 173 | |
| 174 while (!to_remove.empty()) { | |
| 175 Part part = to_remove.front(); | |
| 176 to_remove.pop_front(); | |
| 177 | |
| 178 for (uint32_t i = 0; i < part.input_count(); ++i) { | |
| 179 to_remove.push_back(part.upstream_part(i)); | |
| 180 } | |
| 181 | |
| 182 for (uint32_t i = 0; i < part.output_count(); ++i) { | |
| 183 to_remove.push_back(part.downstream_part(i)); | |
| 184 } | |
| 185 | |
| 186 Remove(part); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void Engine::RemoveAll(Output output) { | |
| 191 DCHECK(output); | |
| 192 | |
| 193 if (!output.connected()) { | |
| 194 return; | |
| 195 } | |
| 196 | |
| 197 Part downstream_part = output.downstream_part(); | |
| 198 Disconnect(output); | |
| 199 RemoveAll(downstream_part); | |
| 200 } | |
| 201 | |
| 202 void Engine::RemoveAll(Input input) { | |
| 203 DCHECK(input); | |
| 204 | |
| 205 if (!input.connected()) { | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 Part upstream_part = input.upstream_part(); | |
| 210 Disconnect(input); | |
| 211 RemoveAll(upstream_part); | |
| 212 } | |
| 213 | |
| 214 void Engine::Prepare() { | |
| 215 for (Stage* sink : sinks_) { | |
| 216 sink->Prepare(update_function_); | |
| 217 sink->engine_private().prepared_ = true; | |
| 218 uint32_t input_count = sink->input_count(); | |
| 219 for (uint32_t input_index = 0; input_index < input_count; input_index++) { | |
| 220 Prepare(sink->input(input_index).upstream_stage()); | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 void Engine::reset() { | |
| 226 supply_backlog_.clear(); | |
| 227 demand_backlog_.clear(); | |
| 228 sources_.clear(); | |
| 229 sinks_.clear(); | |
| 230 stages_.clear(); | |
| 231 } | |
| 232 | |
| 233 Engine::Part Engine::Add(Stage* stage) { | |
| 234 stages_.push_back(std::unique_ptr<Stage>(stage)); | |
|
johngro
2016/01/20 00:25:32
related to the question about unique pointers earl
dalesat
2016/01/28 18:49:15
Using raw pointers here now.
| |
| 235 if (stage->input_count() == 0) { | |
| 236 sources_.push_back(stage); | |
| 237 } | |
| 238 if (stage->output_count() == 0) { | |
| 239 sinks_.push_back(stage); | |
| 240 } | |
| 241 return Part(stage); | |
| 242 } | |
| 243 | |
| 244 // static | |
| 245 Stage* Engine::CreateStage(MultiStreamPacketSourcePtr source) { | |
| 246 return new DistributorStage(source); | |
| 247 } | |
| 248 | |
| 249 // static | |
| 250 Stage* Engine::CreateStage(PacketTransformPtr transform) { | |
| 251 return new PacketTransformStage(transform); | |
| 252 } | |
| 253 | |
| 254 // static | |
| 255 Stage* Engine::CreateStage(ActiveSourcePtr source) { | |
| 256 return new ActiveSourceStage(source); | |
| 257 } | |
| 258 | |
| 259 // static | |
| 260 Stage* Engine::CreateStage(ActiveSinkPtr sink) { | |
| 261 return new ActiveSinkStage(sink); | |
| 262 } | |
| 263 | |
| 264 // static | |
| 265 Stage* Engine::CreateStage(LpcmTransformPtr transform) { | |
| 266 return new LpcmTransformStage(transform); | |
| 267 } | |
| 268 | |
| 269 void Engine::Prepare(Stage* stage) { | |
| 270 if (stage == nullptr || stage->engine_private().prepared_) { | |
| 271 return; | |
| 272 } | |
| 273 | |
| 274 stage->Prepare(update_function_); | |
| 275 stage->engine_private().prepared_ = true; | |
| 276 | |
| 277 uint32_t input_count = stage->input_count(); | |
| 278 for (uint32_t input_index = 0; input_index < input_count; input_index++) { | |
| 279 Prepare(stage->input(input_index).upstream_stage()); | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 void Engine::Update() { | |
| 284 while (true) { | |
|
johngro
2016/01/20 00:25:32
something to consider moving forward;
If this is
dalesat
2016/01/25 17:47:29
Agreed. The threading model isn't complete.
johngro
2016/01/27 22:35:22
Acknowledged.
| |
| 285 Stage* stage = PopFromSupplyBacklog(); | |
| 286 if (stage != nullptr) { | |
| 287 Update(stage); | |
| 288 continue; | |
| 289 } | |
| 290 | |
| 291 stage = PopFromDemandBacklog(); | |
| 292 if (stage != nullptr) { | |
| 293 Update(stage); | |
| 294 continue; | |
| 295 } | |
| 296 | |
| 297 break; | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 void Engine::Update(Stage *stage) { | |
| 302 DCHECK(stage); | |
| 303 | |
| 304 packets_produced_ = false; | |
| 305 | |
| 306 stage->Update(*this); | |
| 307 | |
| 308 // If the stage produced packets, it may need to reevaluate demand later. | |
| 309 if (packets_produced_) { | |
| 310 PushToDemandBacklog(stage); | |
| 311 } | |
| 312 } | |
| 313 | |
| 314 void Engine::PushToSupplyBacklog(Stage* stage) { | |
| 315 DCHECK(stage); | |
| 316 packets_produced_ = true; | |
| 317 if (!stage->engine_private().in_supply_backlog_) { | |
| 318 // LIFO | |
| 319 supply_backlog_.push_back(stage); | |
| 320 stage->engine_private().in_supply_backlog_ = true; | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 void Engine::PushToDemandBacklog(Stage* stage) { | |
| 325 DCHECK(stage); | |
| 326 if (!stage->engine_private().in_demand_backlog_) { | |
| 327 // FIFO | |
| 328 demand_backlog_.push_front(stage); | |
| 329 stage->engine_private().in_demand_backlog_ = true; | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 Stage* Engine::PopFromSupplyBacklog() { | |
| 334 if (supply_backlog_.empty()) { | |
| 335 return nullptr; | |
| 336 } | |
| 337 | |
| 338 Stage* stage = supply_backlog_.front(); | |
|
johngro
2016/01/20 00:25:32
the comment above indicates that this is supposed
johngro
2016/01/27 22:35:22
This still seems backwards, see updated comment in
dalesat
2016/01/28 18:49:15
Done.
| |
| 339 supply_backlog_.pop_front(); | |
| 340 DCHECK(stage->engine_private().in_supply_backlog_); | |
| 341 stage->engine_private().in_supply_backlog_ = false; | |
| 342 return stage; | |
| 343 } | |
| 344 | |
| 345 Stage* Engine::PopFromDemandBacklog() { | |
| 346 if (demand_backlog_.empty()) { | |
| 347 return nullptr; | |
| 348 } | |
| 349 | |
| 350 Stage* stage = demand_backlog_.front(); | |
| 351 demand_backlog_.pop_front(); | |
| 352 DCHECK(stage->engine_private().in_demand_backlog_); | |
| 353 stage->engine_private().in_demand_backlog_ = false; | |
| 354 return stage; | |
| 355 } | |
| 356 | |
| 357 } // namespace media | |
| 358 } // namespace mojo | |
| OLD | NEW |