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 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( | 808 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( |
809 int32_t buffer_id, | 809 int32_t buffer_id, |
810 IMFSample* sample) | 810 IMFSample* sample) |
811 : input_buffer_id(buffer_id), picture_buffer_id(-1) { | 811 : input_buffer_id(buffer_id), picture_buffer_id(-1) { |
812 output_sample.Attach(sample); | 812 output_sample.Attach(sample); |
813 } | 813 } |
814 | 814 |
815 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} | 815 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} |
816 | 816 |
817 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( | 817 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
818 const base::Callback<bool(void)>& make_context_current, | 818 const GetGLContextCallback& get_gl_context_cb, |
819 gfx::GLContext* gl_context, | 819 const MakeGLContextCurrentCallback& make_context_current_cb, |
820 bool enable_accelerated_vpx_decode) | 820 bool enable_accelerated_vpx_decode) |
821 : client_(NULL), | 821 : client_(NULL), |
822 dev_manager_reset_token_(0), | 822 dev_manager_reset_token_(0), |
823 dx11_dev_manager_reset_token_(0), | 823 dx11_dev_manager_reset_token_(0), |
824 egl_config_(NULL), | 824 egl_config_(NULL), |
825 state_(kUninitialized), | 825 state_(kUninitialized), |
826 pictures_requested_(false), | 826 pictures_requested_(false), |
827 inputs_before_decode_(0), | 827 inputs_before_decode_(0), |
828 sent_drain_message_(false), | 828 sent_drain_message_(false), |
829 make_context_current_(make_context_current), | 829 get_gl_context_cb_(get_gl_context_cb), |
| 830 make_context_current_cb_(make_context_current_cb), |
830 codec_(media::kUnknownVideoCodec), | 831 codec_(media::kUnknownVideoCodec), |
831 decoder_thread_("DXVAVideoDecoderThread"), | 832 decoder_thread_("DXVAVideoDecoderThread"), |
832 pending_flush_(false), | 833 pending_flush_(false), |
833 use_dx11_(false), | 834 use_dx11_(false), |
834 use_keyed_mutex_(false), | 835 use_keyed_mutex_(false), |
835 dx11_video_format_converter_media_type_needs_init_(true), | 836 dx11_video_format_converter_media_type_needs_init_(true), |
836 gl_context_(gl_context), | |
837 using_angle_device_(false), | 837 using_angle_device_(false), |
838 enable_accelerated_vpx_decode_(enable_accelerated_vpx_decode), | 838 enable_accelerated_vpx_decode_(enable_accelerated_vpx_decode), |
839 weak_this_factory_(this) { | 839 weak_this_factory_(this) { |
840 weak_ptr_ = weak_this_factory_.GetWeakPtr(); | 840 weak_ptr_ = weak_this_factory_.GetWeakPtr(); |
841 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); | 841 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
842 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); | 842 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); |
843 } | 843 } |
844 | 844 |
845 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { | 845 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { |
846 client_ = NULL; | 846 client_ = NULL; |
847 } | 847 } |
848 | 848 |
849 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, | 849 bool DXVAVideoDecodeAccelerator::Initialize(const Config& config, |
850 Client* client) { | 850 Client* client) { |
| 851 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
| 852 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 853 return false; |
| 854 } |
| 855 |
851 if (config.is_encrypted) { | 856 if (config.is_encrypted) { |
852 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 857 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
853 return false; | 858 return false; |
854 } | 859 } |
855 | 860 |
856 client_ = client; | 861 client_ = client; |
857 | 862 |
858 main_thread_task_runner_ = base::MessageLoop::current()->task_runner(); | 863 main_thread_task_runner_ = base::MessageLoop::current()->task_runner(); |
859 | 864 |
860 bool profile_supported = false; | 865 bool profile_supported = false; |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1207 "Failed to reuse picture buffer", | 1212 "Failed to reuse picture buffer", |
1208 PLATFORM_FAILURE, ); | 1213 PLATFORM_FAILURE, ); |
1209 | 1214 |
1210 ProcessPendingSamples(); | 1215 ProcessPendingSamples(); |
1211 if (pending_flush_) { | 1216 if (pending_flush_) { |
1212 decoder_thread_task_runner_->PostTask( | 1217 decoder_thread_task_runner_->PostTask( |
1213 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, | 1218 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
1214 base::Unretained(this))); | 1219 base::Unretained(this))); |
1215 } | 1220 } |
1216 } else { | 1221 } else { |
1217 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1222 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1218 "Failed to make context current", | 1223 "Failed to make context current", |
1219 PLATFORM_FAILURE, ); | 1224 PLATFORM_FAILURE, ); |
1220 it->second->ResetReuseFence(); | 1225 it->second->ResetReuseFence(); |
1221 | 1226 |
1222 WaitForOutputBuffer(picture_buffer_id, 0); | 1227 WaitForOutputBuffer(picture_buffer_id, 0); |
1223 } | 1228 } |
1224 } | 1229 } |
1225 | 1230 |
1226 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id, | 1231 void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id, |
1227 int count) { | 1232 int count) { |
1228 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1233 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1229 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 1234 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
1230 if (it == output_picture_buffers_.end()) | 1235 if (it == output_picture_buffers_.end()) |
1231 return; | 1236 return; |
1232 | 1237 |
1233 DXVAPictureBuffer* picture_buffer = it->second.get(); | 1238 DXVAPictureBuffer* picture_buffer = it->second.get(); |
1234 | 1239 |
1235 DCHECK(!picture_buffer->available()); | 1240 DCHECK(!picture_buffer->available()); |
1236 DCHECK(picture_buffer->waiting_to_reuse()); | 1241 DCHECK(picture_buffer->waiting_to_reuse()); |
1237 | 1242 |
1238 gfx::GLFence* fence = picture_buffer->reuse_fence(); | 1243 gfx::GLFence* fence = picture_buffer->reuse_fence(); |
1239 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1244 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1240 "Failed to make context current", | 1245 "Failed to make context current", |
1241 PLATFORM_FAILURE, ); | 1246 PLATFORM_FAILURE, ); |
1242 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) { | 1247 if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) { |
1243 main_thread_task_runner_->PostDelayedTask( | 1248 main_thread_task_runner_->PostDelayedTask( |
1244 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer, | 1249 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer, |
1245 weak_this_factory_.GetWeakPtr(), | 1250 weak_this_factory_.GetWeakPtr(), |
1246 picture_buffer_id, count + 1), | 1251 picture_buffer_id, count + 1), |
1247 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); | 1252 base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs)); |
1248 return; | 1253 return; |
1249 } | 1254 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 StartDecoderThread(); | 1328 StartDecoderThread(); |
1324 SetState(kNormal); | 1329 SetState(kNormal); |
1325 } | 1330 } |
1326 | 1331 |
1327 void DXVAVideoDecodeAccelerator::Destroy() { | 1332 void DXVAVideoDecodeAccelerator::Destroy() { |
1328 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1333 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1329 Invalidate(); | 1334 Invalidate(); |
1330 delete this; | 1335 delete this; |
1331 } | 1336 } |
1332 | 1337 |
1333 bool DXVAVideoDecodeAccelerator::CanDecodeOnIOThread() { | 1338 bool DXVAVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 1339 const base::WeakPtr<Client>& decode_client, |
| 1340 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
1334 return false; | 1341 return false; |
1335 } | 1342 } |
1336 | 1343 |
1337 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { | 1344 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { |
1338 return GL_BGRA_EXT; | 1345 return GL_BGRA_EXT; |
1339 } | 1346 } |
1340 | 1347 |
1341 // static | 1348 // static |
1342 media::VideoDecodeAccelerator::SupportedProfiles | 1349 media::VideoDecodeAccelerator::SupportedProfiles |
1343 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { | 1350 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); | 1514 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); |
1508 } | 1515 } |
1509 | 1516 |
1510 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); | 1517 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); |
1511 if (SUCCEEDED(hr)) { | 1518 if (SUCCEEDED(hr)) { |
1512 DVLOG(1) << "Successfully set Low latency mode on decoder."; | 1519 DVLOG(1) << "Successfully set Low latency mode on decoder."; |
1513 } else { | 1520 } else { |
1514 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; | 1521 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; |
1515 } | 1522 } |
1516 | 1523 |
| 1524 auto gl_context = get_gl_context_cb_.Run(); |
| 1525 RETURN_ON_FAILURE(gl_context, "Couldn't get GL context", false); |
| 1526 |
1517 // The decoder should use DX11 iff | 1527 // The decoder should use DX11 iff |
1518 // 1. The underlying H/W decoder supports it. | 1528 // 1. The underlying H/W decoder supports it. |
1519 // 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for | 1529 // 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for |
1520 // this. This should always be true for Windows 8+. | 1530 // this. This should always be true for Windows 8+. |
1521 // 3. ANGLE is using DX11. | 1531 // 3. ANGLE is using DX11. |
1522 DCHECK(gl_context_); | |
1523 if (create_dxgi_device_manager_ && | 1532 if (create_dxgi_device_manager_ && |
1524 (gl_context_->GetGLRenderer().find("Direct3D11") != | 1533 (gl_context->GetGLRenderer().find("Direct3D11") != std::string::npos)) { |
1525 std::string::npos)) { | |
1526 UINT32 dx11_aware = 0; | 1534 UINT32 dx11_aware = 0; |
1527 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); | 1535 attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware); |
1528 use_dx11_ = !!dx11_aware; | 1536 use_dx11_ = !!dx11_aware; |
1529 } | 1537 } |
1530 | 1538 |
1531 use_keyed_mutex_ = | 1539 use_keyed_mutex_ = |
1532 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex"); | 1540 use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex"); |
1533 | 1541 |
1534 return true; | 1542 return true; |
1535 } | 1543 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1717 pictures_requested_ = true; | 1725 pictures_requested_ = true; |
1718 return true; | 1726 return true; |
1719 } | 1727 } |
1720 | 1728 |
1721 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { | 1729 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { |
1722 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1730 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1723 | 1731 |
1724 if (!output_picture_buffers_.size()) | 1732 if (!output_picture_buffers_.size()) |
1725 return; | 1733 return; |
1726 | 1734 |
1727 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 1735 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
1728 "Failed to make context current", PLATFORM_FAILURE,); | 1736 "Failed to make context current", |
| 1737 PLATFORM_FAILURE, ); |
1729 | 1738 |
1730 OutputBuffers::iterator index; | 1739 OutputBuffers::iterator index; |
1731 | 1740 |
1732 for (index = output_picture_buffers_.begin(); | 1741 for (index = output_picture_buffers_.begin(); |
1733 index != output_picture_buffers_.end() && | 1742 index != output_picture_buffers_.end() && |
1734 OutputSamplesPresent(); | 1743 OutputSamplesPresent(); |
1735 ++index) { | 1744 ++index) { |
1736 if (index->second->available()) { | 1745 if (index->second->available()) { |
1737 PendingSampleInfo* pending_sample = NULL; | 1746 PendingSampleInfo* pending_sample = NULL; |
1738 { | 1747 { |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2241 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 2250 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
2242 if (it == output_picture_buffers_.end()) | 2251 if (it == output_picture_buffers_.end()) |
2243 return; | 2252 return; |
2244 | 2253 |
2245 // If the picture buffer is marked as available it probably means that there | 2254 // If the picture buffer is marked as available it probably means that there |
2246 // was a Reset operation which dropped the output frame. | 2255 // was a Reset operation which dropped the output frame. |
2247 DXVAPictureBuffer* picture_buffer = it->second.get(); | 2256 DXVAPictureBuffer* picture_buffer = it->second.get(); |
2248 if (picture_buffer->available()) | 2257 if (picture_buffer->available()) |
2249 return; | 2258 return; |
2250 | 2259 |
2251 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(), | 2260 RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(), |
2252 "Failed to make context current", PLATFORM_FAILURE,); | 2261 "Failed to make context current", |
| 2262 PLATFORM_FAILURE, ); |
2253 | 2263 |
2254 DCHECK(!output_picture_buffers_.empty()); | 2264 DCHECK(!output_picture_buffers_.empty()); |
2255 | 2265 |
2256 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); | 2266 bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface); |
2257 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", | 2267 RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", |
2258 PLATFORM_FAILURE, ); | 2268 PLATFORM_FAILURE, ); |
2259 | 2269 |
2260 NotifyPictureReady(picture_buffer->id(), input_buffer_id); | 2270 NotifyPictureReady(picture_buffer->id(), input_buffer_id); |
2261 | 2271 |
2262 { | 2272 { |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 DismissStaleBuffers(true); | 2666 DismissStaleBuffers(true); |
2657 Invalidate(); | 2667 Invalidate(); |
2658 Initialize(config_, client_); | 2668 Initialize(config_, client_); |
2659 decoder_thread_task_runner_->PostTask( | 2669 decoder_thread_task_runner_->PostTask( |
2660 FROM_HERE, | 2670 FROM_HERE, |
2661 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2671 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
2662 base::Unretained(this))); | 2672 base::Unretained(this))); |
2663 } | 2673 } |
2664 | 2674 |
2665 } // namespace content | 2675 } // namespace content |
OLD | NEW |