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 |