Index: ppapi/examples/video_decode/video_decode.cc |
diff --git a/ppapi/examples/video_decode/video_decode.cc b/ppapi/examples/video_decode/video_decode.cc |
index 58f34b593d69df8fccf639088d27ca3655722872..0e0c5197126506f8c1c391be26eb973ee6a5b10d 100644 |
--- a/ppapi/examples/video_decode/video_decode.cc |
+++ b/ppapi/examples/video_decode/video_decode.cc |
@@ -159,6 +159,10 @@ class Decoder { |
void Reset(); |
void RecyclePicture(const PP_VideoPicture& picture); |
+ PP_TimeTicks GetAverageLatency() { |
+ return num_pictures_ ? total_latency_ / num_pictures_ : 0; |
+ } |
+ |
private: |
void InitializeDone(int32_t result); |
void Start(); |
@@ -178,6 +182,12 @@ class Decoder { |
int next_picture_id_; |
bool flushing_; |
bool resetting_; |
+ |
+ const PPB_Core* core_if_; |
+ static const int kMaxDecodeDelay = 128; |
+ PP_TimeTicks decode_time_[kMaxDecodeDelay]; |
+ PP_TimeTicks total_latency_; |
+ int num_pictures_; |
}; |
#if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
@@ -227,7 +237,12 @@ Decoder::Decoder(MyInstance* instance, |
encoded_data_next_pos_to_decode_(0), |
next_picture_id_(0), |
flushing_(false), |
- resetting_(false) { |
+ resetting_(false), |
+ total_latency_(0.0), |
+ num_pictures_(0) { |
+ core_if_ = static_cast<const PPB_Core*>( |
+ pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
+ |
#if defined USE_VP8_TESTDATA_INSTEAD_OF_H264 |
const PP_VideoProfile kBitstreamProfile = PP_VIDEOPROFILE_VP8MAIN; |
#else |
@@ -295,6 +310,7 @@ void Decoder::DecodeNextFrame() { |
// Decode the frame. On completion, DecodeDone will call DecodeNextFrame |
// to implement a decode loop. |
uint32_t size = static_cast<uint32_t>(end_pos - start_pos); |
+ decode_time_[next_picture_id_ % kMaxDecodeDelay] = core_if_->GetTimeTicks(); |
decoder_->Decode(next_picture_id_++, |
size, |
kData + start_pos, |
@@ -318,6 +334,12 @@ void Decoder::PictureReady(int32_t result, PP_VideoPicture picture) { |
if (result == PP_ERROR_ABORTED) |
return; |
assert(result == PP_OK); |
+ |
+ num_pictures_++; |
+ PP_TimeTicks latency = core_if_->GetTimeTicks() - |
+ decode_time_[picture.decode_id % kMaxDecodeDelay]; |
+ total_latency_ += latency; |
+ |
decoder_->GetPicture( |
callback_factory_.NewCallbackWithOutput(&Decoder::PictureReady)); |
instance_->PaintPicture(this, picture); |
@@ -349,12 +371,13 @@ MyInstance::MyInstance(PP_Instance instance, pp::Module* module) |
swap_ticks_(0), |
callback_factory_(this), |
context_(NULL) { |
- assert((console_if_ = static_cast<const PPB_Console*>( |
- module->GetBrowserInterface(PPB_CONSOLE_INTERFACE)))); |
- assert((core_if_ = static_cast<const PPB_Core*>( |
- module->GetBrowserInterface(PPB_CORE_INTERFACE)))); |
- assert((gles2_if_ = static_cast<const PPB_OpenGLES2*>( |
- module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)))); |
+ console_if_ = static_cast<const PPB_Console*>( |
+ pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE)); |
+ core_if_ = static_cast<const PPB_Core*>( |
+ pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); |
+ gles2_if_ = static_cast<const PPB_OpenGLES2*>( |
+ pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
+ |
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); |
} |
@@ -487,9 +510,18 @@ void MyInstance::PaintFinished(int32_t result) { |
double elapsed = core_if_->GetTimeTicks() - first_frame_delivered_ticks_; |
double fps = (elapsed > 0) ? num_frames_rendered_ / elapsed : 1000; |
double ms_per_swap = (swap_ticks_ * 1e3) / num_frames_rendered_; |
+ double secs_average_latency = 0; |
+ for (DecoderList::iterator it = video_decoders_.begin(); |
+ it != video_decoders_.end(); |
+ ++it) |
+ secs_average_latency += (*it)->GetAverageLatency(); |
+ secs_average_latency /= video_decoders_.size(); |
+ double ms_average_latency = 1000 * secs_average_latency; |
LogError(this).s() << "Rendered frames: " << num_frames_rendered_ |
<< ", fps: " << fps |
- << ", with average ms/swap of: " << ms_per_swap; |
+ << ", with average ms/swap of: " << ms_per_swap |
+ << ", with average latency (ms) of: " |
+ << ms_average_latency; |
} |
// If the decoders were reset, this will be empty. |
@@ -542,8 +574,8 @@ void MyInstance::CreateGLObjects() { |
// Assign vertex positions and texture coordinates to buffers for use in |
// shader program. |
static const float kVertices[] = { |
- -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. |
- 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
+ -1, -1, -1, 1, 1, -1, 1, 1, // Position coordinates. |
+ 0, 1, 0, 0, 1, 1, 1, 0, // Texture coordinates. |
}; |
GLuint buffer; |