OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // The bulk of this file is support code; sorry about that. Here's an overview | 5 // The bulk of this file is support code; sorry about that. Here's an overview |
6 // to hopefully help readers of this code: | 6 // to hopefully help readers of this code: |
7 // - RenderingHelper is charged with interacting with X11, EGL, and GLES2. | 7 // - RenderingHelper is charged with interacting with X11, EGL, and GLES2. |
8 // - ClientState is an enum for the state of the decode client used by the test. | 8 // - ClientState is an enum for the state of the decode client used by the test. |
9 // - ClientStateNotification is a barrier abstraction that allows the test code | 9 // - ClientStateNotification is a barrier abstraction that allows the test code |
10 // to be written sequentially and wait for the decode client to see certain | 10 // to be written sequentially and wait for the decode client to see certain |
11 // state transitions. | 11 // state transitions. |
12 // - EglRenderingVDAClient is a VideoDecodeAccelerator::Client implementation | 12 // - EglRenderingVDAClient is a VideoDecodeAccelerator::Client implementation |
13 // - Finally actual TEST cases are at the bottom of this file, using the above | 13 // - Finally actual TEST cases are at the bottom of this file, using the above |
14 // infrastructure. | 14 // infrastructure. |
15 | 15 |
16 #include <fcntl.h> | 16 #include <fcntl.h> |
17 #include <math.h> | 17 #include <math.h> |
18 #include <sys/stat.h> | 18 #include <sys/stat.h> |
19 #include <sys/types.h> | 19 #include <sys/types.h> |
20 | 20 |
21 // Include gtest.h out of order because <X11/X.h> #define's Bool & None, which | 21 // Include gtest.h out of order because <X11/X.h> #define's Bool & None, which |
22 // gtest uses as struct names (inside a namespace). This means that | 22 // gtest uses as struct names (inside a namespace). This means that |
23 // #include'ing gtest after anything that pulls in X.h fails to compile. | 23 // #include'ing gtest after anything that pulls in X.h fails to compile. |
24 // This is http://code.google.com/p/googletest/issues/detail?id=371 | 24 // This is http://code.google.com/p/googletest/issues/detail?id=371 |
25 #include "testing/gtest/include/gtest/gtest.h" | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
See the comment above this line for why it's inclu
ananta
2011/12/17 00:40:25
Sorry about that. Restored. I did this to fix a li
| |
26 | |
27 #include "base/at_exit.h" | 25 #include "base/at_exit.h" |
28 #include "base/bind.h" | 26 #include "base/bind.h" |
29 #include "base/command_line.h" | 27 #include "base/command_line.h" |
30 #include "base/file_util.h" | 28 #include "base/file_util.h" |
29 #include "base/process_util.h" | |
31 #include "base/stl_util.h" | 30 #include "base/stl_util.h" |
32 #include "base/string_number_conversions.h" | 31 #include "base/string_number_conversions.h" |
33 #include "base/string_split.h" | 32 #include "base/string_split.h" |
34 #include "base/stringize_macros.h" | 33 #include "base/stringize_macros.h" |
35 #include "base/synchronization/condition_variable.h" | 34 #include "base/synchronization/condition_variable.h" |
36 #include "base/synchronization/lock.h" | 35 #include "base/synchronization/lock.h" |
37 #include "base/synchronization/waitable_event.h" | 36 #include "base/synchronization/waitable_event.h" |
38 #include "base/threading/thread.h" | 37 #include "base/threading/thread.h" |
38 #include "base/utf_string_conversions.h" | |
39 | |
40 #if (defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)) || defined(OS_WIN) | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
If you negate this up here & #error out, then afte
ananta
2011/12/17 00:40:25
Done.
| |
41 #if defined(OS_WIN) | |
42 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" | |
43 #else // OS_WIN | |
39 #include "content/common/gpu/media/omx_video_decode_accelerator.h" | 44 #include "content/common/gpu/media/omx_video_decode_accelerator.h" |
45 #endif // defined(OS_WIN) | |
46 #endif // (defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)) || defined(OS_WIN) | |
47 | |
48 #include "testing/gtest/include/gtest/gtest.h" | |
40 #include "third_party/angle/include/EGL/egl.h" | 49 #include "third_party/angle/include/EGL/egl.h" |
41 #include "third_party/angle/include/GLES2/gl2.h" | 50 #include "third_party/angle/include/GLES2/gl2.h" |
42 | 51 |
43 #if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_ARMEL) | 52 #if !defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && !defined(OS_WIN) |
44 #error This test (and OmxVideoDecodeAccelerator) are only supported on cros/ARM! | 53 #error The VideoAccelerator tests are only supported on cros/ARM/Windows. |
45 #endif | 54 #endif |
46 | 55 |
47 using media::VideoDecodeAccelerator; | 56 using media::VideoDecodeAccelerator; |
48 | 57 |
49 namespace { | 58 namespace { |
50 | 59 |
51 // Values optionally filled in from flags; see main() below. | 60 // Values optionally filled in from flags; see main() below. |
52 // The syntax of this variable is: | 61 // The syntax of this variable is: |
53 // filename:width:height:numframes:numNALUs:minFPSwithRender:minFPSnoRender | 62 // filename:width:height:numframes:numNALUs:minFPSwithRender:minFPSnoRender |
54 // where only the first field is required. Value details: | 63 // where only the first field is required. Value details: |
55 // - |filename| must be an h264 Annex B (NAL) stream. | 64 // - |filename| must be an h264 Annex B (NAL) stream. |
56 // - |width| and |height| are in pixels. | 65 // - |width| and |height| are in pixels. |
57 // - |numframes| is the number of picture frames in the file. | 66 // - |numframes| is the number of picture frames in the file. |
58 // - |numNALUs| is the number of NAL units in the stream. | 67 // - |numNALUs| is the number of NAL units in the stream. |
59 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds | 68 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds |
60 // expected to be achieved with and without rendering to the screen, resp. | 69 // expected to be achieved with and without rendering to the screen, resp. |
61 // (the latter tests just decode speed). | 70 // (the latter tests just decode speed). |
62 // - |profile| is the media::H264Profile set during Initialization. | 71 // - |profile| is the media::H264Profile set during Initialization. |
63 // An empty value for a numeric field means "ignore". | 72 // An empty value for a numeric field means "ignore". |
64 const char* test_video_data = "test-25fps.h264:320:240:250:258:50:175:1"; | 73 std::string test_video_data = "test-25fps.h264:320:240:250:258:50:175:1"; |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
style guide prohibits global vars of class type, w
ananta
2011/12/17 00:40:25
Restored.
| |
65 | 74 |
66 // Parse |data| into its constituent parts and set the various output fields | 75 // Parse |data| into its constituent parts and set the various output fields |
67 // accordingly. CHECK-fails on unexpected or missing required data. | 76 // accordingly. CHECK-fails on unexpected or missing required data. |
68 // Unspecified optional fields are set to -1. | 77 // Unspecified optional fields are set to -1. |
69 void ParseTestVideoData(std::string data, | 78 void ParseTestVideoData(std::string data, |
70 std::string* file_name, | 79 std::string* file_name, |
71 int* width, int* height, | 80 int* width, int* height, |
72 int* num_frames, | 81 int* num_frames, |
73 int* num_NALUs, | 82 int* num_NALUs, |
74 int* min_fps_render, | 83 int* min_fps_render, |
(...skipping 16 matching lines...) Expand all Loading... | |
91 if (!elements[4].empty()) | 100 if (!elements[4].empty()) |
92 CHECK(base::StringToInt(elements[4], num_NALUs)); | 101 CHECK(base::StringToInt(elements[4], num_NALUs)); |
93 if (!elements[5].empty()) | 102 if (!elements[5].empty()) |
94 CHECK(base::StringToInt(elements[5], min_fps_render)); | 103 CHECK(base::StringToInt(elements[5], min_fps_render)); |
95 if (!elements[6].empty()) | 104 if (!elements[6].empty()) |
96 CHECK(base::StringToInt(elements[6], min_fps_no_render)); | 105 CHECK(base::StringToInt(elements[6], min_fps_no_render)); |
97 if (!elements[7].empty()) | 106 if (!elements[7].empty()) |
98 CHECK(base::StringToInt(elements[7], profile)); | 107 CHECK(base::StringToInt(elements[7], profile)); |
99 } | 108 } |
100 | 109 |
110 // Helper for Shader creation. | |
111 static void CreateShader( | |
112 GLuint program, GLenum type, const char* source, int size) { | |
113 GLuint shader = glCreateShader(type); | |
114 glShaderSource(shader, 1, &source, &size); | |
115 glCompileShader(shader); | |
116 int result = GL_FALSE; | |
117 glGetShaderiv(shader, GL_COMPILE_STATUS, &result); | |
118 if (!result) { | |
119 char log[4096]; | |
120 glGetShaderInfoLog(shader, arraysize(log), NULL, log); | |
121 LOG(FATAL) << log; | |
122 } | |
123 glAttachShader(program, shader); | |
124 glDeleteShader(shader); | |
125 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
126 } | |
101 | 127 |
102 // Helper for managing X11, EGL, and GLES2 resources. Xlib is not thread-safe, | 128 // Provides base functionality for managing EGL and GLES2 resources. |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Why move this below CreateShader above? It makes
ananta
2011/12/17 00:40:25
Moved this back to just before Initialize.
The Cre
Ami GONE FROM CHROMIUM
2011/12/19 22:53:44
Hahahahahahaha - now it's harder to diff between p
| |
103 // and GL state is thread-specific, so all the methods of this class (except for | 129 // This class is not thread safe and thus all the methods of this class |
104 // ctor/dtor) ensure they're being run on a single thread. | 130 // (except for ctor/dtor) ensure they're being run on a single thread. |
105 // | 131 // |
106 // TODO(fischman): consider moving this into media/ if we can de-dup some of the | 132 // TODO(fischman): consider moving this into media/ if we can de-dup some of |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
TODO can be dropped now that the media/ version of
ananta
2011/12/17 00:40:25
Done.
| |
107 // code that ends up getting copy/pasted all over the place (esp. the GL setup | 133 // the code that ends up getting copy/pasted all over the place (esp. the GL |
108 // code). | 134 // setup code). |
109 class RenderingHelper { | 135 class RenderingHelperBase { |
110 public: | 136 public: |
111 explicit RenderingHelper(); | 137 RenderingHelperBase(); |
112 ~RenderingHelper(); | 138 virtual ~RenderingHelperBase(); |
113 | 139 |
114 // Initialize all structures to prepare to render to one or more windows of | 140 // Initialize all structures to prepare to render to one or more windows of |
115 // the specified dimensions. CHECK-fails if any initialization step fails. | 141 // the specified dimensions. CHECK-fails if any initialization step fails. |
116 // After this returns, texture creation and rendering can be requested. This | 142 // After this returns, texture creation and rendering can be requested. This |
117 // method can be called multiple times, in which case all previously-acquired | 143 // method can be called multiple times, in which case all previously-acquired |
118 // resources and initializations are discarded. If |suppress_swap_to_display| | 144 // resources and initializations are discarded. If |suppress_swap_to_display| |
119 // then all the usual work is done, except for the final swap of the EGL | 145 // then all the usual work is done, except for the final swap of the EGL |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
s/EGL// ?
ananta
2011/12/17 00:40:25
I just copied this as is from the existing comment
Ami GONE FROM CHROMIUM
2011/12/19 22:53:44
My point was that in the DXVA case the surfaces ar
| |
120 // surface to the display. This cuts test times over 50% so is worth doing | 146 // surface to the display. This cuts test times over 50% so is worth doing |
121 // when testing non-rendering-related aspects. | 147 // when testing non-rendering-related aspects. |
122 void Initialize(bool suppress_swap_to_display, int num_windows, | 148 virtual void Initialize( |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
You've introduced a de-facto requirement that subc
ananta
2011/12/17 00:40:25
Done.
| |
123 int width, int height, base::WaitableEvent* done); | 149 bool suppress_swap_to_display, int num_windows, |
150 int width, int height, base::WaitableEvent* done); | |
124 | 151 |
125 // Undo the effects of Initialize() and signal |*done|. | 152 // Undo the effects of Initialize() and signal |*done|. |
126 void UnInitialize(base::WaitableEvent* done); | 153 virtual void UnInitialize(base::WaitableEvent* done); |
154 | |
155 // Platform specific window creation. | |
156 virtual EGLNativeWindowType PlatformCreateWindow(int top_left_x, | |
157 int top_left_y) PURE; | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Is PURE cross-platform? I've only ever seen =0 in
ananta
2011/12/17 00:40:25
Done.
| |
127 | 158 |
128 // Return a newly-created GLES2 texture id rendering to a specific window, and | 159 // Return a newly-created GLES2 texture id rendering to a specific window, and |
129 // signal |*done|. | 160 // signal |*done|. |
130 void CreateTexture(int window_id, GLuint* texture_id, | 161 void CreateTexture(int window_id, GLuint* texture_id, |
131 base::WaitableEvent* done); | 162 base::WaitableEvent* done); |
132 | 163 |
133 // Render |texture_id| to the screen (unless |suppress_swap_to_display_|). | 164 // Render |texture_id| to the screen (unless |suppress_swap_to_display_|). |
134 void RenderTexture(GLuint texture_id); | 165 void RenderTexture(GLuint texture_id); |
135 | 166 |
136 // Delete |texture_id|. | 167 // Delete |texture_id|. |
137 void DeleteTexture(GLuint texture_id); | 168 void DeleteTexture(GLuint texture_id); |
138 | 169 |
139 EGLDisplay egl_display() { return egl_display_; } | 170 EGLDisplay egl_display() { |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
single-line
ananta
2011/12/17 00:40:25
Done.
| |
140 EGLContext egl_context() { return egl_context_; } | 171 return egl_display_; |
172 } | |
173 | |
174 EGLContext egl_context() { | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
single line
ananta
2011/12/17 00:40:25
Done.
| |
175 return egl_context_; | |
176 } | |
177 | |
141 MessageLoop* message_loop() { return message_loop_; } | 178 MessageLoop* message_loop() { return message_loop_; } |
142 | 179 |
143 private: | 180 protected: |
144 // Zero-out internal state. Helper for ctor & UnInitialize(). | |
145 void Clear(); | 181 void Clear(); |
146 | 182 |
147 bool suppress_swap_to_display_; | 183 // We ensure all operations are carried out on the same thread by remembering |
184 // where we were Initialized. | |
185 MessageLoop* message_loop_; | |
148 int width_; | 186 int width_; |
149 int height_; | 187 int height_; |
150 Display* x_display_; | 188 bool suppress_swap_to_display_; |
151 std::vector<Window> x_windows_; | 189 int num_windows_; |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Never used.
ananta
2011/12/17 00:40:25
Removed
| |
190 | |
152 EGLDisplay egl_display_; | 191 EGLDisplay egl_display_; |
153 EGLContext egl_context_; | 192 EGLContext egl_context_; |
154 std::vector<EGLSurface> egl_surfaces_; | 193 std::vector<EGLSurface> egl_surfaces_; |
155 std::map<GLuint, int> texture_id_to_surface_index_; | 194 std::map<GLuint, int> texture_id_to_surface_index_; |
156 // We ensure all operations are carried out on the same thread by remembering | |
157 // where we were Initialized. | |
158 MessageLoop* message_loop_; | |
159 }; | 195 }; |
160 | 196 |
161 RenderingHelper::RenderingHelper() { | 197 RenderingHelperBase::RenderingHelperBase() { |
162 Clear(); | 198 Clear(); |
163 } | 199 } |
164 | 200 |
165 RenderingHelper::~RenderingHelper() { | 201 RenderingHelperBase::~RenderingHelperBase() { |
166 CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor."; | 202 Clear(); |
167 } | 203 } |
168 | 204 |
169 void RenderingHelper::Clear() { | 205 void RenderingHelperBase::Initialize(bool suppress_swap_to_display, |
170 suppress_swap_to_display_ = false; | 206 int num_windows, |
171 width_ = 0; | 207 int width, |
172 height_ = 0; | 208 int height, |
173 x_display_ = NULL; | 209 base::WaitableEvent* done) { |
174 x_windows_.clear(); | |
175 egl_display_ = EGL_NO_DISPLAY; | |
176 egl_context_ = EGL_NO_CONTEXT; | |
177 egl_surfaces_.clear(); | |
178 texture_id_to_surface_index_.clear(); | |
179 message_loop_ = NULL; | |
180 } | |
181 | |
182 // Helper for Shader creation. | |
183 static void CreateShader( | |
184 GLuint program, GLenum type, const char* source, int size) { | |
185 GLuint shader = glCreateShader(type); | |
186 glShaderSource(shader, 1, &source, &size); | |
187 glCompileShader(shader); | |
188 int result = GL_FALSE; | |
189 glGetShaderiv(shader, GL_COMPILE_STATUS, &result); | |
190 if (!result) { | |
191 char log[4096]; | |
192 glGetShaderInfoLog(shader, arraysize(log), NULL, log); | |
193 LOG(FATAL) << log; | |
194 } | |
195 glAttachShader(program, shader); | |
196 glDeleteShader(shader); | |
197 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
198 } | |
199 | |
200 void RenderingHelper::Initialize( | |
201 bool suppress_swap_to_display, | |
202 int num_windows, | |
203 int width, int height, | |
204 base::WaitableEvent* done) { | |
205 // Use width_ != 0 as a proxy for the class having already been | 210 // Use width_ != 0 as a proxy for the class having already been |
206 // Initialize()'d, and UnInitialize() before continuing. | 211 // Initialize()'d, and UnInitialize() before continuing. |
207 if (width_) { | 212 if (width_) { |
208 base::WaitableEvent done(false, false); | 213 base::WaitableEvent done(false, false); |
209 UnInitialize(&done); | 214 UnInitialize(&done); |
210 done.Wait(); | 215 done.Wait(); |
211 } | 216 } |
212 | 217 |
213 suppress_swap_to_display_ = suppress_swap_to_display; | 218 suppress_swap_to_display_ = suppress_swap_to_display; |
214 CHECK_GT(width, 0); | 219 CHECK_GT(width, 0); |
215 CHECK_GT(height, 0); | 220 CHECK_GT(height, 0); |
216 width_ = width; | 221 width_ = width; |
217 height_ = height; | 222 height_ = height; |
218 message_loop_ = MessageLoop::current(); | 223 message_loop_ = MessageLoop::current(); |
219 CHECK_GT(num_windows, 0); | 224 CHECK_GT(num_windows, 0); |
225 num_windows_ = num_windows; | |
220 | 226 |
221 // Per-display X11 & EGL initialization. | |
222 CHECK(x_display_ = XOpenDisplay(NULL)); | |
223 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); | |
224 XSetWindowAttributes window_attributes; | |
225 window_attributes.background_pixel = | |
226 BlackPixel(x_display_, DefaultScreen(x_display_)); | |
227 window_attributes.override_redirect = true; | |
228 | |
229 egl_display_ = eglGetDisplay(x_display_); | |
230 EGLint major; | 227 EGLint major; |
231 EGLint minor; | 228 EGLint minor; |
232 CHECK(eglInitialize(egl_display_, &major, &minor)) << eglGetError(); | 229 CHECK(eglInitialize(egl_display_, &major, &minor)) << eglGetError(); |
233 static EGLint rgba8888[] = { | 230 static EGLint rgba8888[] = { |
234 EGL_RED_SIZE, 8, | 231 EGL_RED_SIZE, 8, |
235 EGL_GREEN_SIZE, 8, | 232 EGL_GREEN_SIZE, 8, |
236 EGL_BLUE_SIZE, 8, | 233 EGL_BLUE_SIZE, 8, |
237 EGL_ALPHA_SIZE, 8, | 234 EGL_ALPHA_SIZE, 8, |
238 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | 235 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
239 EGL_NONE, | 236 EGL_NONE, |
240 }; | 237 }; |
241 EGLConfig egl_config; | 238 EGLConfig egl_config; |
242 int num_configs; | 239 int num_configs; |
243 CHECK(eglChooseConfig(egl_display_, rgba8888, &egl_config, 1, &num_configs)) | 240 CHECK(eglChooseConfig(egl_display_, rgba8888, &egl_config, 1, &num_configs)) |
244 << eglGetError(); | 241 << eglGetError(); |
245 CHECK_GE(num_configs, 1); | 242 CHECK_GE(num_configs, 1); |
246 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; | 243 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; |
247 egl_context_ = eglCreateContext( | 244 egl_context_ = eglCreateContext( |
248 egl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); | 245 egl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); |
249 CHECK_NE(egl_context_, EGL_NO_CONTEXT) << eglGetError(); | 246 CHECK_NE(egl_context_, EGL_NO_CONTEXT) << eglGetError(); |
250 | 247 |
251 // Per-window/surface X11 & EGL initialization. | 248 // Per-window/surface X11 & EGL initialization. |
252 for (int i = 0; i < num_windows; ++i) { | 249 for (int i = 0; i < num_windows; ++i) { |
253 // Arrange X windows whimsically, with some padding. | 250 // Arrange X windows whimsically, with some padding. |
254 int top_left_x = (width + 20) * (i % 4); | 251 int top_left_x = (width + 20) * (i % 4); |
255 int top_left_y = (height + 12) * (i % 3); | 252 int top_left_y = (height + 12) * (i % 3); |
256 Window x_window = XCreateWindow( | |
257 x_display_, DefaultRootWindow(x_display_), | |
258 top_left_x, top_left_y, width_, height_, | |
259 0 /* border width */, | |
260 depth, CopyFromParent /* class */, CopyFromParent /* visual */, | |
261 (CWBackPixel | CWOverrideRedirect), &window_attributes); | |
262 x_windows_.push_back(x_window); | |
263 XStoreName(x_display_, x_window, "OmxVideoDecodeAcceleratorTest"); | |
264 XSelectInput(x_display_, x_window, ExposureMask); | |
265 XMapWindow(x_display_, x_window); | |
266 | 253 |
254 EGLNativeWindowType window = PlatformCreateWindow(top_left_x, top_left_y); | |
267 EGLSurface egl_surface = | 255 EGLSurface egl_surface = |
268 eglCreateWindowSurface(egl_display_, egl_config, x_window, NULL); | 256 eglCreateWindowSurface(egl_display_, egl_config, window, NULL); |
269 egl_surfaces_.push_back(egl_surface); | 257 egl_surfaces_.push_back(egl_surface); |
270 CHECK_NE(egl_surface, EGL_NO_SURFACE); | 258 CHECK_NE(egl_surface, EGL_NO_SURFACE); |
271 } | 259 } |
272 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[0], | 260 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[0], |
273 egl_surfaces_[0], egl_context_)) << eglGetError(); | 261 egl_surfaces_[0], egl_context_)) << eglGetError(); |
274 | |
275 // GLES2 initialization. Note: This is pretty much copy/pasted from | 262 // GLES2 initialization. Note: This is pretty much copy/pasted from |
276 // media/tools/player_x11/gles_video_renderer.cc, with some simplification | 263 // media/tools/player_x11/gles_video_renderer.cc, with some simplification |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Drop the Note: since that file is now gone.
ananta
2011/12/17 00:40:25
Done.
| |
277 // applied. | 264 // applied. |
278 static const float kVertices[] = | 265 static const float kVertices[] = |
279 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, }; | 266 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, }; |
280 static const float kTextureCoordsEgl[] = { 0, 1, 0, 0, 1, 1, 1, 0, }; | 267 static const float kTextureCoordsEgl[] = { 0, 1, 0, 0, 1, 1, 1, 0, }; |
281 static const char kVertexShader[] = STRINGIZE( | 268 static const char kVertexShader[] = STRINGIZE( |
282 varying vec2 interp_tc; | 269 varying vec2 interp_tc; |
283 attribute vec4 in_pos; | 270 attribute vec4 in_pos; |
284 attribute vec2 in_tc; | 271 attribute vec2 in_tc; |
285 void main() { | 272 void main() { |
286 interp_tc = in_tc; | 273 interp_tc = in_tc; |
(...skipping 25 matching lines...) Expand all Loading... | |
312 glDeleteProgram(program); | 299 glDeleteProgram(program); |
313 | 300 |
314 glUniform1i(glGetUniformLocation(program, "tex"), 0); | 301 glUniform1i(glGetUniformLocation(program, "tex"), 0); |
315 int pos_location = glGetAttribLocation(program, "in_pos"); | 302 int pos_location = glGetAttribLocation(program, "in_pos"); |
316 glEnableVertexAttribArray(pos_location); | 303 glEnableVertexAttribArray(pos_location); |
317 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); | 304 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); |
318 int tc_location = glGetAttribLocation(program, "in_tc"); | 305 int tc_location = glGetAttribLocation(program, "in_tc"); |
319 glEnableVertexAttribArray(tc_location); | 306 glEnableVertexAttribArray(tc_location); |
320 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, | 307 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
321 kTextureCoordsEgl); | 308 kTextureCoordsEgl); |
322 | |
323 done->Signal(); | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Since neither impl does anything after calling thi
| |
324 } | 309 } |
325 | 310 |
326 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { | 311 void RenderingHelperBase::UnInitialize(base::WaitableEvent* done) { |
327 CHECK_EQ(MessageLoop::current(), message_loop_); | 312 CHECK_EQ(MessageLoop::current(), message_loop_); |
328 // Destroy resources acquired in Initialize, in reverse-acquisition order. | |
329 CHECK(eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, | 313 CHECK(eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, |
330 EGL_NO_CONTEXT)) << eglGetError(); | 314 EGL_NO_CONTEXT)) << eglGetError(); |
331 CHECK(eglDestroyContext(egl_display_, egl_context_)); | 315 CHECK(eglDestroyContext(egl_display_, egl_context_)); |
332 for (size_t i = 0; i < egl_surfaces_.size(); ++i) | 316 for (size_t i = 0; i < egl_surfaces_.size(); ++i) |
333 CHECK(eglDestroySurface(egl_display_, egl_surfaces_[i])); | 317 CHECK(eglDestroySurface(egl_display_, egl_surfaces_[i])); |
334 CHECK(eglTerminate(egl_display_)); | 318 CHECK(eglTerminate(egl_display_)); |
335 for (size_t i = 0; i < x_windows_.size(); ++i) { | |
336 CHECK(XUnmapWindow(x_display_, x_windows_[i])); | |
337 CHECK(XDestroyWindow(x_display_, x_windows_[i])); | |
338 } | |
339 // Mimic newly-created object. | |
340 Clear(); | 319 Clear(); |
341 done->Signal(); | |
342 } | 320 } |
343 | 321 |
344 void RenderingHelper::CreateTexture(int window_id, GLuint* texture_id, | 322 void RenderingHelperBase::Clear() { |
345 base::WaitableEvent* done) { | 323 suppress_swap_to_display_ = false; |
324 width_ = 0; | |
325 height_ = 0; | |
326 texture_id_to_surface_index_.clear(); | |
327 message_loop_ = NULL; | |
328 num_windows_ = 0; | |
329 egl_display_ = EGL_NO_DISPLAY; | |
330 egl_context_ = EGL_NO_CONTEXT; | |
331 egl_surfaces_.clear(); | |
332 } | |
333 | |
334 void RenderingHelperBase::CreateTexture(int window_id, GLuint* texture_id, | |
335 base::WaitableEvent* done) { | |
336 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id], | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Why is this before the trampoline?
ananta
2011/12/17 00:40:25
Stupid mistake :(
| |
337 egl_surfaces_[window_id], egl_context_)) | |
338 << eglGetError(); | |
346 if (MessageLoop::current() != message_loop_) { | 339 if (MessageLoop::current() != message_loop_) { |
347 message_loop_->PostTask( | 340 message_loop_->PostTask( |
348 FROM_HERE, | 341 FROM_HERE, |
349 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), | 342 base::Bind(&RenderingHelperBase::CreateTexture, base::Unretained(this), |
350 window_id, texture_id, done)); | 343 window_id, texture_id, done)); |
351 return; | 344 return; |
352 } | 345 } |
353 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id], | |
354 egl_surfaces_[window_id], egl_context_)) | |
355 << eglGetError(); | |
356 glGenTextures(1, texture_id); | 346 glGenTextures(1, texture_id); |
357 glBindTexture(GL_TEXTURE_2D, *texture_id); | 347 glBindTexture(GL_TEXTURE_2D, *texture_id); |
358 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, | 348 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, |
359 GL_UNSIGNED_BYTE, NULL); | 349 GL_UNSIGNED_BYTE, NULL); |
360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
362 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. | 352 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. |
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
365 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 355 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
366 CHECK(texture_id_to_surface_index_.insert( | 356 CHECK(texture_id_to_surface_index_.insert( |
367 std::make_pair(*texture_id, window_id)).second); | 357 std::make_pair(*texture_id, window_id)).second); |
368 done->Signal(); | 358 done->Signal(); |
369 } | 359 } |
370 | 360 |
371 void RenderingHelper::RenderTexture(GLuint texture_id) { | 361 void RenderingHelperBase::RenderTexture(GLuint texture_id) { |
372 CHECK_EQ(MessageLoop::current(), message_loop_); | 362 CHECK_EQ(MessageLoop::current(), message_loop_); |
373 glActiveTexture(GL_TEXTURE0); | 363 glActiveTexture(GL_TEXTURE0); |
374 glBindTexture(GL_TEXTURE_2D, texture_id); | 364 glBindTexture(GL_TEXTURE_2D, texture_id); |
375 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 365 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
376 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 366 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
377 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | 367 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
368 | |
378 if (!suppress_swap_to_display_) { | 369 if (!suppress_swap_to_display_) { |
379 int window_id = texture_id_to_surface_index_[texture_id]; | 370 int window_id = texture_id_to_surface_index_[texture_id]; |
380 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id], | 371 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id], |
381 egl_surfaces_[window_id], egl_context_)) | 372 egl_surfaces_[window_id], egl_context_)) |
382 << eglGetError(); | 373 << eglGetError(); |
383 eglSwapBuffers(egl_display_, egl_surfaces_[window_id]); | 374 eglSwapBuffers(egl_display_, egl_surfaces_[window_id]); |
384 } | 375 } |
385 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | 376 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
386 } | 377 } |
387 | 378 |
388 void RenderingHelper::DeleteTexture(GLuint texture_id) { | 379 void RenderingHelperBase::DeleteTexture(GLuint texture_id) { |
389 glDeleteTextures(1, &texture_id); | 380 glDeleteTextures(1, &texture_id); |
390 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 381 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
391 } | 382 } |
392 | 383 |
384 #if defined(OS_WIN) | |
385 // Provides Windows specific functionality for managing resources like HWND's | |
386 // The OpenGL and GLES management is provided by the RenderingHelperBase class. | |
387 class Win32RenderingHelper : public RenderingHelperBase { | |
388 public: | |
389 Win32RenderingHelper(); | |
390 virtual ~Win32RenderingHelper(); | |
391 | |
392 virtual void Initialize( | |
393 bool suppress_swap_to_display, int num_windows, | |
394 int width, int height, base::WaitableEvent* done) OVERRIDE; | |
395 | |
396 virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE; | |
397 | |
398 EGLNativeWindowType PlatformCreateWindow(int top_left_x, | |
399 int top_left_y) OVERRIDE; | |
400 private: | |
401 void Clear(); | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
This shadows the base-class Clear (which isn't vir
ananta
2011/12/17 00:40:25
Replaced this with a virtual override combo Platfo
| |
402 | |
403 std::vector<HWND> windows_; | |
404 }; | |
405 | |
406 Win32RenderingHelper::Win32RenderingHelper() | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Single line.
ananta
2011/12/17 00:40:25
Done.
| |
407 : windows_(NULL) { | |
408 } | |
409 | |
410 Win32RenderingHelper::~Win32RenderingHelper() { | |
411 Clear(); | |
412 } | |
413 | |
414 void Win32RenderingHelper::Initialize(bool suppress_swap_to_display, | |
415 int num_windows, | |
416 int width, | |
417 int height, | |
418 base::WaitableEvent* done) { | |
419 egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
420 RenderingHelperBase::Initialize(suppress_swap_to_display, num_windows, width, | |
421 height, done); | |
422 done->Signal(); | |
423 } | |
424 | |
425 void Win32RenderingHelper::UnInitialize(base::WaitableEvent* done) { | |
426 RenderingHelperBase::UnInitialize(done); | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
No need to undo the eglGetDisplay() from Initializ
ananta
2011/12/17 00:40:25
That happens in the base class Clear function. We
| |
427 Clear(); | |
428 done->Signal(); | |
429 } | |
430 | |
431 void Win32RenderingHelper::Clear() { | |
432 for (size_t i = 0; i < windows_.size(); ++i) { | |
433 DestroyWindow(windows_[i]); | |
434 } | |
435 windows_.clear(); | |
436 } | |
437 | |
438 EGLNativeWindowType Win32RenderingHelper::PlatformCreateWindow( | |
439 int top_left_x, int top_left_y) { | |
440 HWND window = CreateWindowEx(0, | |
441 L"Static", | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Wrap a bit more aggressively?
ananta
2011/12/17 00:40:25
Done.
| |
442 L"VideoDecodeAcceleratorTest", | |
443 WS_OVERLAPPEDWINDOW | WS_VISIBLE, | |
444 top_left_x, | |
445 top_left_y, | |
446 width_, | |
447 height_, | |
448 NULL, | |
449 NULL, | |
450 NULL, | |
451 NULL); | |
452 CHECK(window != NULL); | |
453 windows_.push_back(window); | |
454 return window; | |
455 } | |
456 | |
457 #else // OS_WIN | |
458 | |
459 // Provides X11 specific functionality for managing X11 resources. The OpenGL | |
460 // and GLES management is provided by the RenderingHelperBase class. | |
461 class OmxRenderingHelper : public RenderingHelperBase { | |
462 public: | |
463 explicit OmxRenderingHelper(); | |
464 ~OmxRenderingHelper(); | |
465 | |
466 // Initialize all structures to prepare to render to one or more windows of | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Commentary isn't necessary for OVERRIDEs. Just pr
ananta
2011/12/17 00:40:25
Done.
| |
467 // the specified dimensions. CHECK-fails if any initialization step fails. | |
468 // After this returns, texture creation and rendering can be requested. This | |
469 // method can be called multiple times, in which case all previously-acquired | |
470 // resources and initializations are discarded. If |suppress_swap_to_display| | |
471 // then all the usual work is done, except for the final swap of the EGL | |
472 // surface to the display. This cuts test times over 50% so is worth doing | |
473 // when testing non-rendering-related aspects. | |
474 virtual void Initialize( | |
475 bool suppress_swap_to_display, int num_windows, | |
476 int width, int height, base::WaitableEvent* done) OVERRIDE; | |
477 | |
478 // Undo the effects of Initialize() and signal |*done|. | |
479 virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE; | |
480 | |
481 virtual EGLNativeWindowType PlatformCreateWindow(int top_left_x, | |
482 int top_left_y) OVERRIDE; | |
483 | |
484 | |
485 private: | |
486 // Zero-out internal state. Helper for ctor & UnInitialize(). | |
487 void Clear(); | |
488 | |
489 Display* x_display_; | |
490 std::vector<Window> x_windows_; | |
491 }; | |
492 | |
493 OmxRenderingHelper::OmxRenderingHelper() { | |
494 Clear(); | |
495 } | |
496 | |
497 OmxRenderingHelper::~OmxRenderingHelper() { | |
498 CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor."; | |
499 } | |
500 | |
501 void OmxRenderingHelper::Clear() { | |
502 x_display_ = NULL; | |
503 x_windows_.clear(); | |
504 } | |
505 | |
506 void OmxRenderingHelper::Initialize( | |
507 bool suppress_swap_to_display, | |
508 int num_windows, | |
509 int width, int height, | |
510 base::WaitableEvent* done) { | |
511 // Per-display X11 & EGL initialization. | |
512 CHECK(x_display_ = XOpenDisplay(NULL)); | |
513 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); | |
514 XSetWindowAttributes window_attributes; | |
515 window_attributes.background_pixel = | |
516 BlackPixel(x_display_, DefaultScreen(x_display_)); | |
517 window_attributes.override_redirect = true; | |
518 | |
519 egl_display_ = eglGetDisplay(x_display_); | |
520 | |
521 RenderingHelperBase::Initialize(suppress_swap_to_display, num_windows, | |
522 width, height, done); | |
523 done->Signal(); | |
524 } | |
525 | |
526 void OmxRenderingHelper::UnInitialize(base::WaitableEvent* done) { | |
527 RenderingHelperBase::Uninitialize(); | |
528 // Destroy resources acquired in Initialize, in reverse-acquisition order. | |
529 for (size_t i = 0; i < x_windows_.size(); ++i) { | |
530 CHECK(XUnmapWindow(x_display_, x_windows_[i])); | |
531 CHECK(XDestroyWindow(x_display_, x_windows_[i])); | |
532 } | |
533 // Mimic newly-created object. | |
534 Clear(); | |
535 done->Signal(); | |
536 } | |
537 | |
538 EGLNativeWindowType OmxRenderingHelper::PlatformCreateWindow(int top_left_x, | |
539 int top_left_y) { | |
540 Window x_window = XCreateWindow( | |
541 x_display_, DefaultRootWindow(x_display_), | |
542 top_left_x, top_left_y, width_, height_, | |
543 0 /* border width */, | |
544 depth, CopyFromParent /* class */, CopyFromParent /* visual */, | |
545 (CWBackPixel | CWOverrideRedirect), &window_attributes); | |
546 x_windows_.push_back(x_window); | |
547 XStoreName(x_display_, x_window, "VideoDecodeAcceleratorTest"); | |
548 XSelectInput(x_display_, x_window, ExposureMask); | |
549 XMapWindow(x_display_, x_window); | |
550 return x_window; | |
551 } | |
552 | |
553 #endif // OS_WIN | |
554 | |
393 // State of the EglRenderingVDAClient below. Order matters here as the test | 555 // State of the EglRenderingVDAClient below. Order matters here as the test |
394 // makes assumptions about it. | 556 // makes assumptions about it. |
395 enum ClientState { | 557 enum ClientState { |
396 CS_CREATED, | 558 CS_CREATED, |
397 CS_DECODER_SET, | 559 CS_DECODER_SET, |
398 CS_INITIALIZED, | 560 CS_INITIALIZED, |
399 CS_FLUSHING, | 561 CS_FLUSHING, |
400 CS_FLUSHED, | 562 CS_FLUSHED, |
401 CS_DONE, | 563 CS_DONE, |
402 CS_RESETTING, | 564 CS_RESETTING, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { | 618 class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { |
457 public: | 619 public: |
458 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive | 620 // Doesn't take ownership of |rendering_helper| or |note|, which must outlive |
459 // |*this|. | 621 // |*this|. |
460 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream | 622 // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream |
461 // Reset() should be done after that frame number is delivered, or | 623 // Reset() should be done after that frame number is delivered, or |
462 // END_OF_STREAM_RESET to indicate no mid-stream Reset(). | 624 // END_OF_STREAM_RESET to indicate no mid-stream Reset(). |
463 // |delete_decoder_state| indicates when the underlying decoder should be | 625 // |delete_decoder_state| indicates when the underlying decoder should be |
464 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() | 626 // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() |
465 // calls have been made, N>=0 means interpret as ClientState. | 627 // calls have been made, N>=0 means interpret as ClientState. |
466 EglRenderingVDAClient(RenderingHelper* rendering_helper, | 628 EglRenderingVDAClient(RenderingHelperBase* rendering_helper, |
467 int rendering_window_id, | 629 int rendering_window_id, |
468 ClientStateNotification* note, | 630 ClientStateNotification* note, |
469 const std::string& encoded_data, | 631 const std::string& encoded_data, |
470 int num_NALUs_per_decode, | 632 int num_NALUs_per_decode, |
471 int num_in_flight_decodes, | 633 int num_in_flight_decodes, |
472 int reset_after_frame_num, | 634 int reset_after_frame_num, |
473 int delete_decoder_state, | 635 int delete_decoder_state, |
474 int profile); | 636 int profile); |
475 virtual ~EglRenderingVDAClient(); | 637 virtual ~EglRenderingVDAClient(); |
476 void CreateDecoder(); | 638 void CreateDecoder(); |
(...skipping 30 matching lines...) Expand all Loading... | |
507 // Delete the associated OMX decoder helper. | 669 // Delete the associated OMX decoder helper. |
508 void DeleteDecoder(); | 670 void DeleteDecoder(); |
509 | 671 |
510 // Compute & return in |*end_pos| the end position for the next batch of NALUs | 672 // Compute & return in |*end_pos| the end position for the next batch of NALUs |
511 // to ship to the decoder (based on |start_pos| & |num_NALUs_per_decode_|). | 673 // to ship to the decoder (based on |start_pos| & |num_NALUs_per_decode_|). |
512 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); | 674 void GetRangeForNextNALUs(size_t start_pos, size_t* end_pos); |
513 | 675 |
514 // Request decode of the next batch of NALUs in the encoded data. | 676 // Request decode of the next batch of NALUs in the encoded data. |
515 void DecodeNextNALUs(); | 677 void DecodeNextNALUs(); |
516 | 678 |
517 RenderingHelper* rendering_helper_; | 679 RenderingHelperBase* rendering_helper_; |
680 | |
518 int rendering_window_id_; | 681 int rendering_window_id_; |
519 std::string encoded_data_; | 682 std::string encoded_data_; |
520 const int num_NALUs_per_decode_; | 683 const int num_NALUs_per_decode_; |
521 const int num_in_flight_decodes_; | 684 const int num_in_flight_decodes_; |
522 int outstanding_decodes_; | 685 int outstanding_decodes_; |
523 size_t encoded_data_next_pos_to_decode_; | 686 size_t encoded_data_next_pos_to_decode_; |
524 int next_bitstream_buffer_id_; | 687 int next_bitstream_buffer_id_; |
525 ClientStateNotification* note_; | 688 ClientStateNotification* note_; |
689 #if defined(OS_WIN) | |
690 scoped_refptr<DXVAVideoDecodeAccelerator> decoder_; | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
Can this simply store a scoped_refptr<media::Video
ananta
2011/12/17 00:40:25
Done.
| |
691 #else // OS_WIN | |
526 scoped_refptr<OmxVideoDecodeAccelerator> decoder_; | 692 scoped_refptr<OmxVideoDecodeAccelerator> decoder_; |
693 #endif // OS_WIN | |
527 std::set<int> outstanding_texture_ids_; | 694 std::set<int> outstanding_texture_ids_; |
528 int reset_after_frame_num_; | 695 int reset_after_frame_num_; |
529 int delete_decoder_state_; | 696 int delete_decoder_state_; |
530 ClientState state_; | 697 ClientState state_; |
531 int num_decoded_frames_; | 698 int num_decoded_frames_; |
532 int num_done_bitstream_buffers_; | 699 int num_done_bitstream_buffers_; |
533 PictureBufferById picture_buffers_by_id_; | 700 PictureBufferById picture_buffers_by_id_; |
534 base::TimeTicks initialize_done_ticks_; | 701 base::TimeTicks initialize_done_ticks_; |
535 base::TimeTicks last_frame_delivered_ticks_; | 702 base::TimeTicks last_frame_delivered_ticks_; |
536 int profile_; | 703 int profile_; |
537 }; | 704 }; |
538 | 705 |
539 EglRenderingVDAClient::EglRenderingVDAClient( | 706 EglRenderingVDAClient::EglRenderingVDAClient( |
540 RenderingHelper* rendering_helper, | 707 RenderingHelperBase* rendering_helper, |
541 int rendering_window_id, | 708 int rendering_window_id, |
542 ClientStateNotification* note, | 709 ClientStateNotification* note, |
543 const std::string& encoded_data, | 710 const std::string& encoded_data, |
544 int num_NALUs_per_decode, | 711 int num_NALUs_per_decode, |
545 int num_in_flight_decodes, | 712 int num_in_flight_decodes, |
546 int reset_after_frame_num, | 713 int reset_after_frame_num, |
547 int delete_decoder_state, | 714 int delete_decoder_state, |
548 int profile) | 715 int profile) |
549 : rendering_helper_(rendering_helper), | 716 : rendering_helper_(rendering_helper), |
550 rendering_window_id_(rendering_window_id), | 717 rendering_window_id_(rendering_window_id), |
(...skipping 11 matching lines...) Expand all Loading... | |
562 | 729 |
563 EglRenderingVDAClient::~EglRenderingVDAClient() { | 730 EglRenderingVDAClient::~EglRenderingVDAClient() { |
564 DeleteDecoder(); // Clean up in case of expected error. | 731 DeleteDecoder(); // Clean up in case of expected error. |
565 CHECK(decoder_deleted()); | 732 CHECK(decoder_deleted()); |
566 STLDeleteValues(&picture_buffers_by_id_); | 733 STLDeleteValues(&picture_buffers_by_id_); |
567 SetState(CS_DESTROYED); | 734 SetState(CS_DESTROYED); |
568 } | 735 } |
569 | 736 |
570 void EglRenderingVDAClient::CreateDecoder() { | 737 void EglRenderingVDAClient::CreateDecoder() { |
571 CHECK(decoder_deleted()); | 738 CHECK(decoder_deleted()); |
739 #if defined(OS_WIN) | |
740 decoder_ = new DXVAVideoDecodeAccelerator(this, | |
741 base::GetCurrentProcessHandle()); | |
742 #else // OS_WIN | |
572 decoder_ = new OmxVideoDecodeAccelerator(this); | 743 decoder_ = new OmxVideoDecodeAccelerator(this); |
573 decoder_->SetEglState(egl_display(), egl_context()); | 744 decoder_->SetEglState(egl_display(), egl_context()); |
745 #endif // OS_WIN | |
574 SetState(CS_DECODER_SET); | 746 SetState(CS_DECODER_SET); |
575 if (decoder_deleted()) | 747 if (decoder_deleted()) |
576 return; | 748 return; |
577 | 749 |
578 // Configure the decoder. | 750 // Configure the decoder. |
579 media::VideoDecodeAccelerator::Profile profile = media::H264PROFILE_BASELINE; | 751 media::VideoDecodeAccelerator::Profile profile = media::H264PROFILE_BASELINE; |
580 if (profile_ != -1) | 752 if (profile_ != -1) |
581 profile = static_cast<media::VideoDecodeAccelerator::Profile>(profile_); | 753 profile = static_cast<media::VideoDecodeAccelerator::Profile>(profile_); |
582 CHECK(decoder_->Initialize(profile)); | 754 CHECK(decoder_->Initialize(profile)); |
583 } | 755 } |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 return 0; | 950 return 0; |
779 return num_decoded_frames_ / delta.InSecondsF(); | 951 return num_decoded_frames_ / delta.InSecondsF(); |
780 } | 952 } |
781 | 953 |
782 // Test parameters: | 954 // Test parameters: |
783 // - Number of NALUs per Decode() call. | 955 // - Number of NALUs per Decode() call. |
784 // - Number of concurrent decoders. | 956 // - Number of concurrent decoders. |
785 // - Number of concurrent in-flight Decode() calls per decoder. | 957 // - Number of concurrent in-flight Decode() calls per decoder. |
786 // - reset_after_frame_num: see EglRenderingVDAClient ctor. | 958 // - reset_after_frame_num: see EglRenderingVDAClient ctor. |
787 // - delete_decoder_phase: see EglRenderingVDAClient ctor. | 959 // - delete_decoder_phase: see EglRenderingVDAClient ctor. |
788 class OmxVideoDecodeAcceleratorTest | 960 class VideoDecodeAcceleratorTest |
789 : public ::testing::TestWithParam< | 961 : public ::testing::TestWithParam< |
790 Tuple5<int, int, int, ResetPoint, ClientState> > { | 962 Tuple5<int, int, int, ResetPoint, ClientState> > { |
791 }; | 963 }; |
792 | 964 |
793 // Wait for |note| to report a state and if it's not |expected_state| then | 965 // Wait for |note| to report a state and if it's not |expected_state| then |
794 // assert |client| has deleted its decoder. | 966 // assert |client| has deleted its decoder. |
795 static void AssertWaitForStateOrDeleted(ClientStateNotification* note, | 967 static void AssertWaitForStateOrDeleted(ClientStateNotification* note, |
796 EglRenderingVDAClient* client, | 968 EglRenderingVDAClient* client, |
797 ClientState expected_state) { | 969 ClientState expected_state) { |
798 ClientState state = note->Wait(); | 970 ClientState state = note->Wait(); |
799 if (state == expected_state) return; | 971 if (state == expected_state) return; |
800 ASSERT_TRUE(client->decoder_deleted()) | 972 ASSERT_TRUE(client->decoder_deleted()) |
801 << "Decoder not deleted but Wait() returned " << state | 973 << "Decoder not deleted but Wait() returned " << state |
802 << ", instead of " << expected_state; | 974 << ", instead of " << expected_state; |
803 } | 975 } |
804 | 976 |
805 // We assert a minimal number of concurrent decoders we expect to succeed. | 977 // We assert a minimal number of concurrent decoders we expect to succeed. |
806 // Different platforms can support more concurrent decoders, so we don't assert | 978 // Different platforms can support more concurrent decoders, so we don't assert |
807 // failure above this. | 979 // failure above this. |
808 enum { kMinSupportedNumConcurrentDecoders = 3 }; | 980 enum { kMinSupportedNumConcurrentDecoders = 3 }; |
809 | 981 |
810 // Test the most straightforward case possible: data is decoded from a single | 982 // Test the most straightforward case possible: data is decoded from a single |
811 // chunk and rendered to the screen. | 983 // chunk and rendered to the screen. |
812 TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { | 984 TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { |
813 // Can be useful for debugging VLOGs from OVDA. | 985 // Can be useful for debugging VLOGs from OVDA. |
814 // logging::SetMinLogLevel(-1); | 986 // logging::SetMinLogLevel(-1); |
815 | 987 |
816 // Required for Thread to work. Not used otherwise. | 988 // Required for Thread to work. Not used otherwise. |
817 base::ShadowingAtExitManager at_exit_manager; | 989 base::ShadowingAtExitManager at_exit_manager; |
818 | 990 |
819 const int num_NALUs_per_decode = GetParam().a; | 991 const int num_NALUs_per_decode = GetParam().a; |
820 const size_t num_concurrent_decoders = GetParam().b; | 992 const size_t num_concurrent_decoders = GetParam().b; |
821 const size_t num_in_flight_decodes = GetParam().c; | 993 const size_t num_in_flight_decodes = GetParam().c; |
822 const int reset_after_frame_num = GetParam().d; | 994 const int reset_after_frame_num = GetParam().d; |
(...skipping 15 matching lines...) Expand all Loading... | |
838 | 1010 |
839 // Suppress EGL surface swapping in all but a few tests, to cut down overall | 1011 // Suppress EGL surface swapping in all but a few tests, to cut down overall |
840 // test runtime. | 1012 // test runtime. |
841 const bool suppress_swap_to_display = num_NALUs_per_decode > 1; | 1013 const bool suppress_swap_to_display = num_NALUs_per_decode > 1; |
842 | 1014 |
843 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); | 1015 std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); |
844 std::vector<EglRenderingVDAClient*> clients(num_concurrent_decoders, NULL); | 1016 std::vector<EglRenderingVDAClient*> clients(num_concurrent_decoders, NULL); |
845 | 1017 |
846 // Read in the video data. | 1018 // Read in the video data. |
847 std::string data_str; | 1019 std::string data_str; |
848 CHECK(file_util::ReadFileToString(FilePath(test_video_file), &data_str)); | 1020 CHECK(file_util::ReadFileToString(FilePath(UTF8ToWide(test_video_file)), |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
This is win-specific.
Instead use FILE_PATH_LITERA
ananta
2011/12/17 00:40:25
Done.
| |
1021 &data_str)); | |
849 | 1022 |
850 // Initialize the rendering helper. | 1023 // Initialize the rendering helper. |
851 base::Thread rendering_thread("EglRenderingVDAClientThread"); | 1024 base::Thread rendering_thread("EglRenderingVDAClientThread"); |
852 rendering_thread.Start(); | 1025 rendering_thread.Start(); |
853 RenderingHelper rendering_helper; | 1026 #if defined(OS_WIN) |
1027 Win32RenderingHelper rendering_helper; | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
A crazy idea appears: if you named both renderingh
ananta
2011/12/17 00:40:25
Done.
| |
1028 #else // OS_WIN | |
1029 OmxRenderingHelper rendering_helper; | |
1030 #endif // OS_WIN | |
854 | 1031 |
855 base::WaitableEvent done(false, false); | 1032 base::WaitableEvent done(false, false); |
856 rendering_thread.message_loop()->PostTask( | 1033 rendering_thread.message_loop()->PostTask( |
857 FROM_HERE, | 1034 FROM_HERE, |
858 base::Bind(&RenderingHelper::Initialize, | 1035 base::Bind(&RenderingHelperBase::Initialize, |
859 base::Unretained(&rendering_helper), | 1036 base::Unretained(&rendering_helper), |
860 suppress_swap_to_display, num_concurrent_decoders, | 1037 suppress_swap_to_display, num_concurrent_decoders, |
861 frame_width, frame_height, &done)); | 1038 frame_width, frame_height, &done)); |
862 done.Wait(); | 1039 done.Wait(); |
863 | 1040 |
864 // First kick off all the decoders. | 1041 // First kick off all the decoders. |
865 for (size_t index = 0; index < num_concurrent_decoders; ++index) { | 1042 for (size_t index = 0; index < num_concurrent_decoders; ++index) { |
866 ClientStateNotification* note = new ClientStateNotification(); | 1043 ClientStateNotification* note = new ClientStateNotification(); |
867 notes[index] = note; | 1044 notes[index] = note; |
868 EglRenderingVDAClient* client = new EglRenderingVDAClient( | 1045 EglRenderingVDAClient* client = new EglRenderingVDAClient( |
(...skipping 13 matching lines...) Expand all Loading... | |
882 // Then wait for all the decodes to finish. | 1059 // Then wait for all the decodes to finish. |
883 bool saw_init_failure = false; | 1060 bool saw_init_failure = false; |
884 for (size_t i = 0; i < num_concurrent_decoders; ++i) { | 1061 for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
885 ClientStateNotification* note = notes[i]; | 1062 ClientStateNotification* note = notes[i]; |
886 ClientState state = note->Wait(); | 1063 ClientState state = note->Wait(); |
887 if (state != CS_INITIALIZED) { | 1064 if (state != CS_INITIALIZED) { |
888 saw_init_failure = true; | 1065 saw_init_failure = true; |
889 // We expect initialization to fail only when more than the supported | 1066 // We expect initialization to fail only when more than the supported |
890 // number of decoders is instantiated. Assert here that something else | 1067 // number of decoders is instantiated. Assert here that something else |
891 // didn't trigger failure. | 1068 // didn't trigger failure. |
892 ASSERT_GT(num_concurrent_decoders, kMinSupportedNumConcurrentDecoders); | 1069 ASSERT_GT(num_concurrent_decoders, |
1070 static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); | |
893 continue; | 1071 continue; |
894 } | 1072 } |
895 ASSERT_EQ(state, CS_INITIALIZED); | 1073 ASSERT_EQ(state, CS_INITIALIZED); |
896 // InitializeDone kicks off decoding inside the client, so we just need to | 1074 // InitializeDone kicks off decoding inside the client, so we just need to |
897 // wait for Flush. | 1075 // wait for Flush. |
898 ASSERT_NO_FATAL_FAILURE( | 1076 ASSERT_NO_FATAL_FAILURE( |
899 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHING)); | 1077 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHING)); |
900 ASSERT_NO_FATAL_FAILURE( | 1078 ASSERT_NO_FATAL_FAILURE( |
901 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHED)); | 1079 AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHED)); |
902 // FlushDone requests Reset(). | 1080 // FlushDone requests Reset(). |
(...skipping 27 matching lines...) Expand all Loading... | |
930 rendering_thread.message_loop()->PostTask( | 1108 rendering_thread.message_loop()->PostTask( |
931 FROM_HERE, | 1109 FROM_HERE, |
932 base::Bind(&STLDeleteElements<std::vector<EglRenderingVDAClient*> >, | 1110 base::Bind(&STLDeleteElements<std::vector<EglRenderingVDAClient*> >, |
933 &clients)); | 1111 &clients)); |
934 rendering_thread.message_loop()->PostTask( | 1112 rendering_thread.message_loop()->PostTask( |
935 FROM_HERE, | 1113 FROM_HERE, |
936 base::Bind(&STLDeleteElements<std::vector<ClientStateNotification*> >, | 1114 base::Bind(&STLDeleteElements<std::vector<ClientStateNotification*> >, |
937 ¬es)); | 1115 ¬es)); |
938 rendering_thread.message_loop()->PostTask( | 1116 rendering_thread.message_loop()->PostTask( |
939 FROM_HERE, | 1117 FROM_HERE, |
940 base::Bind(&RenderingHelper::UnInitialize, | 1118 base::Bind(&RenderingHelperBase::UnInitialize, |
941 base::Unretained(&rendering_helper), | 1119 base::Unretained(&rendering_helper), |
942 &done)); | 1120 &done)); |
943 done.Wait(); | 1121 done.Wait(); |
944 rendering_thread.Stop(); | 1122 rendering_thread.Stop(); |
945 }; | 1123 }; |
946 | 1124 |
947 // Test that Reset() mid-stream works fine and doesn't affect decoding even when | 1125 // Test that Reset() mid-stream works fine and doesn't affect decoding even when |
948 // Decode() calls are made during the reset. | 1126 // Decode() calls are made during the reset. |
949 INSTANTIATE_TEST_CASE_P( | 1127 INSTANTIATE_TEST_CASE_P( |
950 MidStreamReset, OmxVideoDecodeAcceleratorTest, | 1128 MidStreamReset, VideoDecodeAcceleratorTest, |
951 ::testing::Values( | 1129 ::testing::Values( |
952 MakeTuple(1, 1, 1, static_cast<ResetPoint>(100), CS_RESET))); | 1130 MakeTuple(1, 1, 1, static_cast<ResetPoint>(100), CS_RESET))); |
953 | 1131 |
954 // Test that Destroy() mid-stream works fine (primarily this is testing that no | 1132 // Test that Destroy() mid-stream works fine (primarily this is testing that no |
955 // crashes occur). | 1133 // crashes occur). |
956 INSTANTIATE_TEST_CASE_P( | 1134 INSTANTIATE_TEST_CASE_P( |
957 TearDownTiming, OmxVideoDecodeAcceleratorTest, | 1135 TearDownTiming, VideoDecodeAcceleratorTest, |
958 ::testing::Values( | 1136 ::testing::Values( |
959 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET), | 1137 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET), |
960 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED), | 1138 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED), |
961 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING), | 1139 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING), |
962 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED), | 1140 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED), |
963 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING), | 1141 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING), |
964 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1142 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
965 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, static_cast<ClientState>(-1)), | 1143 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, static_cast<ClientState>(-1)), |
966 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, static_cast<ClientState>(-10)), | 1144 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, static_cast<ClientState>(-10)), |
967 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, | 1145 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, |
968 static_cast<ClientState>(-100)))); | 1146 static_cast<ClientState>(-100)))); |
969 | 1147 |
970 // Test that decoding various variation works: multiple concurrent decoders and | 1148 // Test that decoding various variation works: multiple concurrent decoders and |
971 // multiple NALUs per Decode() call. | 1149 // multiple NALUs per Decode() call. |
972 INSTANTIATE_TEST_CASE_P( | 1150 INSTANTIATE_TEST_CASE_P( |
973 DecodeVariations, OmxVideoDecodeAcceleratorTest, | 1151 DecodeVariations, VideoDecodeAcceleratorTest, |
974 ::testing::Values( | 1152 ::testing::Values( |
975 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1153 MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
976 MakeTuple(1, 1, 10, END_OF_STREAM_RESET, CS_RESET), | 1154 MakeTuple(1, 1, 10, END_OF_STREAM_RESET, CS_RESET), |
977 MakeTuple(1, 1, 15, END_OF_STREAM_RESET, CS_RESET), // Tests queuing. | 1155 MakeTuple(1, 1, 15, END_OF_STREAM_RESET, CS_RESET), // Tests queuing. |
978 MakeTuple(1, 3, 1, END_OF_STREAM_RESET, CS_RESET), | 1156 MakeTuple(1, 3, 1, END_OF_STREAM_RESET, CS_RESET), |
979 MakeTuple(2, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1157 MakeTuple(2, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
980 MakeTuple(3, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1158 MakeTuple(3, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
981 MakeTuple(5, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1159 MakeTuple(5, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
982 MakeTuple(8, 1, 1, END_OF_STREAM_RESET, CS_RESET), | 1160 MakeTuple(8, 1, 1, END_OF_STREAM_RESET, CS_RESET), |
983 // TODO(fischman): decoding more than 15 NALUs at once breaks decode - | 1161 // TODO(fischman): decoding more than 15 NALUs at once breaks decode - |
984 // visual artifacts are introduced as well as spurious frames are | 1162 // visual artifacts are introduced as well as spurious frames are |
985 // delivered (more pictures are returned than NALUs are fed to the | 1163 // delivered (more pictures are returned than NALUs are fed to the |
986 // decoder). Increase the "15" below when | 1164 // decoder). Increase the "15" below when |
987 // http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 is | 1165 // http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 is |
988 // fixed. | 1166 // fixed. |
989 MakeTuple(15, 1, 1, END_OF_STREAM_RESET, CS_RESET))); | 1167 MakeTuple(15, 1, 1, END_OF_STREAM_RESET, CS_RESET))); |
990 | 1168 |
991 // Find out how many concurrent decoders can go before we exhaust system | 1169 // Find out how many concurrent decoders can go before we exhaust system |
992 // resources. | 1170 // resources. |
993 INSTANTIATE_TEST_CASE_P( | 1171 INSTANTIATE_TEST_CASE_P( |
994 ResourceExhaustion, OmxVideoDecodeAcceleratorTest, | 1172 ResourceExhaustion, VideoDecodeAcceleratorTest, |
995 ::testing::Values( | 1173 ::testing::Values( |
996 // +0 hack below to promote enum to int. | 1174 // +0 hack below to promote enum to int. |
997 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, | 1175 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, |
998 END_OF_STREAM_RESET, CS_RESET), | 1176 END_OF_STREAM_RESET, CS_RESET), |
999 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, | 1177 MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, |
1000 END_OF_STREAM_RESET, CS_RESET))); | 1178 END_OF_STREAM_RESET, CS_RESET))); |
1001 | 1179 |
1002 // TODO(fischman, vrk): add more tests! In particular: | 1180 // TODO(fischman, vrk): add more tests! In particular: |
1003 // - Test life-cycle: Seek/Stop/Pause/Play/RePlay for a single decoder. | 1181 // - Test life-cycle: Seek/Stop/Pause/Play/RePlay for a single decoder. |
1004 // - Test alternate configurations | 1182 // - Test alternate configurations |
1005 // - Test failure conditions. | 1183 // - Test failure conditions. |
1006 // - Test frame size changes mid-stream | 1184 // - Test frame size changes mid-stream |
1007 | 1185 |
1008 } // namespace | 1186 } // namespace |
1009 | 1187 |
1010 int main(int argc, char **argv) { | 1188 int main(int argc, char **argv) { |
1011 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. | 1189 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. |
1012 CommandLine cmd_line(argc, argv); // Must run after InitGoogleTest. | 1190 CommandLine::Init(argc, argv); |
1013 CommandLine::SwitchMap switches = cmd_line.GetSwitches(); | 1191 |
1192 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
1193 DCHECK(cmd_line); | |
1194 | |
1195 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | |
1014 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); | 1196 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); |
1015 it != switches.end(); ++it) { | 1197 it != switches.end(); ++it) { |
1016 if (it->first == "test_video_data") { | 1198 if (it->first == "test_video_data") { |
1199 #if defined(OS_WIN) | |
Ami GONE FROM CHROMIUM
2011/12/16 07:38:54
FILE_PATH_LITERAL should let you lose this.
ananta
2011/12/17 00:40:25
Done.
| |
1200 test_video_data = WideToUTF8(it->second); | |
1201 #else // OS_WIN | |
1017 test_video_data = it->second.c_str(); | 1202 test_video_data = it->second.c_str(); |
1203 #endif // OS_WIN | |
1018 continue; | 1204 continue; |
1019 } | 1205 } |
1020 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1206 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
1021 } | 1207 } |
1022 | |
1023 return RUN_ALL_TESTS(); | 1208 return RUN_ALL_TESTS(); |
1024 } | 1209 } |
OLD | NEW |