Chromium Code Reviews| 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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 // Maximum number of iterations we allow before aborting the attempt to flush | 155 // Maximum number of iterations we allow before aborting the attempt to flush |
| 156 // the batched queries to the driver and allow torn/corrupt frames to be | 156 // the batched queries to the driver and allow torn/corrupt frames to be |
| 157 // rendered. | 157 // rendered. |
| 158 kFlushDecoderSurfaceTimeoutMs = 1, | 158 kFlushDecoderSurfaceTimeoutMs = 1, |
| 159 // Maximum iterations where we try to flush the d3d device. | 159 // Maximum iterations where we try to flush the d3d device. |
| 160 kMaxIterationsForD3DFlush = 4, | 160 kMaxIterationsForD3DFlush = 4, |
| 161 // We only request 5 picture buffers from the client which are used to hold | 161 // We only request 5 picture buffers from the client which are used to hold |
| 162 // the decoded samples. These buffers are then reused when the client tells | 162 // the decoded samples. These buffers are then reused when the client tells |
| 163 // us that it is done with the buffer. | 163 // us that it is done with the buffer. |
| 164 kNumPictureBuffers = 5, | 164 kNumPictureBuffers = 5, |
| 165 // The keyed mutex should always be released before the other thread | |
| 166 // attempts to acquire it, so AcquireSync should always return immediately. | |
| 167 kAcquireSyncWaitMs = 0, | |
| 165 }; | 168 }; |
| 166 | 169 |
| 167 static IMFSample* CreateEmptySample() { | 170 static IMFSample* CreateEmptySample() { |
| 168 base::win::ScopedComPtr<IMFSample> sample; | 171 base::win::ScopedComPtr<IMFSample> sample; |
| 169 HRESULT hr = MFCreateSample(sample.Receive()); | 172 HRESULT hr = MFCreateSample(sample.Receive()); |
| 170 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); | 173 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); |
| 171 return sample.Detach(); | 174 return sample.Detach(); |
| 172 } | 175 } |
| 173 | 176 |
| 174 // Creates a Media Foundation sample with one buffer of length |buffer_length| | 177 // Creates a Media Foundation sample with one buffer of length |buffer_length| |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 // Maintains information about a DXVA picture buffer, i.e. whether it is | 341 // Maintains information about a DXVA picture buffer, i.e. whether it is |
| 339 // available for rendering, the texture information, etc. | 342 // available for rendering, the texture information, etc. |
| 340 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 343 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
| 341 public: | 344 public: |
| 342 static linked_ptr<DXVAPictureBuffer> Create( | 345 static linked_ptr<DXVAPictureBuffer> Create( |
| 343 const DXVAVideoDecodeAccelerator& decoder, | 346 const DXVAVideoDecodeAccelerator& decoder, |
| 344 const media::PictureBuffer& buffer, | 347 const media::PictureBuffer& buffer, |
| 345 EGLConfig egl_config); | 348 EGLConfig egl_config); |
| 346 ~DXVAPictureBuffer(); | 349 ~DXVAPictureBuffer(); |
| 347 | 350 |
| 348 void ReusePictureBuffer(); | 351 bool ReusePictureBuffer(); |
| 349 // Copies the output sample data to the picture buffer provided by the | 352 // Copies the output sample data to the picture buffer provided by the |
| 350 // client. | 353 // client. |
| 351 // The dest_surface parameter contains the decoded bits. | 354 // The dest_surface parameter contains the decoded bits. |
| 352 bool CopyOutputSampleDataToPictureBuffer( | 355 bool CopyOutputSampleDataToPictureBuffer( |
| 353 DXVAVideoDecodeAccelerator* decoder, | 356 DXVAVideoDecodeAccelerator* decoder, |
| 354 IDirect3DSurface9* dest_surface, | 357 IDirect3DSurface9* dest_surface, |
| 355 ID3D11Texture2D* dx11_texture, | 358 ID3D11Texture2D* dx11_texture, |
| 356 int input_buffer_id); | 359 int input_buffer_id); |
| 357 | 360 |
| 358 bool available() const { | 361 bool available() const { |
| 359 return available_; | 362 return available_; |
| 360 } | 363 } |
| 361 | 364 |
| 362 void set_available(bool available) { | 365 void set_available(bool available) { |
| 363 available_ = available; | 366 available_ = available; |
| 364 } | 367 } |
| 365 | 368 |
| 366 int id() const { | 369 int id() const { |
| 367 return picture_buffer_.id(); | 370 return picture_buffer_.id(); |
| 368 } | 371 } |
| 369 | 372 |
| 370 gfx::Size size() const { | 373 gfx::Size size() const { |
| 371 return picture_buffer_.size(); | 374 return picture_buffer_.size(); |
| 372 } | 375 } |
| 373 | 376 |
| 374 // Called when the source surface |src_surface| is copied to the destination | 377 // Called when the source surface |src_surface| is copied to the destination |
| 375 // |dest_surface| | 378 // |dest_surface| |
| 376 void CopySurfaceComplete(IDirect3DSurface9* src_surface, | 379 bool CopySurfaceComplete(IDirect3DSurface9* src_surface, |
| 377 IDirect3DSurface9* dest_surface); | 380 IDirect3DSurface9* dest_surface); |
| 378 | 381 |
| 379 private: | 382 private: |
| 380 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); | 383 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); |
| 381 | 384 |
| 382 bool available_; | 385 bool available_; |
| 383 media::PictureBuffer picture_buffer_; | 386 media::PictureBuffer picture_buffer_; |
| 384 EGLSurface decoding_surface_; | 387 EGLSurface decoding_surface_; |
| 385 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; | 388 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; |
| 386 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; | 389 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; |
| 387 | 390 |
| 391 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_; | |
| 392 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_; | |
| 393 | |
| 394 // This is the last value that was used to release the keyed mutex. | |
| 395 uint64_t keyed_mutex_value_; | |
| 396 | |
| 388 // The following |IDirect3DSurface9| interface pointers are used to hold | 397 // The following |IDirect3DSurface9| interface pointers are used to hold |
| 389 // references on the surfaces during the course of a StretchRect operation | 398 // references on the surfaces during the course of a StretchRect operation |
| 390 // to copy the source surface to the target. The references are released | 399 // to copy the source surface to the target. The references are released |
| 391 // when the StretchRect operation i.e. the copy completes. | 400 // when the StretchRect operation i.e. the copy completes. |
| 392 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_; | 401 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_; |
| 393 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_; | 402 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_; |
| 394 | 403 |
| 395 // This ID3D11Texture2D interface pointer is used to hold a reference to the | 404 // This ID3D11Texture2D interface pointer is used to hold a reference to the |
| 396 // decoder texture during the course of a copy operation. This reference is | 405 // decoder texture during the course of a copy operation. This reference is |
| 397 // released when the copy completes. | 406 // released when the copy completes. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 411 const media::PictureBuffer& buffer, | 420 const media::PictureBuffer& buffer, |
| 412 EGLConfig egl_config) { | 421 EGLConfig egl_config) { |
| 413 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer)); | 422 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer)); |
| 414 | 423 |
| 415 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 424 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 416 | 425 |
| 417 EGLint use_rgb = 1; | 426 EGLint use_rgb = 1; |
| 418 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB, | 427 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB, |
| 419 &use_rgb); | 428 &use_rgb); |
| 420 | 429 |
| 430 HANDLE share_handle = nullptr; | |
| 431 if (decoder.d3d11_device_) { | |
|
ananta
2016/01/22 00:40:18
Please update the patch description to reflect tha
| |
| 432 D3D11_TEXTURE2D_DESC desc; | |
| 433 desc.Width = buffer.size().width(); | |
| 434 desc.Height = buffer.size().height(); | |
| 435 desc.MipLevels = 1; | |
| 436 desc.ArraySize = 1; | |
| 437 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; | |
| 438 desc.SampleDesc.Count = 1; | |
| 439 desc.SampleDesc.Quality = 0; | |
| 440 desc.Usage = D3D11_USAGE_DEFAULT; | |
| 441 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; | |
| 442 desc.CPUAccessFlags = 0; | |
| 443 desc.MiscFlags = decoder.use_keyed_mutex_ | |
| 444 ? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | |
| 445 : D3D11_RESOURCE_MISC_SHARED; | |
| 446 | |
| 447 HRESULT hr = decoder.d3d11_device_->CreateTexture2D( | |
| 448 &desc, nullptr, picture_buffer->dx11_decoding_texture_.Receive()); | |
| 449 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", | |
| 450 linked_ptr<DXVAPictureBuffer>(nullptr)); | |
| 451 if (decoder.use_keyed_mutex_) { | |
| 452 hr = picture_buffer->dx11_keyed_mutex_.QueryFrom( | |
| 453 picture_buffer->dx11_decoding_texture_.get()); | |
| 454 RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", | |
| 455 linked_ptr<DXVAPictureBuffer>(nullptr)); | |
| 456 } | |
| 457 | |
| 458 base::win::ScopedComPtr<IDXGIResource> resource; | |
| 459 hr = resource.QueryFrom(picture_buffer->dx11_decoding_texture_.get()); | |
| 460 DCHECK(SUCCEEDED(hr)); | |
| 461 hr = resource->GetSharedHandle(&share_handle); | |
| 462 RETURN_ON_FAILURE(SUCCEEDED(hr) && share_handle, | |
| 463 "Failed to query shared handle", | |
| 464 linked_ptr<DXVAPictureBuffer>(nullptr)); | |
| 465 | |
| 466 } else { | |
| 467 HRESULT hr = E_FAIL; | |
| 468 hr = decoder.d3d9_device_ex_->CreateTexture( | |
| 469 buffer.size().width(), buffer.size().height(), 1, D3DUSAGE_RENDERTARGET, | |
| 470 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, | |
| 471 picture_buffer->decoding_texture_.Receive(), &share_handle); | |
| 472 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", | |
| 473 linked_ptr<DXVAPictureBuffer>(nullptr)); | |
| 474 RETURN_ON_FAILURE(share_handle, "Failed to query shared handle", | |
| 475 linked_ptr<DXVAPictureBuffer>(nullptr)); | |
| 476 } | |
| 477 | |
| 421 EGLint attrib_list[] = { | 478 EGLint attrib_list[] = { |
| 422 EGL_WIDTH, buffer.size().width(), | 479 EGL_WIDTH, buffer.size().width(), |
| 423 EGL_HEIGHT, buffer.size().height(), | 480 EGL_HEIGHT, buffer.size().height(), |
| 424 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, | 481 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, |
| 425 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, | 482 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, |
| 426 EGL_NONE | 483 EGL_NONE |
| 427 }; | 484 }; |
| 428 | 485 |
| 429 picture_buffer->decoding_surface_ = eglCreatePbufferSurface( | 486 picture_buffer->decoding_surface_ = eglCreatePbufferFromClientBuffer( |
| 430 egl_display, | 487 egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, share_handle, |
| 431 egl_config, | 488 egl_config, attrib_list); |
| 432 attrib_list); | |
| 433 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, | 489 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, |
| 434 "Failed to create surface", | 490 "Failed to create surface", |
| 435 linked_ptr<DXVAPictureBuffer>(NULL)); | 491 linked_ptr<DXVAPictureBuffer>(NULL)); |
| 436 | 492 if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) { |
| 437 HANDLE share_handle = NULL; | 493 void* keyed_mutex = nullptr; |
| 438 EGLBoolean ret = eglQuerySurfacePointerANGLE( | 494 EGLBoolean ret = eglQuerySurfacePointerANGLE( |
| 439 egl_display, | 495 egl_display, picture_buffer->decoding_surface_, |
| 440 picture_buffer->decoding_surface_, | 496 EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex); |
| 441 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, | 497 RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE, |
| 442 &share_handle); | 498 "Failed to query ANGLE keyed mutex", |
| 443 | 499 linked_ptr<DXVAPictureBuffer>(nullptr)); |
| 444 RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE, | 500 picture_buffer->egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>( |
| 445 "Failed to query ANGLE surface pointer", | 501 static_cast<IDXGIKeyedMutex*>(keyed_mutex)); |
| 446 linked_ptr<DXVAPictureBuffer>(NULL)); | |
| 447 | |
| 448 HRESULT hr = E_FAIL; | |
| 449 if (decoder.d3d11_device_) { | |
| 450 base::win::ScopedComPtr<ID3D11Resource> resource; | |
| 451 hr = decoder.d3d11_device_->OpenSharedResource( | |
| 452 share_handle, | |
| 453 __uuidof(ID3D11Resource), | |
| 454 reinterpret_cast<void**>(resource.Receive())); | |
| 455 RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource", | |
| 456 linked_ptr<DXVAPictureBuffer>(NULL)); | |
| 457 hr = picture_buffer->dx11_decoding_texture_.QueryFrom(resource.get()); | |
| 458 } else { | |
| 459 hr = decoder.d3d9_device_ex_->CreateTexture( | |
| 460 buffer.size().width(), | |
| 461 buffer.size().height(), | |
| 462 1, | |
| 463 D3DUSAGE_RENDERTARGET, | |
| 464 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, | |
| 465 D3DPOOL_DEFAULT, | |
| 466 picture_buffer->decoding_texture_.Receive(), | |
| 467 &share_handle); | |
| 468 } | 502 } |
| 469 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", | |
| 470 linked_ptr<DXVAPictureBuffer>(NULL)); | |
| 471 picture_buffer->use_rgb_ = !!use_rgb; | 503 picture_buffer->use_rgb_ = !!use_rgb; |
| 472 return picture_buffer; | 504 return picture_buffer; |
| 473 } | 505 } |
| 474 | 506 |
| 475 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( | 507 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( |
| 476 const media::PictureBuffer& buffer) | 508 const media::PictureBuffer& buffer) |
| 477 : available_(true), | 509 : available_(true), |
| 478 picture_buffer_(buffer), | 510 picture_buffer_(buffer), |
| 479 decoding_surface_(NULL), | 511 decoding_surface_(NULL), |
| 480 use_rgb_(true) { | 512 keyed_mutex_value_(0), |
| 481 } | 513 use_rgb_(true) {} |
| 482 | 514 |
| 483 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { | 515 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { |
| 484 if (decoding_surface_) { | 516 if (decoding_surface_) { |
| 485 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 517 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 486 | 518 |
| 487 eglReleaseTexImage( | 519 eglReleaseTexImage( |
| 488 egl_display, | 520 egl_display, |
| 489 decoding_surface_, | 521 decoding_surface_, |
| 490 EGL_BACK_BUFFER); | 522 EGL_BACK_BUFFER); |
| 491 | 523 |
| 492 eglDestroySurface( | 524 eglDestroySurface( |
| 493 egl_display, | 525 egl_display, |
| 494 decoding_surface_); | 526 decoding_surface_); |
| 495 decoding_surface_ = NULL; | 527 decoding_surface_ = NULL; |
| 496 } | 528 } |
| 497 } | 529 } |
| 498 | 530 |
| 499 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { | 531 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { |
| 500 DCHECK(decoding_surface_); | 532 DCHECK(decoding_surface_); |
| 501 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 533 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 502 eglReleaseTexImage( | 534 eglReleaseTexImage( |
| 503 egl_display, | 535 egl_display, |
| 504 decoding_surface_, | 536 decoding_surface_, |
| 505 EGL_BACK_BUFFER); | 537 EGL_BACK_BUFFER); |
| 506 decoder_surface_.Release(); | 538 decoder_surface_.Release(); |
| 507 target_surface_.Release(); | 539 target_surface_.Release(); |
| 508 decoder_dx11_texture_.Release(); | 540 decoder_dx11_texture_.Release(); |
| 509 set_available(true); | 541 set_available(true); |
| 542 if (egl_keyed_mutex_) { | |
| 543 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_); | |
| 544 if (hr != S_OK) | |
| 545 return false; | |
| 546 } | |
| 547 return true; | |
| 510 } | 548 } |
| 511 | 549 |
| 512 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: | 550 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: |
| 513 CopyOutputSampleDataToPictureBuffer( | 551 CopyOutputSampleDataToPictureBuffer( |
| 514 DXVAVideoDecodeAccelerator* decoder, | 552 DXVAVideoDecodeAccelerator* decoder, |
| 515 IDirect3DSurface9* dest_surface, | 553 IDirect3DSurface9* dest_surface, |
| 516 ID3D11Texture2D* dx11_texture, | 554 ID3D11Texture2D* dx11_texture, |
| 517 int input_buffer_id) { | 555 int input_buffer_id) { |
| 518 DCHECK(dest_surface || dx11_texture); | 556 DCHECK(dest_surface || dx11_texture); |
| 519 if (dx11_texture) { | 557 if (dx11_texture) { |
| 520 // Grab a reference on the decoder texture. This reference will be released | 558 // Grab a reference on the decoder texture. This reference will be released |
| 521 // when we receive a notification that the copy was completed or when the | 559 // when we receive a notification that the copy was completed or when the |
| 522 // DXVAPictureBuffer instance is destroyed. | 560 // DXVAPictureBuffer instance is destroyed. |
| 523 decoder_dx11_texture_ = dx11_texture; | 561 decoder_dx11_texture_ = dx11_texture; |
| 524 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), NULL, | 562 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), |
| 525 id(), input_buffer_id); | 563 dx11_keyed_mutex_, keyed_mutex_value_, NULL, id(), |
| 564 input_buffer_id); | |
| 526 return true; | 565 return true; |
| 527 } | 566 } |
| 528 D3DSURFACE_DESC surface_desc; | 567 D3DSURFACE_DESC surface_desc; |
| 529 HRESULT hr = dest_surface->GetDesc(&surface_desc); | 568 HRESULT hr = dest_surface->GetDesc(&surface_desc); |
| 530 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 569 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
| 531 | 570 |
| 532 D3DSURFACE_DESC texture_desc; | 571 D3DSURFACE_DESC texture_desc; |
| 533 decoding_texture_->GetLevelDesc(0, &texture_desc); | 572 decoding_texture_->GetLevelDesc(0, &texture_desc); |
| 534 | 573 |
| 535 if (texture_desc.Width != surface_desc.Width || | 574 if (texture_desc.Width != surface_desc.Width || |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 555 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive()); | 594 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive()); |
| 556 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); | 595 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); |
| 557 | 596 |
| 558 decoder_surface_ = dest_surface; | 597 decoder_surface_ = dest_surface; |
| 559 | 598 |
| 560 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), | 599 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), |
| 561 input_buffer_id); | 600 input_buffer_id); |
| 562 return true; | 601 return true; |
| 563 } | 602 } |
| 564 | 603 |
| 565 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete( | 604 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete( |
| 566 IDirect3DSurface9* src_surface, | 605 IDirect3DSurface9* src_surface, |
| 567 IDirect3DSurface9* dest_surface) { | 606 IDirect3DSurface9* dest_surface) { |
| 568 DCHECK(!available()); | 607 DCHECK(!available()); |
| 569 | 608 |
| 570 GLint current_texture = 0; | 609 GLint current_texture = 0; |
| 571 glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); | 610 glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); |
| 572 | 611 |
| 573 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); | 612 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); |
| 574 | 613 |
| 575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 614 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 576 | 615 |
| 577 if (src_surface && dest_surface) { | 616 if (src_surface && dest_surface) { |
| 578 DCHECK_EQ(src_surface, decoder_surface_.get()); | 617 DCHECK_EQ(src_surface, decoder_surface_.get()); |
| 579 DCHECK_EQ(dest_surface, target_surface_.get()); | 618 DCHECK_EQ(dest_surface, target_surface_.get()); |
| 580 decoder_surface_.Release(); | 619 decoder_surface_.Release(); |
| 581 target_surface_.Release(); | 620 target_surface_.Release(); |
| 582 } else { | 621 } else { |
| 583 DCHECK(decoder_dx11_texture_.get()); | 622 DCHECK(decoder_dx11_texture_.get()); |
| 584 decoder_dx11_texture_.Release(); | 623 decoder_dx11_texture_.Release(); |
| 585 } | 624 } |
| 625 if (egl_keyed_mutex_) { | |
| 626 keyed_mutex_value_++; | |
| 627 HRESULT result = | |
| 628 egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs); | |
| 629 if (result != S_OK) | |
| 630 return false; | |
| 631 } | |
| 586 | 632 |
| 587 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 633 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 588 eglBindTexImage( | 634 eglBindTexImage( |
| 589 egl_display, | 635 egl_display, |
| 590 decoding_surface_, | 636 decoding_surface_, |
| 591 EGL_BACK_BUFFER); | 637 EGL_BACK_BUFFER); |
| 592 | 638 |
| 593 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 639 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 594 glBindTexture(GL_TEXTURE_2D, current_texture); | 640 glBindTexture(GL_TEXTURE_2D, current_texture); |
| 641 return true; | |
| 595 } | 642 } |
| 596 | 643 |
| 597 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( | 644 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( |
| 598 int32 buffer_id, IMFSample* sample) | 645 int32 buffer_id, IMFSample* sample) |
| 599 : input_buffer_id(buffer_id), | 646 : input_buffer_id(buffer_id), |
| 600 picture_buffer_id(-1) { | 647 picture_buffer_id(-1) { |
| 601 output_sample.Attach(sample); | 648 output_sample.Attach(sample); |
| 602 } | 649 } |
| 603 | 650 |
| 604 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} | 651 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 939 it = stale_output_picture_buffers_.find(picture_buffer_id); | 986 it = stale_output_picture_buffers_.find(picture_buffer_id); |
| 940 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), | 987 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), |
| 941 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); | 988 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); |
| 942 main_thread_task_runner_->PostTask( | 989 main_thread_task_runner_->PostTask( |
| 943 FROM_HERE, | 990 FROM_HERE, |
| 944 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, | 991 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, |
| 945 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); | 992 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); |
| 946 return; | 993 return; |
| 947 } | 994 } |
| 948 | 995 |
| 949 it->second->ReusePictureBuffer(); | 996 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), |
| 997 "Failed to reuse picture buffer", | |
| 998 PLATFORM_FAILURE, ); | |
| 999 | |
| 950 ProcessPendingSamples(); | 1000 ProcessPendingSamples(); |
| 951 if (pending_flush_) { | 1001 if (pending_flush_) { |
| 952 decoder_thread_task_runner_->PostTask( | 1002 decoder_thread_task_runner_->PostTask( |
| 953 FROM_HERE, | 1003 FROM_HERE, |
| 954 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 1004 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
| 955 base::Unretained(this))); | 1005 base::Unretained(this))); |
| 956 } | 1006 } |
| 957 } | 1007 } |
| 958 | 1008 |
| 959 void DXVAVideoDecodeAccelerator::Flush() { | 1009 void DXVAVideoDecodeAccelerator::Flush() { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1216 // this. This should always be true for Windows 8+. | 1266 // this. This should always be true for Windows 8+. |
| 1217 // 3. ANGLE is using DX11. | 1267 // 3. ANGLE is using DX11. |
| 1218 DCHECK(gl_context_); | 1268 DCHECK(gl_context_); |
| 1219 if (create_dxgi_device_manager_ && | 1269 if (create_dxgi_device_manager_ && |
| 1220 (gl_context_->GetGLRenderer().find("Direct3D11") != | 1270 (gl_context_->GetGLRenderer().find("Direct3D11") != |
| 1221 std::string::npos)) { | 1271 std::string::npos)) { |
| 1222 UINT32 dx11_aware = 0; | 1272 UINT32 dx11_aware = 0; |
| 1223 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); | 1273 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); |
| 1224 use_dx11_ = !!dx11_aware; | 1274 use_dx11_ = !!dx11_aware; |
| 1225 } | 1275 } |
| 1276 | |
| 1277 use_keyed_mutex_ = | |
| 1278 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex"); | |
| 1279 | |
| 1226 return true; | 1280 return true; |
| 1227 } | 1281 } |
| 1228 | 1282 |
| 1229 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() { | 1283 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() { |
| 1230 RETURN_ON_FAILURE(SetDecoderInputMediaType(), | 1284 RETURN_ON_FAILURE(SetDecoderInputMediaType(), |
| 1231 "Failed to set decoder input media type", false); | 1285 "Failed to set decoder input media type", false); |
| 1232 return SetDecoderOutputMediaType(MFVideoFormat_NV12); | 1286 return SetDecoderOutputMediaType(MFVideoFormat_NV12); |
| 1233 } | 1287 } |
| 1234 | 1288 |
| 1235 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { | 1289 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1930 // was a Reset operation which dropped the output frame. | 1984 // was a Reset operation which dropped the output frame. |
| 1931 DXVAPictureBuffer* picture_buffer = it->second.get(); | 1985 DXVAPictureBuffer* picture_buffer = it->second.get(); |
| 1932 if (picture_buffer->available()) | 1986 if (picture_buffer->available()) |
| 1933 return; | 1987 return; |
| 1934 | 1988 |
| 1935 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1989 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), |
| 1936 "Failed to make context current", PLATFORM_FAILURE,); | 1990 "Failed to make context current", PLATFORM_FAILURE,); |
| 1937 | 1991 |
| 1938 DCHECK(!output_picture_buffers_.empty()); | 1992 DCHECK(!output_picture_buffers_.empty()); |
| 1939 | 1993 |
| 1940 picture_buffer->CopySurfaceComplete(src_surface, | 1994 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
| 1941 dest_surface); | 1995 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
| 1996 PLATFORM_FAILURE, ); | |
| 1942 | 1997 |
| 1943 NotifyPictureReady(picture_buffer->id(), input_buffer_id); | 1998 NotifyPictureReady(picture_buffer->id(), input_buffer_id); |
| 1944 | 1999 |
| 1945 { | 2000 { |
| 1946 base::AutoLock lock(decoder_lock_); | 2001 base::AutoLock lock(decoder_lock_); |
| 1947 if (!pending_output_samples_.empty()) | 2002 if (!pending_output_samples_.empty()) |
| 1948 pending_output_samples_.pop_front(); | 2003 pending_output_samples_.pop_front(); |
| 1949 } | 2004 } |
| 1950 | 2005 |
| 1951 if (pending_flush_) { | 2006 if (pending_flush_) { |
| 1952 decoder_thread_task_runner_->PostTask( | 2007 decoder_thread_task_runner_->PostTask( |
| 1953 FROM_HERE, | 2008 FROM_HERE, |
| 1954 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 2009 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
| 1955 base::Unretained(this))); | 2010 base::Unretained(this))); |
| 1956 return; | 2011 return; |
| 1957 } | 2012 } |
| 1958 decoder_thread_task_runner_->PostTask( | 2013 decoder_thread_task_runner_->PostTask( |
| 1959 FROM_HERE, | 2014 FROM_HERE, |
| 1960 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2015 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 1961 base::Unretained(this))); | 2016 base::Unretained(this))); |
| 1962 } | 2017 } |
| 1963 | 2018 |
| 1964 void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture, | 2019 void DXVAVideoDecodeAccelerator::CopyTexture( |
| 1965 ID3D11Texture2D* dest_texture, | 2020 ID3D11Texture2D* src_texture, |
| 1966 IMFSample* video_frame, | 2021 ID3D11Texture2D* dest_texture, |
| 1967 int picture_buffer_id, | 2022 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex, |
| 1968 int input_buffer_id) { | 2023 uint64_t keyed_mutex_value, |
| 2024 IMFSample* video_frame, | |
| 2025 int picture_buffer_id, | |
| 2026 int input_buffer_id) { | |
| 1969 HRESULT hr = E_FAIL; | 2027 HRESULT hr = E_FAIL; |
| 1970 | 2028 |
| 1971 DCHECK(use_dx11_); | 2029 DCHECK(use_dx11_); |
| 1972 | 2030 |
| 1973 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { | 2031 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { |
| 1974 // The media foundation H.264 decoder outputs YUV12 textures which we | 2032 // The media foundation H.264 decoder outputs YUV12 textures which we |
| 1975 // cannot copy into ANGLE as they expect ARGB textures. In D3D land | 2033 // cannot copy into ANGLE as they expect ARGB textures. In D3D land |
| 1976 // the StretchRect API in the IDirect3DDevice9Ex interface did the color | 2034 // the StretchRect API in the IDirect3DDevice9Ex interface did the color |
| 1977 // space conversion for us. Sadly in DX11 land the API does not provide | 2035 // space conversion for us. Sadly in DX11 land the API does not provide |
| 1978 // a straightforward way to do this. | 2036 // a straightforward way to do this. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1995 | 2053 |
| 1996 // The input to the video processor is the output sample. | 2054 // The input to the video processor is the output sample. |
| 1997 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; | 2055 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; |
| 1998 { | 2056 { |
| 1999 base::AutoLock lock(decoder_lock_); | 2057 base::AutoLock lock(decoder_lock_); |
| 2000 PendingSampleInfo& sample_info = pending_output_samples_.front(); | 2058 PendingSampleInfo& sample_info = pending_output_samples_.front(); |
| 2001 input_sample_for_conversion = sample_info.output_sample; | 2059 input_sample_for_conversion = sample_info.output_sample; |
| 2002 } | 2060 } |
| 2003 | 2061 |
| 2004 decoder_thread_task_runner_->PostTask( | 2062 decoder_thread_task_runner_->PostTask( |
| 2005 FROM_HERE, | 2063 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture, |
| 2006 base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture, | 2064 base::Unretained(this), src_texture, dest_texture, |
| 2007 base::Unretained(this), | 2065 dest_keyed_mutex, keyed_mutex_value, |
| 2008 src_texture, | 2066 input_sample_for_conversion.Detach(), |
| 2009 dest_texture, | 2067 picture_buffer_id, input_buffer_id)); |
| 2010 input_sample_for_conversion.Detach(), | |
| 2011 picture_buffer_id, | |
| 2012 input_buffer_id)); | |
| 2013 return; | 2068 return; |
| 2014 } | 2069 } |
| 2015 | 2070 |
| 2016 DCHECK(video_frame); | 2071 DCHECK(video_frame); |
| 2017 | 2072 |
| 2018 base::win::ScopedComPtr<IMFSample> input_sample; | 2073 base::win::ScopedComPtr<IMFSample> input_sample; |
| 2019 input_sample.Attach(video_frame); | 2074 input_sample.Attach(video_frame); |
| 2020 | 2075 |
| 2021 DCHECK(video_format_converter_mft_.get()); | 2076 DCHECK(video_format_converter_mft_.get()); |
| 2022 | 2077 |
| 2078 if (dest_keyed_mutex) { | |
| 2079 HRESULT hr = | |
| 2080 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs); | |
| 2081 RETURN_AND_NOTIFY_ON_FAILURE( | |
| 2082 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.", | |
| 2083 PLATFORM_FAILURE, ); | |
| 2084 } | |
| 2023 // The video processor MFT requires output samples to be allocated by the | 2085 // The video processor MFT requires output samples to be allocated by the |
| 2024 // caller. We create a sample with a buffer backed with the ID3D11Texture2D | 2086 // caller. We create a sample with a buffer backed with the ID3D11Texture2D |
| 2025 // interface exposed by ANGLE. This works nicely as this ensures that the | 2087 // interface exposed by ANGLE. This works nicely as this ensures that the |
| 2026 // video processor coverts the color space of the output frame and copies | 2088 // video processor coverts the color space of the output frame and copies |
| 2027 // the result into the ANGLE texture. | 2089 // the result into the ANGLE texture. |
| 2028 base::win::ScopedComPtr<IMFSample> output_sample; | 2090 base::win::ScopedComPtr<IMFSample> output_sample; |
| 2029 hr = MFCreateSample(output_sample.Receive()); | 2091 hr = MFCreateSample(output_sample.Receive()); |
| 2030 if (FAILED(hr)) { | 2092 if (FAILED(hr)) { |
| 2031 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2093 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
| 2032 "Failed to create output sample.", PLATFORM_FAILURE,); | 2094 "Failed to create output sample.", PLATFORM_FAILURE,); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2067 if (FAILED(hr)) { | 2129 if (FAILED(hr)) { |
| 2068 base::debug::Alias(&hr); | 2130 base::debug::Alias(&hr); |
| 2069 // TODO(ananta) | 2131 // TODO(ananta) |
| 2070 // Remove this CHECK when the change to use DX11 for H/W decoding | 2132 // Remove this CHECK when the change to use DX11 for H/W decoding |
| 2071 // stablizes. | 2133 // stablizes. |
| 2072 CHECK(false); | 2134 CHECK(false); |
| 2073 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, | 2135 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, |
| 2074 "Failed to convert output sample format.", PLATFORM_FAILURE,); | 2136 "Failed to convert output sample format.", PLATFORM_FAILURE,); |
| 2075 } | 2137 } |
| 2076 | 2138 |
| 2077 d3d11_device_context_->Flush(); | 2139 if (dest_keyed_mutex) { |
| 2078 d3d11_device_context_->End(d3d11_query_.get()); | 2140 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1); |
| 2141 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.", | |
| 2142 PLATFORM_FAILURE, ); | |
| 2079 | 2143 |
| 2080 decoder_thread_task_runner_->PostDelayedTask( | 2144 main_thread_task_runner_->PostTask( |
| 2081 FROM_HERE, | 2145 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete, |
| 2082 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, | 2146 weak_this_factory_.GetWeakPtr(), nullptr, nullptr, |
| 2083 base::Unretained(this), 0, | 2147 picture_buffer_id, input_buffer_id)); |
| 2084 reinterpret_cast<IDirect3DSurface9*>(NULL), | 2148 } else { |
| 2085 reinterpret_cast<IDirect3DSurface9*>(NULL), | 2149 d3d11_device_context_->Flush(); |
| 2086 picture_buffer_id, input_buffer_id), | 2150 d3d11_device_context_->End(d3d11_query_.get()); |
| 2087 base::TimeDelta::FromMilliseconds( | 2151 |
| 2088 kFlushDecoderSurfaceTimeoutMs)); | 2152 decoder_thread_task_runner_->PostDelayedTask( |
| 2153 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, | |
| 2154 base::Unretained(this), 0, | |
| 2155 reinterpret_cast<IDirect3DSurface9*>(NULL), | |
| 2156 reinterpret_cast<IDirect3DSurface9*>(NULL), | |
| 2157 picture_buffer_id, input_buffer_id), | |
| 2158 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); | |
| 2159 } | |
| 2089 } | 2160 } |
| 2090 | 2161 |
| 2091 void DXVAVideoDecodeAccelerator::FlushDecoder( | 2162 void DXVAVideoDecodeAccelerator::FlushDecoder( |
| 2092 int iterations, | 2163 int iterations, |
| 2093 IDirect3DSurface9* src_surface, | 2164 IDirect3DSurface9* src_surface, |
| 2094 IDirect3DSurface9* dest_surface, | 2165 IDirect3DSurface9* dest_surface, |
| 2095 int picture_buffer_id, | 2166 int picture_buffer_id, |
| 2096 int input_buffer_id) { | 2167 int input_buffer_id) { |
| 2097 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 2168 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2098 | 2169 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2300 D3DSURFACE_DESC surface_desc; | 2371 D3DSURFACE_DESC surface_desc; |
| 2301 hr = surface->GetDesc(&surface_desc); | 2372 hr = surface->GetDesc(&surface_desc); |
| 2302 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2373 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
| 2303 *width = surface_desc.Width; | 2374 *width = surface_desc.Width; |
| 2304 *height = surface_desc.Height; | 2375 *height = surface_desc.Height; |
| 2305 } | 2376 } |
| 2306 return true; | 2377 return true; |
| 2307 } | 2378 } |
| 2308 | 2379 |
| 2309 } // namespace content | 2380 } // namespace content |
| OLD | NEW |