blob: b6ad2ba2e4b48adbba33514ed8474b89205fc82a [file] [log] [blame]
magjed@webrtc.org73d763e2015-03-17 11:40:45 +00001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/common_video/interface/i420_buffer_pool.h"
12
13#include "webrtc/base/checks.h"
14
15namespace {
16
17// One extra indirection is needed to make |HasOneRef| work.
18class PooledI420Buffer : public webrtc::VideoFrameBuffer {
19 public:
20 explicit PooledI420Buffer(
21 const rtc::scoped_refptr<webrtc::I420Buffer>& buffer)
22 : buffer_(buffer) {}
23
24 private:
25 ~PooledI420Buffer() override {}
26
27 int width() const override { return buffer_->width(); }
28 int height() const override { return buffer_->height(); }
29 const uint8_t* data(webrtc::PlaneType type) const override {
30 const webrtc::I420Buffer* cbuffer = buffer_.get();
31 return cbuffer->data(type);
32 }
33 uint8_t* data(webrtc::PlaneType type) {
34 DCHECK(HasOneRef());
35 const webrtc::I420Buffer* cbuffer = buffer_.get();
36 return const_cast<uint8_t*>(cbuffer->data(type));
37 }
38 int stride(webrtc::PlaneType type) const override {
39 return buffer_->stride(type);
40 }
41 rtc::scoped_refptr<webrtc::NativeHandle> native_handle() const override {
42 return nullptr;
43 }
44
45 friend class rtc::RefCountedObject<PooledI420Buffer>;
46 rtc::scoped_refptr<webrtc::I420Buffer> buffer_;
47};
48
49} // namespace
50
51namespace webrtc {
52
53I420BufferPool::I420BufferPool() {
54 thread_checker_.DetachFromThread();
55}
56
57rtc::scoped_refptr<VideoFrameBuffer> I420BufferPool::CreateBuffer(int width,
58 int height) {
59 DCHECK(thread_checker_.CalledOnValidThread());
60 // Release buffers with wrong resolution.
61 for (auto it = buffers_.begin(); it != buffers_.end();) {
62 if ((*it)->width() != width || (*it)->height() != height)
63 it = buffers_.erase(it);
64 else
65 ++it;
66 }
67 // Look for a free buffer.
68 for (const rtc::scoped_refptr<I420Buffer>& buffer : buffers_) {
69 // If the buffer is in use, the ref count will be 2, one from the list we
70 // are looping over and one from a PooledI420Buffer returned from
71 // CreateBuffer that has not been released yet. If the ref count is 1
72 // (HasOneRef), then the list we are looping over holds the only reference
73 // and it's safe to reuse.
74 if (buffer->HasOneRef())
75 return new rtc::RefCountedObject<PooledI420Buffer>(buffer);
76 }
77 // Allocate new buffer.
78 buffers_.push_back(new rtc::RefCountedObject<I420Buffer>(width, height));
79 return new rtc::RefCountedObject<PooledI420Buffer>(buffers_.back());
80}
81
82} // namespace webrtc