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

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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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, &current_texture); 610 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_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
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
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
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
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
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
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
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