| OLD | NEW |
| 1 // Copyright (c) 2014 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 <GLES2/gl2.h> | 5 #include <GLES2/gl2.h> |
| 6 #include <GLES2/gl2ext.h> | 6 #include <GLES2/gl2ext.h> |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <iostream> | 10 #include <iostream> |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "ppapi/cpp/rect.h" | 22 #include "ppapi/cpp/rect.h" |
| 23 #include "ppapi/cpp/var.h" | 23 #include "ppapi/cpp/var.h" |
| 24 #include "ppapi/cpp/video_decoder.h" | 24 #include "ppapi/cpp/video_decoder.h" |
| 25 #include "ppapi/utility/completion_callback_factory.h" | 25 #include "ppapi/utility/completion_callback_factory.h" |
| 26 | 26 |
| 27 // VP8 is more likely to work on different versions of Chrome. Undefine this | 27 // VP8 is more likely to work on different versions of Chrome. Undefine this |
| 28 // to decode H264. | 28 // to decode H264. |
| 29 #define USE_VP8_TESTDATA_INSTEAD_OF_H264 | 29 #define USE_VP8_TESTDATA_INSTEAD_OF_H264 |
| 30 #include "testdata.h" | 30 #include "testdata.h" |
| 31 | 31 |
| 32 | |
| 33 // Use assert as a poor-man's CHECK, even in non-debug mode. | 32 // Use assert as a poor-man's CHECK, even in non-debug mode. |
| 34 // Since <assert.h> redefines assert on every inclusion (it doesn't use | 33 // Since <assert.h> redefines assert on every inclusion (it doesn't use |
| 35 // include-guards), make sure this is the last file #include'd in this file. | 34 // include-guards), make sure this is the last file #include'd in this file. |
| 36 #undef NDEBUG | 35 #undef NDEBUG |
| 37 #include <assert.h> | 36 #include <assert.h> |
| 38 | 37 |
| 39 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a | 38 // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a |
| 40 // function to preserve line number information in the failure message. | 39 // function to preserve line number information in the failure message. |
| 41 #define assertNoGLError() assert(!gles2_if_->GetError(context_->pp_resource())); | 40 #define assertNoGLError() assert(!gles2_if_->GetError(context_->pp_resource())); |
| 42 | 41 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 std::ostringstream stream_; | 105 std::ostringstream stream_; |
| 107 }; | 106 }; |
| 108 | 107 |
| 109 void InitializeDecoders(); | 108 void InitializeDecoders(); |
| 110 | 109 |
| 111 // GL-related functions. | 110 // GL-related functions. |
| 112 void InitGL(); | 111 void InitGL(); |
| 113 void CreateGLObjects(); | 112 void CreateGLObjects(); |
| 114 void Create2DProgramOnce(); | 113 void Create2DProgramOnce(); |
| 115 void CreateRectangleARBProgramOnce(); | 114 void CreateRectangleARBProgramOnce(); |
| 115 void CreateExternalOESProgramOnce(); |
| 116 Shader CreateProgram(const char* vertex_shader, const char* fragment_shader); | 116 Shader CreateProgram(const char* vertex_shader, const char* fragment_shader); |
| 117 void CreateShader(GLuint program, GLenum type, const char* source, int size); | 117 void CreateShader(GLuint program, GLenum type, const char* source, int size); |
| 118 void PaintNextPicture(); | 118 void PaintNextPicture(); |
| 119 void PaintFinished(int32_t result); | 119 void PaintFinished(int32_t result); |
| 120 | 120 |
| 121 pp::Size plugin_size_; | 121 pp::Size plugin_size_; |
| 122 bool is_painting_; | 122 bool is_painting_; |
| 123 // When decode outpaces render, we queue up decoded pictures for later | 123 // When decode outpaces render, we queue up decoded pictures for later |
| 124 // painting. | 124 // painting. |
| 125 typedef std::queue<PendingPicture> PendingPictureQueue; | 125 typedef std::queue<PendingPicture> PendingPictureQueue; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 138 | 138 |
| 139 // Owned data. | 139 // Owned data. |
| 140 pp::Graphics3D* context_; | 140 pp::Graphics3D* context_; |
| 141 typedef std::vector<Decoder*> DecoderList; | 141 typedef std::vector<Decoder*> DecoderList; |
| 142 DecoderList video_decoders_; | 142 DecoderList video_decoders_; |
| 143 | 143 |
| 144 // Shader program to draw GL_TEXTURE_2D target. | 144 // Shader program to draw GL_TEXTURE_2D target. |
| 145 Shader shader_2d_; | 145 Shader shader_2d_; |
| 146 // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. | 146 // Shader program to draw GL_TEXTURE_RECTANGLE_ARB target. |
| 147 Shader shader_rectangle_arb_; | 147 Shader shader_rectangle_arb_; |
| 148 // Shader program to draw GL_TEXTURE_EXTERNAL_OES target. |
| 149 Shader shader_external_oes_; |
| 148 }; | 150 }; |
| 149 | 151 |
| 150 class Decoder { | 152 class Decoder { |
| 151 public: | 153 public: |
| 152 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d); | 154 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d); |
| 153 ~Decoder(); | 155 ~Decoder(); |
| 154 | 156 |
| 155 int id() const { return id_; } | 157 int id() const { return id_; } |
| 156 bool flushing() const { return flushing_; } | 158 bool flushing() const { return flushing_; } |
| 157 bool resetting() const { return resetting_; } | 159 bool resetting() const { return resetting_; } |
| 158 | 160 |
| 159 void Reset(); | 161 void Reset(); |
| 160 void RecyclePicture(const PP_VideoPicture& picture); | 162 void RecyclePicture(const PP_VideoPicture& picture); |
| 161 | 163 |
| 164 PP_TimeTicks GetAverageLatency() { |
| 165 return num_pictures_ ? total_latency_ / num_pictures_ : 0; |
| 166 } |
| 167 |
| 162 private: | 168 private: |
| 163 void InitializeDone(int32_t result); | 169 void InitializeDone(int32_t result); |
| 164 void Start(); | 170 void Start(); |
| 165 void DecodeNextFrame(); | 171 void DecodeNextFrame(); |
| 166 void DecodeDone(int32_t result); | 172 void DecodeDone(int32_t result); |
| 167 void PictureReady(int32_t result, PP_VideoPicture picture); | 173 void PictureReady(int32_t result, PP_VideoPicture picture); |
| 168 void FlushDone(int32_t result); | 174 void FlushDone(int32_t result); |
| 169 void ResetDone(int32_t result); | 175 void ResetDone(int32_t result); |
| 170 | 176 |
| 171 MyInstance* instance_; | 177 MyInstance* instance_; |
| 172 int id_; | 178 int id_; |
| 173 | 179 |
| 174 pp::VideoDecoder* decoder_; | 180 pp::VideoDecoder* decoder_; |
| 175 pp::CompletionCallbackFactory<Decoder> callback_factory_; | 181 pp::CompletionCallbackFactory<Decoder> callback_factory_; |
| 176 | 182 |
| 177 size_t encoded_data_next_pos_to_decode_; | 183 size_t encoded_data_next_pos_to_decode_; |
| 178 int next_picture_id_; | 184 int next_picture_id_; |
| 179 bool flushing_; | 185 bool flushing_; |
| 180 bool resetting_; | 186 bool resetting_; |
| 187 |
| 188 const PPB_Core* core_if_; |
| 189 static const int kMaxDecodeDelay = 128; |
| 190 PP_TimeTicks decode_time_[kMaxDecodeDelay]; |
| 191 PP_TimeTicks total_latency_; |
| 192 int num_pictures_; |
| 181 }; | 193 }; |
| 182 | 194 |
| 183 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 | 195 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
| 184 | 196 |
| 185 // VP8 is stored in an IVF container. | 197 // VP8 is stored in an IVF container. |
| 186 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF | 198 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF |
| 187 | 199 |
| 188 static void GetNextFrame(size_t* start_pos, size_t* end_pos) { | 200 static void GetNextFrame(size_t* start_pos, size_t* end_pos) { |
| 189 size_t current_pos = *start_pos; | 201 size_t current_pos = *start_pos; |
| 190 if (current_pos == 0) | 202 if (current_pos == 0) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 220 Decoder::Decoder(MyInstance* instance, | 232 Decoder::Decoder(MyInstance* instance, |
| 221 int id, | 233 int id, |
| 222 const pp::Graphics3D& graphics_3d) | 234 const pp::Graphics3D& graphics_3d) |
| 223 : instance_(instance), | 235 : instance_(instance), |
| 224 id_(id), | 236 id_(id), |
| 225 decoder_(new pp::VideoDecoder(instance)), | 237 decoder_(new pp::VideoDecoder(instance)), |
| 226 callback_factory_(this), | 238 callback_factory_(this), |
| 227 encoded_data_next_pos_to_decode_(0), | 239 encoded_data_next_pos_to_decode_(0), |
| 228 next_picture_id_(0), | 240 next_picture_id_(0), |
| 229 flushing_(false), | 241 flushing_(false), |
| 230 resetting_(false) { | 242 resetting_(false), |
| 243 total_latency_(0.0), |
| 244 num_pictures_(0) { |
| 245 core_if_ = static_cast<const PPB_Core*>( |
| 246 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
| 247 |
| 231 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 | 248 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
| 232 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; | 249 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; |
| 233 #else | 250 #else |
| 234 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_H264MAIN; | 251 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_H264MAIN; |
| 235 #endif | 252 #endif |
| 236 | 253 |
| 237 assert(!decoder_->is_null()); | 254 assert(!decoder_->is_null()); |
| 238 decoder_->Initialize(graphics_3d, | 255 decoder_->Initialize(graphics_3d, |
| 239 kBitstreamProfile, | 256 kBitstreamProfile, |
| 240 PP_TRUE /* allow_software_fallback */, | 257 PP_TRUE /* allow_software_fallback */, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 } | 305 } |
| 289 | 306 |
| 290 // Find the start of the next frame. | 307 // Find the start of the next frame. |
| 291 size_t start_pos = encoded_data_next_pos_to_decode_; | 308 size_t start_pos = encoded_data_next_pos_to_decode_; |
| 292 size_t end_pos; | 309 size_t end_pos; |
| 293 GetNextFrame(&start_pos, &end_pos); | 310 GetNextFrame(&start_pos, &end_pos); |
| 294 encoded_data_next_pos_to_decode_ = end_pos; | 311 encoded_data_next_pos_to_decode_ = end_pos; |
| 295 // Decode the frame. On completion, DecodeDone will call DecodeNextFrame | 312 // Decode the frame. On completion, DecodeDone will call DecodeNextFrame |
| 296 // to implement a decode loop. | 313 // to implement a decode loop. |
| 297 uint32_t size = static_cast<uint32_t>(end_pos - start_pos); | 314 uint32_t size = static_cast<uint32_t>(end_pos - start_pos); |
| 315 decode_time_[next_picture_id_ % kMaxDecodeDelay] = core_if_->GetTimeTicks(); |
| 298 decoder_->Decode(next_picture_id_++, | 316 decoder_->Decode(next_picture_id_++, |
| 299 size, | 317 size, |
| 300 kData + start_pos, | 318 kData + start_pos, |
| 301 callback_factory_.NewCallback(&Decoder::DecodeDone)); | 319 callback_factory_.NewCallback(&Decoder::DecodeDone)); |
| 302 } | 320 } |
| 303 } | 321 } |
| 304 | 322 |
| 305 void Decoder::DecodeDone(int32_t result) { | 323 void Decoder::DecodeDone(int32_t result) { |
| 306 assert(decoder_); | 324 assert(decoder_); |
| 307 // Break out of the decode loop on abort. | 325 // Break out of the decode loop on abort. |
| 308 if (result == PP_ERROR_ABORTED) | 326 if (result == PP_ERROR_ABORTED) |
| 309 return; | 327 return; |
| 310 assert(result == PP_OK); | 328 assert(result == PP_OK); |
| 311 if (!flushing_ && !resetting_) | 329 if (!flushing_ && !resetting_) |
| 312 DecodeNextFrame(); | 330 DecodeNextFrame(); |
| 313 } | 331 } |
| 314 | 332 |
| 315 void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { | 333 void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { |
| 316 assert(decoder_); | 334 assert(decoder_); |
| 317 // Break out of the get picture loop on abort. | 335 // Break out of the get picture loop on abort. |
| 318 if (result == PP_ERROR_ABORTED) | 336 if (result == PP_ERROR_ABORTED) |
| 319 return; | 337 return; |
| 320 assert(result == PP_OK); | 338 assert(result == PP_OK); |
| 339 |
| 340 num_pictures_++; |
| 341 PP_TimeTicks latency = core_if_->GetTimeTicks() - |
| 342 decode_time_[picture.decode_id % kMaxDecodeDelay]; |
| 343 total_latency_ += latency; |
| 344 |
| 321 decoder_->GetPicture( | 345 decoder_->GetPicture( |
| 322 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); | 346 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); |
| 323 instance_->PaintPicture(this, picture); | 347 instance_->PaintPicture(this, picture); |
| 324 } | 348 } |
| 325 | 349 |
| 326 void Decoder::FlushDone(int32_t result) { | 350 void Decoder::FlushDone(int32_t result) { |
| 327 assert(decoder_); | 351 assert(decoder_); |
| 328 assert(result == PP_OK || result == PP_ERROR_ABORTED); | 352 assert(result == PP_OK || result == PP_ERROR_ABORTED); |
| 329 assert(flushing_); | 353 assert(flushing_); |
| 330 flushing_ = false; | 354 flushing_ = false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 342 MyInstance::MyInstance(PP_Instance instance, pp::Module* module) | 366 MyInstance::MyInstance(PP_Instance instance, pp::Module* module) |
| 343 : pp::Instance(instance), | 367 : pp::Instance(instance), |
| 344 pp::Graphics3DClient(this), | 368 pp::Graphics3DClient(this), |
| 345 is_painting_(false), | 369 is_painting_(false), |
| 346 num_frames_rendered_(0), | 370 num_frames_rendered_(0), |
| 347 first_frame_delivered_ticks_(-1), | 371 first_frame_delivered_ticks_(-1), |
| 348 last_swap_request_ticks_(-1), | 372 last_swap_request_ticks_(-1), |
| 349 swap_ticks_(0), | 373 swap_ticks_(0), |
| 350 callback_factory_(this), | 374 callback_factory_(this), |
| 351 context_(NULL) { | 375 context_(NULL) { |
| 352 assert((console_if_ = static_cast<const PPB_Console*>( | 376 console_if_ = static_cast<const PPB_Console*>( |
| 353 module->GetBrowserInterface(PPB_CONSOLE_INTERFACE)))); | 377 pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE)); |
| 354 assert((core_if_ = static_cast<const PPB_Core*>( | 378 core_if_ = static_cast<const PPB_Core*>( |
| 355 module->GetBrowserInterface(PPB_CORE_INTERFACE)))); | 379 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
| 356 assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>( | 380 gles2_if_ = static_cast<const PPB_OpenGLES2*>( |
| 357 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)))); | 381 pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
| 382 |
| 358 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); | 383 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); |
| 359 } | 384 } |
| 360 | 385 |
| 361 MyInstance::~MyInstance() { | 386 MyInstance::~MyInstance() { |
| 362 if (!context_) | 387 if (!context_) |
| 363 return; | 388 return; |
| 364 | 389 |
| 365 PP_Resource graphics_3d = context_->pp_resource(); | 390 PP_Resource graphics_3d = context_->pp_resource(); |
| 366 if (shader_2d_.program) | 391 if (shader_2d_.program) |
| 367 gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); | 392 gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); |
| 368 if (shader_rectangle_arb_.program) | 393 if (shader_rectangle_arb_.program) |
| 369 gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program); | 394 gles2_if_->DeleteProgram(graphics_3d, shader_rectangle_arb_.program); |
| 395 if (shader_external_oes_.program) |
| 396 gles2_if_->DeleteProgram(graphics_3d, shader_external_oes_.program); |
| 370 | 397 |
| 371 for (DecoderList::iterator it = video_decoders_.begin(); | 398 for (DecoderList::iterator it = video_decoders_.begin(); |
| 372 it != video_decoders_.end(); | 399 it != video_decoders_.end(); |
| 373 ++it) | 400 ++it) |
| 374 delete *it; | 401 delete *it; |
| 375 | 402 |
| 376 delete context_; | 403 delete context_; |
| 377 } | 404 } |
| 378 | 405 |
| 379 void MyInstance::DidChangeView(const pp::Rect& position, | 406 void MyInstance::DidChangeView(const pp::Rect& position, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 x = half_width; | 475 x = half_width; |
| 449 y = half_height; | 476 y = half_height; |
| 450 } | 477 } |
| 451 | 478 |
| 452 PP_Resource graphics_3d = context_->pp_resource(); | 479 PP_Resource graphics_3d = context_->pp_resource(); |
| 453 if (picture.texture_target == GL_TEXTURE_2D) { | 480 if (picture.texture_target == GL_TEXTURE_2D) { |
| 454 Create2DProgramOnce(); | 481 Create2DProgramOnce(); |
| 455 gles2_if_->UseProgram(graphics_3d, shader_2d_.program); | 482 gles2_if_->UseProgram(graphics_3d, shader_2d_.program); |
| 456 gles2_if_->Uniform2f( | 483 gles2_if_->Uniform2f( |
| 457 graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0); | 484 graphics_3d, shader_2d_.texcoord_scale_location, 1.0, 1.0); |
| 458 } else { | 485 } else if (picture.texture_target == GL_TEXTURE_RECTANGLE_ARB) { |
| 459 assert(picture.texture_target == GL_TEXTURE_RECTANGLE_ARB); | |
| 460 CreateRectangleARBProgramOnce(); | 486 CreateRectangleARBProgramOnce(); |
| 461 gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program); | 487 gles2_if_->UseProgram(graphics_3d, shader_rectangle_arb_.program); |
| 462 gles2_if_->Uniform2f(graphics_3d, | 488 gles2_if_->Uniform2f(graphics_3d, |
| 463 shader_rectangle_arb_.texcoord_scale_location, | 489 shader_rectangle_arb_.texcoord_scale_location, |
| 464 picture.texture_size.width, | 490 picture.texture_size.width, |
| 465 picture.texture_size.height); | 491 picture.texture_size.height); |
| 492 } else { |
| 493 assert(picture.texture_target == GL_TEXTURE_EXTERNAL_OES); |
| 494 CreateExternalOESProgramOnce(); |
| 495 gles2_if_->UseProgram(graphics_3d, shader_external_oes_.program); |
| 496 gles2_if_->Uniform2f( |
| 497 graphics_3d, shader_external_oes_.texcoord_scale_location, 1.0, 1.0); |
| 466 } | 498 } |
| 467 | 499 |
| 468 gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height); | 500 gles2_if_->Viewport(graphics_3d, x, y, half_width, half_height); |
| 469 gles2_if_->ActiveTexture(graphics_3d, GL_TEXTURE0); | 501 gles2_if_->ActiveTexture(graphics_3d, GL_TEXTURE0); |
| 470 gles2_if_->BindTexture( | 502 gles2_if_->BindTexture( |
| 471 graphics_3d, picture.texture_target, picture.texture_id); | 503 graphics_3d, picture.texture_target, picture.texture_id); |
| 472 gles2_if_->DrawArrays(graphics_3d, GL_TRIANGLE_STRIP, 0, 4); | 504 gles2_if_->DrawArrays(graphics_3d, GL_TRIANGLE_STRIP, 0, 4); |
| 473 | 505 |
| 474 gles2_if_->UseProgram(graphics_3d, 0); | 506 gles2_if_->UseProgram(graphics_3d, 0); |
| 475 | 507 |
| 476 last_swap_request_ticks_ = core_if_->GetTimeTicks(); | 508 last_swap_request_ticks_ = core_if_->GetTimeTicks(); |
| 477 context_->SwapBuffers( | 509 context_->SwapBuffers( |
| 478 callback_factory_.NewCallback(&MyInstance::PaintFinished)); | 510 callback_factory_.NewCallback(&MyInstance::PaintFinished)); |
| 479 } | 511 } |
| 480 | 512 |
| 481 void MyInstance::PaintFinished(int32_t result) { | 513 void MyInstance::PaintFinished(int32_t result) { |
| 482 assert(result == PP_OK); | 514 assert(result == PP_OK); |
| 483 swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_; | 515 swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_; |
| 484 is_painting_ = false; | 516 is_painting_ = false; |
| 485 ++num_frames_rendered_; | 517 ++num_frames_rendered_; |
| 486 if (num_frames_rendered_ % 50 == 0) { | 518 if (num_frames_rendered_ % 50 == 0) { |
| 487 double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; | 519 double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; |
| 488 double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; | 520 double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; |
| 489 double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; | 521 double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; |
| 522 double secs_average_latency = 0; |
| 523 for (DecoderList::iterator it = video_decoders_.begin(); |
| 524 it != video_decoders_.end(); |
| 525 ++it) |
| 526 secs_average_latency += (*it)->GetAverageLatency(); |
| 527 secs_average_latency /= video_decoders_.size(); |
| 528 double ms_average_latency = 1000 * secs_average_latency; |
| 490 LogError(this).s() << "Rendered frames: " << num_frames_rendered_ | 529 LogError(this).s() << "Rendered frames: " << num_frames_rendered_ |
| 491 << ", fps: " << fps | 530 << ", fps: " << fps |
| 492 << ", with average ms/swap of: " << ms_per_swap; | 531 << ", with average ms/swap of: " << ms_per_swap |
| 532 << ", with average latency (ms) of: " |
| 533 << ms_average_latency; |
| 493 } | 534 } |
| 494 | 535 |
| 495 // If the decoders were reset, this will be empty. | 536 // If the decoders were reset, this will be empty. |
| 496 if (pending_pictures_.empty()) | 537 if (pending_pictures_.empty()) |
| 497 return; | 538 return; |
| 498 | 539 |
| 499 const PendingPicture& next = pending_pictures_.front(); | 540 const PendingPicture& next = pending_pictures_.front(); |
| 500 Decoder* decoder = next.decoder; | 541 Decoder* decoder = next.decoder; |
| 501 const PP_VideoPicture& picture = next.picture; | 542 const PP_VideoPicture& picture = next.picture; |
| 502 decoder->RecyclePicture(picture); | 543 decoder->RecyclePicture(picture); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 | 576 |
| 536 assertNoGLError(); | 577 assertNoGLError(); |
| 537 | 578 |
| 538 CreateGLObjects(); | 579 CreateGLObjects(); |
| 539 } | 580 } |
| 540 | 581 |
| 541 void MyInstance::CreateGLObjects() { | 582 void MyInstance::CreateGLObjects() { |
| 542 // Assign vertex positions and texture coordinates to buffers for use in | 583 // Assign vertex positions and texture coordinates to buffers for use in |
| 543 // shader program. | 584 // shader program. |
| 544 static const float kVertices[] = { | 585 static const float kVertices[] = { |
| 545 -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. | 586 -1, -1, -1, 1, 1, -1, 1, 1, // Position coordinates. |
| 546 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. | 587 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
| 547 }; | 588 }; |
| 548 | 589 |
| 549 GLuint buffer; | 590 GLuint buffer; |
| 550 gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); | 591 gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); |
| 551 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); | 592 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); |
| 552 | 593 |
| 553 gles2_if_->BufferData(context_->pp_resource(), | 594 gles2_if_->BufferData(context_->pp_resource(), |
| 554 GL_ARRAY_BUFFER, | 595 GL_ARRAY_BUFFER, |
| 555 sizeof(kVertices), | 596 sizeof(kVertices), |
| 556 kVertices, | 597 kVertices, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 "#extension GL_ARB_texture_rectangle : require\n" | 632 "#extension GL_ARB_texture_rectangle : require\n" |
| 592 "precision mediump float; \n" | 633 "precision mediump float; \n" |
| 593 "varying vec2 v_texCoord; \n" | 634 "varying vec2 v_texCoord; \n" |
| 594 "uniform sampler2DRect s_texture; \n" | 635 "uniform sampler2DRect s_texture; \n" |
| 595 "void main() \n" | 636 "void main() \n" |
| 596 "{" | 637 "{" |
| 597 " gl_FragColor = texture2DRect(s_texture, v_texCoord).rgba; \n" | 638 " gl_FragColor = texture2DRect(s_texture, v_texCoord).rgba; \n" |
| 598 "}"; | 639 "}"; |
| 599 shader_rectangle_arb_ = | 640 shader_rectangle_arb_ = |
| 600 CreateProgram(kVertexShader, kFragmentShaderRectangle); | 641 CreateProgram(kVertexShader, kFragmentShaderRectangle); |
| 642 assertNoGLError(); |
| 643 } |
| 644 |
| 645 void MyInstance::CreateExternalOESProgramOnce() { |
| 646 if (shader_external_oes_.program) |
| 647 return; |
| 648 static const char kFragmentShaderExternal[] = |
| 649 "#extension GL_OES_EGL_image_external : require\n" |
| 650 "precision mediump float; \n" |
| 651 "varying vec2 v_texCoord; \n" |
| 652 "uniform samplerExternalOES s_texture; \n" |
| 653 "void main() \n" |
| 654 "{" |
| 655 " gl_FragColor = texture2D(s_texture, v_texCoord); \n" |
| 656 "}"; |
| 657 shader_external_oes_ = CreateProgram(kVertexShader, kFragmentShaderExternal); |
| 658 assertNoGLError(); |
| 601 } | 659 } |
| 602 | 660 |
| 603 Shader MyInstance::CreateProgram(const char* vertex_shader, | 661 Shader MyInstance::CreateProgram(const char* vertex_shader, |
| 604 const char* fragment_shader) { | 662 const char* fragment_shader) { |
| 605 Shader shader; | 663 Shader shader; |
| 606 | 664 |
| 607 // Create shader program. | 665 // Create shader program. |
| 608 shader.program = gles2_if_->CreateProgram(context_->pp_resource()); | 666 shader.program = gles2_if_->CreateProgram(context_->pp_resource()); |
| 609 CreateShader( | 667 CreateShader( |
| 610 shader.program, GL_VERTEX_SHADER, vertex_shader, strlen(vertex_shader)); | 668 shader.program, GL_VERTEX_SHADER, vertex_shader, strlen(vertex_shader)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 }; | 730 }; |
| 673 | 731 |
| 674 } // anonymous namespace | 732 } // anonymous namespace |
| 675 | 733 |
| 676 namespace pp { | 734 namespace pp { |
| 677 // Factory function for your specialization of the Module object. | 735 // Factory function for your specialization of the Module object. |
| 678 Module* CreateModule() { | 736 Module* CreateModule() { |
| 679 return new MyModule(); | 737 return new MyModule(); |
| 680 } | 738 } |
| 681 } // namespace pp | 739 } // namespace pp |
| OLD | NEW |