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 |