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