Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: content/common/gpu/media/dxva_video_decode_accelerator.cc

Issue 1235373003: Fix a crasher in the GPU process caused by the DXVA code attempting to create an instance of the Vi… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix indent Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 using GetClassObject = HRESULT (WINAPI*)(
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 factory.ReceiveVoid());
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
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, 767 video_format_converter_mft_.ReceiveVoid());
734 IID_IMFTransform,
735 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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 // Use 1088 to account for 16x16 macroblocks. 968 // Use 1088 to account for 16x16 macroblocks.
937 profile.max_resolution.SetSize(1920, 1088); 969 profile.max_resolution.SetSize(1920, 1088);
938 profiles.push_back(profile); 970 profiles.push_back(profile);
939 } 971 }
940 return profiles; 972 return profiles;
941 } 973 }
942 974
943 bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { 975 bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) {
944 HMODULE decoder_dll = NULL; 976 HMODULE decoder_dll = NULL;
945 977
978 CLSID clsid = {};
979
946 // Profile must fall within the valid range for one of the supported codecs. 980 // Profile must fall within the valid range for one of the supported codecs.
947 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { 981 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) {
948 // We mimic the steps CoCreateInstance uses to instantiate the object. This 982 // We mimic the steps CoCreateInstance uses to instantiate the object. This
949 // was previously done because it failed inside the sandbox, and now is done 983 // was previously done because it failed inside the sandbox, and now is done
950 // as a more minimal approach to avoid other side-effects CCI might have (as 984 // as a more minimal approach to avoid other side-effects CCI might have (as
951 // we are still in a reduced sandbox). 985 // we are still in a reduced sandbox).
952 decoder_dll = ::LoadLibrary(L"msmpeg2vdec.dll"); 986 decoder_dll = ::LoadLibrary(L"msmpeg2vdec.dll");
953 RETURN_ON_FAILURE(decoder_dll, 987 RETURN_ON_FAILURE(decoder_dll,
954 "msmpeg2vdec.dll required for decoding is not loaded", 988 "msmpeg2vdec.dll required for decoding is not loaded",
955 false); 989 false);
956 990
957 // Check version of DLL, version 6.7.7140 is blacklisted due to high crash 991 // Check version of DLL, version 6.7.7140 is blacklisted due to high crash
958 // rates in browsers loading that DLL. If that is the version installed we 992 // rates in browsers loading that DLL. If that is the version installed we
959 // fall back to software decoding. See crbug/403440. 993 // fall back to software decoding. See crbug/403440.
960 FileVersionInfo* version_info = 994 FileVersionInfo* version_info =
961 FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll); 995 FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll);
962 RETURN_ON_FAILURE(version_info, 996 RETURN_ON_FAILURE(version_info,
963 "unable to get version of msmpeg2vdec.dll", 997 "unable to get version of msmpeg2vdec.dll",
964 false); 998 false);
965 base::string16 file_version = version_info->file_version(); 999 base::string16 file_version = version_info->file_version();
966 RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos, 1000 RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos,
967 "blacklisted version of msmpeg2vdec.dll 6.7.7140", 1001 "blacklisted version of msmpeg2vdec.dll 6.7.7140",
968 false); 1002 false);
969 codec_ = media::kCodecH264; 1003 codec_ = media::kCodecH264;
1004 clsid = __uuidof(CMSH264DecoderMFT);
970 } else if (profile == media::VP8PROFILE_ANY || 1005 } else if (profile == media::VP8PROFILE_ANY ||
971 profile == media::VP9PROFILE_ANY) { 1006 profile == media::VP9PROFILE_ANY) {
972 int program_files_key = base::DIR_PROGRAM_FILES; 1007 int program_files_key = base::DIR_PROGRAM_FILES;
973 if (base::win::OSInfo::GetInstance()->wow64_status() == 1008 if (base::win::OSInfo::GetInstance()->wow64_status() ==
974 base::win::OSInfo::WOW64_ENABLED) { 1009 base::win::OSInfo::WOW64_ENABLED) {
975 program_files_key = base::DIR_PROGRAM_FILES6432; 1010 program_files_key = base::DIR_PROGRAM_FILES6432;
976 } 1011 }
977 1012
978 base::FilePath dll_path; 1013 base::FilePath dll_path;
979 RETURN_ON_FAILURE(PathService::Get(program_files_key, &dll_path), 1014 RETURN_ON_FAILURE(PathService::Get(program_files_key, &dll_path),
980 "failed to get path for Program Files", false); 1015 "failed to get path for Program Files", false);
981 1016
982 dll_path = dll_path.Append(kVPXDecoderDLLPath); 1017 dll_path = dll_path.Append(kVPXDecoderDLLPath);
983 if (profile == media::VP8PROFILE_ANY) { 1018 if (profile == media::VP8PROFILE_ANY) {
984 codec_ = media::kCodecVP8; 1019 codec_ = media::kCodecVP8;
985 dll_path = dll_path.Append(kVP8DecoderDLLName); 1020 dll_path = dll_path.Append(kVP8DecoderDLLName);
1021 clsid = CLSID_WebmMfVp8Dec;
986 } else { 1022 } else {
987 codec_ = media::kCodecVP9; 1023 codec_ = media::kCodecVP9;
988 dll_path = dll_path.Append(kVP9DecoderDLLName); 1024 dll_path = dll_path.Append(kVP9DecoderDLLName);
1025 clsid = CLSID_WebmMfVp9Dec;
989 } 1026 }
990 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, 1027 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL,
991 LOAD_WITH_ALTERED_SEARCH_PATH); 1028 LOAD_WITH_ALTERED_SEARCH_PATH);
992 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false); 1029 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false);
993 } else { 1030 } else {
994 RETURN_ON_FAILURE(false, "Unsupported codec.", false); 1031 RETURN_ON_FAILURE(false, "Unsupported codec.", false);
995 } 1032 }
996 1033
997 typedef HRESULT(WINAPI * GetClassObject)( 1034 HRESULT hr = CreateCOMObjectFromDll(decoder_dll,
998 const CLSID & clsid, const IID & iid, void * *object); 1035 clsid,
999 1036 __uuidof(IMFTransform),
1000 GetClassObject get_class_object = reinterpret_cast<GetClassObject>( 1037 decoder_.ReceiveVoid());
1001 GetProcAddress(decoder_dll, "DllGetClassObject"));
1002 RETURN_ON_FAILURE(
1003 get_class_object, "Failed to get DllGetClassObject pointer", false);
1004
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); 1038 RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false);
1028 1039
1029 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), 1040 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(),
1030 "Failed to check decoder DXVA support", false); 1041 "Failed to check decoder DXVA support", false);
1031 1042
1032 ULONG_PTR device_manager_to_use = NULL; 1043 ULONG_PTR device_manager_to_use = NULL;
1033 if (use_dx11_) { 1044 if (use_dx11_) {
1034 CHECK(create_dxgi_device_manager_); 1045 CHECK(create_dxgi_device_manager_);
1035 RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(), 1046 RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(),
1036 "Failed to initialize DX11 device and manager", 1047 "Failed to initialize DX11 device and manager",
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2187 D3DSURFACE_DESC surface_desc; 2198 D3DSURFACE_DESC surface_desc;
2188 hr = surface->GetDesc(&surface_desc); 2199 hr = surface->GetDesc(&surface_desc);
2189 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); 2200 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
2190 *width = surface_desc.Width; 2201 *width = surface_desc.Width;
2191 *height = surface_desc.Height; 2202 *height = surface_desc.Height;
2192 } 2203 }
2193 return true; 2204 return true;
2194 } 2205 }
2195 2206
2196 } // namespace content 2207 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698