OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_source_host.h" | 5 #include "content/renderer/pepper/pepper_video_source_host.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/safe_numerics.h" | 8 #include "base/safe_numerics.h" |
9 #include "content/public/renderer/renderer_ppapi_host.h" | 9 #include "content/public/renderer/renderer_ppapi_host.h" |
10 #include "content/renderer/render_thread_impl.h" | 10 #include "content/renderer/render_thread_impl.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 IPC_END_MESSAGE_MAP() | 55 IPC_END_MESSAGE_MAP() |
56 return PP_ERROR_FAILED; | 56 return PP_ERROR_FAILED; |
57 } | 57 } |
58 | 58 |
59 bool PepperVideoSourceHost::GotFrame(cricket::VideoFrame* frame) { | 59 bool PepperVideoSourceHost::GotFrame(cricket::VideoFrame* frame) { |
60 // It's not safe to access this on another thread, so post a task to our | 60 // It's not safe to access this on another thread, so post a task to our |
61 // main thread to transfer the new frame. | 61 // main thread to transfer the new frame. |
62 main_message_loop_proxy_->PostTask( | 62 main_message_loop_proxy_->PostTask( |
63 FROM_HERE, | 63 FROM_HERE, |
64 base::Bind(&PepperVideoSourceHost::OnGotFrame, | 64 base::Bind(&PepperVideoSourceHost::OnGotFrame, |
65 weak_factory_.GetWeakPtr(), | 65 base::Unretained(this), |
raymes
2013/05/10 05:32:10
I guess this wasn't right before because we can't
bbudge
2013/05/10 12:31:12
The RTC folks say this can't be called after we co
bbudge
2013/05/10 13:52:59
While out on my morning run, around mile 2 I reali
| |
66 base::Passed(scoped_ptr<cricket::VideoFrame>(frame)))); | 66 base::Passed(scoped_ptr<cricket::VideoFrame>(frame)))); |
67 | 67 |
68 return true; | 68 return true; |
69 } | 69 } |
70 | 70 |
71 void PepperVideoSourceHost::OnGotFrame(scoped_ptr<cricket::VideoFrame> frame) { | 71 void PepperVideoSourceHost::OnGotFrame(scoped_ptr<cricket::VideoFrame> frame) { |
72 // Take ownership of the new frame, and possibly delete any unsent one. | 72 // Take ownership of the new frame, and possibly delete any unsent one. |
73 last_frame_.swap(frame); | 73 last_frame_.swap(frame); |
74 | 74 |
75 if (get_frame_pending_) { | 75 if (get_frame_pending_) |
76 ppapi::HostResource image_data_resource; | 76 SendGetFrameReply(true); // Send reply even on failure. |
77 PP_TimeTicks timestamp = 0; | |
78 int32_t result = ConvertFrame(&image_data_resource, ×tamp); | |
79 SendFrame(image_data_resource, timestamp, result); | |
80 } | |
81 } | 77 } |
82 | 78 |
83 int32_t PepperVideoSourceHost::OnHostMsgOpen(HostMessageContext* context, | 79 int32_t PepperVideoSourceHost::OnHostMsgOpen(HostMessageContext* context, |
84 const std::string& stream_url) { | 80 const std::string& stream_url) { |
85 GURL gurl(stream_url); | 81 GURL gurl(stream_url); |
86 if (!gurl.is_valid()) | 82 if (!gurl.is_valid()) |
87 return PP_ERROR_BADARGUMENT; | 83 return PP_ERROR_BADARGUMENT; |
88 | 84 |
89 if (!source_handler_->Open(gurl.spec(), this)) | 85 if (!source_handler_->Open(gurl.spec(), this)) |
90 return PP_ERROR_BADARGUMENT; | 86 return PP_ERROR_BADARGUMENT; |
91 | 87 |
92 stream_url_ = gurl.spec(); | 88 stream_url_ = gurl.spec(); |
93 | 89 |
94 ReplyMessageContext reply_context = context->MakeReplyMessageContext(); | 90 ReplyMessageContext reply_context = context->MakeReplyMessageContext(); |
95 reply_context.params.set_result(PP_OK); | 91 reply_context.params.set_result(PP_OK); |
96 host()->SendReply(reply_context, PpapiPluginMsg_VideoSource_OpenReply()); | 92 host()->SendReply(reply_context, PpapiPluginMsg_VideoSource_OpenReply()); |
97 return PP_OK_COMPLETIONPENDING; | 93 return PP_OK_COMPLETIONPENDING; |
98 } | 94 } |
99 | 95 |
100 int32_t PepperVideoSourceHost::OnHostMsgGetFrame( | 96 int32_t PepperVideoSourceHost::OnHostMsgGetFrame( |
101 HostMessageContext* context) { | 97 HostMessageContext* context) { |
102 if (!source_handler_.get()) | 98 if (!source_handler_.get()) |
103 return PP_ERROR_FAILED; | 99 return PP_ERROR_FAILED; |
104 if (get_frame_pending_) | 100 if (get_frame_pending_) |
105 return PP_ERROR_INPROGRESS; | 101 return PP_ERROR_INPROGRESS; |
106 | 102 |
107 reply_context_ = context->MakeReplyMessageContext(); | 103 reply_context_ = context->MakeReplyMessageContext(); |
108 get_frame_pending_ = true; | 104 get_frame_pending_ = true; |
109 | 105 |
110 // If a frame is ready, try to convert it and reply. | 106 // If a frame is ready, try to convert it and send the reply. |
111 if (last_frame_.get()) { | 107 if (last_frame_.get()) { |
112 ppapi::HostResource image_data_resource; | 108 int32_t result = SendGetFrameReply(false); // Don't send reply on failure. |
raymes
2013/05/10 05:32:10
I think this would be clearer if SendGetFrameReply
bbudge
2013/05/10 12:31:12
Done.
| |
113 PP_TimeTicks timestamp = 0; | 109 if (result != PP_OK) { |
114 int32_t result = ConvertFrame(&image_data_resource, ×tamp); | |
115 if (result == PP_OK) { | |
116 SendFrame(image_data_resource, timestamp, result); | |
117 } else { | |
118 reply_context_ = ppapi::host::ReplyMessageContext(); | 110 reply_context_ = ppapi::host::ReplyMessageContext(); |
119 return result; | 111 return result; |
120 } | 112 } |
121 } | 113 } |
122 | 114 |
123 return PP_OK_COMPLETIONPENDING; | 115 return PP_OK_COMPLETIONPENDING; |
124 } | 116 } |
125 | 117 |
126 int32_t PepperVideoSourceHost::OnHostMsgClose(HostMessageContext* context) { | 118 int32_t PepperVideoSourceHost::OnHostMsgClose(HostMessageContext* context) { |
127 Close(); | 119 Close(); |
128 return PP_OK; | 120 return PP_OK; |
129 } | 121 } |
130 | 122 |
131 int32_t PepperVideoSourceHost::ConvertFrame( | 123 int32_t PepperVideoSourceHost::SendGetFrameReply(bool force_reply) { |
132 ppapi::HostResource* image_data_resource, | |
133 PP_TimeTicks* timestamp) { | |
134 DCHECK(last_frame_.get()); | 124 DCHECK(last_frame_.get()); |
135 scoped_ptr<cricket::VideoFrame> frame(last_frame_.release()); | 125 scoped_ptr<cricket::VideoFrame> frame(last_frame_.release()); |
136 | 126 |
137 int32_t width = base::checked_numeric_cast<int32_t>(frame->GetWidth()); | 127 int32_t width = base::checked_numeric_cast<int32_t>(frame->GetWidth()); |
138 int32_t height = base::checked_numeric_cast<int32_t>(frame->GetHeight()); | 128 int32_t height = base::checked_numeric_cast<int32_t>(frame->GetHeight()); |
139 // Create an image data resource to hold the frame pixels. | 129 // Create an image data resource to hold the frame pixels. |
140 PP_ImageDataDesc desc; | 130 PP_ImageDataDesc image_desc; |
141 IPC::PlatformFileForTransit image_handle; | 131 IPC::PlatformFileForTransit image_handle; |
142 uint32_t byte_count; | 132 uint32_t byte_count; |
143 ppapi::ScopedPPResource resource( | 133 ppapi::ScopedPPResource resource( |
144 ppapi::ScopedPPResource::PassRef(), | 134 ppapi::ScopedPPResource::PassRef(), |
145 ppapi::proxy::PPB_ImageData_Proxy::CreateImageData( | 135 ppapi::proxy::PPB_ImageData_Proxy::CreateImageData( |
146 pp_instance(), | 136 pp_instance(), |
147 PP_IMAGEDATAFORMAT_BGRA_PREMUL, | 137 PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
148 PP_MakeSize(width, height), | 138 PP_MakeSize(width, height), |
149 false /* init_to_zero */, | 139 false /* init_to_zero */, |
150 false /* is_nacl_plugin */, | 140 false /* is_nacl_plugin */, |
151 &desc, &image_handle, &byte_count)); | 141 &image_desc, &image_handle, &byte_count)); |
152 if (!resource.get()) | 142 if (!resource.get()) |
153 return PP_ERROR_FAILED; | 143 return ReportGetFrameError(PP_ERROR_FAILED, force_reply); |
154 | 144 |
155 ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API> | 145 ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API> |
156 enter_resource(resource, false); | 146 enter_resource(resource, false); |
157 if (enter_resource.failed()) | 147 if (enter_resource.failed()) |
158 return PP_ERROR_FAILED; | 148 return ReportGetFrameError(PP_ERROR_FAILED, force_reply); |
159 | 149 |
160 webkit::ppapi::PPB_ImageData_Impl* image_data = | 150 webkit::ppapi::PPB_ImageData_Impl* image_data = |
161 static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object()); | 151 static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object()); |
162 webkit::ppapi::ImageDataAutoMapper mapper(image_data); | 152 webkit::ppapi::ImageDataAutoMapper mapper(image_data); |
163 if (!mapper.is_valid()) | 153 if (!mapper.is_valid()) |
164 return PP_ERROR_FAILED; | 154 return ReportGetFrameError(PP_ERROR_FAILED, force_reply); |
165 | 155 |
166 const SkBitmap* bitmap = image_data->GetMappedBitmap(); | 156 const SkBitmap* bitmap = image_data->GetMappedBitmap(); |
167 if (!bitmap) | 157 if (!bitmap) |
168 return PP_ERROR_FAILED; | 158 return ReportGetFrameError(PP_ERROR_FAILED, force_reply); |
169 uint8_t* bitmap_pixels = static_cast<uint8_t*>(bitmap->getPixels()); | 159 uint8_t* bitmap_pixels = static_cast<uint8_t*>(bitmap->getPixels()); |
170 if (!bitmap_pixels) | 160 if (!bitmap_pixels) |
171 return PP_ERROR_FAILED; | 161 return ReportGetFrameError(PP_ERROR_FAILED, force_reply); |
172 | 162 |
173 size_t bitmap_size = bitmap->getSize(); | 163 size_t bitmap_size = bitmap->getSize(); |
174 frame->ConvertToRgbBuffer(cricket::FOURCC_BGRA, | 164 frame->ConvertToRgbBuffer(cricket::FOURCC_BGRA, |
175 bitmap_pixels, | 165 bitmap_pixels, |
176 bitmap_size, | 166 bitmap_size, |
177 bitmap->rowBytes()); | 167 bitmap->rowBytes()); |
178 | 168 |
179 image_data_resource->SetHostResource(pp_instance(), resource.get()); | 169 ppapi::HostResource host_resource; |
170 host_resource.SetHostResource(pp_instance(), resource.get()); | |
180 | 171 |
181 // Convert a video timestamp (int64, in nanoseconds) to a time delta (int64, | 172 // Convert a video timestamp (int64, in nanoseconds) to a time delta (int64, |
182 // microseconds) and then to a PP_TimeTicks (a double, in seconds). All times | 173 // microseconds) and then to a PP_TimeTicks (a double, in seconds). All times |
183 // are relative to the Unix Epoch. | 174 // are relative to the Unix Epoch. |
184 base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds( | 175 base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds( |
185 frame->GetTimeStamp() / base::Time::kNanosecondsPerMicrosecond); | 176 frame->GetTimeStamp() / base::Time::kNanosecondsPerMicrosecond); |
186 *timestamp = time_delta.InSecondsF(); | 177 PP_TimeTicks timestamp = time_delta.InSecondsF(); |
178 | |
179 DCHECK(get_frame_pending_); | |
180 reply_context_.params.set_result(PP_OK); | |
181 | |
182 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) | |
raymes
2013/05/10 05:32:10
Please add a TODO to unify this with the pdf resou
bbudge
2013/05/10 12:31:12
Done.
| |
183 ppapi::proxy::SerializedHandle serialized_handle; | |
184 PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, | |
185 image_desc, | |
186 0, | |
187 timestamp); | |
188 serialized_handle.set_shmem(image_handle, byte_count); | |
189 reply_context_.params.AppendHandle(serialized_handle); | |
190 #elif defined(OS_LINUX) | |
191 // For Linux, we pass the SysV shared memory key in the message. | |
192 PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, | |
193 image_desc, | |
194 image_handle.fd, | |
195 timestamp); | |
196 #else | |
197 // Not supported on other platforms. | |
198 // This is a stub reply_msg to not break the build. | |
199 PpapiPluginMsg_VideoSource_GetFrameReply reply_msg(host_resource, | |
200 image_desc, | |
201 0, | |
202 timestamp); | |
203 NOTIMPLEMENTED(); | |
204 return PP_ERROR_NOTSUPPORTED; | |
205 #endif | |
206 | |
207 host()->SendReply(reply_context_, reply_msg); | |
208 | |
209 reply_context_ = ppapi::host::ReplyMessageContext(); | |
210 get_frame_pending_ = false; | |
211 | |
212 // Keep a reference once we know this method succeeds. | |
213 resource.Release(); | |
214 | |
187 return PP_OK; | 215 return PP_OK; |
188 } | 216 } |
189 | 217 |
190 void PepperVideoSourceHost::SendFrame( | 218 int32_t PepperVideoSourceHost::ReportGetFrameError(int32_t error, |
191 const ppapi::HostResource& image_data_resource, | 219 bool force_reply) { |
192 PP_TimeTicks timestamp, | |
193 int32_t result) { | |
194 DCHECK(get_frame_pending_); | 220 DCHECK(get_frame_pending_); |
195 reply_context_.params.set_result(result); | 221 if (force_reply) { |
196 host()->SendReply( | 222 reply_context_.params.set_result(error); |
197 reply_context_, | 223 host()->SendReply( |
198 PpapiPluginMsg_VideoSource_GetFrameReply(image_data_resource, timestamp)); | 224 reply_context_, |
225 PpapiPluginMsg_VideoSource_GetFrameReply( | |
226 ppapi::HostResource(), PP_ImageDataDesc(), -1, 0.0)); | |
199 | 227 |
228 } | |
200 reply_context_ = ppapi::host::ReplyMessageContext(); | 229 reply_context_ = ppapi::host::ReplyMessageContext(); |
201 get_frame_pending_ = false; | 230 get_frame_pending_ = false; |
231 return error; | |
202 } | 232 } |
203 | 233 |
204 void PepperVideoSourceHost::Close() { | 234 void PepperVideoSourceHost::Close() { |
205 if (source_handler_.get()) { | 235 if (source_handler_.get() && !stream_url_.empty()) { |
206 source_handler_->Close(stream_url_, this); | 236 source_handler_->Close(stream_url_, this); |
207 source_handler_.reset(NULL); | 237 source_handler_.reset(NULL); |
238 stream_url_.clear(); | |
208 } | 239 } |
209 } | 240 } |
210 | 241 |
211 } // namespace content | 242 } // namespace content |
OLD | NEW |