OLD | NEW |
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 Loading... |
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 Loading... |
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); | 131 stub_->channel()->AddRoute(host_route_id_, this); |
133 child_message_loop_ = base::MessageLoopProxy::current(); | 132 child_message_loop_ = base::MessageLoopProxy::current(); |
134 make_context_current_ = | 133 make_context_current_ = |
135 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 134 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
136 } | 135 } |
137 | 136 |
138 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { | 137 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
139 // This class can only be self-deleted from OnWillDestroyStub(), which means | 138 // This class can only be self-deleted from OnWillDestroyStub(), which means |
140 // the VDA has already been destroyed in there. | 139 // the VDA has already been destroyed in there. |
141 CHECK(!video_decode_accelerator_.get()); | 140 DCHECK(!video_decode_accelerator_); |
142 } | 141 } |
143 | 142 |
144 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { | 143 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { |
145 if (!video_decode_accelerator_) | 144 if (!video_decode_accelerator_) |
146 return false; | 145 return false; |
147 | 146 |
148 bool handled = true; | 147 bool handled = true; |
149 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) | 148 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) |
150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) | 149 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) |
151 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, | 150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( | 209 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( |
211 host_route_id_, | 210 host_route_id_, |
212 picture.picture_buffer_id(), | 211 picture.picture_buffer_id(), |
213 picture.bitstream_buffer_id()))) { | 212 picture.bitstream_buffer_id()))) { |
214 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; | 213 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; |
215 } | 214 } |
216 } | 215 } |
217 | 216 |
218 void GpuVideoDecodeAccelerator::NotifyError( | 217 void GpuVideoDecodeAccelerator::NotifyError( |
219 media::VideoDecodeAccelerator::Error error) { | 218 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( | 219 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( |
231 host_route_id_, error))) { | 220 host_route_id_, error))) { |
232 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " | 221 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " |
233 << "failed"; | 222 << "failed"; |
234 } | 223 } |
235 } | 224 } |
236 | 225 |
237 void GpuVideoDecodeAccelerator::Initialize( | 226 void GpuVideoDecodeAccelerator::Initialize( |
238 const media::VideoCodecProfile profile, | 227 const media::VideoCodecProfile profile, |
239 IPC::Message* init_done_msg) { | 228 IPC::Message* init_done_msg) { |
240 DCHECK(!video_decode_accelerator_.get()); | 229 DCHECK(!video_decode_accelerator_.get()); |
241 DCHECK(!init_done_msg_); | |
242 DCHECK(init_done_msg); | |
243 init_done_msg_ = init_done_msg; | |
244 | 230 |
245 #if !defined(OS_WIN) | 231 #if !defined(OS_WIN) |
246 // Ensure we will be able to get a GL context at all before initializing | 232 // Ensure we will be able to get a GL context at all before initializing |
247 // non-Windows VDAs. | 233 // non-Windows VDAs. |
248 if (!make_context_current_.Run()) { | 234 if (!make_context_current_.Run()) { |
249 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 235 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
250 return; | 236 return; |
251 } | 237 } |
252 #endif | 238 #endif |
253 | 239 |
254 #if defined(OS_WIN) | 240 #if defined(OS_WIN) |
255 if (base::win::GetVersion() < base::win::VERSION_WIN7) { | 241 if (base::win::GetVersion() < base::win::VERSION_WIN7) { |
256 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 242 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
257 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 243 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
258 return; | 244 return; |
259 } | 245 } |
260 DVLOG(0) << "Initializing DXVA HW decoder for windows."; | 246 DVLOG(0) << "Initializing DXVA HW decoder for windows."; |
261 video_decode_accelerator_.reset( | 247 video_decode_accelerator_.reset( |
262 new DXVAVideoDecodeAccelerator(make_context_current_)); | 248 new DXVAVideoDecodeAccelerator(make_context_current_)); |
263 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) | 249 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) |
264 scoped_ptr<V4L2Device> device = | 250 scoped_ptr<V4L2Device> device = |
265 V4L2Device::Create(stub_->decoder()->GetGLContext()->GetHandle()); | 251 V4L2Device::Create(stub_->decoder()->GetGLContext()->GetHandle()); |
266 if (!device.get()) { | 252 if (!device.get()) { |
267 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 253 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
268 return; | 254 return; |
269 } | 255 } |
270 video_decode_accelerator_.reset( | 256 video_decode_accelerator_.reset( |
271 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), | 257 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), |
272 weak_factory_for_io_.GetWeakPtr(), | 258 weak_factory_for_io_.GetWeakPtr(), |
273 make_context_current_, | 259 make_context_current_, |
274 device.Pass(), | 260 device.Pass(), |
275 io_message_loop_)); | 261 io_message_loop_)); |
276 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 262 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
277 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { | 263 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { |
278 VLOG(1) << "HW video decode acceleration not available without " | 264 VLOG(1) << "HW video decode acceleration not available without " |
279 "DesktopGL (GLX)."; | 265 "DesktopGL (GLX)."; |
280 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 266 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
281 return; | 267 return; |
282 } | 268 } |
283 gfx::GLContextGLX* glx_context = | 269 gfx::GLContextGLX* glx_context = |
284 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); | 270 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); |
285 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( | 271 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( |
286 glx_context->display(), make_context_current_)); | 272 glx_context->display(), make_context_current_)); |
287 #elif defined(OS_ANDROID) | 273 #elif defined(OS_ANDROID) |
288 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( | 274 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( |
289 stub_->decoder()->AsWeakPtr(), | 275 stub_->decoder()->AsWeakPtr(), |
290 make_context_current_)); | 276 make_context_current_)); |
291 #else | 277 #else |
292 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 278 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
293 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 279 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
294 return; | 280 return; |
295 #endif | 281 #endif |
296 | 282 |
297 if (video_decode_accelerator_->CanDecodeOnIOThread()) { | 283 if (video_decode_accelerator_->CanDecodeOnIOThread()) { |
298 filter_ = new MessageFilter(this, host_route_id_); | 284 filter_ = new MessageFilter(this, host_route_id_); |
299 stub_->channel()->AddFilter(filter_.get()); | 285 stub_->channel()->AddFilter(filter_.get()); |
300 } | 286 } |
301 | 287 |
302 if (!video_decode_accelerator_->Initialize(profile, this)) | 288 if (!video_decode_accelerator_->Initialize(profile, this)) { |
303 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 289 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 290 return; |
| 291 } |
| 292 |
| 293 SendCreateDecoderReply(init_done_msg, host_route_id_); |
304 } | 294 } |
305 | 295 |
306 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is | 296 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
307 // true, otherwise on the main thread. | 297 // true, otherwise on the main thread. |
308 void GpuVideoDecodeAccelerator::OnDecode( | 298 void GpuVideoDecodeAccelerator::OnDecode( |
309 base::SharedMemoryHandle handle, int32 id, uint32 size) { | 299 base::SharedMemoryHandle handle, int32 id, uint32 size) { |
310 DCHECK(video_decode_accelerator_.get()); | 300 DCHECK(video_decode_accelerator_.get()); |
311 if (id < 0) { | 301 if (id < 0) { |
312 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; | 302 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; |
313 if (child_message_loop_->BelongsToCurrentThread()) { | 303 if (child_message_loop_->BelongsToCurrentThread()) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 420 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
431 int32 bitstream_buffer_id) { | 421 int32 bitstream_buffer_id) { |
432 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( | 422 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( |
433 host_route_id_, bitstream_buffer_id))) { | 423 host_route_id_, bitstream_buffer_id))) { |
434 DLOG(ERROR) | 424 DLOG(ERROR) |
435 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " | 425 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " |
436 << "failed"; | 426 << "failed"; |
437 } | 427 } |
438 } | 428 } |
439 | 429 |
440 void GpuVideoDecodeAccelerator::NotifyInitializeDone() { | |
441 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams( | |
442 init_done_msg_, host_route_id_); | |
443 if (!Send(init_done_msg_)) | |
444 DLOG(ERROR) << "Send(init_done_msg_) failed"; | |
445 init_done_msg_ = NULL; | |
446 } | |
447 | |
448 void GpuVideoDecodeAccelerator::NotifyFlushDone() { | 430 void GpuVideoDecodeAccelerator::NotifyFlushDone() { |
449 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) | 431 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) |
450 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; | 432 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; |
451 } | 433 } |
452 | 434 |
453 void GpuVideoDecodeAccelerator::NotifyResetDone() { | 435 void GpuVideoDecodeAccelerator::NotifyResetDone() { |
454 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) | 436 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) |
455 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; | 437 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; |
456 } | 438 } |
457 | 439 |
(...skipping 13 matching lines...) Expand all Loading... |
471 | 453 |
472 stub_->channel()->RemoveRoute(host_route_id_); | 454 stub_->channel()->RemoveRoute(host_route_id_); |
473 stub_->RemoveDestructionObserver(this); | 455 stub_->RemoveDestructionObserver(this); |
474 | 456 |
475 if (video_decode_accelerator_) | 457 if (video_decode_accelerator_) |
476 video_decode_accelerator_.release()->Destroy(); | 458 video_decode_accelerator_.release()->Destroy(); |
477 | 459 |
478 delete this; | 460 delete this; |
479 } | 461 } |
480 | 462 |
481 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | |
482 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | |
483 return filter_->SendOnIOThread(message); | |
484 DCHECK(child_message_loop_->BelongsToCurrentThread()); | |
485 return stub_->channel()->Send(message); | |
486 } | |
487 | |
488 void GpuVideoDecodeAccelerator::SetTextureCleared( | 463 void GpuVideoDecodeAccelerator::SetTextureCleared( |
489 const media::Picture& picture) { | 464 const media::Picture& picture) { |
490 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 465 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
491 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 466 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
492 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; | 467 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; |
493 it = uncleared_textures_.find(picture.picture_buffer_id()); | 468 it = uncleared_textures_.find(picture.picture_buffer_id()); |
494 if (it == uncleared_textures_.end()) | 469 if (it == uncleared_textures_.end()) |
495 return; // the texture has been cleared | 470 return; // the texture has been cleared |
496 | 471 |
497 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | 472 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; |
498 GLenum target = texture_ref->texture()->target(); | 473 GLenum target = texture_ref->texture()->target(); |
499 gpu::gles2::TextureManager* texture_manager = | 474 gpu::gles2::TextureManager* texture_manager = |
500 stub_->decoder()->GetContextGroup()->texture_manager(); | 475 stub_->decoder()->GetContextGroup()->texture_manager(); |
501 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); | 476 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); |
502 texture_manager->SetLevelCleared(texture_ref, target, 0, true); | 477 texture_manager->SetLevelCleared(texture_ref, target, 0, true); |
503 uncleared_textures_.erase(it); | 478 uncleared_textures_.erase(it); |
504 } | 479 } |
505 | 480 |
| 481 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { |
| 482 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) |
| 483 return filter_->SendOnIOThread(message); |
| 484 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
| 485 return stub_->channel()->Send(message); |
| 486 } |
| 487 |
| 488 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, |
| 489 int32 route_id) { |
| 490 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, route_id); |
| 491 Send(message); |
| 492 } |
| 493 |
506 } // namespace content | 494 } // namespace content |
OLD | NEW |