summaryrefslogtreecommitdiffstats
path: root/content/common/gpu/media/rendering_helper.h
blob: ad178f5f30b090dc1ffbb0bd413ebd422a63d6d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
#define CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <queue>
#include <vector>

#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"

namespace base {
class MessageLoop;
class WaitableEvent;
}

namespace ui {
class DisplayConfigurator;
}

namespace content {

class VideoFrameTexture : public base::RefCounted<VideoFrameTexture> {
 public:
  uint32_t texture_id() const { return texture_id_; }
  uint32_t texture_target() const { return texture_target_; }

  VideoFrameTexture(uint32_t texture_target,
                    uint32_t texture_id,
                    const base::Closure& no_longer_needed_cb);

 private:
  friend class base::RefCounted<VideoFrameTexture>;

  uint32_t texture_target_;
  uint32_t texture_id_;
  base::Closure no_longer_needed_cb_;

  ~VideoFrameTexture();
};

struct RenderingHelperParams {
  RenderingHelperParams();
  ~RenderingHelperParams();

  // The rendering FPS.
  int rendering_fps;

  // The number of empty frames rendered when the rendering helper is
  // initialized.
  int warm_up_iterations;

  // The desired size of each window. We play each stream in its own window
  // on the screen.
  std::vector<gfx::Size> window_sizes;

  // The members below are only used for the thumbnail mode where all frames
  // are rendered in sequence onto one FBO for comparison/verification purposes.

  // Whether the frames are rendered as scaled thumbnails within a
  // larger FBO that is in turn rendered to the window.
  bool render_as_thumbnails;
  // The size of the FBO containing all visible thumbnails.
  gfx::Size thumbnails_page_size;
  // The size of each thumbnail within the FBO.
  gfx::Size thumbnail_size;
};

// Creates and draws textures used by the video decoder.
// This class is not thread safe and thus all the methods of this class
// (except for ctor/dtor) ensure they're being run on a single thread.
class RenderingHelper {
 public:

  RenderingHelper();
  ~RenderingHelper();

  // Initialize GL. This method must be called on the rendering
  // thread.
  static void InitializeOneOff(base::WaitableEvent* done);

  // Setup the platform window to display test results. This method
  // must be called on the main thread.
  void Setup();

  // Tear down the platform window. This method must be called on the
  // main thread.
  void TearDown();

  // Create the render context and windows by the specified
  // dimensions. This method must be called on the rendering thread.
  void Initialize(const RenderingHelperParams& params,
                  base::WaitableEvent* done);

  // Undo the effects of Initialize() and signal |*done|. This method
  // must be called on the rendering thread.
  void UnInitialize(base::WaitableEvent* done);

  // Return a newly-created GLES2 texture id of the specified size, and
  // signal |*done|.
  void CreateTexture(uint32_t texture_target,
                     uint32_t* texture_id,
                     const gfx::Size& size,
                     base::WaitableEvent* done);

  // Render thumbnail in the |texture_id| to the FBO buffer using target
  // |texture_target|.
  void RenderThumbnail(uint32_t texture_target, uint32_t texture_id);

  // Queues the |video_frame| for rendering.
  void QueueVideoFrame(size_t window_id,
                       scoped_refptr<VideoFrameTexture> video_frame);

  // Flushes the pending frames. Notify the rendering_helper there won't be
  // more video frames.
  void Flush(size_t window_id);

  // Delete |texture_id|.
  void DeleteTexture(uint32_t texture_id);

  // Get the platform specific handle to the OpenGL display.
  void* GetGLDisplay();

  // Get the GL context.
  gfx::GLContext* GetGLContext();

  // Get rendered thumbnails as RGB.
  // Sets alpha_solid to true if the alpha channel is entirely 0xff.
  void GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
                          bool* alpha_solid,
                          base::WaitableEvent* done);

 private:
  struct RenderedVideo {
    // The rect on the screen where the video will be rendered.
    gfx::Rect render_area;

    // True if there won't be any new video frames comming.
    bool is_flushing;

    // The number of frames need to be dropped to catch up the rendering. We
    // always keep the last remaining frame in pending_frames even after it
    // has been rendered, so that we have something to display if the client
    // is falling behind on providing us with new frames during timer-driven
    // playback.
    int frames_to_drop;

    // The video frames pending for rendering.
    std::queue<scoped_refptr<VideoFrameTexture> > pending_frames;

    RenderedVideo();
    ~RenderedVideo();
  };

  void Clear();

  void RenderContent();

  void WarmUpRendering(int warm_up_iterations);

  void LayoutRenderingAreas(const std::vector<gfx::Size>& window_sizes);

  void UpdateVSyncParameters(base::WaitableEvent* done,
                             const base::TimeTicks timebase,
                             const base::TimeDelta interval);

  void DropOneFrameForAllVideos();
  void ScheduleNextRenderContent();

  // Render |texture_id| to the current view port of the screen using target
  // |texture_target|.
  void RenderTexture(uint32_t texture_target, uint32_t texture_id);

  base::MessageLoop* message_loop_;

  scoped_refptr<gfx::GLContext> gl_context_;
  scoped_refptr<gfx::GLSurface> gl_surface_;

#if defined(USE_OZONE)
  class StubOzoneDelegate;
  scoped_ptr<StubOzoneDelegate> platform_window_delegate_;

#if defined(OS_CHROMEOS)
  scoped_ptr<ui::DisplayConfigurator> display_configurator_;
#endif
#endif

  bool ignore_vsync_;

  gfx::AcceleratedWidget window_;

  gfx::Size screen_size_;

  std::vector<RenderedVideo> videos_;

  bool render_as_thumbnails_;
  int frame_count_;
  GLuint thumbnails_fbo_id_;
  GLuint thumbnails_texture_id_;
  gfx::Size thumbnails_fbo_size_;
  gfx::Size thumbnail_size_;
  GLuint program_;
  base::TimeDelta frame_duration_;
  base::TimeTicks scheduled_render_time_;
  base::CancelableClosure render_task_;
  base::TimeTicks vsync_timebase_;
  base::TimeDelta vsync_interval_;

  DISALLOW_COPY_AND_ASSIGN(RenderingHelper);
};

}  // namespace content

#endif  // CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_