cdm_helpers.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
15f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant// Copyright 2013 The Chromium Authors. All rights reserved.
25f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant// Use of this source code is governed by a BSD-style license that can be
35f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant// found in the LICENSE file.
45f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant#include "media/cdm/ppapi/cdm_helpers.h"
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant
75f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include <utility>
85f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
95f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "base/basictypes.h"
105f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "base/compiler_specific.h"
115f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "build/build_config.h"
125f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "media/cdm/ppapi/api/content_decryption_module.h"
135f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/c/pp_errors.h"
145f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/c/pp_stdint.h"
155f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/cpp/core.h"
165f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/cpp/dev/buffer_dev.h"
175f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/cpp/instance.h"
185f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/cpp/logging.h"
195f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant#include "ppapi/cpp/module.h"
205f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
215f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnantnamespace media {
225f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
235f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnantcdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
245f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant  PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
255f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
265f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant  if (capacity <= 0)
275f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant    return NULL;
285f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
295f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant  pp::Buffer_Dev buffer;
305f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant  uint32_t buffer_id = 0;
315f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant
325f9b133e2cd3b000056bdda641b94ebb611d4653Howard Hinnant  // Reuse a buffer in the free list if there is one that fits |capacity|.
33  // Otherwise, create a new one.
34  FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
35  if (found == free_buffers_.end()) {
36    // TODO(xhwang): Report statistics about how many new buffers are allocated.
37    buffer = AllocateNewBuffer(capacity);
38    if (buffer.is_null())
39      return NULL;
40    buffer_id = next_buffer_id_++;
41  } else {
42    buffer = found->second.second;
43    buffer_id = found->second.first;
44    free_buffers_.erase(found);
45  }
46
47  allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
48
49  return PpbBuffer::Create(buffer, buffer_id);
50}
51
52void PpbBufferAllocator::Release(uint32_t buffer_id) {
53  if (!buffer_id)
54    return;
55
56  AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
57  if (found == allocated_buffers_.end())
58    return;
59
60  pp::Buffer_Dev& buffer = found->second;
61  free_buffers_.insert(
62      std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
63
64  allocated_buffers_.erase(found);
65}
66
67pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
68  // Always pad new allocated buffer so that we don't need to reallocate
69  // buffers frequently if requested sizes fluctuate slightly.
70  static const int kBufferPadding = 512;
71
72  // Maximum number of free buffers we can keep when allocating new buffers.
73  static const int kFreeLimit = 3;
74
75  // Destroy the smallest buffer before allocating a new bigger buffer if the
76  // number of free buffers exceeds a limit. This mechanism helps avoid ending
77  // up with too many small buffers, which could happen if the size to be
78  // allocated keeps increasing.
79  if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
80    free_buffers_.erase(free_buffers_.begin());
81
82  // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
83  // That's why we try to avoid AllocateNewBuffer() as much as we can.
84  return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
85}
86
87VideoFrameImpl::VideoFrameImpl()
88    : format_(cdm::kUnknownVideoFormat),
89      frame_buffer_(NULL),
90      timestamp_(0) {
91  for (int32_t i = 0; i < kMaxPlanes; ++i) {
92    plane_offsets_[i] = 0;
93    strides_[i] = 0;
94  }
95}
96
97VideoFrameImpl::~VideoFrameImpl() {
98  if (frame_buffer_)
99    frame_buffer_->Destroy();
100}
101
102}  // namespace media
103