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

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

Issue 1745903002: Introduce GpuVideoDecodeAcceleratorFactory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months 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
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/gpu_video_decode_accelerator.h" 5 #include "content/common/gpu/media/gpu_video_decode_accelerator.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 18
19 #include "content/common/gpu/gpu_channel.h" 19 #include "content/common/gpu/gpu_channel.h"
20 #include "content/common/gpu/media/gpu_video_accelerator_util.h" 20 #include "content/common/gpu/media/gpu_video_accelerator_util.h"
21 #include "content/common/gpu/media_messages.h" 21 #include "content/common/gpu/media_messages.h"
22 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/gpu_video_decode_accelerator_factory.h"
23 #include "gpu/command_buffer/common/command_buffer.h" 24 #include "gpu/command_buffer/common/command_buffer.h"
24 #include "ipc/ipc_message_macros.h" 25 #include "ipc/ipc_message_macros.h"
25 #include "ipc/ipc_message_utils.h" 26 #include "ipc/ipc_message_utils.h"
26 #include "ipc/message_filter.h" 27 #include "ipc/message_filter.h"
27 #include "media/base/limits.h" 28 #include "media/base/limits.h"
28 #include "ui/gl/gl_context.h" 29 #include "ui/gl/gl_context.h"
29 #include "ui/gl/gl_image.h" 30 #include "ui/gl/gl_image.h"
30 #include "ui/gl/gl_surface_egl.h"
31
32 #if defined(OS_WIN)
33 #include "base/win/windows_version.h"
34 #include "content/common/gpu/media/dxva_video_decode_accelerator_win.h"
35 #elif defined(OS_MACOSX)
36 #include "content/common/gpu/media/vt_video_decode_accelerator_mac.h"
37 #elif defined(OS_CHROMEOS)
38 #if defined(USE_V4L2_CODEC)
39 #include "content/common/gpu/media/v4l2_device.h"
40 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
41 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
42 #endif
43 #if defined(ARCH_CPU_X86_FAMILY)
44 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
45 #include "ui/gl/gl_implementation.h"
46 #endif
47 #elif defined(USE_OZONE)
48 #include "media/ozone/media_ozone_platform.h"
49 #elif defined(OS_ANDROID)
50 #include "content/common/gpu/media/android_video_decode_accelerator.h"
51 #endif
52
53 #include "ui/gfx/geometry/size.h" 31 #include "ui/gfx/geometry/size.h"
54 32
55 namespace content { 33 namespace content {
56 34
35 namespace {
36 static gfx::GLContext* GetGLContext(
37 const base::WeakPtr<GpuCommandBufferStub>& stub) {
38 if (!stub) {
39 DLOG(ERROR) << "Stub is gone; no GLContext.";
40 return nullptr;
41 }
42
43 return stub->decoder()->GetGLContext();
44 }
45
57 static bool MakeDecoderContextCurrent( 46 static bool MakeDecoderContextCurrent(
58 const base::WeakPtr<GpuCommandBufferStub> stub) { 47 const base::WeakPtr<GpuCommandBufferStub>& stub) {
59 if (!stub) { 48 if (!stub) {
60 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; 49 DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
61 return false; 50 return false;
62 } 51 }
63 52
64 if (!stub->decoder()->MakeCurrent()) { 53 if (!stub->decoder()->MakeCurrent()) {
65 DLOG(ERROR) << "Failed to MakeCurrent()"; 54 DLOG(ERROR) << "Failed to MakeCurrent()";
66 return false; 55 return false;
67 } 56 }
68 57
69 return true; 58 return true;
70 } 59 }
71 60
61 static bool BindImage(const base::WeakPtr<GpuCommandBufferStub>& stub,
62 uint32_t client_texture_id,
63 uint32_t texture_target,
64 const scoped_refptr<gl::GLImage>& image) {
65 if (!stub) {
66 DLOG(ERROR) << "Stub is gone; won't BindImage().";
67 return false;
68 }
69
70 gpu::gles2::GLES2Decoder* command_decoder = stub->decoder();
71 gpu::gles2::TextureManager* texture_manager =
72 command_decoder->GetContextGroup()->texture_manager();
73 gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id);
74 if (ref) {
75 texture_manager->SetLevelImage(ref, texture_target, 0, image.get(),
76 gpu::gles2::Texture::BOUND);
77 }
78
79 return true;
80 }
81
82 static base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder(
83 const base::WeakPtr<GpuCommandBufferStub>& stub) {
84 if (!stub) {
85 DLOG(ERROR) << "Stub is gone; no GLES2Decoder.";
86 return base::WeakPtr<gpu::gles2::GLES2Decoder>();
87 }
88
89 return stub->decoder()->AsWeakPtr();
90 }
91 } // anonymous namespace
92
72 // DebugAutoLock works like AutoLock but only acquires the lock when 93 // DebugAutoLock works like AutoLock but only acquires the lock when
73 // DCHECK is on. 94 // DCHECK is on.
74 #if DCHECK_IS_ON() 95 #if DCHECK_IS_ON()
75 typedef base::AutoLock DebugAutoLock; 96 typedef base::AutoLock DebugAutoLock;
76 #else 97 #else
77 class DebugAutoLock { 98 class DebugAutoLock {
78 public: 99 public:
79 explicit DebugAutoLock(base::Lock&) {} 100 explicit DebugAutoLock(base::Lock&) {}
80 }; 101 };
81 #endif 102 #endif
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 154 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
134 : host_route_id_(host_route_id), 155 : host_route_id_(host_route_id),
135 stub_(stub), 156 stub_(stub),
136 texture_target_(0), 157 texture_target_(0),
137 filter_removed_(true, false), 158 filter_removed_(true, false),
138 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), 159 child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
139 io_task_runner_(io_task_runner), 160 io_task_runner_(io_task_runner),
140 weak_factory_for_io_(this) { 161 weak_factory_for_io_(this) {
141 DCHECK(stub_); 162 DCHECK(stub_);
142 stub_->AddDestructionObserver(this); 163 stub_->AddDestructionObserver(this);
143 make_context_current_ = 164 get_gl_context_cb_ = base::Bind(&GetGLContext, stub_->AsWeakPtr());
165 make_context_current_cb_ =
144 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); 166 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
167 bind_image_cb_ = base::Bind(&BindImage, stub_->AsWeakPtr());
168 get_gles2_decoder_cb_ = base::Bind(&GetGLES2Decoder, stub_->AsWeakPtr());
145 } 169 }
146 170
147 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { 171 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
148 // This class can only be self-deleted from OnWillDestroyStub(), which means 172 // This class can only be self-deleted from OnWillDestroyStub(), which means
149 // the VDA has already been destroyed in there. 173 // the VDA has already been destroyed in there.
150 DCHECK(!video_decode_accelerator_); 174 DCHECK(!video_decode_accelerator_);
151 } 175 }
152 176
153 // static 177 // static
154 gpu::VideoDecodeAcceleratorCapabilities 178 gpu::VideoDecodeAcceleratorCapabilities
155 GpuVideoDecodeAccelerator::GetCapabilities() { 179 GpuVideoDecodeAccelerator::GetCapabilities() {
156 media::VideoDecodeAccelerator::Capabilities capabilities; 180 return GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities();
157 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
158 if (cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
159 return gpu::VideoDecodeAcceleratorCapabilities();
160
161 // Query supported profiles for each VDA. The order of querying VDAs should
162 // be the same as the order of initializing VDAs. Then the returned profile
163 // can be initialized by corresponding VDA successfully.
164 #if defined(OS_WIN)
165 capabilities.supported_profiles =
166 DXVAVideoDecodeAccelerator::GetSupportedProfiles();
167 #elif defined(OS_CHROMEOS)
168 media::VideoDecodeAccelerator::SupportedProfiles vda_profiles;
169 #if defined(USE_V4L2_CODEC)
170 vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles();
171 GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
172 vda_profiles, &capabilities.supported_profiles);
173 vda_profiles = V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
174 GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
175 vda_profiles, &capabilities.supported_profiles);
176 #endif
177 #if defined(ARCH_CPU_X86_FAMILY)
178 vda_profiles = VaapiVideoDecodeAccelerator::GetSupportedProfiles();
179 GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
180 vda_profiles, &capabilities.supported_profiles);
181 #endif
182 #elif defined(OS_MACOSX)
183 capabilities.supported_profiles =
184 VTVideoDecodeAccelerator::GetSupportedProfiles();
185 #elif defined(OS_ANDROID)
186 capabilities = AndroidVideoDecodeAccelerator::GetCapabilities();
187 #endif
188 return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities(
189 capabilities);
190 } 181 }
191 182
192 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { 183 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
193 if (!video_decode_accelerator_) 184 if (!video_decode_accelerator_)
194 return false; 185 return false;
195 186
196 bool handled = true; 187 bool handled = true;
197 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) 188 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
198 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_SetCdm, OnSetCdm) 189 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_SetCdm, OnSetCdm)
199 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) 190 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 DCHECK(!video_decode_accelerator_); 324 DCHECK(!video_decode_accelerator_);
334 325
335 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { 326 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
336 DLOG(ERROR) << "Initialize(): failed to add route"; 327 DLOG(ERROR) << "Initialize(): failed to add route";
337 SendCreateDecoderReply(init_done_msg, false); 328 SendCreateDecoderReply(init_done_msg, false);
338 } 329 }
339 330
340 #if !defined(OS_WIN) 331 #if !defined(OS_WIN)
341 // Ensure we will be able to get a GL context at all before initializing 332 // Ensure we will be able to get a GL context at all before initializing
342 // non-Windows VDAs. 333 // non-Windows VDAs.
343 if (!make_context_current_.Run()) { 334 if (!make_context_current_cb_.Run()) {
344 SendCreateDecoderReply(init_done_msg, false); 335 SendCreateDecoderReply(init_done_msg, false);
345 return; 336 return;
346 } 337 }
347 #endif 338 #endif
348 339
349 // Array of Create..VDA() function pointers, maybe applicable to the current 340 scoped_ptr<GpuVideoDecodeAcceleratorFactory> vda_factory =
350 // platform. This list is ordered by priority of use and it should be the 341 GpuVideoDecodeAcceleratorFactory::CreateWithGLES2Decoder(
351 // same as the order of querying supported profiles of VDAs. 342 get_gl_context_cb_, make_context_current_cb_, bind_image_cb_,
352 const GpuVideoDecodeAccelerator::CreateVDAFp create_vda_fps[] = { 343 get_gles2_decoder_cb_);
353 &GpuVideoDecodeAccelerator::CreateDXVAVDA,
354 &GpuVideoDecodeAccelerator::CreateV4L2VDA,
355 &GpuVideoDecodeAccelerator::CreateV4L2SliceVDA,
356 &GpuVideoDecodeAccelerator::CreateVaapiVDA,
357 &GpuVideoDecodeAccelerator::CreateVTVDA,
358 &GpuVideoDecodeAccelerator::CreateOzoneVDA,
359 &GpuVideoDecodeAccelerator::CreateAndroidVDA};
360 344
361 for (const auto& create_vda_function : create_vda_fps) { 345 if (!vda_factory) {
362 video_decode_accelerator_ = (this->*create_vda_function)(); 346 LOG(ERROR) << "Failed creating the VDA factory";
363 if (!video_decode_accelerator_ || 347 SendCreateDecoderReply(init_done_msg, false);
364 !video_decode_accelerator_->Initialize(config, this))
365 continue;
366
367 if (video_decode_accelerator_->CanDecodeOnIOThread()) {
368 filter_ = new MessageFilter(this, host_route_id_);
369 stub_->channel()->AddFilter(filter_.get());
370 }
371 SendCreateDecoderReply(init_done_msg, true);
372 return; 348 return;
373 } 349 }
374 video_decode_accelerator_.reset();
375 LOG(ERROR) << "HW video decode not available for profile " << config.profile
376 << (config.is_encrypted ? " with encryption" : "");
377 SendCreateDecoderReply(init_done_msg, false);
378 }
379 350
380 scoped_ptr<media::VideoDecodeAccelerator> 351 video_decode_accelerator_ = vda_factory->CreateVDA(this, config);
381 GpuVideoDecodeAccelerator::CreateDXVAVDA() { 352 if (!video_decode_accelerator_) {
382 scoped_ptr<media::VideoDecodeAccelerator> decoder; 353 LOG(ERROR) << "HW video decode not available for profile " << config.profile
383 #if defined(OS_WIN) 354 << (config.is_encrypted ? " with encryption" : "");
384 if (base::win::GetVersion() >= base::win::VERSION_WIN7) { 355 SendCreateDecoderReply(init_done_msg, false);
385 DVLOG(0) << "Initializing DXVA HW decoder for windows."; 356 return;
386 decoder.reset(new DXVAVideoDecodeAccelerator(make_context_current_,
387 stub_->decoder()->GetGLContext()));
388 } else {
389 NOTIMPLEMENTED() << "HW video decode acceleration not available.";
390 } 357 }
391 #endif
392 return decoder;
393 }
394 358
395 scoped_ptr<media::VideoDecodeAccelerator> 359 // Attempt to set up performing decoding tasks on IO thread, if supported by
396 GpuVideoDecodeAccelerator::CreateV4L2VDA() { 360 // the VDA.
397 scoped_ptr<media::VideoDecodeAccelerator> decoder; 361 if (video_decode_accelerator_->TryInitializeDecodeOnSeparateThread(
398 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) 362 weak_factory_for_io_.GetWeakPtr(), io_task_runner_)) {
399 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 363 filter_ = new MessageFilter(this, host_route_id_);
400 if (device.get()) { 364 stub_->channel()->AddFilter(filter_.get());
401 decoder.reset(new V4L2VideoDecodeAccelerator(
402 gfx::GLSurfaceEGL::GetHardwareDisplay(),
403 stub_->decoder()->GetGLContext()->GetHandle(),
404 weak_factory_for_io_.GetWeakPtr(),
405 make_context_current_,
406 device,
407 io_task_runner_));
408 } 365 }
409 #endif
410 return decoder;
411 }
412 366
413 scoped_ptr<media::VideoDecodeAccelerator> 367 SendCreateDecoderReply(init_done_msg, true);
414 GpuVideoDecodeAccelerator::CreateV4L2SliceVDA() {
415 scoped_ptr<media::VideoDecodeAccelerator> decoder;
416 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
417 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
418 if (device.get()) {
419 decoder.reset(new V4L2SliceVideoDecodeAccelerator(
420 device,
421 gfx::GLSurfaceEGL::GetHardwareDisplay(),
422 stub_->decoder()->GetGLContext()->GetHandle(),
423 weak_factory_for_io_.GetWeakPtr(),
424 make_context_current_,
425 io_task_runner_));
426 }
427 #endif
428 return decoder;
429 }
430
431 void GpuVideoDecodeAccelerator::BindImage(uint32_t client_texture_id,
432 uint32_t texture_target,
433 scoped_refptr<gl::GLImage> image) {
434 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder();
435 gpu::gles2::TextureManager* texture_manager =
436 command_decoder->GetContextGroup()->texture_manager();
437 gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id);
438 if (ref) {
439 texture_manager->SetLevelImage(ref, texture_target, 0, image.get(),
440 gpu::gles2::Texture::BOUND);
441 }
442 }
443
444 scoped_ptr<media::VideoDecodeAccelerator>
445 GpuVideoDecodeAccelerator::CreateVaapiVDA() {
446 scoped_ptr<media::VideoDecodeAccelerator> decoder;
447 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
448 decoder.reset(new VaapiVideoDecodeAccelerator(
449 make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
450 base::Unretained(this))));
451 #endif
452 return decoder;
453 }
454
455 scoped_ptr<media::VideoDecodeAccelerator>
456 GpuVideoDecodeAccelerator::CreateVTVDA() {
457 scoped_ptr<media::VideoDecodeAccelerator> decoder;
458 #if defined(OS_MACOSX)
459 decoder.reset(new VTVideoDecodeAccelerator(
460 make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
461 base::Unretained(this))));
462 #endif
463 return decoder;
464 }
465
466 scoped_ptr<media::VideoDecodeAccelerator>
467 GpuVideoDecodeAccelerator::CreateOzoneVDA() {
468 scoped_ptr<media::VideoDecodeAccelerator> decoder;
469 #if !defined(OS_CHROMEOS) && defined(USE_OZONE)
470 media::MediaOzonePlatform* platform =
471 media::MediaOzonePlatform::GetInstance();
472 decoder.reset(platform->CreateVideoDecodeAccelerator(make_context_current_));
473 #endif
474 return decoder;
475 }
476
477 scoped_ptr<media::VideoDecodeAccelerator>
478 GpuVideoDecodeAccelerator::CreateAndroidVDA() {
479 scoped_ptr<media::VideoDecodeAccelerator> decoder;
480 #if defined(OS_ANDROID)
481 decoder.reset(new AndroidVideoDecodeAccelerator(stub_->decoder()->AsWeakPtr(),
482 make_context_current_));
483 #endif
484 return decoder;
485 } 368 }
486 369
487 void GpuVideoDecodeAccelerator::OnSetCdm(int cdm_id) { 370 void GpuVideoDecodeAccelerator::OnSetCdm(int cdm_id) {
488 DCHECK(video_decode_accelerator_); 371 DCHECK(video_decode_accelerator_);
489 video_decode_accelerator_->SetCdm(cdm_id); 372 video_decode_accelerator_->SetCdm(cdm_id);
490 } 373 }
491 374
492 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is 375 // Runs on IO thread if VDA::TryInitializeDecodeOnSeparateThread() succeeded,
493 // true, otherwise on the main thread. 376 // otherwise on the main thread.
494 void GpuVideoDecodeAccelerator::OnDecode( 377 void GpuVideoDecodeAccelerator::OnDecode(
495 const AcceleratedVideoDecoderMsg_Decode_Params& params) { 378 const AcceleratedVideoDecoderMsg_Decode_Params& params) {
496 DCHECK(video_decode_accelerator_); 379 DCHECK(video_decode_accelerator_);
497 media::BitstreamBuffer bitstream_buffer(params.bitstream_buffer_id, 380 media::BitstreamBuffer bitstream_buffer(params.bitstream_buffer_id,
498 params.buffer_handle, params.size, 381 params.buffer_handle, params.size,
499 params.presentation_timestamp); 382 params.presentation_timestamp);
500 if (!params.key_id.empty()) { 383 if (!params.key_id.empty()) {
501 bitstream_buffer.SetDecryptConfig( 384 bitstream_buffer.SetDecryptConfig(
502 media::DecryptConfig(params.key_id, params.iv, params.subsamples)); 385 media::DecryptConfig(params.key_id, params.iv, params.subsamples));
503 } 386 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 uncleared_textures_.erase(it); 505 uncleared_textures_.erase(it);
623 } 506 }
624 507
625 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, 508 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message,
626 bool succeeded) { 509 bool succeeded) {
627 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, succeeded); 510 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, succeeded);
628 Send(message); 511 Send(message);
629 } 512 }
630 513
631 } // namespace content 514 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698