Chromium Code Reviews| 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 "media/gpu/dxva_video_decode_accelerator_win.h" | 5 #include "media/gpu/dxva_video_decode_accelerator_win.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #if !defined(OS_WIN) | 9 #if !defined(OS_WIN) |
| 10 #error This file should only be built on Windows. | 10 #error This file should only be built on Windows. |
| 11 #endif // !defined(OS_WIN) | 11 #endif // !defined(OS_WIN) |
| 12 | 12 |
| 13 #include <codecapi.h> | 13 #include <codecapi.h> |
| 14 #include <dxgi1_2.h> | 14 #include <dxgi1_2.h> |
| 15 #include <ks.h> | 15 #include <ks.h> |
| 16 #include <mfapi.h> | 16 #include <mfapi.h> |
| 17 #include <mferror.h> | 17 #include <mferror.h> |
| 18 #include <ntverp.h> | 18 #include <ntverp.h> |
| 19 #include <stddef.h> | 19 #include <stddef.h> |
| 20 #include <string.h> | 20 #include <string.h> |
| 21 #include <wmcodecdsp.h> | 21 #include <wmcodecdsp.h> |
| 22 | 22 |
| 23 #include "base/base_paths_win.h" | 23 #include "base/base_paths_win.h" |
| 24 #include "base/bind.h" | 24 #include "base/bind.h" |
| 25 #include "base/callback.h" | 25 #include "base/callback.h" |
| 26 #include "base/debug/alias.h" | 26 #include "base/debug/alias.h" |
| 27 #include "base/debug/dump_without_crashing.h" | |
|
scottmg
2016/12/08 17:18:32
Instead of this, #include "third_party/crashpad/cr
| |
| 27 #include "base/file_version_info.h" | 28 #include "base/file_version_info.h" |
| 28 #include "base/files/file_path.h" | 29 #include "base/files/file_path.h" |
| 29 #include "base/location.h" | 30 #include "base/location.h" |
| 30 #include "base/logging.h" | 31 #include "base/logging.h" |
| 31 #include "base/macros.h" | 32 #include "base/macros.h" |
| 32 #include "base/memory/shared_memory.h" | 33 #include "base/memory/shared_memory.h" |
| 33 #include "base/path_service.h" | 34 #include "base/path_service.h" |
| 35 #include "base/process/process.h" | |
| 34 #include "base/single_thread_task_runner.h" | 36 #include "base/single_thread_task_runner.h" |
| 35 #include "base/stl_util.h" | 37 #include "base/stl_util.h" |
| 36 #include "base/threading/thread_task_runner_handle.h" | 38 #include "base/threading/thread_task_runner_handle.h" |
| 37 #include "base/trace_event/trace_event.h" | 39 #include "base/trace_event/trace_event.h" |
| 38 #include "base/win/scoped_co_mem.h" | 40 #include "base/win/scoped_co_mem.h" |
| 39 #include "base/win/windows_version.h" | 41 #include "base/win/windows_version.h" |
| 40 #include "build/build_config.h" | 42 #include "build/build_config.h" |
| 41 #include "gpu/command_buffer/service/gpu_preferences.h" | 43 #include "gpu/command_buffer/service/gpu_preferences.h" |
| 42 #include "gpu/config/gpu_driver_bug_workarounds.h" | 44 #include "gpu/config/gpu_driver_bug_workarounds.h" |
| 43 #include "media/base/media_switches.h" | 45 #include "media/base/media_switches.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 // Legacy Intel GPUs (Second generation) which have trouble with resolutions | 177 // Legacy Intel GPUs (Second generation) which have trouble with resolutions |
| 176 // higher than 1920 x 1088 | 178 // higher than 1920 x 1088 |
| 177 static const DWORD g_IntelLegacyGPUList[] = { | 179 static const DWORD g_IntelLegacyGPUList[] = { |
| 178 0x102, 0x106, 0x116, 0x126, | 180 0x102, 0x106, 0x116, 0x126, |
| 179 }; | 181 }; |
| 180 | 182 |
| 181 constexpr const wchar_t* const kMediaFoundationVideoDecoderDLLs[] = { | 183 constexpr const wchar_t* const kMediaFoundationVideoDecoderDLLs[] = { |
| 182 L"mf.dll", L"mfplat.dll", L"msmpeg2vdec.dll", | 184 L"mf.dll", L"mfplat.dll", L"msmpeg2vdec.dll", |
| 183 }; | 185 }; |
| 184 | 186 |
| 187 LONG CALLBACK VectoredCrashHandler(EXCEPTION_POINTERS* exception_pointers) { | |
| 188 // Try to get crashpad to handle this. | |
|
scottmg
2016/12/08 17:18:32
Then, replace 188-190 with
CrashpadClient::Dump
| |
| 189 UnhandledExceptionFilter(exception_pointers); | |
| 190 base::Process::Current().Terminate(1, true); | |
| 191 return EXCEPTION_CONTINUE_SEARCH; | |
| 192 } | |
| 193 | |
| 194 // The MS VP9 MFT swallows driver exceptions and later hangs because it gets | |
| 195 // into a weird state. Add a vectored exception handler so the process will | |
| 196 // crash instead. See http://crbug.com/636158 | |
| 197 class ScopedExceptionCrasher { | |
| 198 public: | |
| 199 ScopedExceptionCrasher(bool handle_exception) { | |
|
scottmg
2016/12/08 17:18:32
explicit
| |
| 200 if (handle_exception) | |
| 201 handler_ = AddVectoredExceptionHandler(TRUE, &VectoredCrashHandler); | |
| 202 } | |
| 203 | |
| 204 ~ScopedExceptionCrasher() { | |
| 205 if (handler_) | |
| 206 RemoveVectoredExceptionHandler(handler_); | |
| 207 } | |
| 208 | |
| 209 private: | |
| 210 void* handler_ = nullptr; | |
|
scottmg
2016/12/08 17:18:32
DISALLOW...
| |
| 211 }; | |
| 212 | |
| 185 } // namespace | 213 } // namespace |
| 186 | 214 |
| 187 namespace media { | 215 namespace media { |
| 188 | 216 |
| 189 static const VideoCodecProfile kSupportedProfiles[] = { | 217 static const VideoCodecProfile kSupportedProfiles[] = { |
| 190 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, | 218 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, |
| 191 VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, | 219 VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, |
| 192 VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3}; | 220 VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3}; |
| 193 | 221 |
| 194 CreateDXGIDeviceManager | 222 CreateDXGIDeviceManager |
| (...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1737 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1765 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1738 // This function is also called from FlushInternal in a loop which could | 1766 // This function is also called from FlushInternal in a loop which could |
| 1739 // result in the state transitioning to kStopped due to no decoded output. | 1767 // result in the state transitioning to kStopped due to no decoded output. |
| 1740 State state = GetState(); | 1768 State state = GetState(); |
| 1741 RETURN_AND_NOTIFY_ON_FAILURE( | 1769 RETURN_AND_NOTIFY_ON_FAILURE( |
| 1742 (state == kNormal || state == kFlushing || state == kStopped), | 1770 (state == kNormal || state == kFlushing || state == kStopped), |
| 1743 "DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE, ); | 1771 "DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE, ); |
| 1744 | 1772 |
| 1745 MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0}; | 1773 MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0}; |
| 1746 DWORD status = 0; | 1774 DWORD status = 0; |
| 1747 HRESULT hr = decoder_->ProcessOutput(0, // No flags | 1775 HRESULT hr; |
| 1748 1, // # of out streams to pull from | 1776 { |
| 1749 &output_data_buffer, &status); | 1777 ScopedExceptionCrasher crasher(using_ms_vp9_mft_); |
| 1778 hr = decoder_->ProcessOutput(0, // No flags | |
| 1779 1, // # of out streams to pull from | |
| 1780 &output_data_buffer, &status); | |
| 1781 } | |
| 1750 IMFCollection* events = output_data_buffer.pEvents; | 1782 IMFCollection* events = output_data_buffer.pEvents; |
| 1751 if (events != NULL) { | 1783 if (events != NULL) { |
| 1752 DVLOG(1) << "Got events from ProcessOuput, but discarding"; | 1784 DVLOG(1) << "Got events from ProcessOuput, but discarding"; |
| 1753 events->Release(); | 1785 events->Release(); |
| 1754 } | 1786 } |
| 1755 if (FAILED(hr)) { | 1787 if (FAILED(hr)) { |
| 1756 // A stream change needs further ProcessInput calls to get back decoder | 1788 // A stream change needs further ProcessInput calls to get back decoder |
| 1757 // output which is why we need to set the state to stopped. | 1789 // output which is why we need to set the state to stopped. |
| 1758 if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { | 1790 if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { |
| 1759 if (!SetDecoderOutputMediaType(MFVideoFormat_NV12) && | 1791 if (!SetDecoderOutputMediaType(MFVideoFormat_NV12) && |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2167 return; | 2199 return; |
| 2168 } | 2200 } |
| 2169 | 2201 |
| 2170 gfx::ColorSpace color_space = config_change_detector_->current_color_space(); | 2202 gfx::ColorSpace color_space = config_change_detector_->current_color_space(); |
| 2171 | 2203 |
| 2172 if (!inputs_before_decode_) { | 2204 if (!inputs_before_decode_) { |
| 2173 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", | 2205 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", |
| 2174 this); | 2206 this); |
| 2175 } | 2207 } |
| 2176 inputs_before_decode_++; | 2208 inputs_before_decode_++; |
| 2177 | 2209 { |
| 2178 hr = decoder_->ProcessInput(0, sample.get(), 0); | 2210 ScopedExceptionCrasher crasher(using_ms_vp9_mft_); |
| 2211 hr = decoder_->ProcessInput(0, sample.get(), 0); | |
| 2212 } | |
| 2179 // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it | 2213 // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it |
| 2180 // has enough data to produce one or more output samples. In this case the | 2214 // has enough data to produce one or more output samples. In this case the |
| 2181 // recommended options are to | 2215 // recommended options are to |
| 2182 // 1. Generate new output by calling IMFTransform::ProcessOutput until it | 2216 // 1. Generate new output by calling IMFTransform::ProcessOutput until it |
| 2183 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. | 2217 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. |
| 2184 // 2. Flush the input data | 2218 // 2. Flush the input data |
| 2185 // We implement the first option, i.e to retrieve the output sample and then | 2219 // We implement the first option, i.e to retrieve the output sample and then |
| 2186 // process the input again. Failure in either of these steps is treated as a | 2220 // process the input again. Failure in either of these steps is treated as a |
| 2187 // decoder failure. | 2221 // decoder failure. |
| 2188 if (hr == MF_E_NOTACCEPTING) { | 2222 if (hr == MF_E_NOTACCEPTING) { |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2895 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2929 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
| 2896 base::Unretained(this))); | 2930 base::Unretained(this))); |
| 2897 } | 2931 } |
| 2898 | 2932 |
| 2899 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { | 2933 uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const { |
| 2900 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; | 2934 bool provide_nv12_textures = share_nv12_textures_ || copy_nv12_textures_; |
| 2901 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | 2935 return provide_nv12_textures ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
| 2902 } | 2936 } |
| 2903 | 2937 |
| 2904 } // namespace media | 2938 } // namespace media |
| OLD | NEW |