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" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/safe_numerics.h" | 12 #include "base/safe_numerics.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/synchronization/waitable_event.h" | |
14 #include "base/task_runner_util.h" | 15 #include "base/task_runner_util.h" |
15 #include "content/child/child_thread.h" | 16 #include "content/child/child_thread.h" |
16 #include "content/renderer/media/native_handle_impl.h" | 17 #include "content/renderer/media/native_handle_impl.h" |
17 #include "media/base/bind_to_loop.h" | 18 #include "media/base/bind_to_loop.h" |
18 #include "media/filters/gpu_video_accelerator_factories.h" | 19 #include "media/filters/gpu_video_accelerator_factories.h" |
19 #include "third_party/webrtc/common_video/interface/texture_video_frame.h" | 20 #include "third_party/webrtc/common_video/interface/texture_video_frame.h" |
20 #include "third_party/webrtc/system_wrappers/interface/ref_count.h" | 21 #include "third_party/webrtc/system_wrappers/interface/ref_count.h" |
21 | 22 |
22 namespace content { | 23 namespace content { |
23 | 24 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 : weak_factory_(this), | 77 : weak_factory_(this), |
77 weak_this_(weak_factory_.GetWeakPtr()), | 78 weak_this_(weak_factory_.GetWeakPtr()), |
78 factories_(factories), | 79 factories_(factories), |
79 vda_loop_proxy_(factories->GetMessageLoop()), | 80 vda_loop_proxy_(factories->GetMessageLoop()), |
80 decoder_texture_target_(0), | 81 decoder_texture_target_(0), |
81 next_picture_buffer_id_(0), | 82 next_picture_buffer_id_(0), |
82 state_(UNINITIALIZED), | 83 state_(UNINITIALIZED), |
83 decode_complete_callback_(NULL), | 84 decode_complete_callback_(NULL), |
84 num_shm_buffers_(0), | 85 num_shm_buffers_(0), |
85 next_bitstream_buffer_id_(0), | 86 next_bitstream_buffer_id_(0), |
86 reset_bitstream_buffer_id_(ID_INVALID) { | 87 reset_bitstream_buffer_id_(ID_INVALID) {} |
87 DCHECK(!vda_loop_proxy_->BelongsToCurrentThread()); | |
88 base::WaitableEvent message_loop_async_waiter(false, false); | |
89 // Waiting here is safe. The media thread is stopped in the child thread and | |
90 // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder | |
91 // runs. | |
92 vda_loop_proxy_->PostTask(FROM_HERE, | |
93 base::Bind(&RTCVideoDecoder::Initialize, | |
94 base::Unretained(this), | |
95 &message_loop_async_waiter)); | |
96 message_loop_async_waiter.Wait(); | |
97 } | |
98 | 88 |
99 RTCVideoDecoder::~RTCVideoDecoder() { | 89 RTCVideoDecoder::~RTCVideoDecoder() { |
100 DVLOG(2) << "~RTCVideoDecoder"; | 90 DVLOG(2) << "~RTCVideoDecoder"; |
101 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 91 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
102 | 92 |
103 DestroyVDA(); | 93 DestroyVDA(); |
104 | 94 |
105 // Delete all shared memories. | 95 // Delete all shared memories. |
106 STLDeleteElements(&available_shm_segments_); | 96 STLDeleteElements(&available_shm_segments_); |
107 STLDeleteValues(&bitstream_buffers_in_decoder_); | 97 STLDeleteValues(&bitstream_buffers_in_decoder_); |
(...skipping 19 matching lines...) Expand all Loading... | |
127 media::VideoCodecProfile profile; | 117 media::VideoCodecProfile profile; |
128 switch (type) { | 118 switch (type) { |
129 case webrtc::kVideoCodecVP8: | 119 case webrtc::kVideoCodecVP8: |
130 profile = media::VP8PROFILE_MAIN; | 120 profile = media::VP8PROFILE_MAIN; |
131 break; | 121 break; |
132 default: | 122 default: |
133 DVLOG(2) << "Video codec not supported:" << type; | 123 DVLOG(2) << "Video codec not supported:" << type; |
134 return decoder.Pass(); | 124 return decoder.Pass(); |
135 } | 125 } |
136 | 126 |
127 base::WaitableEvent waiter(true, false); | |
137 decoder.reset(new RTCVideoDecoder(factories)); | 128 decoder.reset(new RTCVideoDecoder(factories)); |
138 decoder->vda_ = | 129 decoder->vda_loop_proxy_->PostTask(FROM_HERE, |
139 factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass(); | 130 base::Bind(&RTCVideoDecoder::CreateVDA, |
131 base::Unretained(decoder.get()), | |
132 profile, | |
133 &decoder->vda_, | |
134 &waiter)); | |
135 waiter.Wait(); | |
140 // vda can be NULL if VP8 is not supported. | 136 // vda can be NULL if VP8 is not supported. |
141 if (decoder->vda_ != NULL) { | 137 if (decoder->vda_ != NULL) { |
142 decoder->state_ = INITIALIZED; | 138 decoder->state_ = INITIALIZED; |
143 } else { | 139 } else { |
144 factories->GetMessageLoop()->DeleteSoon(FROM_HERE, decoder.release()); | 140 factories->GetMessageLoop()->DeleteSoon(FROM_HERE, decoder.release()); |
145 } | 141 } |
146 return decoder.Pass(); | 142 return decoder.Pass(); |
147 } | 143 } |
148 | 144 |
149 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, | 145 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 LOG(ERROR) << "VDA Error:" << error; | 455 LOG(ERROR) << "VDA Error:" << error; |
460 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", | 456 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", |
461 error, | 457 error, |
462 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); | 458 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); |
463 DestroyVDA(); | 459 DestroyVDA(); |
464 | 460 |
465 base::AutoLock auto_lock(lock_); | 461 base::AutoLock auto_lock(lock_); |
466 state_ = DECODE_ERROR; | 462 state_ = DECODE_ERROR; |
467 } | 463 } |
468 | 464 |
469 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { | |
470 DVLOG(2) << "WillDestroyCurrentMessageLoop"; | |
471 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | |
472 factories_->Abort(); | |
473 weak_factory_.InvalidateWeakPtrs(); | |
474 DestroyVDA(); | |
475 } | |
476 | |
477 void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) { | |
478 DVLOG(2) << "Initialize"; | |
479 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | |
480 base::MessageLoop::current()->AddDestructionObserver(this); | |
481 waiter->Signal(); | |
482 } | |
483 | |
484 void RTCVideoDecoder::RequestBufferDecode() { | 465 void RTCVideoDecoder::RequestBufferDecode() { |
485 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 466 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
486 if (!vda_) | 467 if (!vda_) |
487 return; | 468 return; |
488 | 469 |
489 MovePendingBuffersToDecodeBuffers(); | 470 MovePendingBuffersToDecodeBuffers(); |
490 | 471 |
491 while (CanMoreDecodeWorkBeDone()) { | 472 while (CanMoreDecodeWorkBeDone()) { |
492 // Get a buffer and data from the queue. | 473 // Get a buffer and data from the queue. |
493 SHMBuffer* shm_buffer = NULL; | 474 SHMBuffer* shm_buffer = NULL; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
633 factories_->DeleteTexture(it->second.texture_id()); | 614 factories_->DeleteTexture(it->second.texture_id()); |
634 dismissed_picture_buffers_.erase(it); | 615 dismissed_picture_buffers_.erase(it); |
635 return; | 616 return; |
636 } | 617 } |
637 | 618 |
638 factories_->WaitSyncPoint(sync_point); | 619 factories_->WaitSyncPoint(sync_point); |
639 | 620 |
640 vda_->ReusePictureBuffer(picture_buffer_id); | 621 vda_->ReusePictureBuffer(picture_buffer_id); |
641 } | 622 } |
642 | 623 |
624 void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile, | |
625 scoped_ptr<media::VideoDecodeAccelerator>* vda, | |
626 base::WaitableEvent* waiter) { | |
627 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | |
628 *vda = factories_->CreateVideoDecodeAccelerator(profile, this); | |
wuchengli
2013/10/16 07:43:17
Just use |vda_| here and remove the parameter?
sheu
2013/10/21 05:17:35
Done.
| |
629 waiter->Signal(); | |
630 } | |
631 | |
643 void RTCVideoDecoder::DestroyTextures() { | 632 void RTCVideoDecoder::DestroyTextures() { |
644 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 633 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
645 std::map<int32, media::PictureBuffer>::iterator it; | 634 std::map<int32, media::PictureBuffer>::iterator it; |
646 | 635 |
647 for (it = assigned_picture_buffers_.begin(); | 636 for (it = assigned_picture_buffers_.begin(); |
648 it != assigned_picture_buffers_.end(); | 637 it != assigned_picture_buffers_.end(); |
649 ++it) { | 638 ++it) { |
650 factories_->DeleteTexture(it->second.texture_id()); | 639 factories_->DeleteTexture(it->second.texture_id()); |
651 } | 640 } |
652 assigned_picture_buffers_.clear(); | 641 assigned_picture_buffers_.clear(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
748 | 737 |
749 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { | 738 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { |
750 // Logging boolean is enough to know if HW decoding has been used. Also, | 739 // Logging boolean is enough to know if HW decoding has been used. Also, |
751 // InitDecode is less likely to return an error so enum is not used here. | 740 // InitDecode is less likely to return an error so enum is not used here. |
752 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; | 741 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; |
753 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample); | 742 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample); |
754 return status; | 743 return status; |
755 } | 744 } |
756 | 745 |
757 } // namespace content | 746 } // namespace content |
OLD | NEW |