OLD | NEW |
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 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" |
6 | 6 |
7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
10 | 10 |
11 #include <ks.h> | 11 #include <ks.h> |
12 #include <codecapi.h> | 12 #include <codecapi.h> |
13 #include <mfapi.h> | 13 #include <mfapi.h> |
14 #include <mferror.h> | 14 #include <mferror.h> |
15 #include <wmcodecdsp.h> | 15 #include <wmcodecdsp.h> |
16 | 16 |
17 #include "base/bind.h" | 17 #include "base/bind.h" |
18 #include "base/callback.h" | 18 #include "base/callback.h" |
19 #include "base/command_line.h" | 19 #include "base/command_line.h" |
20 #include "base/debug/trace_event.h" | 20 #include "base/debug/trace_event.h" |
21 #include "base/logging.h" | 21 #include "base/logging.h" |
22 #include "base/memory/scoped_handle.h" | 22 #include "base/memory/scoped_handle.h" |
23 #include "base/memory/scoped_ptr.h" | 23 #include "base/memory/scoped_ptr.h" |
24 #include "base/message_loop.h" | 24 #include "base/message_loop.h" |
25 #include "base/process_util.h" | 25 #include "base/process_util.h" |
26 #include "base/shared_memory.h" | 26 #include "base/shared_memory.h" |
| 27 #include "base/threading/worker_pool.h" |
27 #include "media/video/video_decode_accelerator.h" | 28 #include "media/video/video_decode_accelerator.h" |
28 #include "third_party/angle/include/EGL/egl.h" | 29 #include "third_party/angle/include/EGL/egl.h" |
29 #include "third_party/angle/include/EGL/eglext.h" | 30 #include "third_party/angle/include/EGL/eglext.h" |
30 #include "ui/gl/gl_bindings.h" | 31 #include "ui/gl/gl_bindings.h" |
31 #include "ui/gl/gl_surface.h" | 32 #include "ui/gl/gl_surface.h" |
32 #include "ui/gl/gl_switches.h" | 33 #include "ui/gl/gl_switches.h" |
33 | 34 |
34 namespace content { | 35 namespace content { |
35 | 36 |
36 // We only request 5 picture buffers from the client which are used to hold the | 37 // We only request 5 picture buffers from the client which are used to hold the |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 | 361 |
361 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( | 362 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( |
362 int32 buffer_id, IMFSample* sample) | 363 int32 buffer_id, IMFSample* sample) |
363 : input_buffer_id(buffer_id) { | 364 : input_buffer_id(buffer_id) { |
364 output_sample.Attach(sample); | 365 output_sample.Attach(sample); |
365 } | 366 } |
366 | 367 |
367 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} | 368 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} |
368 | 369 |
369 // static | 370 // static |
370 void DXVAVideoDecodeAccelerator::PreSandboxInitialization() { | 371 // Initializes DXVA on a separate thread. |
| 372 void DXVAVideoDecodeAccelerator::PreSandboxInitialization( |
| 373 const base::Closure& completion_task) { |
371 // Should be called only once during program startup. | 374 // Should be called only once during program startup. |
372 DCHECK(!pre_sandbox_init_done_); | 375 DCHECK(!pre_sandbox_init_done_); |
373 | 376 |
| 377 base::ScopedClosureRunner scoped_completion_runner(completion_task); |
| 378 |
374 static wchar_t* decoding_dlls[] = { | 379 static wchar_t* decoding_dlls[] = { |
375 L"d3d9.dll", | 380 L"d3d9.dll", |
376 L"dxva2.dll", | 381 L"dxva2.dll", |
377 L"mf.dll", | 382 L"mf.dll", |
378 L"mfplat.dll", | 383 L"mfplat.dll", |
379 L"msmpeg2vdec.dll", | 384 L"msmpeg2vdec.dll", |
380 }; | 385 }; |
381 | 386 |
382 for (int i = 0; i < arraysize(decoding_dlls); ++i) { | 387 for (int i = 0; i < arraysize(decoding_dlls); ++i) { |
383 if (!::LoadLibrary(decoding_dlls[i])) { | 388 if (!::LoadLibrary(decoding_dlls[i])) { |
384 DLOG(ERROR) << "Failed to load decoder dll: " << decoding_dlls[i] | 389 DLOG(ERROR) << "Failed to load decoder dll: " << decoding_dlls[i] |
385 << ", Error: " << ::GetLastError(); | 390 << ", Error: " << ::GetLastError(); |
386 return; | 391 return; |
387 } | 392 } |
388 } | 393 } |
389 | 394 |
390 RETURN_ON_FAILURE(CreateD3DDevManager(), | 395 HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9_); |
391 "Failed to initialize D3D device and manager",); | 396 RETURN_ON_HR_FAILURE(hr, |
392 pre_sandbox_init_done_ = true; | 397 "Failed to initialize D3D9.",); |
| 398 |
| 399 // Initialize H/W video decoding stuff which fails in the sandbox. This is |
| 400 // done on a worker thread because it takes 10s of ms. |
| 401 scoped_completion_runner.Release(); |
| 402 base::WorkerPool::PostTask( |
| 403 FROM_HERE, |
| 404 base::Bind(&DXVAVideoDecodeAccelerator::CreateD3DDevManager, |
| 405 completion_task), |
| 406 true); |
393 } | 407 } |
394 | 408 |
395 // static | 409 // static |
396 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { | 410 void DXVAVideoDecodeAccelerator::CreateD3DDevManager( |
397 HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9_); | 411 const base::Closure& completion_task) { |
398 RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false); | 412 base::ScopedClosureRunner scoped_completion_runner(completion_task); |
399 | 413 |
400 D3DPRESENT_PARAMETERS present_params = {0}; | 414 D3DPRESENT_PARAMETERS present_params = {0}; |
401 present_params.BackBufferWidth = 1; | 415 present_params.BackBufferWidth = 1; |
402 present_params.BackBufferHeight = 1; | 416 present_params.BackBufferHeight = 1; |
403 present_params.BackBufferFormat = D3DFMT_UNKNOWN; | 417 present_params.BackBufferFormat = D3DFMT_UNKNOWN; |
404 present_params.BackBufferCount = 1; | 418 present_params.BackBufferCount = 1; |
405 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; | 419 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; |
406 present_params.hDeviceWindow = ::GetShellWindow(); | 420 present_params.hDeviceWindow = ::GetShellWindow(); |
407 present_params.Windowed = TRUE; | 421 present_params.Windowed = TRUE; |
408 present_params.Flags = D3DPRESENTFLAG_VIDEO; | 422 present_params.Flags = D3DPRESENTFLAG_VIDEO; |
409 present_params.FullScreen_RefreshRateInHz = 0; | 423 present_params.FullScreen_RefreshRateInHz = 0; |
410 present_params.PresentationInterval = 0; | 424 present_params.PresentationInterval = 0; |
411 | 425 |
412 hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, | 426 HRESULT hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, |
413 D3DDEVTYPE_HAL, | 427 D3DDEVTYPE_HAL, |
414 ::GetShellWindow(), | 428 ::GetShellWindow(), |
415 D3DCREATE_FPU_PRESERVE | | 429 D3DCREATE_FPU_PRESERVE | |
416 D3DCREATE_SOFTWARE_VERTEXPROCESSING | | 430 D3DCREATE_SOFTWARE_VERTEXPROCESSING | |
417 D3DCREATE_DISABLE_PSGP_THREADING | | 431 D3DCREATE_DISABLE_PSGP_THREADING | |
418 D3DCREATE_MULTITHREADED, | 432 D3DCREATE_MULTITHREADED, |
419 &present_params, | 433 &present_params, |
420 NULL, | 434 NULL, |
421 &device_); | 435 &device_); |
422 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false); | 436 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device",); |
423 | 437 |
424 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, | 438 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, |
425 &device_manager_); | 439 &device_manager_); |
426 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); | 440 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed",); |
427 | 441 |
428 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); | 442 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); |
429 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 443 RETURN_ON_HR_FAILURE(hr, "Failed to reset device",); |
430 | 444 |
431 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, &query_); | 445 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, &query_); |
432 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); | 446 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query",); |
| 447 |
433 // Ensure query_ API works (to avoid an infinite loop later in | 448 // Ensure query_ API works (to avoid an infinite loop later in |
434 // CopyOutputSampleDataToPictureBuffer). | 449 // CopyOutputSampleDataToPictureBuffer). |
435 hr = query_->Issue(D3DISSUE_END); | 450 hr = query_->Issue(D3DISSUE_END); |
436 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); | 451 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query",); |
437 return true; | 452 |
| 453 pre_sandbox_init_done_ = true; |
438 } | 454 } |
439 | 455 |
440 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( | 456 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
441 media::VideoDecodeAccelerator::Client* client, | 457 media::VideoDecodeAccelerator::Client* client, |
442 const base::Callback<bool(void)>& make_context_current) | 458 const base::Callback<bool(void)>& make_context_current) |
443 : client_(client), | 459 : client_(client), |
444 egl_config_(NULL), | 460 egl_config_(NULL), |
445 state_(kUninitialized), | 461 state_(kUninitialized), |
446 pictures_requested_(false), | 462 pictures_requested_(false), |
447 inputs_before_decode_(0), | 463 inputs_before_decode_(0), |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 return; | 1090 return; |
1075 } | 1091 } |
1076 | 1092 |
1077 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 1093 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
1078 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); | 1094 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); |
1079 | 1095 |
1080 state_ = kNormal; | 1096 state_ = kNormal; |
1081 } | 1097 } |
1082 | 1098 |
1083 } // namespace content | 1099 } // namespace content |
OLD | NEW |