• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 "content/browser/renderer_host/media/video_capture_host.h"
6 
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "content/browser/browser_main_loop.h"
10 #include "content/browser/renderer_host/media/media_stream_manager.h"
11 #include "content/browser/renderer_host/media/video_capture_manager.h"
12 #include "content/common/media/video_capture_messages.h"
13 
14 namespace content {
15 
VideoCaptureHost(MediaStreamManager * media_stream_manager)16 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
17     : media_stream_manager_(media_stream_manager) {
18 }
19 
~VideoCaptureHost()20 VideoCaptureHost::~VideoCaptureHost() {}
21 
OnChannelClosing()22 void VideoCaptureHost::OnChannelClosing() {
23   // Since the IPC channel is gone, close all requested VideoCaptureDevices.
24   for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
25     const base::WeakPtr<VideoCaptureController>& controller = it->second;
26     if (controller) {
27       VideoCaptureControllerID controller_id(it->first);
28       media_stream_manager_->video_capture_manager()->StopCaptureForClient(
29           controller.get(), controller_id, this);
30     }
31   }
32 }
33 
OnDestruct() const34 void VideoCaptureHost::OnDestruct() const {
35   BrowserThread::DeleteOnIOThread::Destruct(this);
36 }
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 
40 // Implements VideoCaptureControllerEventHandler.
OnError(const VideoCaptureControllerID & controller_id)41 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) {
42   DVLOG(1) << "VideoCaptureHost::OnError";
43   BrowserThread::PostTask(
44       BrowserThread::IO, FROM_HERE,
45       base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread,
46                  this, controller_id));
47 }
48 
OnBufferCreated(const VideoCaptureControllerID & controller_id,base::SharedMemoryHandle handle,int length,int buffer_id)49 void VideoCaptureHost::OnBufferCreated(
50     const VideoCaptureControllerID& controller_id,
51     base::SharedMemoryHandle handle,
52     int length,
53     int buffer_id) {
54   BrowserThread::PostTask(
55       BrowserThread::IO, FROM_HERE,
56       base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread,
57                  this, controller_id, handle, length, buffer_id));
58 }
59 
OnBufferDestroyed(const VideoCaptureControllerID & controller_id,int buffer_id)60 void VideoCaptureHost::OnBufferDestroyed(
61     const VideoCaptureControllerID& controller_id,
62     int buffer_id) {
63   BrowserThread::PostTask(
64       BrowserThread::IO, FROM_HERE,
65       base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread,
66                  this, controller_id, buffer_id));
67 }
68 
OnBufferReady(const VideoCaptureControllerID & controller_id,int buffer_id,base::Time timestamp,const media::VideoCaptureFormat & frame_format)69 void VideoCaptureHost::OnBufferReady(
70     const VideoCaptureControllerID& controller_id,
71     int buffer_id,
72     base::Time timestamp,
73     const media::VideoCaptureFormat& frame_format) {
74   BrowserThread::PostTask(
75       BrowserThread::IO, FROM_HERE,
76       base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
77                  this, controller_id, buffer_id, timestamp,
78                  frame_format));
79 }
80 
OnEnded(const VideoCaptureControllerID & controller_id)81 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
82   DVLOG(1) << "VideoCaptureHost::OnEnded";
83   BrowserThread::PostTask(
84       BrowserThread::IO, FROM_HERE,
85       base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id));
86 }
87 
DoSendNewBufferOnIOThread(const VideoCaptureControllerID & controller_id,base::SharedMemoryHandle handle,int length,int buffer_id)88 void VideoCaptureHost::DoSendNewBufferOnIOThread(
89     const VideoCaptureControllerID& controller_id,
90     base::SharedMemoryHandle handle,
91     int length,
92     int buffer_id) {
93   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
94 
95   if (entries_.find(controller_id) == entries_.end())
96     return;
97 
98   Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle,
99                                      length, buffer_id));
100 }
101 
DoSendFreeBufferOnIOThread(const VideoCaptureControllerID & controller_id,int buffer_id)102 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
103     const VideoCaptureControllerID& controller_id,
104     int buffer_id) {
105   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
106 
107   if (entries_.find(controller_id) == entries_.end())
108     return;
109 
110   Send(new VideoCaptureMsg_FreeBuffer(controller_id.device_id, buffer_id));
111 }
112 
DoSendFilledBufferOnIOThread(const VideoCaptureControllerID & controller_id,int buffer_id,base::Time timestamp,const media::VideoCaptureFormat & format)113 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
114     const VideoCaptureControllerID& controller_id,
115     int buffer_id, base::Time timestamp,
116     const media::VideoCaptureFormat& format) {
117   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
118 
119   if (entries_.find(controller_id) == entries_.end())
120     return;
121 
122   Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id,
123                                        timestamp, format));
124 }
125 
DoHandleErrorOnIOThread(const VideoCaptureControllerID & controller_id)126 void VideoCaptureHost::DoHandleErrorOnIOThread(
127     const VideoCaptureControllerID& controller_id) {
128   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
129 
130   if (entries_.find(controller_id) == entries_.end())
131     return;
132 
133   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
134                                         VIDEO_CAPTURE_STATE_ERROR));
135   DeleteVideoCaptureControllerOnIOThread(controller_id);
136 }
137 
DoEndedOnIOThread(const VideoCaptureControllerID & controller_id)138 void VideoCaptureHost::DoEndedOnIOThread(
139     const VideoCaptureControllerID& controller_id) {
140   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
141   DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
142   if (entries_.find(controller_id) == entries_.end())
143     return;
144 
145   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
146                                         VIDEO_CAPTURE_STATE_ENDED));
147   DeleteVideoCaptureControllerOnIOThread(controller_id);
148 }
149 
150 ///////////////////////////////////////////////////////////////////////////////
151 // IPC Messages handler.
OnMessageReceived(const IPC::Message & message,bool * message_was_ok)152 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
153                                          bool* message_was_ok) {
154   bool handled = true;
155   IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok)
156     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
157     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
158     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
159     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer)
160     IPC_MESSAGE_UNHANDLED(handled = false)
161   IPC_END_MESSAGE_MAP_EX()
162 
163   return handled;
164 }
165 
OnStartCapture(int device_id,media::VideoCaptureSessionId session_id,const media::VideoCaptureParams & params)166 void VideoCaptureHost::OnStartCapture(int device_id,
167                                       media::VideoCaptureSessionId session_id,
168                                       const media::VideoCaptureParams& params) {
169   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
170   DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
171            << " session_id=" << session_id
172            << ", device_id=" << device_id
173            << ", format=" << params.requested_format.frame_size.ToString()
174            << "@" << params.requested_format.frame_rate
175            << " (" << (params.allow_resolution_change ? "variable" : "constant")
176            << ")";
177   VideoCaptureControllerID controller_id(device_id);
178   DCHECK(entries_.find(controller_id) == entries_.end());
179 
180   entries_[controller_id] = base::WeakPtr<VideoCaptureController>();
181   media_stream_manager_->video_capture_manager()->StartCaptureForClient(
182       session_id,
183       params,
184       PeerHandle(),
185       controller_id,
186       this,
187       base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
188 }
189 
OnControllerAdded(int device_id,const base::WeakPtr<VideoCaptureController> & controller)190 void VideoCaptureHost::OnControllerAdded(
191     int device_id,
192     const base::WeakPtr<VideoCaptureController>& controller) {
193   BrowserThread::PostTask(
194       BrowserThread::IO,
195       FROM_HERE,
196       base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
197                  this,
198                  device_id,
199                  controller));
200 }
201 
DoControllerAddedOnIOThread(int device_id,const base::WeakPtr<VideoCaptureController> & controller)202 void VideoCaptureHost::DoControllerAddedOnIOThread(
203     int device_id,
204     const base::WeakPtr<VideoCaptureController>& controller) {
205   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
206   VideoCaptureControllerID controller_id(device_id);
207   EntryMap::iterator it = entries_.find(controller_id);
208   if (it == entries_.end()) {
209     if (controller) {
210       media_stream_manager_->video_capture_manager()->StopCaptureForClient(
211           controller.get(), controller_id, this);
212     }
213     return;
214   }
215 
216   if (!controller) {
217     Send(new VideoCaptureMsg_StateChanged(device_id,
218                                           VIDEO_CAPTURE_STATE_ERROR));
219     entries_.erase(controller_id);
220     return;
221   }
222 
223   DCHECK(!it->second);
224   it->second = controller;
225 }
226 
OnStopCapture(int device_id)227 void VideoCaptureHost::OnStopCapture(int device_id) {
228   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229   DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
230 
231   VideoCaptureControllerID controller_id(device_id);
232 
233   Send(new VideoCaptureMsg_StateChanged(device_id,
234                                         VIDEO_CAPTURE_STATE_STOPPED));
235   DeleteVideoCaptureControllerOnIOThread(controller_id);
236 }
237 
OnPauseCapture(int device_id)238 void VideoCaptureHost::OnPauseCapture(int device_id) {
239   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240   DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
241   // Not used.
242   Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
243 }
244 
OnReceiveEmptyBuffer(int device_id,int buffer_id)245 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
246   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
247 
248   VideoCaptureControllerID controller_id(device_id);
249   EntryMap::iterator it = entries_.find(controller_id);
250   if (it != entries_.end()) {
251     const base::WeakPtr<VideoCaptureController>& controller = it->second;
252     if (controller)
253       controller->ReturnBuffer(controller_id, this, buffer_id);
254   }
255 }
256 
DeleteVideoCaptureControllerOnIOThread(const VideoCaptureControllerID & controller_id)257 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
258     const VideoCaptureControllerID& controller_id) {
259   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
260 
261   EntryMap::iterator it = entries_.find(controller_id);
262   if (it == entries_.end())
263     return;
264 
265   if (it->second) {
266     media_stream_manager_->video_capture_manager()->StopCaptureForClient(
267         it->second.get(), controller_id, this);
268   }
269   entries_.erase(it);
270 }
271 
272 }  // namespace content
273