OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" |
6 | 6 |
7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
10 | 10 |
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( | 668 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( |
669 int32_t buffer_id, | 669 int32_t buffer_id, |
670 IMFSample* sample) | 670 IMFSample* sample) |
671 : input_buffer_id(buffer_id), picture_buffer_id(-1) { | 671 : input_buffer_id(buffer_id), picture_buffer_id(-1) { |
672 output_sample.Attach(sample); | 672 output_sample.Attach(sample); |
673 } | 673 } |
674 | 674 |
675 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} | 675 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} |
676 | 676 |
677 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( | 677 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
678 const base::Callback<bool(void)>& make_context_current, | 678 const gpu_vda_helpers::GetGLContextCb& get_gl_context_cb, |
679 gfx::GLContext* gl_context) | 679 const gpu_vda_helpers::MakeGLContextCurrentCb& make_context_current_cb) |
680 : client_(NULL), | 680 : client_(NULL), |
681 dev_manager_reset_token_(0), | 681 dev_manager_reset_token_(0), |
682 dx11_dev_manager_reset_token_(0), | 682 dx11_dev_manager_reset_token_(0), |
683 egl_config_(NULL), | 683 egl_config_(NULL), |
684 state_(kUninitialized), | 684 state_(kUninitialized), |
685 pictures_requested_(false), | 685 pictures_requested_(false), |
686 inputs_before_decode_(0), | 686 inputs_before_decode_(0), |
687 sent_drain_message_(false), | 687 sent_drain_message_(false), |
688 make_context_current_(make_context_current), | 688 get_gl_context_cb_(get_gl_context_cb), |
| 689 make_context_current_cb_(make_context_current_cb), |
689 codec_(media::kUnknownVideoCodec), | 690 codec_(media::kUnknownVideoCodec), |
690 decoder_thread_("DXVAVideoDecoderThread"), | 691 decoder_thread_("DXVAVideoDecoderThread"), |
691 pending_flush_(false), | 692 pending_flush_(false), |
692 use_dx11_(false), | 693 use_dx11_(false), |
693 use_keyed_mutex_(false), | 694 use_keyed_mutex_(false), |
694 dx11_video_format_converter_media_type_needs_init_(true), | 695 dx11_video_format_converter_media_type_needs_init_(true), |
695 gl_context_(gl_context), | |
696 using_angle_device_(false), | 696 using_angle_device_(false), |
697 weak_this_factory_(this) { | 697 weak_this_factory_(this) { |
698 weak_ptr_ = weak_this_factory_.GetWeakPtr(); | 698 weak_ptr_ = weak_this_factory_.GetWeakPtr(); |
699 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); | 699 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
700 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); | 700 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); |
701 } | 701 } |
702 | 702 |
703 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { | 703 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { |
704 client_ = NULL; | 704 client_ = NULL; |
705 } | 705 } |
706 | 706 |
707 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, | 707 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, |
708 Client* client) { | 708 Client* client) { |
| 709 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
| 710 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 711 return false; |
| 712 } |
| 713 |
709 if (config.is_encrypted) { | 714 if (config.is_encrypted) { |
710 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 715 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
711 return false; | 716 return false; |
712 } | 717 } |
713 | 718 |
714 client_ = client; | 719 client_ = client; |
715 | 720 |
716 main_thread_task_runner_ = base::MessageLoop::current()->task_runner(); | 721 main_thread_task_runner_ = base::MessageLoop::current()->task_runner(); |
717 | 722 |
718 bool profile_supported = false; | 723 bool profile_supported = false; |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 "Failed to reuse picture buffer", | 1064 "Failed to reuse picture buffer", |
1060 PLATFORM_FAILURE, ); | 1065 PLATFORM_FAILURE, ); |
1061 | 1066 |
1062 ProcessPendingSamples(); | 1067 ProcessPendingSamples(); |
1063 if (pending_flush_) { | 1068 if (pending_flush_) { |
1064 decoder_thread_task_runner_->PostTask( | 1069 decoder_thread_task_runner_->PostTask( |
1065 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 1070 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
1066 base::Unretained(this))); | 1071 base::Unretained(this))); |
1067 } | 1072 } |
1068 } else { | 1073 } else { |
1069 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1074 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1070 "Failed to make context current", | 1075 "Failed to make context current", |
1071 PLATFORM_FAILURE, ); | 1076 PLATFORM_FAILURE, ); |
1072 it->second->ResetReuseFence(); | 1077 it->second->ResetReuseFence(); |
1073 | 1078 |
1074 WaitForOutputBuffer(picture_buffer_id, 0); | 1079 WaitForOutputBuffer(picture_buffer_id, 0); |
1075 } | 1080 } |
1076 } | 1081 } |
1077 | 1082 |
1078 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id, | 1083 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id, |
1079 int count) { | 1084 int count) { |
1080 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1085 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1081 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 1086 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
1082 if (it == output_picture_buffers_.end()) | 1087 if (it == output_picture_buffers_.end()) |
1083 return; | 1088 return; |
1084 | 1089 |
1085 DXVAPictureBuffer* picture_buffer = it->second.get(); | 1090 DXVAPictureBuffer* picture_buffer = it->second.get(); |
1086 | 1091 |
1087 DCHECK(!picture_buffer->available()); | 1092 DCHECK(!picture_buffer->available()); |
1088 DCHECK(picture_buffer->waiting_to_reuse()); | 1093 DCHECK(picture_buffer->waiting_to_reuse()); |
1089 | 1094 |
1090 gfx::GLFence* fence = picture_buffer->reuse_fence(); | 1095 gfx::GLFence* fence = picture_buffer->reuse_fence(); |
1091 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1096 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1092 "Failed to make context current", | 1097 "Failed to make context current", |
1093 PLATFORM_FAILURE, ); | 1098 PLATFORM_FAILURE, ); |
1094 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) { | 1099 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) { |
1095 main_thread_task_runner_->PostDelayedTask( | 1100 main_thread_task_runner_->PostDelayedTask( |
1096 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer, | 1101 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer, |
1097 weak_this_factory_.GetWeakPtr(), | 1102 weak_this_factory_.GetWeakPtr(), |
1098 picture_buffer_id, count + 1), | 1103 picture_buffer_id, count + 1), |
1099 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); | 1104 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); |
1100 return; | 1105 return; |
1101 } | 1106 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 StartDecoderThread(); | 1180 StartDecoderThread(); |
1176 SetState(kNormal); | 1181 SetState(kNormal); |
1177 } | 1182 } |
1178 | 1183 |
1179 void DXVAVideoDecodeAccelerator::Destroy() { | 1184 void DXVAVideoDecodeAccelerator::Destroy() { |
1180 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1185 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1181 Invalidate(); | 1186 Invalidate(); |
1182 delete this; | 1187 delete this; |
1183 } | 1188 } |
1184 | 1189 |
1185 bool DXVAVideoDecodeAccelerator::CanDecodeOnIOThread() { | 1190 bool DXVAVideoDecodeAccelerator::TryInitializeDecodeOnSeparateThread( |
| 1191 const base::WeakPtr<Client>& decode_client, |
| 1192 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
1186 return false; | 1193 return false; |
1187 } | 1194 } |
1188 | 1195 |
1189 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { | 1196 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { |
1190 return GL_BGRA_EXT; | 1197 return GL_BGRA_EXT; |
1191 } | 1198 } |
1192 | 1199 |
1193 // static | 1200 // static |
1194 media::VideoDecodeAccelerator::SupportedProfiles | 1201 media::VideoDecodeAccelerator::SupportedProfiles |
1195 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { | 1202 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); | 1367 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); |
1361 } | 1368 } |
1362 | 1369 |
1363 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); | 1370 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); |
1364 if (SUCCEEDED(hr)) { | 1371 if (SUCCEEDED(hr)) { |
1365 DVLOG(1) << "Successfully set Low latency mode on decoder."; | 1372 DVLOG(1) << "Successfully set Low latency mode on decoder."; |
1366 } else { | 1373 } else { |
1367 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; | 1374 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; |
1368 } | 1375 } |
1369 | 1376 |
| 1377 auto gl_context = get_gl_context_cb_.Run(); |
| 1378 RETURN_ON_FAILURE(gl_context, "Couldn't get GL context", false); |
| 1379 |
1370 // The decoder should use DX11 iff | 1380 // The decoder should use DX11 iff |
1371 // 1. The underlying H/W decoder supports it. | 1381 // 1. The underlying H/W decoder supports it. |
1372 // 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for | 1382 // 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for |
1373 // this. This should always be true for Windows 8+. | 1383 // this. This should always be true for Windows 8+. |
1374 // 3. ANGLE is using DX11. | 1384 // 3. ANGLE is using DX11. |
1375 DCHECK(gl_context_); | |
1376 if (create_dxgi_device_manager_ && | 1385 if (create_dxgi_device_manager_ && |
1377 (gl_context_->GetGLRenderer().find("Direct3D11") != | 1386 (gl_context->GetGLRenderer().find("Direct3D11") != std::string::npos)) { |
1378 std::string::npos)) { | |
1379 UINT32 dx11_aware = 0; | 1387 UINT32 dx11_aware = 0; |
1380 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); | 1388 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); |
1381 use_dx11_ = !!dx11_aware; | 1389 use_dx11_ = !!dx11_aware; |
1382 } | 1390 } |
1383 | 1391 |
1384 use_keyed_mutex_ = | 1392 use_keyed_mutex_ = |
1385 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex"); | 1393 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex"); |
1386 | 1394 |
1387 return true; | 1395 return true; |
1388 } | 1396 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1570 pictures_requested_ = true; | 1578 pictures_requested_ = true; |
1571 return true; | 1579 return true; |
1572 } | 1580 } |
1573 | 1581 |
1574 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { | 1582 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { |
1575 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1583 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1576 | 1584 |
1577 if (!output_picture_buffers_.size()) | 1585 if (!output_picture_buffers_.size()) |
1578 return; | 1586 return; |
1579 | 1587 |
1580 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1588 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1581 "Failed to make context current", PLATFORM_FAILURE,); | 1589 "Failed to make context current", |
| 1590 PLATFORM_FAILURE, ); |
1582 | 1591 |
1583 OutputBuffers::iterator index; | 1592 OutputBuffers::iterator index; |
1584 | 1593 |
1585 for (index = output_picture_buffers_.begin(); | 1594 for (index = output_picture_buffers_.begin(); |
1586 index != output_picture_buffers_.end() && | 1595 index != output_picture_buffers_.end() && |
1587 OutputSamplesPresent(); | 1596 OutputSamplesPresent(); |
1588 ++index) { | 1597 ++index) { |
1589 if (index->second->available()) { | 1598 if (index->second->available()) { |
1590 PendingSampleInfo* pending_sample = NULL; | 1599 PendingSampleInfo* pending_sample = NULL; |
1591 { | 1600 { |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 2078 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
2070 if (it == output_picture_buffers_.end()) | 2079 if (it == output_picture_buffers_.end()) |
2071 return; | 2080 return; |
2072 | 2081 |
2073 // If the picture buffer is marked as available it probably means that there | 2082 // If the picture buffer is marked as available it probably means that there |
2074 // was a Reset operation which dropped the output frame. | 2083 // was a Reset operation which dropped the output frame. |
2075 DXVAPictureBuffer* picture_buffer = it->second.get(); | 2084 DXVAPictureBuffer* picture_buffer = it->second.get(); |
2076 if (picture_buffer->available()) | 2085 if (picture_buffer->available()) |
2077 return; | 2086 return; |
2078 | 2087 |
2079 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 2088 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
2080 "Failed to make context current", PLATFORM_FAILURE,); | 2089 "Failed to make context current", |
| 2090 PLATFORM_FAILURE, ); |
2081 | 2091 |
2082 DCHECK(!output_picture_buffers_.empty()); | 2092 DCHECK(!output_picture_buffers_.empty()); |
2083 | 2093 |
2084 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); | 2094 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
2085 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", | 2095 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
2086 PLATFORM_FAILURE, ); | 2096 PLATFORM_FAILURE, ); |
2087 | 2097 |
2088 NotifyPictureReady(picture_buffer->id(), input_buffer_id); | 2098 NotifyPictureReady(picture_buffer->id(), input_buffer_id); |
2089 | 2099 |
2090 { | 2100 { |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2456 } | 2466 } |
2457 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); | 2467 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
2458 return true; | 2468 return true; |
2459 } | 2469 } |
2460 media_type.Release(); | 2470 media_type.Release(); |
2461 } | 2471 } |
2462 return false; | 2472 return false; |
2463 } | 2473 } |
2464 | 2474 |
2465 } // namespace content | 2475 } // namespace content |
OLD | NEW |