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.
4
5#ifndef MEDIA_CDM_PPAPI_CDM_HELPERS_H_
6#define MEDIA_CDM_PPAPI_CDM_HELPERS_H_
7
8#include <map>
9#include <utility>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "build/build_config.h"
14#include "media/cdm/ppapi/api/content_decryption_module.h"
15#include "ppapi/c/pp_errors.h"
16#include "ppapi/c/pp_stdint.h"
17#include "ppapi/cpp/dev/buffer_dev.h"
18#include "ppapi/cpp/instance.h"
19#include "ppapi/cpp/logging.h"
20
21namespace media {
22
23class PpbBufferAllocator;
24
25// cdm::Buffer implementation that provides access to memory owned by a
26// pp::Buffer_Dev.
27// This class holds a reference to the Buffer_Dev throughout its lifetime.
28// TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
29// pp::Buffer_Dev and PPB_Buffer_Dev.
30class PpbBuffer : public cdm::Buffer {
31 public:
32  static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id,
33                           PpbBufferAllocator* allocator);
34
35  // cdm::Buffer implementation.
36  virtual void Destroy() OVERRIDE;
37  virtual uint32_t Capacity() const OVERRIDE;
38  virtual uint8_t* Data() OVERRIDE;
39  virtual void SetSize(uint32_t size) OVERRIDE;
40  virtual uint32_t Size() const OVERRIDE { return size_; }
41
42  // Takes the |buffer_| from this class and returns it.
43  // Note: The caller must ensure |allocator->Release()| is called later so that
44  // the buffer can be reused by the allocator.
45  // Since pp::Buffer_Dev is ref-counted, the caller now holds one reference to
46  // the buffer and this class holds no reference. Note that other references
47  // may still exist. For example, PpbBufferAllocator always holds a reference
48  // to all allocated buffers.
49  pp::Buffer_Dev TakeBuffer();
50
51  uint32_t buffer_id() const { return buffer_id_; }
52
53 private:
54  PpbBuffer(pp::Buffer_Dev buffer,
55            uint32_t buffer_id,
56            PpbBufferAllocator* allocator);
57  virtual ~PpbBuffer();
58
59  pp::Buffer_Dev buffer_;
60  uint32_t buffer_id_;
61  uint32_t size_;
62  PpbBufferAllocator* allocator_;
63
64  DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
65};
66
67class PpbBufferAllocator {
68 public:
69  explicit PpbBufferAllocator(pp::Instance* instance)
70      : instance_(instance),
71        next_buffer_id_(1) {}
72  ~PpbBufferAllocator() {}
73
74  cdm::Buffer* Allocate(uint32_t capacity);
75
76  // Releases the buffer with |buffer_id|. A buffer can be recycled after
77  // it is released.
78  void Release(uint32_t buffer_id);
79
80 private:
81  typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
82  typedef std::multimap<uint32_t, std::pair<uint32_t, pp::Buffer_Dev> >
83      FreeBufferMap;
84
85  pp::Buffer_Dev AllocateNewBuffer(uint32_t capacity);
86
87  pp::Instance* const instance_;
88  uint32_t next_buffer_id_;
89  AllocatedBufferMap allocated_buffers_;
90  FreeBufferMap free_buffers_;
91
92  DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
93};
94
95class DecryptedBlockImpl : public cdm::DecryptedBlock {
96 public:
97  DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
98  virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
99
100  virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
101    buffer_ = static_cast<PpbBuffer*>(buffer);
102  }
103  virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
104
105  virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
106    timestamp_ = timestamp;
107  }
108  virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
109
110 private:
111  PpbBuffer* buffer_;
112  int64_t timestamp_;
113
114  DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
115};
116
117class VideoFrameImpl : public cdm::VideoFrame {
118 public:
119  VideoFrameImpl();
120  virtual ~VideoFrameImpl();
121
122  virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
123    format_ = format;
124  }
125  virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
126
127  virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
128  virtual cdm::Size Size() const OVERRIDE { return size_; }
129
130  virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
131    frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
132  }
133  virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
134
135  virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
136                              uint32_t offset) OVERRIDE {
137    PP_DCHECK(plane < kMaxPlanes);
138    plane_offsets_[plane] = offset;
139  }
140  virtual uint32_t PlaneOffset(VideoPlane plane) OVERRIDE {
141    PP_DCHECK(plane < kMaxPlanes);
142    return plane_offsets_[plane];
143  }
144
145  virtual void SetStride(VideoPlane plane, uint32_t stride) OVERRIDE {
146    PP_DCHECK(plane < kMaxPlanes);
147    strides_[plane] = stride;
148  }
149  virtual uint32_t Stride(VideoPlane plane) OVERRIDE {
150    PP_DCHECK(plane < kMaxPlanes);
151    return strides_[plane];
152  }
153
154  virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
155    timestamp_ = timestamp;
156  }
157  virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
158
159 private:
160  // The video buffer format.
161  cdm::VideoFormat format_;
162
163  // Width and height of the video frame.
164  cdm::Size size_;
165
166  // The video frame buffer.
167  PpbBuffer* frame_buffer_;
168
169  // Array of data pointers to each plane in the video frame buffer.
170  uint32_t plane_offsets_[kMaxPlanes];
171
172  // Array of strides for each plane, typically greater or equal to the width
173  // of the surface divided by the horizontal sampling period.  Note that
174  // strides can be negative.
175  uint32_t strides_[kMaxPlanes];
176
177  // Presentation timestamp in microseconds.
178  int64_t timestamp_;
179
180  DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
181};
182
183class AudioFramesImpl : public cdm::AudioFrames_2 {
184 public:
185  AudioFramesImpl() : buffer_(NULL), format_(cdm::kUnknownAudioFormat) {}
186  virtual ~AudioFramesImpl() {
187    if (buffer_)
188      buffer_->Destroy();
189  }
190
191  // AudioFrames implementation.
192  virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
193    buffer_ = static_cast<PpbBuffer*>(buffer);
194  }
195  virtual cdm::Buffer* FrameBuffer() OVERRIDE {
196    return buffer_;
197  }
198  virtual void SetFormat(cdm::AudioFormat format) OVERRIDE {
199    format_ = format;
200  }
201  virtual cdm::AudioFormat Format() const OVERRIDE {
202    return format_;
203  }
204
205  cdm::Buffer* PassFrameBuffer() {
206    PpbBuffer* temp_buffer = buffer_;
207    buffer_ = NULL;
208    return temp_buffer;
209  }
210
211 private:
212  PpbBuffer* buffer_;
213  cdm::AudioFormat format_;
214
215  DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
216};
217
218}  // namespace media
219
220#endif  // MEDIA_CDM_PPAPI_CDM_HELPERS_H_
221