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_win.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.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 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 #endif | 104 #endif |
105 | 105 |
106 // MF_XVP_PLAYBACK_MODE | 106 // MF_XVP_PLAYBACK_MODE |
107 // Data type: UINT32 (treat as BOOL) | 107 // Data type: UINT32 (treat as BOOL) |
108 // If this attribute is TRUE, the video processor will run in playback mode | 108 // If this attribute is TRUE, the video processor will run in playback mode |
109 // where it allows callers to allocate output samples and allows last frame | 109 // where it allows callers to allocate output samples and allows last frame |
110 // regeneration (repaint). | 110 // regeneration (repaint). |
111 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, | 111 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, |
112 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); | 112 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); |
113 | 113 |
| 114 // Defines the GUID for the Intel H264 DXVA device. |
| 115 static const GUID DXVA2_Intel_ModeH264_E = { |
| 116 0x604F8E68, 0x4951, 0x4c54,{ 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6} |
| 117 }; |
| 118 |
114 // Provides scoped access to the underlying buffer in an IMFMediaBuffer | 119 // Provides scoped access to the underlying buffer in an IMFMediaBuffer |
115 // instance. | 120 // instance. |
116 class MediaBufferScopedPointer { | 121 class MediaBufferScopedPointer { |
117 public: | 122 public: |
118 MediaBufferScopedPointer(IMFMediaBuffer* media_buffer) | 123 MediaBufferScopedPointer(IMFMediaBuffer* media_buffer) |
119 : media_buffer_(media_buffer), | 124 : media_buffer_(media_buffer), |
120 buffer_(nullptr), | 125 buffer_(nullptr), |
121 max_length_(0), | 126 max_length_(0), |
122 current_length_(0) { | 127 current_length_(0) { |
123 HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, ¤t_length_); | 128 HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, ¤t_length_); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 return hr; | 315 return hr; |
311 } | 316 } |
312 | 317 |
313 // Helper function to query the ANGLE device object. The template argument T | 318 // Helper function to query the ANGLE device object. The template argument T |
314 // identifies the device interface being queried. IDirect3DDevice9Ex for d3d9 | 319 // identifies the device interface being queried. IDirect3DDevice9Ex for d3d9 |
315 // and ID3D11Device for dx11. | 320 // and ID3D11Device for dx11. |
316 template<class T> | 321 template<class T> |
317 base::win::ScopedComPtr<T> QueryDeviceObjectFromANGLE(int object_type) { | 322 base::win::ScopedComPtr<T> QueryDeviceObjectFromANGLE(int object_type) { |
318 base::win::ScopedComPtr<T> device_object; | 323 base::win::ScopedComPtr<T> device_object; |
319 | 324 |
320 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 325 EGLDisplay egl_display = nullptr; |
321 intptr_t egl_device = 0; | 326 intptr_t egl_device = 0; |
322 intptr_t device = 0; | 327 intptr_t device = 0; |
323 | 328 |
| 329 { |
| 330 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. GetHardwareDisplay"); |
| 331 egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 332 } |
| 333 |
324 RETURN_ON_FAILURE( | 334 RETURN_ON_FAILURE( |
325 gfx::GLSurfaceEGL::HasEGLExtension("EGL_EXT_device_query"), | 335 gfx::GLSurfaceEGL::HasEGLExtension("EGL_EXT_device_query"), |
326 "EGL_EXT_device_query missing", | 336 "EGL_EXT_device_query missing", |
327 device_object); | 337 device_object); |
328 | 338 |
329 PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT = | 339 PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT = nullptr; |
330 reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(eglGetProcAddress( | |
331 "eglQueryDisplayAttribEXT")); | |
332 | 340 |
333 RETURN_ON_FAILURE( | 341 { |
334 QueryDisplayAttribEXT, | 342 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress"); |
335 "Failed to get the eglQueryDisplayAttribEXT function from ANGLE", | |
336 device_object); | |
337 | 343 |
338 PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT = | 344 QueryDisplayAttribEXT = |
339 reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(eglGetProcAddress( | 345 reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(eglGetProcAddress( |
340 "eglQueryDeviceAttribEXT")); | 346 "eglQueryDisplayAttribEXT")); |
341 | 347 |
342 RETURN_ON_FAILURE( | 348 RETURN_ON_FAILURE( |
343 QueryDeviceAttribEXT, | 349 QueryDisplayAttribEXT, |
344 "Failed to get the eglQueryDeviceAttribEXT function from ANGLE", | 350 "Failed to get the eglQueryDisplayAttribEXT function from ANGLE", |
345 device_object); | 351 device_object); |
| 352 } |
346 | 353 |
347 RETURN_ON_FAILURE( | 354 PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT = nullptr; |
348 QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device), | 355 |
349 "The eglQueryDisplayAttribEXT function failed to get the EGL device", | 356 { |
350 device_object); | 357 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress"); |
| 358 |
| 359 QueryDeviceAttribEXT = |
| 360 reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(eglGetProcAddress( |
| 361 "eglQueryDeviceAttribEXT")); |
| 362 |
| 363 RETURN_ON_FAILURE( |
| 364 QueryDeviceAttribEXT, |
| 365 "Failed to get the eglQueryDeviceAttribEXT function from ANGLE", |
| 366 device_object); |
| 367 } |
| 368 |
| 369 { |
| 370 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT"); |
| 371 |
| 372 RETURN_ON_FAILURE( |
| 373 QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device), |
| 374 "The eglQueryDisplayAttribEXT function failed to get the EGL device", |
| 375 device_object); |
| 376 } |
351 | 377 |
352 RETURN_ON_FAILURE( | 378 RETURN_ON_FAILURE( |
353 egl_device, | 379 egl_device, |
354 "Failed to get the EGL device", | 380 "Failed to get the EGL device", |
355 device_object); | 381 device_object); |
356 | 382 |
357 RETURN_ON_FAILURE( | 383 { |
358 QueryDeviceAttribEXT( | 384 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT"); |
359 reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device), | |
360 "The eglQueryDeviceAttribEXT function failed to get the device", | |
361 device_object); | |
362 | 385 |
363 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object); | 386 RETURN_ON_FAILURE( |
| 387 QueryDeviceAttribEXT( |
| 388 reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device), |
| 389 "The eglQueryDeviceAttribEXT function failed to get the device", |
| 390 device_object); |
| 391 |
| 392 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object); |
| 393 } |
364 | 394 |
365 device_object = reinterpret_cast<T*>(device); | 395 device_object = reinterpret_cast<T*>(device); |
366 return device_object; | 396 return device_object; |
367 } | 397 } |
368 | 398 |
369 H264ConfigChangeDetector::H264ConfigChangeDetector() | 399 H264ConfigChangeDetector::H264ConfigChangeDetector() |
370 : last_sps_id_(0), | 400 : last_sps_id_(0), |
371 last_pps_id_(0), | 401 last_pps_id_(0), |
372 config_changed_(false), | 402 config_changed_(false), |
373 pending_config_changed_(false) { | 403 pending_config_changed_(false) { |
(...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 return false; | 1364 return false; |
1335 } | 1365 } |
1336 | 1366 |
1337 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { | 1367 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { |
1338 return GL_BGRA_EXT; | 1368 return GL_BGRA_EXT; |
1339 } | 1369 } |
1340 | 1370 |
1341 // static | 1371 // static |
1342 media::VideoDecodeAccelerator::SupportedProfiles | 1372 media::VideoDecodeAccelerator::SupportedProfiles |
1343 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { | 1373 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { |
| 1374 TRACE_EVENT0("gpu,startup", |
| 1375 "DXVAVideoDecodeAccelerator::GetSupportedProfiles"); |
| 1376 |
1344 // TODO(henryhsu): Need to ensure the profiles are actually supported. | 1377 // TODO(henryhsu): Need to ensure the profiles are actually supported. |
1345 SupportedProfiles profiles; | 1378 SupportedProfiles profiles; |
1346 for (const auto& supported_profile : kSupportedProfiles) { | 1379 for (const auto& supported_profile : kSupportedProfiles) { |
| 1380 std::pair<int, int> min_resolution = GetMinResolution(supported_profile); |
| 1381 std::pair<int, int> max_resolution = GetMaxResolution(supported_profile); |
| 1382 |
1347 SupportedProfile profile; | 1383 SupportedProfile profile; |
1348 profile.profile = supported_profile; | 1384 profile.profile = supported_profile; |
1349 // Windows Media Foundation H.264 decoding does not support decoding videos | 1385 profile.min_resolution.SetSize(min_resolution.first, min_resolution.second); |
1350 // with any dimension smaller than 48 pixels: | 1386 profile.max_resolution.SetSize(max_resolution.first, max_resolution.second); |
1351 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 | |
1352 profile.min_resolution.SetSize(48, 48); | |
1353 // Use 1088 to account for 16x16 macroblocks. | |
1354 profile.max_resolution.SetSize(1920, 1088); | |
1355 profiles.push_back(profile); | 1387 profiles.push_back(profile); |
1356 } | 1388 } |
1357 return profiles; | 1389 return profiles; |
1358 } | 1390 } |
1359 | 1391 |
1360 // static | 1392 // static |
1361 void DXVAVideoDecodeAccelerator::PreSandboxInitialization() { | 1393 void DXVAVideoDecodeAccelerator::PreSandboxInitialization() { |
1362 ::LoadLibrary(L"MFPlat.dll"); | 1394 ::LoadLibrary(L"MFPlat.dll"); |
1363 ::LoadLibrary(L"msmpeg2vdec.dll"); | 1395 ::LoadLibrary(L"msmpeg2vdec.dll"); |
1364 ::LoadLibrary(L"mf.dll"); | 1396 ::LoadLibrary(L"mf.dll"); |
1365 ::LoadLibrary(L"dxva2.dll"); | 1397 ::LoadLibrary(L"dxva2.dll"); |
1366 | 1398 |
1367 if (base::win::GetVersion() > base::win::VERSION_WIN7) { | 1399 if (base::win::GetVersion() > base::win::VERSION_WIN7) { |
1368 LoadLibrary(L"msvproc.dll"); | 1400 LoadLibrary(L"msvproc.dll"); |
1369 } else { | 1401 } else { |
1370 #if defined(ENABLE_DX11_FOR_WIN7) | 1402 #if defined(ENABLE_DX11_FOR_WIN7) |
1371 LoadLibrary(L"mshtmlmedia.dll"); | 1403 LoadLibrary(L"mshtmlmedia.dll"); |
1372 #endif | 1404 #endif |
1373 } | 1405 } |
1374 } | 1406 } |
1375 | 1407 |
| 1408 // static |
| 1409 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMinResolution( |
| 1410 media::VideoCodecProfile profile) { |
| 1411 TRACE_EVENT0("gpu,startup", |
| 1412 "DXVAVideoDecodeAccelerator::GetMinResolution"); |
| 1413 std::pair<int, int> min_resolution; |
| 1414 if (profile >= media::H264PROFILE_BASELINE && |
| 1415 profile <= media::H264PROFILE_HIGH) { |
| 1416 // Windows Media Foundation H.264 decoding does not support decoding videos |
| 1417 // with any dimension smaller than 48 pixels: |
| 1418 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 |
| 1419 min_resolution = std::make_pair(48, 48); |
| 1420 } else { |
| 1421 // TODO(ananta) |
| 1422 // Detect this properly for VP8/VP9 profiles. |
| 1423 min_resolution = std::make_pair(16, 16); |
| 1424 } |
| 1425 return min_resolution; |
| 1426 } |
| 1427 |
| 1428 // static |
| 1429 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxResolution( |
| 1430 const media::VideoCodecProfile profile) { |
| 1431 TRACE_EVENT0("gpu,startup", |
| 1432 "DXVAVideoDecodeAccelerator::GetMaxResolution"); |
| 1433 std::pair<int, int> max_resolution; |
| 1434 if (profile >= media::H264PROFILE_BASELINE && |
| 1435 profile <= media::H264PROFILE_HIGH) { |
| 1436 max_resolution = GetMaxH264Resolution(); |
| 1437 } else { |
| 1438 // TODO(ananta) |
| 1439 // Detect this properly for VP8/VP9 profiles. |
| 1440 max_resolution = std::make_pair(4096, 2160); |
| 1441 } |
| 1442 return max_resolution; |
| 1443 } |
| 1444 |
| 1445 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxH264Resolution() { |
| 1446 TRACE_EVENT0("gpu,startup", |
| 1447 "DXVAVideoDecodeAccelerator::GetMaxH264Resolution"); |
| 1448 // The H.264 resolution detection operation is expensive. This static flag |
| 1449 // allows us to run the detection once. |
| 1450 static bool resolution_detected = false; |
| 1451 // Use 1088 to account for 16x16 macroblocks. |
| 1452 static std::pair<int, int> max_resolution = std::make_pair(1920, 1088); |
| 1453 if (resolution_detected) |
| 1454 return max_resolution; |
| 1455 |
| 1456 resolution_detected = true; |
| 1457 |
| 1458 // On Windows 7 the maximum resolution supported by media foundation is |
| 1459 // 1920 x 1088. |
| 1460 if (base::win::GetVersion() == base::win::VERSION_WIN7) |
| 1461 return max_resolution; |
| 1462 |
| 1463 // To detect if a driver supports the desired resolutions, we try and create |
| 1464 // a DXVA decoder instance for that resolution and profile. If that succeeds |
| 1465 // we assume that the driver supports H/W H.264 decoding for that resolution. |
| 1466 HRESULT hr = E_FAIL; |
| 1467 base::win::ScopedComPtr<ID3D11Device> device; |
| 1468 |
| 1469 { |
| 1470 TRACE_EVENT0("gpu,startup", |
| 1471 "GetMaxH264Resolution. QueryDeviceObjectFromANGLE"); |
| 1472 |
| 1473 device = QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
| 1474 if (!device.get()) |
| 1475 return max_resolution; |
| 1476 } |
| 1477 |
| 1478 base::win::ScopedComPtr<ID3D11VideoDevice> video_device; |
| 1479 hr = device.QueryInterface(IID_ID3D11VideoDevice, |
| 1480 video_device.ReceiveVoid()); |
| 1481 if (FAILED(hr)) |
| 1482 return max_resolution; |
| 1483 |
| 1484 GUID decoder_guid = {}; |
| 1485 |
| 1486 { |
| 1487 TRACE_EVENT0("gpu,startup", |
| 1488 "GetMaxH264Resolution. H.264 guid search begin"); |
| 1489 // Enumerate supported video profiles and look for the H264 profile. |
| 1490 bool found = false; |
| 1491 UINT profile_count = video_device->GetVideoDecoderProfileCount(); |
| 1492 for (UINT profile_idx = 0; profile_idx < profile_count; profile_idx++) { |
| 1493 GUID profile_id = {}; |
| 1494 hr = video_device->GetVideoDecoderProfile(profile_idx, &profile_id); |
| 1495 if (SUCCEEDED(hr) && |
| 1496 (profile_id == DXVA2_ModeH264_E || |
| 1497 profile_id == DXVA2_Intel_ModeH264_E)) { |
| 1498 decoder_guid = profile_id; |
| 1499 found = true; |
| 1500 break; |
| 1501 } |
| 1502 } |
| 1503 if (!found) |
| 1504 return max_resolution; |
| 1505 } |
| 1506 |
| 1507 // We look for the following resolutions in the driver. |
| 1508 // TODO(ananta) |
| 1509 // Look into whether this list needs to be expanded. |
| 1510 static std::pair<int, int> resolution_array[] = { |
| 1511 // Use 1088 to account for 16x16 macroblocks. |
| 1512 std::make_pair(1920, 1088), |
| 1513 std::make_pair(2560, 1440), |
| 1514 std::make_pair(3840, 2160), |
| 1515 std::make_pair(4096, 2160), |
| 1516 std::make_pair(4096, 2304), |
| 1517 }; |
| 1518 |
| 1519 { |
| 1520 TRACE_EVENT0("gpu,startup", |
| 1521 "GetMaxH264Resolution. Resolution search begin"); |
| 1522 |
| 1523 for (size_t res_idx = 0; res_idx < arraysize(resolution_array); |
| 1524 res_idx++) { |
| 1525 D3D11_VIDEO_DECODER_DESC desc = {}; |
| 1526 desc.Guid = decoder_guid; |
| 1527 desc.SampleWidth = resolution_array[res_idx].first; |
| 1528 desc.SampleHeight = resolution_array[res_idx].second; |
| 1529 desc.OutputFormat = DXGI_FORMAT_NV12; |
| 1530 UINT config_count = 0; |
| 1531 hr = video_device->GetVideoDecoderConfigCount(&desc, &config_count); |
| 1532 if (FAILED(hr) || config_count == 0) |
| 1533 return max_resolution; |
| 1534 |
| 1535 D3D11_VIDEO_DECODER_CONFIG config = {}; |
| 1536 hr = video_device->GetVideoDecoderConfig(&desc, 0, &config); |
| 1537 if (FAILED(hr)) |
| 1538 return max_resolution; |
| 1539 |
| 1540 base::win::ScopedComPtr<ID3D11VideoDecoder> video_decoder; |
| 1541 hr = video_device->CreateVideoDecoder(&desc, &config, |
| 1542 video_decoder.Receive()); |
| 1543 if (!video_decoder.get()) |
| 1544 return max_resolution; |
| 1545 |
| 1546 max_resolution = resolution_array[res_idx]; |
| 1547 } |
| 1548 } |
| 1549 return max_resolution; |
| 1550 } |
| 1551 |
1376 bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { | 1552 bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { |
1377 HMODULE decoder_dll = NULL; | 1553 HMODULE decoder_dll = NULL; |
1378 | 1554 |
1379 CLSID clsid = {}; | 1555 CLSID clsid = {}; |
1380 | 1556 |
1381 // Profile must fall within the valid range for one of the supported codecs. | 1557 // Profile must fall within the valid range for one of the supported codecs. |
1382 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { | 1558 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { |
1383 // We mimic the steps CoCreateInstance uses to instantiate the object. This | 1559 // We mimic the steps CoCreateInstance uses to instantiate the object. This |
1384 // was previously done because it failed inside the sandbox, and now is done | 1560 // was previously done because it failed inside the sandbox, and now is done |
1385 // as a more minimal approach to avoid other side-effects CCI might have (as | 1561 // as a more minimal approach to avoid other side-effects CCI might have (as |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1730 OutputBuffers::iterator index; | 1906 OutputBuffers::iterator index; |
1731 | 1907 |
1732 for (index = output_picture_buffers_.begin(); | 1908 for (index = output_picture_buffers_.begin(); |
1733 index != output_picture_buffers_.end() && | 1909 index != output_picture_buffers_.end() && |
1734 OutputSamplesPresent(); | 1910 OutputSamplesPresent(); |
1735 ++index) { | 1911 ++index) { |
1736 if (index->second->available()) { | 1912 if (index->second->available()) { |
1737 PendingSampleInfo* pending_sample = NULL; | 1913 PendingSampleInfo* pending_sample = NULL; |
1738 { | 1914 { |
1739 base::AutoLock lock(decoder_lock_); | 1915 base::AutoLock lock(decoder_lock_); |
1740 | |
1741 PendingSampleInfo& sample_info = pending_output_samples_.front(); | 1916 PendingSampleInfo& sample_info = pending_output_samples_.front(); |
1742 if (sample_info.picture_buffer_id != -1) | 1917 if (sample_info.picture_buffer_id != -1) |
1743 continue; | 1918 continue; |
1744 pending_sample = &sample_info; | 1919 pending_sample = &sample_info; |
1745 } | 1920 } |
1746 | 1921 |
1747 int width = 0; | 1922 int width = 0; |
1748 int height = 0; | 1923 int height = 0; |
1749 if (!GetVideoFrameDimensions(pending_sample->output_sample.get(), | 1924 if (!GetVideoFrameDimensions(pending_sample->output_sample.get(), |
1750 &width, &height)) { | 1925 &width, &height)) { |
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 DismissStaleBuffers(true); | 2831 DismissStaleBuffers(true); |
2657 Invalidate(); | 2832 Invalidate(); |
2658 Initialize(config_, client_); | 2833 Initialize(config_, client_); |
2659 decoder_thread_task_runner_->PostTask( | 2834 decoder_thread_task_runner_->PostTask( |
2660 FROM_HERE, | 2835 FROM_HERE, |
2661 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2836 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
2662 base::Unretained(this))); | 2837 base::Unretained(this))); |
2663 } | 2838 } |
2664 | 2839 |
2665 } // namespace content | 2840 } // namespace content |
OLD | NEW |