OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 "media/mojo/services/mojo_cdm_allocator.h" | 5 #include "media/mojo/services/mojo_cdm_allocator.h" |
6 | 6 |
| 7 #include <limits> |
| 8 |
7 #include "base/callback.h" | 9 #include "base/callback.h" |
8 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/numerics/safe_conversions.h" |
9 #include "base/numerics/safe_math.h" | 12 #include "base/numerics/safe_math.h" |
10 #include "media/cdm/api/content_decryption_module.h" | 13 #include "media/cdm/api/content_decryption_module.h" |
11 #include "media/cdm/cdm_helpers.h" | 14 #include "media/cdm/cdm_helpers.h" |
12 #include "media/cdm/simple_cdm_buffer.h" | 15 #include "media/cdm/simple_cdm_buffer.h" |
13 #include "media/mojo/common/mojo_shared_buffer_video_frame.h" | 16 #include "media/mojo/common/mojo_shared_buffer_video_frame.h" |
14 #include "mojo/public/cpp/system/buffer.h" | 17 #include "mojo/public/cpp/system/buffer.h" |
15 #include "ui/gfx/geometry/rect.h" | 18 #include "ui/gfx/geometry/rect.h" |
16 #include "ui/gfx/geometry/size.h" | 19 #include "ui/gfx/geometry/size.h" |
17 | 20 |
18 namespace media { | 21 namespace media { |
19 | 22 |
20 namespace { | 23 namespace { |
21 | 24 |
22 typedef base::Callback<void(mojo::ScopedSharedBufferHandle buffer, | 25 typedef base::Callback<void(mojo::ScopedSharedBufferHandle buffer, |
23 uint32_t capacity)> | 26 size_t capacity)> |
24 MojoSharedBufferDoneCB; | 27 MojoSharedBufferDoneCB; |
25 | 28 |
26 VideoPixelFormat CdmVideoFormatToVideoPixelFormat(cdm::VideoFormat format) { | 29 VideoPixelFormat CdmVideoFormatToVideoPixelFormat(cdm::VideoFormat format) { |
27 switch (format) { | 30 switch (format) { |
28 case cdm::kYv12: | 31 case cdm::kYv12: |
29 return PIXEL_FORMAT_YV12; | 32 return PIXEL_FORMAT_YV12; |
30 case cdm::kI420: | 33 case cdm::kI420: |
31 return PIXEL_FORMAT_I420; | 34 return PIXEL_FORMAT_I420; |
32 default: | 35 default: |
33 NOTREACHED(); | 36 NOTREACHED(); |
34 return PIXEL_FORMAT_UNKNOWN; | 37 return PIXEL_FORMAT_UNKNOWN; |
35 } | 38 } |
36 } | 39 } |
37 | 40 |
38 // cdm::Buffer implementation that provides access to mojo shared memory. | 41 // cdm::Buffer implementation that provides access to mojo shared memory. |
39 // It owns the memory until Destroy() is called. | 42 // It owns the memory until Destroy() is called. |
40 class MojoCdmBuffer : public cdm::Buffer { | 43 class MojoCdmBuffer : public cdm::Buffer { |
41 public: | 44 public: |
42 static MojoCdmBuffer* Create( | 45 static MojoCdmBuffer* Create( |
43 mojo::ScopedSharedBufferHandle buffer, | 46 mojo::ScopedSharedBufferHandle buffer, |
44 uint32_t capacity, | 47 size_t capacity, |
45 const MojoSharedBufferDoneCB& mojo_shared_buffer_done_cb) { | 48 const MojoSharedBufferDoneCB& mojo_shared_buffer_done_cb) { |
46 DCHECK(buffer.is_valid()); | 49 DCHECK(buffer.is_valid()); |
47 DCHECK(!mojo_shared_buffer_done_cb.is_null()); | 50 DCHECK(!mojo_shared_buffer_done_cb.is_null()); |
48 return new MojoCdmBuffer(std::move(buffer), capacity, | 51 |
| 52 // cdm::Buffer interface limits capacity to uint32. |
| 53 DCHECK_LE(capacity, |
| 54 static_cast<size_t>(std::numeric_limits<uint32_t>::max())); |
| 55 return new MojoCdmBuffer(std::move(buffer), |
| 56 base::checked_cast<uint32_t>(capacity), |
49 mojo_shared_buffer_done_cb); | 57 mojo_shared_buffer_done_cb); |
50 } | 58 } |
51 | 59 |
52 // cdm::Buffer implementation. | 60 // cdm::Buffer implementation. |
53 void Destroy() final { | 61 void Destroy() final { |
54 // Unmap the memory before returning the handle to |allocator_|. | 62 // Unmap the memory before returning the handle to |allocator_|. |
55 MojoResult result = mojo::UnmapBuffer(memory_); | 63 MojoResult result = mojo::UnmapBuffer(memory_); |
56 ALLOW_UNUSED_LOCAL(result); | 64 ALLOW_UNUSED_LOCAL(result); |
57 DCHECK(result == MOJO_RESULT_OK); | 65 DCHECK(result == MOJO_RESULT_OK); |
58 memory_ = nullptr; | 66 memory_ = nullptr; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 | 167 |
160 } // namespace | 168 } // namespace |
161 | 169 |
162 MojoCdmAllocator::MojoCdmAllocator() : weak_ptr_factory_(this) {} | 170 MojoCdmAllocator::MojoCdmAllocator() : weak_ptr_factory_(this) {} |
163 | 171 |
164 MojoCdmAllocator::~MojoCdmAllocator() {} | 172 MojoCdmAllocator::~MojoCdmAllocator() {} |
165 | 173 |
166 // Creates a cdm::Buffer, reusing an existing buffer if one is available. | 174 // Creates a cdm::Buffer, reusing an existing buffer if one is available. |
167 // If not, a new buffer is created using AllocateNewBuffer(). The caller is | 175 // If not, a new buffer is created using AllocateNewBuffer(). The caller is |
168 // responsible for calling Destroy() on the buffer when it is no longer needed. | 176 // responsible for calling Destroy() on the buffer when it is no longer needed. |
169 cdm::Buffer* MojoCdmAllocator::CreateCdmBuffer(uint32_t capacity) { | 177 cdm::Buffer* MojoCdmAllocator::CreateCdmBuffer(size_t capacity) { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 178 DCHECK(thread_checker_.CalledOnValidThread()); |
171 | 179 |
172 if (!capacity) | 180 if (!capacity) |
173 return nullptr; | 181 return nullptr; |
174 | 182 |
175 // Reuse a buffer in the free map if there is one that fits |capacity|. | 183 // Reuse a buffer in the free map if there is one that fits |capacity|. |
176 // Otherwise, create a new one. | 184 // Otherwise, create a new one. |
177 mojo::ScopedSharedBufferHandle buffer; | 185 mojo::ScopedSharedBufferHandle buffer; |
178 auto found = available_buffers_.lower_bound(capacity); | 186 auto found = available_buffers_.lower_bound(capacity); |
179 if (found == available_buffers_.end()) { | 187 if (found == available_buffers_.end()) { |
(...skipping 17 matching lines...) Expand all Loading... |
197 | 205 |
198 // Creates a new SimpleCdmVideoFrame on every request. | 206 // Creates a new SimpleCdmVideoFrame on every request. |
199 scoped_ptr<VideoFrameImpl> MojoCdmAllocator::CreateCdmVideoFrame() { | 207 scoped_ptr<VideoFrameImpl> MojoCdmAllocator::CreateCdmVideoFrame() { |
200 DCHECK(thread_checker_.CalledOnValidThread()); | 208 DCHECK(thread_checker_.CalledOnValidThread()); |
201 return make_scoped_ptr(new MojoCdmVideoFrame( | 209 return make_scoped_ptr(new MojoCdmVideoFrame( |
202 base::Bind(&MojoCdmAllocator::AddBufferToAvailableMap, | 210 base::Bind(&MojoCdmAllocator::AddBufferToAvailableMap, |
203 weak_ptr_factory_.GetWeakPtr()))); | 211 weak_ptr_factory_.GetWeakPtr()))); |
204 } | 212 } |
205 | 213 |
206 mojo::ScopedSharedBufferHandle MojoCdmAllocator::AllocateNewBuffer( | 214 mojo::ScopedSharedBufferHandle MojoCdmAllocator::AllocateNewBuffer( |
207 uint32_t* capacity) { | 215 size_t* capacity) { |
208 DCHECK(thread_checker_.CalledOnValidThread()); | 216 DCHECK(thread_checker_.CalledOnValidThread()); |
209 | 217 |
210 // Always pad new allocated buffer so that we don't need to reallocate | 218 // Always pad new allocated buffer so that we don't need to reallocate |
211 // buffers frequently if requested sizes fluctuate slightly. | 219 // buffers frequently if requested sizes fluctuate slightly. |
212 static const uint32_t kBufferPadding = 512; | 220 static const size_t kBufferPadding = 512; |
213 | 221 |
214 // Maximum number of free buffers we can keep when allocating new buffers. | 222 // Maximum number of free buffers we can keep when allocating new buffers. |
215 static const uint32_t kFreeLimit = 3; | 223 static const size_t kFreeLimit = 3; |
216 | 224 |
217 // Destroy the smallest buffer before allocating a new bigger buffer if the | 225 // Destroy the smallest buffer before allocating a new bigger buffer if the |
218 // number of free buffers exceeds a limit. This mechanism helps avoid ending | 226 // number of free buffers exceeds a limit. This mechanism helps avoid ending |
219 // up with too many small buffers, which could happen if the size to be | 227 // up with too many small buffers, which could happen if the size to be |
220 // allocated keeps increasing. | 228 // allocated keeps increasing. |
221 if (available_buffers_.size() >= kFreeLimit) | 229 if (available_buffers_.size() >= kFreeLimit) |
222 available_buffers_.erase(available_buffers_.begin()); | 230 available_buffers_.erase(available_buffers_.begin()); |
223 | 231 |
224 // Creation of shared memory may be expensive if it involves synchronous IPC | 232 // Creation of shared memory may be expensive if it involves synchronous IPC |
225 // calls. That's why we try to avoid AllocateNewBuffer() as much as we can. | 233 // calls. That's why we try to avoid AllocateNewBuffer() as much as we can. |
226 mojo::ScopedSharedBufferHandle handle; | 234 mojo::ScopedSharedBufferHandle handle; |
227 base::CheckedNumeric<uint32_t> requested_capacity(*capacity); | 235 base::CheckedNumeric<size_t> requested_capacity(*capacity); |
228 requested_capacity += kBufferPadding; | 236 requested_capacity += kBufferPadding; |
229 MojoResult result = mojo::CreateSharedBuffer( | 237 MojoResult result = mojo::CreateSharedBuffer( |
230 nullptr, requested_capacity.ValueOrDie(), &handle); | 238 nullptr, requested_capacity.ValueOrDie(), &handle); |
231 if (result != MOJO_RESULT_OK) | 239 if (result != MOJO_RESULT_OK) |
232 return mojo::ScopedSharedBufferHandle(); | 240 return mojo::ScopedSharedBufferHandle(); |
233 DCHECK(handle.is_valid()); | 241 DCHECK(handle.is_valid()); |
234 *capacity = requested_capacity.ValueOrDie(); | 242 *capacity = requested_capacity.ValueOrDie(); |
235 return handle; | 243 return handle; |
236 } | 244 } |
237 | 245 |
238 void MojoCdmAllocator::AddBufferToAvailableMap( | 246 void MojoCdmAllocator::AddBufferToAvailableMap( |
239 mojo::ScopedSharedBufferHandle buffer, | 247 mojo::ScopedSharedBufferHandle buffer, |
240 uint32_t capacity) { | 248 size_t capacity) { |
241 DCHECK(thread_checker_.CalledOnValidThread()); | 249 DCHECK(thread_checker_.CalledOnValidThread()); |
242 available_buffers_.insert(std::make_pair(capacity, std::move(buffer))); | 250 available_buffers_.insert(std::make_pair(capacity, std::move(buffer))); |
243 } | 251 } |
244 | 252 |
245 MojoHandle MojoCdmAllocator::GetHandleForTesting(cdm::Buffer* buffer) { | 253 MojoHandle MojoCdmAllocator::GetHandleForTesting(cdm::Buffer* buffer) { |
246 MojoCdmBuffer* mojo_buffer = static_cast<MojoCdmBuffer*>(buffer); | 254 MojoCdmBuffer* mojo_buffer = static_cast<MojoCdmBuffer*>(buffer); |
247 return mojo_buffer->Handle().value(); | 255 return mojo_buffer->Handle().value(); |
248 } | 256 } |
249 | 257 |
250 size_t MojoCdmAllocator::GetAvailableBufferCountForTesting() { | 258 size_t MojoCdmAllocator::GetAvailableBufferCountForTesting() { |
251 return available_buffers_.size(); | 259 return available_buffers_.size(); |
252 } | 260 } |
253 | 261 |
254 } // namespace media | 262 } // namespace media |
OLD | NEW |