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

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, 11 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 if (hr != S_OK)
558 return false;
ananta 2016/01/26 23:09:16 Should we be logging errors here?
559 }
560 return true;
514 } 561 }
515 562
516 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer:: 563 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
517 CopyOutputSampleDataToPictureBuffer( 564 CopyOutputSampleDataToPictureBuffer(
518 DXVAVideoDecodeAccelerator* decoder, 565 DXVAVideoDecodeAccelerator* decoder,
519 IDirect3DSurface9* dest_surface, 566 IDirect3DSurface9* dest_surface,
520 ID3D11Texture2D* dx11_texture, 567 ID3D11Texture2D* dx11_texture,
521 int input_buffer_id) { 568 int input_buffer_id) {
522 DCHECK(dest_surface || dx11_texture); 569 DCHECK(dest_surface || dx11_texture);
523 if (dx11_texture) { 570 if (dx11_texture) {
524 // Grab a reference on the decoder texture. This reference will be released 571 // 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 572 // when we receive a notification that the copy was completed or when the
526 // DXVAPictureBuffer instance is destroyed. 573 // DXVAPictureBuffer instance is destroyed.
527 decoder_dx11_texture_ = dx11_texture; 574 decoder_dx11_texture_ = dx11_texture;
528 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), NULL, 575 decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(),
529 id(), input_buffer_id); 576 dx11_keyed_mutex_, keyed_mutex_value_, NULL, id(),
577 input_buffer_id);
530 return true; 578 return true;
531 } 579 }
532 D3DSURFACE_DESC surface_desc; 580 D3DSURFACE_DESC surface_desc;
533 HRESULT hr = dest_surface->GetDesc(&surface_desc); 581 HRESULT hr = dest_surface->GetDesc(&surface_desc);
534 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 582 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
535 583
536 D3DSURFACE_DESC texture_desc; 584 D3DSURFACE_DESC texture_desc;
537 decoding_texture_->GetLevelDesc(0, &texture_desc); 585 decoding_texture_->GetLevelDesc(0, &texture_desc);
538 586
539 if (texture_desc.Width != surface_desc.Width || 587 if (texture_desc.Width != surface_desc.Width ||
(...skipping 19 matching lines...) Expand all
559 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive()); 607 hr = decoding_texture_->GetSurfaceLevel(0, target_surface_.Receive());
560 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); 608 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
561 609
562 decoder_surface_ = dest_surface; 610 decoder_surface_ = dest_surface;
563 611
564 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), 612 decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(),
565 input_buffer_id); 613 input_buffer_id);
566 return true; 614 return true;
567 } 615 }
568 616
569 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete( 617 bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
570 IDirect3DSurface9* src_surface, 618 IDirect3DSurface9* src_surface,
571 IDirect3DSurface9* dest_surface) { 619 IDirect3DSurface9* dest_surface) {
572 DCHECK(!available()); 620 DCHECK(!available());
573 621
574 GLint current_texture = 0; 622 GLint current_texture = 0;
575 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); 623 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
576 624
577 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); 625 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
578 626
579 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 627 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
580 628
581 if (src_surface && dest_surface) { 629 if (src_surface && dest_surface) {
582 DCHECK_EQ(src_surface, decoder_surface_.get()); 630 DCHECK_EQ(src_surface, decoder_surface_.get());
583 DCHECK_EQ(dest_surface, target_surface_.get()); 631 DCHECK_EQ(dest_surface, target_surface_.get());
584 decoder_surface_.Release(); 632 decoder_surface_.Release();
585 target_surface_.Release(); 633 target_surface_.Release();
586 } else { 634 } else {
587 DCHECK(decoder_dx11_texture_.get()); 635 DCHECK(decoder_dx11_texture_.get());
588 decoder_dx11_texture_.Release(); 636 decoder_dx11_texture_.Release();
589 } 637 }
638 if (egl_keyed_mutex_) {
639 keyed_mutex_value_++;
640 HRESULT result =
641 egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
642 if (result != S_OK)
ananta 2016/01/26 23:09:16 Ditto for logging errors
643 return false;
644 }
590 645
591 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); 646 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
592 eglBindTexImage( 647 eglBindTexImage(
593 egl_display, 648 egl_display,
594 decoding_surface_, 649 decoding_surface_,
595 EGL_BACK_BUFFER); 650 EGL_BACK_BUFFER);
596 651
597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
598 glBindTexture(GL_TEXTURE_2D, current_texture); 653 glBindTexture(GL_TEXTURE_2D, current_texture);
654 return true;
599 } 655 }
600 656
601 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( 657 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
602 int32_t buffer_id, 658 int32_t buffer_id,
603 IMFSample* sample) 659 IMFSample* sample)
604 : input_buffer_id(buffer_id), picture_buffer_id(-1) { 660 : input_buffer_id(buffer_id), picture_buffer_id(-1) {
605 output_sample.Attach(sample); 661 output_sample.Attach(sample);
606 } 662 }
607 663
608 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} 664 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); 1015 it = stale_output_picture_buffers_.find(picture_buffer_id);
960 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), 1016 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
961 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); 1017 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
962 main_thread_task_runner_->PostTask( 1018 main_thread_task_runner_->PostTask(
963 FROM_HERE, 1019 FROM_HERE,
964 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, 1020 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
965 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); 1021 weak_this_factory_.GetWeakPtr(), picture_buffer_id));
966 return; 1022 return;
967 } 1023 }
968 1024
969 it->second->ReusePictureBuffer(); 1025 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
1026 "Failed to reuse picture buffer",
1027 PLATFORM_FAILURE, );
1028
970 ProcessPendingSamples(); 1029 ProcessPendingSamples();
971 if (pending_flush_) { 1030 if (pending_flush_) {
972 decoder_thread_task_runner_->PostTask( 1031 decoder_thread_task_runner_->PostTask(
973 FROM_HERE, 1032 FROM_HERE,
974 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 1033 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
975 base::Unretained(this))); 1034 base::Unretained(this)));
976 } 1035 }
977 } 1036 }
978 1037
979 void DXVAVideoDecodeAccelerator::Flush() { 1038 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+. 1295 // this. This should always be true for Windows 8+.
1237 // 3. ANGLE is using DX11. 1296 // 3. ANGLE is using DX11.
1238 DCHECK(gl_context_); 1297 DCHECK(gl_context_);
1239 if (create_dxgi_device_manager_ && 1298 if (create_dxgi_device_manager_ &&
1240 (gl_context_->GetGLRenderer().find("Direct3D11") != 1299 (gl_context_->GetGLRenderer().find("Direct3D11") !=
1241 std::string::npos)) { 1300 std::string::npos)) {
1242 UINT32 dx11_aware = 0; 1301 UINT32 dx11_aware = 0;
1243 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); 1302 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware);
1244 use_dx11_ = !!dx11_aware; 1303 use_dx11_ = !!dx11_aware;
1245 } 1304 }
1305
1306 use_keyed_mutex_ =
1307 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex");
1308
1246 return true; 1309 return true;
1247 } 1310 }
1248 1311
1249 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() { 1312 bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() {
1250 RETURN_ON_FAILURE(SetDecoderInputMediaType(), 1313 RETURN_ON_FAILURE(SetDecoderInputMediaType(),
1251 "Failed to set decoder input media type", false); 1314 "Failed to set decoder input media type", false);
1252 return SetDecoderOutputMediaType(MFVideoFormat_NV12); 1315 return SetDecoderOutputMediaType(MFVideoFormat_NV12);
1253 } 1316 }
1254 1317
1255 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { 1318 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. 1996 // was a Reset operation which dropped the output frame.
1934 DXVAPictureBuffer* picture_buffer = it->second.get(); 1997 DXVAPictureBuffer* picture_buffer = it->second.get();
1935 if (picture_buffer->available()) 1998 if (picture_buffer->available())
1936 return; 1999 return;
1937 2000
1938 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), 2001 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
1939 "Failed to make context current", PLATFORM_FAILURE,); 2002 "Failed to make context current", PLATFORM_FAILURE,);
1940 2003
1941 DCHECK(!output_picture_buffers_.empty()); 2004 DCHECK(!output_picture_buffers_.empty());
1942 2005
1943 picture_buffer->CopySurfaceComplete(src_surface, 2006 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface);
1944 dest_surface); 2007 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
2008 PLATFORM_FAILURE, );
1945 2009
1946 NotifyPictureReady(picture_buffer->id(), input_buffer_id); 2010 NotifyPictureReady(picture_buffer->id(), input_buffer_id);
1947 2011
1948 { 2012 {
1949 base::AutoLock lock(decoder_lock_); 2013 base::AutoLock lock(decoder_lock_);
1950 if (!pending_output_samples_.empty()) 2014 if (!pending_output_samples_.empty())
1951 pending_output_samples_.pop_front(); 2015 pending_output_samples_.pop_front();
1952 } 2016 }
1953 2017
1954 if (pending_flush_) { 2018 if (pending_flush_) {
1955 decoder_thread_task_runner_->PostTask( 2019 decoder_thread_task_runner_->PostTask(
1956 FROM_HERE, 2020 FROM_HERE,
1957 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, 2021 base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
1958 base::Unretained(this))); 2022 base::Unretained(this)));
1959 return; 2023 return;
1960 } 2024 }
1961 decoder_thread_task_runner_->PostTask( 2025 decoder_thread_task_runner_->PostTask(
1962 FROM_HERE, 2026 FROM_HERE,
1963 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2027 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
1964 base::Unretained(this))); 2028 base::Unretained(this)));
1965 } 2029 }
1966 2030
1967 void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture, 2031 void DXVAVideoDecodeAccelerator::CopyTexture(
1968 ID3D11Texture2D* dest_texture, 2032 ID3D11Texture2D* src_texture,
1969 IMFSample* video_frame, 2033 ID3D11Texture2D* dest_texture,
1970 int picture_buffer_id, 2034 base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
1971 int input_buffer_id) { 2035 uint64_t keyed_mutex_value,
2036 IMFSample* video_frame,
2037 int picture_buffer_id,
2038 int input_buffer_id) {
1972 HRESULT hr = E_FAIL; 2039 HRESULT hr = E_FAIL;
1973 2040
1974 DCHECK(use_dx11_); 2041 DCHECK(use_dx11_);
1975 2042
1976 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) { 2043 if (!decoder_thread_task_runner_->BelongsToCurrentThread()) {
1977 // The media foundation H.264 decoder outputs YUV12 textures which we 2044 // The media foundation H.264 decoder outputs YUV12 textures which we
1978 // cannot copy into ANGLE as they expect ARGB textures. In D3D land 2045 // cannot copy into ANGLE as they expect ARGB textures. In D3D land
1979 // the StretchRect API in the IDirect3DDevice9Ex interface did the color 2046 // the StretchRect API in the IDirect3DDevice9Ex interface did the color
1980 // space conversion for us. Sadly in DX11 land the API does not provide 2047 // space conversion for us. Sadly in DX11 land the API does not provide
1981 // a straightforward way to do this. 2048 // a straightforward way to do this.
(...skipping 16 matching lines...) Expand all
1998 2065
1999 // The input to the video processor is the output sample. 2066 // The input to the video processor is the output sample.
2000 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion; 2067 base::win::ScopedComPtr<IMFSample> input_sample_for_conversion;
2001 { 2068 {
2002 base::AutoLock lock(decoder_lock_); 2069 base::AutoLock lock(decoder_lock_);
2003 PendingSampleInfo& sample_info = pending_output_samples_.front(); 2070 PendingSampleInfo& sample_info = pending_output_samples_.front();
2004 input_sample_for_conversion = sample_info.output_sample; 2071 input_sample_for_conversion = sample_info.output_sample;
2005 } 2072 }
2006 2073
2007 decoder_thread_task_runner_->PostTask( 2074 decoder_thread_task_runner_->PostTask(
2008 FROM_HERE, 2075 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture,
2009 base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture, 2076 base::Unretained(this), src_texture, dest_texture,
2010 base::Unretained(this), 2077 dest_keyed_mutex, keyed_mutex_value,
2011 src_texture, 2078 input_sample_for_conversion.Detach(),
2012 dest_texture, 2079 picture_buffer_id, input_buffer_id));
2013 input_sample_for_conversion.Detach(),
2014 picture_buffer_id,
2015 input_buffer_id));
2016 return; 2080 return;
2017 } 2081 }
2018 2082
2019 DCHECK(video_frame); 2083 DCHECK(video_frame);
2020 2084
2021 base::win::ScopedComPtr<IMFSample> input_sample; 2085 base::win::ScopedComPtr<IMFSample> input_sample;
2022 input_sample.Attach(video_frame); 2086 input_sample.Attach(video_frame);
2023 2087
2024 DCHECK(video_format_converter_mft_.get()); 2088 DCHECK(video_format_converter_mft_.get());
2025 2089
2090 if (dest_keyed_mutex) {
2091 HRESULT hr =
2092 dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
2093 RETURN_AND_NOTIFY_ON_FAILURE(
2094 hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
2095 PLATFORM_FAILURE, );
2096 }
2026 // The video processor MFT requires output samples to be allocated by the 2097 // 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 2098 // 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 2099 // 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 2100 // video processor coverts the color space of the output frame and copies
2030 // the result into the ANGLE texture. 2101 // the result into the ANGLE texture.
2031 base::win::ScopedComPtr<IMFSample> output_sample; 2102 base::win::ScopedComPtr<IMFSample> output_sample;
2032 hr = MFCreateSample(output_sample.Receive()); 2103 hr = MFCreateSample(output_sample.Receive());
2033 if (FAILED(hr)) { 2104 if (FAILED(hr)) {
2034 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2105 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2035 "Failed to create output sample.", PLATFORM_FAILURE,); 2106 "Failed to create output sample.", PLATFORM_FAILURE,);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 if (FAILED(hr)) { 2141 if (FAILED(hr)) {
2071 base::debug::Alias(&hr); 2142 base::debug::Alias(&hr);
2072 // TODO(ananta) 2143 // TODO(ananta)
2073 // Remove this CHECK when the change to use DX11 for H/W decoding 2144 // Remove this CHECK when the change to use DX11 for H/W decoding
2074 // stablizes. 2145 // stablizes.
2075 CHECK(false); 2146 CHECK(false);
2076 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, 2147 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr,
2077 "Failed to convert output sample format.", PLATFORM_FAILURE,); 2148 "Failed to convert output sample format.", PLATFORM_FAILURE,);
2078 } 2149 }
2079 2150
2080 d3d11_device_context_->Flush(); 2151 if (dest_keyed_mutex) {
2081 d3d11_device_context_->End(d3d11_query_.get()); 2152 HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
2153 RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
2154 PLATFORM_FAILURE, );
2082 2155
2083 decoder_thread_task_runner_->PostDelayedTask( 2156 main_thread_task_runner_->PostTask(
2084 FROM_HERE, 2157 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
2085 base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, 2158 weak_this_factory_.GetWeakPtr(), nullptr, nullptr,
2086 base::Unretained(this), 0, 2159 picture_buffer_id, input_buffer_id));
2087 reinterpret_cast<IDirect3DSurface9*>(NULL), 2160 } else {
2088 reinterpret_cast<IDirect3DSurface9*>(NULL), 2161 d3d11_device_context_->Flush();
2089 picture_buffer_id, input_buffer_id), 2162 d3d11_device_context_->End(d3d11_query_.get());
2090 base::TimeDelta::FromMilliseconds( 2163
2091 kFlushDecoderSurfaceTimeoutMs)); 2164 decoder_thread_task_runner_->PostDelayedTask(
2165 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
2166 base::Unretained(this), 0,
2167 reinterpret_cast<IDirect3DSurface9*>(NULL),
2168 reinterpret_cast<IDirect3DSurface9*>(NULL),
2169 picture_buffer_id, input_buffer_id),
2170 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
2171 }
2092 } 2172 }
2093 2173
2094 void DXVAVideoDecodeAccelerator::FlushDecoder( 2174 void DXVAVideoDecodeAccelerator::FlushDecoder(
2095 int iterations, 2175 int iterations,
2096 IDirect3DSurface9* src_surface, 2176 IDirect3DSurface9* src_surface,
2097 IDirect3DSurface9* dest_surface, 2177 IDirect3DSurface9* dest_surface,
2098 int picture_buffer_id, 2178 int picture_buffer_id,
2099 int input_buffer_id) { 2179 int input_buffer_id) {
2100 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 2180 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2101 2181
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 } 2378 }
2299 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); 2379 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
2300 return true; 2380 return true;
2301 } 2381 }
2302 media_type.Release(); 2382 media_type.Release();
2303 } 2383 }
2304 return false; 2384 return false;
2305 } 2385 }
2306 2386
2307 } // namespace content 2387 } // 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