1 // Copyright 2013 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.
5 #include "media/cdm/ppapi/cdm_helpers.h"
9 #include "ppapi/cpp/core.h"
10 #include "ppapi/cpp/module.h"
15 PpbBuffer
* PpbBuffer::Create(const pp::Buffer_Dev
& buffer
,
17 PpbBufferAllocator
* allocator
) {
18 PP_DCHECK(buffer
.data());
19 PP_DCHECK(buffer
.size());
22 return new PpbBuffer(buffer
, buffer_id
, allocator
);
25 void PpbBuffer::Destroy() {
29 uint32_t PpbBuffer::Capacity() const {
30 return buffer_
.size();
33 uint8_t* PpbBuffer::Data() {
34 return static_cast<uint8_t*>(buffer_
.data());
37 void PpbBuffer::SetSize(uint32_t size
) {
38 PP_DCHECK(size
<= Capacity());
39 if (size
> Capacity()) {
47 pp::Buffer_Dev
PpbBuffer::TakeBuffer() {
48 PP_DCHECK(!buffer_
.is_null());
49 pp::Buffer_Dev buffer
;
50 std::swap(buffer
, buffer_
);
56 PpbBuffer::PpbBuffer(pp::Buffer_Dev buffer
,
58 PpbBufferAllocator
* allocator
)
59 : buffer_(buffer
), buffer_id_(buffer_id
), size_(0), allocator_(allocator
) {
62 PpbBuffer::~PpbBuffer() {
63 PP_DCHECK(!buffer_id_
== buffer_
.is_null());
64 // If still owning the |buffer_|, release it in the |allocator_|.
66 allocator_
->Release(buffer_id_
);
69 cdm::Buffer
* PpbBufferAllocator::Allocate(uint32_t capacity
) {
70 PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
75 pp::Buffer_Dev buffer
;
76 uint32_t buffer_id
= 0;
78 // Reuse a buffer in the free list if there is one that fits |capacity|.
79 // Otherwise, create a new one.
80 FreeBufferMap::iterator found
= free_buffers_
.lower_bound(capacity
);
81 if (found
== free_buffers_
.end()) {
82 // TODO(xhwang): Report statistics about how many new buffers are allocated.
83 buffer
= AllocateNewBuffer(capacity
);
86 buffer_id
= next_buffer_id_
++;
88 buffer
= found
->second
.second
;
89 buffer_id
= found
->second
.first
;
90 free_buffers_
.erase(found
);
93 allocated_buffers_
.insert(std::make_pair(buffer_id
, buffer
));
95 return PpbBuffer::Create(buffer
, buffer_id
, this);
98 void PpbBufferAllocator::Release(uint32_t buffer_id
) {
102 AllocatedBufferMap::iterator found
= allocated_buffers_
.find(buffer_id
);
103 if (found
== allocated_buffers_
.end())
106 pp::Buffer_Dev
& buffer
= found
->second
;
107 free_buffers_
.insert(
108 std::make_pair(buffer
.size(), std::make_pair(buffer_id
, buffer
)));
110 allocated_buffers_
.erase(found
);
113 pp::Buffer_Dev
PpbBufferAllocator::AllocateNewBuffer(uint32_t capacity
) {
114 // Always pad new allocated buffer so that we don't need to reallocate
115 // buffers frequently if requested sizes fluctuate slightly.
116 static const uint32_t kBufferPadding
= 512;
118 // Maximum number of free buffers we can keep when allocating new buffers.
119 static const uint32_t kFreeLimit
= 3;
121 // Destroy the smallest buffer before allocating a new bigger buffer if the
122 // number of free buffers exceeds a limit. This mechanism helps avoid ending
123 // up with too many small buffers, which could happen if the size to be
124 // allocated keeps increasing.
125 if (free_buffers_
.size() >= kFreeLimit
)
126 free_buffers_
.erase(free_buffers_
.begin());
128 // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
129 // That's why we try to avoid AllocateNewBuffer() as much as we can.
130 return pp::Buffer_Dev(instance_
, capacity
+ kBufferPadding
);
133 VideoFrameImpl::VideoFrameImpl()
134 : format_(cdm::kUnknownVideoFormat
),
137 for (uint32_t i
= 0; i
< kMaxPlanes
; ++i
) {
138 plane_offsets_
[i
] = 0;
143 VideoFrameImpl::~VideoFrameImpl() {
145 frame_buffer_
->Destroy();