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_win.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.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 16 matching lines...) Expand all Loading... |
27 #include "base/logging.h" | 27 #include "base/logging.h" |
28 #include "base/macros.h" | 28 #include "base/macros.h" |
29 #include "base/memory/scoped_ptr.h" | 29 #include "base/memory/scoped_ptr.h" |
30 #include "base/memory/shared_memory.h" | 30 #include "base/memory/shared_memory.h" |
31 #include "base/message_loop/message_loop.h" | 31 #include "base/message_loop/message_loop.h" |
32 #include "base/path_service.h" | 32 #include "base/path_service.h" |
33 #include "base/trace_event/trace_event.h" | 33 #include "base/trace_event/trace_event.h" |
34 #include "base/win/windows_version.h" | 34 #include "base/win/windows_version.h" |
35 #include "build/build_config.h" | 35 #include "build/build_config.h" |
36 #include "media/base/win/mf_initializer.h" | 36 #include "media/base/win/mf_initializer.h" |
| 37 #include "media/filters/h264_parser.h" |
37 #include "media/video/video_decode_accelerator.h" | 38 #include "media/video/video_decode_accelerator.h" |
38 #include "third_party/angle/include/EGL/egl.h" | 39 #include "third_party/angle/include/EGL/egl.h" |
39 #include "third_party/angle/include/EGL/eglext.h" | 40 #include "third_party/angle/include/EGL/eglext.h" |
40 #include "ui/gl/gl_bindings.h" | 41 #include "ui/gl/gl_bindings.h" |
41 #include "ui/gl/gl_context.h" | 42 #include "ui/gl/gl_context.h" |
42 #include "ui/gl/gl_fence.h" | 43 #include "ui/gl/gl_fence.h" |
43 #include "ui/gl/gl_surface_egl.h" | 44 #include "ui/gl/gl_surface_egl.h" |
44 | 45 |
45 namespace { | 46 namespace { |
46 | 47 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 #endif | 105 #endif |
105 | 106 |
106 // MF_XVP_PLAYBACK_MODE | 107 // MF_XVP_PLAYBACK_MODE |
107 // Data type: UINT32 (treat as BOOL) | 108 // Data type: UINT32 (treat as BOOL) |
108 // If this attribute is TRUE, the video processor will run in playback mode | 109 // If this attribute is TRUE, the video processor will run in playback mode |
109 // where it allows callers to allocate output samples and allows last frame | 110 // where it allows callers to allocate output samples and allows last frame |
110 // regeneration (repaint). | 111 // regeneration (repaint). |
111 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, | 112 DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, |
112 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); | 113 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9); |
113 | 114 |
| 115 // Provides scoped access to the underlying buffer in an IMFMediaBuffer |
| 116 // instance. |
| 117 class MediaBufferScopedPointer { |
| 118 public: |
| 119 MediaBufferScopedPointer(IMFMediaBuffer* media_buffer) |
| 120 : media_buffer_(media_buffer), |
| 121 buffer_(nullptr), |
| 122 max_length_(0), |
| 123 current_length_(0) { |
| 124 HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, ¤t_length_); |
| 125 CHECK(SUCCEEDED(hr)); |
| 126 } |
| 127 |
| 128 ~MediaBufferScopedPointer() { |
| 129 HRESULT hr = media_buffer_->Unlock(); |
| 130 CHECK(SUCCEEDED(hr)); |
| 131 } |
| 132 |
| 133 uint8_t* get() { |
| 134 return buffer_; |
| 135 } |
| 136 |
| 137 DWORD current_length() const { |
| 138 return current_length_; |
| 139 } |
| 140 |
| 141 private: |
| 142 base::win::ScopedComPtr<IMFMediaBuffer> media_buffer_; |
| 143 uint8_t* buffer_; |
| 144 DWORD max_length_; |
| 145 DWORD current_length_; |
| 146 |
| 147 DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer); |
| 148 }; |
| 149 |
114 } // namespace | 150 } // namespace |
115 | 151 |
116 namespace content { | 152 namespace content { |
117 | 153 |
118 static const media::VideoCodecProfile kSupportedProfiles[] = { | 154 static const media::VideoCodecProfile kSupportedProfiles[] = { |
119 media::H264PROFILE_BASELINE, | 155 media::H264PROFILE_BASELINE, |
120 media::H264PROFILE_MAIN, | 156 media::H264PROFILE_MAIN, |
121 media::H264PROFILE_HIGH, | 157 media::H264PROFILE_HIGH, |
122 media::VP8PROFILE_ANY, | 158 media::VP8PROFILE_ANY, |
123 media::VP9PROFILE_ANY | 159 media::VP9PROFILE_ANY |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device), | 360 reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device), |
325 "The eglQueryDeviceAttribEXT function failed to get the device", | 361 "The eglQueryDeviceAttribEXT function failed to get the device", |
326 device_object); | 362 device_object); |
327 | 363 |
328 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object); | 364 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object); |
329 | 365 |
330 device_object = reinterpret_cast<T*>(device); | 366 device_object = reinterpret_cast<T*>(device); |
331 return device_object; | 367 return device_object; |
332 } | 368 } |
333 | 369 |
| 370 H264ConfigChangeDetector::H264ConfigChangeDetector() |
| 371 : last_sps_id_(0), |
| 372 last_pps_id_(0), |
| 373 config_changed_(false), |
| 374 pending_config_changed_(false) { |
| 375 } |
| 376 |
| 377 H264ConfigChangeDetector::~H264ConfigChangeDetector() { |
| 378 } |
| 379 |
| 380 bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream, |
| 381 unsigned int size) { |
| 382 std::vector<uint8_t> sps; |
| 383 std::vector<uint8_t> pps; |
| 384 media::H264NALU nalu; |
| 385 bool idr_seen = false; |
| 386 |
| 387 media::H264Parser parser; |
| 388 parser.SetStream(stream, size); |
| 389 config_changed_ = false; |
| 390 |
| 391 while (true) { |
| 392 media::H264Parser::Result result = parser.AdvanceToNextNALU(&nalu); |
| 393 |
| 394 if (result == media::H264Parser::kEOStream) |
| 395 break; |
| 396 |
| 397 if (result == media::H264Parser::kUnsupportedStream) { |
| 398 DLOG(ERROR) << "Unsupported H.264 stream"; |
| 399 return false; |
| 400 } |
| 401 |
| 402 if (result != media::H264Parser::kOk) { |
| 403 DLOG(ERROR) << "Failed to parse H.264 stream"; |
| 404 return false; |
| 405 } |
| 406 |
| 407 switch (nalu.nal_unit_type) { |
| 408 case media::H264NALU::kSPS: |
| 409 result = parser.ParseSPS(&last_sps_id_); |
| 410 if (result == media::H264Parser::kUnsupportedStream) { |
| 411 DLOG(ERROR) << "Unsupported SPS"; |
| 412 return false; |
| 413 } |
| 414 |
| 415 if (result != media::H264Parser::kOk) { |
| 416 DLOG(ERROR) << "Could not parse SPS"; |
| 417 return false; |
| 418 } |
| 419 |
| 420 sps.assign(nalu.data, nalu.data + nalu.size); |
| 421 break; |
| 422 |
| 423 case media::H264NALU::kPPS: |
| 424 result = parser.ParsePPS(&last_pps_id_); |
| 425 if (result == media::H264Parser::kUnsupportedStream) { |
| 426 DLOG(ERROR) << "Unsupported PPS"; |
| 427 return false; |
| 428 } |
| 429 if (result != media::H264Parser::kOk) { |
| 430 DLOG(ERROR) << "Could not parse PPS"; |
| 431 return false; |
| 432 } |
| 433 pps.assign(nalu.data, nalu.data + nalu.size); |
| 434 break; |
| 435 |
| 436 case media::H264NALU::kIDRSlice: |
| 437 idr_seen = true; |
| 438 // If we previously detected a configuration change, and see an IDR |
| 439 // slice next time around, we need to flag a configuration change. |
| 440 if (pending_config_changed_) { |
| 441 config_changed_ = true; |
| 442 pending_config_changed_ = false; |
| 443 } |
| 444 break; |
| 445 |
| 446 default: |
| 447 break; |
| 448 } |
| 449 } |
| 450 |
| 451 if (!sps.empty() && sps != last_sps_) { |
| 452 if (!last_sps_.empty()) { |
| 453 // Flag configuration changes after we see an IDR slice. |
| 454 if (idr_seen) { |
| 455 config_changed_ = true; |
| 456 } else { |
| 457 pending_config_changed_ = true; |
| 458 } |
| 459 } |
| 460 last_sps_.swap(sps); |
| 461 } |
| 462 |
| 463 if (!pps.empty() && pps != last_pps_) { |
| 464 if (!last_pps_.empty()) { |
| 465 // Flag configuration changes after we see an IDR slice. |
| 466 if (idr_seen) { |
| 467 config_changed_ = true; |
| 468 } else { |
| 469 pending_config_changed_ = true; |
| 470 } |
| 471 } |
| 472 last_pps_.swap(pps); |
| 473 } |
| 474 return true; |
| 475 } |
334 | 476 |
335 // Maintains information about a DXVA picture buffer, i.e. whether it is | 477 // Maintains information about a DXVA picture buffer, i.e. whether it is |
336 // available for rendering, the texture information, etc. | 478 // available for rendering, the texture information, etc. |
337 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 479 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
338 public: | 480 public: |
339 static linked_ptr<DXVAPictureBuffer> Create( | 481 static linked_ptr<DXVAPictureBuffer> Create( |
340 const DXVAVideoDecodeAccelerator& decoder, | 482 const DXVAVideoDecodeAccelerator& decoder, |
341 const media::PictureBuffer& buffer, | 483 const media::PictureBuffer& buffer, |
342 EGLConfig egl_config); | 484 EGLConfig egl_config); |
343 ~DXVAPictureBuffer(); | 485 ~DXVAPictureBuffer(); |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 RETURN_AND_NOTIFY_ON_FAILURE( | 923 RETURN_AND_NOTIFY_ON_FAILURE( |
782 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), | 924 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), |
783 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", | 925 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", |
784 PLATFORM_FAILURE, false); | 926 PLATFORM_FAILURE, false); |
785 | 927 |
786 RETURN_AND_NOTIFY_ON_FAILURE( | 928 RETURN_AND_NOTIFY_ON_FAILURE( |
787 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), | 929 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), |
788 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", | 930 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", |
789 PLATFORM_FAILURE, false); | 931 PLATFORM_FAILURE, false); |
790 | 932 |
| 933 config_ = config; |
| 934 |
791 SetState(kNormal); | 935 SetState(kNormal); |
792 | 936 |
793 StartDecoderThread(); | 937 StartDecoderThread(); |
794 return true; | 938 return true; |
795 } | 939 } |
796 | 940 |
797 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { | 941 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { |
798 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); | 942 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); |
799 | 943 |
800 HRESULT hr = E_FAIL; | 944 HRESULT hr = E_FAIL; |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 return; | 1177 return; |
1034 | 1178 |
1035 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 1179 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); |
1036 // If we didn't find the picture id in the |output_picture_buffers_| map we | 1180 // If we didn't find the picture id in the |output_picture_buffers_| map we |
1037 // try the |stale_output_picture_buffers_| map, as this may have been an | 1181 // try the |stale_output_picture_buffers_| map, as this may have been an |
1038 // output picture buffer from before a resolution change, that at resolution | 1182 // output picture buffer from before a resolution change, that at resolution |
1039 // change time had yet to be displayed. The client is calling us back to tell | 1183 // change time had yet to be displayed. The client is calling us back to tell |
1040 // us that we can now recycle this picture buffer, so if we were waiting to | 1184 // us that we can now recycle this picture buffer, so if we were waiting to |
1041 // dispose of it we now can. | 1185 // dispose of it we now can. |
1042 if (it == output_picture_buffers_.end()) { | 1186 if (it == output_picture_buffers_.end()) { |
1043 it = stale_output_picture_buffers_.find(picture_buffer_id); | 1187 if (!stale_output_picture_buffers_.empty()) { |
1044 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), | 1188 it = stale_output_picture_buffers_.find(picture_buffer_id); |
1045 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); | 1189 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), |
1046 main_thread_task_runner_->PostTask( | 1190 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); |
1047 FROM_HERE, | 1191 main_thread_task_runner_->PostTask( |
1048 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, | 1192 FROM_HERE, |
1049 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); | 1193 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, |
| 1194 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); |
| 1195 } |
1050 return; | 1196 return; |
1051 } | 1197 } |
1052 | 1198 |
1053 if (it->second->available() || it->second->waiting_to_reuse()) | 1199 if (it->second->available() || it->second->waiting_to_reuse()) |
1054 return; | 1200 return; |
1055 | 1201 |
1056 if (use_keyed_mutex_ || using_angle_device_) { | 1202 if (use_keyed_mutex_ || using_angle_device_) { |
1057 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), | 1203 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), |
1058 "Failed to reuse picture buffer", | 1204 "Failed to reuse picture buffer", |
1059 PLATFORM_FAILURE, ); | 1205 PLATFORM_FAILURE, ); |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1672 if (GetState() == kUninitialized) | 1818 if (GetState() == kUninitialized) |
1673 return; | 1819 return; |
1674 | 1820 |
1675 decoder_thread_.Stop(); | 1821 decoder_thread_.Stop(); |
1676 weak_this_factory_.InvalidateWeakPtrs(); | 1822 weak_this_factory_.InvalidateWeakPtrs(); |
1677 output_picture_buffers_.clear(); | 1823 output_picture_buffers_.clear(); |
1678 stale_output_picture_buffers_.clear(); | 1824 stale_output_picture_buffers_.clear(); |
1679 pending_output_samples_.clear(); | 1825 pending_output_samples_.clear(); |
1680 pending_input_buffers_.clear(); | 1826 pending_input_buffers_.clear(); |
1681 decoder_.Release(); | 1827 decoder_.Release(); |
| 1828 pictures_requested_ = false; |
1682 | 1829 |
1683 if (use_dx11_) { | 1830 if (use_dx11_) { |
1684 if (video_format_converter_mft_.get()) { | 1831 if (video_format_converter_mft_.get()) { |
1685 video_format_converter_mft_->ProcessMessage( | 1832 video_format_converter_mft_->ProcessMessage( |
1686 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); | 1833 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); |
1687 video_format_converter_mft_.Release(); | 1834 video_format_converter_mft_.Release(); |
1688 } | 1835 } |
1689 d3d11_device_context_.Release(); | 1836 d3d11_device_context_.Release(); |
1690 d3d11_device_.Release(); | 1837 d3d11_device_.Release(); |
1691 d3d11_device_manager_.Release(); | 1838 d3d11_device_manager_.Release(); |
1692 d3d11_query_.Release(); | 1839 d3d11_query_.Release(); |
1693 dx11_video_format_converter_media_type_needs_init_ = true; | 1840 dx11_video_format_converter_media_type_needs_init_ = true; |
| 1841 multi_threaded_.Release(); |
1694 } else { | 1842 } else { |
1695 d3d9_.Release(); | 1843 d3d9_.Release(); |
1696 d3d9_device_ex_.Release(); | 1844 d3d9_device_ex_.Release(); |
1697 device_manager_.Release(); | 1845 device_manager_.Release(); |
1698 query_.Release(); | 1846 query_.Release(); |
1699 } | 1847 } |
1700 | 1848 |
1701 SetState(kUninitialized); | 1849 SetState(kUninitialized); |
1702 } | 1850 } |
1703 | 1851 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1986 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
1839 | 1987 |
1840 if (GetState() == kUninitialized) | 1988 if (GetState() == kUninitialized) |
1841 return; | 1989 return; |
1842 | 1990 |
1843 if (OutputSamplesPresent() || !pending_input_buffers_.empty()) { | 1991 if (OutputSamplesPresent() || !pending_input_buffers_.empty()) { |
1844 pending_input_buffers_.push_back(sample); | 1992 pending_input_buffers_.push_back(sample); |
1845 return; | 1993 return; |
1846 } | 1994 } |
1847 | 1995 |
| 1996 // Check if the resolution, bit rate, etc changed in the stream. If yes we |
| 1997 // reinitialize the decoder to ensure that the stream decodes correctly. |
| 1998 bool config_changed = false; |
| 1999 |
| 2000 HRESULT hr = CheckConfigChanged(sample.get(), &config_changed); |
| 2001 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config", |
| 2002 PLATFORM_FAILURE,); |
| 2003 |
| 2004 if (config_changed) { |
| 2005 main_thread_task_runner_->PostTask( |
| 2006 FROM_HERE, |
| 2007 base::Bind(&DXVAVideoDecodeAccelerator::ConfigChanged, |
| 2008 weak_this_factory_.GetWeakPtr(), |
| 2009 config_, |
| 2010 sample)); |
| 2011 return; |
| 2012 } |
| 2013 |
1848 if (!inputs_before_decode_) { | 2014 if (!inputs_before_decode_) { |
1849 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", | 2015 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", |
1850 this); | 2016 this); |
1851 } | 2017 } |
1852 inputs_before_decode_++; | 2018 inputs_before_decode_++; |
1853 | 2019 |
1854 HRESULT hr = decoder_->ProcessInput(0, sample.get(), 0); | 2020 hr = decoder_->ProcessInput(0, sample.get(), 0); |
1855 // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it | 2021 // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it |
1856 // has enough data to produce one or more output samples. In this case the | 2022 // has enough data to produce one or more output samples. In this case the |
1857 // recommended options are to | 2023 // recommended options are to |
1858 // 1. Generate new output by calling IMFTransform::ProcessOutput until it | 2024 // 1. Generate new output by calling IMFTransform::ProcessOutput until it |
1859 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. | 2025 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. |
1860 // 2. Flush the input data | 2026 // 2. Flush the input data |
1861 // We implement the first option, i.e to retrieve the output sample and then | 2027 // We implement the first option, i.e to retrieve the output sample and then |
1862 // process the input again. Failure in either of these steps is treated as a | 2028 // process the input again. Failure in either of these steps is treated as a |
1863 // decoder failure. | 2029 // decoder failure. |
1864 if (hr == MF_E_NOTACCEPTING) { | 2030 if (hr == MF_E_NOTACCEPTING) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1922 input_buffer_id)); | 2088 input_buffer_id)); |
1923 } | 2089 } |
1924 | 2090 |
1925 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width, | 2091 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width, |
1926 int height) { | 2092 int height) { |
1927 dx11_video_format_converter_media_type_needs_init_ = true; | 2093 dx11_video_format_converter_media_type_needs_init_ = true; |
1928 | 2094 |
1929 main_thread_task_runner_->PostTask( | 2095 main_thread_task_runner_->PostTask( |
1930 FROM_HERE, | 2096 FROM_HERE, |
1931 base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers, | 2097 base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers, |
1932 weak_this_factory_.GetWeakPtr())); | 2098 weak_this_factory_.GetWeakPtr(), false)); |
1933 | 2099 |
1934 main_thread_task_runner_->PostTask( | 2100 main_thread_task_runner_->PostTask( |
1935 FROM_HERE, | 2101 FROM_HERE, |
1936 base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers, | 2102 base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers, |
1937 weak_this_factory_.GetWeakPtr(), | 2103 weak_this_factory_.GetWeakPtr(), |
1938 width, | 2104 width, |
1939 height)); | 2105 height)); |
1940 } | 2106 } |
1941 | 2107 |
1942 void DXVAVideoDecodeAccelerator::DismissStaleBuffers() { | 2108 void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) { |
1943 OutputBuffers::iterator index; | 2109 OutputBuffers::iterator index; |
1944 | 2110 |
1945 for (index = output_picture_buffers_.begin(); | 2111 for (index = output_picture_buffers_.begin(); |
1946 index != output_picture_buffers_.end(); | 2112 index != output_picture_buffers_.end(); |
1947 ++index) { | 2113 ++index) { |
1948 if (index->second->available()) { | 2114 if (force || index->second->available()) { |
1949 DVLOG(1) << "Dismissing picture id: " << index->second->id(); | 2115 DVLOG(1) << "Dismissing picture id: " << index->second->id(); |
1950 client_->DismissPictureBuffer(index->second->id()); | 2116 client_->DismissPictureBuffer(index->second->id()); |
1951 } else { | 2117 } else { |
1952 // Move to |stale_output_picture_buffers_| for deferred deletion. | 2118 // Move to |stale_output_picture_buffers_| for deferred deletion. |
1953 stale_output_picture_buffers_.insert( | 2119 stale_output_picture_buffers_.insert( |
1954 std::make_pair(index->first, index->second)); | 2120 std::make_pair(index->first, index->second)); |
1955 } | 2121 } |
1956 } | 2122 } |
1957 | 2123 |
1958 output_picture_buffers_.clear(); | 2124 output_picture_buffers_.clear(); |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2447 } | 2613 } |
2448 hr = transform->SetOutputType(0, media_type.get(), 0); // No flags | 2614 hr = transform->SetOutputType(0, media_type.get(), 0); // No flags |
2449 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); | 2615 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
2450 return true; | 2616 return true; |
2451 } | 2617 } |
2452 media_type.Release(); | 2618 media_type.Release(); |
2453 } | 2619 } |
2454 return false; | 2620 return false; |
2455 } | 2621 } |
2456 | 2622 |
| 2623 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged( |
| 2624 IMFSample* sample, bool* config_changed) { |
| 2625 if (codec_ != media::kCodecH264) |
| 2626 return S_FALSE; |
| 2627 |
| 2628 base::win::ScopedComPtr<IMFMediaBuffer> buffer; |
| 2629 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); |
| 2630 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); |
| 2631 |
| 2632 MediaBufferScopedPointer scoped_media_buffer(buffer.get()); |
| 2633 |
| 2634 if (!config_change_detector_.DetectConfig( |
| 2635 scoped_media_buffer.get(), |
| 2636 scoped_media_buffer.current_length())) { |
| 2637 RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config", |
| 2638 E_FAIL); |
| 2639 } |
| 2640 *config_changed = config_change_detector_.config_changed(); |
| 2641 return S_OK; |
| 2642 } |
| 2643 |
| 2644 void DXVAVideoDecodeAccelerator::ConfigChanged( |
| 2645 const Config& config, |
| 2646 const base::win::ScopedComPtr<IMFSample>& input_sample) { |
| 2647 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
| 2648 DismissStaleBuffers(true); |
| 2649 Invalidate(); |
| 2650 Initialize(config_, client_); |
| 2651 decoder_thread_task_runner_->PostTask( |
| 2652 FROM_HERE, |
| 2653 base::Bind(&DXVAVideoDecodeAccelerator::DecodeInternal, |
| 2654 base::Unretained(this), input_sample)); |
| 2655 } |
| 2656 |
2457 } // namespace content | 2657 } // namespace content |
OLD | NEW |