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