blob: 04a0ab9b7f35d67803e921f08af6c15913cd1b52 [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() {
pbos@webrtc.orga3209a22015-03-20 13:35:56 +000054 Release();
55}
56
57void I420BufferPool::Release() {
magjed@webrtc.org73d763e2015-03-17 11:40:45 +000058 thread_checker_.DetachFromThread();
pbos@webrtc.orga3209a22015-03-20 13:35:56 +000059 buffers_.clear();
magjed@webrtc.org73d763e2015-03-17 11:40:45 +000060}
61
62rtc::scoped_refptr<VideoFrameBuffer> I420BufferPool::CreateBuffer(int width,
63 int height) {
64 DCHECK(thread_checker_.CalledOnValidThread());
65 // Release buffers with wrong resolution.
66 for (auto it = buffers_.begin(); it != buffers_.end();) {
67 if ((*it)->width() != width || (*it)->height() != height)
68 it = buffers_.erase(it);
69 else
70 ++it;
71 }
72 // Look for a free buffer.
73 for (const rtc::scoped_refptr<I420Buffer>& buffer : buffers_) {
74 // If the buffer is in use, the ref count will be 2, one from the list we
75 // are looping over and one from a PooledI420Buffer returned from
76 // CreateBuffer that has not been released yet. If the ref count is 1
77 // (HasOneRef), then the list we are looping over holds the only reference
78 // and it's safe to reuse.
79 if (buffer->HasOneRef())
80 return new rtc::RefCountedObject<PooledI420Buffer>(buffer);
81 }
82 // Allocate new buffer.
83 buffers_.push_back(new rtc::RefCountedObject<I420Buffer>(width, height));
84 return new rtc::RefCountedObject<PooledI420Buffer>(buffers_.back());
85}
86
87} // namespace webrtc