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 7ee940148d2d2f9e741fd38f0b3c1d798fad37df..65049525edd9bb310481533a83620ab4e221e8fd 100644 |
--- a/content/common/gpu/media/rendering_helper.cc |
+++ b/content/common/gpu/media/rendering_helper.cc |
@@ -9,9 +9,11 @@ |
#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" |
+#include "base/stl_util.h" |
Pawel Osciak
2014/08/20 10:26:26
I think this is not needed anymore now that we use
Owen Lin
2014/08/21 03:45:18
Done.
|
#include "base/strings/stringize_macros.h" |
#include "base/synchronization/waitable_event.h" |
#include "ui/gl/gl_context.h" |
@@ -60,6 +62,19 @@ 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(); |
+} |
+ |
// static |
bool RenderingHelper::InitializeOneOff() { |
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
@@ -78,15 +93,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 +168,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 +385,29 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target, |
++frame_count_; |
} |
+void RenderingHelper::QueueVideoFrame( |
+ size_t window_id, |
+ scoped_refptr<VideoFrameTexture> video_frame) { |
+ RenderedVideo* video = &videos_[window_id]; |
+ |
+ // Pop the front if it has been rendered. |
Pawel Osciak
2014/08/20 10:26:26
This is what is confusing. Because this suggests t
Owen Lin
2014/08/21 03:45:18
Rephrased. Thanks.
|
+ if (video->last_frame_rendered) { |
+ // When last_frame_rendered is True, we should have only one pending frame. |
Pawel Osciak
2014/08/20 10:26:26
s/True/true/
Owen Lin
2014/08/21 03:45:18
Done.
|
+ // 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) { |
+ 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. |
@@ -398,7 +436,7 @@ void* RenderingHelper::GetGLDisplay() { |
} |
void RenderingHelper::Clear() { |
- clients_.clear(); |
+ videos_.clear(); |
message_loop_ = NULL; |
gl_context_ = NULL; |
gl_surface_ = NULL; |
@@ -461,16 +499,30 @@ void RenderingHelper::RenderContent() { |
CHECK_EQ(base::MessageLoop::current(), message_loop_); |
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); |
+ // To keep the frames before calling SwapBuffers(). Otherwise, those frames |
Pawel Osciak
2014/08/20 10:26:26
I think this would be easier to understand:
"Fram
Owen Lin
2014/08/21 03:45:18
Thanks.
|
+ // will be returned to client (via the no_longer_needed_cb) before being |
+ // rendered. |
+ 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 +544,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 +557,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 |