Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/ppb_video_capture_impl.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "ppapi/c/dev/pp_video_capture_dev.h" | |
| 12 #include "ppapi/c/dev/ppb_video_capture_dev.h" | |
| 13 #include "ppapi/c/pp_completion_callback.h" | |
| 14 #include "ppapi/c/pp_errors.h" | |
| 15 #include "ppapi/thunk/enter.h" | |
| 16 #include "webkit/plugins/ppapi/common.h" | |
| 17 #include "webkit/plugins/ppapi/plugin_module.h" | |
| 18 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | |
| 19 #include "webkit/plugins/ppapi/ppb_buffer_impl.h" | |
| 20 #include "webkit/plugins/ppapi/resource_tracker.h" | |
| 21 | |
| 22 using ppapi::thunk::EnterResourceNoLock; | |
| 23 using ppapi::thunk::PPB_Buffer_API; | |
| 24 using ppapi::thunk::PPB_VideoCapture_API; | |
| 25 | |
| 26 namespace webkit { | |
| 27 namespace ppapi { | |
| 28 | |
| 29 PPB_VideoCapture_Impl::PPB_VideoCapture_Impl(PluginInstance* instance) | |
| 30 : Resource(instance), | |
| 31 buffer_count_hint_(0), | |
| 32 status_(PP_VIDEO_CAPTURE_STATUS_STOPPED) { | |
| 33 ppp_videocapture_ = | |
|
brettw
2011/08/02 17:17:44
I'd initialize this to null in the initializer lis
piman
2011/08/03 00:44:41
Done.
| |
| 34 static_cast<const PPP_VideoCapture_Dev*>(instance->module()-> | |
| 35 GetPluginInterface(PPP_VIDEO_CAPTURE_DEV_INTERFACE)); | |
| 36 } | |
| 37 | |
| 38 PPB_VideoCapture_Impl::~PPB_VideoCapture_Impl() { | |
| 39 if (platform_video_capture_.get()) | |
| 40 StopCapture(); | |
| 41 } | |
| 42 | |
| 43 bool PPB_VideoCapture_Impl::Init() { | |
| 44 platform_video_capture_.reset( | |
| 45 instance()->delegate()->CreateVideoCapture(this)); | |
| 46 return ppp_videocapture_ && platform_video_capture_.get(); | |
| 47 } | |
| 48 | |
| 49 PPB_VideoCapture_API* PPB_VideoCapture_Impl::AsPPB_VideoCapture_API() { | |
| 50 return this; | |
| 51 } | |
| 52 | |
| 53 int32_t PPB_VideoCapture_Impl::StartCapture( | |
| 54 const PP_VideoCaptureDeviceInfo_Dev& requested_info, | |
| 55 uint32_t buffer_count) { | |
| 56 switch (status_) { | |
| 57 case PP_VIDEO_CAPTURE_STATUS_STARTING: | |
| 58 case PP_VIDEO_CAPTURE_STATUS_STARTED: | |
| 59 case PP_VIDEO_CAPTURE_STATUS_PAUSED: | |
| 60 default: | |
| 61 return PP_ERROR_FAILED; | |
| 62 case PP_VIDEO_CAPTURE_STATUS_STOPPED: | |
| 63 case PP_VIDEO_CAPTURE_STATUS_STOPPING: | |
| 64 break; | |
| 65 } | |
| 66 DCHECK(buffers_.empty()); | |
| 67 | |
| 68 buffer_count_hint_ = std::min(buffer_count, 1U); | |
| 69 media::VideoCapture::VideoCaptureCapability capability = { | |
| 70 requested_info.width, | |
| 71 requested_info.height, | |
| 72 requested_info.frames_per_second, | |
| 73 0, // ignored. | |
| 74 media::VideoFrame::I420, | |
| 75 false, // ignored | |
| 76 false // resolution_fixed | |
| 77 }; | |
| 78 status_ = PP_VIDEO_CAPTURE_STATUS_STARTING; | |
| 79 platform_video_capture_->StartCapture(this, capability); | |
| 80 return PP_OK; | |
| 81 } | |
| 82 | |
| 83 int32_t PPB_VideoCapture_Impl::ReuseBuffer(uint32_t buffer) { | |
| 84 if (buffer >= buffers_.size() || !buffers_[buffer].in_use) | |
| 85 return PP_ERROR_BADARGUMENT; | |
| 86 buffers_[buffer].in_use = false; | |
| 87 return PP_OK; | |
| 88 } | |
| 89 | |
| 90 int32_t PPB_VideoCapture_Impl::StopCapture() { | |
| 91 switch (status_) { | |
| 92 case PP_VIDEO_CAPTURE_STATUS_STOPPED: | |
| 93 case PP_VIDEO_CAPTURE_STATUS_STOPPING: | |
| 94 default: | |
| 95 return PP_ERROR_FAILED; | |
|
wjia(left Chromium)
2011/08/02 16:22:28
Is this a fatal error, or just warning? It might b
piman
2011/08/03 00:44:41
It's essentially silent, except if the plugin look
| |
| 96 case PP_VIDEO_CAPTURE_STATUS_STARTING: | |
| 97 case PP_VIDEO_CAPTURE_STATUS_STARTED: | |
| 98 case PP_VIDEO_CAPTURE_STATUS_PAUSED: | |
| 99 break; | |
| 100 } | |
| 101 FreeBuffers(); | |
| 102 status_ = PP_VIDEO_CAPTURE_STATUS_STOPPING; | |
| 103 platform_video_capture_->StopCapture(this); | |
| 104 return PP_OK; | |
| 105 } | |
| 106 | |
| 107 void PPB_VideoCapture_Impl::OnStarted(media::VideoCapture* capture) { | |
| 108 switch (status_) { | |
| 109 case PP_VIDEO_CAPTURE_STATUS_STARTING: | |
| 110 case PP_VIDEO_CAPTURE_STATUS_PAUSED: | |
| 111 break; | |
| 112 case PP_VIDEO_CAPTURE_STATUS_STOPPED: | |
| 113 case PP_VIDEO_CAPTURE_STATUS_STOPPING: | |
| 114 case PP_VIDEO_CAPTURE_STATUS_STARTED: | |
| 115 default: | |
| 116 return; | |
| 117 } | |
| 118 status_ = PP_VIDEO_CAPTURE_STATUS_STARTED; | |
| 119 SendStatus(); | |
| 120 } | |
| 121 | |
| 122 void PPB_VideoCapture_Impl::OnStopped(media::VideoCapture* capture) { | |
| 123 switch (status_) { | |
| 124 case PP_VIDEO_CAPTURE_STATUS_STOPPING: | |
| 125 break; | |
| 126 case PP_VIDEO_CAPTURE_STATUS_STARTING: | |
| 127 case PP_VIDEO_CAPTURE_STATUS_PAUSED: | |
| 128 case PP_VIDEO_CAPTURE_STATUS_STOPPED: | |
| 129 case PP_VIDEO_CAPTURE_STATUS_STARTED: | |
| 130 default: | |
| 131 return; | |
| 132 } | |
| 133 status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED; | |
| 134 SendStatus(); | |
| 135 } | |
| 136 | |
| 137 void PPB_VideoCapture_Impl::OnPaused(media::VideoCapture* capture) { | |
| 138 switch (status_) { | |
| 139 case PP_VIDEO_CAPTURE_STATUS_STARTING: | |
| 140 case PP_VIDEO_CAPTURE_STATUS_STARTED: | |
| 141 break; | |
| 142 case PP_VIDEO_CAPTURE_STATUS_STOPPED: | |
| 143 case PP_VIDEO_CAPTURE_STATUS_STOPPING: | |
| 144 case PP_VIDEO_CAPTURE_STATUS_PAUSED: | |
| 145 default: | |
| 146 return; | |
| 147 } | |
| 148 status_ = PP_VIDEO_CAPTURE_STATUS_PAUSED; | |
| 149 SendStatus(); | |
| 150 } | |
| 151 | |
| 152 void PPB_VideoCapture_Impl::OnError(media::VideoCapture* capture, | |
| 153 int error_code) { | |
| 154 // Today, the media layer only sends "1" as an error. | |
| 155 DCHECK(error_code == 1); | |
| 156 // It either comes because some error was detected while starting (e.g. 2 | |
| 157 // conflicting "master" resolution), or because the browser failed to start | |
| 158 // the capture. | |
| 159 status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED; | |
| 160 ppp_videocapture_->OnError(instance()->pp_instance(), | |
| 161 ScopedResourceId(this).id, | |
| 162 PP_ERROR_FAILED); | |
| 163 } | |
| 164 | |
| 165 void PPB_VideoCapture_Impl::OnBufferReady( | |
| 166 media::VideoCapture* capture, | |
|
wjia(left Chromium)
2011/08/02 16:22:28
This |capture| looks like an alien since PPB_Video
piman
2011/08/03 00:44:41
So, I was kinda wondering about that, but decided
| |
| 167 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buffer) { | |
|
wjia(left Chromium)
2011/08/02 16:22:28
it would be good to check buffer (not a NULL point
piman
2011/08/03 00:44:41
Is there a reason the VideoCaptureImpl would send
wjia(left Chromium)
2011/08/03 02:40:00
I meant DCHECK which has been added.
| |
| 168 if (!buffers_.empty()) { | |
| 169 for (uint32_t i = 0; i < buffers_.size(); ++i) { | |
| 170 if (!buffers_[i].in_use) { | |
| 171 // TODO(piman): it looks like stride isn't actually used/filled. | |
| 172 DCHECK(buffer->stride == 0); | |
| 173 size_t size = std::min(buffers_[i].buffer->size(), buffer->buffer_size); | |
| 174 memcpy(buffers_[i].data, buffer->memory_pointer, size); | |
|
wjia(left Chromium)
2011/08/02 16:22:28
would it be good to call "platform_video_capture_-
piman
2011/08/03 00:44:41
Done.
| |
| 175 ppp_videocapture_->OnBufferReady(instance()->pp_instance(), | |
| 176 ScopedResourceId(this).id, | |
| 177 i); | |
| 178 break; | |
| 179 } | |
| 180 } | |
| 181 } | |
| 182 // TODO(piman): signal dropped buffers ? | |
| 183 platform_video_capture_->FeedBuffer(buffer); | |
| 184 } | |
| 185 | |
| 186 void PPB_VideoCapture_Impl::OnDeviceInfoReceived( | |
| 187 media::VideoCapture* capture, | |
| 188 const media::VideoCaptureParams& device_info) { | |
| 189 PP_VideoCaptureDeviceInfo_Dev info = { | |
| 190 device_info.width, | |
| 191 device_info.height, | |
| 192 device_info.frame_per_second | |
| 193 }; | |
| 194 FreeBuffers(); | |
|
wjia(left Chromium)
2011/08/02 16:22:28
is it guaranteed that no buffer is in use by plugi
piman
2011/08/03 00:44:41
The plugin is responsible for keeping its own refe
| |
| 195 | |
| 196 // Allocate buffers. We keep a reference to them, that is released in | |
| 197 // FreeBuffers. | |
| 198 // YUV 4:2:0 | |
| 199 int uv_width = info.width / 2; | |
| 200 int uv_height = info.height / 2; | |
| 201 size_t size = info.width * info.height + 2 * uv_width * uv_height; | |
| 202 scoped_array<PP_Resource> resources(new PP_Resource[buffer_count_hint_]); | |
| 203 | |
| 204 buffers_.reserve(buffer_count_hint_); | |
| 205 for (size_t i = 0; i < buffer_count_hint_; ++i) { | |
| 206 resources[i] = PPB_Buffer_Impl::Create(instance(), size); | |
| 207 if (!resources[i]) { | |
| 208 break; | |
| 209 } | |
| 210 | |
| 211 EnterResourceNoLock<PPB_Buffer_API> enter(resources[i], true); | |
| 212 DCHECK(enter.succeeded()); | |
| 213 | |
| 214 BufferInfo info; | |
| 215 info.buffer = static_cast<PPB_Buffer_Impl*>(enter.object()); | |
| 216 info.data = info.buffer->Map(); | |
| 217 if (!info.data) { | |
| 218 ResourceTracker::Get()->UnrefResource(resources[i]); | |
| 219 break; | |
| 220 } | |
| 221 buffers_.push_back(info); | |
| 222 } | |
| 223 | |
| 224 if (buffers_.empty()) { | |
| 225 // We couldn't allocate/map buffers at all. Send an error and stop the | |
| 226 // capture. | |
| 227 ppp_videocapture_->OnError(instance()->pp_instance(), | |
| 228 ScopedResourceId(this).id, | |
| 229 PP_ERROR_NOMEMORY); | |
| 230 status_ = PP_VIDEO_CAPTURE_STATUS_STOPPING; | |
| 231 platform_video_capture_->StopCapture(this); | |
| 232 return; | |
| 233 } | |
| 234 | |
| 235 ppp_videocapture_->OnDeviceInfo(instance()->pp_instance(), | |
| 236 ScopedResourceId(this).id, | |
| 237 &info, | |
| 238 buffers_.size(), | |
| 239 resources.get()); | |
| 240 } | |
| 241 | |
| 242 void PPB_VideoCapture_Impl::FreeBuffers() { | |
| 243 ResourceTracker *tracker = ResourceTracker::Get(); | |
| 244 for (size_t i = 0; i < buffers_.size(); ++i) { | |
| 245 buffers_[i].buffer->Unmap(); | |
| 246 tracker->UnrefResource(buffers_[i].buffer->GetReferenceNoAddRef()); | |
| 247 } | |
| 248 buffers_.clear(); | |
| 249 } | |
| 250 | |
| 251 void PPB_VideoCapture_Impl::SendStatus() { | |
| 252 ppp_videocapture_->OnStatus(instance()->pp_instance(), | |
| 253 ScopedResourceId(this).id, | |
| 254 status_); | |
| 255 } | |
| 256 | |
| 257 } // namespace ppapi | |
| 258 } // namespace webkit | |
| OLD | NEW |