Chromium Code Reviews| 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 |