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

Side by Side Diff: content/common/gpu/media/rendering_helper.cc

Issue 462413004: rendering_helper - Refactoring - remove the Client interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 6 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/media/rendering_helper.h" 5 #include "content/common/gpu/media/rendering_helper.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <numeric> 8 #include <numeric>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/mac/scoped_nsautorelease_pool.h" 14 #include "base/mac/scoped_nsautorelease_pool.h"
14 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/stl_util.h"
15 #include "base/strings/stringize_macros.h" 17 #include "base/strings/stringize_macros.h"
16 #include "base/synchronization/waitable_event.h" 18 #include "base/synchronization/waitable_event.h"
17 #include "ui/gl/gl_context.h" 19 #include "ui/gl/gl_context.h"
18 #include "ui/gl/gl_implementation.h" 20 #include "ui/gl/gl_implementation.h"
19 #include "ui/gl/gl_surface.h" 21 #include "ui/gl/gl_surface.h"
20 #include "ui/gl/gl_surface_egl.h" 22 #include "ui/gl/gl_surface_egl.h"
21 #include "ui/gl/gl_surface_glx.h" 23 #include "ui/gl/gl_surface_glx.h"
22 24
23 #if defined(OS_WIN) 25 #if defined(OS_WIN)
24 #include <windows.h> 26 #include <windows.h>
(...skipping 28 matching lines...) Expand all
53 glDeleteShader(shader); 55 glDeleteShader(shader);
54 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); 56 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
55 } 57 }
56 58
57 namespace content { 59 namespace content {
58 60
59 RenderingHelperParams::RenderingHelperParams() {} 61 RenderingHelperParams::RenderingHelperParams() {}
60 62
61 RenderingHelperParams::~RenderingHelperParams() {} 63 RenderingHelperParams::~RenderingHelperParams() {}
62 64
65 VideoFrame::VideoFrame(uint32 texture_target,
66 uint32 texture_id,
67 const base::Closure& no_longer_needed_cb)
68 : texture_target_(texture_target),
69 texture_id_(texture_id),
70 no_longer_needed_cb_(no_longer_needed_cb) {
71 DCHECK(!no_longer_needed_cb_.is_null());
72 }
73
74 VideoFrame::~VideoFrame() {
75 base::ResetAndReturn(&no_longer_needed_cb_).Run();
76 }
77
63 // static 78 // static
64 bool RenderingHelper::InitializeOneOff() { 79 bool RenderingHelper::InitializeOneOff() {
65 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 80 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
66 #if GL_VARIANT_GLX 81 #if GL_VARIANT_GLX
67 cmd_line->AppendSwitchASCII(switches::kUseGL, 82 cmd_line->AppendSwitchASCII(switches::kUseGL,
68 gfx::kGLImplementationDesktopName); 83 gfx::kGLImplementationDesktopName);
69 #else 84 #else
70 cmd_line->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName); 85 cmd_line->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName);
71 #endif 86 #endif
72 return gfx::GLSurface::InitializeOneOff(); 87 return gfx::GLSurface::InitializeOneOff();
73 } 88 }
74 89
75 RenderingHelper::RenderingHelper() { 90 RenderingHelper::RenderingHelper() {
76 window_ = gfx::kNullAcceleratedWidget; 91 window_ = gfx::kNullAcceleratedWidget;
77 Clear(); 92 Clear();
78 } 93 }
79 94
80 RenderingHelper::~RenderingHelper() { 95 RenderingHelper::~RenderingHelper() {
81 CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor."; 96 CHECK_EQ(videos_.size(), 0U) << "Must call UnInitialize before dtor.";
82 Clear(); 97 Clear();
83 } 98 }
84 99
85 void RenderingHelper::Initialize(const RenderingHelperParams& params, 100 void RenderingHelper::Initialize(const RenderingHelperParams& params,
86 base::WaitableEvent* done) { 101 base::WaitableEvent* done) {
87 // Use cients_.size() != 0 as a proxy for the class having already been 102 // Use videos_.size() != 0 as a proxy for the class having already been
88 // Initialize()'d, and UnInitialize() before continuing. 103 // Initialize()'d, and UnInitialize() before continuing.
89 if (clients_.size()) { 104 if (videos_.size()) {
90 base::WaitableEvent done(false, false); 105 base::WaitableEvent done(false, false);
91 UnInitialize(&done); 106 UnInitialize(&done);
92 done.Wait(); 107 done.Wait();
93 } 108 }
94 109
95 frame_duration_ = params.rendering_fps > 0 110 frame_duration_ = params.rendering_fps > 0
96 ? base::TimeDelta::FromSeconds(1) / params.rendering_fps 111 ? base::TimeDelta::FromSeconds(1) / params.rendering_fps
97 : base::TimeDelta(); 112 : base::TimeDelta();
98 113
99 render_as_thumbnails_ = params.render_as_thumbnails; 114 render_as_thumbnails_ = params.render_as_thumbnails;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 #else 161 #else
147 #error unknown platform 162 #error unknown platform
148 #endif 163 #endif
149 CHECK(window_ != gfx::kNullAcceleratedWidget); 164 CHECK(window_ != gfx::kNullAcceleratedWidget);
150 165
151 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(window_); 166 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(window_);
152 gl_context_ = gfx::GLContext::CreateGLContext( 167 gl_context_ = gfx::GLContext::CreateGLContext(
153 NULL, gl_surface_, gfx::PreferIntegratedGpu); 168 NULL, gl_surface_, gfx::PreferIntegratedGpu);
154 gl_context_->MakeCurrent(gl_surface_); 169 gl_context_->MakeCurrent(gl_surface_);
155 170
156 clients_ = params.clients; 171 CHECK_GT(params.window_sizes.size(), 0U);
157 CHECK_GT(clients_.size(), 0U); 172 videos_.resize(params.window_sizes.size());
158 LayoutRenderingAreas(); 173 LayoutRenderingAreas(params.window_sizes);
159 174
160 if (render_as_thumbnails_) { 175 if (render_as_thumbnails_) {
161 CHECK_EQ(clients_.size(), 1U); 176 CHECK_EQ(videos_.size(), 1U);
162 177
163 GLint max_texture_size; 178 GLint max_texture_size;
164 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); 179 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
165 CHECK_GE(max_texture_size, params.thumbnails_page_size.width()); 180 CHECK_GE(max_texture_size, params.thumbnails_page_size.width());
166 CHECK_GE(max_texture_size, params.thumbnails_page_size.height()); 181 CHECK_GE(max_texture_size, params.thumbnails_page_size.height());
167 182
168 thumbnails_fbo_size_ = params.thumbnails_page_size; 183 thumbnails_fbo_size_ = params.thumbnails_page_size;
169 thumbnail_size_ = params.thumbnail_size; 184 thumbnail_size_ = params.thumbnail_size;
170 185
171 glGenFramebuffersEXT(1, &thumbnails_fbo_id_); 186 glGenFramebuffersEXT(1, &thumbnails_fbo_id_);
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 GLSetViewPort(area); 378 GLSetViewPort(area);
364 RenderTexture(texture_target, texture_id); 379 RenderTexture(texture_target, texture_id);
365 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 380 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
366 381
367 // Need to flush the GL commands before we return the tnumbnail texture to 382 // Need to flush the GL commands before we return the tnumbnail texture to
368 // the decoder. 383 // the decoder.
369 glFlush(); 384 glFlush();
370 ++frame_count_; 385 ++frame_count_;
371 } 386 }
372 387
388 void RenderingHelper::QueueVideoFrame(size_t window_id,
389 scoped_refptr<VideoFrame> video_frame) {
390 RenderedVideo* video = &videos_[window_id];
391
392 // Pop the front if it has been rendered.
393 if (video->last_frame_rendered) {
394 DCHECK(!video->pending_frames.empty());
Pawel Osciak 2014/08/15 05:45:16 Please comment why, this is not obvious.
Owen Lin 2014/08/18 09:03:08 Done.
395 video->pending_frames.pop_front();
396 video->last_frame_rendered = false;
Pawel Osciak 2014/08/15 05:45:16 By the way, for the future, we should have some th
Owen Lin 2014/08/18 09:03:08 Acknowledged.
397 }
398
399 video->pending_frames.push_back(video_frame);
400 }
401
402 void RenderingHelper::DropPendingFrames(size_t window_id) {
403 RenderedVideo* video = &videos_[window_id];
404 video->pending_frames.clear();
405 video->last_frame_rendered = false;
406 }
407
373 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { 408 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
374 // The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler 409 // The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler
375 // is bound to GL_TEXTURE0. 410 // is bound to GL_TEXTURE0.
376 if (texture_target == GL_TEXTURE_2D) { 411 if (texture_target == GL_TEXTURE_2D) {
377 glActiveTexture(GL_TEXTURE0 + 0); 412 glActiveTexture(GL_TEXTURE0 + 0);
378 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) { 413 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
379 glActiveTexture(GL_TEXTURE0 + 1); 414 glActiveTexture(GL_TEXTURE0 + 1);
380 } 415 }
381 glBindTexture(texture_target, texture_id); 416 glBindTexture(texture_target, texture_id);
382 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 417 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
383 glBindTexture(texture_target, 0); 418 glBindTexture(texture_target, 0);
384 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); 419 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
385 } 420 }
386 421
387 void RenderingHelper::DeleteTexture(uint32 texture_id) { 422 void RenderingHelper::DeleteTexture(uint32 texture_id) {
388 glDeleteTextures(1, &texture_id); 423 glDeleteTextures(1, &texture_id);
389 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); 424 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
390 } 425 }
391 426
392 void* RenderingHelper::GetGLContext() { 427 void* RenderingHelper::GetGLContext() {
393 return gl_context_->GetHandle(); 428 return gl_context_->GetHandle();
394 } 429 }
395 430
396 void* RenderingHelper::GetGLDisplay() { 431 void* RenderingHelper::GetGLDisplay() {
397 return gl_surface_->GetDisplay(); 432 return gl_surface_->GetDisplay();
398 } 433 }
399 434
400 void RenderingHelper::Clear() { 435 void RenderingHelper::Clear() {
401 clients_.clear(); 436 videos_.clear();
402 message_loop_ = NULL; 437 message_loop_ = NULL;
403 gl_context_ = NULL; 438 gl_context_ = NULL;
404 gl_surface_ = NULL; 439 gl_surface_ = NULL;
405 440
406 render_as_thumbnails_ = false; 441 render_as_thumbnails_ = false;
407 frame_count_ = 0; 442 frame_count_ = 0;
408 thumbnails_fbo_id_ = 0; 443 thumbnails_fbo_id_ = 0;
409 thumbnails_texture_id_ = 0; 444 thumbnails_texture_id_ = 0;
410 445
411 #if defined(OS_WIN) 446 #if defined(OS_WIN)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } 489 }
455 *alpha_solid = solid; 490 *alpha_solid = solid;
456 491
457 done->Signal(); 492 done->Signal();
458 } 493 }
459 494
460 void RenderingHelper::RenderContent() { 495 void RenderingHelper::RenderContent() {
461 CHECK_EQ(base::MessageLoop::current(), message_loop_); 496 CHECK_EQ(base::MessageLoop::current(), message_loop_);
462 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); 497 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
463 498
499 // To keep the frame before SwapBuffers()
Pawel Osciak 2014/08/15 05:45:16 This is a bit too vague. Maybe: "Frames that will
Owen Lin 2014/08/18 09:03:08 The same comment was added to the member "last_fra
500 std::vector<scoped_refptr<VideoFrame> > frames_to_be_returned;
501
464 if (render_as_thumbnails_) { 502 if (render_as_thumbnails_) {
465 // In render_as_thumbnails_ mode, we render the FBO content on the 503 // In render_as_thumbnails_ mode, we render the FBO content on the
466 // screen instead of the decoded textures. 504 // screen instead of the decoded textures.
467 GLSetViewPort(render_areas_[0]); 505 GLSetViewPort(videos_[0].render_area);
468 RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_); 506 RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
469 } else { 507 } else {
470 for (size_t i = 0; i < clients_.size(); ++i) { 508 for (size_t i = 0; i < videos_.size(); ++i) {
471 if (clients_[i]) { 509 RenderedVideo* video = &videos_[i];
472 GLSetViewPort(render_areas_[i]); 510 if (video->pending_frames.empty())
473 clients_[i]->RenderContent(this); 511 continue;
512 scoped_refptr<VideoFrame> frame = video->pending_frames.front();
513 GLSetViewPort(video->render_area);
514 RenderTexture(frame->texture_target(), frame->texture_id());
515
516 if (video->pending_frames.size() > 1) {
517 frames_to_be_returned.push_back(video->pending_frames.front());
Pawel Osciak 2014/08/15 05:45:16 s/video->pending_frames.front()/frame/
Owen Lin 2014/08/18 09:03:08 Done.
518 video->pending_frames.pop_front();
519 } else {
520 video->last_frame_rendered = true;
Pawel Osciak 2014/08/15 05:45:16 Isn't this a problem in QueueVideoFrame? We may re
Owen Lin 2014/08/18 09:03:08 No, it won't. We set video_last_frame_rendered = t
Pawel Osciak 2014/08/20 10:26:26 Ok now I know why I misunderstood this. You are us
Owen Lin 2014/08/21 03:45:18 We will keep at most one frame for delayed decodin
474 } 521 }
475 } 522 }
476 } 523 }
477 524
478 gl_surface_->SwapBuffers(); 525 gl_surface_->SwapBuffers();
479 } 526 }
480 527
481 // Helper function for the LayoutRenderingAreas(). The |lengths| are the 528 // Helper function for the LayoutRenderingAreas(). The |lengths| are the
482 // heights(widths) of the rows(columns). It scales the elements in 529 // heights(widths) of the rows(columns). It scales the elements in
483 // |lengths| proportionally so that the sum of them equal to |total_length|. 530 // |lengths| proportionally so that the sum of them equal to |total_length|.
484 // It also outputs the coordinates of the rows(columns) to |offsets|. 531 // It also outputs the coordinates of the rows(columns) to |offsets|.
485 static void ScaleAndCalculateOffsets(std::vector<int>* lengths, 532 static void ScaleAndCalculateOffsets(std::vector<int>* lengths,
486 std::vector<int>* offsets, 533 std::vector<int>* offsets,
487 int total_length) { 534 int total_length) {
488 int sum = std::accumulate(lengths->begin(), lengths->end(), 0); 535 int sum = std::accumulate(lengths->begin(), lengths->end(), 0);
489 for (size_t i = 0; i < lengths->size(); ++i) { 536 for (size_t i = 0; i < lengths->size(); ++i) {
490 lengths->at(i) = lengths->at(i) * total_length / sum; 537 lengths->at(i) = lengths->at(i) * total_length / sum;
491 offsets->at(i) = (i == 0) ? 0 : offsets->at(i - 1) + lengths->at(i - 1); 538 offsets->at(i) = (i == 0) ? 0 : offsets->at(i - 1) + lengths->at(i - 1);
492 } 539 }
493 } 540 }
494 541
495 void RenderingHelper::LayoutRenderingAreas() { 542 void RenderingHelper::LayoutRenderingAreas(
543 const std::vector<gfx::Size>& window_sizes) {
496 // Find the number of colums and rows. 544 // Find the number of colums and rows.
497 // The smallest n * n or n * (n + 1) > number of clients. 545 // The smallest n * n or n * (n + 1) > number of windows.
498 size_t cols = sqrt(clients_.size() - 1) + 1; 546 size_t cols = sqrt(videos_.size() - 1) + 1;
499 size_t rows = (clients_.size() + cols - 1) / cols; 547 size_t rows = (videos_.size() + cols - 1) / cols;
500 548
501 // Find the widths and heights of the grid. 549 // Find the widths and heights of the grid.
502 std::vector<int> widths(cols); 550 std::vector<int> widths(cols);
503 std::vector<int> heights(rows); 551 std::vector<int> heights(rows);
504 std::vector<int> offset_x(cols); 552 std::vector<int> offset_x(cols);
505 std::vector<int> offset_y(rows); 553 std::vector<int> offset_y(rows);
506 554
507 for (size_t i = 0; i < clients_.size(); ++i) { 555 for (size_t i = 0; i < window_sizes.size(); ++i) {
508 const gfx::Size& window_size = clients_[i]->GetWindowSize(); 556 const gfx::Size& size = window_sizes[i];
509 widths[i % cols] = std::max(widths[i % cols], window_size.width()); 557 widths[i % cols] = std::max(widths[i % cols], size.width());
510 heights[i / cols] = std::max(heights[i / cols], window_size.height()); 558 heights[i / cols] = std::max(heights[i / cols], size.height());
511 } 559 }
512 560
513 ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width()); 561 ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width());
514 ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height()); 562 ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height());
515 563
516 // Put each render_area_ in the center of each cell. 564 // Put each render_area_ in the center of each cell.
517 render_areas_.clear(); 565 for (size_t i = 0; i < window_sizes.size(); ++i) {
518 for (size_t i = 0; i < clients_.size(); ++i) { 566 const gfx::Size& size = window_sizes[i];
519 const gfx::Size& window_size = clients_[i]->GetWindowSize();
520 float scale = 567 float scale =
521 std::min(static_cast<float>(widths[i % cols]) / window_size.width(), 568 std::min(static_cast<float>(widths[i % cols]) / size.width(),
522 static_cast<float>(heights[i / cols]) / window_size.height()); 569 static_cast<float>(heights[i / cols]) / size.height());
523 570
524 // Don't scale up the texture. 571 // Don't scale up the texture.
525 scale = std::min(1.0f, scale); 572 scale = std::min(1.0f, scale);
526 573
527 size_t w = scale * window_size.width(); 574 size_t w = scale * size.width();
528 size_t h = scale * window_size.height(); 575 size_t h = scale * size.height();
529 size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2; 576 size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2;
530 size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2; 577 size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2;
531 render_areas_.push_back(gfx::Rect(x, y, w, h)); 578 videos_[i].render_area = gfx::Rect(x, y, w, h);
532 } 579 }
533 } 580 }
534 } // namespace content 581 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698