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 "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 } | |
| 375 | |
| 376 H264ConfigChangeDetector::~H264ConfigChangeDetector() { | |
| 377 } | |
| 378 | |
| 379 bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream, | |
| 380 unsigned int size) { | |
| 381 std::vector<uint8_t> sps; | |
| 382 std::vector<uint8_t> pps; | |
| 383 media::H264NALU nalu; | |
| 384 bool idr_seen = false; | |
| 385 | |
| 386 media::H264Parser parser; | |
| 387 parser.SetStream(stream, size); | |
| 388 config_changed_ = false; | |
| 389 | |
| 390 while (true) { | |
| 391 media::H264Parser::Result result = parser.AdvanceToNextNALU(&nalu); | |
| 392 | |
| 393 if (result == media::H264Parser::kEOStream) | |
| 394 break; | |
| 395 | |
| 396 if (result == media::H264Parser::kUnsupportedStream) { | |
| 397 DLOG(ERROR) << "Unsupported H.264 stream"; | |
| 398 return false; | |
| 399 } | |
| 400 | |
| 401 if (result != media::H264Parser::kOk) { | |
| 402 DLOG(ERROR) << "Failed to parse H.264 stream"; | |
| 403 return false; | |
| 404 } | |
| 405 | |
| 406 switch (nalu.nal_unit_type) { | |
| 407 case media::H264NALU::kSPS: | |
| 408 result = parser.ParseSPS(&last_sps_id_); | |
| 409 if (result == media::H264Parser::kUnsupportedStream) { | |
| 410 DLOG(ERROR) << "Unsupported SPS"; | |
| 411 return false; | |
| 412 } | |
| 413 | |
| 414 if (result != media::H264Parser::kOk) { | |
| 415 DLOG(ERROR) << "Could not parse SPS"; | |
| 416 return false; | |
| 417 } | |
| 418 | |
| 419 sps.assign(nalu.data, nalu.data + nalu.size); | |
| 420 break; | |
| 421 | |
| 422 case media::H264NALU::kPPS: | |
| 423 result = parser.ParsePPS(&last_pps_id_); | |
| 424 if (result == media::H264Parser::kUnsupportedStream) { | |
| 425 DLOG(ERROR) << "Unsupported PPS"; | |
| 426 return false; | |
| 427 } | |
| 428 if (result != media::H264Parser::kOk) { | |
| 429 DLOG(ERROR) << "Could not parse PPS"; | |
| 430 return false; | |
| 431 } | |
| 432 pps.assign(nalu.data, nalu.data + nalu.size); | |
| 433 break; | |
| 434 | |
| 435 case media::H264NALU::kIDRSlice: | |
| 436 idr_seen = true; | |
| 437 break; | |
| 438 | |
| 439 default: | |
| 440 break; | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 if (!sps.empty() && sps != last_sps_) { | |
| 445 if (!last_sps_.empty() && idr_seen) | |
|
sandersd (OOO until July 31)
2016/03/18 23:38:29
I worry that Flash may send the SPS/PPS on one buf
ananta
2016/03/19 00:00:59
Thanks for pointing that out. Updated
| |
| 446 config_changed_ = true; | |
| 447 last_sps_.swap(sps); | |
| 448 } | |
| 449 | |
| 450 if (!pps.empty() && pps != last_pps_) { | |
| 451 if (!last_pps_.empty() && idr_seen) | |
| 452 config_changed_ = true; | |
| 453 last_pps_.swap(pps); | |
| 454 } | |
| 455 return true; | |
| 456 } | |
| 334 | 457 |
| 335 // Maintains information about a DXVA picture buffer, i.e. whether it is | 458 // Maintains information about a DXVA picture buffer, i.e. whether it is |
| 336 // available for rendering, the texture information, etc. | 459 // available for rendering, the texture information, etc. |
| 337 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 460 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
| 338 public: | 461 public: |
| 339 static linked_ptr<DXVAPictureBuffer> Create( | 462 static linked_ptr<DXVAPictureBuffer> Create( |
| 340 const DXVAVideoDecodeAccelerator& decoder, | 463 const DXVAVideoDecodeAccelerator& decoder, |
| 341 const media::PictureBuffer& buffer, | 464 const media::PictureBuffer& buffer, |
| 342 EGLConfig egl_config); | 465 EGLConfig egl_config); |
| 343 ~DXVAPictureBuffer(); | 466 ~DXVAPictureBuffer(); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 RETURN_AND_NOTIFY_ON_FAILURE( | 904 RETURN_AND_NOTIFY_ON_FAILURE( |
| 782 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), | 905 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), |
| 783 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", | 906 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", |
| 784 PLATFORM_FAILURE, false); | 907 PLATFORM_FAILURE, false); |
| 785 | 908 |
| 786 RETURN_AND_NOTIFY_ON_FAILURE( | 909 RETURN_AND_NOTIFY_ON_FAILURE( |
| 787 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), | 910 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), |
| 788 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", | 911 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", |
| 789 PLATFORM_FAILURE, false); | 912 PLATFORM_FAILURE, false); |
| 790 | 913 |
| 914 config_ = config; | |
| 915 | |
| 791 SetState(kNormal); | 916 SetState(kNormal); |
| 792 | 917 |
| 793 StartDecoderThread(); | 918 StartDecoderThread(); |
| 794 return true; | 919 return true; |
| 795 } | 920 } |
| 796 | 921 |
| 797 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { | 922 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { |
| 798 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); | 923 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); |
| 799 | 924 |
| 800 HRESULT hr = E_FAIL; | 925 HRESULT hr = E_FAIL; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1033 return; | 1158 return; |
| 1034 | 1159 |
| 1035 OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id); | 1160 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 | 1161 // 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 | 1162 // 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 | 1163 // 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 | 1164 // 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 | 1165 // us that we can now recycle this picture buffer, so if we were waiting to |
| 1041 // dispose of it we now can. | 1166 // dispose of it we now can. |
| 1042 if (it == output_picture_buffers_.end()) { | 1167 if (it == output_picture_buffers_.end()) { |
| 1043 it = stale_output_picture_buffers_.find(picture_buffer_id); | 1168 if (!stale_output_picture_buffers_.empty()) { |
| 1044 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), | 1169 it = stale_output_picture_buffers_.find(picture_buffer_id); |
| 1045 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); | 1170 RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(), |
| 1046 main_thread_task_runner_->PostTask( | 1171 "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,); |
| 1047 FROM_HERE, | 1172 main_thread_task_runner_->PostTask( |
| 1048 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, | 1173 FROM_HERE, |
| 1049 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); | 1174 base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer, |
| 1175 weak_this_factory_.GetWeakPtr(), picture_buffer_id)); | |
| 1176 } | |
| 1050 return; | 1177 return; |
| 1051 } | 1178 } |
| 1052 | 1179 |
| 1053 if (it->second->available() || it->second->waiting_to_reuse()) | 1180 if (it->second->available() || it->second->waiting_to_reuse()) |
| 1054 return; | 1181 return; |
| 1055 | 1182 |
| 1056 if (use_keyed_mutex_ || using_angle_device_) { | 1183 if (use_keyed_mutex_ || using_angle_device_) { |
| 1057 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), | 1184 RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(), |
| 1058 "Failed to reuse picture buffer", | 1185 "Failed to reuse picture buffer", |
| 1059 PLATFORM_FAILURE, ); | 1186 PLATFORM_FAILURE, ); |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1672 if (GetState() == kUninitialized) | 1799 if (GetState() == kUninitialized) |
| 1673 return; | 1800 return; |
| 1674 | 1801 |
| 1675 decoder_thread_.Stop(); | 1802 decoder_thread_.Stop(); |
| 1676 weak_this_factory_.InvalidateWeakPtrs(); | 1803 weak_this_factory_.InvalidateWeakPtrs(); |
| 1677 output_picture_buffers_.clear(); | 1804 output_picture_buffers_.clear(); |
| 1678 stale_output_picture_buffers_.clear(); | 1805 stale_output_picture_buffers_.clear(); |
| 1679 pending_output_samples_.clear(); | 1806 pending_output_samples_.clear(); |
| 1680 pending_input_buffers_.clear(); | 1807 pending_input_buffers_.clear(); |
| 1681 decoder_.Release(); | 1808 decoder_.Release(); |
| 1809 pictures_requested_ = false; | |
| 1682 | 1810 |
| 1683 if (use_dx11_) { | 1811 if (use_dx11_) { |
| 1684 if (video_format_converter_mft_.get()) { | 1812 if (video_format_converter_mft_.get()) { |
| 1685 video_format_converter_mft_->ProcessMessage( | 1813 video_format_converter_mft_->ProcessMessage( |
| 1686 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); | 1814 MFT_MESSAGE_NOTIFY_END_STREAMING, 0); |
| 1687 video_format_converter_mft_.Release(); | 1815 video_format_converter_mft_.Release(); |
| 1688 } | 1816 } |
| 1689 d3d11_device_context_.Release(); | 1817 d3d11_device_context_.Release(); |
| 1690 d3d11_device_.Release(); | 1818 d3d11_device_.Release(); |
| 1691 d3d11_device_manager_.Release(); | 1819 d3d11_device_manager_.Release(); |
| 1692 d3d11_query_.Release(); | 1820 d3d11_query_.Release(); |
| 1693 dx11_video_format_converter_media_type_needs_init_ = true; | 1821 dx11_video_format_converter_media_type_needs_init_ = true; |
| 1822 multi_threaded_.Release(); | |
| 1694 } else { | 1823 } else { |
| 1695 d3d9_.Release(); | 1824 d3d9_.Release(); |
| 1696 d3d9_device_ex_.Release(); | 1825 d3d9_device_ex_.Release(); |
| 1697 device_manager_.Release(); | 1826 device_manager_.Release(); |
| 1698 query_.Release(); | 1827 query_.Release(); |
| 1699 } | 1828 } |
| 1700 | 1829 |
| 1701 SetState(kUninitialized); | 1830 SetState(kUninitialized); |
| 1702 } | 1831 } |
| 1703 | 1832 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1838 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1967 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1839 | 1968 |
| 1840 if (GetState() == kUninitialized) | 1969 if (GetState() == kUninitialized) |
| 1841 return; | 1970 return; |
| 1842 | 1971 |
| 1843 if (OutputSamplesPresent() || !pending_input_buffers_.empty()) { | 1972 if (OutputSamplesPresent() || !pending_input_buffers_.empty()) { |
| 1844 pending_input_buffers_.push_back(sample); | 1973 pending_input_buffers_.push_back(sample); |
| 1845 return; | 1974 return; |
| 1846 } | 1975 } |
| 1847 | 1976 |
| 1977 // Check if the resolution, bit rate, etc changed in the stream. If yes we | |
| 1978 // reinitialize the decoder to ensure that the stream decodes correctly. | |
| 1979 bool config_changed = false; | |
| 1980 | |
| 1981 HRESULT hr = CheckConfigChanged(sample.get(), &config_changed); | |
| 1982 RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config", | |
| 1983 PLATFORM_FAILURE,); | |
| 1984 | |
| 1985 if (config_changed) { | |
| 1986 main_thread_task_runner_->PostTask( | |
| 1987 FROM_HERE, | |
| 1988 base::Bind(&DXVAVideoDecodeAccelerator::ConfigChanged, | |
| 1989 weak_this_factory_.GetWeakPtr(), | |
| 1990 config_, | |
| 1991 sample)); | |
| 1992 return; | |
| 1993 } | |
| 1994 | |
| 1848 if (!inputs_before_decode_) { | 1995 if (!inputs_before_decode_) { |
| 1849 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", | 1996 TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding", |
| 1850 this); | 1997 this); |
| 1851 } | 1998 } |
| 1852 inputs_before_decode_++; | 1999 inputs_before_decode_++; |
| 1853 | 2000 |
| 1854 HRESULT hr = decoder_->ProcessInput(0, sample.get(), 0); | 2001 hr = decoder_->ProcessInput(0, sample.get(), 0); |
| 1855 // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it | 2002 // 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 | 2003 // has enough data to produce one or more output samples. In this case the |
| 1857 // recommended options are to | 2004 // recommended options are to |
| 1858 // 1. Generate new output by calling IMFTransform::ProcessOutput until it | 2005 // 1. Generate new output by calling IMFTransform::ProcessOutput until it |
| 1859 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. | 2006 // returns MF_E_TRANSFORM_NEED_MORE_INPUT. |
| 1860 // 2. Flush the input data | 2007 // 2. Flush the input data |
| 1861 // We implement the first option, i.e to retrieve the output sample and then | 2008 // 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 | 2009 // process the input again. Failure in either of these steps is treated as a |
| 1863 // decoder failure. | 2010 // decoder failure. |
| 1864 if (hr == MF_E_NOTACCEPTING) { | 2011 if (hr == MF_E_NOTACCEPTING) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1922 input_buffer_id)); | 2069 input_buffer_id)); |
| 1923 } | 2070 } |
| 1924 | 2071 |
| 1925 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width, | 2072 void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width, |
| 1926 int height) { | 2073 int height) { |
| 1927 dx11_video_format_converter_media_type_needs_init_ = true; | 2074 dx11_video_format_converter_media_type_needs_init_ = true; |
| 1928 | 2075 |
| 1929 main_thread_task_runner_->PostTask( | 2076 main_thread_task_runner_->PostTask( |
| 1930 FROM_HERE, | 2077 FROM_HERE, |
| 1931 base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers, | 2078 base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers, |
| 1932 weak_this_factory_.GetWeakPtr())); | 2079 weak_this_factory_.GetWeakPtr(), false)); |
| 1933 | 2080 |
| 1934 main_thread_task_runner_->PostTask( | 2081 main_thread_task_runner_->PostTask( |
| 1935 FROM_HERE, | 2082 FROM_HERE, |
| 1936 base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers, | 2083 base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers, |
| 1937 weak_this_factory_.GetWeakPtr(), | 2084 weak_this_factory_.GetWeakPtr(), |
| 1938 width, | 2085 width, |
| 1939 height)); | 2086 height)); |
| 1940 } | 2087 } |
| 1941 | 2088 |
| 1942 void DXVAVideoDecodeAccelerator::DismissStaleBuffers() { | 2089 void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) { |
| 1943 OutputBuffers::iterator index; | 2090 OutputBuffers::iterator index; |
| 1944 | 2091 |
| 1945 for (index = output_picture_buffers_.begin(); | 2092 for (index = output_picture_buffers_.begin(); |
| 1946 index != output_picture_buffers_.end(); | 2093 index != output_picture_buffers_.end(); |
| 1947 ++index) { | 2094 ++index) { |
| 1948 if (index->second->available()) { | 2095 if (force || index->second->available()) { |
| 1949 DVLOG(1) << "Dismissing picture id: " << index->second->id(); | 2096 DVLOG(1) << "Dismissing picture id: " << index->second->id(); |
| 1950 client_->DismissPictureBuffer(index->second->id()); | 2097 client_->DismissPictureBuffer(index->second->id()); |
| 1951 } else { | 2098 } else { |
| 1952 // Move to |stale_output_picture_buffers_| for deferred deletion. | 2099 // Move to |stale_output_picture_buffers_| for deferred deletion. |
| 1953 stale_output_picture_buffers_.insert( | 2100 stale_output_picture_buffers_.insert( |
| 1954 std::make_pair(index->first, index->second)); | 2101 std::make_pair(index->first, index->second)); |
| 1955 } | 2102 } |
| 1956 } | 2103 } |
| 1957 | 2104 |
| 1958 output_picture_buffers_.clear(); | 2105 output_picture_buffers_.clear(); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2447 } | 2594 } |
| 2448 hr = transform->SetOutputType(0, media_type.get(), 0); // No flags | 2595 hr = transform->SetOutputType(0, media_type.get(), 0); // No flags |
| 2449 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); | 2596 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
| 2450 return true; | 2597 return true; |
| 2451 } | 2598 } |
| 2452 media_type.Release(); | 2599 media_type.Release(); |
| 2453 } | 2600 } |
| 2454 return false; | 2601 return false; |
| 2455 } | 2602 } |
| 2456 | 2603 |
| 2604 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged( | |
| 2605 IMFSample* sample, bool* config_changed) { | |
| 2606 if (codec_ != media::kCodecH264) | |
| 2607 return S_FALSE; | |
| 2608 | |
| 2609 base::win::ScopedComPtr<IMFMediaBuffer> buffer; | |
| 2610 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); | |
| 2611 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); | |
| 2612 | |
| 2613 MediaBufferScopedPointer scoped_media_buffer(buffer.get()); | |
| 2614 | |
| 2615 if (!config_change_detector_.DetectConfig( | |
| 2616 scoped_media_buffer.get(), | |
| 2617 scoped_media_buffer.current_length())) { | |
| 2618 RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config", | |
| 2619 E_FAIL); | |
| 2620 } | |
| 2621 *config_changed = config_change_detector_.config_changed(); | |
| 2622 return S_OK; | |
| 2623 } | |
| 2624 | |
| 2625 void DXVAVideoDecodeAccelerator::ConfigChanged( | |
| 2626 const Config& config, | |
| 2627 const base::win::ScopedComPtr<IMFSample>& input_sample) { | |
| 2628 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | |
| 2629 DismissStaleBuffers(true); | |
| 2630 Invalidate(); | |
| 2631 Initialize(config_, client_); | |
| 2632 decoder_thread_task_runner_->PostTask( | |
| 2633 FROM_HERE, | |
| 2634 base::Bind(&DXVAVideoDecodeAccelerator::DecodeInternal, | |
| 2635 base::Unretained(this), input_sample)); | |
| 2636 } | |
| 2637 | |
| 2457 } // namespace content | 2638 } // namespace content |
| OLD | NEW |