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

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

Issue 1553603002: Use IDXGIKeyedMutex to synchronize between DXVA decoder and main context (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // Maximum number of iterations we allow before aborting the attempt to flush 159 // Maximum number of iterations we allow before aborting the attempt to flush
160 // the batched queries to the driver and allow torn/corrupt frames to be 160 // the batched queries to the driver and allow torn/corrupt frames to be
161 // rendered. 161 // rendered.
162 kFlushDecoderSurfaceTimeoutMs = 1, 162 kFlushDecoderSurfaceTimeoutMs = 1,
163 // Maximum iterations where we try to flush the d3d device. 163 // Maximum iterations where we try to flush the d3d device.
164 kMaxIterationsForD3DFlush = 4, 164 kMaxIterationsForD3DFlush = 4,
165 // We only request 5 picture buffers from the client which are used to hold 165 // We only request 5 picture buffers from the client which are used to hold
166 // the decoded samples. These buffers are then reused when the client tells 166 // the decoded samples. These buffers are then reused when the client tells
167 // us that it is done with the buffer. 167 // us that it is done with the buffer.
168 kNumPictureBuffers = 5, 168 kNumPictureBuffers = 5,
169 // The keyed mutex should always be released before the other thread
170 // attempts to acquire it, so AcquireSync should always return immediately.
171 kAcquireSyncWaitMs = 0,
169 }; 172 };
170 173
171 static IMFSample* CreateEmptySample() { 174 static IMFSample* CreateEmptySample() {
172 base::win::ScopedComPtr<IMFSample> sample; 175 base::win::ScopedComPtr<IMFSample> sample;
173 HRESULT hr = MFCreateSample(sample.Receive()); 176 HRESULT hr = MFCreateSample(sample.Receive());
174 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); 177 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL);
175 return sample.Detach(); 178 return sample.Detach();
176 } 179 }
177 180
178 // Creates a Media Foundation sample with one buffer of length |buffer_length| 181 // Creates a Media Foundation sample with one buffer of length |buffer_length|
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 // Maintains information about a DXVA picture buffer, i.e. whether it is 345 // Maintains information about a DXVA picture buffer, i.e. whether it is
343 // available for rendering, the texture information, etc. 346 // available for rendering, the texture information, etc.
344 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { 347 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
345 public: 348 public:
346 static linked_ptr<DXVAPictureBuffer> Create( 349 static linked_ptr<DXVAPictureBuffer> Create(
347 const DXVAVideoDecodeAccelerator& decoder, 350 const DXVAVideoDecodeAccelerator& decoder,
348 const media::PictureBuffer& buffer, 351 const media::PictureBuffer& buffer,
349 EGLConfig egl_config); 352 EGLConfig egl_config);
350 ~DXVAPictureBuffer(); 353 ~DXVAPictureBuffer();
351 354
352 void ReusePictureBuffer(); 355 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
356 bool use_rgb);
357
358 bool ReusePictureBuffer();
353 // Copies the output sample data to the picture buffer provided by the 359 // Copies the output sample data to the picture buffer provided by the
354 // client. 360 // client.
355 // The dest_surface parameter contains the decoded bits. 361 // The dest_surface parameter contains the decoded bits.
356 bool CopyOutputSampleDataToPictureBuffer( 362 bool CopyOutputSampleDataToPictureBuffer(
357 DXVAVideoDecodeAccelerator* decoder, 363 DXVAVideoDecodeAccelerator* decoder,
358 IDirect3DSurface9* dest_surface, 364 IDirect3DSurface9* dest_surface,
359 ID3D11Texture2D* dx11_texture, 365 ID3D11Texture2D* dx11_texture,
360 int input_buffer_id); 366 int input_buffer_id);
361 367
362 bool available() const { 368 bool available() const {
363 return available_; 369 return available_;
364 } 370 }
365 371
366 void set_available(bool available) { 372 void set_available(bool available) {
367 available_ = available; 373 available_ = available;
368 } 374 }
369 375
370 int id() const { 376 int id() const {
371 return picture_buffer_.id(); 377 return picture_buffer_.id();
372 } 378 }
373 379
374 gfx::Size size() const { 380 gfx::Size size() const {
375 return picture_buffer_.size(); 381 return picture_buffer_.size();
376 } 382 }
377 383
378 // Called when the source surface |src_surface| is copied to the destination 384 // Called when the source surface |src_surface| is copied to the destination
379 // |dest_surface| 385 // |dest_surface|
380 void CopySurfaceComplete(IDirect3DSurface9* src_surface, 386 bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
381 IDirect3DSurface9* dest_surface); 387 IDirect3DSurface9* dest_surface);
382 388
383 private: 389 private:
384 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer); 390 explicit DXVAPictureBuffer(const media::PictureBuffer& buffer);
385 391
386 bool available_; 392 bool available_;
387 media::PictureBuffer picture_buffer_; 393 media::PictureBuffer picture_buffer_;
388 EGLSurface decoding_surface_; 394 EGLSurface decoding_surface_;
395
396 HANDLE texture_share_handle_;
389 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_; 397 base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_;
390 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_; 398 base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_;
391 399
400 base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
401 base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
402
403 // This is the last value that was used to release the keyed mutex.
404 uint64_t keyed_mutex_value_;
405
392 // The following |IDirect3DSurface9| interface pointers are used to hold 406 // The following |IDirect3DSurface9| interface pointers are used to hold
393 // references on the surfaces during the course of a StretchRect operation 407 // references on the surfaces during the course of a StretchRect operation
394 // to copy the source surface to the target. The references are released 408 // to copy the source surface to the target. The references are released
395 // when the StretchRect operation i.e. the copy completes. 409 // when the StretchRect operation i.e. the copy completes.
396 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_; 410 base::win::ScopedComPtr<IDirect3DSurface9> decoder_surface_;
397 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_; 411 base::win::ScopedComPtr<IDirect3DSurface9> target_surface_;
398 412
399 // This ID3D11Texture2D interface pointer is used to hold a reference to the 413 // This ID3D11Texture2D interface pointer is used to hold a reference to the
400 // decoder texture during the course of a copy operation. This reference is 414 // decoder texture during the course of a copy operation. This reference is
401 // released when the copy completes. 415 // released when the copy completes.
(...skipping 13 matching lines...) Expand all
415 const media::PictureBuffer& buffer, 429 const media::PictureBuffer& buffer,
416 EGLConfig egl_config) { 430 EGLConfig egl_config) {
417 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer)); 431 linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer));
418 432
419 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 433 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
420 434
421 EGLint use_rgb = 1; 435 EGLint use_rgb = 1;
422 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB, 436 eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB,
423 &use_rgb); 437 &use_rgb);
424 438
439 if (!picture_buffer->InitializeTexture(decoder, !!use_rgb))
440 return linked_ptr<DXVAPictureBuffer>(nullptr);
441
425 EGLint attrib_list[] = { 442 EGLint attrib_list[] = {
426 EGL_WIDTH, buffer.size().width(), 443 EGL_WIDTH, buffer.size().width(),
427 EGL_HEIGHT, buffer.size().height(), 444 EGL_HEIGHT, buffer.size().height(),
428 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, 445 EGL_TEXTURE_FORMAT, use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA,
429 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, 446 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
430 EGL_NONE 447 EGL_NONE
431 }; 448 };
432 449
433 picture_buffer->decoding_surface_ = eglCreatePbufferSurface( 450 picture_buffer->decoding_surface_ = eglCreatePbufferFromClientBuffer(
434 egl_display, 451 egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
435 egl_config, 452 picture_buffer->texture_share_handle_, egl_config, attrib_list);
436 attrib_list);
437 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, 453 RETURN_ON_FAILURE(picture_buffer->decoding_surface_,
438 "Failed to create surface", 454 "Failed to create surface",
439 linked_ptr<DXVAPictureBuffer>(NULL)); 455 linked_ptr<DXVAPictureBuffer>(NULL));
440 456 if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) {
441 HANDLE share_handle = NULL; 457 void* keyed_mutex = nullptr;
442 EGLBoolean ret = eglQuerySurfacePointerANGLE( 458 EGLBoolean ret = eglQuerySurfacePointerANGLE(
443 egl_display, 459 egl_display, picture_buffer->decoding_surface_,
444 picture_buffer->decoding_surface_, 460 EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex);
445 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, 461 RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE,
446 &share_handle); 462 "Failed to query ANGLE keyed mutex",
447 463 linked_ptr<DXVAPictureBuffer>(nullptr));
448 RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE, 464 picture_buffer->egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>(
449 "Failed to query ANGLE surface pointer", 465 static_cast<IDXGIKeyedMutex*>(keyed_mutex));
450 linked_ptr<DXVAPictureBuffer>(NULL));
451
452 HRESULT hr = E_FAIL;
453 if (decoder.d3d11_device_) {
454 base::win::ScopedComPtr<ID3D11Resource> resource;
455 hr = decoder.d3d11_device_->OpenSharedResource(
456 share_handle,
457 __uuidof(ID3D11Resource),
458 reinterpret_cast<void**>(resource.Receive()));
459 RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource",
460 linked_ptr<DXVAPictureBuffer>(NULL));
461 hr = picture_buffer->dx11_decoding_texture_.QueryFrom(resource.get());
462 } else {
463 hr = decoder.d3d9_device_ex_->CreateTexture(
464 buffer.size().width(),
465 buffer.size().height(),
466 1,
467 D3DUSAGE_RENDERTARGET,
468 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
469 D3DPOOL_DEFAULT,
470 picture_buffer->decoding_texture_.Receive(),
471 &share_handle);
472 } 466 }
473 RETURN_ON_HR_FAILURE(hr, "Failed to create texture",
474 linked_ptr<DXVAPictureBuffer>(NULL));
475 picture_buffer->use_rgb_ = !!use_rgb; 467 picture_buffer->use_rgb_ = !!use_rgb;
476 return picture_buffer; 468 return picture_buffer;
477 } 469 }
478 470
471 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::InitializeTexture(
472 const DXVAVideoDecodeAccelerator& decoder,
473 bool use_rgb) {
474 DCHECK(!texture_share_handle_);
475 if (decoder.d3d11_device_) {
476 D3D11_TEXTURE2D_DESC desc;
477 desc.Width = picture_buffer_.size().width();
478 desc.Height = picture_buffer_.size().height();
479 desc.MipLevels = 1;
480 desc.ArraySize = 1;
481 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
482 desc.SampleDesc.Count = 1;
483 desc.SampleDesc.Quality = 0;
484 desc.Usage = D3D11_USAGE_DEFAULT;
485 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
486 desc.CPUAccessFlags = 0;
487 desc.MiscFlags = decoder.use_keyed_mutex_
488 ? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
489 : D3D11_RESOURCE_MISC_SHARED;
490
491 HRESULT hr = decoder.d3d11_device_->CreateTexture2D(
492 &desc, nullptr, dx11_decoding_texture_.Receive());
493 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
494 if (decoder.use_keyed_mutex_) {
495 hr = dx11_keyed_mutex_.QueryFrom(dx11_decoding_texture_.get());
496 RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
497 }
498
499 base::win::ScopedComPtr<IDXGIResource> resource;
500 hr = resource.QueryFrom(dx11_decoding_texture_.get());
501 DCHECK(SUCCEEDED(hr));
502 hr = resource->GetSharedHandle(&texture_share_handle_);
503 RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
504 "Failed to query shared handle", false);
505
506 } else {
507 HRESULT hr = E_FAIL;
508 hr = decoder.d3d9_device_ex_->CreateTexture(
509 picture_buffer_.size().width(), picture_buffer_.size().height(), 1,
510 D3DUSAGE_RENDERTARGET, use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
511 D3DPOOL_DEFAULT, decoding_texture_.Receive(), &texture_share_handle_);
512 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
513 RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
514 false);
515 }
516 return true;
517 }
518
479 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( 519 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer(
480 const media::PictureBuffer& buffer) 520 const media::PictureBuffer& buffer)
481 : available_(true), 521 : available_(true),
482 picture_buffer_(buffer), 522 picture_buffer_(buffer),
483 decoding_surface_(NULL), 523 decoding_surface_(NULL),
484 use_rgb_(true) { 524 texture_share_handle_(nullptr),
485 } 525 keyed_mutex_value_(0),
526 use_rgb_(true) {}
486 527
487 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { 528 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
488 if (decoding_surface_) { 529 if (decoding_surface_) {
489 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 530 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
490 531
491 eglReleaseTexImage( 532 eglReleaseTexImage(
492 egl_display, 533 egl_display,
493 decoding_surface_, 534 decoding_surface_,
494 EGL_BACK_BUFFER); 535 EGL_BACK_BUFFER);
495 536
496 eglDestroySurface( 537 eglDestroySurface(
497 egl_display, 538 egl_display,
498 decoding_surface_); 539 decoding_surface_);
499 decoding_surface_ = NULL; 540 decoding_surface_ = NULL;
500 } 541 }
501 } 542 }
502 543
503 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { 544 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
504 DCHECK(decoding_surface_); 545 DCHECK(decoding_surface_);
505 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 546 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
506 eglReleaseTexImage( 547 eglReleaseTexImage(
507 egl_display, 548 egl_display,
508 decoding_surface_, 549 decoding_surface_,
509 EGL_BACK_BUFFER); 550 EGL_BACK_BUFFER);
510 decoder_surface_.Release(); 551 decoder_surface_.Release();
511 target_surface_.Release(); 552 target_surface_.Release();
512 decoder_dx11_texture_.Release(); 553 decoder_dx11_texture_.Release();
513 set_available(true); 554 set_available(true);
555 if (egl_keyed_mutex_) {
556 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
557 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
558 }
559 return true;
514 } 560 }
515 561
516 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: 562 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
517 CopyOutputSampleDataToPictureBuffer( 563 CopyOutputSampleDataToPictureBuffer(
518 DXVAVideoDecodeAccelerator* decoder, 564 DXVAVideoDecodeAccelerator* decoder,
519 IDirect3DSurface9* dest_surface, 565 IDirect3DSurface9* dest_surface,
520 ID3D11Texture2D* dx11_texture, 566 ID3D11Texture2D* dx11_texture,
521 int input_buffer_id) { 567 int input_buffer_id) {
522 DCHECK(dest_surface || dx11_texture); 568 DCHECK(dest_surface || dx11_texture);
523 if (dx11_texture) { 569 if (dx11_texture) {
524 // Grab a reference on the decoder texture. This reference will be released 570 // Grab a reference on the decoder texture. This reference will be released
525 // when we receive a notification that the copy was completed or when the 571 // when we receive a notification that the copy was completed or when the
526 // DXVAPictureBuffer instance is destroyed. 572 // DXVAPictureBuffer instance is destroyed.
527 decoder_dx11_texture_ = dx11_texture; 573 decoder_dx11_texture_ = dx11_texture;
528 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), NULL, 574 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(),
529 id(), input_buffer_id); 575 dx11_keyed_mutex_, keyed_mutex_value_, NULL, id(),
576 input_buffer_id);
530 return true; 577 return true;
531 } 578 }
532 D3DSURFACE_DESC surface_desc; 579 D3DSURFACE_DESC surface_desc;
533 HRESULT hr = dest_surface->GetDesc(&surface_desc); 580 HRESULT hr = dest_surface->GetDesc(&surface_desc);
534 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 581 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
535 582
536 D3DSURFACE_DESC texture_desc; 583 D3DSURFACE_DESC texture_desc;
537 decoding_texture_->GetLevelDesc(0, &texture_desc); 584 decoding_texture_->GetLevelDesc(0, &texture_desc);
538 585
539 if (texture_desc.Width != surface_desc.Width || 586 if (texture_desc.Width != surface_desc.Width ||
(...skipping 19 matching lines...) Expand all
559 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive()); 606 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive());
560 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); 607 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
561 608
562 decoder_surface_ = dest_surface; 609 decoder_surface_ = dest_surface;
563 610
564 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), 611 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(),
565 input_buffer_id); 612 input_buffer_id);
566 return true; 613 return true;
567 } 614 }
568 615
569 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete( 616 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
570 IDirect3DSurface9* src_surface, 617 IDirect3DSurface9* src_surface,
571 IDirect3DSurface9* dest_surface) { 618 IDirect3DSurface9* dest_surface) {
572 DCHECK(!available()); 619 DCHECK(!available());
573 620
574 GLint current_texture = 0; 621 GLint current_texture = 0;
575 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); 622 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
576 623
577 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); 624 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
578 625
579 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 626 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
580 627
581 if (src_surface && dest_surface) { 628 if (src_surface && dest_surface) {
582 DCHECK_EQ(src_surface, decoder_surface_.get()); 629 DCHECK_EQ(src_surface, decoder_surface_.get());
583 DCHECK_EQ(dest_surface, target_surface_.get()); 630 DCHECK_EQ(dest_surface, target_surface_.get());
584 decoder_surface_.Release(); 631 decoder_surface_.Release();
585 target_surface_.Release(); 632 target_surface_.Release();
586 } else { 633 } else {
587 DCHECK(decoder_dx11_texture_.get()); 634 DCHECK(decoder_dx11_texture_.get());
588 decoder_dx11_texture_.Release(); 635 decoder_dx11_texture_.Release();
589 } 636 }
637 if (egl_keyed_mutex_) {
638 keyed_mutex_value_++;
639 HRESULT result =
640 egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
641 RETURN_ON_FAILURE(result == S_OK, "Could not acquire sync mutex", false);
642 }
590 643
591 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 644 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
592 eglBindTexImage( 645 eglBindTexImage(
593 egl_display, 646 egl_display,
594 decoding_surface_, 647 decoding_surface_,
595 EGL_BACK_BUFFER); 648 EGL_BACK_BUFFER);
596 649
597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
598 glBindTexture(GL_TEXTURE_2D, current_texture); 651 glBindTexture(GL_TEXTURE_2D, current_texture);
652 return true;
599 } 653 }
600 654
601 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( 655 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
602 int32_t buffer_id, 656 int32_t buffer_id,
603 IMFSample* sample) 657 IMFSample* sample)
604 : input_buffer_id(buffer_id), picture_buffer_id(-1) { 658 : input_buffer_id(buffer_id), picture_buffer_id(-1) {
605 output_sample.Attach(sample); 659 output_sample.Attach(sample);
606 } 660 }
607 661
608 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} 662 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 it = stale_output_picture_buffers_.find(picture_buffer_id); 1013 it = stale_output_picture_buffers_.find(picture_buffer_id);
960 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), 1014 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
961 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); 1015 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
962 main_thread_task_runner_->PostTask( 1016 main_thread_task_runner_->PostTask(
963 FROM_HERE, 1017 FROM_HERE,
964 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, 1018 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
965 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); 1019 weak_this_factory_.GetWeakPtr(), picture_buffer_id));
966 return; 1020 return;
967 } 1021 }
968 1022
969 it->second->ReusePictureBuffer(); 1023 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
1024 "Failed to reuse picture buffer",
1025 PLATFORM_FAILURE, );
1026
970 ProcessPendingSamples(); 1027 ProcessPendingSamples();
971 if (pending_flush_) { 1028 if (pending_flush_) {
972 decoder_thread_task_runner_->PostTask( 1029 decoder_thread_task_runner_->PostTask(
973 FROM_HERE, 1030 FROM_HERE,
974 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 1031 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
975 base::Unretained(this))); 1032 base::Unretained(this)));
976 } 1033 }
977 } 1034 }
978 1035
979 void DXVAVideoDecodeAccelerator::Flush() { 1036 void DXVAVideoDecodeAccelerator::Flush() {
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 // this. This should always be true for Windows 8+. 1293 // this. This should always be true for Windows 8+.
1237 // 3. ANGLE is using DX11. 1294 // 3. ANGLE is using DX11.
1238 DCHECK(gl_context_); 1295 DCHECK(gl_context_);
1239 if (create_dxgi_device_manager_ && 1296 if (create_dxgi_device_manager_ &&
1240 (gl_context_->GetGLRenderer().find("Direct3D11") != 1297 (gl_context_->GetGLRenderer().find("Direct3D11") !=
1241 std::string::npos)) { 1298 std::string::npos)) {
1242 UINT32 dx11_aware = 0; 1299 UINT32 dx11_aware = 0;
1243 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); 1300 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware);
1244 use_dx11_ = !!dx11_aware; 1301 use_dx11_ = !!dx11_aware;
1245 } 1302 }
1303
1304 use_keyed_mutex_ =
ananta 2016/01/28 02:32:55 Please initialize this member in the ctor.
1305 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex");
1306
1246 return true; 1307 return true;
1247 } 1308 }
1248 1309
1249 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() { 1310 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() {
1250 RETURN_ON_FAILURE(SetDecoderInputMediaType(), 1311 RETURN_ON_FAILURE(SetDecoderInputMediaType(),
1251 "Failed to set decoder input media type", false); 1312 "Failed to set decoder input media type", false);
1252 return SetDecoderOutputMediaType(MFVideoFormat_NV12); 1313 return SetDecoderOutputMediaType(MFVideoFormat_NV12);
1253 } 1314 }
1254 1315
1255 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { 1316 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() {
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 // was a Reset operation which dropped the output frame. 1994 // was a Reset operation which dropped the output frame.
1934 DXVAPictureBuffer* picture_buffer = it->second.get(); 1995 DXVAPictureBuffer* picture_buffer = it->second.get();
1935 if (picture_buffer->available()) 1996 if (picture_buffer->available())
1936 return; 1997 return;
1937 1998
1938 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), 1999 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1939 "Failed to make context current", PLATFORM_FAILURE,); 2000 "Failed to make context current", PLATFORM_FAILURE,);
1940 2001
1941 DCHECK(!output_picture_buffers_.empty()); 2002 DCHECK(!output_picture_buffers_.empty());
1942 2003
1943 picture_buffer->CopySurfaceComplete(src_surface, 2004 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface);
1944 dest_surface); 2005 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
2006 PLATFORM_FAILURE, );
1945 2007
1946 NotifyPictureReady(picture_buffer->id(), input_buffer_id); 2008 NotifyPictureReady(picture_buffer->id(), input_buffer_id);
1947 2009
1948 { 2010 {
1949 base::AutoLock lock(decoder_lock_); 2011 base::AutoLock lock(decoder_lock_);
1950 if (!pending_output_samples_.empty()) 2012 if (!pending_output_samples_.empty())
1951 pending_output_samples_.pop_front(); 2013 pending_output_samples_.pop_front();
1952 } 2014 }
1953 2015
1954 if (pending_flush_) { 2016 if (pending_flush_) {
1955 decoder_thread_task_runner_->PostTask( 2017 decoder_thread_task_runner_->PostTask(
1956 FROM_HERE, 2018 FROM_HERE,
1957 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 2019 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1958 base::Unretained(this))); 2020 base::Unretained(this)));
1959 return; 2021 return;
1960 } 2022 }
1961 decoder_thread_task_runner_->PostTask( 2023 decoder_thread_task_runner_->PostTask(
1962 FROM_HERE, 2024 FROM_HERE,
1963 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2025 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
1964 base::Unretained(this))); 2026 base::Unretained(this)));
1965 } 2027 }
1966 2028
1967 void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture, 2029 void DXVAVideoDecodeAccelerator::CopyTexture(
1968 ID3D11Texture2D* dest_texture, 2030 ID3D11Texture2D* src_texture,
1969 IMFSample* video_frame, 2031 ID3D11Texture2D* dest_texture,
1970 int picture_buffer_id, 2032 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
1971 int input_buffer_id) { 2033 uint64_t keyed_mutex_value,
2034 IMFSample* video_frame,
2035 int picture_buffer_id,
2036 int input_buffer_id) {
1972 HRESULT hr = E_FAIL; 2037 HRESULT hr = E_FAIL;
1973 2038
1974 DCHECK(use_dx11_); 2039 DCHECK(use_dx11_);
1975 2040
1976 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { 2041 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) {
1977 // The media foundation H.264 decoder outputs YUV12 textures which we 2042 // The media foundation H.264 decoder outputs YUV12 textures which we
1978 // cannot copy into ANGLE as they expect ARGB textures. In D3D land 2043 // cannot copy into ANGLE as they expect ARGB textures. In D3D land
1979 // the StretchRect API in the IDirect3DDevice9Ex interface did the color 2044 // the StretchRect API in the IDirect3DDevice9Ex interface did the color
1980 // space conversion for us. Sadly in DX11 land the API does not provide 2045 // space conversion for us. Sadly in DX11 land the API does not provide
1981 // a straightforward way to do this. 2046 // a straightforward way to do this.
(...skipping 16 matching lines...) Expand all
1998 2063
1999 // The input to the video processor is the output sample. 2064 // The input to the video processor is the output sample.
2000 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; 2065 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion;
2001 { 2066 {
2002 base::AutoLock lock(decoder_lock_); 2067 base::AutoLock lock(decoder_lock_);
2003 PendingSampleInfo& sample_info = pending_output_samples_.front(); 2068 PendingSampleInfo& sample_info = pending_output_samples_.front();
2004 input_sample_for_conversion = sample_info.output_sample; 2069 input_sample_for_conversion = sample_info.output_sample;
2005 } 2070 }
2006 2071
2007 decoder_thread_task_runner_->PostTask( 2072 decoder_thread_task_runner_->PostTask(
2008 FROM_HERE, 2073 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture,
2009 base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture, 2074 base::Unretained(this), src_texture, dest_texture,
2010 base::Unretained(this), 2075 dest_keyed_mutex, keyed_mutex_value,
2011 src_texture, 2076 input_sample_for_conversion.Detach(),
2012 dest_texture, 2077 picture_buffer_id, input_buffer_id));
2013 input_sample_for_conversion.Detach(),
2014 picture_buffer_id,
2015 input_buffer_id));
2016 return; 2078 return;
2017 } 2079 }
2018 2080
2019 DCHECK(video_frame); 2081 DCHECK(video_frame);
2020 2082
2021 base::win::ScopedComPtr<IMFSample> input_sample; 2083 base::win::ScopedComPtr<IMFSample> input_sample;
2022 input_sample.Attach(video_frame); 2084 input_sample.Attach(video_frame);
2023 2085
2024 DCHECK(video_format_converter_mft_.get()); 2086 DCHECK(video_format_converter_mft_.get());
2025 2087
2088 if (dest_keyed_mutex) {
2089 HRESULT hr =
2090 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
2091 RETURN_AND_NOTIFY_ON_FAILURE(
2092 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
2093 PLATFORM_FAILURE, );
2094 }
2026 // The video processor MFT requires output samples to be allocated by the 2095 // The video processor MFT requires output samples to be allocated by the
2027 // caller. We create a sample with a buffer backed with the ID3D11Texture2D 2096 // caller. We create a sample with a buffer backed with the ID3D11Texture2D
2028 // interface exposed by ANGLE. This works nicely as this ensures that the 2097 // interface exposed by ANGLE. This works nicely as this ensures that the
2029 // video processor coverts the color space of the output frame and copies 2098 // video processor coverts the color space of the output frame and copies
2030 // the result into the ANGLE texture. 2099 // the result into the ANGLE texture.
2031 base::win::ScopedComPtr<IMFSample> output_sample; 2100 base::win::ScopedComPtr<IMFSample> output_sample;
2032 hr = MFCreateSample(output_sample.Receive()); 2101 hr = MFCreateSample(output_sample.Receive());
2033 if (FAILED(hr)) { 2102 if (FAILED(hr)) {
2034 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2103 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2035 "Failed to create output sample.", PLATFORM_FAILURE,); 2104 "Failed to create output sample.", PLATFORM_FAILURE,);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 if (FAILED(hr)) { 2139 if (FAILED(hr)) {
2071 base::debug::Alias(&hr); 2140 base::debug::Alias(&hr);
2072 // TODO(ananta) 2141 // TODO(ananta)
2073 // Remove this CHECK when the change to use DX11 for H/W decoding 2142 // Remove this CHECK when the change to use DX11 for H/W decoding
2074 // stablizes. 2143 // stablizes.
2075 CHECK(false); 2144 CHECK(false);
2076 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2145 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2077 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2146 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2078 } 2147 }
2079 2148
2080 d3d11_device_context_->Flush(); 2149 if (dest_keyed_mutex) {
2081 d3d11_device_context_->End(d3d11_query_.get()); 2150 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
2151 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
2152 PLATFORM_FAILURE, );
2082 2153
2083 decoder_thread_task_runner_->PostDelayedTask( 2154 main_thread_task_runner_->PostTask(
2084 FROM_HERE, 2155 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2085 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2156 weak_this_factory_.GetWeakPtr(), nullptr, nullptr,
2086 base::Unretained(this), 0, 2157 picture_buffer_id, input_buffer_id));
2087 reinterpret_cast<IDirect3DSurface9*>(NULL), 2158 } else {
2088 reinterpret_cast<IDirect3DSurface9*>(NULL), 2159 d3d11_device_context_->Flush();
2089 picture_buffer_id, input_buffer_id), 2160 d3d11_device_context_->End(d3d11_query_.get());
2090 base::TimeDelta::FromMilliseconds( 2161
2091 kFlushDecoderSurfaceTimeoutMs)); 2162 decoder_thread_task_runner_->PostDelayedTask(
2163 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2164 base::Unretained(this), 0,
2165 reinterpret_cast<IDirect3DSurface9*>(NULL),
2166 reinterpret_cast<IDirect3DSurface9*>(NULL),
2167 picture_buffer_id, input_buffer_id),
2168 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2169 }
2092 } 2170 }
2093 2171
2094 void DXVAVideoDecodeAccelerator::FlushDecoder( 2172 void DXVAVideoDecodeAccelerator::FlushDecoder(
2095 int iterations, 2173 int iterations,
2096 IDirect3DSurface9* src_surface, 2174 IDirect3DSurface9* src_surface,
2097 IDirect3DSurface9* dest_surface, 2175 IDirect3DSurface9* dest_surface,
2098 int picture_buffer_id, 2176 int picture_buffer_id,
2099 int input_buffer_id) { 2177 int input_buffer_id) {
2100 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2178 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2101 2179
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 } 2376 }
2299 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); 2377 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
2300 return true; 2378 return true;
2301 } 2379 }
2302 media_type.Release(); 2380 media_type.Release();
2303 } 2381 }
2304 return false; 2382 return false;
2305 } 2383 }
2306 2384
2307 } // namespace content 2385 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698