Chromium Code Reviews| Index: content/renderer/pepper/pepper_video_source_host.cc |
| diff --git a/content/renderer/pepper/pepper_video_source_host.cc b/content/renderer/pepper/pepper_video_source_host.cc |
| index 462c8aca537a2ba9e2749600bf9bad3514b63ee2..a97ca646c0bfae809a977da3a63acbde4da54ec4 100644 |
| --- a/content/renderer/pepper/pepper_video_source_host.cc |
| +++ b/content/renderer/pepper/pepper_video_source_host.cc |
| @@ -26,6 +26,39 @@ using ppapi::host::ReplyMessageContext; |
| namespace content { |
| +PepperVideoSourceHost::FrameReceiver::FrameReceiver( |
| + const base::WeakPtr<PepperVideoSourceHost>& host) |
| + : host_(host), |
| + main_message_loop_proxy_(base::MessageLoopProxy::current()) { |
| +} |
| + |
| +PepperVideoSourceHost::FrameReceiver::~FrameReceiver() { |
| +} |
| + |
| +bool PepperVideoSourceHost::FrameReceiver::GotFrame( |
| + cricket::VideoFrame* frame) { |
| + // It's not safe to access the host from this thread, so post a task to our |
| + // main thread to transfer the new frame. |
| + main_message_loop_proxy_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&FrameReceiver::OnGotFrame, |
| + this, |
| + base::Passed(scoped_ptr<cricket::VideoFrame>(frame)))); |
| + |
| + return true; |
| +} |
| + |
| +void PepperVideoSourceHost::FrameReceiver::OnGotFrame( |
| + scoped_ptr<cricket::VideoFrame> frame) { |
| + if (host_) { |
| + // Take ownership of the new frame, and possibly delete any unsent one. |
| + host_->last_frame_.swap(frame); |
| + |
| + if (host_->get_frame_pending_) |
| + host_->SendGetFrameReply(); |
| + } |
| +} |
| + |
| PepperVideoSourceHost::PepperVideoSourceHost( |
| RendererPpapiHost* host, |
| PP_Instance instance, |
| @@ -33,8 +66,8 @@ PepperVideoSourceHost::PepperVideoSourceHost( |
| : ResourceHost(host->GetPpapiHost(), instance, resource), |
| renderer_ppapi_host_(host), |
| weak_factory_(this), |
| - main_message_loop_proxy_(base::MessageLoopProxy::current()), |
| source_handler_(new content::VideoSourceHandler(NULL)), |
| + frame_receiver_(new FrameReceiver(weak_factory_.GetWeakPtr())), |
| get_frame_pending_(false) { |
| } |
| @@ -56,37 +89,13 @@ int32_t PepperVideoSourceHost::OnResourceMessageReceived( |
| return PP_ERROR_FAILED; |
| } |
| -bool PepperVideoSourceHost::GotFrame(cricket::VideoFrame* frame) { |
| - // It's not safe to access this on another thread, so post a task to our |
| - // main thread to transfer the new frame. |
| - main_message_loop_proxy_->PostTask( |
| - FROM_HERE, |
| - base::Bind(&PepperVideoSourceHost::OnGotFrame, |
| - weak_factory_.GetWeakPtr(), |
| - base::Passed(scoped_ptr<cricket::VideoFrame>(frame)))); |
| - |
| - return true; |
| -} |
| - |
| -void PepperVideoSourceHost::OnGotFrame(scoped_ptr<cricket::VideoFrame> frame) { |
| - // Take ownership of the new frame, and possibly delete any unsent one. |
| - last_frame_.swap(frame); |
| - |
| - if (get_frame_pending_) { |
| - ppapi::HostResource image_data_resource; |
| - PP_TimeTicks timestamp = 0; |
| - int32_t result = ConvertFrame(&image_data_resource, ×tamp); |
| - SendFrame(image_data_resource, timestamp, result); |
| - } |
| -} |
| - |
| int32_t PepperVideoSourceHost::OnHostMsgOpen(HostMessageContext* context, |
| const std::string& stream_url) { |
| GURL gurl(stream_url); |
| if (!gurl.is_valid()) |
| return PP_ERROR_BADARGUMENT; |
| - if (!source_handler_->Open(gurl.spec(), this)) |
| + if (!source_handler_->Open(gurl.spec(), frame_receiver_.get())) |
| return PP_ERROR_BADARGUMENT; |
| stream_url_ = gurl.spec(); |
| @@ -107,18 +116,9 @@ int32_t PepperVideoSourceHost::OnHostMsgGetFrame( |
| reply_context_ = context->MakeReplyMessageContext(); |
| get_frame_pending_ = true; |
| - // If a frame is ready, try to convert it and reply. |
| - if (last_frame_.get()) { |
| - ppapi::HostResource image_data_resource; |
| - PP_TimeTicks timestamp = 0; |
| - int32_t result = ConvertFrame(&image_data_resource, ×tamp); |
| - if (result == PP_OK) { |
| - SendFrame(image_data_resource, timestamp, result); |
| - } else { |
| - reply_context_ = ppapi::host::ReplyMessageContext(); |
| - return result; |
| - } |
| - } |
| + // If a frame is ready, try to convert it and send the reply. |
| + if (last_frame_.get()) |
| + SendGetFrameReply(); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| @@ -128,16 +128,14 @@ int32_t PepperVideoSourceHost::OnHostMsgClose(HostMessageContext* context) { |
| return PP_OK; |
| } |
| -int32_t PepperVideoSourceHost::ConvertFrame( |
| - ppapi::HostResource* image_data_resource, |
| - PP_TimeTicks* timestamp) { |
| +void PepperVideoSourceHost::SendGetFrameReply() { |
|
raymes
2013/05/10 15:14:48
I think the state is a little hard to follow, alth
bbudge
2013/05/10 17:38:21
Done.
|
| DCHECK(last_frame_.get()); |
| scoped_ptr<cricket::VideoFrame> frame(last_frame_.release()); |
| int32_t width = base::checked_numeric_cast<int32_t>(frame->GetWidth()); |
| int32_t height = base::checked_numeric_cast<int32_t>(frame->GetHeight()); |
| // Create an image data resource to hold the frame pixels. |
| - PP_ImageDataDesc desc; |
| + PP_ImageDataDesc image_desc; |
| IPC::PlatformFileForTransit image_handle; |
| uint32_t byte_count; |
| ppapi::ScopedPPResource resource( |
| @@ -148,27 +146,27 @@ int32_t PepperVideoSourceHost::ConvertFrame( |
| PP_MakeSize(width, height), |
| false /* init_to_zero */, |
| false /* is_nacl_plugin */, |
| - &desc, &image_handle, &byte_count)); |
| + &image_desc, &image_handle, &byte_count)); |
| if (!resource.get()) |
| - return PP_ERROR_FAILED; |
| + return ReportGetFrameError(PP_ERROR_FAILED); |
|
raymes
2013/05/10 15:14:48
Since ReportGetFrameError() doesn't return a value
bbudge
2013/05/10 17:38:21
Done.
|
| ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API> |
| enter_resource(resource, false); |
| if (enter_resource.failed()) |
| - return PP_ERROR_FAILED; |
| + return ReportGetFrameError(PP_ERROR_FAILED); |
| webkit::ppapi::PPB_ImageData_Impl* image_data = |
| static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object()); |
| webkit::ppapi::ImageDataAutoMapper mapper(image_data); |
| if (!mapper.is_valid()) |
| - return PP_ERROR_FAILED; |
| + return ReportGetFrameError(PP_ERROR_FAILED); |
| const SkBitmap* bitmap = image_data->GetMappedBitmap(); |
| if (!bitmap) |
| - return PP_ERROR_FAILED; |
| + return ReportGetFrameError(PP_ERROR_FAILED); |
| uint8_t* bitmap_pixels = static_cast<uint8_t*>(bitmap->getPixels()); |
| if (!bitmap_pixels) |
| - return PP_ERROR_FAILED; |
| + return ReportGetFrameError(PP_ERROR_FAILED); |
| size_t bitmap_size = bitmap->getSize(); |
| frame->ConvertToRgbBuffer(cricket::FOURCC_BGRA, |
| @@ -176,35 +174,70 @@ int32_t PepperVideoSourceHost::ConvertFrame( |
| bitmap_size, |
| bitmap->rowBytes()); |
| - image_data_resource->SetHostResource(pp_instance(), resource.get()); |
| + ppapi::HostResource host_resource; |
| + host_resource.SetHostResource(pp_instance(), resource.get()); |
| // Convert a video timestamp (int64, in nanoseconds) to a time delta (int64, |
| // microseconds) and then to a PP_TimeTicks (a double, in seconds). All times |
| // are relative to the Unix Epoch. |
| base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds( |
| frame->GetTimeStamp() / base::Time::kNanosecondsPerMicrosecond); |
| - *timestamp = time_delta.InSecondsF(); |
| - return PP_OK; |
| + PP_TimeTicks timestamp = time_delta.InSecondsF(); |
| + |
| + DCHECK(get_frame_pending_); |
| + reply_context_.params.set_result(PP_OK); |
| + |
| + // TODO(bbudge) Change the PDF Host's image creation code to match. |
| +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) |
| + ppapi::proxy::SerializedHandle serialized_handle; |
| + PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, |
| + image_desc, |
| + 0, |
| + timestamp); |
| + serialized_handle.set_shmem(image_handle, byte_count); |
| + reply_context_.params.AppendHandle(serialized_handle); |
| +#elif defined(OS_LINUX) |
| + // For Linux, we pass the SysV shared memory key in the message. |
| + PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, |
| + image_desc, |
| + image_handle.fd, |
| + timestamp); |
| +#else |
| + // Not supported on other platforms. |
| + // This is a stub reply_msg to not break the build. |
| + PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, |
| + image_desc, |
| + 0, |
| + timestamp); |
| + NOTIMPLEMENTED(); |
| + return ReportGetFrameError(PP_ERROR_NOTSUPPORTED); |
| +#endif |
| + |
| + host()->SendReply(reply_context_, reply_msg); |
| + |
| + reply_context_ = ppapi::host::ReplyMessageContext(); |
| + get_frame_pending_ = false; |
| + |
| + // Keep a reference once we know this method succeeds. |
| + resource.Release(); |
| } |
| -void PepperVideoSourceHost::SendFrame( |
| - const ppapi::HostResource& image_data_resource, |
| - PP_TimeTicks timestamp, |
| - int32_t result) { |
| +void PepperVideoSourceHost::ReportGetFrameError(int32_t error) { |
| DCHECK(get_frame_pending_); |
| - reply_context_.params.set_result(result); |
| + reply_context_.params.set_result(error); |
| host()->SendReply( |
| reply_context_, |
| - PpapiPluginMsg_VideoSource_GetFrameReply(image_data_resource, timestamp)); |
| - |
| + PpapiPluginMsg_VideoSource_GetFrameReply( |
| + ppapi::HostResource(), PP_ImageDataDesc(), -1, 0.0)); |
| reply_context_ = ppapi::host::ReplyMessageContext(); |
| get_frame_pending_ = false; |
| } |
| void PepperVideoSourceHost::Close() { |
| - if (source_handler_.get()) { |
| - source_handler_->Close(stream_url_, this); |
| + if (source_handler_.get() && !stream_url_.empty()) { |
| + source_handler_->Close(stream_url_, frame_receiver_.get()); |
| source_handler_.reset(NULL); |
| + stream_url_.clear(); |
| } |
| } |