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.get() && !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->set_timestamp(timestamp); 79 break; 80 } 81 } 82 83 if (!frame.get()) { 84 frame = VideoFrame::CreateFrame( 85 format, coded_size, visible_rect, natural_size, timestamp); 86 } 87 88 return VideoFrame::WrapVideoFrame( 89 frame, frame->visible_rect(), frame->natural_size(), 90 base::Bind(&VideoFramePool::PoolImpl::FrameReleased, this, frame)); 91 } 92 93 void VideoFramePool::PoolImpl::Shutdown() { 94 base::AutoLock auto_lock(lock_); 95 is_shutdown_ = true; 96 frames_.clear(); 97 } 98 99 void VideoFramePool::PoolImpl::FrameReleased( 100 const scoped_refptr<VideoFrame>& frame) { 101 base::AutoLock auto_lock(lock_); 102 if (is_shutdown_) 103 return; 104 105 frames_.push_back(frame); 106 } 107 108 VideoFramePool::VideoFramePool() : pool_(new PoolImpl()) { 109 } 110 111 VideoFramePool::~VideoFramePool() { 112 pool_->Shutdown(); 113 } 114 115 scoped_refptr<VideoFrame> VideoFramePool::CreateFrame( 116 VideoFrame::Format format, 117 const gfx::Size& coded_size, 118 const gfx::Rect& visible_rect, 119 const gfx::Size& natural_size, 120 base::TimeDelta timestamp) { 121 return pool_->CreateFrame(format, coded_size, visible_rect, natural_size, 122 timestamp); 123 } 124 125 size_t VideoFramePool::GetPoolSizeForTesting() const { 126 return pool_->GetPoolSizeForTesting(); 127 } 128 129 } // namespace media 130