OLD | NEW |
1 // Copyright (c) 2011 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 UNICODE | 5 #ifdef UNICODE |
6 #undef UNICODE | 6 #undef UNICODE |
7 #endif | 7 #endif |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include <d3d9.h> | 11 #include <d3d9.h> |
12 #include <dxva2api.h> | 12 #include <dxva2api.h> |
13 #include <evr.h> | 13 #include <evr.h> |
14 #include <mfapi.h> | 14 #include <mfapi.h> |
15 #include <mfreadwrite.h> | 15 #include <mfreadwrite.h> |
16 #include <windows.h> | 16 #include <windows.h> |
17 | 17 |
18 #include "base/at_exit.h" | 18 #include "base/at_exit.h" |
19 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
20 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
22 #include "base/message_loop.h" | 22 #include "base/message_loop.h" |
23 #include "base/scoped_comptr_win.h" | |
24 #include "base/time.h" | 23 #include "base/time.h" |
| 24 #include "base/win/scoped_comptr.h" |
25 #include "media/base/yuv_convert.h" | 25 #include "media/base/yuv_convert.h" |
26 #include "media/tools/mfdecoder/mfdecoder.h" | 26 #include "media/tools/mfdecoder/mfdecoder.h" |
27 #include "ui/gfx/gdi_util.h" | 27 #include "ui/gfx/gdi_util.h" |
28 | 28 |
29 static const char* const kWindowClass = "Chrome_MF_Decoder"; | 29 static const char* const kWindowClass = "Chrome_MF_Decoder"; |
30 static const char* const kWindowTitle = "MF Decoder"; | 30 static const char* const kWindowTitle = "MF Decoder"; |
31 static const int kWindowStyleFlags = | 31 static const int kWindowStyleFlags = |
32 (WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME); | 32 (WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME); |
33 static bool g_render_to_window = false; | 33 static bool g_render_to_window = false; |
34 static bool g_render_asap = false; | 34 static bool g_render_asap = false; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 video_buffer->Unlock(); | 159 video_buffer->Unlock(); |
160 return true; | 160 return true; |
161 } | 161 } |
162 | 162 |
163 // Obtains the D3D9 surface from the given IMFMediaBuffer, then calls methods | 163 // Obtains the D3D9 surface from the given IMFMediaBuffer, then calls methods |
164 // in the D3D device to draw to the window associated with it. | 164 // in the D3D device to draw to the window associated with it. |
165 // Returns: true on success. | 165 // Returns: true on success. |
166 static bool PaintD3D9BufferOntoWindow(IDirect3DDevice9* device, | 166 static bool PaintD3D9BufferOntoWindow(IDirect3DDevice9* device, |
167 IMFMediaBuffer* video_buffer) { | 167 IMFMediaBuffer* video_buffer) { |
168 CHECK(device != NULL); | 168 CHECK(device != NULL); |
169 ScopedComPtr<IDirect3DSurface9> surface; | 169 base::win::ScopedComPtr<IDirect3DSurface9> surface; |
170 HRESULT hr = MFGetService(video_buffer, MR_BUFFER_SERVICE, | 170 HRESULT hr = MFGetService(video_buffer, MR_BUFFER_SERVICE, |
171 IID_PPV_ARGS(surface.Receive())); | 171 IID_PPV_ARGS(surface.Receive())); |
172 if (FAILED(hr)) { | 172 if (FAILED(hr)) { |
173 LOG(ERROR) << "Failed to get D3D9 surface from buffer"; | 173 LOG(ERROR) << "Failed to get D3D9 surface from buffer"; |
174 return false; | 174 return false; |
175 } | 175 } |
176 if (g_render_to_window) { | 176 if (g_render_to_window) { |
177 base::Time render_start(base::Time::Now()); | 177 base::Time render_start(base::Time::Now()); |
178 hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), | 178 hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), |
179 1.0f, 0); | 179 1.0f, 0); |
180 if (FAILED(hr)) { | 180 if (FAILED(hr)) { |
181 LOG(ERROR) << "Device->Clear() failed"; | 181 LOG(ERROR) << "Device->Clear() failed"; |
182 return false; | 182 return false; |
183 } | 183 } |
184 ScopedComPtr<IDirect3DSurface9> backbuffer; | 184 base::win::ScopedComPtr<IDirect3DSurface9> backbuffer; |
185 hr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, | 185 hr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, |
186 backbuffer.Receive()); | 186 backbuffer.Receive()); |
187 if (FAILED(hr)) { | 187 if (FAILED(hr)) { |
188 LOG(ERROR) << "Device->GetBackBuffer() failed"; | 188 LOG(ERROR) << "Device->GetBackBuffer() failed"; |
189 return false; | 189 return false; |
190 } | 190 } |
191 hr = device->StretchRect(surface.get(), NULL, backbuffer.get(), NULL, | 191 hr = device->StretchRect(surface.get(), NULL, backbuffer.get(), NULL, |
192 D3DTEXF_NONE); | 192 D3DTEXF_NONE); |
193 if (FAILED(hr)) { | 193 if (FAILED(hr)) { |
194 LOG(ERROR) << "Device->StretchRect() failed"; | 194 LOG(ERROR) << "Device->StretchRect() failed"; |
(...skipping 27 matching lines...) Expand all Loading... |
222 IDirect3DDevice9* device) { | 222 IDirect3DDevice9* device) { |
223 CHECK(video_window != NULL); | 223 CHECK(video_window != NULL); |
224 CHECK(decoder != NULL); | 224 CHECK(decoder != NULL); |
225 CHECK(decoder->initialized()); | 225 CHECK(decoder->initialized()); |
226 | 226 |
227 if (decoder->end_of_stream()) { | 227 if (decoder->end_of_stream()) { |
228 LOG(ERROR) << "Failed to obtain more samples from decoder because end of " | 228 LOG(ERROR) << "Failed to obtain more samples from decoder because end of " |
229 << "stream has been reached"; | 229 << "stream has been reached"; |
230 return false; | 230 return false; |
231 } | 231 } |
232 ScopedComPtr<IMFSample> video_sample; | 232 base::win::ScopedComPtr<IMFSample> video_sample; |
233 base::Time decode_time_start(base::Time::Now()); | 233 base::Time decode_time_start(base::Time::Now()); |
234 video_sample.Attach(decoder->ReadVideoSample()); | 234 video_sample.Attach(decoder->ReadVideoSample()); |
235 if (video_sample.get() == NULL) { | 235 if (video_sample.get() == NULL) { |
236 LOG(ERROR) << "Failed to obtain a sample from decoder: end of stream? " | 236 LOG(ERROR) << "Failed to obtain a sample from decoder: end of stream? " |
237 << (decoder->end_of_stream() ? "true" : "false"); | 237 << (decoder->end_of_stream() ? "true" : "false"); |
238 return false; | 238 return false; |
239 } | 239 } |
240 *g_decode_time += base::Time::Now() - decode_time_start; | 240 *g_decode_time += base::Time::Now() - decode_time_start; |
241 | 241 |
242 // Get the buffer inside the sample. | 242 // Get the buffer inside the sample. |
243 DWORD buffer_count; | 243 DWORD buffer_count; |
244 HRESULT hr = video_sample->GetBufferCount(&buffer_count); | 244 HRESULT hr = video_sample->GetBufferCount(&buffer_count); |
245 if (FAILED(hr)) { | 245 if (FAILED(hr)) { |
246 LOG(ERROR) << "Failed to get buffer count from sample"; | 246 LOG(ERROR) << "Failed to get buffer count from sample"; |
247 return false; | 247 return false; |
248 } | 248 } |
249 | 249 |
250 // For H.264 videos, the number of buffers in the sample is 1. | 250 // For H.264 videos, the number of buffers in the sample is 1. |
251 CHECK_EQ(buffer_count, 1u) << "buffer_count should be equal " | 251 CHECK_EQ(buffer_count, 1u) << "buffer_count should be equal " |
252 << "to 1 for H.264 format"; | 252 << "to 1 for H.264 format"; |
253 ScopedComPtr<IMFMediaBuffer> video_buffer; | 253 base::win::ScopedComPtr<IMFMediaBuffer> video_buffer; |
254 hr = video_sample->GetBufferByIndex(0, video_buffer.Receive()); | 254 hr = video_sample->GetBufferByIndex(0, video_buffer.Receive()); |
255 if (FAILED(hr)) { | 255 if (FAILED(hr)) { |
256 LOG(ERROR) << "Failed to get buffer from sample"; | 256 LOG(ERROR) << "Failed to get buffer from sample"; |
257 return false; | 257 return false; |
258 } | 258 } |
259 if (decoder->use_dxva2()) { | 259 if (decoder->use_dxva2()) { |
260 return PaintD3D9BufferOntoWindow(device, video_buffer); | 260 return PaintD3D9BufferOntoWindow(device, video_buffer); |
261 } else { | 261 } else { |
262 return PaintMediaBufferOntoWindow(video_window, video_buffer, | 262 return PaintMediaBufferOntoWindow(video_window, video_buffer, |
263 decoder->width(), decoder->height(), | 263 decoder->width(), decoder->height(), |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 // to use the device, and returns the manager. It also initializes the D3D | 301 // to use the device, and returns the manager. It also initializes the D3D |
302 // device. This function is used by mfdecoder.cc during the call to | 302 // device. This function is used by mfdecoder.cc during the call to |
303 // MFDecoder::GetDXVA2AttributesForSourceReader(). | 303 // MFDecoder::GetDXVA2AttributesForSourceReader(). |
304 // Returns: The D3D manager object if successful. Otherwise, NULL is returned. | 304 // Returns: The D3D manager object if successful. Otherwise, NULL is returned. |
305 static IDirect3DDeviceManager9* CreateD3DDevManager(HWND video_window, | 305 static IDirect3DDeviceManager9* CreateD3DDevManager(HWND video_window, |
306 IDirect3DDevice9** device) { | 306 IDirect3DDevice9** device) { |
307 CHECK(video_window != NULL); | 307 CHECK(video_window != NULL); |
308 CHECK(device != NULL); | 308 CHECK(device != NULL); |
309 int ret = -1; | 309 int ret = -1; |
310 | 310 |
311 ScopedComPtr<IDirect3DDeviceManager9> dev_manager; | 311 base::win::ScopedComPtr<IDirect3DDeviceManager9> dev_manager; |
312 ScopedComPtr<IDirect3D9> d3d; | 312 base::win::ScopedComPtr<IDirect3D9> d3d; |
313 d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION)); | 313 d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION)); |
314 if (d3d == NULL) { | 314 if (d3d == NULL) { |
315 LOG(ERROR) << "Failed to create D3D9"; | 315 LOG(ERROR) << "Failed to create D3D9"; |
316 return NULL; | 316 return NULL; |
317 } | 317 } |
318 D3DPRESENT_PARAMETERS present_params = {0}; | 318 D3DPRESENT_PARAMETERS present_params = {0}; |
319 | 319 |
320 // Not sure if these values are correct, or if | 320 // Not sure if these values are correct, or if |
321 // they even matter. (taken from DXVA_HD sample code) | 321 // they even matter. (taken from DXVA_HD sample code) |
322 present_params.BackBufferWidth = 0; | 322 present_params.BackBufferWidth = 0; |
323 present_params.BackBufferHeight = 0; | 323 present_params.BackBufferHeight = 0; |
324 present_params.BackBufferFormat = D3DFMT_UNKNOWN; | 324 present_params.BackBufferFormat = D3DFMT_UNKNOWN; |
325 present_params.BackBufferCount = 1; | 325 present_params.BackBufferCount = 1; |
326 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; | 326 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; |
327 present_params.hDeviceWindow = video_window; | 327 present_params.hDeviceWindow = video_window; |
328 present_params.Windowed = TRUE; | 328 present_params.Windowed = TRUE; |
329 present_params.Flags = D3DPRESENTFLAG_VIDEO; | 329 present_params.Flags = D3DPRESENTFLAG_VIDEO; |
330 present_params.FullScreen_RefreshRateInHz = 0; | 330 present_params.FullScreen_RefreshRateInHz = 0; |
331 present_params.PresentationInterval = 0; | 331 present_params.PresentationInterval = 0; |
332 | 332 |
333 ScopedComPtr<IDirect3DDevice9> temp_device; | 333 base::win::ScopedComPtr<IDirect3DDevice9> temp_device; |
334 | 334 |
335 // D3DCREATE_HARDWARE_VERTEXPROCESSING specifies hardware vertex processing. | 335 // D3DCREATE_HARDWARE_VERTEXPROCESSING specifies hardware vertex processing. |
336 HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, | 336 HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, |
337 D3DDEVTYPE_HAL, | 337 D3DDEVTYPE_HAL, |
338 video_window, | 338 video_window, |
339 (D3DCREATE_HARDWARE_VERTEXPROCESSING | | 339 (D3DCREATE_HARDWARE_VERTEXPROCESSING | |
340 D3DCREATE_MULTITHREADED), | 340 D3DCREATE_MULTITHREADED), |
341 &present_params, | 341 &present_params, |
342 temp_device.Receive()); | 342 temp_device.Receive()); |
343 if (FAILED(hr)) { | 343 if (FAILED(hr)) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 : GetDesktopWindow(); | 474 : GetDesktopWindow(); |
475 if (video_window == NULL) { | 475 if (video_window == NULL) { |
476 LOG(ERROR) << "main: Failed to create the video window"; | 476 LOG(ERROR) << "main: Failed to create the video window"; |
477 return -1; | 477 return -1; |
478 } | 478 } |
479 scoped_ptr<media::MFDecoder> decoder(new media::MFDecoder(use_dxva2)); | 479 scoped_ptr<media::MFDecoder> decoder(new media::MFDecoder(use_dxva2)); |
480 if (decoder == NULL) { | 480 if (decoder == NULL) { |
481 LOG(ERROR) << "Failed to create decoder"; | 481 LOG(ERROR) << "Failed to create decoder"; |
482 return -1; | 482 return -1; |
483 } | 483 } |
484 ScopedComPtr<IDirect3DDeviceManager9> dev_manager; | 484 base::win::ScopedComPtr<IDirect3DDeviceManager9> dev_manager; |
485 ScopedComPtr<IDirect3DDevice9> device; | 485 base::win::ScopedComPtr<IDirect3DDevice9> device; |
486 if (decoder->use_dxva2()) { | 486 if (decoder->use_dxva2()) { |
487 dev_manager.Attach(CreateD3DDevManager(video_window, device.Receive())); | 487 dev_manager.Attach(CreateD3DDevManager(video_window, device.Receive())); |
488 if (dev_manager.get() == NULL || device.get() == NULL) { | 488 if (dev_manager.get() == NULL || device.get() == NULL) { |
489 LOG(ERROR) << "DXVA2 specified, but failed to create D3D device"; | 489 LOG(ERROR) << "DXVA2 specified, but failed to create D3D device"; |
490 return -1; | 490 return -1; |
491 } | 491 } |
492 } | 492 } |
493 if (!decoder->Init(file_name.get(), dev_manager.get())) { | 493 if (!decoder->Init(file_name.get(), dev_manager.get())) { |
494 LOG(ERROR) << "main: Decoder initialization failed"; | 494 LOG(ERROR) << "main: Decoder initialization failed"; |
495 return -1; | 495 return -1; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 << "\nAverage decode time: " << ((g_num_frames == 0) ? | 548 << "\nAverage decode time: " << ((g_num_frames == 0) ? |
549 0 : (g_decode_time->InMillisecondsF() / g_num_frames)) | 549 0 : (g_decode_time->InMillisecondsF() / g_num_frames)) |
550 << "\nRender time: " << g_render_time->InMilliseconds() << "ms" | 550 << "\nRender time: " << g_render_time->InMilliseconds() << "ms" |
551 << "\nAverage render time: " << ((g_num_frames == 0) ? | 551 << "\nAverage render time: " << ((g_num_frames == 0) ? |
552 0 : (g_render_time->InMillisecondsF() / g_num_frames)); | 552 0 : (g_render_time->InMillisecondsF() / g_num_frames)); |
553 printf("Normal termination\n"); | 553 printf("Normal termination\n"); |
554 delete g_decode_time; | 554 delete g_decode_time; |
555 delete g_render_time; | 555 delete g_render_time; |
556 return 0; | 556 return 0; |
557 } | 557 } |
OLD | NEW |