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 |