| 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 |