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 |