OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #ifdef WINVER | 5 #ifdef WINVER |
6 #undef WINVER | 6 #undef WINVER |
7 #define WINVER 0x0601 // Windows 7 | 7 #define WINVER 0x0601 // Windows 7 |
8 #endif | 8 #endif |
9 | 9 |
10 #include <d3d9.h> | 10 #include <d3d9.h> |
11 #include <dxva2api.h> | 11 #include <dxva2api.h> |
12 #include <evr.h> | 12 #include <evr.h> |
13 #include <mfapi.h> | 13 #include <mfapi.h> |
14 #include <mferror.h> | 14 #include <mferror.h> |
15 #include <mfreadwrite.h> // depends on evr.h | 15 #include <mfreadwrite.h> // depends on evr.h |
16 #include <windows.h> | 16 #include <windows.h> |
17 | 17 |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/scoped_comptr_win.h" | 19 #include "base/win/scoped_comptr.h" |
20 #include "media/tools/mfdecoder/mfdecoder.h" | 20 #include "media/tools/mfdecoder/mfdecoder.h" |
21 | 21 |
22 #pragma comment(lib, "shlwapi.lib") | 22 #pragma comment(lib, "shlwapi.lib") |
23 #pragma comment(lib, "strmiids.lib") | 23 #pragma comment(lib, "strmiids.lib") |
24 #pragma comment(lib, "dxva2.lib") | 24 #pragma comment(lib, "dxva2.lib") |
25 #pragma comment(lib, "d3d9.lib") | 25 #pragma comment(lib, "d3d9.lib") |
26 #pragma comment(lib, "mfuuid.lib") | 26 #pragma comment(lib, "mfuuid.lib") |
27 #pragma comment(lib, "mfplat.lib") | 27 #pragma comment(lib, "mfplat.lib") |
28 #pragma comment(lib, "mf.lib") | 28 #pragma comment(lib, "mf.lib") |
29 #pragma comment(lib, "evr.lib") | 29 #pragma comment(lib, "evr.lib") |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 if (!InitVideoInfo(dev_manager)) | 82 if (!InitVideoInfo(dev_manager)) |
83 return false; | 83 return false; |
84 | 84 |
85 initialized_ = true; | 85 initialized_ = true; |
86 return true; | 86 return true; |
87 } | 87 } |
88 | 88 |
89 IMFSample* MFDecoder::ReadVideoSample() { | 89 IMFSample* MFDecoder::ReadVideoSample() { |
90 CHECK(reader_ != NULL); | 90 CHECK(reader_ != NULL); |
91 CHECK_GE(video_stream_index_, 0); | 91 CHECK_GE(video_stream_index_, 0); |
92 ScopedComPtr<IMFSample> video_sample; | 92 base::win::ScopedComPtr<IMFSample> video_sample; |
93 DWORD actual_stream_index; | 93 DWORD actual_stream_index; |
94 DWORD output_flags; | 94 DWORD output_flags; |
95 | 95 |
96 // TODO(imcheng): Get timestamp back instead by passing in a timestamp pointer | 96 // TODO(imcheng): Get timestamp back instead by passing in a timestamp pointer |
97 // instead of NULL. | 97 // instead of NULL. |
98 // TODO(imcheng): Read samples asynchronously and use callbacks. | 98 // TODO(imcheng): Read samples asynchronously and use callbacks. |
99 HRESULT hr = reader_->ReadSample(video_stream_index_, | 99 HRESULT hr = reader_->ReadSample(video_stream_index_, |
100 0, // No flags. | 100 0, // No flags. |
101 &actual_stream_index, | 101 &actual_stream_index, |
102 &output_flags, | 102 &output_flags, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 return false; | 146 return false; |
147 } | 147 } |
148 mf_lib_initialized_ = true; | 148 mf_lib_initialized_ = true; |
149 | 149 |
150 return true; | 150 return true; |
151 } | 151 } |
152 | 152 |
153 bool MFDecoder::InitSourceReader(const wchar_t* source_url, | 153 bool MFDecoder::InitSourceReader(const wchar_t* source_url, |
154 IDirect3DDeviceManager9* dev_manager) { | 154 IDirect3DDeviceManager9* dev_manager) { |
155 CHECK(source_url != NULL); | 155 CHECK(source_url != NULL); |
156 ScopedComPtr<IMFAttributes> reader_attributes; | 156 base::win::ScopedComPtr<IMFAttributes> reader_attributes; |
157 if (use_dxva2_) { | 157 if (use_dxva2_) { |
158 reader_attributes.Attach(GetDXVA2AttributesForSourceReader(dev_manager)); | 158 reader_attributes.Attach(GetDXVA2AttributesForSourceReader(dev_manager)); |
159 if (reader_attributes == NULL) { | 159 if (reader_attributes == NULL) { |
160 LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; | 160 LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; |
161 return false; | 161 return false; |
162 } | 162 } |
163 } | 163 } |
164 HRESULT hr = MFCreateSourceReaderFromURL(source_url, reader_attributes.get(), | 164 HRESULT hr = MFCreateSourceReaderFromURL(source_url, reader_attributes.get(), |
165 &reader_); | 165 &reader_); |
166 if (FAILED(hr)) { | 166 if (FAILED(hr)) { |
167 LOG(ERROR) << "Failed to create source reader"; | 167 LOG(ERROR) << "Failed to create source reader"; |
168 return false; | 168 return false; |
169 } | 169 } |
170 VLOG(1) << "Source reader created"; | 170 VLOG(1) << "Source reader created"; |
171 return true; | 171 return true; |
172 } | 172 } |
173 | 173 |
174 IMFAttributes* MFDecoder::GetDXVA2AttributesForSourceReader( | 174 IMFAttributes* MFDecoder::GetDXVA2AttributesForSourceReader( |
175 IDirect3DDeviceManager9* dev_manager) { | 175 IDirect3DDeviceManager9* dev_manager) { |
176 if (!use_dxva2_) | 176 if (!use_dxva2_) |
177 return NULL; | 177 return NULL; |
178 CHECK(dev_manager != NULL); | 178 CHECK(dev_manager != NULL); |
179 ScopedComPtr<IMFAttributes> attributes; | 179 base::win::ScopedComPtr<IMFAttributes> attributes; |
180 | 180 |
181 // Create an attribute store with an initial size of 2. | 181 // Create an attribute store with an initial size of 2. |
182 HRESULT hr = MFCreateAttributes(attributes.Receive(), 2); | 182 HRESULT hr = MFCreateAttributes(attributes.Receive(), 2); |
183 if (FAILED(hr)) { | 183 if (FAILED(hr)) { |
184 LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; | 184 LOG(ERROR) << "Failed to create DXVA2 attributes for source reader"; |
185 return NULL; | 185 return NULL; |
186 } | 186 } |
187 hr = attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, dev_manager); | 187 hr = attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, dev_manager); |
188 if (FAILED(hr)) { | 188 if (FAILED(hr)) { |
189 LOG(ERROR) << "Failed to set D3D9 manager to attribute"; | 189 LOG(ERROR) << "Failed to set D3D9 manager to attribute"; |
190 return NULL; | 190 return NULL; |
191 } | 191 } |
192 hr = attributes->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, FALSE); | 192 hr = attributes->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, FALSE); |
193 if (FAILED(hr)) { | 193 if (FAILED(hr)) { |
194 LOG(ERROR) << "Failed to set DISABLE_DXVA to false"; | 194 LOG(ERROR) << "Failed to set DISABLE_DXVA to false"; |
195 return NULL; | 195 return NULL; |
196 } | 196 } |
197 return attributes.Detach(); | 197 return attributes.Detach(); |
198 } | 198 } |
199 | 199 |
200 bool MFDecoder::SelectVideoStreamOnly() { | 200 bool MFDecoder::SelectVideoStreamOnly() { |
201 CHECK(reader_ != NULL); | 201 CHECK(reader_ != NULL); |
202 HRESULT hr; | 202 HRESULT hr; |
203 for (DWORD stream_index = 0; ; stream_index++) { | 203 for (DWORD stream_index = 0; ; stream_index++) { |
204 ScopedComPtr<IMFMediaType> media_type; | 204 base::win::ScopedComPtr<IMFMediaType> media_type; |
205 hr = reader_->GetCurrentMediaType(stream_index, media_type.Receive()); | 205 hr = reader_->GetCurrentMediaType(stream_index, media_type.Receive()); |
206 if (SUCCEEDED(hr)) { | 206 if (SUCCEEDED(hr)) { |
207 GUID major_type; | 207 GUID major_type; |
208 hr = media_type->GetMajorType(&major_type); | 208 hr = media_type->GetMajorType(&major_type); |
209 if (FAILED(hr)) { | 209 if (FAILED(hr)) { |
210 LOG(ERROR) << "Could not determine major type for stream " | 210 LOG(ERROR) << "Could not determine major type for stream " |
211 << stream_index; | 211 << stream_index; |
212 return false; | 212 return false; |
213 } | 213 } |
214 if (major_type != MFMediaType_Video) { | 214 if (major_type != MFMediaType_Video) { |
(...skipping 19 matching lines...) Expand all Loading... |
234 LOG(ERROR) << "Error occurred while getting stream " << stream_index; | 234 LOG(ERROR) << "Error occurred while getting stream " << stream_index; |
235 return false; | 235 return false; |
236 } | 236 } |
237 } // end of for-loop | 237 } // end of for-loop |
238 return video_stream_index_ >= 0; | 238 return video_stream_index_ >= 0; |
239 } | 239 } |
240 | 240 |
241 bool MFDecoder::InitVideoInfo(IDirect3DDeviceManager9* dev_manager) { | 241 bool MFDecoder::InitVideoInfo(IDirect3DDeviceManager9* dev_manager) { |
242 CHECK(reader_ != NULL); | 242 CHECK(reader_ != NULL); |
243 CHECK_GE(video_stream_index_, 0); | 243 CHECK_GE(video_stream_index_, 0); |
244 ScopedComPtr<IMFMediaType> video_type; | 244 base::win::ScopedComPtr<IMFMediaType> video_type; |
245 HRESULT hr = reader_->GetCurrentMediaType(video_stream_index_, | 245 HRESULT hr = reader_->GetCurrentMediaType(video_stream_index_, |
246 video_type.Receive()); | 246 video_type.Receive()); |
247 if (FAILED(hr)) { | 247 if (FAILED(hr)) { |
248 LOG(ERROR) << "InitVideoInfo: Failed to get video stream"; | 248 LOG(ERROR) << "InitVideoInfo: Failed to get video stream"; |
249 return false; | 249 return false; |
250 } | 250 } |
251 GUID video_subtype; | 251 GUID video_subtype; |
252 hr = video_type->GetGUID(MF_MT_SUBTYPE, &video_subtype); | 252 hr = video_type->GetGUID(MF_MT_SUBTYPE, &video_subtype); |
253 if (FAILED(hr)) { | 253 if (FAILED(hr)) { |
254 LOG(ERROR) << "Failed to determine video subtype"; | 254 LOG(ERROR) << "Failed to determine video subtype"; |
255 return false; | 255 return false; |
256 } | 256 } |
257 VLOG(1) << "Video subtype is " | 257 VLOG(1) << "Video subtype is " |
258 << ((video_subtype == MFVideoFormat_H264) ? "" : "NOT ") << "H.264"; | 258 << ((video_subtype == MFVideoFormat_H264) ? "" : "NOT ") << "H.264"; |
259 hr = MFGetAttributeSize(video_type, MF_MT_FRAME_SIZE, | 259 hr = MFGetAttributeSize(video_type, MF_MT_FRAME_SIZE, |
260 reinterpret_cast<UINT32*>(&width_), | 260 reinterpret_cast<UINT32*>(&width_), |
261 reinterpret_cast<UINT32*>(&height_)); | 261 reinterpret_cast<UINT32*>(&height_)); |
262 if (FAILED(hr)) { | 262 if (FAILED(hr)) { |
263 LOG(ERROR) << "Failed to determine frame size"; | 263 LOG(ERROR) << "Failed to determine frame size"; |
264 return false; | 264 return false; |
265 } | 265 } |
266 VLOG(1) << "Video width: " << width_ << ", height: " << height_; | 266 VLOG(1) << "Video width: " << width_ << ", height: " << height_; |
267 | 267 |
268 // Try to change to YV12 output format. | 268 // Try to change to YV12 output format. |
269 const GUID kOutputVideoSubtype = MFVideoFormat_YV12; | 269 const GUID kOutputVideoSubtype = MFVideoFormat_YV12; |
270 ScopedComPtr<IMFMediaType> output_video_format; | 270 base::win::ScopedComPtr<IMFMediaType> output_video_format; |
271 hr = MFCreateMediaType(output_video_format.Receive()); | 271 hr = MFCreateMediaType(output_video_format.Receive()); |
272 if (FAILED(hr)) { | 272 if (FAILED(hr)) { |
273 LOG(ERROR) << "Failed to create a IMFMediaType object for video output"; | 273 LOG(ERROR) << "Failed to create a IMFMediaType object for video output"; |
274 return false; | 274 return false; |
275 } | 275 } |
276 if (SUCCEEDED(hr)) | 276 if (SUCCEEDED(hr)) |
277 hr = output_video_format->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 277 hr = output_video_format->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
278 if (SUCCEEDED(hr)) | 278 if (SUCCEEDED(hr)) |
279 hr = output_video_format->SetGUID(MF_MT_SUBTYPE, kOutputVideoSubtype); | 279 hr = output_video_format->SetGUID(MF_MT_SUBTYPE, kOutputVideoSubtype); |
280 if (SUCCEEDED(hr)) { | 280 if (SUCCEEDED(hr)) { |
(...skipping 13 matching lines...) Expand all Loading... |
294 } | 294 } |
295 if (FAILED(hr)) { | 295 if (FAILED(hr)) { |
296 LOG(ERROR) << "Failed to change output video format and determine stride"; | 296 LOG(ERROR) << "Failed to change output video format and determine stride"; |
297 return false; | 297 return false; |
298 } | 298 } |
299 VLOG(1) << "IMFMediaBuffer stride: " << mfbuffer_stride_; | 299 VLOG(1) << "IMFMediaBuffer stride: " << mfbuffer_stride_; |
300 | 300 |
301 // Send a message to the decoder to tell it to use DXVA2. | 301 // Send a message to the decoder to tell it to use DXVA2. |
302 if (use_dxva2_) { | 302 if (use_dxva2_) { |
303 // Call GetServiceForStream to get the interface to the video decoder. | 303 // Call GetServiceForStream to get the interface to the video decoder. |
304 ScopedComPtr<IMFTransform> video_decoder; | 304 base::win::ScopedComPtr<IMFTransform> video_decoder; |
305 hr = reader_->GetServiceForStream(video_stream_index_, GUID_NULL, | 305 hr = reader_->GetServiceForStream(video_stream_index_, GUID_NULL, |
306 IID_PPV_ARGS(video_decoder.Receive())); | 306 IID_PPV_ARGS(video_decoder.Receive())); |
307 if (FAILED(hr)) { | 307 if (FAILED(hr)) { |
308 LOG(ERROR) << "Failed to obtain interface to decoder"; | 308 LOG(ERROR) << "Failed to obtain interface to decoder"; |
309 return false; | 309 return false; |
310 } else { | 310 } else { |
311 hr = video_decoder->ProcessMessage( | 311 hr = video_decoder->ProcessMessage( |
312 MFT_MESSAGE_SET_D3D_MANAGER, | 312 MFT_MESSAGE_SET_D3D_MANAGER, |
313 reinterpret_cast<ULONG_PTR>(dev_manager)); | 313 reinterpret_cast<ULONG_PTR>(dev_manager)); |
314 if (FAILED(hr)) { | 314 if (FAILED(hr)) { |
315 LOG(ERROR) << "Failed to send DXVA message to decoder"; | 315 LOG(ERROR) << "Failed to send DXVA message to decoder"; |
316 return false; | 316 return false; |
317 } | 317 } |
318 } | 318 } |
319 } | 319 } |
320 return true; | 320 return true; |
321 } | 321 } |
322 | 322 |
323 } // namespace media | 323 } // namespace media |
OLD | NEW |