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

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

Issue 104713014: VDA: Restructure EVDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years 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"
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 }; 125 };
126 126
127 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( 127 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
128 int32 host_route_id, 128 int32 host_route_id,
129 GpuCommandBufferStub* stub, 129 GpuCommandBufferStub* stub,
130 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) 130 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
131 : init_done_msg_(NULL), 131 : init_done_msg_(NULL),
132 host_route_id_(host_route_id), 132 host_route_id_(host_route_id),
133 stub_(stub), 133 stub_(stub),
134 texture_target_(0), 134 texture_target_(0),
135 filter_removed_(true, false),
Pawel Osciak 2013/12/24 03:45:24 Please rebase.
135 io_message_loop_(io_message_loop), 136 io_message_loop_(io_message_loop),
136 weak_factory_for_io_(this) { 137 weak_factory_for_io_(this) {
137 DCHECK(stub_); 138 DCHECK(stub_);
138 stub_->AddDestructionObserver(this); 139 stub_->AddDestructionObserver(this);
139 stub_->channel()->AddRoute(host_route_id_, this); 140 stub_->channel()->AddRoute(host_route_id_, this);
140 child_message_loop_ = base::MessageLoopProxy::current(); 141 child_message_loop_ = base::MessageLoopProxy::current();
141 make_context_current_ = 142 make_context_current_ =
142 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); 143 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
143 } 144 }
144 145
145 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { 146 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
146 if (video_decode_accelerator_) 147 // This class can only be self-deleted from OnWillDestroyStub(), which means
147 video_decode_accelerator_.release()->Destroy(); 148 // the VDA has already been destroyed in there.
149 CHECK(!video_decode_accelerator_.get());
148 } 150 }
149 151
150 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { 152 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
151 DCHECK(stub_);
152 if (!video_decode_accelerator_) 153 if (!video_decode_accelerator_)
153 return false; 154 return false;
155
154 bool handled = true; 156 bool handled = true;
155 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) 157 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
156 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) 158 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
157 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, 159 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
158 OnAssignPictureBuffers) 160 OnAssignPictureBuffers)
159 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer, 161 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
160 OnReusePictureBuffer) 162 OnReusePictureBuffer)
161 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Flush, OnFlush) 163 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Flush, OnFlush)
162 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Reset, OnReset) 164 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Reset, OnReset)
163 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Destroy, OnDestroy) 165 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Destroy, OnDestroy)
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( 240 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification(
239 host_route_id_, error))) { 241 host_route_id_, error))) {
240 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " 242 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) "
241 << "failed"; 243 << "failed";
242 } 244 }
243 } 245 }
244 246
245 void GpuVideoDecodeAccelerator::Initialize( 247 void GpuVideoDecodeAccelerator::Initialize(
246 const media::VideoCodecProfile profile, 248 const media::VideoCodecProfile profile,
247 IPC::Message* init_done_msg) { 249 IPC::Message* init_done_msg) {
248 DCHECK(stub_);
249 DCHECK(!video_decode_accelerator_.get()); 250 DCHECK(!video_decode_accelerator_.get());
250 DCHECK(!init_done_msg_); 251 DCHECK(!init_done_msg_);
251 DCHECK(init_done_msg); 252 DCHECK(init_done_msg);
252 init_done_msg_ = init_done_msg; 253 init_done_msg_ = init_done_msg;
253 254
254 #if !defined(OS_WIN) 255 #if !defined(OS_WIN)
255 // Ensure we will be able to get a GL context at all before initializing 256 // Ensure we will be able to get a GL context at all before initializing
256 // non-Windows VDAs. 257 // non-Windows VDAs.
257 if (!make_context_current_.Run()) { 258 if (!make_context_current_.Run()) {
258 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 259 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
259 return; 260 return;
260 } 261 }
261 #endif 262 #endif
262 263
263 #if defined(OS_WIN) 264 #if defined(OS_WIN)
264 if (base::win::GetVersion() < base::win::VERSION_WIN7) { 265 if (base::win::GetVersion() < base::win::VERSION_WIN7) {
265 NOTIMPLEMENTED() << "HW video decode acceleration not available."; 266 NOTIMPLEMENTED() << "HW video decode acceleration not available.";
266 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 267 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
267 return; 268 return;
268 } 269 }
269 DVLOG(0) << "Initializing DXVA HW decoder for windows."; 270 DVLOG(0) << "Initializing DXVA HW decoder for windows.";
270 video_decode_accelerator_.reset(new DXVAVideoDecodeAccelerator( 271 video_decode_accelerator_.reset(new DXVAVideoDecodeAccelerator(
271 this, make_context_current_)); 272 this, make_context_current_));
272 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) 273 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
273 video_decode_accelerator_.reset(new ExynosVideoDecodeAccelerator( 274 video_decode_accelerator_.reset(new V4L2VideoDecodeAccelerator(
274 gfx::GLSurfaceEGL::GetHardwareDisplay(), 275 gfx::GLSurfaceEGL::GetHardwareDisplay(),
275 stub_->decoder()->GetGLContext()->GetHandle(),
276 this, 276 this,
277 weak_factory_for_io_.GetWeakPtr(), 277 weak_factory_for_io_.GetWeakPtr(),
278 make_context_current_, 278 make_context_current_,
279 io_message_loop_)); 279 io_message_loop_));
280 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) 280 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
281 gfx::GLContextGLX* glx_context = 281 gfx::GLContextGLX* glx_context =
282 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); 282 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
283 GLXContext glx_context_handle =
284 static_cast<GLXContext>(glx_context->GetHandle());
285 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( 283 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
286 glx_context->display(), glx_context_handle, this, 284 glx_context->display(), this, make_context_current_));
287 make_context_current_));
288 #elif defined(OS_ANDROID) 285 #elif defined(OS_ANDROID)
289 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( 286 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
290 this, 287 this,
291 stub_->decoder()->AsWeakPtr(), 288 stub_->decoder()->AsWeakPtr(),
292 make_context_current_)); 289 make_context_current_));
293 #else 290 #else
294 NOTIMPLEMENTED() << "HW video decode acceleration not available."; 291 NOTIMPLEMENTED() << "HW video decode acceleration not available.";
295 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 292 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
296 return; 293 return;
297 #endif 294 #endif
(...skipping 24 matching lines...) Expand all
322 media::VideoDecodeAccelerator::INVALID_ARGUMENT)); 319 media::VideoDecodeAccelerator::INVALID_ARGUMENT));
323 } 320 }
324 return; 321 return;
325 } 322 }
326 video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size)); 323 video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size));
327 } 324 }
328 325
329 void GpuVideoDecodeAccelerator::OnAssignPictureBuffers( 326 void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
330 const std::vector<int32>& buffer_ids, 327 const std::vector<int32>& buffer_ids,
331 const std::vector<uint32>& texture_ids) { 328 const std::vector<uint32>& texture_ids) {
332 DCHECK(stub_);
333 if (buffer_ids.size() != texture_ids.size()) { 329 if (buffer_ids.size() != texture_ids.size()) {
334 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); 330 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
335 return; 331 return;
336 } 332 }
337 333
338 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); 334 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder();
339 gpu::gles2::TextureManager* texture_manager = 335 gpu::gles2::TextureManager* texture_manager =
340 command_decoder->GetContextGroup()->texture_manager(); 336 command_decoder->GetContextGroup()->texture_manager();
341 337
342 std::vector<media::PictureBuffer> buffers; 338 std::vector<media::PictureBuffer> buffers;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 416 }
421 417
422 void GpuVideoDecodeAccelerator::OnDestroy() { 418 void GpuVideoDecodeAccelerator::OnDestroy() {
423 DCHECK(video_decode_accelerator_.get()); 419 DCHECK(video_decode_accelerator_.get());
424 OnWillDestroyStub(); 420 OnWillDestroyStub();
425 } 421 }
426 422
427 void GpuVideoDecodeAccelerator::OnFilterRemoved() { 423 void GpuVideoDecodeAccelerator::OnFilterRemoved() {
428 // We're destroying; cancel all callbacks. 424 // We're destroying; cancel all callbacks.
429 weak_factory_for_io_.InvalidateWeakPtrs(); 425 weak_factory_for_io_.InvalidateWeakPtrs();
430 child_message_loop_->DeleteSoon(FROM_HERE, this); 426 filter_removed_.Signal();
431 } 427 }
432 428
433 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( 429 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
434 int32 bitstream_buffer_id) { 430 int32 bitstream_buffer_id) {
435 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( 431 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed(
436 host_route_id_, bitstream_buffer_id))) { 432 host_route_id_, bitstream_buffer_id))) {
437 DLOG(ERROR) 433 DLOG(ERROR)
438 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " 434 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) "
439 << "failed"; 435 << "failed";
440 } 436 }
(...skipping 11 matching lines...) Expand all
452 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) 448 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_)))
453 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; 449 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed";
454 } 450 }
455 451
456 void GpuVideoDecodeAccelerator::NotifyResetDone() { 452 void GpuVideoDecodeAccelerator::NotifyResetDone() {
457 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) 453 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_)))
458 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; 454 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
459 } 455 }
460 456
461 void GpuVideoDecodeAccelerator::OnWillDestroyStub() { 457 void GpuVideoDecodeAccelerator::OnWillDestroyStub() {
462 DCHECK(stub_); 458 // The stub is going away, so we have to stop and destroy VDA here, before
459 // returning, because the VDA may need the GL context to run and/or do its
460 // cleanup. We cannot destroy the VDA before the IO thread message filter is
461 // removed however, since we cannot service incoming messages with VDA gone.
462 // We cannot simply check for existence of VDA on IO thread though, because
463 // we don't want to synchronize the IO thread with the ChildThread.
464 // So we have to wait for the RemoveFilter callback here instead and remove
465 // the VDA after it arrives and before returning.
466 if (filter_.get()) {
467 stub_->channel()->RemoveFilter(filter_.get());
468 filter_removed_.Wait();
469 }
470
463 stub_->channel()->RemoveRoute(host_route_id_); 471 stub_->channel()->RemoveRoute(host_route_id_);
464 stub_->RemoveDestructionObserver(this); 472 stub_->RemoveDestructionObserver(this);
465 { 473
466 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); 474 if (video_decode_accelerator_)
467 uncleared_textures_.clear(); 475 video_decode_accelerator_.release()->Destroy();
468 } 476
469 if (filter_.get()) { 477 delete this;
470 // Remove the filter first because the member variables can be accessed on
471 // IO thread. When filter is removed, OnFilterRemoved will delete |this|.
472 stub_->channel()->RemoveFilter(filter_.get());
473 } else {
474 delete this;
475 }
476 } 478 }
477 479
478 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { 480 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
479 DCHECK(stub_);
480 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) 481 if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
481 return filter_->SendOnIOThread(message); 482 return filter_->SendOnIOThread(message);
482 DCHECK(child_message_loop_->BelongsToCurrentThread()); 483 DCHECK(child_message_loop_->BelongsToCurrentThread());
483 return stub_->channel()->Send(message); 484 return stub_->channel()->Send(message);
484 } 485 }
485 486
486 void GpuVideoDecodeAccelerator::SetTextureCleared( 487 void GpuVideoDecodeAccelerator::SetTextureCleared(
487 const media::Picture& picture) { 488 const media::Picture& picture) {
488 DCHECK(child_message_loop_->BelongsToCurrentThread()); 489 DCHECK(child_message_loop_->BelongsToCurrentThread());
489 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); 490 DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
490 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; 491 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it;
491 it = uncleared_textures_.find(picture.picture_buffer_id()); 492 it = uncleared_textures_.find(picture.picture_buffer_id());
492 if (it == uncleared_textures_.end()) 493 if (it == uncleared_textures_.end())
493 return; // the texture has been cleared 494 return; // the texture has been cleared
494 495
495 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; 496 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second;
496 GLenum target = texture_ref->texture()->target(); 497 GLenum target = texture_ref->texture()->target();
497 gpu::gles2::TextureManager* texture_manager = 498 gpu::gles2::TextureManager* texture_manager =
498 stub_->decoder()->GetContextGroup()->texture_manager(); 499 stub_->decoder()->GetContextGroup()->texture_manager();
499 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); 500 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0));
500 texture_manager->SetLevelCleared(texture_ref, target, 0, true); 501 texture_manager->SetLevelCleared(texture_ref, target, 0, true);
501 uncleared_textures_.erase(it); 502 uncleared_textures_.erase(it);
502 } 503 }
503 504
504 } // namespace content 505 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698