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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 error_code, ret); | 64 error_code, ret); |
65 | 65 |
66 // Maximum number of iterations we allow before aborting the attempt to flush | 66 // Maximum number of iterations we allow before aborting the attempt to flush |
67 // the batched queries to the driver and allow torn/corrupt frames to be | 67 // the batched queries to the driver and allow torn/corrupt frames to be |
68 // rendered. | 68 // rendered. |
69 enum { kMaxIterationsForD3DFlush = 10 }; | 69 enum { kMaxIterationsForD3DFlush = 10 }; |
70 | 70 |
71 static IMFSample* CreateEmptySample() { | 71 static IMFSample* CreateEmptySample() { |
72 base::win::ScopedComPtr<IMFSample> sample; | 72 base::win::ScopedComPtr<IMFSample> sample; |
73 HRESULT hr = MFCreateSample(sample.Receive()); | 73 HRESULT hr = MFCreateSample(sample.Receive()); |
74 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); | 74 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", nullptr); |
75 return sample.Detach(); | 75 return sample.Detach(); |
76 } | 76 } |
77 | 77 |
78 // Creates a Media Foundation sample with one buffer of length |buffer_length| | 78 // Creates a Media Foundation sample with one buffer of length |buffer_length| |
79 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. | 79 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. |
80 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { | 80 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { |
81 CHECK_GT(buffer_length, 0); | 81 CHECK_GT(buffer_length, 0); |
82 | 82 |
83 base::win::ScopedComPtr<IMFSample> sample; | 83 base::win::ScopedComPtr<IMFSample> sample; |
84 sample.Attach(CreateEmptySample()); | 84 sample.Attach(CreateEmptySample()); |
85 | 85 |
86 base::win::ScopedComPtr<IMFMediaBuffer> buffer; | 86 base::win::ScopedComPtr<IMFMediaBuffer> buffer; |
87 HRESULT hr = E_FAIL; | 87 HRESULT hr = E_FAIL; |
88 if (align == 0) { | 88 if (align == 0) { |
89 // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer | 89 // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer |
90 // with the align argument being 0. | 90 // with the align argument being 0. |
91 hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive()); | 91 hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive()); |
92 } else { | 92 } else { |
93 hr = MFCreateAlignedMemoryBuffer(buffer_length, | 93 hr = MFCreateAlignedMemoryBuffer(buffer_length, |
94 align - 1, | 94 align - 1, |
95 buffer.Receive()); | 95 buffer.Receive()); |
96 } | 96 } |
97 RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", NULL); | 97 RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", |
| 98 nullptr); |
98 | 99 |
99 hr = sample->AddBuffer(buffer); | 100 hr = sample->AddBuffer(buffer); |
100 RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", NULL); | 101 RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", nullptr); |
101 | 102 |
102 return sample.Detach(); | 103 return sample.Detach(); |
103 } | 104 } |
104 | 105 |
105 // Creates a Media Foundation sample with one buffer containing a copy of the | 106 // Creates a Media Foundation sample with one buffer containing a copy of the |
106 // given Annex B stream data. | 107 // given Annex B stream data. |
107 // If duration and sample time are not known, provide 0. | 108 // If duration and sample time are not known, provide 0. |
108 // |min_size| specifies the minimum size of the buffer (might be required by | 109 // |min_size| specifies the minimum size of the buffer (might be required by |
109 // the decoder for input). If no alignment is required, provide 0. | 110 // the decoder for input). If no alignment is required, provide 0. |
110 static IMFSample* CreateInputSample(const uint8* stream, int size, | 111 static IMFSample* CreateInputSample(const uint8* stream, int size, |
111 int min_size, int alignment) { | 112 int min_size, int alignment) { |
112 CHECK(stream); | 113 CHECK(stream); |
113 CHECK_GT(size, 0); | 114 CHECK_GT(size, 0); |
114 base::win::ScopedComPtr<IMFSample> sample; | 115 base::win::ScopedComPtr<IMFSample> sample; |
115 sample.Attach(CreateEmptySampleWithBuffer(std::max(min_size, size), | 116 sample.Attach(CreateEmptySampleWithBuffer(std::max(min_size, size), |
116 alignment)); | 117 alignment)); |
117 RETURN_ON_FAILURE(sample, "Failed to create empty sample", NULL); | 118 RETURN_ON_FAILURE(sample, "Failed to create empty sample", nullptr); |
118 | 119 |
119 base::win::ScopedComPtr<IMFMediaBuffer> buffer; | 120 base::win::ScopedComPtr<IMFMediaBuffer> buffer; |
120 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); | 121 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); |
121 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample", NULL); | 122 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample", nullptr); |
122 | 123 |
123 DWORD max_length = 0; | 124 DWORD max_length = 0; |
124 DWORD current_length = 0; | 125 DWORD current_length = 0; |
125 uint8* destination = NULL; | 126 uint8* destination = nullptr; |
126 hr = buffer->Lock(&destination, &max_length, ¤t_length); | 127 hr = buffer->Lock(&destination, &max_length, ¤t_length); |
127 RETURN_ON_HR_FAILURE(hr, "Failed to lock buffer", NULL); | 128 RETURN_ON_HR_FAILURE(hr, "Failed to lock buffer", nullptr); |
128 | 129 |
129 CHECK_EQ(current_length, 0u); | 130 CHECK_EQ(current_length, 0u); |
130 CHECK_GE(static_cast<int>(max_length), size); | 131 CHECK_GE(static_cast<int>(max_length), size); |
131 memcpy(destination, stream, size); | 132 memcpy(destination, stream, size); |
132 | 133 |
133 hr = buffer->Unlock(); | 134 hr = buffer->Unlock(); |
134 RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer", NULL); | 135 RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer", nullptr); |
135 | 136 |
136 hr = buffer->SetCurrentLength(size); | 137 hr = buffer->SetCurrentLength(size); |
137 RETURN_ON_HR_FAILURE(hr, "Failed to set buffer length", NULL); | 138 RETURN_ON_HR_FAILURE(hr, "Failed to set buffer length", nullptr); |
138 | 139 |
139 return sample.Detach(); | 140 return sample.Detach(); |
140 } | 141 } |
141 | 142 |
142 static IMFSample* CreateSampleFromInputBuffer( | 143 static IMFSample* CreateSampleFromInputBuffer( |
143 const media::BitstreamBuffer& bitstream_buffer, | 144 const media::BitstreamBuffer& bitstream_buffer, |
144 DWORD stream_size, | 145 DWORD stream_size, |
145 DWORD alignment) { | 146 DWORD alignment) { |
146 base::SharedMemory shm(bitstream_buffer.handle(), true); | 147 base::SharedMemory shm(bitstream_buffer.handle(), true); |
147 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), | 148 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), |
148 "Failed in base::SharedMemory::Map", NULL); | 149 "Failed in base::SharedMemory::Map", nullptr); |
149 | 150 |
150 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()), | 151 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()), |
151 bitstream_buffer.size(), | 152 bitstream_buffer.size(), |
152 stream_size, | 153 stream_size, |
153 alignment); | 154 alignment); |
154 } | 155 } |
155 | 156 |
156 // Maintains information about a DXVA picture buffer, i.e. whether it is | 157 // Maintains information about a DXVA picture buffer, i.e. whether it is |
157 // available for rendering, the texture information, etc. | 158 // available for rendering, the texture information, etc. |
158 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 159 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, | 223 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, |
223 EGL_NONE | 224 EGL_NONE |
224 }; | 225 }; |
225 | 226 |
226 picture_buffer->decoding_surface_ = eglCreatePbufferSurface( | 227 picture_buffer->decoding_surface_ = eglCreatePbufferSurface( |
227 egl_display, | 228 egl_display, |
228 egl_config, | 229 egl_config, |
229 attrib_list); | 230 attrib_list); |
230 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, | 231 RETURN_ON_FAILURE(picture_buffer->decoding_surface_, |
231 "Failed to create surface", | 232 "Failed to create surface", |
232 linked_ptr<DXVAPictureBuffer>(NULL)); | 233 linked_ptr<DXVAPictureBuffer>(nullptr)); |
233 | 234 |
234 HANDLE share_handle = NULL; | 235 HANDLE share_handle = nullptr; |
235 EGLBoolean ret = eglQuerySurfacePointerANGLE( | 236 EGLBoolean ret = eglQuerySurfacePointerANGLE( |
236 egl_display, | 237 egl_display, |
237 picture_buffer->decoding_surface_, | 238 picture_buffer->decoding_surface_, |
238 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, | 239 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, |
239 &share_handle); | 240 &share_handle); |
240 | 241 |
241 RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE, | 242 RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE, |
242 "Failed to query ANGLE surface pointer", | 243 "Failed to query ANGLE surface pointer", |
243 linked_ptr<DXVAPictureBuffer>(NULL)); | 244 linked_ptr<DXVAPictureBuffer>(nullptr)); |
244 | 245 |
245 HRESULT hr = decoder.device_->CreateTexture( | 246 HRESULT hr = decoder.device_->CreateTexture( |
246 buffer.size().width(), | 247 buffer.size().width(), |
247 buffer.size().height(), | 248 buffer.size().height(), |
248 1, | 249 1, |
249 D3DUSAGE_RENDERTARGET, | 250 D3DUSAGE_RENDERTARGET, |
250 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, | 251 use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, |
251 D3DPOOL_DEFAULT, | 252 D3DPOOL_DEFAULT, |
252 picture_buffer->decoding_texture_.Receive(), | 253 picture_buffer->decoding_texture_.Receive(), |
253 &share_handle); | 254 &share_handle); |
254 | 255 |
255 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", | 256 RETURN_ON_HR_FAILURE(hr, "Failed to create texture", |
256 linked_ptr<DXVAPictureBuffer>(NULL)); | 257 linked_ptr<DXVAPictureBuffer>(nullptr)); |
257 picture_buffer->use_rgb_ = !!use_rgb; | 258 picture_buffer->use_rgb_ = !!use_rgb; |
258 return picture_buffer; | 259 return picture_buffer; |
259 } | 260 } |
260 | 261 |
261 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( | 262 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer( |
262 const media::PictureBuffer& buffer) | 263 const media::PictureBuffer& buffer) |
263 : available_(true), | 264 : available_(true), |
264 picture_buffer_(buffer), | 265 picture_buffer_(buffer), |
265 decoding_surface_(NULL), | 266 decoding_surface_(nullptr), |
266 use_rgb_(true) { | 267 use_rgb_(true) { |
267 } | 268 } |
268 | 269 |
269 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { | 270 DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() { |
270 if (decoding_surface_) { | 271 if (decoding_surface_) { |
271 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 272 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
272 | 273 |
273 eglReleaseTexImage( | 274 eglReleaseTexImage( |
274 egl_display, | 275 egl_display, |
275 decoding_surface_, | 276 decoding_surface_, |
276 EGL_BACK_BUFFER); | 277 EGL_BACK_BUFFER); |
277 | 278 |
278 eglDestroySurface( | 279 eglDestroySurface( |
279 egl_display, | 280 egl_display, |
280 decoding_surface_); | 281 decoding_surface_); |
281 decoding_surface_ = NULL; | 282 decoding_surface_ = nullptr; |
282 } | 283 } |
283 } | 284 } |
284 | 285 |
285 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { | 286 void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() { |
286 DCHECK(decoding_surface_); | 287 DCHECK(decoding_surface_); |
287 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 288 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
288 eglReleaseTexImage( | 289 eglReleaseTexImage( |
289 egl_display, | 290 egl_display, |
290 decoding_surface_, | 291 decoding_surface_, |
291 EGL_BACK_BUFFER); | 292 EGL_BACK_BUFFER); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 | 324 |
324 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); | 325 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); |
325 | 326 |
326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
327 | 328 |
328 base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface; | 329 base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface; |
329 hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive()); | 330 hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive()); |
330 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); | 331 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false); |
331 | 332 |
332 hr = decoder.device_->StretchRect( | 333 hr = decoder.device_->StretchRect( |
333 dest_surface, NULL, d3d_surface, NULL, D3DTEXF_NONE); | 334 dest_surface, nullptr, d3d_surface, nullptr, D3DTEXF_NONE); |
334 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", | 335 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", |
335 false); | 336 false); |
336 | 337 |
337 // Ideally, this should be done immediately before the draw call that uses | 338 // Ideally, this should be done immediately before the draw call that uses |
338 // the texture. Flush it once here though. | 339 // the texture. Flush it once here though. |
339 hr = decoder.query_->Issue(D3DISSUE_END); | 340 hr = decoder.query_->Issue(D3DISSUE_END); |
340 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); | 341 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); |
341 | 342 |
342 // The DXVA decoder has its own device which it uses for decoding. ANGLE | 343 // The DXVA decoder has its own device which it uses for decoding. ANGLE |
343 // has its own device which we don't have access to. | 344 // has its own device which we don't have access to. |
344 // The above code attempts to copy the decoded picture into a surface | 345 // The above code attempts to copy the decoded picture into a surface |
345 // which is owned by ANGLE. As there are multiple devices involved in | 346 // which is owned by ANGLE. As there are multiple devices involved in |
346 // this, the StretchRect call above is not synchronous. | 347 // this, the StretchRect call above is not synchronous. |
347 // We attempt to flush the batched operations to ensure that the picture is | 348 // We attempt to flush the batched operations to ensure that the picture is |
348 // copied to the surface owned by ANGLE. | 349 // copied to the surface owned by ANGLE. |
349 // We need to do this in a loop and call flush multiple times. | 350 // We need to do this in a loop and call flush multiple times. |
350 // We have seen the GetData call for flushing the command buffer fail to | 351 // We have seen the GetData call for flushing the command buffer fail to |
351 // return success occassionally on multi core machines, leading to an | 352 // return success occassionally on multi core machines, leading to an |
352 // infinite loop. | 353 // infinite loop. |
353 // Workaround is to have an upper limit of 10 on the number of iterations to | 354 // Workaround is to have an upper limit of 10 on the number of iterations to |
354 // wait for the Flush to finish. | 355 // wait for the Flush to finish. |
355 int iterations = 0; | 356 int iterations = 0; |
356 while ((decoder.query_->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) && | 357 while ((decoder.query_->GetData(nullptr, 0, D3DGETDATA_FLUSH) == S_FALSE) && |
357 ++iterations < kMaxIterationsForD3DFlush) { | 358 ++iterations < kMaxIterationsForD3DFlush) { |
358 Sleep(1); // Poor-man's Yield(). | 359 Sleep(1); // Poor-man's Yield(). |
359 } | 360 } |
360 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 361 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
361 eglBindTexImage( | 362 eglBindTexImage( |
362 egl_display, | 363 egl_display, |
363 decoding_surface_, | 364 decoding_surface_, |
364 EGL_BACK_BUFFER); | 365 EGL_BACK_BUFFER); |
365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
366 glBindTexture(GL_TEXTURE_2D, current_texture); | 367 glBindTexture(GL_TEXTURE_2D, current_texture); |
(...skipping 28 matching lines...) Expand all Loading... |
395 present_params.PresentationInterval = 0; | 396 present_params.PresentationInterval = 0; |
396 | 397 |
397 hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, | 398 hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, |
398 D3DDEVTYPE_HAL, | 399 D3DDEVTYPE_HAL, |
399 ::GetShellWindow(), | 400 ::GetShellWindow(), |
400 D3DCREATE_FPU_PRESERVE | | 401 D3DCREATE_FPU_PRESERVE | |
401 D3DCREATE_SOFTWARE_VERTEXPROCESSING | | 402 D3DCREATE_SOFTWARE_VERTEXPROCESSING | |
402 D3DCREATE_DISABLE_PSGP_THREADING | | 403 D3DCREATE_DISABLE_PSGP_THREADING | |
403 D3DCREATE_MULTITHREADED, | 404 D3DCREATE_MULTITHREADED, |
404 &present_params, | 405 &present_params, |
405 NULL, | 406 nullptr, |
406 device_.Receive()); | 407 device_.Receive()); |
407 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false); | 408 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false); |
408 | 409 |
409 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, | 410 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, |
410 device_manager_.Receive()); | 411 device_manager_.Receive()); |
411 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); | 412 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); |
412 | 413 |
413 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); | 414 hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_); |
414 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 415 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
415 | 416 |
416 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); | 417 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); |
417 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); | 418 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); |
418 // Ensure query_ API works (to avoid an infinite loop later in | 419 // Ensure query_ API works (to avoid an infinite loop later in |
419 // CopyOutputSampleDataToPictureBuffer). | 420 // CopyOutputSampleDataToPictureBuffer). |
420 hr = query_->Issue(D3DISSUE_END); | 421 hr = query_->Issue(D3DISSUE_END); |
421 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); | 422 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); |
422 return true; | 423 return true; |
423 } | 424 } |
424 | 425 |
425 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( | 426 DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
426 const base::Callback<bool(void)>& make_context_current) | 427 const base::Callback<bool(void)>& make_context_current) |
427 : client_(NULL), | 428 : client_(nullptr), |
428 dev_manager_reset_token_(0), | 429 dev_manager_reset_token_(0), |
429 egl_config_(NULL), | 430 egl_config_(nullptr), |
430 state_(kUninitialized), | 431 state_(kUninitialized), |
431 pictures_requested_(false), | 432 pictures_requested_(false), |
432 inputs_before_decode_(0), | 433 inputs_before_decode_(0), |
433 make_context_current_(make_context_current), | 434 make_context_current_(make_context_current), |
434 weak_this_factory_(this) { | 435 weak_this_factory_(this) { |
435 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); | 436 memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
436 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); | 437 memset(&output_stream_info_, 0, sizeof(output_stream_info_)); |
437 } | 438 } |
438 | 439 |
439 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { | 440 DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() { |
440 client_ = NULL; | 441 client_ = nullptr; |
441 } | 442 } |
442 | 443 |
443 bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, | 444 bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
444 Client* client) { | 445 Client* client) { |
445 DCHECK(CalledOnValidThread()); | 446 DCHECK(CalledOnValidThread()); |
446 | 447 |
447 client_ = client; | 448 client_ = client; |
448 | 449 |
449 // Not all versions of Windows 7 and later include Media Foundation DLLs. | 450 // Not all versions of Windows 7 and later include Media Foundation DLLs. |
450 // Instead of crashing while delay loading the DLL when calling MFStartup() | 451 // Instead of crashing while delay loading the DLL when calling MFStartup() |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 GetProcAddress(decoder_dll, "DllGetClassObject")); | 673 GetProcAddress(decoder_dll, "DllGetClassObject")); |
673 RETURN_ON_FAILURE( | 674 RETURN_ON_FAILURE( |
674 get_class_object, "Failed to get DllGetClassObject pointer", false); | 675 get_class_object, "Failed to get DllGetClassObject pointer", false); |
675 | 676 |
676 base::win::ScopedComPtr<IClassFactory> factory; | 677 base::win::ScopedComPtr<IClassFactory> factory; |
677 HRESULT hr = get_class_object(__uuidof(CMSH264DecoderMFT), | 678 HRESULT hr = get_class_object(__uuidof(CMSH264DecoderMFT), |
678 __uuidof(IClassFactory), | 679 __uuidof(IClassFactory), |
679 reinterpret_cast<void**>(factory.Receive())); | 680 reinterpret_cast<void**>(factory.Receive())); |
680 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject for decoder failed", false); | 681 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject for decoder failed", false); |
681 | 682 |
682 hr = factory->CreateInstance(NULL, | 683 hr = factory->CreateInstance(nullptr, |
683 __uuidof(IMFTransform), | 684 __uuidof(IMFTransform), |
684 reinterpret_cast<void**>(decoder_.Receive())); | 685 reinterpret_cast<void**>(decoder_.Receive())); |
685 RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false); | 686 RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false); |
686 | 687 |
687 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), | 688 RETURN_ON_FAILURE(CheckDecoderDxvaSupport(), |
688 "Failed to check decoder DXVA support", false); | 689 "Failed to check decoder DXVA support", false); |
689 | 690 |
690 hr = decoder_->ProcessMessage( | 691 hr = decoder_->ProcessMessage( |
691 MFT_MESSAGE_SET_D3D_MANAGER, | 692 MFT_MESSAGE_SET_D3D_MANAGER, |
692 reinterpret_cast<ULONG_PTR>(device_manager_.get())); | 693 reinterpret_cast<ULONG_PTR>(device_manager_.get())); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 "DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE,); | 829 "DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE,); |
829 | 830 |
830 MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0}; | 831 MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0}; |
831 DWORD status = 0; | 832 DWORD status = 0; |
832 | 833 |
833 HRESULT hr = decoder_->ProcessOutput(0, // No flags | 834 HRESULT hr = decoder_->ProcessOutput(0, // No flags |
834 1, // # of out streams to pull from | 835 1, // # of out streams to pull from |
835 &output_data_buffer, | 836 &output_data_buffer, |
836 &status); | 837 &status); |
837 IMFCollection* events = output_data_buffer.pEvents; | 838 IMFCollection* events = output_data_buffer.pEvents; |
838 if (events != NULL) { | 839 if (events != nullptr) { |
839 VLOG(1) << "Got events from ProcessOuput, but discarding"; | 840 VLOG(1) << "Got events from ProcessOuput, but discarding"; |
840 events->Release(); | 841 events->Release(); |
841 } | 842 } |
842 if (FAILED(hr)) { | 843 if (FAILED(hr)) { |
843 // A stream change needs further ProcessInput calls to get back decoder | 844 // A stream change needs further ProcessInput calls to get back decoder |
844 // output which is why we need to set the state to stopped. | 845 // output which is why we need to set the state to stopped. |
845 if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { | 846 if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { |
846 if (!SetDecoderOutputMediaType(MFVideoFormat_NV12)) { | 847 if (!SetDecoderOutputMediaType(MFVideoFormat_NV12)) { |
847 // Decoder didn't let us set NV12 output format. Not sure as to why | 848 // Decoder didn't let us set NV12 output format. Not sure as to why |
848 // this can happen. Give up in disgust. | 849 // this can happen. Give up in disgust. |
(...skipping 19 matching lines...) Expand all Loading... |
868 TRACE_COUNTER1("DXVA Decoding", "TotalPacketsBeforeDecode", | 869 TRACE_COUNTER1("DXVA Decoding", "TotalPacketsBeforeDecode", |
869 inputs_before_decode_); | 870 inputs_before_decode_); |
870 | 871 |
871 inputs_before_decode_ = 0; | 872 inputs_before_decode_ = 0; |
872 | 873 |
873 RETURN_AND_NOTIFY_ON_FAILURE(ProcessOutputSample(output_data_buffer.pSample), | 874 RETURN_AND_NOTIFY_ON_FAILURE(ProcessOutputSample(output_data_buffer.pSample), |
874 "Failed to process output sample.", PLATFORM_FAILURE,); | 875 "Failed to process output sample.", PLATFORM_FAILURE,); |
875 } | 876 } |
876 | 877 |
877 bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) { | 878 bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) { |
878 RETURN_ON_FAILURE(sample, "Decode succeeded with NULL output sample", false); | 879 RETURN_ON_FAILURE(sample, "Decode succeeded with nullptr output sample", |
| 880 false); |
879 | 881 |
880 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; | 882 base::win::ScopedComPtr<IMFMediaBuffer> output_buffer; |
881 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive()); | 883 HRESULT hr = sample->GetBufferByIndex(0, output_buffer.Receive()); |
882 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); | 884 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); |
883 | 885 |
884 base::win::ScopedComPtr<IDirect3DSurface9> surface; | 886 base::win::ScopedComPtr<IDirect3DSurface9> surface; |
885 hr = MFGetService(output_buffer, MR_BUFFER_SERVICE, | 887 hr = MFGetService(output_buffer, MR_BUFFER_SERVICE, |
886 IID_PPV_ARGS(surface.Receive())); | 888 IID_PPV_ARGS(surface.Receive())); |
887 RETURN_ON_HR_FAILURE(hr, "Failed to get D3D surface from output sample", | 889 RETURN_ON_HR_FAILURE(hr, "Failed to get D3D surface from output sample", |
888 false); | 890 false); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 weak_this_factory_.GetWeakPtr())); | 992 weak_this_factory_.GetWeakPtr())); |
991 } | 993 } |
992 } | 994 } |
993 | 995 |
994 void DXVAVideoDecodeAccelerator::StopOnError( | 996 void DXVAVideoDecodeAccelerator::StopOnError( |
995 media::VideoDecodeAccelerator::Error error) { | 997 media::VideoDecodeAccelerator::Error error) { |
996 DCHECK(CalledOnValidThread()); | 998 DCHECK(CalledOnValidThread()); |
997 | 999 |
998 if (client_) | 1000 if (client_) |
999 client_->NotifyError(error); | 1001 client_->NotifyError(error); |
1000 client_ = NULL; | 1002 client_ = nullptr; |
1001 | 1003 |
1002 if (state_ != kUninitialized) { | 1004 if (state_ != kUninitialized) { |
1003 Invalidate(); | 1005 Invalidate(); |
1004 } | 1006 } |
1005 } | 1007 } |
1006 | 1008 |
1007 void DXVAVideoDecodeAccelerator::Invalidate() { | 1009 void DXVAVideoDecodeAccelerator::Invalidate() { |
1008 if (state_ == kUninitialized) | 1010 if (state_ == kUninitialized) |
1009 return; | 1011 return; |
1010 weak_this_factory_.InvalidateWeakPtrs(); | 1012 weak_this_factory_.InvalidateWeakPtrs(); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 int32 picture_buffer_id) { | 1221 int32 picture_buffer_id) { |
1220 OutputBuffers::iterator it = stale_output_picture_buffers_.find( | 1222 OutputBuffers::iterator it = stale_output_picture_buffers_.find( |
1221 picture_buffer_id); | 1223 picture_buffer_id); |
1222 DCHECK(it != stale_output_picture_buffers_.end()); | 1224 DCHECK(it != stale_output_picture_buffers_.end()); |
1223 DVLOG(1) << "Dismissing picture id: " << it->second->id(); | 1225 DVLOG(1) << "Dismissing picture id: " << it->second->id(); |
1224 client_->DismissPictureBuffer(it->second->id()); | 1226 client_->DismissPictureBuffer(it->second->id()); |
1225 stale_output_picture_buffers_.erase(it); | 1227 stale_output_picture_buffers_.erase(it); |
1226 } | 1228 } |
1227 | 1229 |
1228 } // namespace content | 1230 } // namespace content |
OLD | NEW |