| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/pepper/pepper_video_capture_host.h" | 5 #include "content/renderer/pepper/pepper_video_capture_host.h" |
| 6 | 6 |
| 7 #include "content/renderer/pepper/host_globals.h" | 7 #include "content/renderer/pepper/host_globals.h" |
| 8 #include "content/renderer/pepper/pepper_media_device_manager.h" | 8 #include "content/renderer/pepper/pepper_media_device_manager.h" |
| 9 #include "content/renderer/pepper/pepper_platform_video_capture.h" | 9 #include "content/renderer/pepper/pepper_platform_video_capture.h" |
| 10 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" | 10 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 namespace content { | 35 namespace content { |
| 36 | 36 |
| 37 PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host, | 37 PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host, |
| 38 PP_Instance instance, | 38 PP_Instance instance, |
| 39 PP_Resource resource) | 39 PP_Resource resource) |
| 40 : ResourceHost(host->GetPpapiHost(), instance, resource), | 40 : ResourceHost(host->GetPpapiHost(), instance, resource), |
| 41 renderer_ppapi_host_(host), | 41 renderer_ppapi_host_(host), |
| 42 buffer_count_hint_(0), | 42 buffer_count_hint_(0), |
| 43 status_(PP_VIDEO_CAPTURE_STATUS_STOPPED), | 43 status_(PP_VIDEO_CAPTURE_STATUS_STOPPED), |
| 44 enumeration_helper_( | 44 enumeration_helper_(this, |
| 45 this, | 45 PepperMediaDeviceManager::GetForRenderView( |
| 46 PepperMediaDeviceManager::GetForRenderView( | 46 host->GetRenderViewForInstance(pp_instance())), |
| 47 host->GetRenderViewForInstance(pp_instance())), | 47 PP_DEVICETYPE_DEV_VIDEOCAPTURE, |
| 48 PP_DEVICETYPE_DEV_VIDEOCAPTURE, | 48 host->GetDocumentURL(instance)) {} |
| 49 host->GetDocumentURL(instance)) { | |
| 50 } | |
| 51 | 49 |
| 52 PepperVideoCaptureHost::~PepperVideoCaptureHost() { | 50 PepperVideoCaptureHost::~PepperVideoCaptureHost() { Close(); } |
| 53 Close(); | |
| 54 } | |
| 55 | 51 |
| 56 bool PepperVideoCaptureHost::Init() { | 52 bool PepperVideoCaptureHost::Init() { |
| 57 return !!renderer_ppapi_host_->GetPluginInstance(pp_instance()); | 53 return !!renderer_ppapi_host_->GetPluginInstance(pp_instance()); |
| 58 } | 54 } |
| 59 | 55 |
| 60 int32_t PepperVideoCaptureHost::OnResourceMessageReceived( | 56 int32_t PepperVideoCaptureHost::OnResourceMessageReceived( |
| 61 const IPC::Message& msg, | 57 const IPC::Message& msg, |
| 62 ppapi::host::HostMessageContext* context) { | 58 ppapi::host::HostMessageContext* context) { |
| 63 int32_t result = PP_ERROR_FAILED; | 59 int32_t result = PP_ERROR_FAILED; |
| 64 if (enumeration_helper_.HandleResourceMessage(msg, context, &result)) | 60 if (enumeration_helper_.HandleResourceMessage(msg, context, &result)) |
| 65 return result; | 61 return result; |
| 66 | 62 |
| 67 IPC_BEGIN_MESSAGE_MAP(PepperVideoCaptureHost, msg) | 63 IPC_BEGIN_MESSAGE_MAP(PepperVideoCaptureHost, msg) |
| 68 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | 64 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoCapture_Open, OnOpen) |
| 69 PpapiHostMsg_VideoCapture_Open, | 65 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoCapture_StartCapture, |
| 70 OnOpen) | 66 OnStartCapture) |
| 71 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | 67 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoCapture_ReuseBuffer, |
| 72 PpapiHostMsg_VideoCapture_StartCapture, | 68 OnReuseBuffer) |
| 73 OnStartCapture) | 69 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoCapture_StopCapture, |
| 74 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | 70 OnStopCapture) |
| 75 PpapiHostMsg_VideoCapture_ReuseBuffer, | 71 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoCapture_Close, OnClose) |
| 76 OnReuseBuffer) | |
| 77 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
| 78 PpapiHostMsg_VideoCapture_StopCapture, | |
| 79 OnStopCapture) | |
| 80 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
| 81 PpapiHostMsg_VideoCapture_Close, | |
| 82 OnClose) | |
| 83 IPC_END_MESSAGE_MAP() | 72 IPC_END_MESSAGE_MAP() |
| 84 return PP_ERROR_FAILED; | 73 return PP_ERROR_FAILED; |
| 85 } | 74 } |
| 86 | 75 |
| 87 void PepperVideoCaptureHost::OnInitialized(media::VideoCapture* capture, | 76 void PepperVideoCaptureHost::OnInitialized(media::VideoCapture* capture, |
| 88 bool succeeded) { | 77 bool succeeded) { |
| 89 DCHECK(capture == platform_video_capture_.get()); | 78 DCHECK(capture == platform_video_capture_.get()); |
| 90 | 79 |
| 91 if (succeeded) { | 80 if (succeeded) { |
| 92 open_reply_context_.params.set_result(PP_OK); | 81 open_reply_context_.params.set_result(PP_OK); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 119 // Today, the media layer only sends "1" as an error. | 108 // Today, the media layer only sends "1" as an error. |
| 120 DCHECK(error_code == 1); | 109 DCHECK(error_code == 1); |
| 121 PostErrorReply(); | 110 PostErrorReply(); |
| 122 } | 111 } |
| 123 | 112 |
| 124 void PepperVideoCaptureHost::PostErrorReply() { | 113 void PepperVideoCaptureHost::PostErrorReply() { |
| 125 // It either comes because some error was detected while starting (e.g. 2 | 114 // It either comes because some error was detected while starting (e.g. 2 |
| 126 // conflicting "master" resolution), or because the browser failed to start | 115 // conflicting "master" resolution), or because the browser failed to start |
| 127 // the capture. | 116 // the capture. |
| 128 SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, true); | 117 SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, true); |
| 129 host()->SendUnsolicitedReply(pp_resource(), | 118 host()->SendUnsolicitedReply( |
| 130 PpapiPluginMsg_VideoCapture_OnError(PP_ERROR_FAILED)); | 119 pp_resource(), PpapiPluginMsg_VideoCapture_OnError(PP_ERROR_FAILED)); |
| 131 } | 120 } |
| 132 | 121 |
| 133 void PepperVideoCaptureHost::OnRemoved(media::VideoCapture* capture) { | 122 void PepperVideoCaptureHost::OnRemoved(media::VideoCapture* capture) {} |
| 134 } | |
| 135 | 123 |
| 136 void PepperVideoCaptureHost::OnFrameReady( | 124 void PepperVideoCaptureHost::OnFrameReady( |
| 137 media::VideoCapture* capture, | 125 media::VideoCapture* capture, |
| 138 const scoped_refptr<media::VideoFrame>& frame) { | 126 const scoped_refptr<media::VideoFrame>& frame) { |
| 139 DCHECK(frame.get()); | 127 DCHECK(frame.get()); |
| 140 | 128 |
| 141 if (alloc_size_ != frame->coded_size()) { | 129 if (alloc_size_ != frame->coded_size()) { |
| 142 AllocBuffers(frame->coded_size(), capture->CaptureFrameRate()); | 130 AllocBuffers(frame->coded_size(), capture->CaptureFrameRate()); |
| 143 alloc_size_ = frame->coded_size(); | 131 alloc_size_ = frame->coded_size(); |
| 144 } | 132 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 161 const uint8* src = frame->data(j); | 149 const uint8* src = frame->data(j); |
| 162 const size_t row_bytes = frame->row_bytes(j); | 150 const size_t row_bytes = frame->row_bytes(j); |
| 163 const size_t src_stride = frame->stride(j); | 151 const size_t src_stride = frame->stride(j); |
| 164 for (int k = 0; k < frame->rows(j); ++k) { | 152 for (int k = 0; k < frame->rows(j); ++k) { |
| 165 memcpy(dst, src, row_bytes); | 153 memcpy(dst, src, row_bytes); |
| 166 dst += row_bytes; | 154 dst += row_bytes; |
| 167 src += src_stride; | 155 src += src_stride; |
| 168 } | 156 } |
| 169 } | 157 } |
| 170 buffers_[i].in_use = true; | 158 buffers_[i].in_use = true; |
| 171 host()->SendUnsolicitedReply(pp_resource(), | 159 host()->SendUnsolicitedReply( |
| 172 PpapiPluginMsg_VideoCapture_OnBufferReady(i)); | 160 pp_resource(), PpapiPluginMsg_VideoCapture_OnBufferReady(i)); |
| 173 return; | 161 return; |
| 174 } | 162 } |
| 175 } | 163 } |
| 176 } | 164 } |
| 177 | 165 |
| 178 void PepperVideoCaptureHost::AllocBuffers( | 166 void PepperVideoCaptureHost::AllocBuffers(const gfx::Size& resolution, |
| 179 const gfx::Size& resolution, | 167 int frame_rate) { |
| 180 int frame_rate) { | |
| 181 PP_VideoCaptureDeviceInfo_Dev info = { | 168 PP_VideoCaptureDeviceInfo_Dev info = { |
| 182 static_cast<uint32_t>(resolution.width()), | 169 static_cast<uint32_t>(resolution.width()), |
| 183 static_cast<uint32_t>(resolution.height()), | 170 static_cast<uint32_t>(resolution.height()), |
| 184 static_cast<uint32_t>(frame_rate) | 171 static_cast<uint32_t>(frame_rate)}; |
| 185 }; | |
| 186 ReleaseBuffers(); | 172 ReleaseBuffers(); |
| 187 | 173 |
| 188 const size_t size = media::VideoFrame::AllocationSize( | 174 const size_t size = media::VideoFrame::AllocationSize( |
| 189 media::VideoFrame::I420, gfx::Size(info.width, info.height)); | 175 media::VideoFrame::I420, gfx::Size(info.width, info.height)); |
| 190 | 176 |
| 191 ppapi::proxy::ResourceMessageReplyParams params(pp_resource(), 0); | 177 ppapi::proxy::ResourceMessageReplyParams params(pp_resource(), 0); |
| 192 | 178 |
| 193 // Allocate buffers. We keep a reference to them, that is released in | 179 // Allocate buffers. We keep a reference to them, that is released in |
| 194 // ReleaseBuffers. In the mean time, we prepare the resource and handle here | 180 // ReleaseBuffers. In the mean time, we prepare the resource and handle here |
| 195 // for sending below. | 181 // for sending below. |
| 196 std::vector<HostResource> buffer_host_resources; | 182 std::vector<HostResource> buffer_host_resources; |
| 197 buffers_.reserve(buffer_count_hint_); | 183 buffers_.reserve(buffer_count_hint_); |
| 198 ppapi::ResourceTracker* tracker = | 184 ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker(); |
| 199 HostGlobals::Get()->GetResourceTracker(); | |
| 200 ppapi::proxy::HostDispatcher* dispatcher = | 185 ppapi::proxy::HostDispatcher* dispatcher = |
| 201 ppapi::proxy::HostDispatcher::GetForInstance(pp_instance()); | 186 ppapi::proxy::HostDispatcher::GetForInstance(pp_instance()); |
| 202 for (size_t i = 0; i < buffer_count_hint_; ++i) { | 187 for (size_t i = 0; i < buffer_count_hint_; ++i) { |
| 203 PP_Resource res = PPB_Buffer_Impl::Create(pp_instance(), size); | 188 PP_Resource res = PPB_Buffer_Impl::Create(pp_instance(), size); |
| 204 if (!res) | 189 if (!res) |
| 205 break; | 190 break; |
| 206 | 191 |
| 207 EnterResourceNoLock<PPB_Buffer_API> enter(res, true); | 192 EnterResourceNoLock<PPB_Buffer_API> enter(res, true); |
| 208 DCHECK(enter.succeeded()); | 193 DCHECK(enter.succeeded()); |
| 209 | 194 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 237 // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle, | 222 // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle, |
| 238 // those casts are ugly. | 223 // those casts are ugly. |
| 239 base::PlatformFile platform_file = | 224 base::PlatformFile platform_file = |
| 240 #if defined(OS_WIN) | 225 #if defined(OS_WIN) |
| 241 reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle)); | 226 reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle)); |
| 242 #elif defined(OS_POSIX) | 227 #elif defined(OS_POSIX) |
| 243 handle; | 228 handle; |
| 244 #else | 229 #else |
| 245 #error Not implemented. | 230 #error Not implemented. |
| 246 #endif | 231 #endif |
| 247 params.AppendHandle( | 232 params.AppendHandle(ppapi::proxy::SerializedHandle( |
| 248 ppapi::proxy::SerializedHandle( | 233 dispatcher->ShareHandleWithRemote(platform_file, false), size)); |
| 249 dispatcher->ShareHandleWithRemote(platform_file, false), | |
| 250 size)); | |
| 251 } | 234 } |
| 252 } | 235 } |
| 253 | 236 |
| 254 if (buffers_.empty()) { | 237 if (buffers_.empty()) { |
| 255 // We couldn't allocate/map buffers at all. Send an error and stop the | 238 // We couldn't allocate/map buffers at all. Send an error and stop the |
| 256 // capture. | 239 // capture. |
| 257 SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPING, true); | 240 SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPING, true); |
| 258 platform_video_capture_->StopCapture(this); | 241 platform_video_capture_->StopCapture(this); |
| 259 PostErrorReply(); | 242 PostErrorReply(); |
| 260 return; | 243 return; |
| 261 } | 244 } |
| 262 | 245 |
| 263 host()->Send(new PpapiPluginMsg_ResourceReply( | 246 host()->Send( |
| 264 params, PpapiPluginMsg_VideoCapture_OnDeviceInfo( | 247 new PpapiPluginMsg_ResourceReply(params, |
| 265 info, buffer_host_resources, size))); | 248 PpapiPluginMsg_VideoCapture_OnDeviceInfo( |
| 249 info, buffer_host_resources, size))); |
| 266 } | 250 } |
| 267 | 251 |
| 268 int32_t PepperVideoCaptureHost::OnOpen( | 252 int32_t PepperVideoCaptureHost::OnOpen( |
| 269 ppapi::host::HostMessageContext* context, | 253 ppapi::host::HostMessageContext* context, |
| 270 const std::string& device_id, | 254 const std::string& device_id, |
| 271 const PP_VideoCaptureDeviceInfo_Dev& requested_info, | 255 const PP_VideoCaptureDeviceInfo_Dev& requested_info, |
| 272 uint32_t buffer_count) { | 256 uint32_t buffer_count) { |
| 273 if (platform_video_capture_.get()) | 257 if (platform_video_capture_.get()) |
| 274 return PP_ERROR_FAILED; | 258 return PP_ERROR_FAILED; |
| 275 | 259 |
| 276 SetRequestedInfo(requested_info, buffer_count); | 260 SetRequestedInfo(requested_info, buffer_count); |
| 277 | 261 |
| 278 GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance()); | 262 GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance()); |
| 279 if (!document_url.is_valid()) | 263 if (!document_url.is_valid()) |
| 280 return PP_ERROR_FAILED; | 264 return PP_ERROR_FAILED; |
| 281 | 265 |
| 282 RenderViewImpl* render_view = static_cast<RenderViewImpl*>( | 266 RenderViewImpl* render_view = static_cast<RenderViewImpl*>( |
| 283 renderer_ppapi_host_->GetRenderViewForInstance(pp_instance())); | 267 renderer_ppapi_host_->GetRenderViewForInstance(pp_instance())); |
| 284 | 268 |
| 285 platform_video_capture_ = new PepperPlatformVideoCapture( | 269 platform_video_capture_ = new PepperPlatformVideoCapture( |
| 286 render_view->AsWeakPtr(), device_id, | 270 render_view->AsWeakPtr(), device_id, document_url, this); |
| 287 document_url, this); | |
| 288 | 271 |
| 289 open_reply_context_ = context->MakeReplyMessageContext(); | 272 open_reply_context_ = context->MakeReplyMessageContext(); |
| 290 | 273 |
| 291 return PP_OK_COMPLETIONPENDING; | 274 return PP_OK_COMPLETIONPENDING; |
| 292 } | 275 } |
| 293 | 276 |
| 294 int32_t PepperVideoCaptureHost::OnStartCapture( | 277 int32_t PepperVideoCaptureHost::OnStartCapture( |
| 295 ppapi::host::HostMessageContext* context) { | 278 ppapi::host::HostMessageContext* context) { |
| 296 if (!SetStatus(PP_VIDEO_CAPTURE_STATUS_STARTING, false) || | 279 if (!SetStatus(PP_VIDEO_CAPTURE_STATUS_STARTING, false) || |
| 297 !platform_video_capture_.get()) | 280 !platform_video_capture_.get()) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker(); | 334 ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker(); |
| 352 for (size_t i = 0; i < buffers_.size(); ++i) { | 335 for (size_t i = 0; i < buffers_.size(); ++i) { |
| 353 buffers_[i].buffer->Unmap(); | 336 buffers_[i].buffer->Unmap(); |
| 354 tracker->ReleaseResource(buffers_[i].buffer->pp_resource()); | 337 tracker->ReleaseResource(buffers_[i].buffer->pp_resource()); |
| 355 } | 338 } |
| 356 buffers_.clear(); | 339 buffers_.clear(); |
| 357 } | 340 } |
| 358 | 341 |
| 359 void PepperVideoCaptureHost::SendStatus() { | 342 void PepperVideoCaptureHost::SendStatus() { |
| 360 host()->SendUnsolicitedReply(pp_resource(), | 343 host()->SendUnsolicitedReply(pp_resource(), |
| 361 PpapiPluginMsg_VideoCapture_OnStatus(status_)); | 344 PpapiPluginMsg_VideoCapture_OnStatus(status_)); |
| 362 } | 345 } |
| 363 | 346 |
| 364 void PepperVideoCaptureHost::SetRequestedInfo( | 347 void PepperVideoCaptureHost::SetRequestedInfo( |
| 365 const PP_VideoCaptureDeviceInfo_Dev& device_info, | 348 const PP_VideoCaptureDeviceInfo_Dev& device_info, |
| 366 uint32_t buffer_count) { | 349 uint32_t buffer_count) { |
| 367 // Clamp the buffer count to between 1 and |kMaxBuffers|. | 350 // Clamp the buffer count to between 1 and |kMaxBuffers|. |
| 368 buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers); | 351 buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers); |
| 369 // Clamp the frame rate to between 1 and |kMaxFramesPerSecond - 1|. | 352 // Clamp the frame rate to between 1 and |kMaxFramesPerSecond - 1|. |
| 370 int frames_per_second = | 353 int frames_per_second = |
| 371 std::min(std::max(device_info.frames_per_second, 1U), | 354 std::min(std::max(device_info.frames_per_second, 1U), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 } | 409 } |
| 427 break; | 410 break; |
| 428 } | 411 } |
| 429 } | 412 } |
| 430 | 413 |
| 431 status_ = status; | 414 status_ = status; |
| 432 return true; | 415 return true; |
| 433 } | 416 } |
| 434 | 417 |
| 435 PepperVideoCaptureHost::BufferInfo::BufferInfo() | 418 PepperVideoCaptureHost::BufferInfo::BufferInfo() |
| 436 : in_use(false), | 419 : in_use(false), data(NULL), buffer() {} |
| 437 data(NULL), | |
| 438 buffer() { | |
| 439 } | |
| 440 | 420 |
| 441 PepperVideoCaptureHost::BufferInfo::~BufferInfo() { | 421 PepperVideoCaptureHost::BufferInfo::~BufferInfo() {} |
| 442 } | |
| 443 | 422 |
| 444 } // namespace content | 423 } // namespace content |
| OLD | NEW |