Index: content/renderer/media/rtc_video_decoder.cc |
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc |
index d05cdc99a6569366e7c49b35a8d7993c5b4cb00c..dd043c289a5a55a68bb4e5ef55e45033d0f6687e 100644 |
--- a/content/renderer/media/rtc_video_decoder.cc |
+++ b/content/renderer/media/rtc_video_decoder.cc |
@@ -11,13 +11,11 @@ |
#include "base/metrics/histogram.h" |
#include "base/numerics/safe_conversions.h" |
#include "base/stl_util.h" |
-#include "base/synchronization/waitable_event.h" |
#include "base/task_runner_util.h" |
#include "content/child/child_thread.h" |
#include "content/renderer/media/native_handle_impl.h" |
#include "media/base/bind_to_current_loop.h" |
#include "media/filters/gpu_video_accelerator_factories.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
#include "third_party/webrtc/common_video/interface/texture_video_frame.h" |
#include "third_party/webrtc/system_wrappers/interface/ref_count.h" |
@@ -87,12 +85,28 @@ |
weak_factory_(this) { |
DCHECK(!vda_task_runner_->BelongsToCurrentThread()); |
weak_this_ = weak_factory_.GetWeakPtr(); |
+ |
+ base::WaitableEvent message_loop_async_waiter(false, false); |
+ // Waiting here is safe. The media thread is stopped in the child thread and |
+ // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder |
+ // runs. |
+ vda_task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&RTCVideoDecoder::Initialize, |
+ base::Unretained(this), |
+ &message_loop_async_waiter)); |
+ message_loop_async_waiter.Wait(); |
} |
RTCVideoDecoder::~RTCVideoDecoder() { |
DVLOG(2) << "~RTCVideoDecoder"; |
- DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
- DestroyVDA(); |
+ // Destroy VDA and remove |this| from the observer if this is vda thread. |
+ if (vda_task_runner_->BelongsToCurrentThread()) { |
+ base::MessageLoop::current()->RemoveDestructionObserver(this); |
+ DestroyVDA(); |
+ } else { |
+ // VDA should have been destroyed in WillDestroyCurrentMessageLoop. |
+ DCHECK(!vda_); |
+ } |
// Delete all shared memories. |
STLDeleteElements(&available_shm_segments_); |
@@ -110,7 +124,6 @@ |
} |
} |
-// static |
scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create( |
webrtc::VideoCodecType type, |
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) { |
@@ -126,15 +139,9 @@ |
return decoder.Pass(); |
} |
- base::WaitableEvent waiter(true, false); |
decoder.reset(new RTCVideoDecoder(factories)); |
- decoder->vda_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&RTCVideoDecoder::CreateVDA, |
- base::Unretained(decoder.get()), |
- profile, |
- &waiter)); |
- waiter.Wait(); |
+ decoder->vda_ = |
+ factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass(); |
// vda can be NULL if VP8 is not supported. |
if (decoder->vda_ != NULL) { |
decoder->state_ = INITIALIZED; |
@@ -399,33 +406,6 @@ |
} |
} |
-static void ReadPixelsSyncInner( |
- const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
- uint32 texture_id, |
- const gfx::Rect& visible_rect, |
- const SkBitmap& pixels, |
- base::WaitableEvent* event) { |
- factories->ReadPixels(texture_id, visible_rect, pixels); |
- event->Signal(); |
-} |
- |
-static void ReadPixelsSync( |
- const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
- uint32 texture_id, |
- const gfx::Rect& visible_rect, |
- const SkBitmap& pixels) { |
- base::WaitableEvent event(true, false); |
- if (!factories->GetTaskRunner()->PostTask(FROM_HERE, |
- base::Bind(&ReadPixelsSyncInner, |
- factories, |
- texture_id, |
- visible_rect, |
- pixels, |
- &event))) |
- return; |
- event.Wait(); |
-} |
- |
scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( |
const media::Picture& picture, |
const media::PictureBuffer& pb, |
@@ -434,6 +414,7 @@ |
uint32_t height, |
size_t size) { |
gfx::Rect visible_rect(width, height); |
+ gfx::Size natural_size(width, height); |
DCHECK(decoder_texture_target_); |
// Convert timestamp from 90KHz to ms. |
base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( |
@@ -449,9 +430,12 @@ |
decoder_texture_target_, |
pb.size(), |
visible_rect, |
- visible_rect.size(), |
+ natural_size, |
timestamp_ms, |
- base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect), |
+ base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels, |
+ factories_, |
+ pb.texture_id(), |
+ natural_size), |
base::Closure()); |
} |
@@ -510,6 +494,21 @@ |
base::AutoLock auto_lock(lock_); |
state_ = DECODE_ERROR; |
+} |
+ |
+void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { |
+ DVLOG(2) << "WillDestroyCurrentMessageLoop"; |
+ DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
+ factories_->Abort(); |
+ weak_factory_.InvalidateWeakPtrs(); |
+ DestroyVDA(); |
+} |
+ |
+void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) { |
+ DVLOG(2) << "Initialize"; |
+ DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
+ base::MessageLoop::current()->AddDestructionObserver(this); |
+ waiter->Signal(); |
} |
void RTCVideoDecoder::RequestBufferDecode() { |
@@ -671,13 +670,6 @@ |
vda_->ReusePictureBuffer(picture_buffer_id); |
} |
-void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile, |
- base::WaitableEvent* waiter) { |
- DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
- vda_ = factories_->CreateVideoDecodeAccelerator(profile, this); |
- waiter->Signal(); |
-} |
- |
void RTCVideoDecoder::DestroyTextures() { |
DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
std::map<int32, media::PictureBuffer>::iterator it; |