OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 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 <vector> |
| 6 |
5 #include "ppapi/c/pp_errors.h" | 7 #include "ppapi/c/pp_errors.h" |
6 #include "ppapi/c/ppb_opengles2.h" | 8 #include "ppapi/c/ppb_opengles2.h" |
7 #include "ppapi/cpp/completion_callback.h" | 9 #include "ppapi/cpp/completion_callback.h" |
8 #include "ppapi/cpp/graphics_3d.h" | 10 #include "ppapi/cpp/graphics_3d.h" |
9 #include "ppapi/cpp/graphics_3d_client.h" | 11 #include "ppapi/cpp/graphics_3d_client.h" |
10 #include "ppapi/cpp/instance.h" | 12 #include "ppapi/cpp/instance.h" |
11 #include "ppapi/cpp/media_stream_video_track.h" | 13 #include "ppapi/cpp/media_stream_video_track.h" |
12 #include "ppapi/cpp/module.h" | 14 #include "ppapi/cpp/module.h" |
13 #include "ppapi/cpp/rect.h" | 15 #include "ppapi/cpp/rect.h" |
14 #include "ppapi/cpp/var.h" | 16 #include "ppapi/cpp/var.h" |
15 #include "ppapi/cpp/video_frame.h" | 17 #include "ppapi/cpp/video_frame.h" |
16 #include "ppapi/lib/gl/include/GLES2/gl2.h" | 18 #include "ppapi/lib/gl/include/GLES2/gl2.h" |
| 19 #include "ppapi/lib/gl/include/GLES2/gl2ext.h" |
17 #include "ppapi/utility/completion_callback_factory.h" | 20 #include "ppapi/utility/completion_callback_factory.h" |
18 | 21 |
19 // When compiling natively on Windows, PostMessage can be #define-d to | 22 // When compiling natively on Windows, PostMessage can be #define-d to |
20 // something else. | 23 // something else. |
21 #ifdef PostMessage | 24 #ifdef PostMessage |
22 #undef PostMessage | 25 #undef PostMessage |
23 #endif | 26 #endif |
24 | 27 |
25 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a | 28 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a |
26 // function to preserve line number information in the failure message. | 29 // function to preserve line number information in the failure message. |
(...skipping 19 matching lines...) Expand all Loading... |
46 virtual ~MediaStreamVideoDemoInstance(); | 49 virtual ~MediaStreamVideoDemoInstance(); |
47 | 50 |
48 // pp::Instance implementation (see PPP_Instance). | 51 // pp::Instance implementation (see PPP_Instance). |
49 virtual void DidChangeView(const pp::Rect& position, | 52 virtual void DidChangeView(const pp::Rect& position, |
50 const pp::Rect& clip_ignored); | 53 const pp::Rect& clip_ignored); |
51 virtual void HandleMessage(const pp::Var& message_data); | 54 virtual void HandleMessage(const pp::Var& message_data); |
52 | 55 |
53 // pp::Graphics3DClient implementation. | 56 // pp::Graphics3DClient implementation. |
54 virtual void Graphics3DContextLost() { | 57 virtual void Graphics3DContextLost() { |
55 InitGL(); | 58 InitGL(); |
56 CreateYUVTextures(); | 59 CreateTextures(); |
57 Render(); | 60 Render(); |
58 } | 61 } |
59 | 62 |
60 private: | 63 private: |
| 64 void DrawYUV(); |
| 65 void DrawRGB(); |
61 void Render(); | 66 void Render(); |
62 | 67 |
63 // GL-related functions. | 68 // GL-related functions. |
64 void InitGL(); | 69 void InitGL(); |
65 GLuint CreateTexture(int32_t width, int32_t height, int unit); | 70 GLuint CreateTexture(int32_t width, int32_t height, int unit, bool rgba); |
66 void CreateGLObjects(); | 71 void CreateGLObjects(); |
67 void CreateShader(GLuint program, GLenum type, const char* source, int size); | 72 void CreateShader(GLuint program, GLenum type, const char* source, int size); |
68 void PaintFinished(int32_t result); | 73 void PaintFinished(int32_t result); |
69 void CreateYUVTextures(); | 74 void CreateTextures(); |
| 75 void ConfigureTrack(); |
70 | 76 |
71 // Callback that is invoked when new frames are recevied. | 77 |
| 78 // MediaStreamVideoTrack callbacks. |
| 79 void OnConfigure(int32_t result); |
72 void OnGetFrame(int32_t result, pp::VideoFrame frame); | 80 void OnGetFrame(int32_t result, pp::VideoFrame frame); |
73 | 81 |
74 pp::Size position_size_; | 82 pp::Size position_size_; |
75 bool is_painting_; | 83 bool is_painting_; |
76 bool needs_paint_; | 84 bool needs_paint_; |
| 85 bool is_bgra_; |
| 86 GLuint program_yuv_; |
| 87 GLuint program_rgb_; |
| 88 GLuint buffer_; |
77 GLuint texture_y_; | 89 GLuint texture_y_; |
78 GLuint texture_u_; | 90 GLuint texture_u_; |
79 GLuint texture_v_; | 91 GLuint texture_v_; |
| 92 GLuint texture_rgb_; |
80 pp::MediaStreamVideoTrack video_track_; | 93 pp::MediaStreamVideoTrack video_track_; |
81 pp::CompletionCallbackFactory<MediaStreamVideoDemoInstance> callback_factory_; | 94 pp::CompletionCallbackFactory<MediaStreamVideoDemoInstance> callback_factory_; |
| 95 std::vector<int32_t> attrib_list_; |
| 96 |
| 97 // MediaStreamVideoTrack attributes: |
| 98 bool need_config_; |
| 99 PP_VideoFrame_Format attrib_format_; |
| 100 int32_t attrib_width_; |
| 101 int32_t attrib_height_; |
82 | 102 |
83 // Unowned pointers. | 103 // Unowned pointers. |
84 const struct PPB_OpenGLES2* gles2_if_; | 104 const struct PPB_OpenGLES2* gles2_if_; |
85 | 105 |
86 // Owned data. | 106 // Owned data. |
87 pp::Graphics3D* context_; | 107 pp::Graphics3D* context_; |
88 | 108 |
89 pp::Size frame_size_; | 109 pp::Size frame_size_; |
90 }; | 110 }; |
91 | 111 |
92 MediaStreamVideoDemoInstance::MediaStreamVideoDemoInstance( | 112 MediaStreamVideoDemoInstance::MediaStreamVideoDemoInstance( |
93 PP_Instance instance, pp::Module* module) | 113 PP_Instance instance, pp::Module* module) |
94 : pp::Instance(instance), | 114 : pp::Instance(instance), |
95 pp::Graphics3DClient(this), | 115 pp::Graphics3DClient(this), |
96 is_painting_(false), | 116 is_painting_(false), |
97 needs_paint_(false), | 117 needs_paint_(false), |
| 118 is_bgra_(false), |
98 texture_y_(0), | 119 texture_y_(0), |
99 texture_u_(0), | 120 texture_u_(0), |
100 texture_v_(0), | 121 texture_v_(0), |
| 122 texture_rgb_(0), |
101 callback_factory_(this), | 123 callback_factory_(this), |
| 124 need_config_(false), |
| 125 attrib_format_(PP_VIDEOFRAME_FORMAT_I420), |
| 126 attrib_width_(0), |
| 127 attrib_height_(0), |
102 context_(NULL) { | 128 context_(NULL) { |
103 gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( | 129 gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( |
104 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); | 130 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
105 PP_DCHECK(gles2_if_); | 131 PP_DCHECK(gles2_if_); |
106 } | 132 } |
107 | 133 |
108 MediaStreamVideoDemoInstance::~MediaStreamVideoDemoInstance() { | 134 MediaStreamVideoDemoInstance::~MediaStreamVideoDemoInstance() { |
109 delete context_; | 135 delete context_; |
110 } | 136 } |
111 | 137 |
112 void MediaStreamVideoDemoInstance::DidChangeView( | 138 void MediaStreamVideoDemoInstance::DidChangeView( |
113 const pp::Rect& position, const pp::Rect& clip_ignored) { | 139 const pp::Rect& position, const pp::Rect& clip_ignored) { |
114 if (position.width() == 0 || position.height() == 0) | 140 if (position.width() == 0 || position.height() == 0) |
115 return; | 141 return; |
116 if (position.size() == position_size_) | 142 if (position.size() == position_size_) |
117 return; | 143 return; |
118 | 144 |
119 position_size_ = position.size(); | 145 position_size_ = position.size(); |
120 | 146 |
121 // Initialize graphics. | 147 // Initialize graphics. |
122 InitGL(); | 148 InitGL(); |
123 Render(); | 149 Render(); |
124 } | 150 } |
125 | 151 |
126 void MediaStreamVideoDemoInstance::HandleMessage(const pp::Var& var_message) { | 152 void MediaStreamVideoDemoInstance::HandleMessage(const pp::Var& var_message) { |
127 if (!var_message.is_dictionary()) | 153 if (!var_message.is_dictionary()) |
128 return; | 154 return; |
| 155 |
129 pp::VarDictionary var_dictionary_message(var_message); | 156 pp::VarDictionary var_dictionary_message(var_message); |
130 pp::Var var_track = var_dictionary_message.Get("track"); | 157 std::string command = var_dictionary_message.Get("command").AsString(); |
131 if (!var_track.is_resource()) | |
132 return; | |
133 | 158 |
134 pp::Resource resource_track = var_track.AsResource(); | 159 if (command == "init") { |
135 | 160 pp::Var var_track = var_dictionary_message.Get("track"); |
136 video_track_ = pp::MediaStreamVideoTrack(resource_track); | 161 if (!var_track.is_resource()) |
137 | 162 return; |
138 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( | 163 pp::Resource resource_track = var_track.AsResource(); |
139 &MediaStreamVideoDemoInstance::OnGetFrame)); | 164 video_track_ = pp::MediaStreamVideoTrack(resource_track); |
| 165 ConfigureTrack(); |
| 166 } else if (command == "format") { |
| 167 std::string str_format = var_dictionary_message.Get("format").AsString(); |
| 168 if (str_format == "YV12") { |
| 169 attrib_format_ = PP_VIDEOFRAME_FORMAT_YV12; |
| 170 } else if (str_format == "I420") { |
| 171 attrib_format_ = PP_VIDEOFRAME_FORMAT_I420; |
| 172 } else if (str_format == "BGRA") { |
| 173 attrib_format_ = PP_VIDEOFRAME_FORMAT_BGRA; |
| 174 } else { |
| 175 attrib_format_ = PP_VIDEOFRAME_FORMAT_UNKNOWN; |
| 176 } |
| 177 need_config_ = true; |
| 178 } else if (command == "size") { |
| 179 attrib_width_ = var_dictionary_message.Get("width").AsInt(); |
| 180 attrib_height_ = var_dictionary_message.Get("height").AsInt(); |
| 181 need_config_ = true; |
| 182 } |
140 } | 183 } |
141 | 184 |
142 void MediaStreamVideoDemoInstance::InitGL() { | 185 void MediaStreamVideoDemoInstance::InitGL() { |
143 PP_DCHECK(position_size_.width() && position_size_.height()); | 186 PP_DCHECK(position_size_.width() && position_size_.height()); |
144 is_painting_ = false; | 187 is_painting_ = false; |
145 | 188 |
146 delete context_; | 189 delete context_; |
147 int32_t attributes[] = { | 190 int32_t attributes[] = { |
148 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0, | 191 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0, |
149 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, | 192 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, |
(...skipping 15 matching lines...) Expand all Loading... |
165 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); | 208 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); |
166 gles2_if_->Viewport(context_->pp_resource(), 0, 0, | 209 gles2_if_->Viewport(context_->pp_resource(), 0, 0, |
167 position_size_.width(), position_size_.height()); | 210 position_size_.width(), position_size_.height()); |
168 | 211 |
169 BindGraphics(*context_); | 212 BindGraphics(*context_); |
170 AssertNoGLError(); | 213 AssertNoGLError(); |
171 | 214 |
172 CreateGLObjects(); | 215 CreateGLObjects(); |
173 } | 216 } |
174 | 217 |
| 218 void MediaStreamVideoDemoInstance::DrawYUV() { |
| 219 PP_Resource context = context_->pp_resource(); |
| 220 static const float kColorMatrix[9] = { |
| 221 1.1643828125f, 1.1643828125f, 1.1643828125f, |
| 222 0.0f, -0.39176171875f, 2.017234375f, |
| 223 1.59602734375f, -0.81296875f, 0.0f |
| 224 }; |
| 225 |
| 226 gles2_if_->UseProgram(context, program_yuv_); |
| 227 gles2_if_->Uniform1i(context, gles2_if_->GetUniformLocation( |
| 228 context, program_yuv_, "y_texture"), 0); |
| 229 gles2_if_->Uniform1i(context, gles2_if_->GetUniformLocation( |
| 230 context, program_yuv_, "u_texture"), 1); |
| 231 gles2_if_->Uniform1i(context, gles2_if_->GetUniformLocation( |
| 232 context, program_yuv_, "v_texture"), 2); |
| 233 gles2_if_->UniformMatrix3fv( |
| 234 context, |
| 235 gles2_if_->GetUniformLocation(context, program_yuv_, "color_matrix"), |
| 236 1, GL_FALSE, kColorMatrix); |
| 237 AssertNoGLError(); |
| 238 |
| 239 GLint pos_location = gles2_if_->GetAttribLocation( |
| 240 context, program_yuv_, "a_position"); |
| 241 GLint tc_location = gles2_if_->GetAttribLocation( |
| 242 context, program_yuv_, "a_texCoord"); |
| 243 AssertNoGLError(); |
| 244 gles2_if_->EnableVertexAttribArray(context, pos_location); |
| 245 gles2_if_->VertexAttribPointer(context, pos_location, 2, |
| 246 GL_FLOAT, GL_FALSE, 0, 0); |
| 247 gles2_if_->EnableVertexAttribArray(context, tc_location); |
| 248 gles2_if_->VertexAttribPointer( |
| 249 context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
| 250 static_cast<float*>(0) + 16); // Skip position coordinates. |
| 251 AssertNoGLError(); |
| 252 |
| 253 gles2_if_->DrawArrays(context, GL_TRIANGLE_STRIP, 0, 4); |
| 254 AssertNoGLError(); |
| 255 } |
| 256 |
| 257 void MediaStreamVideoDemoInstance::DrawRGB() { |
| 258 PP_Resource context = context_->pp_resource(); |
| 259 gles2_if_->UseProgram(context, program_rgb_); |
| 260 gles2_if_->Uniform1i(context, |
| 261 gles2_if_->GetUniformLocation(context, program_rgb_, "rgb_texture"), 3); |
| 262 AssertNoGLError(); |
| 263 |
| 264 GLint pos_location = gles2_if_->GetAttribLocation( |
| 265 context, program_rgb_, "a_position"); |
| 266 GLint tc_location = gles2_if_->GetAttribLocation( |
| 267 context, program_rgb_, "a_texCoord"); |
| 268 AssertNoGLError(); |
| 269 gles2_if_->EnableVertexAttribArray(context, pos_location); |
| 270 gles2_if_->VertexAttribPointer(context, pos_location, 2, |
| 271 GL_FLOAT, GL_FALSE, 0, 0); |
| 272 gles2_if_->EnableVertexAttribArray(context, tc_location); |
| 273 gles2_if_->VertexAttribPointer( |
| 274 context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
| 275 static_cast<float*>(0) + 16); // Skip position coordinates. |
| 276 AssertNoGLError(); |
| 277 |
| 278 gles2_if_->DrawArrays(context, GL_TRIANGLE_STRIP, 4, 4); |
| 279 } |
| 280 |
175 void MediaStreamVideoDemoInstance::Render() { | 281 void MediaStreamVideoDemoInstance::Render() { |
176 PP_DCHECK(!is_painting_); | 282 PP_DCHECK(!is_painting_); |
177 is_painting_ = true; | 283 is_painting_ = true; |
178 needs_paint_ = false; | 284 needs_paint_ = false; |
| 285 |
179 if (texture_y_) { | 286 if (texture_y_) { |
180 gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); | 287 DrawRGB(); |
| 288 DrawYUV(); |
181 } else { | 289 } else { |
182 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); | 290 gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); |
183 } | 291 } |
184 pp::CompletionCallback cb = callback_factory_.NewCallback( | 292 pp::CompletionCallback cb = callback_factory_.NewCallback( |
185 &MediaStreamVideoDemoInstance::PaintFinished); | 293 &MediaStreamVideoDemoInstance::PaintFinished); |
186 context_->SwapBuffers(cb); | 294 context_->SwapBuffers(cb); |
187 } | 295 } |
188 | 296 |
189 void MediaStreamVideoDemoInstance::PaintFinished(int32_t result) { | 297 void MediaStreamVideoDemoInstance::PaintFinished(int32_t result) { |
190 is_painting_ = false; | 298 is_painting_ = false; |
191 if (needs_paint_) | 299 if (needs_paint_) |
192 Render(); | 300 Render(); |
193 } | 301 } |
194 | 302 |
195 GLuint MediaStreamVideoDemoInstance::CreateTexture( | 303 GLuint MediaStreamVideoDemoInstance::CreateTexture( |
196 int32_t width, int32_t height, int unit) { | 304 int32_t width, int32_t height, int unit, bool rgba) { |
197 GLuint texture_id; | 305 GLuint texture_id; |
198 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); | 306 gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); |
199 AssertNoGLError(); | 307 AssertNoGLError(); |
| 308 |
200 // Assign parameters. | 309 // Assign parameters. |
201 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit); | 310 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit); |
202 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); | 311 gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); |
203 gles2_if_->TexParameteri( | 312 gles2_if_->TexParameteri( |
204 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | 313 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
205 GL_NEAREST); | 314 GL_NEAREST); |
206 gles2_if_->TexParameteri( | 315 gles2_if_->TexParameteri( |
207 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, | 316 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
208 GL_NEAREST); | 317 GL_NEAREST); |
209 gles2_if_->TexParameterf( | 318 gles2_if_->TexParameterf( |
210 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, | 319 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
211 GL_CLAMP_TO_EDGE); | 320 GL_CLAMP_TO_EDGE); |
212 gles2_if_->TexParameterf( | 321 gles2_if_->TexParameterf( |
213 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, | 322 context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
214 GL_CLAMP_TO_EDGE); | 323 GL_CLAMP_TO_EDGE); |
215 | |
216 // Allocate texture. | 324 // Allocate texture. |
217 gles2_if_->TexImage2D( | 325 gles2_if_->TexImage2D( |
218 context_->pp_resource(), GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, | 326 context_->pp_resource(), GL_TEXTURE_2D, 0, |
219 GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); | 327 rgba ? GL_BGRA_EXT : GL_LUMINANCE, |
| 328 width, height, 0, |
| 329 rgba ? GL_BGRA_EXT : GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); |
220 AssertNoGLError(); | 330 AssertNoGLError(); |
221 return texture_id; | 331 return texture_id; |
222 } | 332 } |
223 | 333 |
224 void MediaStreamVideoDemoInstance::CreateGLObjects() { | 334 void MediaStreamVideoDemoInstance::CreateGLObjects() { |
225 // Code and constants for shader. | 335 // Code and constants for shader. |
226 static const char kVertexShader[] = | 336 static const char kVertexShader[] = |
227 "varying vec2 v_texCoord; \n" | 337 "varying vec2 v_texCoord; \n" |
228 "attribute vec4 a_position; \n" | 338 "attribute vec4 a_position; \n" |
229 "attribute vec2 a_texCoord; \n" | 339 "attribute vec2 a_texCoord; \n" |
230 "void main() \n" | 340 "void main() \n" |
231 "{ \n" | 341 "{ \n" |
232 " v_texCoord = a_texCoord; \n" | 342 " v_texCoord = a_texCoord; \n" |
233 " gl_Position = a_position; \n" | 343 " gl_Position = a_position; \n" |
234 "}"; | 344 "}"; |
235 | 345 |
236 static const char kFragmentShader[] = | 346 static const char kFragmentShaderYUV[] = |
237 "precision mediump float; \n" | 347 "precision mediump float; \n" |
238 "varying vec2 v_texCoord; \n" | 348 "varying vec2 v_texCoord; \n" |
239 "uniform sampler2D y_texture; \n" | 349 "uniform sampler2D y_texture; \n" |
240 "uniform sampler2D u_texture; \n" | 350 "uniform sampler2D u_texture; \n" |
241 "uniform sampler2D v_texture; \n" | 351 "uniform sampler2D v_texture; \n" |
242 "uniform mat3 color_matrix; \n" | 352 "uniform mat3 color_matrix; \n" |
243 "void main() \n" | 353 "void main() \n" |
244 "{ \n" | 354 "{ \n" |
245 " vec3 yuv; \n" | 355 " vec3 yuv; \n" |
246 " yuv.x = texture2D(y_texture, v_texCoord).r; \n" | 356 " yuv.x = texture2D(y_texture, v_texCoord).r; \n" |
247 " yuv.y = texture2D(u_texture, v_texCoord).r; \n" | 357 " yuv.y = texture2D(u_texture, v_texCoord).r; \n" |
248 " yuv.z = texture2D(v_texture, v_texCoord).r; \n" | 358 " yuv.z = texture2D(v_texture, v_texCoord).r; \n" |
249 " vec3 rgb = color_matrix * (yuv - vec3(0.0625, 0.5, 0.5));\n" | 359 " vec3 rgb = color_matrix * (yuv - vec3(0.0625, 0.5, 0.5));\n" |
250 " gl_FragColor = vec4(rgb, 1.0); \n" | 360 " gl_FragColor = vec4(rgb, 1.0); \n" |
251 "}"; | 361 "}"; |
252 | 362 |
253 static const float kColorMatrix[9] = { | 363 static const char kFragmentShaderRGB[] = |
254 1.1643828125f, 1.1643828125f, 1.1643828125f, | 364 "precision mediump float; \n" |
255 0.0f, -0.39176171875f, 2.017234375f, | 365 "varying vec2 v_texCoord; \n" |
256 1.59602734375f, -0.81296875f, 0.0f | 366 "uniform sampler2D rgb_texture; \n" |
257 }; | 367 "void main() \n" |
| 368 "{ \n" |
| 369 " gl_FragColor = texture2D(rgb_texture, v_texCoord); \n" |
| 370 "}"; |
258 | 371 |
259 PP_Resource context = context_->pp_resource(); | 372 PP_Resource context = context_->pp_resource(); |
260 | 373 |
261 // Create shader program. | 374 // Create shader programs. |
262 GLuint program = gles2_if_->CreateProgram(context); | 375 program_yuv_ = gles2_if_->CreateProgram(context); |
263 CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader)); | 376 CreateShader(program_yuv_, GL_VERTEX_SHADER, |
264 CreateShader( | 377 kVertexShader, sizeof(kVertexShader)); |
265 program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader)); | 378 CreateShader(program_yuv_, GL_FRAGMENT_SHADER, |
266 gles2_if_->LinkProgram(context, program); | 379 kFragmentShaderYUV, sizeof(kFragmentShaderYUV)); |
267 gles2_if_->UseProgram(context, program); | 380 gles2_if_->LinkProgram(context, program_yuv_); |
268 gles2_if_->DeleteProgram(context, program); | 381 AssertNoGLError(); |
269 gles2_if_->Uniform1i( | 382 |
270 context, gles2_if_->GetUniformLocation(context, program, "y_texture"), 0); | 383 program_rgb_ = gles2_if_->CreateProgram(context); |
271 gles2_if_->Uniform1i( | 384 CreateShader(program_rgb_, GL_VERTEX_SHADER, |
272 context, gles2_if_->GetUniformLocation(context, program, "u_texture"), 1); | 385 kVertexShader, sizeof(kVertexShader)); |
273 gles2_if_->Uniform1i( | 386 CreateShader(program_rgb_, GL_FRAGMENT_SHADER, |
274 context, gles2_if_->GetUniformLocation(context, program, "v_texture"), 2); | 387 kFragmentShaderRGB, sizeof(kFragmentShaderRGB)); |
275 gles2_if_->UniformMatrix3fv( | 388 gles2_if_->LinkProgram(context, program_rgb_); |
276 context, | |
277 gles2_if_->GetUniformLocation(context, program, "color_matrix"), | |
278 1, GL_FALSE, kColorMatrix); | |
279 AssertNoGLError(); | 389 AssertNoGLError(); |
280 | 390 |
281 // Assign vertex positions and texture coordinates to buffers for use in | 391 // Assign vertex positions and texture coordinates to buffers for use in |
282 // shader program. | 392 // shader program. |
283 static const float kVertices[] = { | 393 static const float kVertices[] = { |
284 -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. | 394 -1, 1, -1, -1, 0, 1, 0, -1, // Position coordinates. |
| 395 0, 1, 0, -1, 1, 1, 1, -1, // Position coordinates. |
| 396 0, 0, 0, 1, 1, 0, 1, 1, // Texture coordinates. |
285 0, 0, 0, 1, 1, 0, 1, 1, // Texture coordinates. | 397 0, 0, 0, 1, 1, 0, 1, 1, // Texture coordinates. |
286 }; | 398 }; |
287 | 399 |
288 GLuint buffer; | 400 gles2_if_->GenBuffers(context, 1, &buffer_); |
289 gles2_if_->GenBuffers(context, 1, &buffer); | 401 gles2_if_->BindBuffer(context, GL_ARRAY_BUFFER, buffer_); |
290 gles2_if_->BindBuffer(context, GL_ARRAY_BUFFER, buffer); | |
291 gles2_if_->BufferData(context, GL_ARRAY_BUFFER, | 402 gles2_if_->BufferData(context, GL_ARRAY_BUFFER, |
292 sizeof(kVertices), kVertices, GL_STATIC_DRAW); | 403 sizeof(kVertices), kVertices, GL_STATIC_DRAW); |
293 AssertNoGLError(); | 404 AssertNoGLError(); |
294 GLint pos_location = gles2_if_->GetAttribLocation( | |
295 context, program, "a_position"); | |
296 GLint tc_location = gles2_if_->GetAttribLocation( | |
297 context, program, "a_texCoord"); | |
298 AssertNoGLError(); | |
299 gles2_if_->EnableVertexAttribArray(context, pos_location); | |
300 gles2_if_->VertexAttribPointer(context, pos_location, 2, | |
301 GL_FLOAT, GL_FALSE, 0, 0); | |
302 gles2_if_->EnableVertexAttribArray(context, tc_location); | |
303 gles2_if_->VertexAttribPointer( | |
304 context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, | |
305 static_cast<float*>(0) + 8); // Skip position coordinates. | |
306 AssertNoGLError(); | |
307 } | 405 } |
308 | 406 |
309 void MediaStreamVideoDemoInstance::CreateShader( | 407 void MediaStreamVideoDemoInstance::CreateShader( |
310 GLuint program, GLenum type, const char* source, int size) { | 408 GLuint program, GLenum type, const char* source, int size) { |
311 PP_Resource context = context_->pp_resource(); | 409 PP_Resource context = context_->pp_resource(); |
312 GLuint shader = gles2_if_->CreateShader(context, type); | 410 GLuint shader = gles2_if_->CreateShader(context, type); |
313 gles2_if_->ShaderSource(context, shader, 1, &source, &size); | 411 gles2_if_->ShaderSource(context, shader, 1, &source, &size); |
314 gles2_if_->CompileShader(context, shader); | 412 gles2_if_->CompileShader(context, shader); |
315 gles2_if_->AttachShader(context, program, shader); | 413 gles2_if_->AttachShader(context, program, shader); |
316 gles2_if_->DeleteShader(context, shader); | 414 gles2_if_->DeleteShader(context, shader); |
317 } | 415 } |
318 | 416 |
319 void MediaStreamVideoDemoInstance::CreateYUVTextures() { | 417 void MediaStreamVideoDemoInstance::CreateTextures() { |
320 int32_t width = frame_size_.width(); | 418 int32_t width = frame_size_.width(); |
321 int32_t height = frame_size_.height(); | 419 int32_t height = frame_size_.height(); |
322 if (width == 0 || height == 0) | 420 if (width == 0 || height == 0) |
323 return; | 421 return; |
324 if (texture_y_) | 422 if (texture_y_) |
325 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_y_); | 423 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_y_); |
326 if (texture_u_) | 424 if (texture_u_) |
327 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_u_); | 425 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_u_); |
328 if (texture_v_) | 426 if (texture_v_) |
329 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_v_); | 427 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_v_); |
330 texture_y_ = CreateTexture(width, height, 0); | 428 if (texture_rgb_) |
| 429 gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_rgb_); |
| 430 texture_y_ = CreateTexture(width, height, 0, false); |
331 | 431 |
332 width /= 2; | 432 texture_u_ = CreateTexture(width / 2, height / 2, 1, false); |
333 height /= 2; | 433 texture_v_ = CreateTexture(width / 2, height / 2, 2, false); |
334 texture_u_ = CreateTexture(width, height, 1); | 434 texture_rgb_ = CreateTexture(width, height, 3, true); |
335 texture_v_ = CreateTexture(width, height, 2); | 435 } |
| 436 |
| 437 void MediaStreamVideoDemoInstance::ConfigureTrack() { |
| 438 const int32_t attrib_list[] = { |
| 439 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, attrib_format_, |
| 440 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, attrib_width_, |
| 441 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT, attrib_height_, |
| 442 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE |
| 443 }; |
| 444 video_track_.Configure(attrib_list, callback_factory_.NewCallback( |
| 445 &MediaStreamVideoDemoInstance::OnConfigure)); |
| 446 } |
| 447 |
| 448 void MediaStreamVideoDemoInstance::OnConfigure(int32_t result) { |
| 449 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
| 450 &MediaStreamVideoDemoInstance::OnGetFrame)); |
336 } | 451 } |
337 | 452 |
338 void MediaStreamVideoDemoInstance::OnGetFrame( | 453 void MediaStreamVideoDemoInstance::OnGetFrame( |
339 int32_t result, pp::VideoFrame frame) { | 454 int32_t result, pp::VideoFrame frame) { |
340 if (result != PP_OK) | 455 if (result != PP_OK) |
341 return; | 456 return; |
342 const char* data = static_cast<const char*>(frame.GetDataBuffer()); | 457 const char* data = static_cast<const char*>(frame.GetDataBuffer()); |
343 pp::Size size; | 458 pp::Size size; |
344 frame.GetSize(&size); | 459 frame.GetSize(&size); |
345 | 460 |
346 if (size != frame_size_) { | 461 if (size != frame_size_) { |
347 frame_size_ = size; | 462 frame_size_ = size; |
348 CreateYUVTextures(); | 463 CreateTextures(); |
349 } | 464 } |
350 | 465 |
| 466 is_bgra_ = (frame.GetFormat() == PP_VIDEOFRAME_FORMAT_BGRA); |
| 467 |
351 int32_t width = frame_size_.width(); | 468 int32_t width = frame_size_.width(); |
352 int32_t height = frame_size_.height(); | 469 int32_t height = frame_size_.height(); |
353 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); | 470 if (!is_bgra_) { |
354 gles2_if_->TexSubImage2D( | 471 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
355 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | 472 gles2_if_->TexSubImage2D( |
356 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | 473 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| 474 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
357 | 475 |
358 data += width * height; | 476 data += width * height; |
359 width /= 2; | 477 width /= 2; |
360 height /= 2; | 478 height /= 2; |
361 | 479 |
362 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); | 480 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); |
363 gles2_if_->TexSubImage2D( | 481 gles2_if_->TexSubImage2D( |
364 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | 482 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
365 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | 483 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
366 | 484 |
367 data += width * height; | 485 data += width * height; |
368 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); | 486 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); |
369 gles2_if_->TexSubImage2D( | 487 gles2_if_->TexSubImage2D( |
370 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, | 488 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
371 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | 489 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 490 } else { |
| 491 gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE3); |
| 492 gles2_if_->TexSubImage2D( |
| 493 context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| 494 GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); |
| 495 } |
372 | 496 |
373 if (is_painting_) | 497 if (is_painting_) |
374 needs_paint_ = true; | 498 needs_paint_ = true; |
375 else | 499 else |
376 Render(); | 500 Render(); |
377 | 501 |
378 video_track_.RecycleFrame(frame); | 502 video_track_.RecycleFrame(frame); |
379 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( | 503 if (need_config_) { |
380 &MediaStreamVideoDemoInstance::OnGetFrame)); | 504 ConfigureTrack(); |
| 505 need_config_ = false; |
| 506 } else { |
| 507 video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
| 508 &MediaStreamVideoDemoInstance::OnGetFrame)); |
| 509 } |
381 } | 510 } |
382 | 511 |
383 pp::Instance* MediaStreamVideoModule::CreateInstance(PP_Instance instance) { | 512 pp::Instance* MediaStreamVideoModule::CreateInstance(PP_Instance instance) { |
384 return new MediaStreamVideoDemoInstance(instance, this); | 513 return new MediaStreamVideoDemoInstance(instance, this); |
385 } | 514 } |
386 | 515 |
387 } // anonymous namespace | 516 } // anonymous namespace |
388 | 517 |
389 namespace pp { | 518 namespace pp { |
390 // Factory function for your specialization of the Module object. | 519 // Factory function for your specialization of the Module object. |
391 Module* CreateModule() { | 520 Module* CreateModule() { |
392 return new MediaStreamVideoModule(); | 521 return new MediaStreamVideoModule(); |
393 } | 522 } |
394 } // namespace pp | 523 } // namespace pp |
OLD | NEW |