Home | History | Annotate | Download | only in base
      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