diff options
Diffstat (limited to 'chromium/media/base/video_frame_pool.cc')
-rw-r--r-- | chromium/media/base/video_frame_pool.cc | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/chromium/media/base/video_frame_pool.cc b/chromium/media/base/video_frame_pool.cc new file mode 100644 index 00000000000..4c5a5e31e22 --- /dev/null +++ b/chromium/media/base/video_frame_pool.cc @@ -0,0 +1,128 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/video_frame_pool.h" + +#include <list> + +#include "base/bind.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" + +namespace media { + +class VideoFramePool::PoolImpl + : public base::RefCountedThreadSafe<VideoFramePool::PoolImpl> { + public: + PoolImpl(); + + // Returns a frame from the pool that matches the specified + // parameters or creates a new frame if no suitable frame exists in + // the pool. The pool is drained if no matching frame is found. + scoped_refptr<VideoFrame> CreateFrame(VideoFrame::Format format, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + base::TimeDelta timestamp); + + // Shuts down the frame pool and releases all frames in |frames_|. + // Once this is called frames will no longer be inserted back into + // |frames_|. + void Shutdown(); + + size_t GetPoolSizeForTesting() const { return frames_.size(); } + + private: + friend class base::RefCountedThreadSafe<VideoFramePool::PoolImpl>; + ~PoolImpl(); + + // Called when the frame wrapper gets destroyed. + // |frame| is the actual frame that was wrapped and is placed + // in |frames_| by this function so it can be reused. + void FrameReleased(const scoped_refptr<VideoFrame>& frame); + + base::Lock lock_; + bool is_shutdown_; + std::list<scoped_refptr<VideoFrame> > frames_; + + DISALLOW_COPY_AND_ASSIGN(PoolImpl); +}; + +VideoFramePool::PoolImpl::PoolImpl() : is_shutdown_(false) {} + +VideoFramePool::PoolImpl::~PoolImpl() { + DCHECK(is_shutdown_); +} + +scoped_refptr<VideoFrame> VideoFramePool::PoolImpl::CreateFrame( + VideoFrame::Format format, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + base::TimeDelta timestamp) { + base::AutoLock auto_lock(lock_); + DCHECK(!is_shutdown_); + + scoped_refptr<VideoFrame> frame; + + while (!frame && !frames_.empty()) { + scoped_refptr<VideoFrame> pool_frame = frames_.front(); + frames_.pop_front(); + + if (pool_frame->format() == format && + pool_frame->coded_size() == coded_size && + pool_frame->visible_rect() == visible_rect && + pool_frame->natural_size() == natural_size) { + frame = pool_frame; + frame->SetTimestamp(kNoTimestamp()); + break; + } + } + + if (!frame) { + frame = VideoFrame::CreateFrame( + format, coded_size, visible_rect, natural_size, kNoTimestamp()); + } + + return VideoFrame::WrapVideoFrame( + frame, base::Bind(&VideoFramePool::PoolImpl::FrameReleased, this, frame)); +} + +void VideoFramePool::PoolImpl::Shutdown() { + base::AutoLock auto_lock(lock_); + is_shutdown_ = true; + frames_.clear(); +} + +void VideoFramePool::PoolImpl::FrameReleased( + const scoped_refptr<VideoFrame>& frame) { + base::AutoLock auto_lock(lock_); + if (is_shutdown_) + return; + + frames_.push_back(frame); +} + +VideoFramePool::VideoFramePool() : pool_(new PoolImpl()) { +} + +VideoFramePool::~VideoFramePool() { + pool_->Shutdown(); +} + +scoped_refptr<VideoFrame> VideoFramePool::CreateFrame( + VideoFrame::Format format, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + base::TimeDelta timestamp) { + return pool_->CreateFrame(format, coded_size, visible_rect, natural_size, + timestamp); +} + +size_t VideoFramePool::GetPoolSizeForTesting() const { + return pool_->GetPoolSizeForTesting(); +} + +} // namespace media |