| 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 <stdio.h> | 5 #include <stdio.h> |
| 6 #include <string.h> | 6 #include <string.h> |
| 7 | 7 |
| 8 #include <iostream> | 8 #include <iostream> |
| 9 #include <queue> | 9 #include <queue> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d); | 152 Decoder(MyInstance* instance, int id, const pp::Graphics3D& graphics_3d); |
| 153 ~Decoder(); | 153 ~Decoder(); |
| 154 | 154 |
| 155 int id() const { return id_; } | 155 int id() const { return id_; } |
| 156 bool flushing() const { return flushing_; } | 156 bool flushing() const { return flushing_; } |
| 157 bool resetting() const { return resetting_; } | 157 bool resetting() const { return resetting_; } |
| 158 | 158 |
| 159 void Reset(); | 159 void Reset(); |
| 160 void RecyclePicture(const PP_VideoPicture& picture); | 160 void RecyclePicture(const PP_VideoPicture& picture); |
| 161 | 161 |
| 162 PP_TimeTicks GetAverageLatency() { |
| 163 return num_pictures_ ? total_latency_ / num_pictures_ : 0; |
| 164 } |
| 165 |
| 162 private: | 166 private: |
| 163 void InitializeDone(int32_t result); | 167 void InitializeDone(int32_t result); |
| 164 void Start(); | 168 void Start(); |
| 165 void DecodeNextFrame(); | 169 void DecodeNextFrame(); |
| 166 void DecodeDone(int32_t result); | 170 void DecodeDone(int32_t result); |
| 167 void PictureReady(int32_t result, PP_VideoPicture picture); | 171 void PictureReady(int32_t result, PP_VideoPicture picture); |
| 168 void FlushDone(int32_t result); | 172 void FlushDone(int32_t result); |
| 169 void ResetDone(int32_t result); | 173 void ResetDone(int32_t result); |
| 170 | 174 |
| 171 MyInstance* instance_; | 175 MyInstance* instance_; |
| 172 int id_; | 176 int id_; |
| 173 | 177 |
| 174 pp::VideoDecoder* decoder_; | 178 pp::VideoDecoder* decoder_; |
| 175 pp::CompletionCallbackFactory<Decoder> callback_factory_; | 179 pp::CompletionCallbackFactory<Decoder> callback_factory_; |
| 176 | 180 |
| 177 size_t encoded_data_next_pos_to_decode_; | 181 size_t encoded_data_next_pos_to_decode_; |
| 178 int next_picture_id_; | 182 int next_picture_id_; |
| 179 bool flushing_; | 183 bool flushing_; |
| 180 bool resetting_; | 184 bool resetting_; |
| 185 |
| 186 const PPB_Core* core_if_; |
| 187 static const int kMaxDecodeDelay = 128; |
| 188 PP_TimeTicks decode_time_[kMaxDecodeDelay]; |
| 189 PP_TimeTicks total_latency_; |
| 190 int num_pictures_; |
| 181 }; | 191 }; |
| 182 | 192 |
| 183 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 | 193 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
| 184 | 194 |
| 185 // VP8 is stored in an IVF container. | 195 // VP8 is stored in an IVF container. |
| 186 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF | 196 // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF |
| 187 | 197 |
| 188 static void GetNextFrame(size_t* start_pos, size_t* end_pos) { | 198 static void GetNextFrame(size_t* start_pos, size_t* end_pos) { |
| 189 size_t current_pos = *start_pos; | 199 size_t current_pos = *start_pos; |
| 190 if (current_pos == 0) | 200 if (current_pos == 0) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 220 Decoder::Decoder(MyInstance* instance, | 230 Decoder::Decoder(MyInstance* instance, |
| 221 int id, | 231 int id, |
| 222 const pp::Graphics3D& graphics_3d) | 232 const pp::Graphics3D& graphics_3d) |
| 223 : instance_(instance), | 233 : instance_(instance), |
| 224 id_(id), | 234 id_(id), |
| 225 decoder_(new pp::VideoDecoder(instance)), | 235 decoder_(new pp::VideoDecoder(instance)), |
| 226 callback_factory_(this), | 236 callback_factory_(this), |
| 227 encoded_data_next_pos_to_decode_(0), | 237 encoded_data_next_pos_to_decode_(0), |
| 228 next_picture_id_(0), | 238 next_picture_id_(0), |
| 229 flushing_(false), | 239 flushing_(false), |
| 230 resetting_(false) { | 240 resetting_(false), |
| 241 total_latency_(0.0), |
| 242 num_pictures_(0) { |
| 243 core_if_ = static_cast<const PPB_Core*>( |
| 244 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
| 245 |
| 231 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 | 246 #if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
| 232 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; | 247 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; |
| 233 #else | 248 #else |
| 234 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_H264MAIN; | 249 const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_H264MAIN; |
| 235 #endif | 250 #endif |
| 236 | 251 |
| 237 assert(!decoder_->is_null()); | 252 assert(!decoder_->is_null()); |
| 238 decoder_->Initialize(graphics_3d, | 253 decoder_->Initialize(graphics_3d, |
| 239 kBitstreamProfile, | 254 kBitstreamProfile, |
| 240 PP_TRUE /* allow_software_fallback */, | 255 PP_TRUE /* allow_software_fallback */, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 } | 303 } |
| 289 | 304 |
| 290 // Find the start of the next frame. | 305 // Find the start of the next frame. |
| 291 size_t start_pos = encoded_data_next_pos_to_decode_; | 306 size_t start_pos = encoded_data_next_pos_to_decode_; |
| 292 size_t end_pos; | 307 size_t end_pos; |
| 293 GetNextFrame(&start_pos, &end_pos); | 308 GetNextFrame(&start_pos, &end_pos); |
| 294 encoded_data_next_pos_to_decode_ = end_pos; | 309 encoded_data_next_pos_to_decode_ = end_pos; |
| 295 // Decode the frame. On completion, DecodeDone will call DecodeNextFrame | 310 // Decode the frame. On completion, DecodeDone will call DecodeNextFrame |
| 296 // to implement a decode loop. | 311 // to implement a decode loop. |
| 297 uint32_t size = static_cast<uint32_t>(end_pos - start_pos); | 312 uint32_t size = static_cast<uint32_t>(end_pos - start_pos); |
| 313 decode_time_[next_picture_id_ % kMaxDecodeDelay] = core_if_->GetTimeTicks(); |
| 298 decoder_->Decode(next_picture_id_++, | 314 decoder_->Decode(next_picture_id_++, |
| 299 size, | 315 size, |
| 300 kData + start_pos, | 316 kData + start_pos, |
| 301 callback_factory_.NewCallback(&Decoder::DecodeDone)); | 317 callback_factory_.NewCallback(&Decoder::DecodeDone)); |
| 302 } | 318 } |
| 303 } | 319 } |
| 304 | 320 |
| 305 void Decoder::DecodeDone(int32_t result) { | 321 void Decoder::DecodeDone(int32_t result) { |
| 306 assert(decoder_); | 322 assert(decoder_); |
| 307 // Break out of the decode loop on abort. | 323 // Break out of the decode loop on abort. |
| 308 if (result == PP_ERROR_ABORTED) | 324 if (result == PP_ERROR_ABORTED) |
| 309 return; | 325 return; |
| 310 assert(result == PP_OK); | 326 assert(result == PP_OK); |
| 311 if (!flushing_ && !resetting_) | 327 if (!flushing_ && !resetting_) |
| 312 DecodeNextFrame(); | 328 DecodeNextFrame(); |
| 313 } | 329 } |
| 314 | 330 |
| 315 void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { | 331 void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { |
| 316 assert(decoder_); | 332 assert(decoder_); |
| 317 // Break out of the get picture loop on abort. | 333 // Break out of the get picture loop on abort. |
| 318 if (result == PP_ERROR_ABORTED) | 334 if (result == PP_ERROR_ABORTED) |
| 319 return; | 335 return; |
| 320 assert(result == PP_OK); | 336 assert(result == PP_OK); |
| 337 |
| 338 num_pictures_++; |
| 339 PP_TimeTicks latency = core_if_->GetTimeTicks() - |
| 340 decode_time_[picture.decode_id % kMaxDecodeDelay]; |
| 341 total_latency_ += latency; |
| 342 |
| 321 decoder_->GetPicture( | 343 decoder_->GetPicture( |
| 322 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); | 344 callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); |
| 323 instance_->PaintPicture(this, picture); | 345 instance_->PaintPicture(this, picture); |
| 324 } | 346 } |
| 325 | 347 |
| 326 void Decoder::FlushDone(int32_t result) { | 348 void Decoder::FlushDone(int32_t result) { |
| 327 assert(decoder_); | 349 assert(decoder_); |
| 328 assert(result == PP_OK || result == PP_ERROR_ABORTED); | 350 assert(result == PP_OK || result == PP_ERROR_ABORTED); |
| 329 assert(flushing_); | 351 assert(flushing_); |
| 330 flushing_ = false; | 352 flushing_ = false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 342 MyInstance::MyInstance(PP_Instance instance, pp::Module* module) | 364 MyInstance::MyInstance(PP_Instance instance, pp::Module* module) |
| 343 : pp::Instance(instance), | 365 : pp::Instance(instance), |
| 344 pp::Graphics3DClient(this), | 366 pp::Graphics3DClient(this), |
| 345 is_painting_(false), | 367 is_painting_(false), |
| 346 num_frames_rendered_(0), | 368 num_frames_rendered_(0), |
| 347 first_frame_delivered_ticks_(-1), | 369 first_frame_delivered_ticks_(-1), |
| 348 last_swap_request_ticks_(-1), | 370 last_swap_request_ticks_(-1), |
| 349 swap_ticks_(0), | 371 swap_ticks_(0), |
| 350 callback_factory_(this), | 372 callback_factory_(this), |
| 351 context_(NULL) { | 373 context_(NULL) { |
| 352 assert((console_if_ = static_cast<const PPB_Console*>( | 374 console_if_ = static_cast<const PPB_Console*>( |
| 353 module->GetBrowserInterface(PPB_CONSOLE_INTERFACE)))); | 375 pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE)); |
| 354 assert((core_if_ = static_cast<const PPB_Core*>( | 376 core_if_ = static_cast<const PPB_Core*>( |
| 355 module->GetBrowserInterface(PPB_CORE_INTERFACE)))); | 377 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
| 356 assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>( | 378 gles2_if_ = static_cast<const PPB_OpenGLES2*>( |
| 357 module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)))); | 379 pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
| 380 |
| 358 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); | 381 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); |
| 359 } | 382 } |
| 360 | 383 |
| 361 MyInstance::~MyInstance() { | 384 MyInstance::~MyInstance() { |
| 362 if (!context_) | 385 if (!context_) |
| 363 return; | 386 return; |
| 364 | 387 |
| 365 PP_Resource graphics_3d = context_->pp_resource(); | 388 PP_Resource graphics_3d = context_->pp_resource(); |
| 366 if (shader_2d_.program) | 389 if (shader_2d_.program) |
| 367 gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); | 390 gles2_if_->DeleteProgram(graphics_3d, shader_2d_.program); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 | 503 |
| 481 void MyInstance::PaintFinished(int32_t result) { | 504 void MyInstance::PaintFinished(int32_t result) { |
| 482 assert(result == PP_OK); | 505 assert(result == PP_OK); |
| 483 swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_; | 506 swap_ticks_ += core_if_->GetTimeTicks() - last_swap_request_ticks_; |
| 484 is_painting_ = false; | 507 is_painting_ = false; |
| 485 ++num_frames_rendered_; | 508 ++num_frames_rendered_; |
| 486 if (num_frames_rendered_ % 50 == 0) { | 509 if (num_frames_rendered_ % 50 == 0) { |
| 487 double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; | 510 double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; |
| 488 double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; | 511 double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; |
| 489 double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; | 512 double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; |
| 513 double secs_average_latency = 0; |
| 514 for (DecoderList::iterator it = video_decoders_.begin(); |
| 515 it != video_decoders_.end(); |
| 516 ++it) |
| 517 secs_average_latency += (*it)->GetAverageLatency(); |
| 518 secs_average_latency /= video_decoders_.size(); |
| 519 double ms_average_latency = 1000 * secs_average_latency; |
| 490 LogError(this).s() << "Rendered frames: " << num_frames_rendered_ | 520 LogError(this).s() << "Rendered frames: " << num_frames_rendered_ |
| 491 << ", fps: " << fps | 521 << ", fps: " << fps |
| 492 << ", with average ms/swap of: " << ms_per_swap; | 522 << ", with average ms/swap of: " << ms_per_swap |
| 523 << ", with average latency (ms) of: " |
| 524 << ms_average_latency; |
| 493 } | 525 } |
| 494 | 526 |
| 495 // If the decoders were reset, this will be empty. | 527 // If the decoders were reset, this will be empty. |
| 496 if (pending_pictures_.empty()) | 528 if (pending_pictures_.empty()) |
| 497 return; | 529 return; |
| 498 | 530 |
| 499 const PendingPicture& next = pending_pictures_.front(); | 531 const PendingPicture& next = pending_pictures_.front(); |
| 500 Decoder* decoder = next.decoder; | 532 Decoder* decoder = next.decoder; |
| 501 const PP_VideoPicture& picture = next.picture; | 533 const PP_VideoPicture& picture = next.picture; |
| 502 decoder->RecyclePicture(picture); | 534 decoder->RecyclePicture(picture); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 | 567 |
| 536 assertNoGLError(); | 568 assertNoGLError(); |
| 537 | 569 |
| 538 CreateGLObjects(); | 570 CreateGLObjects(); |
| 539 } | 571 } |
| 540 | 572 |
| 541 void MyInstance::CreateGLObjects() { | 573 void MyInstance::CreateGLObjects() { |
| 542 // Assign vertex positions and texture coordinates to buffers for use in | 574 // Assign vertex positions and texture coordinates to buffers for use in |
| 543 // shader program. | 575 // shader program. |
| 544 static const float kVertices[] = { | 576 static const float kVertices[] = { |
| 545 -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. | 577 -1, -1, -1, 1, 1, -1, 1, 1, // Position coordinates. |
| 546 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. | 578 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
| 547 }; | 579 }; |
| 548 | 580 |
| 549 GLuint buffer; | 581 GLuint buffer; |
| 550 gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); | 582 gles2_if_->GenBuffers(context_->pp_resource(), 1, &buffer); |
| 551 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); | 583 gles2_if_->BindBuffer(context_->pp_resource(), GL_ARRAY_BUFFER, buffer); |
| 552 | 584 |
| 553 gles2_if_->BufferData(context_->pp_resource(), | 585 gles2_if_->BufferData(context_->pp_resource(), |
| 554 GL_ARRAY_BUFFER, | 586 GL_ARRAY_BUFFER, |
| 555 sizeof(kVertices), | 587 sizeof(kVertices), |
| 556 kVertices, | 588 kVertices, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 }; | 704 }; |
| 673 | 705 |
| 674 } // anonymous namespace | 706 } // anonymous namespace |
| 675 | 707 |
| 676 namespace pp { | 708 namespace pp { |
| 677 // Factory function for your specialization of the Module object. | 709 // Factory function for your specialization of the Module object. |
| 678 Module* CreateModule() { | 710 Module* CreateModule() { |
| 679 return new MyModule(); | 711 return new MyModule(); |
| 680 } | 712 } |
| 681 } // namespace pp | 713 } // namespace pp |
| OLD | NEW |