Chromium Code Reviews| 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 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; | |
|
Alexei Svitkine (slow)
2013/09/13 14:53:25
Why not log the actual status as an enum rather th
wuchengli
2013/09/14 01:40:17
Success case is more important than error. Most of
Alexei Svitkine (slow)
2013/09/14 02:37:27
Okay, that sounds reasonable. Might be worth addin
| |
| 756 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample); | |
| 757 return status; | |
| 758 } | |
| 759 | |
| 750 } // namespace content | 760 } // namespace content |
| OLD | NEW |