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..5f8ae749e1eef31f9e7972f3bbd8c075cb711452 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" |
#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() {} |
+VideoFrame::VideoFrame(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) { |
+} |
+ |
+VideoFrame::~VideoFrame() { |
+ if (!no_longer_needed_cb_.is_null()) |
Pawel Osciak
2014/08/14 04:48:23
I don't think we can allow this to be optional, be
Owen Lin
2014/08/14 09:20:41
Done.
|
+ base::ResetAndReturn(&no_longer_needed_cb_).Run(); |
+} |
+ |
// static |
bool RenderingHelper::InitializeOneOff() { |
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
@@ -84,7 +99,7 @@ RenderingHelper::~RenderingHelper() { |
void RenderingHelper::Initialize(const RenderingHelperParams& params, |
base::WaitableEvent* done) { |
- // Use cients_.size() != 0 as a proxy for the class having already been |
+ // Use clients_.size() != 0 as a proxy for the class having already been |
// Initialize()'d, and UnInitialize() before continuing. |
if (clients_.size()) { |
base::WaitableEvent done(false, false); |
@@ -153,9 +168,9 @@ 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); |
+ clients_.resize(params.window_sizes.size()); |
Pawel Osciak
2014/08/14 04:48:22
This should go to LayoutRenderingAreas() maybe?
Owen Lin
2014/08/14 09:20:41
mmm... I would prefer keep it here. As the name su
Pawel Osciak
2014/08/15 05:45:15
Ok, my issue was that we use videos_.size and wind
|
+ LayoutRenderingAreas(params.window_sizes); |
if (render_as_thumbnails_) { |
CHECK_EQ(clients_.size(), 1U); |
@@ -370,6 +385,24 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target, |
++frame_count_; |
} |
+void RenderingHelper::QueueVideoFrame(size_t window_id, |
+ scoped_ptr<VideoFrame> video_frame) { |
+ RenderingClient* client = &clients_[window_id]; |
+ |
+ // Pop the front if it has been rendered. |
+ if (client->last_frame_rendered && !client->pending_frames.empty()) { |
+ delete client->pending_frames.front(); |
Pawel Osciak
2014/08/14 04:48:23
Please use container of scoped_refptrs and just po
Owen Lin
2014/08/14 09:20:40
Done
|
+ client->pending_frames.pop_front(); |
+ } |
+ |
+ client->pending_frames.push_back(video_frame.release()); |
+ client->last_frame_rendered = false; |
Pawel Osciak
2014/08/14 04:48:23
Technically this should go to the if clause?
Owen Lin
2014/08/14 09:20:41
Yes, the code is modified.
|
+} |
+ |
+void RenderingHelper::ClearVideoFrames(size_t window_id) { |
+ STLDeleteElements(&clients_[window_id].pending_frames); |
Pawel Osciak
2014/08/14 04:48:23
client->last_frame_rendered = false just in case?
Owen Lin
2014/08/14 09:20:40
Good catch. Thanks.
|
+} |
+ |
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. |
@@ -464,18 +497,34 @@ void RenderingHelper::RenderContent() { |
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(clients_[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); |
- } |
- } |
+ gl_surface_->SwapBuffers(); |
+ return; |
+ } |
+ |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ RenderingClient* client = &clients_[i]; |
+ if (client->pending_frames.empty()) |
+ continue; |
+ VideoFrame* frame = client->pending_frames.front(); |
+ GLSetViewPort(client->render_area); |
+ RenderTexture(frame->texture_target(), frame->texture_id()); |
} |
gl_surface_->SwapBuffers(); |
+ |
+ // Releases the rendered frame after SwapBuffers() if it is not the last one. |
Pawel Osciak
2014/08/14 04:48:22
Instead of this, just check if client->pending_fra
Owen Lin
2014/08/14 09:20:41
Done. I was avoid using RefCounted object since t
|
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ RenderingClient* client = &clients_[i]; |
+ if (client->pending_frames.size() > 1) { |
+ delete client->pending_frames.front(); |
+ client->pending_frames.pop_front(); |
+ client->last_frame_rendered = false; |
+ continue; |
+ } |
+ client->last_frame_rendered = true; |
+ } |
} |
// Helper function for the LayoutRenderingAreas(). The |lengths| are the |
@@ -492,7 +541,8 @@ 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; |
@@ -504,31 +554,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)); |
+ clients_[i].render_area = gfx::Rect(x, y, w, h); |
} |
} |
} // namespace content |