| 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_encoder.h" | 5 #include "content/renderer/media/rtc_video_encoder.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 int32_t GetStatus() const; | 142 int32_t GetStatus() const; |
| 143 | 143 |
| 144 webrtc::VideoCodecType video_codec_type() { return video_codec_type_; } | 144 webrtc::VideoCodecType video_codec_type() { return video_codec_type_; } |
| 145 | 145 |
| 146 // media::VideoEncodeAccelerator::Client implementation. | 146 // media::VideoEncodeAccelerator::Client implementation. |
| 147 void RequireBitstreamBuffers(unsigned int input_count, | 147 void RequireBitstreamBuffers(unsigned int input_count, |
| 148 const gfx::Size& input_coded_size, | 148 const gfx::Size& input_coded_size, |
| 149 size_t output_buffer_size) override; | 149 size_t output_buffer_size) override; |
| 150 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 150 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 151 size_t payload_size, | 151 size_t payload_size, |
| 152 bool key_frame) override; | 152 bool key_frame, |
| 153 base::TimeDelta timestamp) override; |
| 153 void NotifyError(media::VideoEncodeAccelerator::Error error) override; | 154 void NotifyError(media::VideoEncodeAccelerator::Error error) override; |
| 154 | 155 |
| 155 private: | 156 private: |
| 156 friend class base::RefCountedThreadSafe<Impl>; | 157 friend class base::RefCountedThreadSafe<Impl>; |
| 157 | 158 |
| 158 enum { | 159 enum { |
| 159 kInputBufferExtraCount = 1, // The number of input buffers allocated, more | 160 kInputBufferExtraCount = 1, // The number of input buffers allocated, more |
| 160 // than what is requested by | 161 // than what is requested by |
| 161 // VEA::RequireBitstreamBuffers(). | 162 // VEA::RequireBitstreamBuffers(). |
| 162 kOutputBufferCount = 3, | 163 kOutputBufferCount = 3, |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( | 443 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( |
| 443 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size())); | 444 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size())); |
| 444 output_buffers_free_count_++; | 445 output_buffers_free_count_++; |
| 445 } | 446 } |
| 446 DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED); | 447 DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
| 447 SetStatus(WEBRTC_VIDEO_CODEC_OK); | 448 SetStatus(WEBRTC_VIDEO_CODEC_OK); |
| 448 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); | 449 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); |
| 449 } | 450 } |
| 450 | 451 |
| 451 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, | 452 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 452 size_t payload_size, | 453 size_t payload_size, |
| 453 bool key_frame) { | 454 bool key_frame, |
| 455 base::TimeDelta timestamp) { |
| 454 DVLOG(3) << "Impl::BitstreamBufferReady(): " | 456 DVLOG(3) << "Impl::BitstreamBufferReady(): " |
| 455 "bitstream_buffer_id=" << bitstream_buffer_id | 457 "bitstream_buffer_id=" << bitstream_buffer_id |
| 456 << ", payload_size=" << payload_size | 458 << ", payload_size=" << payload_size |
| 457 << ", key_frame=" << key_frame; | 459 << ", key_frame=" << key_frame; |
| 458 DCHECK(thread_checker_.CalledOnValidThread()); | 460 DCHECK(thread_checker_.CalledOnValidThread()); |
| 459 | 461 |
| 460 if (bitstream_buffer_id < 0 || | 462 if (bitstream_buffer_id < 0 || |
| 461 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) { | 463 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) { |
| 462 LogAndNotifyError(FROM_HERE, "invalid bitstream_buffer_id", | 464 LogAndNotifyError(FROM_HERE, "invalid bitstream_buffer_id", |
| 463 media::VideoEncodeAccelerator::kPlatformFailureError); | 465 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 464 return; | 466 return; |
| 465 } | 467 } |
| 466 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 468 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; |
| 467 if (payload_size > output_buffer->mapped_size()) { | 469 if (payload_size > output_buffer->mapped_size()) { |
| 468 LogAndNotifyError(FROM_HERE, "invalid payload_size", | 470 LogAndNotifyError(FROM_HERE, "invalid payload_size", |
| 469 media::VideoEncodeAccelerator::kPlatformFailureError); | 471 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 470 return; | 472 return; |
| 471 } | 473 } |
| 472 output_buffers_free_count_--; | 474 output_buffers_free_count_--; |
| 473 | 475 |
| 474 // Use webrtc timestamps to ensure correct RTP sender behavior. | |
| 475 // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106. | |
| 476 const int64_t capture_time_us = rtc::TimeMicros(); | |
| 477 | |
| 478 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). | 476 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). |
| 479 const int64_t capture_time_ms = capture_time_us / 1000; | 477 // This is based on how input timestamps are calculated in |
| 478 // webrtc/video/video_capture_input.cc. |
| 480 const uint32_t rtp_timestamp = | 479 const uint32_t rtp_timestamp = |
| 481 static_cast<uint32_t>(capture_time_us * 90 / 1000); | 480 static_cast<uint32_t>(timestamp.InMilliseconds()) * 90; |
| 482 | 481 |
| 483 webrtc::EncodedImage image( | 482 webrtc::EncodedImage image( |
| 484 reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, | 483 reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, |
| 485 output_buffer->mapped_size()); | 484 output_buffer->mapped_size()); |
| 486 image._encodedWidth = input_visible_size_.width(); | 485 image._encodedWidth = input_visible_size_.width(); |
| 487 image._encodedHeight = input_visible_size_.height(); | 486 image._encodedHeight = input_visible_size_.height(); |
| 488 image._timeStamp = rtp_timestamp; | 487 image._timeStamp = rtp_timestamp; |
| 489 image.capture_time_ms_ = capture_time_ms; | 488 image.capture_time_ms_ = timestamp.InMilliseconds(); |
| 490 image._frameType = | 489 image._frameType = |
| 491 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 490 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
| 492 image._completeFrame = true; | 491 image._completeFrame = true; |
| 493 | 492 |
| 494 ReturnEncodedImage(image, bitstream_buffer_id, picture_id_); | 493 ReturnEncodedImage(image, bitstream_buffer_id, picture_id_); |
| 495 // Picture ID must wrap after reaching the maximum. | 494 // Picture ID must wrap after reaching the maximum. |
| 496 picture_id_ = (picture_id_ + 1) & 0x7FFF; | 495 picture_id_ = (picture_id_ + 1) & 0x7FFF; |
| 497 } | 496 } |
| 498 | 497 |
| 499 void RTCVideoEncoder::Impl::NotifyError( | 498 void RTCVideoEncoder::Impl::NotifyError( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 requires_copy = true; | 560 requires_copy = true; |
| 562 } | 561 } |
| 563 | 562 |
| 564 if (requires_copy) { | 563 if (requires_copy) { |
| 565 base::SharedMemory* input_buffer = input_buffers_[index]; | 564 base::SharedMemory* input_buffer = input_buffers_[index]; |
| 566 frame = media::VideoFrame::WrapExternalSharedMemory( | 565 frame = media::VideoFrame::WrapExternalSharedMemory( |
| 567 media::PIXEL_FORMAT_I420, input_frame_coded_size_, | 566 media::PIXEL_FORMAT_I420, input_frame_coded_size_, |
| 568 gfx::Rect(input_visible_size_), input_visible_size_, | 567 gfx::Rect(input_visible_size_), input_visible_size_, |
| 569 reinterpret_cast<uint8_t*>(input_buffer->memory()), | 568 reinterpret_cast<uint8_t*>(input_buffer->memory()), |
| 570 input_buffer->mapped_size(), input_buffer->handle(), 0, | 569 input_buffer->mapped_size(), input_buffer->handle(), 0, |
| 571 base::TimeDelta()); | 570 base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms())); |
| 572 if (!frame.get()) { | 571 if (!frame.get()) { |
| 573 LogAndNotifyError(FROM_HERE, "failed to create frame", | 572 LogAndNotifyError(FROM_HERE, "failed to create frame", |
| 574 media::VideoEncodeAccelerator::kPlatformFailureError); | 573 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 575 return; | 574 return; |
| 576 } | 575 } |
| 577 // Do a strided copy of the input frame to match the input requirements for | 576 // Do a strided copy of the input frame to match the input requirements for |
| 578 // the encoder. | 577 // the encoder. |
| 579 // TODO(sheu): support zero-copy from WebRTC. http://crbug.com/269312 | 578 // TODO(sheu): support zero-copy from WebRTC. http://crbug.com/269312 |
| 580 if (libyuv::I420Copy(next_frame->video_frame_buffer()->DataY(), | 579 if (libyuv::I420Copy(next_frame->video_frame_buffer()->DataY(), |
| 581 next_frame->video_frame_buffer()->StrideY(), | 580 next_frame->video_frame_buffer()->StrideY(), |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 854 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
| 856 init_retval == WEBRTC_VIDEO_CODEC_OK); | 855 init_retval == WEBRTC_VIDEO_CODEC_OK); |
| 857 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 856 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
| 858 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 857 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
| 859 profile, | 858 profile, |
| 860 media::VIDEO_CODEC_PROFILE_MAX + 1); | 859 media::VIDEO_CODEC_PROFILE_MAX + 1); |
| 861 } | 860 } |
| 862 } | 861 } |
| 863 | 862 |
| 864 } // namespace content | 863 } // namespace content |
| OLD | NEW |