Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: content/common/gpu/media/dxva_video_decode_accelerator.cc

Issue 11369232: DXVA: remove path that reads back decoded frames to system memory. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.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
11 #include <ks.h> 11 #include <ks.h>
12 #include <codecapi.h> 12 #include <codecapi.h>
13 #include <d3dx9tex.h>
14 #include <mfapi.h> 13 #include <mfapi.h>
15 #include <mferror.h> 14 #include <mferror.h>
16 #include <wmcodecdsp.h> 15 #include <wmcodecdsp.h>
17 16
18 #include "base/bind.h" 17 #include "base/bind.h"
19 #include "base/callback.h" 18 #include "base/callback.h"
20 #include "base/command_line.h" 19 #include "base/command_line.h"
21 #include "base/debug/trace_event.h" 20 #include "base/debug/trace_event.h"
22 #include "base/logging.h" 21 #include "base/logging.h"
23 #include "base/memory/scoped_handle.h" 22 #include "base/memory/scoped_handle.h"
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 base::SharedMemory shm(bitstream_buffer.handle(), true); 150 base::SharedMemory shm(bitstream_buffer.handle(), true);
152 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), 151 RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()),
153 "Failed in base::SharedMemory::Map", NULL); 152 "Failed in base::SharedMemory::Map", NULL);
154 153
155 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()), 154 return CreateInputSample(reinterpret_cast<const uint8*>(shm.memory()),
156 bitstream_buffer.size(), 155 bitstream_buffer.size(),
157 stream_size, 156 stream_size,
158 alignment); 157 alignment);
159 } 158 }
160 159
161 // Helper function to read the bitmap from the D3D surface passed in.
162 static bool GetBitmapFromSurface(IDirect3DDevice9Ex* device,
163 IDirect3DSurface9* surface,
164 scoped_array<char>* bits) {
165 // TODO(ananta)
166 // The code below may not be necessary once we have an ANGLE extension which
167 // allows us to pass the Direct 3D surface directly for rendering.
168
169 // The decoded bits in the source direct 3d surface are in the YUV
170 // format. Angle does not support that. As a workaround we create an
171 // offscreen surface in the RGB format and copy the source surface
172 // to this surface.
173 D3DSURFACE_DESC surface_desc;
174 HRESULT hr = surface->GetDesc(&surface_desc);
175 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
176
177 base::win::ScopedComPtr<IDirect3DSurface9> dest_surface;
178 hr = device->CreateOffscreenPlainSurface(surface_desc.Width,
179 surface_desc.Height,
180 D3DFMT_A8R8G8B8,
181 D3DPOOL_DEFAULT,
182 dest_surface.Receive(),
183 NULL);
184 RETURN_ON_HR_FAILURE(hr, "Failed to create offscreen surface", false);
185
186 hr = D3DXLoadSurfaceFromSurface(dest_surface, NULL, NULL, surface, NULL,
187 NULL, D3DX_DEFAULT, 0);
188 RETURN_ON_HR_FAILURE(hr, "D3DXLoadSurfaceFromSurface failed", false);
189
190 // Get the currently loaded bitmap from the DC.
191 HDC hdc = NULL;
192 hr = dest_surface->GetDC(&hdc);
193 RETURN_ON_HR_FAILURE(hr, "Failed to get HDC from surface", false);
194
195 HBITMAP bitmap =
196 reinterpret_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
197 if (!bitmap) {
198 NOTREACHED() << "Failed to get bitmap from DC";
199 dest_surface->ReleaseDC(hdc);
200 return false;
201 }
202
203 BITMAP bitmap_basic_info = {0};
204 if (!GetObject(bitmap, sizeof(BITMAP), &bitmap_basic_info)) {
205 NOTREACHED() << "Failed to read bitmap info";
206 dest_surface->ReleaseDC(hdc);
207 return false;
208 }
209 BITMAPINFO bitmap_info = {0};
210 bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
211 bitmap_info.bmiHeader.biWidth = bitmap_basic_info.bmWidth;
212 bitmap_info.bmiHeader.biHeight = bitmap_basic_info.bmHeight;
213 bitmap_info.bmiHeader.biPlanes = 1;
214 bitmap_info.bmiHeader.biBitCount = bitmap_basic_info.bmBitsPixel;
215 bitmap_info.bmiHeader.biCompression = BI_RGB;
216 bitmap_info.bmiHeader.biSizeImage = 0;
217 bitmap_info.bmiHeader.biClrUsed = 0;
218
219 int ret = GetDIBits(hdc, bitmap, 0, 0, NULL, &bitmap_info, DIB_RGB_COLORS);
220 if (!ret || bitmap_info.bmiHeader.biSizeImage <= 0) {
221 NOTREACHED() << "Failed to read bitmap size";
222 dest_surface->ReleaseDC(hdc);
223 return false;
224 }
225
226 bits->reset(new char[bitmap_info.bmiHeader.biSizeImage]);
227 ret = GetDIBits(hdc, bitmap, 0, bitmap_basic_info.bmHeight, bits->get(),
228 &bitmap_info, DIB_RGB_COLORS);
229 if (!ret) {
230 NOTREACHED() << "Failed to retrieve bitmap bits.";
231 }
232 dest_surface->ReleaseDC(hdc);
233 return !!ret;
234 }
235
236 // Maintains information about a DXVA picture buffer, i.e. whether it is 160 // Maintains information about a DXVA picture buffer, i.e. whether it is
237 // available for rendering, the texture information, etc. 161 // available for rendering, the texture information, etc.
238 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { 162 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
239 public: 163 public:
240 static linked_ptr<DXVAPictureBuffer> Create( 164 static linked_ptr<DXVAPictureBuffer> Create(
241 const media::PictureBuffer& buffer, EGLConfig egl_config); 165 const media::PictureBuffer& buffer, EGLConfig egl_config);
242 ~DXVAPictureBuffer(); 166 ~DXVAPictureBuffer();
243 167
244 void ReusePictureBuffer(); 168 void ReusePictureBuffer();
245 // Copies the output sample data to the picture buffer provided by the 169 // Copies the output sample data to the picture buffer provided by the
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 NOTREACHED() << "Decode surface of different dimension than texture"; 288 NOTREACHED() << "Decode surface of different dimension than texture";
365 return false; 289 return false;
366 } 290 }
367 291
368 hr = d3d9_->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT, 292 hr = d3d9_->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT,
369 D3DDEVTYPE_HAL, 293 D3DDEVTYPE_HAL,
370 surface_desc.Format, 294 surface_desc.Format,
371 D3DFMT_X8R8G8B8); 295 D3DFMT_X8R8G8B8);
372 bool device_supports_format_conversion = (hr == S_OK); 296 bool device_supports_format_conversion = (hr == S_OK);
373 297
298 RETURN_ON_FAILURE(device_supports_format_conversion,
299 "Device does not support format converision",
300 false);
301
374 // This function currently executes in the context of IPC handlers in the 302 // This function currently executes in the context of IPC handlers in the
375 // GPU process which ensures that there is always an OpenGL context. 303 // GPU process which ensures that there is always an OpenGL context.
376 GLint current_texture = 0; 304 GLint current_texture = 0;
377 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); 305 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
378 306
379 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id()); 307 glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
380 308
381 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
382 310
383 if (device_supports_format_conversion) { 311 base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface;
384 base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface; 312 hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive());
385 HRESULT hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive()); 313 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
386 RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
387 314
388 hr = device_->StretchRect(dest_surface, 315 hr = device_->StretchRect(dest_surface,
389 NULL, 316 NULL,
390 d3d_surface, 317 d3d_surface,
391 NULL, 318 NULL,
392 D3DTEXF_NONE); 319 D3DTEXF_NONE);
393 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", 320 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",
394 false); 321 false);
395 // Ideally, this should be done immediately before the draw call that uses 322
396 // the texture. Flush it once here though. 323 // Ideally, this should be done immediately before the draw call that uses
397 hr = query_->Issue(D3DISSUE_END); 324 // the texture. Flush it once here though.
398 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); 325 hr = query_->Issue(D3DISSUE_END);
399 do { 326 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false);
400 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); 327 do {
401 if (hr == S_FALSE) 328 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
402 Sleep(1); // Poor-man's Yield(). 329 if (hr == S_FALSE)
403 } while (hr == S_FALSE); 330 Sleep(1); // Poor-man's Yield().
404 eglBindTexImage( 331 } while (hr == S_FALSE);
405 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)), 332 eglBindTexImage(
406 decoding_surface_, 333 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)),
407 EGL_BACK_BUFFER); 334 decoding_surface_,
408 } else { 335 EGL_BACK_BUFFER);
409 scoped_array<char> bits; 336
410 RETURN_ON_FAILURE(GetBitmapFromSurface(DXVAVideoDecodeAccelerator::device_,
411 dest_surface, &bits),
412 "Failed to get bitmap from surface for rendering",
413 false);
414 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, surface_desc.Width,
415 surface_desc.Height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
416 reinterpret_cast<GLvoid*>(bits.get()));
417 }
418 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
419 glBindTexture(GL_TEXTURE_2D, current_texture); 338 glBindTexture(GL_TEXTURE_2D, current_texture);
420 return true; 339 return true;
421 } 340 }
422 341
423 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo( 342 DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
424 int32 buffer_id, IMFSample* sample) 343 int32 buffer_id, IMFSample* sample)
425 : input_buffer_id(buffer_id) { 344 : input_buffer_id(buffer_id) {
426 output_sample.Attach(sample); 345 output_sample.Attach(sample);
427 } 346 }
428 347
429 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {} 348 DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}
430 349
431 // static 350 // static
432 void DXVAVideoDecodeAccelerator::PreSandboxInitialization() { 351 void DXVAVideoDecodeAccelerator::PreSandboxInitialization() {
433 // Should be called only once during program startup. 352 // Should be called only once during program startup.
434 DCHECK(!pre_sandbox_init_done_); 353 DCHECK(!pre_sandbox_init_done_);
435 354
436 static wchar_t* decoding_dlls[] = { 355 static wchar_t* decoding_dlls[] = {
437 L"d3d9.dll", 356 L"d3d9.dll",
438 L"d3dx9_43.dll",
439 L"dxva2.dll", 357 L"dxva2.dll",
440 L"mf.dll", 358 L"mf.dll",
441 L"mfplat.dll", 359 L"mfplat.dll",
442 L"msmpeg2vdec.dll", 360 L"msmpeg2vdec.dll",
443 }; 361 };
444 362
445 for (int i = 0; i < arraysize(decoding_dlls); ++i) { 363 for (int i = 0; i < arraysize(decoding_dlls); ++i) {
446 if (!::LoadLibrary(decoding_dlls[i])) { 364 if (!::LoadLibrary(decoding_dlls[i])) {
447 DLOG(ERROR) << "Failed to load decoder dll: " << decoding_dlls[i] 365 DLOG(ERROR) << "Failed to load decoder dll: " << decoding_dlls[i]
448 << ", Error: " << ::GetLastError(); 366 << ", Error: " << ::GetLastError();
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 return; 1056 return;
1139 } 1057 }
1140 1058
1141 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 1059 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1142 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); 1060 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
1143 1061
1144 state_ = kNormal; 1062 state_ = kNormal;
1145 } 1063 }
1146 1064
1147 } // namespace content 1065 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698