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

Side by Side Diff: services/media/framework_mojo/mojo_pull_mode_producer.cc

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

Powered by Google App Engine
This is Rietveld 408576698