Index: services/media/framework/stages/stage_output.cc |
diff --git a/services/media/framework/stages/stage_output.cc b/services/media/framework/stages/stage_output.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..34d921f66fb9fbd9454bf11c5182e33c1846656c |
--- /dev/null |
+++ b/services/media/framework/stages/stage_output.cc |
@@ -0,0 +1,122 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "services/media/framework/engine.h" |
+#include "services/media/framework/stages/stage.h" |
+#include "services/media/framework/stages/stage_output.h" |
+ |
+namespace mojo { |
+namespace media { |
+ |
+StageOutput::StageOutput() : |
+ downstream_stage_(nullptr), |
+ input_index_(0), |
+ demand_(Demand::kNegative), |
+ copy_allocator_(nullptr) {} |
+ |
+StageOutput::~StageOutput() {} |
+ |
+void StageOutput::connect(Stage* downstream_stage, uint32_t input_index) { |
+ DCHECK(downstream_stage); |
+ DCHECK(input_index < downstream_stage->input_count()); |
+ DCHECK(downstream_stage_ == nullptr); |
+ downstream_stage_ = downstream_stage; |
+ input_index_ = input_index; |
+} |
+ |
+StageInput& StageOutput::mate() const { |
+ DCHECK(downstream_stage_); |
+ DCHECK(input_index_ < downstream_stage_->input_count()); |
+ return downstream_stage_->input(input_index_); |
+} |
+ |
+Allocator* StageOutput::Prepare(bool can_accept_allocator) { |
+ DCHECK(connected()); |
+ StageInput& mate = this->mate(); |
+ copy_allocator_ = nullptr; |
+ |
+ if (can_accept_allocator) { |
+ // We can use an allocator. Use our mate's allocator, if it has one. |
+ return mate.allocator(); |
+ } else if (mate.must_allocate()) { |
+ // We can't use an allocator, but our mate needs us to. We'll need to copy |
+ // every packet. |
+ copy_allocator_ = mate.allocator(); |
+ DCHECK(copy_allocator_); |
+ return nullptr; |
+ } else { |
+ // We can't use an allocator, and our mate doesn't need us to. |
+ return nullptr; |
+ } |
+} |
+ |
+Demand StageOutput::demand() const { |
+ DCHECK(connected()); |
+ |
+ // Return negative demand if mate() already has a packet. |
+ // We check demand_ here to possibly avoid the second check. |
+ if (demand_ == Demand::kNegative || mate().packet_from_upstream()) { |
+ return Demand::kNegative; |
+ } |
+ |
+ return demand_; |
+} |
+ |
+void StageOutput::SupplyPacket(PacketPtr packet, Engine* engine) const { |
+ DCHECK(packet); |
+ DCHECK(engine); |
+ DCHECK(connected()); |
+ |
+ if (copy_allocator_ != nullptr) { |
+ // Need to copy the packet due to an allocation conflict. |
+ uint64_t size = packet->size(); |
+ void *buffer; |
+ |
+ if (size == 0) { |
+ buffer = nullptr; |
+ } else { |
+ buffer = copy_allocator_->AllocatePayloadBuffer(size); |
+ if (buffer == nullptr) { |
+ // Starved for buffer space. |
+ return; |
+ } |
+ memcpy(buffer, packet->payload(), size); |
+ } |
+ |
+ packet = Packet::Create( |
+ packet->presentation_time(), |
+ packet->duration(), |
+ packet->end_of_stream(), |
+ size, |
+ buffer, |
+ copy_allocator_); |
+ } |
+ |
+ SupplyPacketInternal(std::move(packet), engine); |
+} |
+ |
+bool StageOutput::UpdateDemand(Demand demand) { |
+ if (demand_ == demand) { |
+ return false; |
+ } |
+ demand_ = demand; |
+ return true; |
+} |
+ |
+LpcmStageOutput* StageOutput::get_lpcm() { |
+ return nullptr; |
+} |
+ |
+void StageOutput::SupplyPacketInternal(PacketPtr packet, Engine* engine) |
+ const { |
+ DCHECK(packet); |
+ DCHECK(engine); |
+ DCHECK(connected()); |
+ if (mate().SupplyPacketFromOutput(std::move(packet))) { |
+ engine->PushToSupplyBacklogUnsafe(downstream_stage()); |
+ } |
+} |
+ |
+} // namespace media |
+} // namespace mojo |