OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chromecast/media/cma/ipc/media_message_fifo.h" | 5 #include "chromecast/media/cma/ipc/media_message_fifo.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 flag_ = scoped_refptr<MediaMessageFlag>(); | 98 flag_ = scoped_refptr<MediaMessageFlag>(); |
99 if (!release_msg_cb_.is_null()) { | 99 if (!release_msg_cb_.is_null()) { |
100 if (task_runner_->BelongsToCurrentThread()) { | 100 if (task_runner_->BelongsToCurrentThread()) { |
101 release_msg_cb_.Run(); | 101 release_msg_cb_.Run(); |
102 } else { | 102 } else { |
103 task_runner_->PostTask(FROM_HERE, release_msg_cb_); | 103 task_runner_->PostTask(FROM_HERE, release_msg_cb_); |
104 } | 104 } |
105 } | 105 } |
106 } | 106 } |
107 | 107 |
108 MediaMessageFifo::MediaMessageFifo(scoped_ptr<MediaMemoryChunk> mem, bool init) | 108 MediaMessageFifo::MediaMessageFifo(std::unique_ptr<MediaMemoryChunk> mem, |
| 109 bool init) |
109 : mem_(std::move(mem)), weak_factory_(this) { | 110 : mem_(std::move(mem)), weak_factory_(this) { |
110 CHECK_EQ(reinterpret_cast<uintptr_t>(mem_->data()) % ALIGNOF(Descriptor), | 111 CHECK_EQ(reinterpret_cast<uintptr_t>(mem_->data()) % ALIGNOF(Descriptor), |
111 0u); | 112 0u); |
112 CHECK_GE(mem_->size(), sizeof(Descriptor)); | 113 CHECK_GE(mem_->size(), sizeof(Descriptor)); |
113 Descriptor* desc = static_cast<Descriptor*>(mem_->data()); | 114 Descriptor* desc = static_cast<Descriptor*>(mem_->data()); |
114 base_ = static_cast<void*>(&desc->first_item); | 115 base_ = static_cast<void*>(&desc->first_item); |
115 | 116 |
116 // TODO(damienv): remove cast when atomic size_t is defined in Chrome. | 117 // TODO(damienv): remove cast when atomic size_t is defined in Chrome. |
117 // Currently, the sign differs. | 118 // Currently, the sign differs. |
118 rd_offset_ = reinterpret_cast<AtomicSize*>(&(desc->rd_offset)); | 119 rd_offset_ = reinterpret_cast<AtomicSize*>(&(desc->rd_offset)); |
(...skipping 29 matching lines...) Expand all Loading... |
148 void MediaMessageFifo::ObserveReadActivity( | 149 void MediaMessageFifo::ObserveReadActivity( |
149 const base::Closure& read_event_cb) { | 150 const base::Closure& read_event_cb) { |
150 read_event_cb_ = read_event_cb; | 151 read_event_cb_ = read_event_cb; |
151 } | 152 } |
152 | 153 |
153 void MediaMessageFifo::ObserveWriteActivity( | 154 void MediaMessageFifo::ObserveWriteActivity( |
154 const base::Closure& write_event_cb) { | 155 const base::Closure& write_event_cb) { |
155 write_event_cb_ = write_event_cb; | 156 write_event_cb_ = write_event_cb; |
156 } | 157 } |
157 | 158 |
158 scoped_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemory( | 159 std::unique_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemory( |
159 size_t size_to_reserve) { | 160 size_t size_to_reserve) { |
160 DCHECK(thread_checker_.CalledOnValidThread()); | 161 DCHECK(thread_checker_.CalledOnValidThread()); |
161 | 162 |
162 // Capture first both the read and write offsets. | 163 // Capture first both the read and write offsets. |
163 // and exit right away if not enough free space. | 164 // and exit right away if not enough free space. |
164 size_t wr_offset = internal_wr_offset(); | 165 size_t wr_offset = internal_wr_offset(); |
165 size_t rd_offset = current_rd_offset(); | 166 size_t rd_offset = current_rd_offset(); |
166 size_t allocated_size = (size_ + wr_offset - rd_offset) % size_; | 167 size_t allocated_size = (size_ + wr_offset - rd_offset) % size_; |
167 size_t free_size = size_ - 1 - allocated_size; | 168 size_t free_size = size_ - 1 - allocated_size; |
168 if (free_size < size_to_reserve) | 169 if (free_size < size_to_reserve) |
169 return scoped_ptr<MediaMemoryChunk>(); | 170 return std::unique_ptr<MediaMemoryChunk>(); |
170 CHECK_LE(MediaMessage::minimum_msg_size(), size_to_reserve); | 171 CHECK_LE(MediaMessage::minimum_msg_size(), size_to_reserve); |
171 | 172 |
172 // Note: in the next 2 conditions, we have: | 173 // Note: in the next 2 conditions, we have: |
173 // trailing_byte_count < size_to_reserve | 174 // trailing_byte_count < size_to_reserve |
174 // and since at this stage: size_to_reserve <= free_size | 175 // and since at this stage: size_to_reserve <= free_size |
175 // we also have trailing_byte_count <= free_size | 176 // we also have trailing_byte_count <= free_size |
176 // which means that all the trailing bytes are free space in the fifo. | 177 // which means that all the trailing bytes are free space in the fifo. |
177 size_t trailing_byte_count = size_ - wr_offset; | 178 size_t trailing_byte_count = size_ - wr_offset; |
178 if (trailing_byte_count < MediaMessage::minimum_msg_size()) { | 179 if (trailing_byte_count < MediaMessage::minimum_msg_size()) { |
179 // If there is no space to even write the smallest message, | 180 // If there is no space to even write the smallest message, |
180 // skip the trailing bytes and come back to the beginning of the fifo. | 181 // skip the trailing bytes and come back to the beginning of the fifo. |
181 // (no way to insert a padding message). | 182 // (no way to insert a padding message). |
182 if (free_size < trailing_byte_count) | 183 if (free_size < trailing_byte_count) |
183 return scoped_ptr<MediaMemoryChunk>(); | 184 return std::unique_ptr<MediaMemoryChunk>(); |
184 wr_offset = 0; | 185 wr_offset = 0; |
185 CommitInternalWrite(wr_offset); | 186 CommitInternalWrite(wr_offset); |
186 | 187 |
187 } else if (trailing_byte_count < size_to_reserve) { | 188 } else if (trailing_byte_count < size_to_reserve) { |
188 // At this point, we know we have at least the space to write a message. | 189 // At this point, we know we have at least the space to write a message. |
189 // However, to avoid splitting a message, a padding message is needed. | 190 // However, to avoid splitting a message, a padding message is needed. |
190 scoped_ptr<MediaMemoryChunk> mem( | 191 std::unique_ptr<MediaMemoryChunk> mem( |
191 ReserveMemoryNoCheck(trailing_byte_count)); | 192 ReserveMemoryNoCheck(trailing_byte_count)); |
192 scoped_ptr<MediaMessage> padding_message( | 193 std::unique_ptr<MediaMessage> padding_message( |
193 MediaMessage::CreateMessage(PaddingMediaMsg, std::move(mem))); | 194 MediaMessage::CreateMessage(PaddingMediaMsg, std::move(mem))); |
194 } | 195 } |
195 | 196 |
196 // Recalculate the free size and exit if not enough free space. | 197 // Recalculate the free size and exit if not enough free space. |
197 wr_offset = internal_wr_offset(); | 198 wr_offset = internal_wr_offset(); |
198 allocated_size = (size_ + wr_offset - rd_offset) % size_; | 199 allocated_size = (size_ + wr_offset - rd_offset) % size_; |
199 free_size = size_ - 1 - allocated_size; | 200 free_size = size_ - 1 - allocated_size; |
200 if (free_size < size_to_reserve) | 201 if (free_size < size_to_reserve) |
201 return scoped_ptr<MediaMemoryChunk>(); | 202 return std::unique_ptr<MediaMemoryChunk>(); |
202 | 203 |
203 return ReserveMemoryNoCheck(size_to_reserve); | 204 return ReserveMemoryNoCheck(size_to_reserve); |
204 } | 205 } |
205 | 206 |
206 scoped_ptr<MediaMessage> MediaMessageFifo::Pop() { | 207 std::unique_ptr<MediaMessage> MediaMessageFifo::Pop() { |
207 DCHECK(thread_checker_.CalledOnValidThread()); | 208 DCHECK(thread_checker_.CalledOnValidThread()); |
208 | 209 |
209 // Capture the read and write offsets. | 210 // Capture the read and write offsets. |
210 size_t rd_offset = internal_rd_offset(); | 211 size_t rd_offset = internal_rd_offset(); |
211 size_t wr_offset = current_wr_offset(); | 212 size_t wr_offset = current_wr_offset(); |
212 size_t allocated_size = (size_ + wr_offset - rd_offset) % size_; | 213 size_t allocated_size = (size_ + wr_offset - rd_offset) % size_; |
213 | 214 |
214 if (allocated_size < MediaMessage::minimum_msg_size()) | 215 if (allocated_size < MediaMessage::minimum_msg_size()) |
215 return scoped_ptr<MediaMessage>(); | 216 return std::unique_ptr<MediaMessage>(); |
216 | 217 |
217 size_t trailing_byte_count = size_ - rd_offset; | 218 size_t trailing_byte_count = size_ - rd_offset; |
218 if (trailing_byte_count < MediaMessage::minimum_msg_size()) { | 219 if (trailing_byte_count < MediaMessage::minimum_msg_size()) { |
219 // If there is no space to even have the smallest message, | 220 // If there is no space to even have the smallest message, |
220 // skip the trailing bytes and come back to the beginning of the fifo. | 221 // skip the trailing bytes and come back to the beginning of the fifo. |
221 // Note: all the trailing bytes correspond to allocated bytes since: | 222 // Note: all the trailing bytes correspond to allocated bytes since: |
222 // trailing_byte_count < MediaMessage::minimum_msg_size() <= allocated_size | 223 // trailing_byte_count < MediaMessage::minimum_msg_size() <= allocated_size |
223 rd_offset = 0; | 224 rd_offset = 0; |
224 allocated_size -= trailing_byte_count; | 225 allocated_size -= trailing_byte_count; |
225 trailing_byte_count = size_; | 226 trailing_byte_count = size_; |
226 CommitInternalRead(rd_offset); | 227 CommitInternalRead(rd_offset); |
227 } | 228 } |
228 | 229 |
229 // The message should not be longer than the allocated size | 230 // The message should not be longer than the allocated size |
230 // but since a message is a contiguous area of memory, it should also be | 231 // but since a message is a contiguous area of memory, it should also be |
231 // smaller than |trailing_byte_count|. | 232 // smaller than |trailing_byte_count|. |
232 size_t max_msg_size = std::min(allocated_size, trailing_byte_count); | 233 size_t max_msg_size = std::min(allocated_size, trailing_byte_count); |
233 if (max_msg_size < MediaMessage::minimum_msg_size()) | 234 if (max_msg_size < MediaMessage::minimum_msg_size()) |
234 return scoped_ptr<MediaMessage>(); | 235 return std::unique_ptr<MediaMessage>(); |
235 void* msg_src = static_cast<uint8_t*>(base_) + rd_offset; | 236 void* msg_src = static_cast<uint8_t*>(base_) + rd_offset; |
236 | 237 |
237 // Create a flag to protect the serialized structure of the message | 238 // Create a flag to protect the serialized structure of the message |
238 // from being overwritten. | 239 // from being overwritten. |
239 // The serialized structure starts at offset |rd_offset|. | 240 // The serialized structure starts at offset |rd_offset|. |
240 scoped_refptr<MediaMessageFlag> rd_flag(new MediaMessageFlag(rd_offset)); | 241 scoped_refptr<MediaMessageFlag> rd_flag(new MediaMessageFlag(rd_offset)); |
241 rd_flags_.push_back(rd_flag); | 242 rd_flags_.push_back(rd_flag); |
242 scoped_ptr<MediaMemoryChunk> mem( | 243 std::unique_ptr<MediaMemoryChunk> mem(new FifoOwnedMemory( |
243 new FifoOwnedMemory( | 244 msg_src, max_msg_size, rd_flag, |
244 msg_src, max_msg_size, rd_flag, | 245 base::Bind(&MediaMessageFifo::OnRdMemoryReleased, weak_this_))); |
245 base::Bind(&MediaMessageFifo::OnRdMemoryReleased, weak_this_))); | |
246 | 246 |
247 // Create the message which wraps its the serialized structure. | 247 // Create the message which wraps its the serialized structure. |
248 scoped_ptr<MediaMessage> message(MediaMessage::MapMessage(std::move(mem))); | 248 std::unique_ptr<MediaMessage> message( |
| 249 MediaMessage::MapMessage(std::move(mem))); |
249 CHECK(message); | 250 CHECK(message); |
250 | 251 |
251 // Update the internal read pointer. | 252 // Update the internal read pointer. |
252 rd_offset = (rd_offset + message->size()) % size_; | 253 rd_offset = (rd_offset + message->size()) % size_; |
253 CommitInternalRead(rd_offset); | 254 CommitInternalRead(rd_offset); |
254 | 255 |
255 return message; | 256 return message; |
256 } | 257 } |
257 | 258 |
258 void MediaMessageFifo::Flush() { | 259 void MediaMessageFifo::Flush() { |
259 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
260 | 261 |
261 size_t wr_offset = current_wr_offset(); | 262 size_t wr_offset = current_wr_offset(); |
262 | 263 |
263 // Invalidate every memory region before flushing. | 264 // Invalidate every memory region before flushing. |
264 while (!rd_flags_.empty()) { | 265 while (!rd_flags_.empty()) { |
265 CMALOG(kLogControl) << "Invalidate flag"; | 266 CMALOG(kLogControl) << "Invalidate flag"; |
266 rd_flags_.front()->Invalidate(); | 267 rd_flags_.front()->Invalidate(); |
267 rd_flags_.pop_front(); | 268 rd_flags_.pop_front(); |
268 } | 269 } |
269 | 270 |
270 // Flush by setting the read pointer to the value of the write pointer. | 271 // Flush by setting the read pointer to the value of the write pointer. |
271 // Update first the internal read pointer then the public one. | 272 // Update first the internal read pointer then the public one. |
272 CommitInternalRead(wr_offset); | 273 CommitInternalRead(wr_offset); |
273 CommitRead(wr_offset); | 274 CommitRead(wr_offset); |
274 } | 275 } |
275 | 276 |
276 scoped_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemoryNoCheck( | 277 std::unique_ptr<MediaMemoryChunk> MediaMessageFifo::ReserveMemoryNoCheck( |
277 size_t size_to_reserve) { | 278 size_t size_to_reserve) { |
278 size_t wr_offset = internal_wr_offset(); | 279 size_t wr_offset = internal_wr_offset(); |
279 | 280 |
280 // Memory block corresponding to the serialized structure of the message. | 281 // Memory block corresponding to the serialized structure of the message. |
281 void* msg_start = static_cast<uint8_t*>(base_) + wr_offset; | 282 void* msg_start = static_cast<uint8_t*>(base_) + wr_offset; |
282 scoped_refptr<MediaMessageFlag> wr_flag(new MediaMessageFlag(wr_offset)); | 283 scoped_refptr<MediaMessageFlag> wr_flag(new MediaMessageFlag(wr_offset)); |
283 wr_flags_.push_back(wr_flag); | 284 wr_flags_.push_back(wr_flag); |
284 scoped_ptr<MediaMemoryChunk> mem( | 285 std::unique_ptr<MediaMemoryChunk> mem(new FifoOwnedMemory( |
285 new FifoOwnedMemory( | 286 msg_start, size_to_reserve, wr_flag, |
286 msg_start, size_to_reserve, wr_flag, | 287 base::Bind(&MediaMessageFifo::OnWrMemoryReleased, weak_this_))); |
287 base::Bind(&MediaMessageFifo::OnWrMemoryReleased, weak_this_))); | |
288 | 288 |
289 // Update the internal write pointer. | 289 // Update the internal write pointer. |
290 wr_offset = (wr_offset + size_to_reserve) % size_; | 290 wr_offset = (wr_offset + size_to_reserve) % size_; |
291 CommitInternalWrite(wr_offset); | 291 CommitInternalWrite(wr_offset); |
292 | 292 |
293 return mem; | 293 return mem; |
294 } | 294 } |
295 | 295 |
296 void MediaMessageFifo::OnWrMemoryReleased() { | 296 void MediaMessageFifo::OnWrMemoryReleased() { |
297 DCHECK(thread_checker_.CalledOnValidThread()); | 297 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 void MediaMessageFifo::CommitInternalRead(size_t new_rd_offset) { | 396 void MediaMessageFifo::CommitInternalRead(size_t new_rd_offset) { |
397 internal_rd_offset_ = new_rd_offset; | 397 internal_rd_offset_ = new_rd_offset; |
398 } | 398 } |
399 | 399 |
400 void MediaMessageFifo::CommitInternalWrite(size_t new_wr_offset) { | 400 void MediaMessageFifo::CommitInternalWrite(size_t new_wr_offset) { |
401 internal_wr_offset_ = new_wr_offset; | 401 internal_wr_offset_ = new_wr_offset; |
402 } | 402 } |
403 | 403 |
404 } // namespace media | 404 } // namespace media |
405 } // namespace chromecast | 405 } // namespace chromecast |
OLD | NEW |