OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 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 <stdlib.h> | |
6 #include <string.h> | |
7 | |
8 #include <map> | |
9 #include <vector> | |
10 | |
11 #include "ppapi/c/dev/ppb_video_capture_dev.h" | |
12 #include "ppapi/c/pp_errors.h" | 5 #include "ppapi/c/pp_errors.h" |
13 #include "ppapi/c/ppb_opengles2.h" | 6 #include "ppapi/c/ppb_opengles2.h" |
14 #include "ppapi/cpp/dev/buffer_dev.h" | |
15 #include "ppapi/cpp/dev/device_ref_dev.h" | |
16 #include "ppapi/cpp/dev/video_capture_dev.h" | |
17 #include "ppapi/cpp/dev/video_capture_client_dev.h" | |
18 #include "ppapi/cpp/completion_callback.h" | 7 #include "ppapi/cpp/completion_callback.h" |
| 8 #include "ppapi/cpp/dev/var_resource_dev.h" |
| 9 #include "ppapi/cpp/graphics_3d.h" |
19 #include "ppapi/cpp/graphics_3d_client.h" | 10 #include "ppapi/cpp/graphics_3d_client.h" |
20 #include "ppapi/cpp/graphics_3d.h" | |
21 #include "ppapi/cpp/instance.h" | 11 #include "ppapi/cpp/instance.h" |
| 12 #include "ppapi/cpp/media_stream_video_track.h" |
22 #include "ppapi/cpp/module.h" | 13 #include "ppapi/cpp/module.h" |
23 #include "ppapi/cpp/rect.h" | 14 #include "ppapi/cpp/rect.h" |
24 #include "ppapi/cpp/var.h" | 15 #include "ppapi/cpp/var.h" |
| 16 #include "ppapi/cpp/video_frame.h" |
25 #include "ppapi/lib/gl/include/GLES2/gl2.h" | 17 #include "ppapi/lib/gl/include/GLES2/gl2.h" |
26 #include "ppapi/utility/completion_callback_factory.h" | 18 #include "ppapi/utility/completion_callback_factory.h" |
27 | 19 |
28 // When compiling natively on Windows, PostMessage can be #define-d to | 20 // When compiling natively on Windows, PostMessage can be #define-d to |
29 // something else. | 21 // something else. |
30 #ifdef PostMessage | 22 #ifdef PostMessage |
31 #undef PostMessage | 23 #undef PostMessage |
32 #endif | 24 #endif |
33 | 25 |
34 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a | 26 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a |
35 // function to preserve line number information in the failure message. | 27 // function to preserve line number information in the failure message. |
36 #define AssertNoGLError() \ | 28 #define AssertNoGLError() \ |
37 PP_DCHECK(!gles2_if_->GetError(context_->pp_resource())); | 29 PP_DCHECK(!gles2_if_->GetError(context_->pp_resource())); |
38 | 30 |
39 namespace { | 31 namespace { |
40 | 32 |
41 const char* const kDelimiter = "#__#"; | |
42 | |
43 // This object is the global object representing this plugin library as long | 33 // This object is the global object representing this plugin library as long |
44 // as it is loaded. | 34 // as it is loaded. |
45 class VCDemoModule : public pp::Module { | 35 class MediaStreamVideoModule : public pp::Module { |
46 public: | 36 public: |
47 VCDemoModule() : pp::Module() {} | 37 MediaStreamVideoModule() : pp::Module() {} |
48 virtual ~VCDemoModule() {} | 38 virtual ~MediaStreamVideoModule() {} |
49 | 39 |
50 virtual pp::Instance* CreateInstance(PP_Instance instance); | 40 virtual pp::Instance* CreateInstance(PP_Instance instance); |
51 }; | 41 }; |
52 | 42 |
53 class VCDemoInstance : public pp::Instance, | 43 class MediaStreamVideoDemoInstance : public pp::Instance, |
54 public pp::Graphics3DClient, | 44 public pp::Graphics3DClient { |
55 public pp::VideoCaptureClient_Dev { | |
56 public: | 45 public: |
57 VCDemoInstance(PP_Instance instance, pp::Module* module); | 46 MediaStreamVideoDemoInstance(PP_Instance instance, pp::Module* module); |
58 virtual ~VCDemoInstance(); | 47 virtual ~MediaStreamVideoDemoInstance(); |
59 | 48 |
60 // pp::Instance implementation (see PPP_Instance). | 49 // pp::Instance implementation (see PPP_Instance). |
61 virtual void DidChangeView(const pp::Rect& position, | 50 virtual void DidChangeView(const pp::Rect& position, |
62 const pp::Rect& clip_ignored); | 51 const pp::Rect& clip_ignored); |
63 virtual void HandleMessage(const pp::Var& message_data); | 52 virtual void HandleMessage(const pp::Var& message_data); |
64 | 53 |
65 // pp::Graphics3DClient implementation. | 54 // pp::Graphics3DClient implementation. |
66 virtual void Graphics3DContextLost() { | 55 virtual void Graphics3DContextLost() { |
67 InitGL(); | 56 InitGL(); |
68 CreateYUVTextures(); | 57 CreateYUVTextures(); |
69 Render(); | 58 Render(); |
70 } | 59 } |
71 | 60 |
72 virtual void OnDeviceInfo(PP_Resource resource, | |
73 const PP_VideoCaptureDeviceInfo_Dev& info, | |
74 const std::vector<pp::Buffer_Dev>& buffers) { | |
75 capture_info_ = info; | |
76 buffers_ = buffers; | |
77 CreateYUVTextures(); | |
78 } | |
79 | |
80 virtual void OnStatus(PP_Resource resource, uint32_t status) { | |
81 } | |
82 | |
83 virtual void OnError(PP_Resource resource, uint32_t error) { | |
84 } | |
85 | |
86 virtual void OnBufferReady(PP_Resource resource, uint32_t buffer) { | |
87 const char* data = static_cast<const char*>(buffers_[buffer].data()); | |
88 int32_t width = capture_info_.width; | |
89 int32_t height = capture_info_.height; | |
90 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); | |
91 gles2_if_->TexSubImage2D( | |
92 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | |
93 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |
94 | |
95 data += width * height; | |
96 width /= 2; | |
97 height /= 2; | |
98 | |
99 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); | |
100 gles2_if_->TexSubImage2D( | |
101 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | |
102 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |
103 | |
104 data += width * height; | |
105 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); | |
106 gles2_if_->TexSubImage2D( | |
107 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | |
108 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |
109 | |
110 video_capture_.ReuseBuffer(buffer); | |
111 if (is_painting_) | |
112 needs_paint_ = true; | |
113 else | |
114 Render(); | |
115 } | |
116 | |
117 private: | 61 private: |
118 void Render(); | 62 void Render(); |
119 | 63 |
120 // GL-related functions. | 64 // GL-related functions. |
121 void InitGL(); | 65 void InitGL(); |
122 GLuint CreateTexture(int32_t width, int32_t height, int unit); | 66 GLuint CreateTexture(int32_t width, int32_t height, int unit); |
123 void CreateGLObjects(); | 67 void CreateGLObjects(); |
124 void CreateShader(GLuint program, GLenum type, const char* source, int size); | 68 void CreateShader(GLuint program, GLenum type, const char* source, int size); |
125 void PaintFinished(int32_t result); | 69 void PaintFinished(int32_t result); |
126 void CreateYUVTextures(); | 70 void CreateYUVTextures(); |
127 | 71 |
128 void Open(const pp::DeviceRef_Dev& device); | 72 // Callback that is invoked when new frames are recevied. |
129 void Stop(); | 73 void OnGetFrame(int32_t result, pp::VideoFrame frame); |
130 void Start(); | |
131 void EnumerateDevicesFinished(int32_t result, | |
132 std::vector<pp::DeviceRef_Dev>& devices); | |
133 void OpenFinished(int32_t result); | |
134 | |
135 static void MonitorDeviceChangeCallback(void* user_data, | |
136 uint32_t device_count, | |
137 const PP_Resource devices[]); | |
138 | 74 |
139 pp::Size position_size_; | 75 pp::Size position_size_; |
140 bool is_painting_; | 76 bool is_painting_; |
141 bool needs_paint_; | 77 bool needs_paint_; |
142 GLuint texture_y_; | 78 GLuint texture_y_; |
143 GLuint texture_u_; | 79 GLuint texture_u_; |
144 GLuint texture_v_; | 80 GLuint texture_v_; |
145 pp::VideoCapture_Dev video_capture_; | 81 pp::MediaStreamVideoTrack video_track_; |
146 PP_VideoCaptureDeviceInfo_Dev capture_info_; | 82 pp::CompletionCallbackFactory<MediaStreamVideoDemoInstance> callback_factory_; |
147 std::vector<pp::Buffer_Dev> buffers_; | |
148 pp::CompletionCallbackFactory<VCDemoInstance> callback_factory_; | |
149 | 83 |
150 // Unowned pointers. | 84 // Unowned pointers. |
151 const struct PPB_OpenGLES2* gles2_if_; | 85 const struct PPB_OpenGLES2* gles2_if_; |
152 | 86 |
153 // Owned data. | 87 // Owned data. |
154 pp::Graphics3D* context_; | 88 pp::Graphics3D* context_; |
155 | 89 |
156 std::vector<pp::DeviceRef_Dev> enumerate_devices_; | 90 pp::Size frame_size_; |
157 std::vector<pp::DeviceRef_Dev> monitor_devices_; | |
158 }; | 91 }; |
159 | 92 |
160 VCDemoInstance::VCDemoInstance(PP_Instance instance, pp::Module* module) | 93 MediaStreamVideoDemoInstance::MediaStreamVideoDemoInstance( |
| 94 PP_Instance instance, pp::Module* module) |
161 : pp::Instance(instance), | 95 : pp::Instance(instance), |
162 pp::Graphics3DClient(this), | 96 pp::Graphics3DClient(this), |
163 pp::VideoCaptureClient_Dev(this), | |
164 is_painting_(false), | 97 is_painting_(false), |
165 needs_paint_(false), | 98 needs_paint_(false), |
166 texture_y_(0), | 99 texture_y_(0), |
167 texture_u_(0), | 100 texture_u_(0), |
168 texture_v_(0), | 101 texture_v_(0), |
169 video_capture_(this), | |
170 callback_factory_(this), | 102 callback_factory_(this), |
171 context_(NULL) { | 103 context_(NULL) { |
172 gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( | 104 gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( |
173 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); | 105 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
174 PP_DCHECK(gles2_if_); | 106 PP_DCHECK(gles2_if_); |
175 | |
176 capture_info_.width = 320; | |
177 capture_info_.height = 240; | |
178 capture_info_.frames_per_second = 30; | |
179 } | 107 } |
180 | 108 |
181 VCDemoInstance::~VCDemoInstance() { | 109 MediaStreamVideoDemoInstance::~MediaStreamVideoDemoInstance() { |
182 video_capture_.MonitorDeviceChange(NULL, NULL); | |
183 delete context_; | 110 delete context_; |
184 } | 111 } |
185 | 112 |
186 void VCDemoInstance::DidChangeView( | 113 void MediaStreamVideoDemoInstance::DidChangeView( |
187 const pp::Rect& position, const pp::Rect& clip_ignored) { | 114 const pp::Rect& position, const pp::Rect& clip_ignored) { |
188 if (position.width() == 0 || position.height() == 0) | 115 if (position.width() == 0 || position.height() == 0) |
189 return; | 116 return; |
190 if (position.size() == position_size_) | 117 if (position.size() == position_size_) |
191 return; | 118 return; |
192 | 119 |
193 position_size_ = position.size(); | 120 position_size_ = position.size(); |
194 | 121 |
195 // Initialize graphics. | 122 // Initialize graphics. |
196 InitGL(); | 123 InitGL(); |
197 | |
198 Render(); | 124 Render(); |
199 } | 125 } |
200 | 126 |
201 void VCDemoInstance::HandleMessage(const pp::Var& message_data) { | 127 void MediaStreamVideoDemoInstance::HandleMessage(const pp::Var& var_message) { |
202 if (message_data.is_string()) { | 128 if (!var_message.is_dictionary()) |
203 std::string event = message_data.AsString(); | 129 return; |
204 if (event == "PageInitialized") { | 130 pp::VarDictionary var_dictionary_message(var_message); |
205 int32_t result = video_capture_.MonitorDeviceChange( | 131 pp::Var var_track = var_dictionary_message.Get("track"); |
206 &VCDemoInstance::MonitorDeviceChangeCallback, this); | 132 if (!var_track.is_resource()) |
207 if (result != PP_OK) | 133 return; |
208 PostMessage(pp::Var("MonitorDeviceChangeFailed")); | |
209 | 134 |
210 pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> > | 135 pp::Resource resource_track = pp::VarResource_Dev(var_track).AsResource(); |
211 callback = callback_factory_.NewCallbackWithOutput( | 136 |
212 &VCDemoInstance::EnumerateDevicesFinished); | 137 video_track_ = pp::MediaStreamVideoTrack(resource_track); |
213 result = video_capture_.EnumerateDevices(callback); | 138 |
214 if (result != PP_OK_COMPLETIONPENDING) | 139 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
215 PostMessage(pp::Var("EnumerationFailed")); | 140 &MediaStreamVideoDemoInstance::OnGetFrame)); |
216 } else if (event == "UseDefault") { | |
217 Open(pp::DeviceRef_Dev()); | |
218 } else if (event == "Stop") { | |
219 Stop(); | |
220 } else if (event == "Start") { | |
221 Start(); | |
222 } else if (event.find("Monitor:") == 0) { | |
223 std::string index_str = event.substr(strlen("Monitor:")); | |
224 int index = atoi(index_str.c_str()); | |
225 if (index >= 0 && index < static_cast<int>(monitor_devices_.size())) | |
226 Open(monitor_devices_[index]); | |
227 else | |
228 PP_NOTREACHED(); | |
229 } else if (event.find("Enumerate:") == 0) { | |
230 std::string index_str = event.substr(strlen("Enumerate:")); | |
231 int index = atoi(index_str.c_str()); | |
232 if (index >= 0 && index < static_cast<int>(enumerate_devices_.size())) | |
233 Open(enumerate_devices_[index]); | |
234 else | |
235 PP_NOTREACHED(); | |
236 } | |
237 } | |
238 } | 141 } |
239 | 142 |
240 void VCDemoInstance::InitGL() { | 143 void MediaStreamVideoDemoInstance::InitGL() { |
241 PP_DCHECK(position_size_.width() && position_size_.height()); | 144 PP_DCHECK(position_size_.width() && position_size_.height()); |
242 is_painting_ = false; | 145 is_painting_ = false; |
243 | 146 |
244 delete context_; | 147 delete context_; |
245 int32_t attributes[] = { | 148 int32_t attributes[] = { |
246 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0, | 149 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0, |
247 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, | 150 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, |
248 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, | 151 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, |
249 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, | 152 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, |
250 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, | 153 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, |
(...skipping 12 matching lines...) Expand all Loading... |
263 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); | 166 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); |
264 gles2_if_->Viewport(context_->pp_resource(), 0, 0, | 167 gles2_if_->Viewport(context_->pp_resource(), 0, 0, |
265 position_size_.width(), position_size_.height()); | 168 position_size_.width(), position_size_.height()); |
266 | 169 |
267 BindGraphics(*context_); | 170 BindGraphics(*context_); |
268 AssertNoGLError(); | 171 AssertNoGLError(); |
269 | 172 |
270 CreateGLObjects(); | 173 CreateGLObjects(); |
271 } | 174 } |
272 | 175 |
273 void VCDemoInstance::Render() { | 176 void MediaStreamVideoDemoInstance::Render() { |
274 PP_DCHECK(!is_painting_); | 177 PP_DCHECK(!is_painting_); |
275 is_painting_ = true; | 178 is_painting_ = true; |
276 needs_paint_ = false; | 179 needs_paint_ = false; |
277 if (texture_y_) { | 180 if (texture_y_) { |
278 gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); | 181 gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); |
279 } else { | 182 } else { |
280 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); | 183 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); |
281 } | 184 } |
282 pp::CompletionCallback cb = callback_factory_.NewCallback( | 185 pp::CompletionCallback cb = callback_factory_.NewCallback( |
283 &VCDemoInstance::PaintFinished); | 186 &MediaStreamVideoDemoInstance::PaintFinished); |
284 context_->SwapBuffers(cb); | 187 context_->SwapBuffers(cb); |
285 } | 188 } |
286 | 189 |
287 void VCDemoInstance::PaintFinished(int32_t result) { | 190 void MediaStreamVideoDemoInstance::PaintFinished(int32_t result) { |
288 is_painting_ = false; | 191 is_painting_ = false; |
289 if (needs_paint_) | 192 if (needs_paint_) |
290 Render(); | 193 Render(); |
291 } | 194 } |
292 | 195 |
293 GLuint VCDemoInstance::CreateTexture(int32_t width, int32_t height, int unit) { | 196 GLuint MediaStreamVideoDemoInstance::CreateTexture( |
| 197 int32_t width, int32_t height, int unit) { |
294 GLuint texture_id; | 198 GLuint texture_id; |
295 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); | 199 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); |
296 AssertNoGLError(); | 200 AssertNoGLError(); |
297 // Assign parameters. | 201 // Assign parameters. |
298 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit); | 202 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit); |
299 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); | 203 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); |
300 gles2_if_->TexParameteri( | 204 gles2_if_->TexParameteri( |
301 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | 205 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
302 GL_NEAREST); | 206 GL_NEAREST); |
303 gles2_if_->TexParameteri( | 207 gles2_if_->TexParameteri( |
304 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, | 208 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
305 GL_NEAREST); | 209 GL_NEAREST); |
306 gles2_if_->TexParameterf( | 210 gles2_if_->TexParameterf( |
307 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, | 211 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
308 GL_CLAMP_TO_EDGE); | 212 GL_CLAMP_TO_EDGE); |
309 gles2_if_->TexParameterf( | 213 gles2_if_->TexParameterf( |
310 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, | 214 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
311 GL_CLAMP_TO_EDGE); | 215 GL_CLAMP_TO_EDGE); |
312 | 216 |
313 // Allocate texture. | 217 // Allocate texture. |
314 gles2_if_->TexImage2D( | 218 gles2_if_->TexImage2D( |
315 context_->pp_resource(), GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, | 219 context_->pp_resource(), GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, |
316 GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); | 220 GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); |
317 AssertNoGLError(); | 221 AssertNoGLError(); |
318 return texture_id; | 222 return texture_id; |
319 } | 223 } |
320 | 224 |
321 void VCDemoInstance::CreateGLObjects() { | 225 void MediaStreamVideoDemoInstance::CreateGLObjects() { |
322 // Code and constants for shader. | 226 // Code and constants for shader. |
323 static const char kVertexShader[] = | 227 static const char kVertexShader[] = |
324 "varying vec2 v_texCoord; \n" | 228 "varying vec2 v_texCoord; \n" |
325 "attribute vec4 a_position; \n" | 229 "attribute vec4 a_position; \n" |
326 "attribute vec2 a_texCoord; \n" | 230 "attribute vec2 a_texCoord; \n" |
327 "void main() \n" | 231 "void main() \n" |
328 "{ \n" | 232 "{ \n" |
329 " v_texCoord = a_texCoord; \n" | 233 " v_texCoord = a_texCoord; \n" |
330 " gl_Position = a_position; \n" | 234 " gl_Position = a_position; \n" |
331 "}"; | 235 "}"; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 gles2_if_->EnableVertexAttribArray(context, pos_location); | 300 gles2_if_->EnableVertexAttribArray(context, pos_location); |
397 gles2_if_->VertexAttribPointer(context, pos_location, 2, | 301 gles2_if_->VertexAttribPointer(context, pos_location, 2, |
398 GL_FLOAT, GL_FALSE, 0, 0); | 302 GL_FLOAT, GL_FALSE, 0, 0); |
399 gles2_if_->EnableVertexAttribArray(context, tc_location); | 303 gles2_if_->EnableVertexAttribArray(context, tc_location); |
400 gles2_if_->VertexAttribPointer( | 304 gles2_if_->VertexAttribPointer( |
401 context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, | 305 context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
402 static_cast<float*>(0) + 8); // Skip position coordinates. | 306 static_cast<float*>(0) + 8); // Skip position coordinates. |
403 AssertNoGLError(); | 307 AssertNoGLError(); |
404 } | 308 } |
405 | 309 |
406 void VCDemoInstance::CreateShader( | 310 void MediaStreamVideoDemoInstance::CreateShader( |
407 GLuint program, GLenum type, const char* source, int size) { | 311 GLuint program, GLenum type, const char* source, int size) { |
408 PP_Resource context = context_->pp_resource(); | 312 PP_Resource context = context_->pp_resource(); |
409 GLuint shader = gles2_if_->CreateShader(context, type); | 313 GLuint shader = gles2_if_->CreateShader(context, type); |
410 gles2_if_->ShaderSource(context, shader, 1, &source, &size); | 314 gles2_if_->ShaderSource(context, shader, 1, &source, &size); |
411 gles2_if_->CompileShader(context, shader); | 315 gles2_if_->CompileShader(context, shader); |
412 gles2_if_->AttachShader(context, program, shader); | 316 gles2_if_->AttachShader(context, program, shader); |
413 gles2_if_->DeleteShader(context, shader); | 317 gles2_if_->DeleteShader(context, shader); |
414 } | 318 } |
415 | 319 |
416 void VCDemoInstance::CreateYUVTextures() { | 320 void MediaStreamVideoDemoInstance::CreateYUVTextures() { |
417 int32_t width = capture_info_.width; | 321 int32_t width = frame_size_.width(); |
418 int32_t height = capture_info_.height; | 322 int32_t height = frame_size_.height(); |
| 323 if (width == 0 || height == 0) |
| 324 return; |
| 325 if (texture_y_) |
| 326 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_y_); |
| 327 if (texture_u_) |
| 328 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_u_); |
| 329 if (texture_v_) |
| 330 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_v_); |
419 texture_y_ = CreateTexture(width, height, 0); | 331 texture_y_ = CreateTexture(width, height, 0); |
420 | 332 |
421 width /= 2; | 333 width /= 2; |
422 height /= 2; | 334 height /= 2; |
423 texture_u_ = CreateTexture(width, height, 1); | 335 texture_u_ = CreateTexture(width, height, 1); |
424 texture_v_ = CreateTexture(width, height, 2); | 336 texture_v_ = CreateTexture(width, height, 2); |
425 } | 337 } |
426 | 338 |
427 void VCDemoInstance::Open(const pp::DeviceRef_Dev& device) { | 339 void MediaStreamVideoDemoInstance::OnGetFrame( |
428 pp::CompletionCallback callback = callback_factory_.NewCallback( | 340 int32_t result, pp::VideoFrame frame) { |
429 &VCDemoInstance::OpenFinished); | 341 if (result != PP_OK) |
430 int32_t result = video_capture_.Open(device, capture_info_, 4, callback); | 342 return; |
431 if (result != PP_OK_COMPLETIONPENDING) | 343 const char* data = static_cast<const char*>(frame.GetDataBuffer()); |
432 PostMessage(pp::Var("OpenFailed")); | 344 pp::Size size; |
| 345 PP_DCHECK(frame.GetSize(&size)); |
| 346 if (size != frame_size_) { |
| 347 frame_size_ = size; |
| 348 CreateYUVTextures(); |
| 349 } |
| 350 |
| 351 int32_t width = frame_size_.width(); |
| 352 int32_t height = frame_size_.height(); |
| 353 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
| 354 gles2_if_->TexSubImage2D( |
| 355 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| 356 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 357 |
| 358 data += width * height; |
| 359 width /= 2; |
| 360 height /= 2; |
| 361 |
| 362 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); |
| 363 gles2_if_->TexSubImage2D( |
| 364 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| 365 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 366 |
| 367 data += width * height; |
| 368 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); |
| 369 gles2_if_->TexSubImage2D( |
| 370 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| 371 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 372 |
| 373 if (is_painting_) |
| 374 needs_paint_ = true; |
| 375 else |
| 376 Render(); |
| 377 |
| 378 video_track_.RecycleFrame(frame); |
| 379 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
| 380 &MediaStreamVideoDemoInstance::OnGetFrame)); |
433 } | 381 } |
434 | 382 |
435 void VCDemoInstance::Stop() { | 383 pp::Instance* MediaStreamVideoModule::CreateInstance(PP_Instance instance) { |
436 if (video_capture_.StopCapture() != PP_OK) | 384 return new MediaStreamVideoDemoInstance(instance, this); |
437 PostMessage(pp::Var("StopFailed")); | |
438 } | |
439 | |
440 void VCDemoInstance::Start() { | |
441 if (video_capture_.StartCapture() != PP_OK) | |
442 PostMessage(pp::Var("StartFailed")); | |
443 } | |
444 | |
445 void VCDemoInstance::EnumerateDevicesFinished( | |
446 int32_t result, | |
447 std::vector<pp::DeviceRef_Dev>& devices) { | |
448 if (result == PP_OK) { | |
449 enumerate_devices_.swap(devices); | |
450 std::string device_names = "Enumerate:"; | |
451 for (size_t index = 0; index < enumerate_devices_.size(); ++index) { | |
452 pp::Var name = enumerate_devices_[index].GetName(); | |
453 PP_DCHECK(name.is_string()); | |
454 | |
455 if (index != 0) | |
456 device_names += kDelimiter; | |
457 device_names += name.AsString(); | |
458 } | |
459 PostMessage(pp::Var(device_names)); | |
460 } else { | |
461 PostMessage(pp::Var("EnumerationFailed")); | |
462 } | |
463 } | |
464 | |
465 void VCDemoInstance::OpenFinished(int32_t result) { | |
466 if (result == PP_OK) | |
467 Start(); | |
468 else | |
469 PostMessage(pp::Var("OpenFailed")); | |
470 } | |
471 | |
472 // static | |
473 void VCDemoInstance::MonitorDeviceChangeCallback(void* user_data, | |
474 uint32_t device_count, | |
475 const PP_Resource devices[]) { | |
476 VCDemoInstance* thiz = static_cast<VCDemoInstance*>(user_data); | |
477 | |
478 std::string device_names = "Monitor:"; | |
479 thiz->monitor_devices_.clear(); | |
480 thiz->monitor_devices_.reserve(device_count); | |
481 for (size_t index = 0; index < device_count; ++index) { | |
482 thiz->monitor_devices_.push_back(pp::DeviceRef_Dev(devices[index])); | |
483 pp::Var name = thiz->monitor_devices_.back().GetName(); | |
484 PP_DCHECK(name.is_string()); | |
485 | |
486 if (index != 0) | |
487 device_names += kDelimiter; | |
488 device_names += name.AsString(); | |
489 } | |
490 thiz->PostMessage(pp::Var(device_names)); | |
491 } | |
492 | |
493 pp::Instance* VCDemoModule::CreateInstance(PP_Instance instance) { | |
494 return new VCDemoInstance(instance, this); | |
495 } | 385 } |
496 | 386 |
497 } // anonymous namespace | 387 } // anonymous namespace |
498 | 388 |
499 namespace pp { | 389 namespace pp { |
500 // Factory function for your specialization of the Module object. | 390 // Factory function for your specialization of the Module object. |
501 Module* CreateModule() { | 391 Module* CreateModule() { |
502 return new VCDemoModule(); | 392 return new MediaStreamVideoModule(); |
503 } | 393 } |
504 } // namespace pp | 394 } // namespace pp |
OLD | NEW |