| 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 "base/logging.h" | |
| 6 #include "services/media/framework_mojo/mojo_pull_mode_producer.h" | |
| 7 | |
| 8 namespace mojo { | |
| 9 namespace media { | |
| 10 | |
| 11 MojoPullModeProducer::MojoPullModeProducer() | |
| 12 : demand_(Demand::kNegative), | |
| 13 pts_(0), | |
| 14 cached_packet_(nullptr) {} | |
| 15 | |
| 16 MojoPullModeProducer::~MojoPullModeProducer() { | |
| 17 base::AutoLock lock(lock_); | |
| 18 } | |
| 19 | |
| 20 void MojoPullModeProducer::AddBinding( | |
| 21 InterfaceRequest<MediaPullModeProducer> producer) { | |
| 22 bindings_.AddBinding(this, producer.Pass()); | |
| 23 } | |
| 24 | |
| 25 void MojoPullModeProducer::GetBuffer(const GetBufferCallback& callback) { | |
| 26 if (!mojo_allocator_.initialized()) { | |
| 27 mojo_allocator_.InitNew(256 * 1024); // TODO(dalesat): Made up! | |
| 28 } | |
| 29 | |
| 30 callback.Run(mojo_allocator_.GetDuplicateHandle()); | |
| 31 | |
| 32 DCHECK(!cached_packet_); | |
| 33 DCHECK(demand_callback_); | |
| 34 demand_callback_(Demand::kPositive); | |
| 35 } | |
| 36 | |
| 37 void MojoPullModeProducer::PullPacket(MediaPacketPtr to_release, | |
| 38 const PullPacketCallback& callback) { | |
| 39 if (to_release) { | |
| 40 // The client has piggy-backed a release on this pull request. | |
| 41 ReleasePacket(to_release.Pass()); | |
| 42 } | |
| 43 | |
| 44 { | |
| 45 base::AutoLock lock(lock_); | |
| 46 | |
| 47 //if (state_ == MediaState::UNPREPARED) { | |
| 48 // The consumer has yet to call GetBuffer. This request will have to wait. | |
| 49 // pending_pulls_.push_back(callback); | |
| 50 // return; | |
| 51 //} | |
| 52 | |
| 53 DCHECK(mojo_allocator_.initialized()); | |
| 54 | |
| 55 // If there are no pending requests, see if we can handle this now. If | |
| 56 // requests are pending, add the callback to the pending queue. | |
| 57 if (!pending_pulls_.empty() || !MaybeHandlePullUnsafe(callback)) { | |
| 58 pending_pulls_.push_back(callback); | |
| 59 } | |
| 60 | |
| 61 DCHECK(!cached_packet_); | |
| 62 } | |
| 63 | |
| 64 DCHECK(demand_callback_); | |
| 65 demand_callback_(Demand::kPositive); | |
| 66 } | |
| 67 | |
| 68 void MojoPullModeProducer::ReleasePacket(MediaPacketPtr to_release) { | |
| 69 { | |
| 70 base::AutoLock lock(lock_); | |
| 71 uint64_t size = to_release->payload ? to_release->payload->length : 0; | |
| 72 void* payload = size == 0 ? nullptr : mojo_allocator_.PtrFromOffset( | |
| 73 to_release->payload->offset); | |
| 74 | |
| 75 for (auto iterator = unreleased_packets_.begin(); true; ++iterator) { | |
| 76 if (iterator == unreleased_packets_.end()) { | |
| 77 DCHECK(false) << "released packet has bad offset and/or size"; | |
| 78 break; | |
| 79 } | |
| 80 | |
| 81 if ((*iterator)->payload() == payload && (*iterator)->size() == size) { | |
| 82 unreleased_packets_.erase(iterator); | |
| 83 break; | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 // TODO(dalesat): What if the allocator has starved? | |
| 88 } | |
| 89 | |
| 90 DCHECK(demand_callback_); | |
| 91 demand_callback_(cached_packet_ ? Demand::kNegative : Demand::kPositive); | |
| 92 } | |
| 93 | |
| 94 PayloadAllocator* MojoPullModeProducer::allocator() { | |
| 95 return mojo_allocator_.initialized() ? &mojo_allocator_ : nullptr; | |
| 96 } | |
| 97 | |
| 98 void MojoPullModeProducer::SetDemandCallback( | |
| 99 const DemandCallback& demand_callback) { | |
| 100 demand_callback_ = demand_callback; | |
| 101 } | |
| 102 | |
| 103 Demand MojoPullModeProducer::SupplyPacket(PacketPtr packet) { | |
| 104 base::AutoLock lock(lock_); | |
| 105 DCHECK(demand_ != Demand::kNegative) << "packet pushed with negative demand"; | |
| 106 | |
| 107 DCHECK(!cached_packet_); | |
| 108 | |
| 109 // If there's no binding on the stream, throw the packet away. This can | |
| 110 // happen if a pull client disconnects unexpectedly. | |
| 111 if (bindings_.size() == 0) { | |
| 112 demand_ = Demand::kNegative; | |
| 113 // TODO(dalesat): More shutdown? | |
| 114 return demand_; | |
| 115 } | |
| 116 | |
| 117 // Accept the packet and handle pending pulls with it. | |
| 118 cached_packet_ = std::move(packet); | |
| 119 | |
| 120 HandlePendingPullsUnsafe(); | |
| 121 | |
| 122 demand_ = cached_packet_ ? Demand::kNegative : Demand::kPositive; | |
| 123 return demand_; | |
| 124 } | |
| 125 | |
| 126 void MojoPullModeProducer::HandlePendingPullsUnsafe() { | |
| 127 lock_.AssertAcquired(); | |
| 128 | |
| 129 while (!pending_pulls_.empty()) { | |
| 130 DCHECK(mojo_allocator_.initialized()); | |
| 131 | |
| 132 if (MaybeHandlePullUnsafe(pending_pulls_.front())) { | |
| 133 pending_pulls_.pop_front(); | |
| 134 } else { | |
| 135 break; | |
| 136 } | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 bool MojoPullModeProducer::MaybeHandlePullUnsafe( | |
| 141 const PullPacketCallback& callback) { | |
| 142 DCHECK(!callback.is_null()); | |
| 143 lock_.AssertAcquired(); | |
| 144 | |
| 145 //if (state_ == MediaState::ENDED) { | |
| 146 // At end-of-stream. Respond with empty end-of-stream packet. | |
| 147 // HandlePullWithPacketUnsafe(callback, Packet::CreateEndOfStream(pts_)); | |
| 148 // return true; | |
| 149 //} | |
| 150 | |
| 151 if (!cached_packet_) { | |
| 152 // Waiting for packet or end-of-stream indication. | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 HandlePullWithPacketUnsafe(callback, std::move(cached_packet_)); | |
| 157 return true; | |
| 158 } | |
| 159 | |
| 160 void MojoPullModeProducer::HandlePullWithPacketUnsafe( | |
| 161 const PullPacketCallback& callback, | |
| 162 PacketPtr packet) { | |
| 163 DCHECK(packet); | |
| 164 lock_.AssertAcquired(); | |
| 165 | |
| 166 // TODO(dalesat): Use TaskRunner for this callback. | |
| 167 callback.Run(CreateMediaPacket(packet)); | |
| 168 unreleased_packets_.push_back(std::move(packet)); | |
| 169 } | |
| 170 | |
| 171 MediaPacketPtr MojoPullModeProducer::CreateMediaPacket( | |
| 172 const PacketPtr& packet) { | |
| 173 DCHECK(packet); | |
| 174 | |
| 175 MediaPacketRegionPtr region = MediaPacketRegion::New(); | |
| 176 region->offset = mojo_allocator_.OffsetFromPtr(packet->payload()); | |
| 177 region->length = packet->size(); | |
| 178 | |
| 179 MediaPacketPtr media_packet = MediaPacket::New(); | |
| 180 media_packet->pts = packet->pts(); | |
| 181 media_packet->end_of_stream = packet->end_of_stream(); | |
| 182 media_packet->payload = region.Pass(); | |
| 183 pts_ = packet->pts(); | |
| 184 | |
| 185 return media_packet.Pass(); | |
| 186 } | |
| 187 | |
| 188 } // namespace media | |
| 189 } // namespace mojo | |
| OLD | NEW |