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

Side by Side Diff: media/gpu/dxva_video_decode_accelerator_win.cc

Issue 2172703002: Revert of H264 HW encode using MediaFoundation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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 | « media/gpu/BUILD.gn ('k') | media/gpu/ipc/service/gpu_video_encode_accelerator.h » ('j') | 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 "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.
(...skipping 21 matching lines...) Expand all
32 #include "base/memory/shared_memory.h" 32 #include "base/memory/shared_memory.h"
33 #include "base/path_service.h" 33 #include "base/path_service.h"
34 #include "base/single_thread_task_runner.h" 34 #include "base/single_thread_task_runner.h"
35 #include "base/stl_util.h" 35 #include "base/stl_util.h"
36 #include "base/threading/thread_task_runner_handle.h" 36 #include "base/threading/thread_task_runner_handle.h"
37 #include "base/trace_event/trace_event.h" 37 #include "base/trace_event/trace_event.h"
38 #include "base/win/windows_version.h" 38 #include "base/win/windows_version.h"
39 #include "build/build_config.h" 39 #include "build/build_config.h"
40 #include "gpu/command_buffer/service/gpu_preferences.h" 40 #include "gpu/command_buffer/service/gpu_preferences.h"
41 #include "gpu/config/gpu_driver_bug_workarounds.h" 41 #include "gpu/config/gpu_driver_bug_workarounds.h"
42 #include "media/base/win/mf_helpers.h"
43 #include "media/base/win/mf_initializer.h" 42 #include "media/base/win/mf_initializer.h"
44 #include "media/gpu/dxva_picture_buffer_win.h" 43 #include "media/gpu/dxva_picture_buffer_win.h"
45 #include "media/video/video_decode_accelerator.h" 44 #include "media/video/video_decode_accelerator.h"
46 #include "third_party/angle/include/EGL/egl.h" 45 #include "third_party/angle/include/EGL/egl.h"
47 #include "third_party/angle/include/EGL/eglext.h" 46 #include "third_party/angle/include/EGL/eglext.h"
48 #include "ui/gl/gl_bindings.h" 47 #include "ui/gl/gl_bindings.h"
49 #include "ui/gl/gl_context.h" 48 #include "ui/gl/gl_context.h"
50 #include "ui/gl/gl_fence.h" 49 #include "ui/gl/gl_fence.h"
51 #include "ui/gl/gl_surface_egl.h" 50 #include "ui/gl/gl_surface_egl.h"
52 51
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998, 180 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998,
182 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4, 181 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4,
183 }; 182 };
184 183
185 // Legacy Intel GPUs (Second generation) which have trouble with resolutions 184 // Legacy Intel GPUs (Second generation) which have trouble with resolutions
186 // higher than 1920 x 1088 185 // higher than 1920 x 1088
187 static const DWORD g_IntelLegacyGPUList[] = { 186 static const DWORD g_IntelLegacyGPUList[] = {
188 0x102, 0x106, 0x116, 0x126, 187 0x102, 0x106, 0x116, 0x126,
189 }; 188 };
190 189
190 // Provides scoped access to the underlying buffer in an IMFMediaBuffer
191 // instance.
192 class MediaBufferScopedPointer {
193 public:
194 explicit MediaBufferScopedPointer(IMFMediaBuffer* media_buffer)
195 : media_buffer_(media_buffer),
196 buffer_(nullptr),
197 max_length_(0),
198 current_length_(0) {
199 HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, &current_length_);
200 CHECK(SUCCEEDED(hr));
201 }
202
203 ~MediaBufferScopedPointer() {
204 HRESULT hr = media_buffer_->Unlock();
205 CHECK(SUCCEEDED(hr));
206 }
207
208 uint8_t* get() { return buffer_; }
209
210 DWORD current_length() const { return current_length_; }
211
212 private:
213 base::win::ScopedComPtr<IMFMediaBuffer> media_buffer_;
214 uint8_t* buffer_;
215 DWORD max_length_;
216 DWORD current_length_;
217
218 DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer);
219 };
220
221 void LogDXVAError(int line) {
222 LOG(ERROR) << "Error in dxva_video_decode_accelerator_win.cc on line "
223 << line;
224 }
225
191 } // namespace 226 } // namespace
192 227
193 namespace media { 228 namespace media {
194 229
195 static const VideoCodecProfile kSupportedProfiles[] = { 230 static const VideoCodecProfile kSupportedProfiles[] = {
196 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, 231 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH,
197 VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, 232 VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1,
198 VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3}; 233 VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3};
199 234
200 CreateDXGIDeviceManager 235 CreateDXGIDeviceManager
201 DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL; 236 DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL;
202 237
238 #define RETURN_ON_FAILURE(result, log, ret) \
239 do { \
240 if (!(result)) { \
241 DLOG(ERROR) << log; \
242 LogDXVAError(__LINE__); \
243 return ret; \
244 } \
245 } while (0)
246
247 #define RETURN_ON_HR_FAILURE(result, log, ret) \
248 RETURN_ON_FAILURE(SUCCEEDED(result), \
249 log << ", HRESULT: 0x" << std::hex << result, ret);
250
251 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
252 do { \
253 if (!(result)) { \
254 DVLOG(1) << log; \
255 LogDXVAError(__LINE__); \
256 StopOnError(error_code); \
257 return ret; \
258 } \
259 } while (0)
260
261 #define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret) \
262 RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result), \
263 log << ", HRESULT: 0x" << std::hex << result, \
264 error_code, ret);
265
203 enum { 266 enum {
204 // Maximum number of iterations we allow before aborting the attempt to flush 267 // Maximum number of iterations we allow before aborting the attempt to flush
205 // the batched queries to the driver and allow torn/corrupt frames to be 268 // the batched queries to the driver and allow torn/corrupt frames to be
206 // rendered. 269 // rendered.
207 kFlushDecoderSurfaceTimeoutMs = 1, 270 kFlushDecoderSurfaceTimeoutMs = 1,
208 // Maximum iterations where we try to flush the d3d device. 271 // Maximum iterations where we try to flush the d3d device.
209 kMaxIterationsForD3DFlush = 4, 272 kMaxIterationsForD3DFlush = 4,
210 // Maximum iterations where we try to flush the ANGLE device before reusing 273 // Maximum iterations where we try to flush the ANGLE device before reusing
211 // the texture. 274 // the texture.
212 kMaxIterationsForANGLEReuseFlush = 16, 275 kMaxIterationsForANGLEReuseFlush = 16,
213 // We only request 5 picture buffers from the client which are used to hold 276 // We only request 5 picture buffers from the client which are used to hold
214 // the decoded samples. These buffers are then reused when the client tells 277 // the decoded samples. These buffers are then reused when the client tells
215 // us that it is done with the buffer. 278 // us that it is done with the buffer.
216 kNumPictureBuffers = 5, 279 kNumPictureBuffers = 5,
217 // The keyed mutex should always be released before the other thread 280 // The keyed mutex should always be released before the other thread
218 // attempts to acquire it, so AcquireSync should always return immediately. 281 // attempts to acquire it, so AcquireSync should always return immediately.
219 kAcquireSyncWaitMs = 0, 282 kAcquireSyncWaitMs = 0,
220 }; 283 };
221 284
285 static IMFSample* CreateEmptySample() {
286 base::win::ScopedComPtr<IMFSample> sample;
287 HRESULT hr = MFCreateSample(sample.Receive());
288 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL);
289 return sample.Detach();
290 }
291
292 // Creates a Media Foundation sample with one buffer of length |buffer_length|
293 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
294 static IMFSample* CreateEmptySampleWithBuffer(uint32_t buffer_length,
295 int align) {
296 CHECK_GT(buffer_length, 0U);
297
298 base::win::ScopedComPtr<IMFSample> sample;
299 sample.Attach(CreateEmptySample());
300
301 base::win::ScopedComPtr<IMFMediaBuffer> buffer;
302 HRESULT hr = E_FAIL;
303 if (align == 0) {
304 // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer
305 // with the align argument being 0.
306 hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive());
307 } else {
308 hr =
309 MFCreateAlignedMemoryBuffer(buffer_length, align - 1, buffer.Receive());
310 }
311 RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", NULL);
312
313 hr = sample->AddBuffer(buffer.get());
314 RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", NULL);
315
316 buffer->SetCurrentLength(0);
317 return sample.Detach();
318 }
319
222 // Creates a Media Foundation sample with one buffer containing a copy of the 320 // Creates a Media Foundation sample with one buffer containing a copy of the
223 // given Annex B stream data. 321 // given Annex B stream data.
224 // If duration and sample time are not known, provide 0. 322 // If duration and sample time are not known, provide 0.
225 // |min_size| specifies the minimum size of the buffer (might be required by 323 // |min_size| specifies the minimum size of the buffer (might be required by
226 // the decoder for input). If no alignment is required, provide 0. 324 // the decoder for input). If no alignment is required, provide 0.
227 static IMFSample* CreateInputSample(const uint8_t* stream, 325 static IMFSample* CreateInputSample(const uint8_t* stream,
228 uint32_t size, 326 uint32_t size,
229 uint32_t min_size, 327 uint32_t min_size,
230 int alignment) { 328 int alignment) {
231 CHECK(stream); 329 CHECK(stream);
232 CHECK_GT(size, 0U); 330 CHECK_GT(size, 0U);
233 base::win::ScopedComPtr<IMFSample> sample; 331 base::win::ScopedComPtr<IMFSample> sample;
234 sample.Attach( 332 sample.Attach(
235 mf::CreateEmptySampleWithBuffer(std::max(min_size, size), alignment)); 333 CreateEmptySampleWithBuffer(std::max(min_size, size), alignment));
236 RETURN_ON_FAILURE(sample.get(), "Failed to create empty sample", NULL); 334 RETURN_ON_FAILURE(sample.get(), "Failed to create empty sample", NULL);
237 335
238 base::win::ScopedComPtr<IMFMediaBuffer> buffer; 336 base::win::ScopedComPtr<IMFMediaBuffer> buffer;
239 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); 337 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive());
240 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample", NULL); 338 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample", NULL);
241 339
242 DWORD max_length = 0; 340 DWORD max_length = 0;
243 DWORD current_length = 0; 341 DWORD current_length = 0;
244 uint8_t* destination = NULL; 342 uint8_t* destination = NULL;
245 hr = buffer->Lock(&destination, &max_length, &current_length); 343 hr = buffer->Lock(&destination, &max_length, &current_length);
(...skipping 2400 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 2744
2647 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(IMFSample* sample, 2745 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(IMFSample* sample,
2648 bool* config_changed) { 2746 bool* config_changed) {
2649 if (codec_ != kCodecH264) 2747 if (codec_ != kCodecH264)
2650 return S_FALSE; 2748 return S_FALSE;
2651 2749
2652 base::win::ScopedComPtr<IMFMediaBuffer> buffer; 2750 base::win::ScopedComPtr<IMFMediaBuffer> buffer;
2653 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); 2751 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive());
2654 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); 2752 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr);
2655 2753
2656 mf::MediaBufferScopedPointer scoped_media_buffer(buffer.get()); 2754 MediaBufferScopedPointer scoped_media_buffer(buffer.get());
2657 2755
2658 if (!config_change_detector_->DetectConfig( 2756 if (!config_change_detector_->DetectConfig(
2659 scoped_media_buffer.get(), scoped_media_buffer.current_length())) { 2757 scoped_media_buffer.get(), scoped_media_buffer.current_length())) {
2660 RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config", 2758 RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config",
2661 E_FAIL); 2759 E_FAIL);
2662 } 2760 }
2663 *config_changed = config_change_detector_->config_changed(); 2761 *config_changed = config_change_detector_->config_changed();
2664 return S_OK; 2762 return S_OK;
2665 } 2763 }
2666 2764
2667 void DXVAVideoDecodeAccelerator::ConfigChanged(const Config& config) { 2765 void DXVAVideoDecodeAccelerator::ConfigChanged(const Config& config) {
2668 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); 2766 DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
2669 2767
2670 SetState(kConfigChange); 2768 SetState(kConfigChange);
2671 Invalidate(); 2769 Invalidate();
2672 Initialize(config_, client_); 2770 Initialize(config_, client_);
2673 decoder_thread_task_runner_->PostTask( 2771 decoder_thread_task_runner_->PostTask(
2674 FROM_HERE, 2772 FROM_HERE,
2675 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, 2773 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
2676 base::Unretained(this))); 2774 base::Unretained(this)));
2677 } 2775 }
2678 2776
2679 } // namespace media 2777 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/BUILD.gn ('k') | media/gpu/ipc/service/gpu_video_encode_accelerator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698