summaryrefslogtreecommitdiff
path: root/content/common/gpu/media/rendering_helper.cc
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-08-28 12:05:23 +0100
committerTorne (Richard Coles) <torne@google.com>2014-08-28 12:05:23 +0100
commit03b57e008b61dfcb1fbad3aea950ae0e001748b0 (patch)
tree9a740c1a5fbe659ec83484b67cbc679332f5a408 /content/common/gpu/media/rendering_helper.cc
parentca7d0c81aa30d24514c34c963f43cd24da34a2bf (diff)
downloadchromium_org-03b57e008b61dfcb1fbad3aea950ae0e001748b0.tar.gz
Merge from Chromium at DEPS revision 291560
This commit was generated by merge_to_master.py. Change-Id: Ic58269055810d51286b4109e59b90b6856887a30
Diffstat (limited to 'content/common/gpu/media/rendering_helper.cc')
-rw-r--r--content/common/gpu/media/rendering_helper.cc118
1 files changed, 89 insertions, 29 deletions
diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc
index 7ee940148d..ce2f94b16d 100644
--- a/content/common/gpu/media/rendering_helper.cc
+++ b/content/common/gpu/media/rendering_helper.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/message_loop/message_loop.h"
@@ -60,6 +61,25 @@ RenderingHelperParams::RenderingHelperParams() {}
RenderingHelperParams::~RenderingHelperParams() {}
+VideoFrameTexture::VideoFrameTexture(uint32 texture_target,
+ uint32 texture_id,
+ const base::Closure& no_longer_needed_cb)
+ : texture_target_(texture_target),
+ texture_id_(texture_id),
+ no_longer_needed_cb_(no_longer_needed_cb) {
+ DCHECK(!no_longer_needed_cb_.is_null());
+}
+
+VideoFrameTexture::~VideoFrameTexture() {
+ base::ResetAndReturn(&no_longer_needed_cb_).Run();
+}
+
+RenderingHelper::RenderedVideo::RenderedVideo() : last_frame_rendered(false) {
+}
+
+RenderingHelper::RenderedVideo::~RenderedVideo() {
+}
+
// static
bool RenderingHelper::InitializeOneOff() {
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
@@ -78,15 +98,15 @@ RenderingHelper::RenderingHelper() {
}
RenderingHelper::~RenderingHelper() {
- CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor.";
+ CHECK_EQ(videos_.size(), 0U) << "Must call UnInitialize before dtor.";
Clear();
}
void RenderingHelper::Initialize(const RenderingHelperParams& params,
base::WaitableEvent* done) {
- // Use cients_.size() != 0 as a proxy for the class having already been
+ // Use videos_.size() != 0 as a proxy for the class having already been
// Initialize()'d, and UnInitialize() before continuing.
- if (clients_.size()) {
+ if (videos_.size()) {
base::WaitableEvent done(false, false);
UnInitialize(&done);
done.Wait();
@@ -153,12 +173,12 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
NULL, gl_surface_, gfx::PreferIntegratedGpu);
gl_context_->MakeCurrent(gl_surface_);
- clients_ = params.clients;
- CHECK_GT(clients_.size(), 0U);
- LayoutRenderingAreas();
+ CHECK_GT(params.window_sizes.size(), 0U);
+ videos_.resize(params.window_sizes.size());
+ LayoutRenderingAreas(params.window_sizes);
if (render_as_thumbnails_) {
- CHECK_EQ(clients_.size(), 1U);
+ CHECK_EQ(videos_.size(), 1U);
GLint max_texture_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
@@ -370,6 +390,31 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target,
++frame_count_;
}
+void RenderingHelper::QueueVideoFrame(
+ size_t window_id,
+ scoped_refptr<VideoFrameTexture> video_frame) {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
+ RenderedVideo* video = &videos_[window_id];
+
+ // 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);
+}
+
+void RenderingHelper::DropPendingFrames(size_t window_id) {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
+ RenderedVideo* video = &videos_[window_id];
+ video->pending_frames = std::queue<scoped_refptr<VideoFrameTexture> >();
+ video->last_frame_rendered = false;
+}
+
void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
// The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler
// is bound to GL_TEXTURE0.
@@ -385,6 +430,7 @@ void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
}
void RenderingHelper::DeleteTexture(uint32 texture_id) {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
glDeleteTextures(1, &texture_id);
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}
@@ -398,7 +444,7 @@ void* RenderingHelper::GetGLDisplay() {
}
void RenderingHelper::Clear() {
- clients_.clear();
+ videos_.clear();
message_loop_ = NULL;
gl_context_ = NULL;
gl_surface_ = NULL;
@@ -461,16 +507,30 @@ void RenderingHelper::RenderContent() {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
+ // Frames that will be returned to the client (via the no_longer_needed_cb)
+ // 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;
+
if (render_as_thumbnails_) {
// In render_as_thumbnails_ mode, we render the FBO content on the
// screen instead of the decoded textures.
- GLSetViewPort(render_areas_[0]);
+ GLSetViewPort(videos_[0].render_area);
RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
} else {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i]) {
- GLSetViewPort(render_areas_[i]);
- clients_[i]->RenderContent(this);
+ for (size_t i = 0; i < videos_.size(); ++i) {
+ RenderedVideo* video = &videos_[i];
+ if (video->pending_frames.empty())
+ continue;
+ scoped_refptr<VideoFrameTexture> frame = video->pending_frames.front();
+ GLSetViewPort(video->render_area);
+ RenderTexture(frame->texture_target(), frame->texture_id());
+
+ if (video->pending_frames.size() > 1) {
+ frames_to_be_returned.push_back(video->pending_frames.front());
+ video->pending_frames.pop();
+ } else {
+ video->last_frame_rendered = true;
}
}
}
@@ -492,11 +552,12 @@ static void ScaleAndCalculateOffsets(std::vector<int>* lengths,
}
}
-void RenderingHelper::LayoutRenderingAreas() {
+void RenderingHelper::LayoutRenderingAreas(
+ const std::vector<gfx::Size>& window_sizes) {
// Find the number of colums and rows.
- // The smallest n * n or n * (n + 1) > number of clients.
- size_t cols = sqrt(clients_.size() - 1) + 1;
- size_t rows = (clients_.size() + cols - 1) / cols;
+ // The smallest n * n or n * (n + 1) > number of windows.
+ size_t cols = sqrt(videos_.size() - 1) + 1;
+ size_t rows = (videos_.size() + cols - 1) / cols;
// Find the widths and heights of the grid.
std::vector<int> widths(cols);
@@ -504,31 +565,30 @@ void RenderingHelper::LayoutRenderingAreas() {
std::vector<int> offset_x(cols);
std::vector<int> offset_y(rows);
- for (size_t i = 0; i < clients_.size(); ++i) {
- const gfx::Size& window_size = clients_[i]->GetWindowSize();
- widths[i % cols] = std::max(widths[i % cols], window_size.width());
- heights[i / cols] = std::max(heights[i / cols], window_size.height());
+ for (size_t i = 0; i < window_sizes.size(); ++i) {
+ const gfx::Size& size = window_sizes[i];
+ widths[i % cols] = std::max(widths[i % cols], size.width());
+ heights[i / cols] = std::max(heights[i / cols], size.height());
}
ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width());
ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height());
// Put each render_area_ in the center of each cell.
- render_areas_.clear();
- for (size_t i = 0; i < clients_.size(); ++i) {
- const gfx::Size& window_size = clients_[i]->GetWindowSize();
+ for (size_t i = 0; i < window_sizes.size(); ++i) {
+ const gfx::Size& size = window_sizes[i];
float scale =
- std::min(static_cast<float>(widths[i % cols]) / window_size.width(),
- static_cast<float>(heights[i / cols]) / window_size.height());
+ std::min(static_cast<float>(widths[i % cols]) / size.width(),
+ static_cast<float>(heights[i / cols]) / size.height());
// Don't scale up the texture.
scale = std::min(1.0f, scale);
- size_t w = scale * window_size.width();
- size_t h = scale * window_size.height();
+ size_t w = scale * size.width();
+ size_t h = scale * size.height();
size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2;
size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2;
- render_areas_.push_back(gfx::Rect(x, y, w, h));
+ videos_[i].render_area = gfx::Rect(x, y, w, h);
}
}
} // namespace content