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