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