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 |