| 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/gpu/rtc_video_encoder.h" | 5 #include "content/renderer/media/gpu/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 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 // we don't care about ordering. | 229 // we don't care about ordering. |
| 230 std::vector<int> input_buffers_free_; | 230 std::vector<int> input_buffers_free_; |
| 231 | 231 |
| 232 // The number of output buffers ready to be filled with output from the | 232 // The number of output buffers ready to be filled with output from the |
| 233 // encoder. | 233 // encoder. |
| 234 int output_buffers_free_count_; | 234 int output_buffers_free_count_; |
| 235 | 235 |
| 236 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. | 236 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. |
| 237 uint16_t picture_id_; | 237 uint16_t picture_id_; |
| 238 | 238 |
| 239 // |capture_time_ms_| field of the last returned webrtc::EncodedImage from |
| 240 // BitstreamBufferReady(). |
| 241 int64_t last_capture_time_ms_; |
| 242 |
| 239 // webrtc::VideoEncoder encode complete callback. | 243 // webrtc::VideoEncoder encode complete callback. |
| 240 webrtc::EncodedImageCallback* encoded_image_callback_; | 244 webrtc::EncodedImageCallback* encoded_image_callback_; |
| 241 | 245 |
| 242 // The video codec type, as reported to WebRTC. | 246 // The video codec type, as reported to WebRTC. |
| 243 const webrtc::VideoCodecType video_codec_type_; | 247 const webrtc::VideoCodecType video_codec_type_; |
| 244 | 248 |
| 245 // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in | 249 // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in |
| 246 // Impl. It can be read in RTCVideoEncoder on other threads. | 250 // Impl. It can be read in RTCVideoEncoder on other threads. |
| 247 mutable base::Lock status_lock_; | 251 mutable base::Lock status_lock_; |
| 248 | 252 |
| 249 // We cannot immediately return error conditions to the WebRTC user of this | 253 // We cannot immediately return error conditions to the WebRTC user of this |
| 250 // class, as there is no error callback in the webrtc::VideoEncoder interface. | 254 // class, as there is no error callback in the webrtc::VideoEncoder interface. |
| 251 // Instead, we cache an error status here and return it the next time an | 255 // Instead, we cache an error status here and return it the next time an |
| 252 // interface entry point is called. This is protected by |status_lock_|. | 256 // interface entry point is called. This is protected by |status_lock_|. |
| 253 int32_t status_; | 257 int32_t status_; |
| 254 | 258 |
| 255 DISALLOW_COPY_AND_ASSIGN(Impl); | 259 DISALLOW_COPY_AND_ASSIGN(Impl); |
| 256 }; | 260 }; |
| 257 | 261 |
| 258 RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, | 262 RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, |
| 259 webrtc::VideoCodecType video_codec_type) | 263 webrtc::VideoCodecType video_codec_type) |
| 260 : gpu_factories_(gpu_factories), | 264 : gpu_factories_(gpu_factories), |
| 261 async_waiter_(NULL), | 265 async_waiter_(NULL), |
| 262 async_retval_(NULL), | 266 async_retval_(NULL), |
| 263 input_next_frame_(NULL), | 267 input_next_frame_(NULL), |
| 264 input_next_frame_keyframe_(false), | 268 input_next_frame_keyframe_(false), |
| 265 output_buffers_free_count_(0), | 269 output_buffers_free_count_(0), |
| 270 last_capture_time_ms_(-1), |
| 266 encoded_image_callback_(nullptr), | 271 encoded_image_callback_(nullptr), |
| 267 video_codec_type_(video_codec_type), | 272 video_codec_type_(video_codec_type), |
| 268 status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) { | 273 status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) { |
| 269 thread_checker_.DetachFromThread(); | 274 thread_checker_.DetachFromThread(); |
| 270 // Picture ID should start on a random number. | 275 // Picture ID should start on a random number. |
| 271 picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); | 276 picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); |
| 272 } | 277 } |
| 273 | 278 |
| 274 void RTCVideoEncoder::Impl::CreateAndInitializeVEA( | 279 void RTCVideoEncoder::Impl::CreateAndInitializeVEA( |
| 275 const gfx::Size& input_visible_size, | 280 const gfx::Size& input_visible_size, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 return; | 469 return; |
| 465 } | 470 } |
| 466 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 471 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; |
| 467 if (payload_size > output_buffer->mapped_size()) { | 472 if (payload_size > output_buffer->mapped_size()) { |
| 468 LogAndNotifyError(FROM_HERE, "invalid payload_size", | 473 LogAndNotifyError(FROM_HERE, "invalid payload_size", |
| 469 media::VideoEncodeAccelerator::kPlatformFailureError); | 474 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 470 return; | 475 return; |
| 471 } | 476 } |
| 472 output_buffers_free_count_--; | 477 output_buffers_free_count_--; |
| 473 | 478 |
| 474 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). | 479 // Derive the capture time in ms from system clock. Make sure that it is |
| 475 int64_t capture_time_us, capture_time_ms; | 480 // greater than the last. |
| 476 uint32_t rtp_timestamp; | 481 const int64_t capture_time_us = rtc::TimeMicros(); |
| 482 int64_t capture_time_ms = |
| 483 capture_time_us / base::Time::kMicrosecondsPerMillisecond; |
| 484 capture_time_ms = std::max(capture_time_ms, last_capture_time_ms_ + 1); |
| 485 last_capture_time_ms_ = capture_time_ms; |
| 477 | 486 |
| 478 if (!timestamp.is_zero()) { | 487 // Fallback to the current time if encoder does not provide timestamp. |
| 479 capture_time_us = timestamp.InMicroseconds();; | 488 const int64_t encoder_time_us = |
| 480 capture_time_ms = timestamp.InMilliseconds(); | 489 timestamp.is_zero() ? capture_time_us : timestamp.InMicroseconds(); |
| 481 } else { | 490 |
| 482 // Fallback to the current time if encoder does not provide timestamp. | 491 // Derive the RTP timestamp (in 90KHz ticks). It can wrap around, get the |
| 483 capture_time_us = rtc::TimeMicros(); | 492 // lower 32 bits. |
| 484 capture_time_ms = capture_time_us / base::Time::kMicrosecondsPerMillisecond; | 493 const uint32_t rtp_timestamp = static_cast<uint32_t>( |
| 485 } | 494 encoder_time_us * 90 / base::Time::kMicrosecondsPerMillisecond); |
| 486 // RTP timestamp can wrap around. Get the lower 32 bits. | |
| 487 rtp_timestamp = static_cast<uint32_t>( | |
| 488 capture_time_us * 90 / base::Time::kMicrosecondsPerMillisecond); | |
| 489 | 495 |
| 490 webrtc::EncodedImage image( | 496 webrtc::EncodedImage image( |
| 491 reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, | 497 reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, |
| 492 output_buffer->mapped_size()); | 498 output_buffer->mapped_size()); |
| 493 image._encodedWidth = input_visible_size_.width(); | 499 image._encodedWidth = input_visible_size_.width(); |
| 494 image._encodedHeight = input_visible_size_.height(); | 500 image._encodedHeight = input_visible_size_.height(); |
| 495 image._timeStamp = rtp_timestamp; | 501 image._timeStamp = rtp_timestamp; |
| 496 image.capture_time_ms_ = capture_time_ms; | 502 image.capture_time_ms_ = capture_time_ms; |
| 497 image._frameType = | 503 image._frameType = |
| 498 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 504 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 888 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
| 883 init_retval == WEBRTC_VIDEO_CODEC_OK); | 889 init_retval == WEBRTC_VIDEO_CODEC_OK); |
| 884 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 890 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
| 885 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 891 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
| 886 profile, | 892 profile, |
| 887 media::VIDEO_CODEC_PROFILE_MAX + 1); | 893 media::VIDEO_CODEC_PROFILE_MAX + 1); |
| 888 } | 894 } |
| 889 } | 895 } |
| 890 | 896 |
| 891 } // namespace content | 897 } // namespace content |
| OLD | NEW |