OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderer/media/rtc_video_decoder.h" | 5 #include "content/renderer/media/rtc_video_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 vda_task_runner_(factories->GetTaskRunner()), | 80 vda_task_runner_(factories->GetTaskRunner()), |
81 decoder_texture_target_(0), | 81 decoder_texture_target_(0), |
82 next_picture_buffer_id_(0), | 82 next_picture_buffer_id_(0), |
83 state_(UNINITIALIZED), | 83 state_(UNINITIALIZED), |
84 decode_complete_callback_(NULL), | 84 decode_complete_callback_(NULL), |
85 num_shm_buffers_(0), | 85 num_shm_buffers_(0), |
86 next_bitstream_buffer_id_(0), | 86 next_bitstream_buffer_id_(0), |
87 reset_bitstream_buffer_id_(ID_INVALID), | 87 reset_bitstream_buffer_id_(ID_INVALID), |
88 weak_factory_(this) { | 88 weak_factory_(this) { |
89 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); | 89 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); |
90 weak_this_ = weak_factory_.GetWeakPtr(); | |
91 } | 90 } |
92 | 91 |
93 RTCVideoDecoder::~RTCVideoDecoder() { | 92 RTCVideoDecoder::~RTCVideoDecoder() { |
94 DVLOG(2) << "~RTCVideoDecoder"; | 93 DVLOG(2) << "~RTCVideoDecoder"; |
95 DCHECK(vda_task_runner_->BelongsToCurrentThread()); | 94 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
96 DestroyVDA(); | 95 DestroyVDA(); |
97 | 96 |
98 // Delete all shared memories. | 97 // Delete all shared memories. |
99 STLDeleteElements(&available_shm_segments_); | 98 STLDeleteElements(&available_shm_segments_); |
100 STLDeleteValues(&bitstream_buffers_in_decoder_); | 99 STLDeleteValues(&bitstream_buffers_in_decoder_); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 | 155 |
157 base::AutoLock auto_lock(lock_); | 156 base::AutoLock auto_lock(lock_); |
158 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { | 157 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { |
159 LOG(ERROR) << "VDA is not initialized. state=" << state_; | 158 LOG(ERROR) << "VDA is not initialized. state=" << state_; |
160 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); | 159 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
161 } | 160 } |
162 // Create some shared memory if the queue is empty. | 161 // Create some shared memory if the queue is empty. |
163 if (available_shm_segments_.size() == 0) { | 162 if (available_shm_segments_.size() == 0) { |
164 vda_task_runner_->PostTask(FROM_HERE, | 163 vda_task_runner_->PostTask(FROM_HERE, |
165 base::Bind(&RTCVideoDecoder::CreateSHM, | 164 base::Bind(&RTCVideoDecoder::CreateSHM, |
166 weak_this_, | 165 weak_factory_.GetWeakPtr(), |
167 kMaxInFlightDecodes, | 166 kMaxInFlightDecodes, |
168 kSharedMemorySegmentBytes)); | 167 kSharedMemorySegmentBytes)); |
169 } | 168 } |
170 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); | 169 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); |
171 } | 170 } |
172 | 171 |
173 int32_t RTCVideoDecoder::Decode( | 172 int32_t RTCVideoDecoder::Decode( |
174 const webrtc::EncodedImage& inputImage, | 173 const webrtc::EncodedImage& inputImage, |
175 bool missingFrames, | 174 bool missingFrames, |
176 const webrtc::RTPFragmentationHeader* /*fragmentation*/, | 175 const webrtc::RTPFragmentationHeader* /*fragmentation*/, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) | 243 if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) |
245 return WEBRTC_VIDEO_CODEC_ERROR; | 244 return WEBRTC_VIDEO_CODEC_ERROR; |
246 if (need_to_reset_for_midstream_resize) { | 245 if (need_to_reset_for_midstream_resize) { |
247 base::AutoUnlock auto_unlock(lock_); | 246 base::AutoUnlock auto_unlock(lock_); |
248 Reset(); | 247 Reset(); |
249 } | 248 } |
250 return WEBRTC_VIDEO_CODEC_OK; | 249 return WEBRTC_VIDEO_CODEC_OK; |
251 } | 250 } |
252 | 251 |
253 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); | 252 SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); |
254 vda_task_runner_->PostTask( | 253 vda_task_runner_->PostTask(FROM_HERE, |
255 FROM_HERE, base::Bind(&RTCVideoDecoder::RequestBufferDecode, weak_this_)); | 254 base::Bind(&RTCVideoDecoder::RequestBufferDecode, |
| 255 weak_factory_.GetWeakPtr())); |
256 return WEBRTC_VIDEO_CODEC_OK; | 256 return WEBRTC_VIDEO_CODEC_OK; |
257 } | 257 } |
258 | 258 |
259 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( | 259 int32_t RTCVideoDecoder::RegisterDecodeCompleteCallback( |
260 webrtc::DecodedImageCallback* callback) { | 260 webrtc::DecodedImageCallback* callback) { |
261 DVLOG(2) << "RegisterDecodeCompleteCallback"; | 261 DVLOG(2) << "RegisterDecodeCompleteCallback"; |
262 base::AutoLock auto_lock(lock_); | 262 base::AutoLock auto_lock(lock_); |
263 decode_complete_callback_ = callback; | 263 decode_complete_callback_ = callback; |
264 return WEBRTC_VIDEO_CODEC_OK; | 264 return WEBRTC_VIDEO_CODEC_OK; |
265 } | 265 } |
(...skipping 12 matching lines...) Expand all Loading... |
278 LOG(ERROR) << "Decoder not initialized."; | 278 LOG(ERROR) << "Decoder not initialized."; |
279 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 279 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
280 } | 280 } |
281 if (next_bitstream_buffer_id_ != 0) | 281 if (next_bitstream_buffer_id_ != 0) |
282 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; | 282 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; |
283 else | 283 else |
284 reset_bitstream_buffer_id_ = ID_LAST; | 284 reset_bitstream_buffer_id_ = ID_LAST; |
285 // If VDA is already resetting, no need to request the reset again. | 285 // If VDA is already resetting, no need to request the reset again. |
286 if (state_ != RESETTING) { | 286 if (state_ != RESETTING) { |
287 state_ = RESETTING; | 287 state_ = RESETTING; |
288 vda_task_runner_->PostTask( | 288 vda_task_runner_->PostTask(FROM_HERE, |
289 FROM_HERE, base::Bind(&RTCVideoDecoder::ResetInternal, weak_this_)); | 289 base::Bind(&RTCVideoDecoder::ResetInternal, |
| 290 weak_factory_.GetWeakPtr())); |
290 } | 291 } |
291 return WEBRTC_VIDEO_CODEC_OK; | 292 return WEBRTC_VIDEO_CODEC_OK; |
292 } | 293 } |
293 | 294 |
294 void RTCVideoDecoder::NotifyInitializeDone() { | 295 void RTCVideoDecoder::NotifyInitializeDone() { |
295 DVLOG(2) << "NotifyInitializeDone"; | 296 DVLOG(2) << "NotifyInitializeDone"; |
296 NOTREACHED(); | 297 NOTREACHED(); |
297 } | 298 } |
298 | 299 |
299 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, | 300 void RTCVideoDecoder::ProvidePictureBuffers(uint32 count, |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 size_t size) { | 435 size_t size) { |
435 gfx::Rect visible_rect(width, height); | 436 gfx::Rect visible_rect(width, height); |
436 DCHECK(decoder_texture_target_); | 437 DCHECK(decoder_texture_target_); |
437 // Convert timestamp from 90KHz to ms. | 438 // Convert timestamp from 90KHz to ms. |
438 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( | 439 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( |
439 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); | 440 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); |
440 return media::VideoFrame::WrapNativeTexture( | 441 return media::VideoFrame::WrapNativeTexture( |
441 make_scoped_ptr(new gpu::MailboxHolder( | 442 make_scoped_ptr(new gpu::MailboxHolder( |
442 pb.texture_mailbox(), decoder_texture_target_, 0)), | 443 pb.texture_mailbox(), decoder_texture_target_, 0)), |
443 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer, | 444 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer, |
444 weak_this_, | 445 weak_factory_.GetWeakPtr(), |
445 picture.picture_buffer_id())), | 446 picture.picture_buffer_id())), |
446 pb.size(), | 447 pb.size(), |
447 visible_rect, | 448 visible_rect, |
448 visible_rect.size(), | 449 visible_rect.size(), |
449 timestamp_ms, | 450 timestamp_ms, |
450 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)); | 451 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)); |
451 } | 452 } |
452 | 453 |
453 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 454 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
454 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; | 455 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 SHMBuffer* ret = NULL; | 712 SHMBuffer* ret = NULL; |
712 if (!available_shm_segments_.empty() && | 713 if (!available_shm_segments_.empty() && |
713 available_shm_segments_.back()->size >= min_size) { | 714 available_shm_segments_.back()->size >= min_size) { |
714 ret = available_shm_segments_.back(); | 715 ret = available_shm_segments_.back(); |
715 available_shm_segments_.pop_back(); | 716 available_shm_segments_.pop_back(); |
716 } | 717 } |
717 // Post to vda thread to create shared memory if SHM cannot be reused or the | 718 // Post to vda thread to create shared memory if SHM cannot be reused or the |
718 // queue is almost empty. | 719 // queue is almost empty. |
719 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && | 720 if (num_shm_buffers_ < kMaxNumSharedMemorySegments && |
720 (ret == NULL || available_shm_segments_.size() <= 1)) { | 721 (ret == NULL || available_shm_segments_.size() <= 1)) { |
721 vda_task_runner_->PostTask( | 722 vda_task_runner_->PostTask(FROM_HERE, |
722 FROM_HERE, | 723 base::Bind(&RTCVideoDecoder::CreateSHM, |
723 base::Bind(&RTCVideoDecoder::CreateSHM, weak_this_, 1, min_size)); | 724 weak_factory_.GetWeakPtr(), |
| 725 1, |
| 726 min_size)); |
724 } | 727 } |
725 return scoped_ptr<SHMBuffer>(ret); | 728 return scoped_ptr<SHMBuffer>(ret); |
726 } | 729 } |
727 | 730 |
728 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { | 731 void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<SHMBuffer> shm_buffer) { |
729 available_shm_segments_.push_back(shm_buffer.release()); | 732 available_shm_segments_.push_back(shm_buffer.release()); |
730 } | 733 } |
731 | 734 |
732 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { | 735 void RTCVideoDecoder::CreateSHM(int number, size_t min_size) { |
733 DCHECK(vda_task_runner_->BelongsToCurrentThread()); | 736 DCHECK(vda_task_runner_->BelongsToCurrentThread()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 | 787 |
785 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { | 788 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { |
786 // Logging boolean is enough to know if HW decoding has been used. Also, | 789 // Logging boolean is enough to know if HW decoding has been used. Also, |
787 // InitDecode is less likely to return an error so enum is not used here. | 790 // InitDecode is less likely to return an error so enum is not used here. |
788 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; | 791 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; |
789 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); | 792 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); |
790 return status; | 793 return status; |
791 } | 794 } |
792 | 795 |
793 } // namespace content | 796 } // namespace content |
OLD | NEW |