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.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, | 93 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, |
94 0xc9, 0x82); | 94 0xc9, 0x82); |
95 | 95 |
96 // MF_XVP_PLAYBACK_MODE | 96 // MF_XVP_PLAYBACK_MODE |
97 // Data type: UINT32 (treat as BOOL) | 97 // Data type: UINT32 (treat as BOOL) |
98 // If this attribute is TRUE, the video processor will run in playback mode | 98 // If this attribute is TRUE, the video processor will run in playback mode |
99 // where it allows callers to allocate output samples and allows last frame | 99 // where it allows callers to allocate output samples and allows last frame |
100 // regeneration (repaint). | 100 // regeneration (repaint). |
101 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, | 101 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, |
102 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); | 102 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); |
103 } | 103 |
104 } // namespace | |
104 | 105 |
105 namespace content { | 106 namespace content { |
106 | 107 |
107 static const media::VideoCodecProfile kSupportedProfiles[] = { | 108 static const media::VideoCodecProfile kSupportedProfiles[] = { |
108 media::H264PROFILE_BASELINE, | 109 media::H264PROFILE_BASELINE, |
109 media::H264PROFILE_MAIN, | 110 media::H264PROFILE_MAIN, |
110 media::H264PROFILE_HIGH, | 111 media::H264PROFILE_HIGH, |
111 media::VP8PROFILE_ANY, | 112 media::VP8PROFILE_ANY, |
112 media::VP9PROFILE_ANY | 113 media::VP9PROFILE_ANY |
113 }; | 114 }; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 base::SharedMemory shm(bitstream_buffer.handle(), true); | 235 base::SharedMemory shm(bitstream_buffer.handle(), true); |
235 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), | 236 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), |
236 "Failed in base::SharedMemory::Map", NULL); | 237 "Failed in base::SharedMemory::Map", NULL); |
237 | 238 |
238 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()), | 239 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()), |
239 bitstream_buffer.size(), | 240 bitstream_buffer.size(), |
240 stream_size, | 241 stream_size, |
241 alignment); | 242 alignment); |
242 } | 243 } |
243 | 244 |
245 // Helper function to create a COM object instance from a DLL. The alternative | |
246 // is to use the CoCreateInstance API which requires the COM apartment to be | |
247 // initialized which is not the case on the GPU main thread. We want to avoid | |
248 // initializing COM as it may have sideeffects. | |
249 HRESULT CreateCOMObjectFromDll(HMODULE dll, const CLSID& clsid, const IID& iid, | |
250 void** object) { | |
251 if (!dll || !object) | |
252 return E_INVALIDARG; | |
253 | |
254 typedef HRESULT(WINAPI * GetClassObject)( | |
DaleCurtis
2015/07/15 23:11:56
No space before & and * on all lines? If you want,
ananta
2015/07/15 23:15:01
eek. i dunno how i uploaded with this :(
Will uplo
ananta
2015/07/15 23:23:25
Done.
| |
255 const CLSID & clsid, const IID & iid, void * *object); | |
256 | |
257 GetClassObject get_class_object = reinterpret_cast<GetClassObject>( | |
258 GetProcAddress(dll, "DllGetClassObject")); | |
259 RETURN_ON_FAILURE( | |
260 get_class_object, "Failed to get DllGetClassObject pointer", false); | |
261 | |
262 base::win::ScopedComPtr<IClassFactory> factory; | |
263 HRESULT hr = get_class_object( | |
264 clsid, | |
265 __uuidof(IClassFactory), | |
266 reinterpret_cast<void**>(factory.Receive())); | |
DaleCurtis
2015/07/15 23:11:56
ReceiveVoid to avoid cast?
ananta
2015/07/15 23:23:25
Done.
| |
267 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject failed", false); | |
268 | |
269 hr = factory->CreateInstance(NULL, iid, object); | |
270 return hr; | |
271 } | |
272 | |
244 // Maintains information about a DXVA picture buffer, i.e. whether it is | 273 // Maintains information about a DXVA picture buffer, i.e. whether it is |
245 // available for rendering, the texture information, etc. | 274 // available for rendering, the texture information, etc. |
246 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 275 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
247 public: | 276 public: |
248 static linked_ptr<DXVAPictureBuffer> Create( | 277 static linked_ptr<DXVAPictureBuffer> Create( |
249 const DXVAVideoDecodeAccelerator& decoder, | 278 const DXVAVideoDecodeAccelerator& decoder, |
250 const media::PictureBuffer& buffer, | 279 const media::PictureBuffer& buffer, |
251 EGLConfig egl_config); | 280 EGLConfig egl_config); |
252 ~DXVAPictureBuffer(); | 281 ~DXVAPictureBuffer(); |
253 | 282 |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
720 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 749 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
721 | 750 |
722 D3D11_QUERY_DESC query_desc; | 751 D3D11_QUERY_DESC query_desc; |
723 query_desc.Query = D3D11_QUERY_EVENT; | 752 query_desc.Query = D3D11_QUERY_EVENT; |
724 query_desc.MiscFlags = 0; | 753 query_desc.MiscFlags = 0; |
725 hr = d3d11_device_->CreateQuery( | 754 hr = d3d11_device_->CreateQuery( |
726 &query_desc, | 755 &query_desc, |
727 d3d11_query_.Receive()); | 756 d3d11_query_.Receive()); |
728 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); | 757 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); |
729 | 758 |
730 hr = ::CoCreateInstance( | 759 HMODULE video_processor_dll = ::LoadLibrary(L"msvproc.dll"); |
760 RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", | |
761 false); | |
762 | |
763 hr = CreateCOMObjectFromDll( | |
764 video_processor_dll, | |
731 CLSID_VideoProcessorMFT, | 765 CLSID_VideoProcessorMFT, |
732 NULL, | 766 __uuidof(IMFTransform), |
733 CLSCTX_INPROC_SERVER, | |
734 IID_IMFTransform, | |
735 reinterpret_cast<void**>(video_format_converter_mft_.Receive())); | 767 reinterpret_cast<void**>(video_format_converter_mft_.Receive())); |
736 | |
737 if (FAILED(hr)) { | 768 if (FAILED(hr)) { |
738 base::debug::Alias(&hr); | 769 base::debug::Alias(&hr); |
739 // TODO(ananta) | 770 // TODO(ananta) |
740 // Remove this CHECK when the change to use DX11 for H/W decoding | 771 // Remove this CHECK when the change to use DX11 for H/W decoding |
741 // stablizes. | 772 // stablizes. |
742 CHECK(false); | 773 CHECK(false); |
743 } | 774 } |
775 | |
744 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); | 776 RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); |
745 return true; | 777 return true; |
746 } | 778 } |
747 | 779 |
748 void DXVAVideoDecodeAccelerator::Decode( | 780 void DXVAVideoDecodeAccelerator::Decode( |
749 const media::BitstreamBuffer& bitstream_buffer) { | 781 const media::BitstreamBuffer& bitstream_buffer) { |
750 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 782 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
751 | 783 |
752 State state = GetState(); | 784 State state = GetState(); |
753 RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped || | 785 RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped || |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
987 codec_ = media::kCodecVP9; | 1019 codec_ = media::kCodecVP9; |
988 dll_path = dll_path.Append(kVP9DecoderDLLName); | 1020 dll_path = dll_path.Append(kVP9DecoderDLLName); |
989 } | 1021 } |
990 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, | 1022 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, |
991 LOAD_WITH_ALTERED_SEARCH_PATH); | 1023 LOAD_WITH_ALTERED_SEARCH_PATH); |
992 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false); | 1024 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false); |
993 } else { | 1025 } else { |
994 RETURN_ON_FAILURE(false, "Unsupported codec.", false); | 1026 RETURN_ON_FAILURE(false, "Unsupported codec.", false); |
995 } | 1027 } |
996 | 1028 |
997 typedef HRESULT(WINAPI * GetClassObject)( | 1029 CLSID clsid = {}; |
DaleCurtis
2015/07/15 23:11:56
Seems you could just roll this into the conditiona
ananta
2015/07/15 23:23:25
Yes. Done.
| |
998 const CLSID & clsid, const IID & iid, void * *object); | 1030 if (codec_ == media::kCodecH264) { |
1031 clsid = __uuidof(CMSH264DecoderMFT); | |
1032 } else if (codec_ == media::kCodecVP8) { | |
1033 clsid = CLSID_WebmMfVp8Dec; | |
1034 } else if (codec_ == media::kCodecVP9) { | |
1035 clsid = CLSID_WebmMfVp9Dec; | |
1036 } else { | |
1037 NOTREACHED() << "Unsupported codec: " << codec_; | |
1038 } | |
999 | 1039 |
1000 GetClassObject get_class_object = reinterpret_cast<GetClassObject>( | 1040 HRESULT hr = CreateCOMObjectFromDll(decoder_dll, |
1001 GetProcAddress(decoder_dll, "DllGetClassObject")); | 1041 clsid, |
1002 RETURN_ON_FAILURE( | 1042 __uuidof(IMFTransform), |
1003 get_class_object, "Failed to get DllGetClassObject pointer", false); | 1043 reinterpret_cast<void**>( |
1004 | 1044 decoder_.Receive())); |
DaleCurtis
2015/07/15 23:11:56
ReceiveVoid
| |
1005 base::win::ScopedComPtr<IClassFactory> factory; | |
1006 HRESULT hr; | |
1007 if (codec_ == media::kCodecH264) { | |
1008 hr = get_class_object(__uuidof(CMSH264DecoderMFT), | |
1009 __uuidof(IClassFactory), | |
1010 reinterpret_cast<void**>(factory.Receive())); | |
1011 } else if (codec_ == media::kCodecVP8) { | |
1012 hr = get_class_object(CLSID_WebmMfVp8Dec, | |
1013 __uuidof(IClassFactory), | |
1014 reinterpret_cast<void**>(factory.Receive())); | |
1015 } else if (codec_ == media::kCodecVP9) { | |
1016 hr = get_class_object(CLSID_WebmMfVp9Dec, | |
1017 __uuidof(IClassFactory), | |
1018 reinterpret_cast<void**>(factory.Receive())); | |
1019 } else { | |
1020 RETURN_ON_FAILURE(false, "Unsupported codec.", false); | |
1021 } | |
1022 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject for decoder failed", false); | |
1023 | |
1024 hr = factory->CreateInstance(NULL, | |
1025 __uuidof(IMFTransform), | |
1026 reinterpret_cast<void**>(decoder_.Receive())); | |
1027 RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false); | 1045 RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false); |
1028 | 1046 |
1029 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), | 1047 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), |
1030 "Failed to check decoder DXVA support", false); | 1048 "Failed to check decoder DXVA support", false); |
1031 | 1049 |
1032 ULONG_PTR device_manager_to_use = NULL; | 1050 ULONG_PTR device_manager_to_use = NULL; |
1033 if (use_dx11_) { | 1051 if (use_dx11_) { |
1034 CHECK(create_dxgi_device_manager_); | 1052 CHECK(create_dxgi_device_manager_); |
1035 RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(), | 1053 RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(), |
1036 "Failed to initialize DX11 device and manager", | 1054 "Failed to initialize DX11 device and manager", |
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2187 D3DSURFACE_DESC surface_desc; | 2205 D3DSURFACE_DESC surface_desc; |
2188 hr = surface->GetDesc(&surface_desc); | 2206 hr = surface->GetDesc(&surface_desc); |
2189 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2207 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
2190 *width = surface_desc.Width; | 2208 *width = surface_desc.Width; |
2191 *height = surface_desc.Height; | 2209 *height = surface_desc.Height; |
2192 } | 2210 } |
2193 return true; | 2211 return true; |
2194 } | 2212 } |
2195 | 2213 |
2196 } // namespace content | 2214 } // namespace content |
OLD | NEW |