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. Requests bigger than | |
53 // uint32_max will fail. | |
54 if (capacity > static_cast<size_t>(std::numeric_limits<uint32_t>::max())) | |
55 return nullptr; | |
xhwang
2016/03/15 06:17:22
ditto
jrummell
2016/03/15 18:49:42
Done.
| |
56 | |
57 return new MojoCdmBuffer(std::move(buffer), | |
58 base::checked_cast<uint32_t>(capacity), | |
49 mojo_shared_buffer_done_cb); | 59 mojo_shared_buffer_done_cb); |
50 } | 60 } |
51 | 61 |
52 // cdm::Buffer implementation. | 62 // cdm::Buffer implementation. |
53 void Destroy() final { | 63 void Destroy() final { |
54 // Unmap the memory before returning the handle to |allocator_|. | 64 // Unmap the memory before returning the handle to |allocator_|. |
55 MojoResult result = mojo::UnmapBuffer(memory_); | 65 MojoResult result = mojo::UnmapBuffer(memory_); |
56 ALLOW_UNUSED_LOCAL(result); | 66 ALLOW_UNUSED_LOCAL(result); |
57 DCHECK(result == MOJO_RESULT_OK); | 67 DCHECK(result == MOJO_RESULT_OK); |
58 memory_ = nullptr; | 68 memory_ = nullptr; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 | 169 |
160 } // namespace | 170 } // namespace |
161 | 171 |
162 MojoCdmAllocator::MojoCdmAllocator() : weak_ptr_factory_(this) {} | 172 MojoCdmAllocator::MojoCdmAllocator() : weak_ptr_factory_(this) {} |
163 | 173 |
164 MojoCdmAllocator::~MojoCdmAllocator() {} | 174 MojoCdmAllocator::~MojoCdmAllocator() {} |
165 | 175 |
166 // Creates a cdm::Buffer, reusing an existing buffer if one is available. | 176 // 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 | 177 // 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. | 178 // responsible for calling Destroy() on the buffer when it is no longer needed. |
169 cdm::Buffer* MojoCdmAllocator::CreateCdmBuffer(uint32_t capacity) { | 179 cdm::Buffer* MojoCdmAllocator::CreateCdmBuffer(size_t capacity) { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 180 DCHECK(thread_checker_.CalledOnValidThread()); |
171 | 181 |
172 if (!capacity) | 182 if (!capacity) |
173 return nullptr; | 183 return nullptr; |
174 | 184 |
175 // Reuse a buffer in the free map if there is one that fits |capacity|. | 185 // Reuse a buffer in the free map if there is one that fits |capacity|. |
176 // Otherwise, create a new one. | 186 // Otherwise, create a new one. |
177 mojo::ScopedSharedBufferHandle buffer; | 187 mojo::ScopedSharedBufferHandle buffer; |
178 auto found = available_buffers_.lower_bound(capacity); | 188 auto found = available_buffers_.lower_bound(capacity); |
179 if (found == available_buffers_.end()) { | 189 if (found == available_buffers_.end()) { |
(...skipping 17 matching lines...) Expand all Loading... | |
197 | 207 |
198 // Creates a new SimpleCdmVideoFrame on every request. | 208 // Creates a new SimpleCdmVideoFrame on every request. |
199 scoped_ptr<VideoFrameImpl> MojoCdmAllocator::CreateCdmVideoFrame() { | 209 scoped_ptr<VideoFrameImpl> MojoCdmAllocator::CreateCdmVideoFrame() { |
200 DCHECK(thread_checker_.CalledOnValidThread()); | 210 DCHECK(thread_checker_.CalledOnValidThread()); |
201 return make_scoped_ptr(new MojoCdmVideoFrame( | 211 return make_scoped_ptr(new MojoCdmVideoFrame( |
202 base::Bind(&MojoCdmAllocator::AddBufferToAvailableMap, | 212 base::Bind(&MojoCdmAllocator::AddBufferToAvailableMap, |
203 weak_ptr_factory_.GetWeakPtr()))); | 213 weak_ptr_factory_.GetWeakPtr()))); |
204 } | 214 } |
205 | 215 |
206 mojo::ScopedSharedBufferHandle MojoCdmAllocator::AllocateNewBuffer( | 216 mojo::ScopedSharedBufferHandle MojoCdmAllocator::AllocateNewBuffer( |
207 uint32_t* capacity) { | 217 size_t* capacity) { |
208 DCHECK(thread_checker_.CalledOnValidThread()); | 218 DCHECK(thread_checker_.CalledOnValidThread()); |
209 | 219 |
210 // Always pad new allocated buffer so that we don't need to reallocate | 220 // Always pad new allocated buffer so that we don't need to reallocate |
211 // buffers frequently if requested sizes fluctuate slightly. | 221 // buffers frequently if requested sizes fluctuate slightly. |
212 static const uint32_t kBufferPadding = 512; | 222 static const size_t kBufferPadding = 512; |
213 | 223 |
214 // Maximum number of free buffers we can keep when allocating new buffers. | 224 // Maximum number of free buffers we can keep when allocating new buffers. |
215 static const uint32_t kFreeLimit = 3; | 225 static const size_t kFreeLimit = 3; |
216 | 226 |
217 // Destroy the smallest buffer before allocating a new bigger buffer if the | 227 // 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 | 228 // 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 | 229 // up with too many small buffers, which could happen if the size to be |
220 // allocated keeps increasing. | 230 // allocated keeps increasing. |
221 if (available_buffers_.size() >= kFreeLimit) | 231 if (available_buffers_.size() >= kFreeLimit) |
222 available_buffers_.erase(available_buffers_.begin()); | 232 available_buffers_.erase(available_buffers_.begin()); |
223 | 233 |
224 // Creation of shared memory may be expensive if it involves synchronous IPC | 234 // 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. | 235 // calls. That's why we try to avoid AllocateNewBuffer() as much as we can. |
226 mojo::ScopedSharedBufferHandle handle; | 236 mojo::ScopedSharedBufferHandle handle; |
227 base::CheckedNumeric<uint32_t> requested_capacity(*capacity); | 237 base::CheckedNumeric<size_t> requested_capacity(*capacity); |
228 requested_capacity += kBufferPadding; | 238 requested_capacity += kBufferPadding; |
229 MojoResult result = mojo::CreateSharedBuffer( | 239 MojoResult result = mojo::CreateSharedBuffer( |
230 nullptr, requested_capacity.ValueOrDie(), &handle); | 240 nullptr, requested_capacity.ValueOrDie(), &handle); |
231 if (result != MOJO_RESULT_OK) | 241 if (result != MOJO_RESULT_OK) |
232 return mojo::ScopedSharedBufferHandle(); | 242 return mojo::ScopedSharedBufferHandle(); |
233 DCHECK(handle.is_valid()); | 243 DCHECK(handle.is_valid()); |
234 *capacity = requested_capacity.ValueOrDie(); | 244 *capacity = requested_capacity.ValueOrDie(); |
235 return handle; | 245 return handle; |
236 } | 246 } |
237 | 247 |
238 void MojoCdmAllocator::AddBufferToAvailableMap( | 248 void MojoCdmAllocator::AddBufferToAvailableMap( |
239 mojo::ScopedSharedBufferHandle buffer, | 249 mojo::ScopedSharedBufferHandle buffer, |
240 uint32_t capacity) { | 250 size_t capacity) { |
241 DCHECK(thread_checker_.CalledOnValidThread()); | 251 DCHECK(thread_checker_.CalledOnValidThread()); |
242 available_buffers_.insert(std::make_pair(capacity, std::move(buffer))); | 252 available_buffers_.insert(std::make_pair(capacity, std::move(buffer))); |
243 } | 253 } |
244 | 254 |
245 MojoHandle MojoCdmAllocator::GetHandleForTesting(cdm::Buffer* buffer) { | 255 MojoHandle MojoCdmAllocator::GetHandleForTesting(cdm::Buffer* buffer) { |
246 MojoCdmBuffer* mojo_buffer = static_cast<MojoCdmBuffer*>(buffer); | 256 MojoCdmBuffer* mojo_buffer = static_cast<MojoCdmBuffer*>(buffer); |
247 return mojo_buffer->Handle().value(); | 257 return mojo_buffer->Handle().value(); |
248 } | 258 } |
249 | 259 |
250 size_t MojoCdmAllocator::GetAvailableBufferCountForTesting() { | 260 size_t MojoCdmAllocator::GetAvailableBufferCountForTesting() { |
251 return available_buffers_.size(); | 261 return available_buffers_.size(); |
252 } | 262 } |
253 | 263 |
254 } // namespace media | 264 } // namespace media |
OLD | NEW |