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 4a43f431395cbc78d898b61b2fb5784359575ae3..e03001531a90f86758a819a79dcdbbbc3bce22c2 100644 |
--- a/content/renderer/media/rtc_video_decoder.cc |
+++ b/content/renderer/media/rtc_video_decoder.cc |
@@ -73,7 +73,6 @@ RTCVideoDecoder::RTCVideoDecoder( |
weak_this_(weak_factory_.GetWeakPtr()), |
factories_(factories), |
vda_loop_proxy_(factories_->GetMessageLoop()), |
- create_shm_thread_("CreateSHMThread"), |
decoder_texture_target_(0), |
next_picture_buffer_id_(0), |
state_(UNINITIALIZED), |
@@ -81,35 +80,23 @@ RTCVideoDecoder::RTCVideoDecoder( |
num_shm_buffers_(0), |
next_bitstream_buffer_id_(0), |
reset_bitstream_buffer_id_(ID_INVALID) { |
- create_shm_thread_.Start(); |
- // Initialize directly if |vda_loop_proxy_| is the renderer thread. |
- base::WaitableEvent compositor_loop_async_waiter(false, false); |
- if (vda_loop_proxy_->BelongsToCurrentThread()) { |
- Initialize(&compositor_loop_async_waiter); |
- return; |
- } |
- // Post the task if |vda_loop_proxy_| is the compositor thread. Waiting here |
- // is safe because the compositor thread will not be stopped until the |
- // renderer thread shuts down. |
+ DCHECK(!vda_loop_proxy_->BelongsToCurrentThread()); |
+ base::WaitableEvent message_loop_async_waiter(false, false); |
+ // Waiting here is safe because RTCVideoDecoderFactory owns the thread. |
vda_loop_proxy_->PostTask(FROM_HERE, |
base::Bind(&RTCVideoDecoder::Initialize, |
base::Unretained(this), |
- &compositor_loop_async_waiter)); |
- compositor_loop_async_waiter.Wait(); |
+ &message_loop_async_waiter)); |
+ message_loop_async_waiter.Wait(); |
} |
RTCVideoDecoder::~RTCVideoDecoder() { |
DVLOG(2) << "~RTCVideoDecoder"; |
- factories_->Abort(); |
- create_shm_thread_.Stop(); |
- // Delete vda and remove |this| from the observer if vda thread is alive. |
- if (vda_loop_proxy_->BelongsToCurrentThread()) { |
+ // Remove |this| from the observer if vda thread is alive. |
+ if (vda_loop_proxy_->BelongsToCurrentThread()) |
base::MessageLoop::current()->RemoveDestructionObserver(this); |
- DestroyVDA(); |
- } else { |
- // VDA should have been destroyed in WillDestroyCurrentMessageLoop. |
- DCHECK(!vda_); |
- } |
+ // VDA should have been destroyed. |
+ DCHECK(!vda_); |
// Delete all shared memories. |
STLDeleteElements(&available_shm_segments_); |
@@ -128,10 +115,23 @@ RTCVideoDecoder::~RTCVideoDecoder() { |
} |
scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create( |
+ webrtc::VideoCodecType type, |
const scoped_refptr<media::GpuVideoDecoder::Factories>& factories) { |
- scoped_ptr<RTCVideoDecoder> decoder(new RTCVideoDecoder(factories)); |
- decoder->vda_.reset(factories->CreateVideoDecodeAccelerator( |
- media::VP8PROFILE_MAIN, decoder.get())); |
+ scoped_ptr<RTCVideoDecoder> decoder; |
+ // Convert WebRTC codec type to media codec profile. |
+ media::VideoCodecProfile profile; |
+ switch (type) { |
+ case webrtc::kVideoCodecVP8: |
+ profile = media::VP8PROFILE_MAIN; |
+ break; |
+ default: |
+ DVLOG(2) << "Video codec not supported:" << type; |
+ return decoder.Pass(); |
+ } |
+ |
+ decoder.reset(new RTCVideoDecoder(factories)); |
+ decoder->vda_ |
+ .reset(factories->CreateVideoDecodeAccelerator(profile, decoder.get())); |
// vda can be NULL if VP8 is not supported. |
if (decoder->vda_ != NULL) { |
decoder->state_ = INITIALIZED; |
@@ -157,14 +157,11 @@ int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, |
} |
// Create some shared memory if the queue is empty. |
if (available_shm_segments_.size() == 0) { |
- // Unretained is safe because the destructor will wait until |
- // |create_shm_thread_| stops. |
- create_shm_thread_.message_loop_proxy() |
- ->PostTask(FROM_HERE, |
- base::Bind(&RTCVideoDecoder::CreateSHM, |
- base::Unretained(this), |
- kMaxInFlightDecodes, |
- kSharedMemorySegmentBytes)); |
+ vda_loop_proxy_->PostTask(FROM_HERE, |
+ base::Bind(&RTCVideoDecoder::CreateSHM, |
+ weak_this_, |
+ kMaxInFlightDecodes, |
+ kSharedMemorySegmentBytes)); |
} |
return WEBRTC_VIDEO_CODEC_OK; |
} |
@@ -231,9 +228,19 @@ int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( |
int32_t RTCVideoDecoder::Release() { |
DVLOG(2) << "Release"; |
- // Do not destroy VDA because the decoder will be recycled by |
- // RTCVideoDecoderFactory. Just reset VDA. |
- return Reset(); |
+ base::AutoLock auto_lock(lock_); |
+ if (state_ == UNINITIALIZED) { |
+ LOG(ERROR) << "Decoder not initialized."; |
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
+ } |
+ if (next_bitstream_buffer_id_ != 0) |
+ reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; |
+ else |
+ reset_bitstream_buffer_id_ = ID_LAST; |
+ factories_->Abort(); |
+ vda_loop_proxy_->PostTask( |
+ FROM_HERE, base::Bind(&RTCVideoDecoder::ReleaseInternal, weak_this_)); |
+ return WEBRTC_VIDEO_CODEC_OK; |
} |
int32_t RTCVideoDecoder::Reset() { |
@@ -594,6 +601,12 @@ void RTCVideoDecoder::ResetInternal() { |
vda_->Reset(); |
} |
+void RTCVideoDecoder::ReleaseInternal() { |
+ DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
+ DVLOG(2) << "ReleaseInternal"; |
+ DestroyVDA(); |
+} |
+ |
void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, |
uint32 sync_point) { |
DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
@@ -660,16 +673,13 @@ scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked( |
ret = available_shm_segments_.back(); |
available_shm_segments_.pop_back(); |
} |
- // Post to the child thread to create shared memory if SHM cannot be reused |
- // or the queue is almost empty. |
+ // Post to vda thread to create shared memory if SHM cannot be reused or the |
+ // queue is almost empty. |
if (num_shm_buffers_ < kMaxNumSharedMemorySegments && |
(ret == NULL || available_shm_segments_.size() <= 1)) { |
- create_shm_thread_.message_loop_proxy()->PostTask( |
+ vda_loop_proxy_->PostTask( |
FROM_HERE, |
- // Unretained is safe because the destructor will wait until |
- // |create_shm_thread_| stops. |
- base::Bind( |
- &RTCVideoDecoder::CreateSHM, base::Unretained(this), 1, min_size)); |
+ base::Bind(&RTCVideoDecoder::CreateSHM, weak_this_, 1, min_size)); |
} |
return scoped_ptr<SHMBuffer>(ret); |
} |
@@ -679,7 +689,7 @@ void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { |
} |
void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { |
- DCHECK(create_shm_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
+ DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
DVLOG(2) << "CreateSHM. size=" << min_size; |
int number_to_allocate; |
{ |
@@ -695,12 +705,10 @@ void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { |
num_shm_buffers_++; |
PutSHM_Locked( |
scoped_ptr<SHMBuffer>(new SHMBuffer(shm, size_to_allocate))); |
- // Kick off the decoding. |
- vda_loop_proxy_->PostTask( |
- FROM_HERE, |
- base::Bind(&RTCVideoDecoder::RequestBufferDecode, weak_this_)); |
} |
} |
+ // Kick off the decoding. |
+ RequestBufferDecode(); |
} |
void RTCVideoDecoder::RecordBufferData(const BufferData& buffer_data) { |