Index: content/common/gpu/media/dxva_video_decode_accelerator.cc |
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc |
index 568b128e1d1bdea5e0d98bed04fda5db6b54b733..4b9530791071df99911215f489677cef6488166d 100644 |
--- a/content/common/gpu/media/dxva_video_decode_accelerator.cc |
+++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc |
@@ -100,7 +100,8 @@ DEFINE_GUID(CLSID_VideoProcessorMFT, |
// regeneration (repaint). |
DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, |
0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); |
-} |
+ |
+} // namespace |
namespace content { |
@@ -241,6 +242,34 @@ static IMFSample* CreateSampleFromInputBuffer( |
alignment); |
} |
+// Helper function to create a COM object instance from a DLL. The alternative |
+// is to use the CoCreateInstance API which requires the COM apartment to be |
+// initialized which is not the case on the GPU main thread. We want to avoid |
+// initializing COM as it may have sideeffects. |
+HRESULT CreateCOMObjectFromDll(HMODULE dll, const CLSID& clsid, const IID& iid, |
+ void** object) { |
+ if (!dll || !object) |
+ return E_INVALIDARG; |
+ |
+ using GetClassObject = HRESULT (WINAPI*)( |
+ const CLSID& clsid, const IID& iid, void** object); |
+ |
+ GetClassObject get_class_object = reinterpret_cast<GetClassObject>( |
+ GetProcAddress(dll, "DllGetClassObject")); |
+ RETURN_ON_FAILURE( |
+ get_class_object, "Failed to get DllGetClassObject pointer", false); |
+ |
+ base::win::ScopedComPtr<IClassFactory> factory; |
+ HRESULT hr = get_class_object( |
+ clsid, |
+ __uuidof(IClassFactory), |
+ factory.ReceiveVoid()); |
+ RETURN_ON_HR_FAILURE(hr, "DllGetClassObject failed", false); |
+ |
+ hr = factory->CreateInstance(NULL, iid, object); |
+ return hr; |
+} |
+ |
// Maintains information about a DXVA picture buffer, i.e. whether it is |
// available for rendering, the texture information, etc. |
struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
@@ -727,13 +756,15 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
d3d11_query_.Receive()); |
RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false); |
- hr = ::CoCreateInstance( |
- CLSID_VideoProcessorMFT, |
- NULL, |
- CLSCTX_INPROC_SERVER, |
- IID_IMFTransform, |
- reinterpret_cast<void**>(video_format_converter_mft_.Receive())); |
+ HMODULE video_processor_dll = ::LoadLibrary(L"msvproc.dll"); |
+ RETURN_ON_FAILURE(video_processor_dll, "Failed to load video processor", |
+ false); |
+ hr = CreateCOMObjectFromDll( |
+ video_processor_dll, |
+ CLSID_VideoProcessorMFT, |
+ __uuidof(IMFTransform), |
+ video_format_converter_mft_.ReceiveVoid()); |
if (FAILED(hr)) { |
base::debug::Alias(&hr); |
// TODO(ananta) |
@@ -741,6 +772,7 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
// stablizes. |
CHECK(false); |
} |
+ |
RETURN_ON_HR_FAILURE(hr, "Failed to create video format converter", false); |
return true; |
} |
@@ -943,6 +975,8 @@ DXVAVideoDecodeAccelerator::GetSupportedProfiles() { |
bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { |
HMODULE decoder_dll = NULL; |
+ CLSID clsid = {}; |
+ |
// Profile must fall within the valid range for one of the supported codecs. |
if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { |
// We mimic the steps CoCreateInstance uses to instantiate the object. This |
@@ -967,6 +1001,7 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { |
"blacklisted version of msmpeg2vdec.dll 6.7.7140", |
false); |
codec_ = media::kCodecH264; |
+ clsid = __uuidof(CMSH264DecoderMFT); |
} else if (profile == media::VP8PROFILE_ANY || |
profile == media::VP9PROFILE_ANY) { |
int program_files_key = base::DIR_PROGRAM_FILES; |
@@ -983,9 +1018,11 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { |
if (profile == media::VP8PROFILE_ANY) { |
codec_ = media::kCodecVP8; |
dll_path = dll_path.Append(kVP8DecoderDLLName); |
+ clsid = CLSID_WebmMfVp8Dec; |
} else { |
codec_ = media::kCodecVP9; |
dll_path = dll_path.Append(kVP9DecoderDLLName); |
+ clsid = CLSID_WebmMfVp9Dec; |
} |
decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, |
LOAD_WITH_ALTERED_SEARCH_PATH); |
@@ -994,36 +1031,10 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { |
RETURN_ON_FAILURE(false, "Unsupported codec.", false); |
} |
- typedef HRESULT(WINAPI * GetClassObject)( |
- const CLSID & clsid, const IID & iid, void * *object); |
- |
- GetClassObject get_class_object = reinterpret_cast<GetClassObject>( |
- GetProcAddress(decoder_dll, "DllGetClassObject")); |
- RETURN_ON_FAILURE( |
- get_class_object, "Failed to get DllGetClassObject pointer", false); |
- |
- base::win::ScopedComPtr<IClassFactory> factory; |
- HRESULT hr; |
- if (codec_ == media::kCodecH264) { |
- hr = get_class_object(__uuidof(CMSH264DecoderMFT), |
- __uuidof(IClassFactory), |
- reinterpret_cast<void**>(factory.Receive())); |
- } else if (codec_ == media::kCodecVP8) { |
- hr = get_class_object(CLSID_WebmMfVp8Dec, |
- __uuidof(IClassFactory), |
- reinterpret_cast<void**>(factory.Receive())); |
- } else if (codec_ == media::kCodecVP9) { |
- hr = get_class_object(CLSID_WebmMfVp9Dec, |
- __uuidof(IClassFactory), |
- reinterpret_cast<void**>(factory.Receive())); |
- } else { |
- RETURN_ON_FAILURE(false, "Unsupported codec.", false); |
- } |
- RETURN_ON_HR_FAILURE(hr, "DllGetClassObject for decoder failed", false); |
- |
- hr = factory->CreateInstance(NULL, |
- __uuidof(IMFTransform), |
- reinterpret_cast<void**>(decoder_.Receive())); |
+ HRESULT hr = CreateCOMObjectFromDll(decoder_dll, |
+ clsid, |
+ __uuidof(IMFTransform), |
+ decoder_.ReceiveVoid()); |
RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false); |
RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), |