Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_host.cc
blob17f56b550e67edb305a5a0364b971e1f3be5e85e
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.
5 #include "content/browser/renderer_host/media/video_capture_host.h"
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "content/browser/browser_main_loop.h"
11 #include "content/browser/renderer_host/media/media_stream_manager.h"
12 #include "content/browser/renderer_host/media/video_capture_manager.h"
13 #include "content/common/media/video_capture_messages.h"
15 namespace content {
17 struct VideoCaptureHost::Entry {
18 Entry(VideoCaptureController* controller)
19 : controller(controller) {}
21 ~Entry() {}
23 scoped_refptr<VideoCaptureController> controller;
26 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
27 : media_stream_manager_(media_stream_manager) {
30 VideoCaptureHost::~VideoCaptureHost() {}
32 void VideoCaptureHost::OnChannelClosing() {
33 BrowserMessageFilter::OnChannelClosing();
35 // Since the IPC channel is gone, close all requested VideCaptureDevices.
36 for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
37 VideoCaptureController* controller = it->second->controller.get();
38 if (controller) {
39 VideoCaptureControllerID controller_id(it->first);
40 controller->StopCapture(controller_id, this);
41 media_stream_manager_->video_capture_manager()->RemoveController(
42 controller, this);
45 STLDeleteValues(&entries_);
48 void VideoCaptureHost::OnDestruct() const {
49 BrowserThread::DeleteOnIOThread::Destruct(this);
52 ///////////////////////////////////////////////////////////////////////////////
54 // Implements VideoCaptureControllerEventHandler.
55 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) {
56 DVLOG(1) << "VideoCaptureHost::OnError";
57 BrowserThread::PostTask(
58 BrowserThread::IO, FROM_HERE,
59 base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread,
60 this, controller_id));
63 void VideoCaptureHost::OnBufferCreated(
64 const VideoCaptureControllerID& controller_id,
65 base::SharedMemoryHandle handle,
66 int length,
67 int buffer_id) {
68 BrowserThread::PostTask(
69 BrowserThread::IO, FROM_HERE,
70 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread,
71 this, controller_id, handle, length, buffer_id));
74 void VideoCaptureHost::OnBufferReady(
75 const VideoCaptureControllerID& controller_id,
76 int buffer_id,
77 base::Time timestamp) {
78 BrowserThread::PostTask(
79 BrowserThread::IO, FROM_HERE,
80 base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
81 this, controller_id, buffer_id, timestamp));
84 void VideoCaptureHost::OnFrameInfo(
85 const VideoCaptureControllerID& controller_id,
86 int width,
87 int height,
88 int frame_per_second) {
89 BrowserThread::PostTask(
90 BrowserThread::IO, FROM_HERE,
91 base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread,
92 this, controller_id, width, height, frame_per_second));
95 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
96 DVLOG(1) << "VideoCaptureHost::OnEnded";
97 BrowserThread::PostTask(
98 BrowserThread::IO, FROM_HERE,
99 base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id));
102 void VideoCaptureHost::DoSendNewBufferOnIOThread(
103 const VideoCaptureControllerID& controller_id,
104 base::SharedMemoryHandle handle,
105 int length,
106 int buffer_id) {
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
109 if (entries_.find(controller_id) == entries_.end())
110 return;
112 Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle,
113 length, buffer_id));
116 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
117 const VideoCaptureControllerID& controller_id,
118 int buffer_id, base::Time timestamp) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
121 if (entries_.find(controller_id) == entries_.end())
122 return;
124 Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id,
125 timestamp));
128 void VideoCaptureHost::DoHandleErrorOnIOThread(
129 const VideoCaptureControllerID& controller_id) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
132 if (entries_.find(controller_id) == entries_.end())
133 return;
135 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
136 VIDEO_CAPTURE_STATE_ERROR));
137 DeleteVideoCaptureControllerOnIOThread(controller_id);
140 void VideoCaptureHost::DoEndedOnIOThread(
141 const VideoCaptureControllerID& controller_id) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
143 DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
144 if (entries_.find(controller_id) == entries_.end())
145 return;
147 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
148 VIDEO_CAPTURE_STATE_ENDED));
149 DeleteVideoCaptureControllerOnIOThread(controller_id);
152 void VideoCaptureHost::DoSendFrameInfoOnIOThread(
153 const VideoCaptureControllerID& controller_id,
154 int width, int height, int frame_per_second) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157 if (entries_.find(controller_id) == entries_.end())
158 return;
160 media::VideoCaptureParams params;
161 params.width = width;
162 params.height = height;
163 params.frame_per_second = frame_per_second;
164 Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params));
165 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
166 VIDEO_CAPTURE_STATE_STARTED));
169 ///////////////////////////////////////////////////////////////////////////////
170 // IPC Messages handler.
171 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
172 bool* message_was_ok) {
173 bool handled = true;
174 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok)
175 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
176 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
177 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
178 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer)
179 IPC_MESSAGE_UNHANDLED(handled = false)
180 IPC_END_MESSAGE_MAP_EX()
182 return handled;
185 void VideoCaptureHost::OnStartCapture(int device_id,
186 const media::VideoCaptureParams& params) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
188 DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
189 << ", (" << params.width
190 << ", " << params.height
191 << ", " << params.frame_per_second
192 << ", " << params.session_id
193 << ")";
194 VideoCaptureControllerID controller_id(device_id);
195 DCHECK(entries_.find(controller_id) == entries_.end());
197 entries_[controller_id] = new Entry(NULL);
198 media_stream_manager_->video_capture_manager()->AddController(
199 params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this,
200 device_id, params));
203 void VideoCaptureHost::OnControllerAdded(
204 int device_id, const media::VideoCaptureParams& params,
205 VideoCaptureController* controller) {
206 BrowserThread::PostTask(
207 BrowserThread::IO, FROM_HERE,
208 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
209 this, device_id, params, make_scoped_refptr(controller)));
212 void VideoCaptureHost::DoControllerAddedOnIOThread(
213 int device_id, const media::VideoCaptureParams params,
214 VideoCaptureController* controller) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
216 VideoCaptureControllerID controller_id(device_id);
217 EntryMap::iterator it = entries_.find(controller_id);
218 if (it == entries_.end()) {
219 if (controller) {
220 media_stream_manager_->video_capture_manager()->RemoveController(
221 controller, this);
223 return;
226 if (controller == NULL) {
227 Send(new VideoCaptureMsg_StateChanged(device_id,
228 VIDEO_CAPTURE_STATE_ERROR));
229 delete it->second;
230 entries_.erase(controller_id);
231 return;
234 it->second->controller = controller;
235 controller->StartCapture(controller_id, this, peer_handle(), params);
238 void VideoCaptureHost::OnStopCapture(int device_id) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
242 VideoCaptureControllerID controller_id(device_id);
244 Send(new VideoCaptureMsg_StateChanged(device_id,
245 VIDEO_CAPTURE_STATE_STOPPED));
246 DeleteVideoCaptureControllerOnIOThread(controller_id);
249 void VideoCaptureHost::OnPauseCapture(int device_id) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
251 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
252 // Not used.
253 Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
256 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
259 VideoCaptureControllerID controller_id(device_id);
260 EntryMap::iterator it = entries_.find(controller_id);
261 if (it != entries_.end()) {
262 scoped_refptr<VideoCaptureController> controller = it->second->controller;
263 if (controller.get())
264 controller->ReturnBuffer(controller_id, this, buffer_id);
268 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
269 const VideoCaptureControllerID& controller_id) {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
272 EntryMap::iterator it = entries_.find(controller_id);
273 if (it == entries_.end())
274 return;
276 VideoCaptureController* controller = it->second->controller.get();
277 if (controller) {
278 controller->StopCapture(controller_id, this);
279 media_stream_manager_->video_capture_manager()->RemoveController(
280 controller, this);
282 delete it->second;
283 entries_.erase(controller_id);
286 } // namespace content