1 /* 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/include/i420_buffer_pool.h" 12 13 #include "webrtc/base/checks.h" 14 15 namespace { 16 17 // One extra indirection is needed to make |HasOneRef| work. 18 class PooledI420Buffer : public webrtc::VideoFrameBuffer { 19 public: PooledI420Buffer(const rtc::scoped_refptr<webrtc::I420Buffer> & buffer)20 explicit PooledI420Buffer( 21 const rtc::scoped_refptr<webrtc::I420Buffer>& buffer) 22 : buffer_(buffer) {} 23 24 private: ~PooledI420Buffer()25 ~PooledI420Buffer() override {} 26 width() const27 int width() const override { return buffer_->width(); } height() const28 int height() const override { return buffer_->height(); } data(webrtc::PlaneType type) const29 const uint8_t* data(webrtc::PlaneType type) const override { 30 return buffer_->data(type); 31 } MutableData(webrtc::PlaneType type)32 uint8_t* MutableData(webrtc::PlaneType type) override { 33 // Make the HasOneRef() check here instead of in |buffer_|, because the pool 34 // also has a reference to |buffer_|. 35 RTC_DCHECK(HasOneRef()); 36 return const_cast<uint8_t*>(buffer_->data(type)); 37 } stride(webrtc::PlaneType type) const38 int stride(webrtc::PlaneType type) const override { 39 return buffer_->stride(type); 40 } native_handle() const41 void* native_handle() const override { return nullptr; } 42 NativeToI420Buffer()43 rtc::scoped_refptr<VideoFrameBuffer> NativeToI420Buffer() override { 44 RTC_NOTREACHED(); 45 return nullptr; 46 } 47 48 friend class rtc::RefCountedObject<PooledI420Buffer>; 49 rtc::scoped_refptr<webrtc::I420Buffer> buffer_; 50 }; 51 52 } // namespace 53 54 namespace webrtc { 55 I420BufferPool()56I420BufferPool::I420BufferPool() { 57 Release(); 58 } 59 Release()60void I420BufferPool::Release() { 61 thread_checker_.DetachFromThread(); 62 buffers_.clear(); 63 } 64 CreateBuffer(int width,int height)65rtc::scoped_refptr<VideoFrameBuffer> I420BufferPool::CreateBuffer(int width, 66 int height) { 67 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 68 // Release buffers with wrong resolution. 69 for (auto it = buffers_.begin(); it != buffers_.end();) { 70 if ((*it)->width() != width || (*it)->height() != height) 71 it = buffers_.erase(it); 72 else 73 ++it; 74 } 75 // Look for a free buffer. 76 for (const rtc::scoped_refptr<I420Buffer>& buffer : buffers_) { 77 // If the buffer is in use, the ref count will be 2, one from the list we 78 // are looping over and one from a PooledI420Buffer returned from 79 // CreateBuffer that has not been released yet. If the ref count is 1 80 // (HasOneRef), then the list we are looping over holds the only reference 81 // and it's safe to reuse. 82 if (buffer->HasOneRef()) 83 return new rtc::RefCountedObject<PooledI420Buffer>(buffer); 84 } 85 // Allocate new buffer. 86 buffers_.push_back(new rtc::RefCountedObject<I420Buffer>(width, height)); 87 return new rtc::RefCountedObject<PooledI420Buffer>(buffers_.back()); 88 } 89 90 } // namespace webrtc 91