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 #include "media/base/video_frame_pool.h" 6 7 #include <list> 8 9 #include "base/bind.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/synchronization/lock.h" 12 13 namespace media { 14 15 class VideoFramePool::PoolImpl 16 : public base::RefCountedThreadSafe<VideoFramePool::PoolImpl> { 17 public: 18 PoolImpl(); 19 20 // Returns a frame from the pool that matches the specified 21 // parameters or creates a new frame if no suitable frame exists in 22 // the pool. The pool is drained if no matching frame is found. 23 scoped_refptr<VideoFrame> CreateFrame(VideoFrame::Format format, 24 const gfx::Size& coded_size, 25 const gfx::Rect& visible_rect, 26 const gfx::Size& natural_size, 27 base::TimeDelta timestamp); 28 29 // Shuts down the frame pool and releases all frames in |frames_|. 30 // Once this is called frames will no longer be inserted back into 31 // |frames_|. 32 void Shutdown(); 33 34 size_t GetPoolSizeForTesting() const { return frames_.size(); } 35 36 private: 37 friend class base::RefCountedThreadSafe<VideoFramePool::PoolImpl>; 38 ~PoolImpl(); 39 40 // Called when the frame wrapper gets destroyed. 41 // |frame| is the actual frame that was wrapped and is placed 42 // in |frames_| by this function so it can be reused. 43 void FrameReleased(const scoped_refptr<VideoFrame>& frame); 44 45 base::Lock lock_; 46 bool is_shutdown_; 47 std::list<scoped_refptr<VideoFrame> > frames_; 48 49 DISALLOW_COPY_AND_ASSIGN(PoolImpl); 50 }; 51 52 VideoFramePool::PoolImpl::PoolImpl() : is_shutdown_(false) {} 53 54 VideoFramePool::PoolImpl::~PoolImpl() { 55 DCHECK(is_shutdown_); 56 } 57 58 scoped_refptr<VideoFrame> VideoFramePool::PoolImpl::CreateFrame( 59 VideoFrame::Format format, 60 const gfx::Size& coded_size, 61 const gfx::Rect& visible_rect, 62 const gfx::Size& natural_size, 63 base::TimeDelta timestamp) { 64 base::AutoLock auto_lock(lock_); 65 DCHECK(!is_shutdown_); 66 67 scoped_refptr<VideoFrame> frame; 68 69 while (!frame && !frames_.empty()) { 70 scoped_refptr<VideoFrame> pool_frame = frames_.front(); 71 frames_.pop_front(); 72 73 if (pool_frame->format() == format && 74 pool_frame->coded_size() == coded_size && 75 pool_frame->visible_rect() == visible_rect && 76 pool_frame->natural_size() == natural_size) { 77 frame = pool_frame; 78 frame->SetTimestamp(kNoTimestamp()); 79 break; 80 } 81 } 82 83 if (!frame) { 84 frame = VideoFrame::CreateFrame( 85 format, coded_size, visible_rect, natural_size, kNoTimestamp()); 86 } 87 88 return VideoFrame::WrapVideoFrame( 89 frame, base::Bind(&VideoFramePool::PoolImpl::FrameReleased, this, frame)); 90 } 91 92 void VideoFramePool::PoolImpl::Shutdown() { 93 base::AutoLock auto_lock(lock_); 94 is_shutdown_ = true; 95 frames_.clear(); 96 } 97 98 void VideoFramePool::PoolImpl::FrameReleased( 99 const scoped_refptr<VideoFrame>& frame) { 100 base::AutoLock auto_lock(lock_); 101 if (is_shutdown_) 102 return; 103 104 frames_.push_back(frame); 105 } 106 107 VideoFramePool::VideoFramePool() : pool_(new PoolImpl()) { 108 } 109 110 VideoFramePool::~VideoFramePool() { 111 pool_->Shutdown(); 112 } 113 114 scoped_refptr<VideoFrame> VideoFramePool::CreateFrame( 115 VideoFrame::Format format, 116 const gfx::Size& coded_size, 117 const gfx::Rect& visible_rect, 118 const gfx::Size& natural_size, 119 base::TimeDelta timestamp) { 120 return pool_->CreateFrame(format, coded_size, visible_rect, natural_size, 121 timestamp); 122 } 123 124 size_t VideoFramePool::GetPoolSizeForTesting() const { 125 return pool_->GetPoolSizeForTesting(); 126 } 127 128 } // namespace media 129