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

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

Issue 10388108: Implement media::VideoDecodeAccelerator on Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix cros build Created 8 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « content/common/gpu/media/rendering_helper_mac.mm ('k') | content/content_common.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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
(...skipping 20 matching lines...) Expand all
31 #include "base/process_util.h" 31 #include "base/process_util.h"
32 #include "base/stl_util.h" 32 #include "base/stl_util.h"
33 #include "base/string_number_conversions.h" 33 #include "base/string_number_conversions.h"
34 #include "base/string_split.h" 34 #include "base/string_split.h"
35 #include "base/stringize_macros.h" 35 #include "base/stringize_macros.h"
36 #include "base/synchronization/condition_variable.h" 36 #include "base/synchronization/condition_variable.h"
37 #include "base/synchronization/lock.h" 37 #include "base/synchronization/lock.h"
38 #include "base/synchronization/waitable_event.h" 38 #include "base/synchronization/waitable_event.h"
39 #include "base/threading/thread.h" 39 #include "base/threading/thread.h"
40 #include "base/utf_string_conversions.h" 40 #include "base/utf_string_conversions.h"
41 41 #include "content/common/gpu/media/rendering_helper.h"
42 #if (!defined(OS_CHROMEOS) || !defined(ARCH_CPU_ARMEL)) && !defined(OS_WIN)
43 #error The VideoAccelerator tests are only supported on cros/ARM/Windows.
44 #endif
45 42
46 #if defined(OS_WIN) 43 #if defined(OS_WIN)
47 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" 44 #include "content/common/gpu/media/dxva_video_decode_accelerator.h"
48 #else // OS_WIN 45 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
49 #include "content/common/gpu/media/omx_video_decode_accelerator.h" 46 #include "content/common/gpu/media/omx_video_decode_accelerator.h"
47 #elif defined(OS_MACOSX)
48 #include "content/common/gpu/media/mac_video_decode_accelerator.h"
49 #else
50 #error The VideoAccelerator tests are not supported on this platform.
50 #endif // defined(OS_WIN) 51 #endif // defined(OS_WIN)
51 52
52 #include "third_party/angle/include/EGL/egl.h"
53
54 #if defined(OS_WIN)
55 #include "ui/gl/gl_bindings.h"
56 #include "ui/gl/gl_context.h"
57 #include "ui/gl/gl_implementation.h"
58 #include "ui/gl/gl_surface.h"
59 #else // OS_WIN
60 #include "third_party/angle/include/GLES2/gl2.h"
61 #endif // OS_WIN
62
63 using media::VideoDecodeAccelerator; 53 using media::VideoDecodeAccelerator;
54 using video_test_util::RenderingHelper;
64 55
65 namespace { 56 namespace {
66 57
67 // Values optionally filled in from flags; see main() below. 58 // Values optionally filled in from flags; see main() below.
68 // The syntax of this variable is: 59 // The syntax of this variable is:
69 // filename:width:height:numframes:numNALUs:minFPSwithRender:minFPSnoRender 60 // filename:width:height:numframes:numNALUs:minFPSwithRender:minFPSnoRender
70 // where only the first field is required. Value details: 61 // where only the first field is required. Value details:
71 // - |filename| must be an h264 Annex B (NAL) stream. 62 // - |filename| must be an h264 Annex B (NAL) stream.
72 // - |width| and |height| are in pixels. 63 // - |width| and |height| are in pixels.
73 // - |numframes| is the number of picture frames in the file. 64 // - |numframes| is the number of picture frames in the file.
74 // - |numNALUs| is the number of NAL units in the stream. 65 // - |numNALUs| is the number of NAL units in the stream.
75 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds 66 // - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds
76 // expected to be achieved with and without rendering to the screen, resp. 67 // expected to be achieved with and without rendering to the screen, resp.
77 // (the latter tests just decode speed). 68 // (the latter tests just decode speed).
78 // - |profile| is the media::H264Profile set during Initialization. 69 // - |profile| is the media::H264Profile set during Initialization.
79 // An empty value for a numeric field means "ignore". 70 // An empty value for a numeric field means "ignore".
71 #if defined(OS_MACOSX)
72 const FilePath::CharType* test_video_data =
73 FILE_PATH_LITERAL("test-25fps_high.h264:1280:720:249:252:50:175:4");
74 #else
80 const FilePath::CharType* test_video_data = 75 const FilePath::CharType* test_video_data =
81 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); 76 FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1");
77 #endif
78
79 // AAVC data required to initialize the H.264 video decoder.
80 // TODO(sail): Remove this and build the AVC configuration record instead.
81 const uint8 MP4_EXTRA_DATA[] = {
82 0x01, 0x64, 0x00, 0x1f, 0xff, 0xe1, 0x00, 0x19,
83 0x67, 0x64, 0x00, 0x1f, 0xac, 0x34, 0xec, 0x05,
84 0x00, 0x5b, 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01,
85 0x00, 0x00, 0x03, 0x00, 0x32, 0x0f, 0x18, 0x31,
86 0x38, 0x01, 0x00, 0x05, 0x68, 0xef, 0xb2, 0xc8,
87 0xb0,
88 };
82 89
83 // Parse |data| into its constituent parts and set the various output fields 90 // Parse |data| into its constituent parts and set the various output fields
84 // accordingly. CHECK-fails on unexpected or missing required data. 91 // accordingly. CHECK-fails on unexpected or missing required data.
85 // Unspecified optional fields are set to -1. 92 // Unspecified optional fields are set to -1.
86 void ParseTestVideoData(FilePath::StringType data, 93 void ParseTestVideoData(FilePath::StringType data,
87 FilePath::StringType* file_name, 94 FilePath::StringType* file_name,
88 int* width, int* height, 95 int* width, int* height,
89 int* num_frames, 96 int* num_frames,
90 int* num_NALUs, 97 int* num_NALUs,
91 int* min_fps_render, 98 int* min_fps_render,
(...skipping 16 matching lines...) Expand all
108 if (!elements[4].empty()) 115 if (!elements[4].empty())
109 CHECK(base::StringToInt(elements[4], num_NALUs)); 116 CHECK(base::StringToInt(elements[4], num_NALUs));
110 if (!elements[5].empty()) 117 if (!elements[5].empty())
111 CHECK(base::StringToInt(elements[5], min_fps_render)); 118 CHECK(base::StringToInt(elements[5], min_fps_render));
112 if (!elements[6].empty()) 119 if (!elements[6].empty())
113 CHECK(base::StringToInt(elements[6], min_fps_no_render)); 120 CHECK(base::StringToInt(elements[6], min_fps_no_render));
114 if (!elements[7].empty()) 121 if (!elements[7].empty())
115 CHECK(base::StringToInt(elements[7], profile)); 122 CHECK(base::StringToInt(elements[7], profile));
116 } 123 }
117 124
118 // Provides functionality for managing EGL, GLES2 and UI resources.
119 // This class is not thread safe and thus all the methods of this class
120 // (except for ctor/dtor) ensure they're being run on a single thread.
121 class RenderingHelper {
122 public:
123 RenderingHelper();
124 ~RenderingHelper();
125
126 // Initialize all structures to prepare to render to one or more windows of
127 // the specified dimensions. CHECK-fails if any initialization step fails.
128 // After this returns, texture creation and rendering can be requested. This
129 // method can be called multiple times, in which case all previously-acquired
130 // resources and initializations are discarded. If |suppress_swap_to_display|
131 // then all the usual work is done, except for the final swap of the EGL
132 // surface to the display. This cuts test times over 50% so is worth doing
133 // when testing non-rendering-related aspects.
134 void Initialize(bool suppress_swap_to_display, int num_windows, int width,
135 int height, base::WaitableEvent* done);
136
137 // Undo the effects of Initialize() and signal |*done|.
138 void UnInitialize(base::WaitableEvent* done);
139
140 // Return a newly-created GLES2 texture id rendering to a specific window, and
141 // signal |*done|.
142 void CreateTexture(int window_id, GLuint* texture_id,
143 base::WaitableEvent* done);
144
145 // Render |texture_id| to the screen (unless |suppress_swap_to_display_|).
146 void RenderTexture(GLuint texture_id);
147
148 // Delete |texture_id|.
149 void DeleteTexture(GLuint texture_id);
150
151 // Platform specific Init/Uninit.
152 void PlatformInitialize();
153 void PlatformUnInitialize();
154
155 // Platform specific window creation.
156 EGLNativeWindowType PlatformCreateWindow(int top_left_x, int top_left_y);
157
158 // Platform specific display surface returned here.
159 EGLDisplay PlatformGetDisplay();
160
161 EGLDisplay egl_display() { return egl_display_; }
162
163 EGLContext egl_context() { return egl_context_; }
164
165 MessageLoop* message_loop() { return message_loop_; }
166
167 protected:
168 void Clear();
169
170 // We ensure all operations are carried out on the same thread by remembering
171 // where we were Initialized.
172 MessageLoop* message_loop_;
173 int width_;
174 int height_;
175 bool suppress_swap_to_display_;
176
177 EGLDisplay egl_display_;
178 EGLContext egl_context_;
179 std::vector<EGLSurface> egl_surfaces_;
180 std::map<GLuint, int> texture_id_to_surface_index_;
181
182 #if defined(OS_WIN)
183 std::vector<HWND> windows_;
184 #else // OS_WIN
185 Display* x_display_;
186 std::vector<Window> x_windows_;
187 #endif // OS_WIN
188 };
189
190 RenderingHelper::RenderingHelper() {
191 Clear();
192 }
193
194 RenderingHelper::~RenderingHelper() {
195 CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor.";
196 Clear();
197 }
198
199 // Helper for Shader creation.
200 static void CreateShader(
201 GLuint program, GLenum type, const char* source, int size) {
202 GLuint shader = glCreateShader(type);
203 glShaderSource(shader, 1, &source, &size);
204 glCompileShader(shader);
205 int result = GL_FALSE;
206 glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
207 if (!result) {
208 char log[4096];
209 glGetShaderInfoLog(shader, arraysize(log), NULL, log);
210 LOG(FATAL) << log;
211 }
212 glAttachShader(program, shader);
213 glDeleteShader(shader);
214 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
215 }
216
217 void RenderingHelper::Initialize(
218 bool suppress_swap_to_display,
219 int num_windows,
220 int width,
221 int height,
222 base::WaitableEvent* done) {
223 // Use width_ != 0 as a proxy for the class having already been
224 // Initialize()'d, and UnInitialize() before continuing.
225 if (width_) {
226 base::WaitableEvent done(false, false);
227 UnInitialize(&done);
228 done.Wait();
229 }
230
231 suppress_swap_to_display_ = suppress_swap_to_display;
232 CHECK_GT(width, 0);
233 CHECK_GT(height, 0);
234 width_ = width;
235 height_ = height;
236 message_loop_ = MessageLoop::current();
237 CHECK_GT(num_windows, 0);
238
239 PlatformInitialize();
240
241 egl_display_ = PlatformGetDisplay();
242
243 EGLint major;
244 EGLint minor;
245 CHECK(eglInitialize(egl_display_, &major, &minor)) << eglGetError();
246 static EGLint rgba8888[] = {
247 EGL_RED_SIZE, 8,
248 EGL_GREEN_SIZE, 8,
249 EGL_BLUE_SIZE, 8,
250 EGL_ALPHA_SIZE, 8,
251 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
252 EGL_NONE,
253 };
254 EGLConfig egl_config;
255 int num_configs;
256 CHECK(eglChooseConfig(egl_display_, rgba8888, &egl_config, 1, &num_configs))
257 << eglGetError();
258 CHECK_GE(num_configs, 1);
259 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
260 egl_context_ = eglCreateContext(
261 egl_display_, egl_config, EGL_NO_CONTEXT, context_attribs);
262 CHECK_NE(egl_context_, EGL_NO_CONTEXT) << eglGetError();
263
264 // Per-window/surface X11 & EGL initialization.
265 for (int i = 0; i < num_windows; ++i) {
266 // Arrange X windows whimsically, with some padding.
267 int top_left_x = (width + 20) * (i % 4);
268 int top_left_y = (height + 12) * (i % 3);
269
270 EGLNativeWindowType window = PlatformCreateWindow(top_left_x, top_left_y);
271 EGLSurface egl_surface =
272 eglCreateWindowSurface(egl_display_, egl_config, window, NULL);
273 egl_surfaces_.push_back(egl_surface);
274 CHECK_NE(egl_surface, EGL_NO_SURFACE);
275 }
276 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[0],
277 egl_surfaces_[0], egl_context_)) << eglGetError();
278
279 static const float kVertices[] =
280 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, };
281 static const float kTextureCoordsEgl[] = { 0, 1, 0, 0, 1, 1, 1, 0, };
282 static const char kVertexShader[] = STRINGIZE(
283 varying vec2 interp_tc;
284 attribute vec4 in_pos;
285 attribute vec2 in_tc;
286 void main() {
287 interp_tc = in_tc;
288 gl_Position = in_pos;
289 }
290 );
291 static const char kFragmentShaderEgl[] = STRINGIZE(
292 precision mediump float;
293 varying vec2 interp_tc;
294 uniform sampler2D tex;
295 void main() {
296 gl_FragColor = texture2D(tex, interp_tc);
297 }
298 );
299 GLuint program = glCreateProgram();
300 CreateShader(program, GL_VERTEX_SHADER,
301 kVertexShader, arraysize(kVertexShader));
302 CreateShader(program, GL_FRAGMENT_SHADER,
303 kFragmentShaderEgl, arraysize(kFragmentShaderEgl));
304 glLinkProgram(program);
305 int result = GL_FALSE;
306 glGetProgramiv(program, GL_LINK_STATUS, &result);
307 if (!result) {
308 char log[4096];
309 glGetShaderInfoLog(program, arraysize(log), NULL, log);
310 LOG(FATAL) << log;
311 }
312 glUseProgram(program);
313 glDeleteProgram(program);
314
315 glUniform1i(glGetUniformLocation(program, "tex"), 0);
316 int pos_location = glGetAttribLocation(program, "in_pos");
317 glEnableVertexAttribArray(pos_location);
318 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices);
319 int tc_location = glGetAttribLocation(program, "in_tc");
320 glEnableVertexAttribArray(tc_location);
321 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0,
322 kTextureCoordsEgl);
323 done->Signal();
324 }
325
326 void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
327 CHECK_EQ(MessageLoop::current(), message_loop_);
328 CHECK(eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
329 EGL_NO_CONTEXT)) << eglGetError();
330 CHECK(eglDestroyContext(egl_display_, egl_context_));
331 for (size_t i = 0; i < egl_surfaces_.size(); ++i)
332 CHECK(eglDestroySurface(egl_display_, egl_surfaces_[i]));
333 CHECK(eglTerminate(egl_display_));
334 Clear();
335 done->Signal();
336 }
337
338 void RenderingHelper::Clear() {
339 suppress_swap_to_display_ = false;
340 width_ = 0;
341 height_ = 0;
342 texture_id_to_surface_index_.clear();
343 message_loop_ = NULL;
344 egl_display_ = EGL_NO_DISPLAY;
345 egl_context_ = EGL_NO_CONTEXT;
346 egl_surfaces_.clear();
347 PlatformUnInitialize();
348 }
349
350 void RenderingHelper::CreateTexture(int window_id, GLuint* texture_id,
351 base::WaitableEvent* done) {
352 if (MessageLoop::current() != message_loop_) {
353 message_loop_->PostTask(
354 FROM_HERE,
355 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this),
356 window_id, texture_id, done));
357 return;
358 }
359 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id],
360 egl_surfaces_[window_id], egl_context_))
361 << eglGetError();
362 glGenTextures(1, texture_id);
363 glBindTexture(GL_TEXTURE_2D, *texture_id);
364 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
365 GL_UNSIGNED_BYTE, NULL);
366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
368 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures.
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
371 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
372 CHECK(texture_id_to_surface_index_.insert(
373 std::make_pair(*texture_id, window_id)).second);
374 done->Signal();
375 }
376
377 void RenderingHelper::RenderTexture(GLuint texture_id) {
378 CHECK_EQ(MessageLoop::current(), message_loop_);
379 glActiveTexture(GL_TEXTURE0);
380 glBindTexture(GL_TEXTURE_2D, texture_id);
381 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
382 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
383 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
384 if (!suppress_swap_to_display_) {
385 int window_id = texture_id_to_surface_index_[texture_id];
386 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id],
387 egl_surfaces_[window_id], egl_context_))
388 << eglGetError();
389 eglSwapBuffers(egl_display_, egl_surfaces_[window_id]);
390 }
391 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
392 }
393
394 void RenderingHelper::DeleteTexture(GLuint texture_id) {
395 glDeleteTextures(1, &texture_id);
396 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
397 }
398
399 #if defined(OS_WIN)
400 void RenderingHelper::PlatformInitialize() {}
401
402 void RenderingHelper::PlatformUnInitialize() {
403 for (size_t i = 0; i < windows_.size(); ++i) {
404 DestroyWindow(windows_[i]);
405 }
406 windows_.clear();
407 }
408
409 EGLNativeWindowType RenderingHelper::PlatformCreateWindow(
410 int top_left_x, int top_left_y) {
411 HWND window = CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest",
412 WS_OVERLAPPEDWINDOW | WS_VISIBLE, top_left_x,
413 top_left_y, width_, height_, NULL, NULL, NULL,
414 NULL);
415 CHECK(window != NULL);
416 windows_.push_back(window);
417 return window;
418 }
419
420 EGLDisplay RenderingHelper::PlatformGetDisplay() {
421 return eglGetDisplay(EGL_DEFAULT_DISPLAY);
422 }
423
424 #else // OS_WIN
425
426 void RenderingHelper::PlatformInitialize() {
427 CHECK(x_display_ = base::MessagePumpForUI::GetDefaultXDisplay());
428 }
429
430 void RenderingHelper::PlatformUnInitialize() {
431 // Destroy resources acquired in Initialize, in reverse-acquisition order.
432 for (size_t i = 0; i < x_windows_.size(); ++i) {
433 CHECK(XUnmapWindow(x_display_, x_windows_[i]));
434 CHECK(XDestroyWindow(x_display_, x_windows_[i]));
435 }
436 // Mimic newly created object.
437 x_display_ = NULL;
438 x_windows_.clear();
439 }
440
441 EGLDisplay RenderingHelper::PlatformGetDisplay() {
442 return eglGetDisplay(x_display_);
443 }
444
445 EGLNativeWindowType RenderingHelper::PlatformCreateWindow(int top_left_x,
446 int top_left_y) {
447 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_));
448
449 XSetWindowAttributes window_attributes;
450 window_attributes.background_pixel =
451 BlackPixel(x_display_, DefaultScreen(x_display_));
452 window_attributes.override_redirect = true;
453
454 Window x_window = XCreateWindow(
455 x_display_, DefaultRootWindow(x_display_),
456 top_left_x, top_left_y, width_, height_,
457 0 /* border width */,
458 depth, CopyFromParent /* class */, CopyFromParent /* visual */,
459 (CWBackPixel | CWOverrideRedirect), &window_attributes);
460 x_windows_.push_back(x_window);
461 XStoreName(x_display_, x_window, "VideoDecodeAcceleratorTest");
462 XSelectInput(x_display_, x_window, ExposureMask);
463 XMapWindow(x_display_, x_window);
464 return x_window;
465 }
466
467 #endif // OS_WIN
468
469 // State of the EglRenderingVDAClient below. Order matters here as the test 125 // State of the EglRenderingVDAClient below. Order matters here as the test
470 // makes assumptions about it. 126 // makes assumptions about it.
471 enum ClientState { 127 enum ClientState {
472 CS_CREATED, 128 CS_CREATED,
473 CS_DECODER_SET, 129 CS_DECODER_SET,
474 CS_INITIALIZED, 130 CS_INITIALIZED,
475 CS_FLUSHING, 131 CS_FLUSHING,
476 CS_FLUSHED, 132 CS_FLUSHED,
477 CS_DONE, 133 CS_DONE,
478 CS_RESETTING, 134 CS_RESETTING,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 // last play-through (governed by |num_play_throughs|). 200 // last play-through (governed by |num_play_throughs|).
545 EglRenderingVDAClient(RenderingHelper* rendering_helper, 201 EglRenderingVDAClient(RenderingHelper* rendering_helper,
546 int rendering_window_id, 202 int rendering_window_id,
547 ClientStateNotification* note, 203 ClientStateNotification* note,
548 const std::string& encoded_data, 204 const std::string& encoded_data,
549 int num_NALUs_per_decode, 205 int num_NALUs_per_decode,
550 int num_in_flight_decodes, 206 int num_in_flight_decodes,
551 int num_play_throughs, 207 int num_play_throughs,
552 int reset_after_frame_num, 208 int reset_after_frame_num,
553 int delete_decoder_state, 209 int delete_decoder_state,
210 int frame_width,
211 int frame_height,
554 int profile); 212 int profile);
555 virtual ~EglRenderingVDAClient(); 213 virtual ~EglRenderingVDAClient();
556 void CreateDecoder(); 214 void CreateDecoder();
557 215
558 // VideoDecodeAccelerator::Client implementation. 216 // VideoDecodeAccelerator::Client implementation.
559 // The heart of the Client. 217 // The heart of the Client.
560 virtual void ProvidePictureBuffers( 218 virtual void ProvidePictureBuffers(
561 uint32 requested_num_of_buffers, 219 uint32 requested_num_of_buffers,
562 const gfx::Size& dimensions); 220 const gfx::Size& dimensions);
563 virtual void DismissPictureBuffer(int32 picture_buffer_id); 221 virtual void DismissPictureBuffer(int32 picture_buffer_id);
564 virtual void PictureReady(const media::Picture& picture); 222 virtual void PictureReady(const media::Picture& picture);
565 // Simple state changes. 223 // Simple state changes.
566 virtual void NotifyInitializeDone(); 224 virtual void NotifyInitializeDone();
567 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id); 225 virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id);
568 virtual void NotifyFlushDone(); 226 virtual void NotifyFlushDone();
569 virtual void NotifyResetDone(); 227 virtual void NotifyResetDone();
570 virtual void NotifyError(VideoDecodeAccelerator::Error error); 228 virtual void NotifyError(VideoDecodeAccelerator::Error error);
571 229
572 // Simple getters for inspecting the state of the Client. 230 // Simple getters for inspecting the state of the Client.
573 ClientState state() { return state_; } 231 ClientState state() { return state_; }
574 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } 232 int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; }
575 int num_decoded_frames() { return num_decoded_frames_; } 233 int num_decoded_frames() { return num_decoded_frames_; }
576 EGLDisplay egl_display() { return rendering_helper_->egl_display(); }
577 EGLContext egl_context() { return rendering_helper_->egl_context(); }
578 double frames_per_second(); 234 double frames_per_second();
579 bool decoder_deleted() { return !decoder_; } 235 bool decoder_deleted() { return !decoder_; }
580 236
581 private: 237 private:
582 typedef std::map<int, media::PictureBuffer*> PictureBufferById; 238 typedef std::map<int, media::PictureBuffer*> PictureBufferById;
583 239
584 void SetState(ClientState new_state); 240 void SetState(ClientState new_state);
585 241
586 // Delete the associated OMX decoder helper. 242 // Delete the associated OMX decoder helper.
587 void DeleteDecoder(); 243 void DeleteDecoder();
(...skipping 18 matching lines...) Expand all
606 std::set<int> outstanding_texture_ids_; 262 std::set<int> outstanding_texture_ids_;
607 int remaining_play_throughs_; 263 int remaining_play_throughs_;
608 int reset_after_frame_num_; 264 int reset_after_frame_num_;
609 int delete_decoder_state_; 265 int delete_decoder_state_;
610 ClientState state_; 266 ClientState state_;
611 int num_decoded_frames_; 267 int num_decoded_frames_;
612 int num_done_bitstream_buffers_; 268 int num_done_bitstream_buffers_;
613 PictureBufferById picture_buffers_by_id_; 269 PictureBufferById picture_buffers_by_id_;
614 base::TimeTicks initialize_done_ticks_; 270 base::TimeTicks initialize_done_ticks_;
615 base::TimeTicks last_frame_delivered_ticks_; 271 base::TimeTicks last_frame_delivered_ticks_;
272 int frame_width_;
273 int frame_height_;
616 int profile_; 274 int profile_;
617 }; 275 };
618 276
619 EglRenderingVDAClient::EglRenderingVDAClient( 277 EglRenderingVDAClient::EglRenderingVDAClient(
620 RenderingHelper* rendering_helper, 278 RenderingHelper* rendering_helper,
621 int rendering_window_id, 279 int rendering_window_id,
622 ClientStateNotification* note, 280 ClientStateNotification* note,
623 const std::string& encoded_data, 281 const std::string& encoded_data,
624 int num_NALUs_per_decode, 282 int num_NALUs_per_decode,
625 int num_in_flight_decodes, 283 int num_in_flight_decodes,
626 int num_play_throughs, 284 int num_play_throughs,
627 int reset_after_frame_num, 285 int reset_after_frame_num,
628 int delete_decoder_state, 286 int delete_decoder_state,
287 int frame_width,
288 int frame_height,
629 int profile) 289 int profile)
630 : rendering_helper_(rendering_helper), 290 : rendering_helper_(rendering_helper),
631 rendering_window_id_(rendering_window_id), 291 rendering_window_id_(rendering_window_id),
632 encoded_data_(encoded_data), num_NALUs_per_decode_(num_NALUs_per_decode), 292 encoded_data_(encoded_data), num_NALUs_per_decode_(num_NALUs_per_decode),
633 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), 293 num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0),
634 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), 294 encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0),
635 note_(note), 295 note_(note),
636 remaining_play_throughs_(num_play_throughs), 296 remaining_play_throughs_(num_play_throughs),
637 reset_after_frame_num_(reset_after_frame_num), 297 reset_after_frame_num_(reset_after_frame_num),
638 delete_decoder_state_(delete_decoder_state), 298 delete_decoder_state_(delete_decoder_state),
639 state_(CS_CREATED), 299 state_(CS_CREATED),
640 num_decoded_frames_(0), num_done_bitstream_buffers_(0), 300 num_decoded_frames_(0), num_done_bitstream_buffers_(0),
301 frame_width_(frame_width),
302 frame_height_(frame_height),
641 profile_(profile) { 303 profile_(profile) {
642 CHECK_GT(num_NALUs_per_decode, 0); 304 CHECK_GT(num_NALUs_per_decode, 0);
643 CHECK_GT(num_in_flight_decodes, 0); 305 CHECK_GT(num_in_flight_decodes, 0);
644 CHECK_GT(num_play_throughs, 0); 306 CHECK_GT(num_play_throughs, 0);
645 } 307 }
646 308
647 EglRenderingVDAClient::~EglRenderingVDAClient() { 309 EglRenderingVDAClient::~EglRenderingVDAClient() {
648 DeleteDecoder(); // Clean up in case of expected error. 310 DeleteDecoder(); // Clean up in case of expected error.
649 CHECK(decoder_deleted()); 311 CHECK(decoder_deleted());
650 STLDeleteValues(&picture_buffers_by_id_); 312 STLDeleteValues(&picture_buffers_by_id_);
651 SetState(CS_DESTROYED); 313 SetState(CS_DESTROYED);
652 } 314 }
653 315
654 void EglRenderingVDAClient::CreateDecoder() { 316 void EglRenderingVDAClient::CreateDecoder() {
655 CHECK(decoder_deleted()); 317 CHECK(decoder_deleted());
656 #if defined(OS_WIN) 318 #if defined(OS_WIN)
657 scoped_refptr<DXVAVideoDecodeAccelerator> decoder = 319 scoped_refptr<DXVAVideoDecodeAccelerator> decoder =
658 new DXVAVideoDecodeAccelerator(this); 320 new DXVAVideoDecodeAccelerator(this);
659 #else // OS_WIN 321 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
660 scoped_refptr<OmxVideoDecodeAccelerator> decoder = 322 scoped_refptr<OmxVideoDecodeAccelerator> decoder =
661 new OmxVideoDecodeAccelerator(this); 323 new OmxVideoDecodeAccelerator(this);
662 decoder->SetEglState(egl_display(), egl_context()); 324 decoder->SetEglState(
325 static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
326 static_cast<EGLContext>(rendering_helper_->GetGLContext()));
327 #elif defined(OS_MACOSX)
328 scoped_refptr<MacVideoDecodeAccelerator> decoder =
329 new MacVideoDecodeAccelerator(this);
330 decoder->SetCGLContext(
331 static_cast<CGLContextObj>(rendering_helper_->GetGLContext()));
332 std::vector<uint8> avc_data(MP4_EXTRA_DATA,
333 MP4_EXTRA_DATA + arraysize(MP4_EXTRA_DATA));
334 if (!decoder->SetConfigInfo(frame_width_, frame_height_, avc_data)) {
335 SetState(CS_ERROR);
336 return;
337 }
663 #endif // OS_WIN 338 #endif // OS_WIN
664 decoder_ = decoder.release(); 339 decoder_ = decoder.release();
665 SetState(CS_DECODER_SET); 340 SetState(CS_DECODER_SET);
666 if (decoder_deleted()) 341 if (decoder_deleted())
667 return; 342 return;
668 343
669 // Configure the decoder. 344 // Configure the decoder.
670 media::VideoCodecProfile profile = media::H264PROFILE_BASELINE; 345 media::VideoCodecProfile profile = media::H264PROFILE_BASELINE;
671 if (profile_ != -1) 346 if (profile_ != -1)
672 profile = static_cast<media::VideoCodecProfile>(profile_); 347 profile = static_cast<media::VideoCodecProfile>(profile_);
673 CHECK(decoder_->Initialize(profile)); 348 CHECK(decoder_->Initialize(profile));
674 } 349 }
675 350
676 void EglRenderingVDAClient::ProvidePictureBuffers( 351 void EglRenderingVDAClient::ProvidePictureBuffers(
677 uint32 requested_num_of_buffers, 352 uint32 requested_num_of_buffers,
678 const gfx::Size& dimensions) { 353 const gfx::Size& dimensions) {
679 if (decoder_deleted()) 354 if (decoder_deleted())
680 return; 355 return;
681 std::vector<media::PictureBuffer> buffers; 356 std::vector<media::PictureBuffer> buffers;
682 357
683 for (uint32 i = 0; i < requested_num_of_buffers; ++i) { 358 for (uint32 i = 0; i < requested_num_of_buffers; ++i) {
684 uint32 id = picture_buffers_by_id_.size(); 359 uint32 id = picture_buffers_by_id_.size();
685 GLuint texture_id; 360 uint32 texture_id;
686 base::WaitableEvent done(false, false); 361 base::WaitableEvent done(false, false);
687 rendering_helper_->CreateTexture(rendering_window_id_, &texture_id, &done); 362 rendering_helper_->CreateTexture(rendering_window_id_, &texture_id, &done);
688 done.Wait(); 363 done.Wait();
689 CHECK(outstanding_texture_ids_.insert(texture_id).second); 364 CHECK(outstanding_texture_ids_.insert(texture_id).second);
690 media::PictureBuffer* buffer = 365 media::PictureBuffer* buffer =
691 new media::PictureBuffer(id, dimensions, texture_id); 366 new media::PictureBuffer(id, dimensions, texture_id);
692 CHECK(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); 367 CHECK(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second);
693 buffers.push_back(*buffer); 368 buffers.push_back(*buffer);
694 } 369 }
695 decoder_->AssignPictureBuffers(buffers); 370 decoder_->AssignPictureBuffers(buffers);
696 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
697 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
698 } 371 }
699 372
700 void EglRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) { 373 void EglRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) {
701 PictureBufferById::iterator it = 374 PictureBufferById::iterator it =
702 picture_buffers_by_id_.find(picture_buffer_id); 375 picture_buffers_by_id_.find(picture_buffer_id);
703 CHECK(it != picture_buffers_by_id_.end()); 376 CHECK(it != picture_buffers_by_id_.end());
704 CHECK_EQ(outstanding_texture_ids_.erase(it->second->texture_id()), 1U); 377 CHECK_EQ(outstanding_texture_ids_.erase(it->second->texture_id()), 1U);
705 rendering_helper_->DeleteTexture(it->second->texture_id()); 378 rendering_helper_->DeleteTexture(it->second->texture_id());
706 delete it->second; 379 delete it->second;
707 picture_buffers_by_id_.erase(it); 380 picture_buffers_by_id_.erase(it);
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 base::Thread rendering_thread("EglRenderingVDAClientThread"); 629 base::Thread rendering_thread("EglRenderingVDAClientThread");
957 base::Thread::Options options; 630 base::Thread::Options options;
958 options.message_loop_type = MessageLoop::TYPE_DEFAULT; 631 options.message_loop_type = MessageLoop::TYPE_DEFAULT;
959 #if defined(OS_WIN) 632 #if defined(OS_WIN)
960 // For windows the decoding thread initializes the media foundation decoder 633 // For windows the decoding thread initializes the media foundation decoder
961 // which uses COM. We need the thread to be a UI thread. 634 // which uses COM. We need the thread to be a UI thread.
962 options.message_loop_type = MessageLoop::TYPE_UI; 635 options.message_loop_type = MessageLoop::TYPE_UI;
963 #endif // OS_WIN 636 #endif // OS_WIN
964 637
965 rendering_thread.StartWithOptions(options); 638 rendering_thread.StartWithOptions(options);
966 RenderingHelper rendering_helper; 639 scoped_ptr<RenderingHelper> rendering_helper(RenderingHelper::Create());
967 640
968 base::WaitableEvent done(false, false); 641 base::WaitableEvent done(false, false);
969 rendering_thread.message_loop()->PostTask( 642 rendering_thread.message_loop()->PostTask(
970 FROM_HERE, 643 FROM_HERE,
971 base::Bind(&RenderingHelper::Initialize, 644 base::Bind(&RenderingHelper::Initialize,
972 base::Unretained(&rendering_helper), 645 base::Unretained(rendering_helper.get()),
973 suppress_swap_to_display, num_concurrent_decoders, 646 suppress_swap_to_display, num_concurrent_decoders,
974 frame_width, frame_height, &done)); 647 frame_width, frame_height, &done));
975 done.Wait(); 648 done.Wait();
976 649
977 // First kick off all the decoders. 650 // First kick off all the decoders.
978 for (size_t index = 0; index < num_concurrent_decoders; ++index) { 651 for (size_t index = 0; index < num_concurrent_decoders; ++index) {
979 ClientStateNotification* note = new ClientStateNotification(); 652 ClientStateNotification* note = new ClientStateNotification();
980 notes[index] = note; 653 notes[index] = note;
981 EglRenderingVDAClient* client = new EglRenderingVDAClient( 654 EglRenderingVDAClient* client = new EglRenderingVDAClient(
982 &rendering_helper, index, 655 rendering_helper.get(), index, note, data_str, num_NALUs_per_decode,
983 note, data_str, num_NALUs_per_decode, 656 num_in_flight_decodes, num_play_throughs, reset_after_frame_num,
984 num_in_flight_decodes, num_play_throughs, 657 delete_decoder_state, frame_width, frame_height, profile);
985 reset_after_frame_num, delete_decoder_state, profile);
986 clients[index] = client; 658 clients[index] = client;
987 659
988 rendering_thread.message_loop()->PostTask( 660 rendering_thread.message_loop()->PostTask(
989 FROM_HERE, 661 FROM_HERE,
990 base::Bind(&EglRenderingVDAClient::CreateDecoder, 662 base::Bind(&EglRenderingVDAClient::CreateDecoder,
991 base::Unretained(client))); 663 base::Unretained(client)));
992 664
993 ASSERT_EQ(note->Wait(), CS_DECODER_SET); 665 ASSERT_EQ(note->Wait(), CS_DECODER_SET);
994 } 666 }
995 // Then wait for all the decodes to finish. 667 // Then wait for all the decodes to finish.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 FROM_HERE, 727 FROM_HERE,
1056 base::Bind(&STLDeleteElements<std::vector<EglRenderingVDAClient*> >, 728 base::Bind(&STLDeleteElements<std::vector<EglRenderingVDAClient*> >,
1057 &clients)); 729 &clients));
1058 rendering_thread.message_loop()->PostTask( 730 rendering_thread.message_loop()->PostTask(
1059 FROM_HERE, 731 FROM_HERE,
1060 base::Bind(&STLDeleteElements<std::vector<ClientStateNotification*> >, 732 base::Bind(&STLDeleteElements<std::vector<ClientStateNotification*> >,
1061 &notes)); 733 &notes));
1062 rendering_thread.message_loop()->PostTask( 734 rendering_thread.message_loop()->PostTask(
1063 FROM_HERE, 735 FROM_HERE,
1064 base::Bind(&RenderingHelper::UnInitialize, 736 base::Bind(&RenderingHelper::UnInitialize,
1065 base::Unretained(&rendering_helper), 737 base::Unretained(rendering_helper.get()),
1066 &done)); 738 &done));
1067 done.Wait(); 739 done.Wait();
1068 rendering_thread.Stop(); 740 rendering_thread.Stop();
1069 }; 741 };
1070 742
1071 // Test that replay after EOS works fine. 743 // Test that replay after EOS works fine.
1072 INSTANTIATE_TEST_CASE_P( 744 INSTANTIATE_TEST_CASE_P(
1073 ReplayAfterEOS, VideoDecodeAcceleratorTest, 745 ReplayAfterEOS, VideoDecodeAcceleratorTest,
1074 ::testing::Values( 746 ::testing::Values(
1075 MakeTuple(1, 1, 1, 4, END_OF_STREAM_RESET, CS_RESET))); 747 MakeTuple(1, 1, 1, 4, END_OF_STREAM_RESET, CS_RESET)));
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 821
1150 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); 822 CommandLine::SwitchMap switches = cmd_line->GetSwitches();
1151 for (CommandLine::SwitchMap::const_iterator it = switches.begin(); 823 for (CommandLine::SwitchMap::const_iterator it = switches.begin();
1152 it != switches.end(); ++it) { 824 it != switches.end(); ++it) {
1153 if (it->first == "test_video_data") { 825 if (it->first == "test_video_data") {
1154 test_video_data = it->second.c_str(); 826 test_video_data = it->second.c_str();
1155 continue; 827 continue;
1156 } 828 }
1157 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; 829 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
1158 } 830 }
831
832 base::ShadowingAtExitManager at_exit_manager;
833 RenderingHelper::InitializePlatform();
834
1159 #if defined(OS_WIN) 835 #if defined(OS_WIN)
1160 base::ShadowingAtExitManager at_exit_manager;
1161 gfx::InitializeGLBindings(gfx::kGLImplementationEGLGLES2);
1162 gfx::GLSurface::InitializeOneOff();
1163 {
1164 // Hack to ensure that EGL extension function pointers are initialized.
1165 scoped_refptr<gfx::GLSurface> surface(
1166 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)));
1167 scoped_refptr<gfx::GLContext> context(
1168 gfx::GLContext::CreateGLContext(NULL, surface.get(),
1169 gfx::PreferIntegratedGpu));
1170 context->MakeCurrent(surface.get());
1171 }
1172 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); 836 DXVAVideoDecodeAccelerator::PreSandboxInitialization();
1173 #endif // OS_WIN 837 #endif
838
1174 return RUN_ALL_TESTS(); 839 return RUN_ALL_TESTS();
1175 } 840 }
OLDNEW
« no previous file with comments | « content/common/gpu/media/rendering_helper_mac.mm ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698