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 16 matching lines...) Expand all Loading... | |
27 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" | 27 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" |
28 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) | 28 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) |
29 #include "content/common/gpu/media/exynos_video_decode_accelerator.h" | 29 #include "content/common/gpu/media/exynos_video_decode_accelerator.h" |
30 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 30 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
31 #include "ui/gl/gl_context_glx.h" | 31 #include "ui/gl/gl_context_glx.h" |
32 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h" | 32 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h" |
33 #elif defined(OS_ANDROID) | 33 #elif defined(OS_ANDROID) |
34 #include "content/common/gpu/media/android_video_decode_accelerator.h" | 34 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
35 #endif | 35 #endif |
36 | 36 |
37 #include "gpu/command_buffer/service/texture_manager.h" | |
38 #include "ui/gfx/size.h" | 37 #include "ui/gfx/size.h" |
39 | 38 |
40 namespace content { | 39 namespace content { |
41 | 40 |
42 static bool MakeDecoderContextCurrent( | 41 static bool MakeDecoderContextCurrent( |
43 const base::WeakPtr<GpuCommandBufferStub> stub) { | 42 const base::WeakPtr<GpuCommandBufferStub> stub) { |
44 if (!stub.get()) { | 43 if (!stub.get()) { |
45 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; | 44 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; |
46 return false; | 45 return false; |
47 } | 46 } |
48 | 47 |
49 if (!stub->decoder()->MakeCurrent()) { | 48 if (!stub->decoder()->MakeCurrent()) { |
50 DLOG(ERROR) << "Failed to MakeCurrent()"; | 49 DLOG(ERROR) << "Failed to MakeCurrent()"; |
51 return false; | 50 return false; |
52 } | 51 } |
53 | 52 |
54 return true; | 53 return true; |
55 } | 54 } |
56 | 55 |
56 // A helper class that works like AutoLock but only acquires the lock when | |
57 // DCHECK is on. | |
58 class DebugAutoLock { | |
59 public: | |
60 explicit DebugAutoLock(base::Lock& lock) : lock_(lock) { | |
61 if (DCHECK_IS_ON()) | |
62 lock_.Acquire(); | |
63 } | |
64 | |
65 ~DebugAutoLock() { | |
66 if (DCHECK_IS_ON()) { | |
67 lock_.AssertAcquired(); | |
68 lock_.Release(); | |
69 } | |
70 } | |
71 | |
72 private: | |
73 base::Lock& lock_; | |
74 DISALLOW_COPY_AND_ASSIGN(DebugAutoLock); | |
75 }; | |
76 | |
57 class GpuVideoDecodeAccelerator::MessageFilter | 77 class GpuVideoDecodeAccelerator::MessageFilter |
58 : public IPC::ChannelProxy::MessageFilter { | 78 : public IPC::ChannelProxy::MessageFilter { |
59 public: | 79 public: |
60 MessageFilter(GpuVideoDecodeAccelerator* owner, int32 host_route_id) | 80 MessageFilter(GpuVideoDecodeAccelerator* owner, int32 host_route_id) |
61 : owner_(owner), host_route_id_(host_route_id) {} | 81 : owner_(owner), host_route_id_(host_route_id) {} |
62 | 82 |
63 virtual void OnChannelError() OVERRIDE { channel_ = NULL; } | 83 virtual void OnChannelError() OVERRIDE { channel_ = NULL; } |
64 | 84 |
65 virtual void OnChannelClosing() OVERRIDE { channel_ = NULL; } | 85 virtual void OnChannelClosing() OVERRIDE { channel_ = NULL; } |
66 | 86 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 } | 189 } |
170 | 190 |
171 void GpuVideoDecodeAccelerator::DismissPictureBuffer( | 191 void GpuVideoDecodeAccelerator::DismissPictureBuffer( |
172 int32 picture_buffer_id) { | 192 int32 picture_buffer_id) { |
173 // Notify client that picture buffer is now unused. | 193 // Notify client that picture buffer is now unused. |
174 if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer( | 194 if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer( |
175 host_route_id_, picture_buffer_id))) { | 195 host_route_id_, picture_buffer_id))) { |
176 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) " | 196 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) " |
177 << "failed"; | 197 << "failed"; |
178 } | 198 } |
199 DebugAutoLock auto_lock(lock_); | |
200 uncleared_textures_.erase(picture_buffer_id); | |
179 } | 201 } |
180 | 202 |
181 void GpuVideoDecodeAccelerator::PictureReady( | 203 void GpuVideoDecodeAccelerator::PictureReady( |
182 const media::Picture& picture) { | 204 const media::Picture& picture) { |
205 // VDA may call PictureReady on IO thread. SetTextureCleared should run on | |
206 // the child thread. VDA is responsible to call PictureReady on the child | |
207 // thread when a picture buffer is delivered the first time. | |
208 if (child_message_loop_->BelongsToCurrentThread()) { | |
209 if (!SetTextureCleared(picture)) | |
210 return; | |
211 } else { | |
212 DCHECK(io_message_loop_->BelongsToCurrentThread()); | |
213 if (DCHECK_IS_ON()) { | |
214 DebugAutoLock auto_lock(lock_); | |
215 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); | |
216 } | |
217 } | |
218 | |
183 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( | 219 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( |
184 host_route_id_, | 220 host_route_id_, |
185 picture.picture_buffer_id(), | 221 picture.picture_buffer_id(), |
186 picture.bitstream_buffer_id()))) { | 222 picture.bitstream_buffer_id()))) { |
187 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; | 223 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; |
188 } | 224 } |
189 } | 225 } |
190 | 226 |
191 void GpuVideoDecodeAccelerator::NotifyError( | 227 void GpuVideoDecodeAccelerator::NotifyError( |
192 media::VideoDecodeAccelerator::Error error) { | 228 media::VideoDecodeAccelerator::Error error) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 if (buffer_ids.size() != texture_ids.size()) { | 334 if (buffer_ids.size() != texture_ids.size()) { |
299 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 335 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
300 return; | 336 return; |
301 } | 337 } |
302 | 338 |
303 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); | 339 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); |
304 gpu::gles2::TextureManager* texture_manager = | 340 gpu::gles2::TextureManager* texture_manager = |
305 command_decoder->GetContextGroup()->texture_manager(); | 341 command_decoder->GetContextGroup()->texture_manager(); |
306 | 342 |
307 std::vector<media::PictureBuffer> buffers; | 343 std::vector<media::PictureBuffer> buffers; |
344 std::vector<scoped_refptr<gpu::gles2::TextureRef> > textures; | |
308 for (uint32 i = 0; i < buffer_ids.size(); ++i) { | 345 for (uint32 i = 0; i < buffer_ids.size(); ++i) { |
309 if (buffer_ids[i] < 0) { | 346 if (buffer_ids[i] < 0) { |
310 DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range"; | 347 DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range"; |
311 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 348 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
312 return; | 349 return; |
313 } | 350 } |
314 gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture( | 351 gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture( |
315 texture_ids[i]); | 352 texture_ids[i]); |
316 if (!texture_ref) { | 353 if (!texture_ref) { |
317 DLOG(ERROR) << "Failed to find texture id " << texture_ids[i]; | 354 DLOG(ERROR) << "Failed to find texture id " << texture_ids[i]; |
318 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 355 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
319 return; | 356 return; |
320 } | 357 } |
321 gpu::gles2::Texture* info = texture_ref->texture(); | 358 gpu::gles2::Texture* info = texture_ref->texture(); |
322 if (info->target() != texture_target_) { | 359 if (info->target() != texture_target_) { |
323 DLOG(ERROR) << "Texture target mismatch for texture id " | 360 DLOG(ERROR) << "Texture target mismatch for texture id " |
324 << texture_ids[i]; | 361 << texture_ids[i]; |
325 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 362 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
326 return; | 363 return; |
327 } | 364 } |
328 if (texture_target_ == GL_TEXTURE_EXTERNAL_OES) { | 365 if (texture_target_ == GL_TEXTURE_EXTERNAL_OES) { |
329 // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the | 366 // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the |
330 // underlying EGLImage. Use |texture_dimensions_| for this size. The | 367 // underlying EGLImage. Use |texture_dimensions_| for this size. |
331 // textures cannot be rendered to or cleared, so we set |cleared| true to | |
332 // skip clearing. | |
333 texture_manager->SetLevelInfo(texture_ref, | 368 texture_manager->SetLevelInfo(texture_ref, |
334 GL_TEXTURE_EXTERNAL_OES, | 369 GL_TEXTURE_EXTERNAL_OES, |
335 0, | 370 0, |
336 0, | 371 0, |
337 texture_dimensions_.width(), | 372 texture_dimensions_.width(), |
338 texture_dimensions_.height(), | 373 texture_dimensions_.height(), |
339 1, | 374 1, |
340 0, | 375 0, |
341 0, | 376 0, |
342 0, | 377 0, |
343 true); | 378 false); |
344 } else { | 379 } else { |
345 // For other targets, texture dimensions should already be defined. | 380 // For other targets, texture dimensions should already be defined. |
346 GLsizei width = 0, height = 0; | 381 GLsizei width = 0, height = 0; |
347 info->GetLevelSize(texture_target_, 0, &width, &height); | 382 info->GetLevelSize(texture_target_, 0, &width, &height); |
348 if (width != texture_dimensions_.width() || | 383 if (width != texture_dimensions_.width() || |
349 height != texture_dimensions_.height()) { | 384 height != texture_dimensions_.height()) { |
350 DLOG(ERROR) << "Size mismatch for texture id " << texture_ids[i]; | 385 DLOG(ERROR) << "Size mismatch for texture id " << texture_ids[i]; |
351 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 386 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
352 return; | 387 return; |
353 } | 388 } |
354 } | 389 } |
355 if (!texture_manager->ClearRenderableLevels(command_decoder, texture_ref)) { | |
356 DLOG(ERROR) << "Failed to Clear texture id " << texture_ids[i]; | |
357 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | |
358 return; | |
359 } | |
360 uint32 service_texture_id; | 390 uint32 service_texture_id; |
361 if (!command_decoder->GetServiceTextureId( | 391 if (!command_decoder->GetServiceTextureId( |
362 texture_ids[i], &service_texture_id)) { | 392 texture_ids[i], &service_texture_id)) { |
363 DLOG(ERROR) << "Failed to translate texture!"; | 393 DLOG(ERROR) << "Failed to translate texture!"; |
364 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 394 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
365 return; | 395 return; |
366 } | 396 } |
367 buffers.push_back(media::PictureBuffer( | 397 buffers.push_back(media::PictureBuffer( |
368 buffer_ids[i], texture_dimensions_, service_texture_id)); | 398 buffer_ids[i], texture_dimensions_, service_texture_id)); |
399 textures.push_back(texture_ref); | |
369 } | 400 } |
370 video_decode_accelerator_->AssignPictureBuffers(buffers); | 401 video_decode_accelerator_->AssignPictureBuffers(buffers); |
402 DebugAutoLock auto_lock(lock_); | |
403 for (uint32 i = 0; i < buffer_ids.size(); ++i) | |
404 uncleared_textures_[buffer_ids[i]] = textures[i]; | |
371 } | 405 } |
372 | 406 |
373 void GpuVideoDecodeAccelerator::OnReusePictureBuffer( | 407 void GpuVideoDecodeAccelerator::OnReusePictureBuffer( |
374 int32 picture_buffer_id) { | 408 int32 picture_buffer_id) { |
375 DCHECK(video_decode_accelerator_.get()); | 409 DCHECK(video_decode_accelerator_.get()); |
376 video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id); | 410 video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id); |
377 } | 411 } |
378 | 412 |
379 void GpuVideoDecodeAccelerator::OnFlush() { | 413 void GpuVideoDecodeAccelerator::OnFlush() { |
380 DCHECK(video_decode_accelerator_.get()); | 414 DCHECK(video_decode_accelerator_.get()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 } | 473 } |
440 | 474 |
441 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | 475 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { |
442 DCHECK(stub_); | 476 DCHECK(stub_); |
443 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | 477 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) |
444 return filter_->SendOnIOThread(message); | 478 return filter_->SendOnIOThread(message); |
445 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 479 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
446 return stub_->channel()->Send(message); | 480 return stub_->channel()->Send(message); |
447 } | 481 } |
448 | 482 |
483 bool GpuVideoDecodeAccelerator::SetTextureCleared( | |
484 const media::Picture& picture) { | |
485 DCHECK(child_message_loop_->BelongsToCurrentThread()); | |
486 DebugAutoLock auto_lock(lock_); | |
487 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; | |
488 it = uncleared_textures_.find(picture.picture_buffer_id()); | |
489 if (it == uncleared_textures_.end()) | |
490 return true; | |
Ami GONE FROM CHROMIUM
2013/09/30 18:03:03
NOTREACHED?
Ami GONE FROM CHROMIUM
2013/09/30 18:03:03
return false?
(as it is, this function always retu
wuchengli
2013/10/01 03:49:43
Done. Changed to return void.
| |
491 | |
492 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | |
493 GLenum target = texture_ref->texture()->target(); | |
494 gpu::gles2::TextureManager* texture_manager = | |
495 stub_->decoder()->GetContextGroup()->texture_manager(); | |
496 texture_manager->SetLevelCleared(texture_ref, target, 0, true); | |
497 uncleared_textures_.erase(it); | |
498 return true; | |
499 } | |
500 | |
449 } // namespace content | 501 } // namespace content |
OLD | NEW |