Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: content/common/gpu/media/rendering_helper.cc

Issue 590403004: rendering_helper - Schedule RenderContent() based on VSync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: schedule base on vsync Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/common/gpu/media/rendering_helper.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/gpu/media/rendering_helper.cc
diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc
index 6693f5f07dd5a2cb2b983ea5d289d1a1dc7b835c..618fdc91e5031911de683c982cdb19caeb15cdf8 100644
--- a/content/common/gpu/media/rendering_helper.cc
+++ b/content/common/gpu/media/rendering_helper.cc
@@ -76,7 +76,7 @@ VideoFrameTexture::~VideoFrameTexture() {
}
RenderingHelper::RenderedVideo::RenderedVideo()
- : last_frame_rendered(false), is_flushing(false), frames_to_drop(0) {
+ : is_flushing(false), frames_to_drop(0) {
}
RenderingHelper::RenderedVideo::~RenderedVideo() {
@@ -302,7 +302,8 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
glEnableVertexAttribArray(tc_location);
glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords);
- done->Signal();
+ gl_surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind(
+ &RenderingHelper::UpdateVSyncParameters, base::Unretained(this), done));
piman 2014/10/16 21:13:29 Can you document why Unretained is safe?
Owen Lin 2014/10/20 08:48:42 Done.
}
void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
@@ -396,28 +397,18 @@ void RenderingHelper::QueueVideoFrame(
RenderedVideo* video = &videos_[window_id];
DCHECK(!video->is_flushing);
- // Start the rendering task when getting the first frame.
- if (scheduled_render_time_.is_null() &&
- (frame_duration_ != base::TimeDelta())) {
- scheduled_render_time_ = base::TimeTicks::Now();
- message_loop_->PostTask(FROM_HERE, render_task_.callback());
- }
+ video->pending_frames.push(video_frame);
- if (video->frames_to_drop > 0) {
+ if (video->frames_to_drop > 0 && video->pending_frames.size() > 1) {
--video->frames_to_drop;
- return;
- }
-
- // Pop the last frame if it has been rendered.
- if (video->last_frame_rendered) {
- // When last_frame_rendered is true, we should have only one pending frame.
- // Since we are going to have a new frame, we can release the pending one.
- DCHECK(video->pending_frames.size() == 1);
video->pending_frames.pop();
- video->last_frame_rendered = false;
}
- video->pending_frames.push(video_frame);
+ // Schedules the first RenderContent() if need.
+ if (scheduled_render_time_.is_null()) {
+ scheduled_render_time_ = base::TimeTicks::Now();
+ message_loop_->PostTask(FROM_HERE, render_task_.callback());
+ }
}
void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
@@ -515,10 +506,11 @@ void RenderingHelper::Flush(size_t window_id) {
void RenderingHelper::RenderContent() {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
- scheduled_render_time_ += frame_duration_;
- base::TimeDelta delay = scheduled_render_time_ - base::TimeTicks::Now();
- message_loop_->PostDelayedTask(
- FROM_HERE, render_task_.callback(), std::max(delay, base::TimeDelta()));
+ // Update the VSync params.
+ gl_surface_->GetVSyncProvider()->GetVSyncParameters(
+ base::Bind(&RenderingHelper::UpdateVSyncParameters,
+ base::Unretained(this),
piman 2014/10/16 21:13:28 Can you document why Unretained is safe?
Owen Lin 2014/10/20 08:48:42 Done.
+ static_cast<base::WaitableEvent*>(NULL)));
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
@@ -526,35 +518,36 @@ void RenderingHelper::RenderContent() {
// after this vector falls out of scope at the end of this method. We need
// to keep references to them until after SwapBuffers() call below.
std::vector<scoped_refptr<VideoFrameTexture> > frames_to_be_returned;
-
+ bool need_swap_buffer = false;
if (render_as_thumbnails_) {
// In render_as_thumbnails_ mode, we render the FBO content on the
// screen instead of the decoded textures.
GLSetViewPort(videos_[0].render_area);
RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
+ need_swap_buffer = true;
} else {
for (size_t i = 0; i < videos_.size(); ++i) {
RenderedVideo* video = &videos_[i];
if (video->pending_frames.empty())
continue;
+ need_swap_buffer = true;
scoped_refptr<VideoFrameTexture> frame = video->pending_frames.front();
GLSetViewPort(video->render_area);
RenderTexture(frame->texture_target(), frame->texture_id());
- if (video->last_frame_rendered)
- ++video->frames_to_drop;
-
if (video->pending_frames.size() > 1 || video->is_flushing) {
frames_to_be_returned.push_back(video->pending_frames.front());
video->pending_frames.pop();
- video->last_frame_rendered = false;
} else {
- video->last_frame_rendered = true;
+ ++video->frames_to_drop;
}
}
}
- gl_surface_->SwapBuffers();
+ if (need_swap_buffer)
+ gl_surface_->SwapBuffers();
+
+ ScheduleNextRenderContent();
}
// Helper function for the LayoutRenderingAreas(). The |lengths| are the
@@ -610,4 +603,50 @@ void RenderingHelper::LayoutRenderingAreas(
videos_[i].render_area = gfx::Rect(x, y, w, h);
}
}
+
+void RenderingHelper::UpdateVSyncParameters(base::WaitableEvent* done,
+ const base::TimeTicks timebase,
+ const base::TimeDelta interval) {
+ vsync_timebase_ = timebase;
+ vsync_interval_ = interval;
+
+ if (done)
+ done->Signal();
+}
+
+void RenderingHelper::DropOneFrameForAllVideos() {
+ for (size_t i = 0; i < videos_.size(); ++i) {
+ RenderedVideo* video = &videos_[i];
piman 2014/10/16 21:13:28 nit: for (RenderedVideo& video : videos_) {
Owen Lin 2014/10/20 08:48:42 Done. Thanks
+ if (video->pending_frames.empty())
+ continue;
+
+ if (video->pending_frames.size() > 1 || video->is_flushing) {
+ video->pending_frames.pop();
+ } else {
+ ++video->frames_to_drop;
+ }
+ }
+}
+
+void RenderingHelper::ScheduleNextRenderContent() {
+ scheduled_render_time_ += frame_duration_;
+
+ // Schedules the next RenderContent() at latest VSYNC before the
+ // |scheuled_render_time_|.
piman 2014/10/16 21:13:28 nit: typo scheduled_render_time_
Owen Lin 2014/10/20 08:48:42 Done.
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks target =
+ std::max(now, scheduled_render_time_ - vsync_interval_);
+
+ while (vsync_timebase_ < target)
+ vsync_timebase_ += vsync_interval_;
piman 2014/10/16 21:13:28 vsync_timebase_ may not be close to the current ti
Owen Lin 2014/10/20 08:48:42 Thanks.
+
+ // When the rendering falls behind, drops frames.
+ while (scheduled_render_time_ < vsync_timebase_) {
+ scheduled_render_time_ += frame_duration_;
+ DropOneFrameForAllVideos();
+ }
+
+ message_loop_->PostDelayedTask(
+ FROM_HERE, render_task_.callback(), vsync_timebase_ - now);
+}
} // namespace content
« no previous file with comments | « content/common/gpu/media/rendering_helper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698