15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/debug/trace_event.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/metrics/histogram.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/strings/stringprintf.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/gpu/client/gl_helper.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox_holder.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/video_frame.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/video_util.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libyuv/include/libyuv.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/image_transport_factory_android.h" 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/compositor/image_transport_factory.h" 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using media::VideoCaptureFormat; 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static const int kInfiniteRatio = 99999; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \ 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY( \ 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) name, \ 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (height) ? ((width) * 100) / (height) : kInfiniteRatio); 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer { 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public: 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int buffer_id, 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* data, 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t size) 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : Buffer(buffer_id, data, size), pool_(pool) { 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(pool_.get()); 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private: 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); } 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const scoped_refptr<VideoCaptureBufferPool> pool_; 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) explicit SyncPointClientImpl(GLHelper* gl_helper) : gl_helper_(gl_helper) {} 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~SyncPointClientImpl() {} 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual uint32 InsertSyncPoint() OVERRIDE { 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return gl_helper_->InsertSyncPoint(); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE { 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gl_helper_->WaitSyncPoint(sync_point); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GLHelper* gl_helper_; 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ReturnVideoFrame(const scoped_refptr<media::VideoFrame>& video_frame, 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 sync_point) { 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GLHelper* gl_helper = 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ImageTransportFactoryAndroid::GetInstance()->GetGLHelper(); 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(gl_helper); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // UpdateReleaseSyncPoint() creates a new sync_point using |gl_helper|, so 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // wait the given |sync_point| using |gl_helper|. 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gl_helper->WaitSyncPoint(sync_point); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SyncPointClientImpl client(gl_helper); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_frame->UpdateReleaseSyncPoint(&client); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // anonymous namespace 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VideoCaptureController::ControllerClient { 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ControllerClient(const VideoCaptureControllerID& id, 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VideoCaptureControllerEventHandler* handler, 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::ProcessHandle render_process, 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureSessionId session_id, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const media::VideoCaptureParams& params) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : controller_id(id), 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler(handler), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_process_handle(render_process), 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) session_id(session_id), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parameters(params), 10634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) session_closed(false), 10734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) paused(false) {} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ControllerClient() {} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ID used for identifying this object. 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const VideoCaptureControllerID controller_id; 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VideoCaptureControllerEventHandler* const event_handler; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Handle to the render process that will receive the capture buffers. 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::ProcessHandle render_process_handle; 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const media::VideoCaptureSessionId session_id; 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const media::VideoCaptureParams parameters; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Buffers that are currently known to this client. 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::set<int> known_buffers; 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Buffers currently held by this client, and syncpoint callback to call when 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // they are returned from the client. 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef std::map<int, scoped_refptr<media::VideoFrame> > ActiveBufferMap; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ActiveBufferMap active_buffers; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // State of capture session, controlled by VideoCaptureManager directly. This 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // transitions to true as soon as StopSession() occurs, at which point the 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // client is sent an OnEnded() event. However, because the client retains a 131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // VideoCaptureController* pointer, its ControllerClient entry lives on until 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // it unregisters itself via RemoveClient(), which may happen asynchronously. 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(nick): If we changed the semantics of VideoCaptureHost so that 135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // OnEnded() events were processed synchronously (with the RemoveClient() done 136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // implicitly), we could avoid tracking this state here in the Controller, and 137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // simplify the code in both places. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool session_closed; 13934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 14034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // Indicates whether the client is paused, if true, VideoCaptureController 14134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // stops updating its buffer. 14234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) bool paused; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Receives events from the VideoCaptureDevice and posts them to a 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// VideoCaptureController on the IO thread. An instance of this class may safely 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// outlive its target VideoCaptureController. 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Methods of this class may be called from any thread, and in practice will 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// often be called on some auxiliary thread depending on the platform and the 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// device type; including, for example, the DirectShow thread on Windows, the 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// v4l2_thread on Linux, and the UI thread for tab capture. 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class VideoCaptureController::VideoCaptureDeviceClient 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) : public media::VideoCaptureDevice::Client { 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit VideoCaptureDeviceClient( 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const base::WeakPtr<VideoCaptureController>& controller, 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const scoped_refptr<VideoCaptureBufferPool>& buffer_pool); 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~VideoCaptureDeviceClient(); 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // VideoCaptureDevice::Client implementation. 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual scoped_refptr<Buffer> ReserveOutputBuffer( 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::Format format, 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const gfx::Size& size) OVERRIDE; 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnIncomingCapturedData(const uint8* data, 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int length, 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const VideoCaptureFormat& frame_format, 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int rotation, 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) OVERRIDE; 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnIncomingCapturedVideoFrame( 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<Buffer>& buffer, 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const VideoCaptureFormat& buffer_format, 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame, 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) OVERRIDE; 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnError(const std::string& reason) OVERRIDE; 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnLog(const std::string& message) OVERRIDE; 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format, 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Size& dimensions); 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The controller to which we post events. 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const base::WeakPtr<VideoCaptureController> controller_; 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The pool of shared-memory buffers used for capturing. 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)VideoCaptureController::VideoCaptureController(int max_buffers) 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : buffer_pool_(new VideoCaptureBufferPool(max_buffers)), 1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state_(VIDEO_CAPTURE_STATE_STARTED), 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame_received_(false), 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) weak_ptr_factory_(this) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient( 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const base::WeakPtr<VideoCaptureController>& controller, 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : controller_(controller), buffer_pool_(buffer_pool) {} 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() { 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return weak_ptr_factory_.GetWeakPtr(); 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)scoped_ptr<media::VideoCaptureDevice::Client> 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureController::NewDeviceClient() { 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<media::VideoCaptureDevice::Client> result( 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new VideoCaptureDeviceClient(this->GetWeakPtr(), buffer_pool_)); 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return result.Pass(); 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureController::AddClient( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VideoCaptureControllerID& id, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerEventHandler* event_handler, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle render_process, 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureSessionId session_id, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const media::VideoCaptureParams& params) { 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << ", " << params.requested_format.frame_size.ToString() 2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << ", " << params.requested_format.frame_rate 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << ", " << session_id 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ")"; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If this is the first client added to the controller, cache the parameters. 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!controller_clients_.size()) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) video_capture_format_ = params.requested_format; 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal error in case device is already in error state. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == VIDEO_CAPTURE_STATE_ERROR) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_handler->OnError(id); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Do nothing if this client has called AddClient before. 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (FindClient(id, event_handler, controller_clients_)) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ControllerClient* client = new ControllerClient( 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) id, event_handler, render_process, session_id, params); 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If we already have gotten frame_info from the device, repeat it to the new 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // client. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_clients_.push_back(client); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int VideoCaptureController::RemoveClient( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VideoCaptureControllerID& id, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerEventHandler* event_handler) { 254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ControllerClient* client = FindClient(id, event_handler, controller_clients_); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!client) 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return kInvalidMediaCaptureSessionId; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Take back all buffers held by the |client|. 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (ControllerClient::ActiveBufferMap::iterator buffer_it = 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->active_buffers.begin(); 2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) buffer_it != client->active_buffers.end(); 2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++buffer_it) { 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_pool_->RelinquishConsumerHold(buffer_it->first, 1); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) client->active_buffers.clear(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int session_id = client->session_id; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_clients_.remove(client); 272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete client; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return session_id; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void VideoCaptureController::PauseOrResumeClient( 27834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) const VideoCaptureControllerID& id, 27934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureControllerEventHandler* event_handler, 28034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) bool pause) { 28134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 28234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DVLOG(1) << "VideoCaptureController::PauseOrResumeClient, id " 28334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) << id.device_id << ", " << pause; 28434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 28534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ControllerClient* client = FindClient(id, event_handler, controller_clients_); 28634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!client) 28734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 28834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 28934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK(client->paused != pause); 29034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) client->paused = pause; 29134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 29234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureController::StopSession(int session_id) { 294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ControllerClient* client = FindClient(session_id, controller_clients_); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client->session_closed = true; 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) client->event_handler->OnEnded(client->controller_id); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoCaptureController::ReturnBuffer( 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VideoCaptureControllerID& id, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerEventHandler* event_handler, 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int buffer_id, 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 sync_point) { 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ControllerClient* client = FindClient(id, event_handler, controller_clients_); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this buffer is not held by this client, or this client doesn't exist 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in controller, do nothing. 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ControllerClient::ActiveBufferMap::iterator iter; 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!client || (iter = client->active_buffers.find(buffer_id)) == 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->active_buffers.end()) { 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = iter->second; 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->active_buffers.erase(iter); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer_pool_->RelinquishConsumerHold(buffer_id, 1); 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sync_point) 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&ReturnVideoFrame, frame, sync_point)); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const media::VideoCaptureFormat& 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VideoCaptureController::GetVideoCaptureFormat() const { 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return video_capture_format_; 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<media::VideoCaptureDevice::Client::Buffer> 3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer( 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::Format format, 3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const gfx::Size& size) { 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DoReserveOutputBuffer(format, size); 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData( 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint8* data, 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int length, 348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const VideoCaptureFormat& frame_format, 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int rotation, 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) { 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedData"); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!frame_format.IsValid()) 354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Chopped pixels in width/height in case video capture device has odd 357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // numbers for width/height. 358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int chopped_width = 0; 359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int chopped_height = 0; 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int new_unrotated_width = frame_format.frame_size.width(); 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int new_unrotated_height = frame_format.frame_size.height(); 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (new_unrotated_width & 1) { 364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) --new_unrotated_width; 365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) chopped_width = 1; 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (new_unrotated_height & 1) { 368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) --new_unrotated_height; 369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) chopped_height = 1; 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int destination_width = new_unrotated_width; 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int destination_height = new_unrotated_height; 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (rotation == 90 || rotation == 270) { 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) destination_width = new_unrotated_height; 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) destination_height = new_unrotated_width; 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Size dimensions(destination_width, destination_height); 379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!media::VideoFrame::IsValidConfig(media::VideoFrame::I420, 380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch dimensions, 381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch gfx::Rect(dimensions), 382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch dimensions)) { 383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 385c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<Buffer> buffer = 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DoReserveOutputBuffer(media::VideoFrame::I420, dimensions); 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!buffer.get()) 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8* yplane = NULL; 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool flip = false; 393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) yplane = reinterpret_cast<uint8*>(buffer->data()); 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint8* uplane = 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yplane + 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::PlaneAllocationSize( 397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::I420, media::VideoFrame::kYPlane, dimensions); 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint8* vplane = 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uplane + 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::PlaneAllocationSize( 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::I420, media::VideoFrame::kUPlane, dimensions); 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int yplane_stride = dimensions.width(); 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int uv_plane_stride = yplane_stride / 2; 40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int crop_x = 0; 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int crop_y = 0; 40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; 407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) libyuv::RotationMode rotation_mode = libyuv::kRotate0; 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (rotation == 90) 41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) rotation_mode = libyuv::kRotate90; 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else if (rotation == 180) 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) rotation_mode = libyuv::kRotate180; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else if (rotation == 270) 41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) rotation_mode = libyuv::kRotate270; 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (frame_format.pixel_format) { 41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_I420: 420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!chopped_width && !chopped_height); 42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_I420; 42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_YV12: 424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!chopped_width && !chopped_height); 42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_YV12; 42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_NV21: 428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!chopped_width && !chopped_height); 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin_colorspace = libyuv::FOURCC_NV21; 43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_YUY2: 432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!chopped_width && !chopped_height); 43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_YUY2; 43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_UYVY: 436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!chopped_width && !chopped_height); 43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_UYVY; 43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_RGB24: 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) origin_colorspace = libyuv::FOURCC_24BG; 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(wjia): Currently, for RGB24 on WIN, capture device always 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // passes in positive src_width and src_height. Remove this hardcoded 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // value when nagative src_height is supported. The negative src_height 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // indicates that vertical flipping is needed. 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flip = true; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 44858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_ARGB: 45058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_ARGB; 45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 45258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case media::PIXEL_FORMAT_MJPEG: 45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) origin_colorspace = libyuv::FOURCC_MJPG; 45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) default: 45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NOTREACHED(); 45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) libyuv::ConvertToI420(data, 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) length, 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) yplane, 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) yplane_stride, 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uplane, 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uv_plane_stride, 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) vplane, 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uv_plane_stride, 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) crop_x, 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) crop_y, 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame_format.frame_size.width(), 470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (flip ? -frame_format.frame_size.height() : 471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) frame_format.frame_size.height()), 472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new_unrotated_width, 473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new_unrotated_height, 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rotation_mode, 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) origin_colorspace); 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::WrapExternalPackedMemory( 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::I420, 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Rect(dimensions), 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions, 482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) yplane, 483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) media::VideoFrame::AllocationSize(media::VideoFrame::I420, 484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dimensions), 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::SharedMemory::NULLHandle(), 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta(), 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Closure()); 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(frame.get()); 489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VideoCaptureFormat format( 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch dimensions, frame_format.frame_rate, media::PIXEL_FORMAT_I420); 49258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BrowserThread::PostTask( 49358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BrowserThread::IO, 49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) FROM_HERE, 495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind( 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, 497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_, 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer, 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) format, 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame, 501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) timestamp)); 50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( 506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const scoped_refptr<Buffer>& buffer, 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const VideoCaptureFormat& buffer_format, 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame, 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks timestamp) { 510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::PostTask( 511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserThread::IO, 512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind( 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, 515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller_, 516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer, 517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_format, 518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame, 519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) timestamp)); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VideoCaptureController::VideoCaptureDeviceClient::OnError( 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& reason) { 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string log_message = base::StringPrintf( 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error on video capture: %s, OS message: %s", 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reason.c_str(), 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci logging::SystemErrorCodeToString( 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci logging::GetLastSystemErrorCode()).c_str()); 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(ERROR) << log_message; 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MediaStreamManager::SendMessageToNativeLog(log_message); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::IO, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void VideoCaptureController::VideoCaptureDeviceClient::OnLog( 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& message) { 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 541f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<media::VideoCaptureDevice::Client::Buffer> 542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer( 543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoFrame::Format format, 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Size& dimensions) { 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t frame_bytes = 0; 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (format == media::VideoFrame::NATIVE_TEXTURE) { 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(dimensions.width(), 0); 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(dimensions.height(), 0); 549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The capture pipeline expects I420 for now. 551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(format, media::VideoFrame::I420) 552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Non-I420 output buffer format " << format << " requested"; 553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame_bytes = media::VideoFrame::AllocationSize(format, dimensions); 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; 557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int buffer_id = 558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); 559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (buffer_id == VideoCaptureBufferPool::kInvalidId) 560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return NULL; 561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* data; 562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t size; 563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer_pool_->GetBufferInfo(buffer_id, &data, &size); 564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( 566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new PoolBuffer(buffer_pool_, buffer_id, data, size)); 567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { 5691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::IO, 5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, 5721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) controller_, buffer_id_to_drop)); 573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return output_buffer; 5767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureController::~VideoCaptureController() { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteContainerPointers(controller_clients_.begin(), 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_clients_.end()); 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_BOOLEAN("Media.VideoCapture.FramesReceived", frame_received_); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 584a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( 585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, 586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const media::VideoCaptureFormat& buffer_format, 587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame, 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks timestamp) { 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ControllerClients::iterator client_it = controller_clients_.begin(); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_it != controller_clients_.end(); ++client_it) { 5961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ControllerClient* client = *client_it; 59734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (client->session_closed || client->paused) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { 601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->event_handler->OnMailboxBufferReady(client->controller_id, 602a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->id(), 603a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *frame->mailbox_holder(), 604a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_format, 605a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timestamp); 606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 607a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_new_buffer = client->known_buffers.insert(buffer->id()).second; 608a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_new_buffer) { 609a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // On the first use of a buffer on a client, share the memory handle. 610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t memory_size = 0; 611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess( 612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->id(), client->render_process_handle, &memory_size); 613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->event_handler->OnBufferCreated( 614a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->controller_id, remote_handle, memory_size, buffer->id()); 615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->event_handler->OnBufferReady( 6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client->controller_id, buffer->id(), buffer_format, 6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame->visible_rect(), timestamp); 6201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool inserted = 623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client->active_buffers.insert(std::make_pair(buffer->id(), frame)) 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .second; 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id(); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!frame_received_) { 6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", 6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.frame_size.width()); 6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", 6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.frame_size.height()); 6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", 6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.frame_size.width(), 6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.frame_size.height()); 6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", 6391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.frame_rate); 6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.PixelFormat", 6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer_format.pixel_format, 6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::PIXEL_FORMAT_MAX); 6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci frame_received_ = true; 6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buffer_pool_->HoldForConsumers(buffer->id(), count); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void VideoCaptureController::DoErrorOnIOThread() { 650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 6511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state_ = VIDEO_CAPTURE_STATE_ERROR; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ControllerClients::iterator client_it = controller_clients_.begin(); 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_it != controller_clients_.end(); ++client_it) { 6551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ControllerClient* client = *client_it; 6561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (client->session_closed) 6571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) continue; 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) client->event_handler->OnError(client->controller_id); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void VideoCaptureController::DoBufferDestroyedOnIOThread( 6641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int buffer_id_to_drop) { 665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (ControllerClients::iterator client_it = controller_clients_.begin(); 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_it != controller_clients_.end(); ++client_it) { 6691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ControllerClient* client = *client_it; 6701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (client->session_closed) 6711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) continue; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (client->known_buffers.erase(buffer_id_to_drop)) { 6741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) client->event_handler->OnBufferDestroyed(client->controller_id, 6751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) buffer_id_to_drop); 6761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureController::ControllerClient* 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureController::FindClient( 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VideoCaptureControllerID& id, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoCaptureControllerEventHandler* handler, 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ControllerClients& clients) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ControllerClients::const_iterator client_it = clients.begin(); 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_it != clients.end(); ++client_it) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*client_it)->controller_id == id && 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*client_it)->event_handler == handler) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *client_it; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureController::ControllerClient* 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureController::FindClient( 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int session_id, 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ControllerClients& clients) { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ControllerClients::const_iterator client_it = clients.begin(); 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_it != clients.end(); ++client_it) { 701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ((*client_it)->session_id == session_id) { 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *client_it; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)int VideoCaptureController::GetClientCount() const { 709effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return controller_clients_.size(); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)int VideoCaptureController::GetActiveClientCount() const { 71434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 71534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) int active_client_count = 0; 71634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (ControllerClient* client : controller_clients_) { 71734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!client->paused) 71834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ++active_client_count; 71934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 72034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return active_client_count; 72134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 72234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 724