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/safe_numerics.h" | 12 #include "base/safe_numerics.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/task_runner_util.h" | 14 #include "base/task_runner_util.h" |
14 #include "content/child/child_thread.h" | 15 #include "content/child/child_thread.h" |
15 #include "content/renderer/media/native_handle_impl.h" | 16 #include "content/renderer/media/native_handle_impl.h" |
16 #include "media/base/bind_to_loop.h" | 17 #include "media/base/bind_to_loop.h" |
17 #include "media/filters/gpu_video_accelerator_factories.h" | 18 #include "media/filters/gpu_video_accelerator_factories.h" |
18 #include "third_party/webrtc/common_video/interface/texture_video_frame.h" | 19 #include "third_party/webrtc/common_video/interface/texture_video_frame.h" |
19 #include "third_party/webrtc/system_wrappers/interface/ref_count.h" | 20 #include "third_party/webrtc/system_wrappers/interface/ref_count.h" |
20 | 21 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 } | 149 } |
149 return decoder.Pass(); | 150 return decoder.Pass(); |
150 } | 151 } |
151 | 152 |
152 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, | 153 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, |
153 int32_t /*numberOfCores*/) { | 154 int32_t /*numberOfCores*/) { |
154 DVLOG(2) << "InitDecode"; | 155 DVLOG(2) << "InitDecode"; |
155 DCHECK_EQ(codecSettings->codecType, webrtc::kVideoCodecVP8); | 156 DCHECK_EQ(codecSettings->codecType, webrtc::kVideoCodecVP8); |
156 if (codecSettings->codecSpecific.VP8.feedbackModeOn) { | 157 if (codecSettings->codecSpecific.VP8.feedbackModeOn) { |
157 LOG(ERROR) << "Feedback mode not supported"; | 158 LOG(ERROR) << "Feedback mode not supported"; |
158 return WEBRTC_VIDEO_CODEC_ERROR; | 159 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_ERROR); |
159 } | 160 } |
160 | 161 |
161 base::AutoLock auto_lock(lock_); | 162 base::AutoLock auto_lock(lock_); |
162 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { | 163 if (state_ == UNINITIALIZED || state_ == DECODE_ERROR) { |
163 LOG(ERROR) << "VDA is not initialized. state=" << state_; | 164 LOG(ERROR) << "VDA is not initialized. state=" << state_; |
164 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 165 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
165 } | 166 } |
166 // Create some shared memory if the queue is empty. | 167 // Create some shared memory if the queue is empty. |
167 if (available_shm_segments_.size() == 0) { | 168 if (available_shm_segments_.size() == 0) { |
168 vda_loop_proxy_->PostTask(FROM_HERE, | 169 vda_loop_proxy_->PostTask(FROM_HERE, |
169 base::Bind(&RTCVideoDecoder::CreateSHM, | 170 base::Bind(&RTCVideoDecoder::CreateSHM, |
170 weak_this_, | 171 weak_this_, |
171 kMaxInFlightDecodes, | 172 kMaxInFlightDecodes, |
172 kSharedMemorySegmentBytes)); | 173 kSharedMemorySegmentBytes)); |
173 } | 174 } |
174 return WEBRTC_VIDEO_CODEC_OK; | 175 return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_OK); |
175 } | 176 } |
176 | 177 |
177 int32_t RTCVideoDecoder::Decode( | 178 int32_t RTCVideoDecoder::Decode( |
178 const webrtc::EncodedImage& inputImage, | 179 const webrtc::EncodedImage& inputImage, |
179 bool missingFrames, | 180 bool missingFrames, |
180 const webrtc::RTPFragmentationHeader* /*fragmentation*/, | 181 const webrtc::RTPFragmentationHeader* /*fragmentation*/, |
181 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/, | 182 const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/, |
182 int64_t /*renderTimeMs*/) { | 183 int64_t /*renderTimeMs*/) { |
183 DVLOG(3) << "Decode"; | 184 DVLOG(3) << "Decode"; |
184 | 185 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 // Send the pending buffers for decoding. | 455 // Send the pending buffers for decoding. |
455 RequestBufferDecode(); | 456 RequestBufferDecode(); |
456 } | 457 } |
457 | 458 |
458 void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 459 void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
459 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 460 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
460 if (!vda_) | 461 if (!vda_) |
461 return; | 462 return; |
462 | 463 |
463 LOG(ERROR) << "VDA Error:" << error; | 464 LOG(ERROR) << "VDA Error:" << error; |
| 465 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", |
| 466 error, |
| 467 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); |
464 DestroyVDA(); | 468 DestroyVDA(); |
465 | 469 |
466 base::AutoLock auto_lock(lock_); | 470 base::AutoLock auto_lock(lock_); |
467 state_ = DECODE_ERROR; | 471 state_ = DECODE_ERROR; |
468 } | 472 } |
469 | 473 |
470 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { | 474 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() { |
471 DVLOG(2) << "WillDestroyCurrentMessageLoop"; | 475 DVLOG(2) << "WillDestroyCurrentMessageLoop"; |
472 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 476 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
473 factories_->Abort(); | 477 factories_->Abort(); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 if (it->bitstream_buffer_id != bitstream_buffer_id) | 744 if (it->bitstream_buffer_id != bitstream_buffer_id) |
741 continue; | 745 continue; |
742 *timestamp = it->timestamp; | 746 *timestamp = it->timestamp; |
743 *width = it->width; | 747 *width = it->width; |
744 *height = it->height; | 748 *height = it->height; |
745 return; | 749 return; |
746 } | 750 } |
747 NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id; | 751 NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id; |
748 } | 752 } |
749 | 753 |
| 754 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { |
| 755 // Logging boolean is enough to know if HW decoding has been used. Also, |
| 756 // InitDecode is less likely to return an error so enum is not used here. |
| 757 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; |
| 758 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample); |
| 759 return status; |
| 760 } |
| 761 |
750 } // namespace content | 762 } // namespace content |
OLD | NEW |