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