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

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

Issue 185403020: Make VEA client of command buffer; move sync. IPC to VDA/VEA::Initialize() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 85629196 fischman@ comments. Created 6 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 | Annotate | Revision Log
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 24 matching lines...) Expand all
35 #elif defined(OS_ANDROID) 35 #elif defined(OS_ANDROID)
36 #include "content/common/gpu/media/android_video_decode_accelerator.h" 36 #include "content/common/gpu/media/android_video_decode_accelerator.h"
37 #endif 37 #endif
38 38
39 #include "ui/gfx/size.h" 39 #include "ui/gfx/size.h"
40 40
41 namespace content { 41 namespace content {
42 42
43 static bool MakeDecoderContextCurrent( 43 static bool MakeDecoderContextCurrent(
44 const base::WeakPtr<GpuCommandBufferStub> stub) { 44 const base::WeakPtr<GpuCommandBufferStub> stub) {
45 if (!stub.get()) { 45 if (!stub) {
46 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; 46 DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
47 return false; 47 return false;
48 } 48 }
49 49
50 if (!stub->decoder()->MakeCurrent()) { 50 if (!stub->decoder()->MakeCurrent()) {
51 DLOG(ERROR) << "Failed to MakeCurrent()"; 51 DLOG(ERROR) << "Failed to MakeCurrent()";
52 return false; 52 return false;
53 } 53 }
54 54
55 return true; 55 return true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 GpuVideoDecodeAccelerator* owner_; 113 GpuVideoDecodeAccelerator* owner_;
114 int32 host_route_id_; 114 int32 host_route_id_;
115 // The channel to which this filter was added. 115 // The channel to which this filter was added.
116 IPC::Channel* channel_; 116 IPC::Channel* channel_;
117 }; 117 };
118 118
119 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( 119 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
120 int32 host_route_id, 120 int32 host_route_id,
121 GpuCommandBufferStub* stub, 121 GpuCommandBufferStub* stub,
122 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) 122 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
123 : init_done_msg_(NULL), 123 : host_route_id_(host_route_id),
124 host_route_id_(host_route_id),
125 stub_(stub), 124 stub_(stub),
126 texture_target_(0), 125 texture_target_(0),
127 filter_removed_(true, false), 126 filter_removed_(true, false),
128 io_message_loop_(io_message_loop), 127 io_message_loop_(io_message_loop),
129 weak_factory_for_io_(this) { 128 weak_factory_for_io_(this) {
130 DCHECK(stub_); 129 DCHECK(stub_);
131 stub_->AddDestructionObserver(this); 130 stub_->AddDestructionObserver(this);
132 stub_->channel()->AddRoute(host_route_id_, this);
133 child_message_loop_ = base::MessageLoopProxy::current(); 131 child_message_loop_ = base::MessageLoopProxy::current();
134 make_context_current_ = 132 make_context_current_ =
135 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); 133 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
136 } 134 }
137 135
138 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { 136 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
139 // This class can only be self-deleted from OnWillDestroyStub(), which means 137 // This class can only be self-deleted from OnWillDestroyStub(), which means
140 // the VDA has already been destroyed in there. 138 // the VDA has already been destroyed in there.
141 CHECK(!video_decode_accelerator_.get()); 139 DCHECK(!video_decode_accelerator_);
142 } 140 }
143 141
144 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { 142 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
145 if (!video_decode_accelerator_) 143 if (!video_decode_accelerator_)
146 return false; 144 return false;
147 145
148 bool handled = true; 146 bool handled = true;
149 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) 147 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) 148 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
151 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, 149 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 194
197 void GpuVideoDecodeAccelerator::PictureReady( 195 void GpuVideoDecodeAccelerator::PictureReady(
198 const media::Picture& picture) { 196 const media::Picture& picture) {
199 // VDA may call PictureReady on IO thread. SetTextureCleared should run on 197 // VDA may call PictureReady on IO thread. SetTextureCleared should run on
200 // the child thread. VDA is responsible to call PictureReady on the child 198 // the child thread. VDA is responsible to call PictureReady on the child
201 // thread when a picture buffer is delivered the first time. 199 // thread when a picture buffer is delivered the first time.
202 if (child_message_loop_->BelongsToCurrentThread()) { 200 if (child_message_loop_->BelongsToCurrentThread()) {
203 SetTextureCleared(picture); 201 SetTextureCleared(picture);
204 } else { 202 } else {
205 DCHECK(io_message_loop_->BelongsToCurrentThread()); 203 DCHECK(io_message_loop_->BelongsToCurrentThread());
206 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); 204 DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
Ami GONE FROM CHROMIUM 2014/03/18 23:53:19 this is tricky business; it replaces a run-time DC
sheu 2014/03/19 20:38:24 Rebase change :-( DCHECK_IS_ON is now a compile-t
207 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); 205 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
208 } 206 }
209 207
210 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( 208 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
211 host_route_id_, 209 host_route_id_,
212 picture.picture_buffer_id(), 210 picture.picture_buffer_id(),
213 picture.bitstream_buffer_id()))) { 211 picture.bitstream_buffer_id()))) {
214 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; 212 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed";
215 } 213 }
216 } 214 }
217 215
218 void GpuVideoDecodeAccelerator::NotifyError( 216 void GpuVideoDecodeAccelerator::NotifyError(
219 media::VideoDecodeAccelerator::Error error) { 217 media::VideoDecodeAccelerator::Error error) {
220 if (init_done_msg_) {
221 // If we get an error while we're initializing, NotifyInitializeDone won't
222 // be called, so we need to send the reply (with an error) here.
223 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(
224 init_done_msg_, -1);
225 if (!Send(init_done_msg_))
226 DLOG(ERROR) << "Send(init_done_msg_) failed";
227 init_done_msg_ = NULL;
228 return;
229 }
230 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( 218 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification(
231 host_route_id_, error))) { 219 host_route_id_, error))) {
232 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " 220 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) "
233 << "failed"; 221 << "failed";
234 } 222 }
235 } 223 }
236 224
237 void GpuVideoDecodeAccelerator::Initialize( 225 void GpuVideoDecodeAccelerator::Initialize(
238 const media::VideoCodecProfile profile, 226 const media::VideoCodecProfile profile,
239 IPC::Message* init_done_msg) { 227 IPC::Message* init_done_msg) {
240 DCHECK(!video_decode_accelerator_.get()); 228 DCHECK(!video_decode_accelerator_.get());
241 DCHECK(!init_done_msg_);
242 DCHECK(init_done_msg);
243 init_done_msg_ = init_done_msg;
244 229
245 #if !defined(OS_WIN) 230 #if !defined(OS_WIN)
246 // Ensure we will be able to get a GL context at all before initializing 231 // Ensure we will be able to get a GL context at all before initializing
247 // non-Windows VDAs. 232 // non-Windows VDAs.
248 if (!make_context_current_.Run()) { 233 if (!make_context_current_.Run()) {
249 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 234 SendCreateDecoderReply(init_done_msg, -1);
250 return; 235 return;
251 } 236 }
252 #endif 237 #endif
253 238
254 #if defined(OS_WIN) 239 #if defined(OS_WIN)
255 if (base::win::GetVersion() < base::win::VERSION_WIN7) { 240 if (base::win::GetVersion() < base::win::VERSION_WIN7) {
256 NOTIMPLEMENTED() << "HW video decode acceleration not available."; 241 NOTIMPLEMENTED() << "HW video decode acceleration not available.";
257 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 242 SendCreateDecoderReply(init_done_msg, -1);
258 return; 243 return;
259 } 244 }
260 DVLOG(0) << "Initializing DXVA HW decoder for windows."; 245 DVLOG(0) << "Initializing DXVA HW decoder for windows.";
261 video_decode_accelerator_.reset( 246 video_decode_accelerator_.reset(
262 new DXVAVideoDecodeAccelerator(make_context_current_)); 247 new DXVAVideoDecodeAccelerator(make_context_current_));
263 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) 248 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
264 scoped_ptr<V4L2Device> device = V4L2Device::Create(); 249 scoped_ptr<V4L2Device> device = V4L2Device::Create();
265 if (!device.get()) { 250 if (!device.get()) {
266 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 251 SendCreateDecoderReply(init_done_msg, -1);
267 return; 252 return;
268 } 253 }
269 video_decode_accelerator_.reset( 254 video_decode_accelerator_.reset(
270 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), 255 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(),
271 weak_factory_for_io_.GetWeakPtr(), 256 weak_factory_for_io_.GetWeakPtr(),
272 make_context_current_, 257 make_context_current_,
273 device.Pass(), 258 device.Pass(),
274 io_message_loop_)); 259 io_message_loop_));
275 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) 260 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
276 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { 261 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
277 VLOG(1) << "HW video decode acceleration not available without " 262 VLOG(1) << "HW video decode acceleration not available without "
278 "DesktopGL (GLX)."; 263 "DesktopGL (GLX).";
279 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 264 SendCreateDecoderReply(init_done_msg, -1);
280 return; 265 return;
281 } 266 }
282 gfx::GLContextGLX* glx_context = 267 gfx::GLContextGLX* glx_context =
283 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); 268 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
284 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( 269 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
285 glx_context->display(), make_context_current_)); 270 glx_context->display(), make_context_current_));
286 #elif defined(OS_ANDROID) 271 #elif defined(OS_ANDROID)
287 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( 272 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
288 stub_->decoder()->AsWeakPtr(), 273 stub_->decoder()->AsWeakPtr(),
289 make_context_current_)); 274 make_context_current_));
290 #else 275 #else
291 NOTIMPLEMENTED() << "HW video decode acceleration not available."; 276 NOTIMPLEMENTED() << "HW video decode acceleration not available.";
292 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 277 SendCreateDecoderReply(init_done_msg, -1);
293 return; 278 return;
294 #endif 279 #endif
295 280
296 if (video_decode_accelerator_->CanDecodeOnIOThread()) { 281 if (video_decode_accelerator_->CanDecodeOnIOThread()) {
297 filter_ = new MessageFilter(this, host_route_id_); 282 filter_ = new MessageFilter(this, host_route_id_);
298 stub_->channel()->AddFilter(filter_.get()); 283 stub_->channel()->AddFilter(filter_.get());
299 } 284 }
300 285
301 if (!video_decode_accelerator_->Initialize(profile, this)) 286 if (!video_decode_accelerator_->Initialize(profile, this)) {
302 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 287 SendCreateDecoderReply(init_done_msg, -1);
288 return;
289 }
290
291 SendCreateDecoderReply(init_done_msg, host_route_id_);
303 } 292 }
304 293
305 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is 294 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is
306 // true, otherwise on the main thread. 295 // true, otherwise on the main thread.
307 void GpuVideoDecodeAccelerator::OnDecode( 296 void GpuVideoDecodeAccelerator::OnDecode(
308 base::SharedMemoryHandle handle, int32 id, uint32 size) { 297 base::SharedMemoryHandle handle, int32 id, uint32 size) {
309 DCHECK(video_decode_accelerator_.get()); 298 DCHECK(video_decode_accelerator_.get());
310 if (id < 0) { 299 if (id < 0) {
311 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; 300 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range";
312 if (child_message_loop_->BelongsToCurrentThread()) { 301 if (child_message_loop_->BelongsToCurrentThread()) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( 418 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
430 int32 bitstream_buffer_id) { 419 int32 bitstream_buffer_id) {
431 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( 420 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed(
432 host_route_id_, bitstream_buffer_id))) { 421 host_route_id_, bitstream_buffer_id))) {
433 DLOG(ERROR) 422 DLOG(ERROR)
434 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " 423 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) "
435 << "failed"; 424 << "failed";
436 } 425 }
437 } 426 }
438 427
439 void GpuVideoDecodeAccelerator::NotifyInitializeDone() {
440 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(
441 init_done_msg_, host_route_id_);
442 if (!Send(init_done_msg_))
443 DLOG(ERROR) << "Send(init_done_msg_) failed";
444 init_done_msg_ = NULL;
445 }
446
447 void GpuVideoDecodeAccelerator::NotifyFlushDone() { 428 void GpuVideoDecodeAccelerator::NotifyFlushDone() {
448 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) 429 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_)))
449 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; 430 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed";
450 } 431 }
451 432
452 void GpuVideoDecodeAccelerator::NotifyResetDone() { 433 void GpuVideoDecodeAccelerator::NotifyResetDone() {
453 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) 434 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_)))
454 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; 435 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
455 } 436 }
456 437
(...skipping 13 matching lines...) Expand all
470 451
471 stub_->channel()->RemoveRoute(host_route_id_); 452 stub_->channel()->RemoveRoute(host_route_id_);
472 stub_->RemoveDestructionObserver(this); 453 stub_->RemoveDestructionObserver(this);
473 454
474 if (video_decode_accelerator_) 455 if (video_decode_accelerator_)
475 video_decode_accelerator_.release()->Destroy(); 456 video_decode_accelerator_.release()->Destroy();
476 457
477 delete this; 458 delete this;
478 } 459 }
479 460
480 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
481 if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
482 return filter_->SendOnIOThread(message);
483 DCHECK(child_message_loop_->BelongsToCurrentThread());
484 return stub_->channel()->Send(message);
485 }
486
487 void GpuVideoDecodeAccelerator::SetTextureCleared( 461 void GpuVideoDecodeAccelerator::SetTextureCleared(
488 const media::Picture& picture) { 462 const media::Picture& picture) {
489 DCHECK(child_message_loop_->BelongsToCurrentThread()); 463 DCHECK(child_message_loop_->BelongsToCurrentThread());
490 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); 464 DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
491 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; 465 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it;
492 it = uncleared_textures_.find(picture.picture_buffer_id()); 466 it = uncleared_textures_.find(picture.picture_buffer_id());
493 if (it == uncleared_textures_.end()) 467 if (it == uncleared_textures_.end())
494 return; // the texture has been cleared 468 return; // the texture has been cleared
495 469
496 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; 470 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second;
497 GLenum target = texture_ref->texture()->target(); 471 GLenum target = texture_ref->texture()->target();
498 gpu::gles2::TextureManager* texture_manager = 472 gpu::gles2::TextureManager* texture_manager =
499 stub_->decoder()->GetContextGroup()->texture_manager(); 473 stub_->decoder()->GetContextGroup()->texture_manager();
500 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); 474 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0));
501 texture_manager->SetLevelCleared(texture_ref, target, 0, true); 475 texture_manager->SetLevelCleared(texture_ref, target, 0, true);
502 uncleared_textures_.erase(it); 476 uncleared_textures_.erase(it);
503 } 477 }
504 478
479 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
480 if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
481 return filter_->SendOnIOThread(message);
482 DCHECK(child_message_loop_->BelongsToCurrentThread());
483 return stub_->channel()->Send(message);
484 }
485
486 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message,
487 int32 route_id) {
488 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, route_id);
489 Send(message);
490 }
491
505 } // namespace content 492 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698