| 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 <memory> |
| 10 #include <vector> |
| 11 |
| 9 #include "base/bind.h" | 12 #include "base/bind.h" |
| 10 #include "base/location.h" | 13 #include "base/location.h" |
| 11 #include "base/logging.h" | 14 #include "base/logging.h" |
| 12 #include "base/macros.h" | 15 #include "base/macros.h" |
| 13 #include "base/memory/scoped_vector.h" | |
| 14 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/numerics/safe_conversions.h" | 17 #include "base/numerics/safe_conversions.h" |
| 16 #include "base/rand_util.h" | 18 #include "base/rand_util.h" |
| 17 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 18 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 19 #include "base/synchronization/waitable_event.h" | 21 #include "base/synchronization/waitable_event.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "media/base/bind_to_current_loop.h" | 23 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/bitstream_buffer.h" | 24 #include "media/base/bitstream_buffer.h" |
| 23 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 const webrtc::VideoFrame* input_next_frame_; | 217 const webrtc::VideoFrame* input_next_frame_; |
| 216 | 218 |
| 217 // Whether to encode a keyframe next. | 219 // Whether to encode a keyframe next. |
| 218 bool input_next_frame_keyframe_; | 220 bool input_next_frame_keyframe_; |
| 219 | 221 |
| 220 // Frame sizes. | 222 // Frame sizes. |
| 221 gfx::Size input_frame_coded_size_; | 223 gfx::Size input_frame_coded_size_; |
| 222 gfx::Size input_visible_size_; | 224 gfx::Size input_visible_size_; |
| 223 | 225 |
| 224 // Shared memory buffers for input/output with the VEA. | 226 // Shared memory buffers for input/output with the VEA. |
| 225 ScopedVector<base::SharedMemory> input_buffers_; | 227 std::vector<std::unique_ptr<base::SharedMemory>> input_buffers_; |
| 226 ScopedVector<base::SharedMemory> output_buffers_; | 228 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_; |
| 227 | 229 |
| 228 // Input buffers ready to be filled with input from Encode(). As a LIFO since | 230 // Input buffers ready to be filled with input from Encode(). As a LIFO since |
| 229 // we don't care about ordering. | 231 // we don't care about ordering. |
| 230 std::vector<int> input_buffers_free_; | 232 std::vector<int> input_buffers_free_; |
| 231 | 233 |
| 232 // The number of output buffers ready to be filled with output from the | 234 // The number of output buffers ready to be filled with output from the |
| 233 // encoder. | 235 // encoder. |
| 234 int output_buffers_free_count_; | 236 int output_buffers_free_count_; |
| 235 | 237 |
| 236 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. | 238 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 | 421 |
| 420 for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) { | 422 for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) { |
| 421 std::unique_ptr<base::SharedMemory> shm = | 423 std::unique_ptr<base::SharedMemory> shm = |
| 422 gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize( | 424 gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize( |
| 423 media::PIXEL_FORMAT_I420, input_coded_size)); | 425 media::PIXEL_FORMAT_I420, input_coded_size)); |
| 424 if (!shm) { | 426 if (!shm) { |
| 425 LogAndNotifyError(FROM_HERE, "failed to create input buffer ", | 427 LogAndNotifyError(FROM_HERE, "failed to create input buffer ", |
| 426 media::VideoEncodeAccelerator::kPlatformFailureError); | 428 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 427 return; | 429 return; |
| 428 } | 430 } |
| 429 input_buffers_.push_back(shm.release()); | 431 input_buffers_.push_back(std::move(shm)); |
| 430 input_buffers_free_.push_back(i); | 432 input_buffers_free_.push_back(i); |
| 431 } | 433 } |
| 432 | 434 |
| 433 for (int i = 0; i < kOutputBufferCount; ++i) { | 435 for (int i = 0; i < kOutputBufferCount; ++i) { |
| 434 std::unique_ptr<base::SharedMemory> shm = | 436 std::unique_ptr<base::SharedMemory> shm = |
| 435 gpu_factories_->CreateSharedMemory(output_buffer_size); | 437 gpu_factories_->CreateSharedMemory(output_buffer_size); |
| 436 if (!shm) { | 438 if (!shm) { |
| 437 LogAndNotifyError(FROM_HERE, "failed to create output buffer", | 439 LogAndNotifyError(FROM_HERE, "failed to create output buffer", |
| 438 media::VideoEncodeAccelerator::kPlatformFailureError); | 440 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 439 return; | 441 return; |
| 440 } | 442 } |
| 441 output_buffers_.push_back(shm.release()); | 443 output_buffers_.push_back(std::move(shm)); |
| 442 } | 444 } |
| 443 | 445 |
| 444 // Immediately provide all output buffers to the VEA. | 446 // Immediately provide all output buffers to the VEA. |
| 445 for (size_t i = 0; i < output_buffers_.size(); ++i) { | 447 for (size_t i = 0; i < output_buffers_.size(); ++i) { |
| 446 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( | 448 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( |
| 447 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size())); | 449 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size())); |
| 448 output_buffers_free_count_++; | 450 output_buffers_free_count_++; |
| 449 } | 451 } |
| 450 DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED); | 452 DCHECK_EQ(GetStatus(), WEBRTC_VIDEO_CODEC_UNINITIALIZED); |
| 451 SetStatus(WEBRTC_VIDEO_CODEC_OK); | 453 SetStatus(WEBRTC_VIDEO_CODEC_OK); |
| 452 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); | 454 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); |
| 453 } | 455 } |
| 454 | 456 |
| 455 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, | 457 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 456 size_t payload_size, | 458 size_t payload_size, |
| 457 bool key_frame, | 459 bool key_frame, |
| 458 base::TimeDelta timestamp) { | 460 base::TimeDelta timestamp) { |
| 459 DVLOG(3) << "Impl::BitstreamBufferReady(): bitstream_buffer_id=" | 461 DVLOG(3) << "Impl::BitstreamBufferReady(): bitstream_buffer_id=" |
| 460 << bitstream_buffer_id << ", payload_size=" << payload_size | 462 << bitstream_buffer_id << ", payload_size=" << payload_size |
| 461 << ", key_frame=" << key_frame | 463 << ", key_frame=" << key_frame |
| 462 << ", timestamp ms=" << timestamp.InMilliseconds(); | 464 << ", timestamp ms=" << timestamp.InMilliseconds(); |
| 463 DCHECK(thread_checker_.CalledOnValidThread()); | 465 DCHECK(thread_checker_.CalledOnValidThread()); |
| 464 | 466 |
| 465 if (bitstream_buffer_id < 0 || | 467 if (bitstream_buffer_id < 0 || |
| 466 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) { | 468 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) { |
| 467 LogAndNotifyError(FROM_HERE, "invalid bitstream_buffer_id", | 469 LogAndNotifyError(FROM_HERE, "invalid bitstream_buffer_id", |
| 468 media::VideoEncodeAccelerator::kPlatformFailureError); | 470 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 469 return; | 471 return; |
| 470 } | 472 } |
| 471 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 473 base::SharedMemory* output_buffer = |
| 474 output_buffers_[bitstream_buffer_id].get(); |
| 472 if (payload_size > output_buffer->mapped_size()) { | 475 if (payload_size > output_buffer->mapped_size()) { |
| 473 LogAndNotifyError(FROM_HERE, "invalid payload_size", | 476 LogAndNotifyError(FROM_HERE, "invalid payload_size", |
| 474 media::VideoEncodeAccelerator::kPlatformFailureError); | 477 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 475 return; | 478 return; |
| 476 } | 479 } |
| 477 output_buffers_free_count_--; | 480 output_buffers_free_count_--; |
| 478 | 481 |
| 479 // Derive the capture time in ms from system clock. Make sure that it is | 482 // Derive the capture time in ms from system clock. Make sure that it is |
| 480 // greater than the last. | 483 // greater than the last. |
| 481 const int64_t capture_time_us = rtc::TimeMicros(); | 484 const int64_t capture_time_us = rtc::TimeMicros(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 requires_copy = RequiresSizeChange(frame) || | 575 requires_copy = RequiresSizeChange(frame) || |
| 573 frame->storage_type() != media::VideoFrame::STORAGE_SHMEM; | 576 frame->storage_type() != media::VideoFrame::STORAGE_SHMEM; |
| 574 } else { | 577 } else { |
| 575 requires_copy = true; | 578 requires_copy = true; |
| 576 } | 579 } |
| 577 | 580 |
| 578 if (requires_copy) { | 581 if (requires_copy) { |
| 579 const base::TimeDelta timestamp = | 582 const base::TimeDelta timestamp = |
| 580 frame ? frame->timestamp() | 583 frame ? frame->timestamp() |
| 581 : base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms()); | 584 : base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms()); |
| 582 base::SharedMemory* input_buffer = input_buffers_[index]; | 585 base::SharedMemory* input_buffer = input_buffers_[index].get(); |
| 583 frame = media::VideoFrame::WrapExternalSharedMemory( | 586 frame = media::VideoFrame::WrapExternalSharedMemory( |
| 584 media::PIXEL_FORMAT_I420, input_frame_coded_size_, | 587 media::PIXEL_FORMAT_I420, input_frame_coded_size_, |
| 585 gfx::Rect(input_visible_size_), input_visible_size_, | 588 gfx::Rect(input_visible_size_), input_visible_size_, |
| 586 reinterpret_cast<uint8_t*>(input_buffer->memory()), | 589 reinterpret_cast<uint8_t*>(input_buffer->memory()), |
| 587 input_buffer->mapped_size(), input_buffer->handle(), 0, timestamp); | 590 input_buffer->mapped_size(), input_buffer->handle(), 0, timestamp); |
| 588 if (!frame.get()) { | 591 if (!frame.get()) { |
| 589 LogAndNotifyError(FROM_HERE, "failed to create frame", | 592 LogAndNotifyError(FROM_HERE, "failed to create frame", |
| 590 media::VideoEncodeAccelerator::kPlatformFailureError); | 593 media::VideoEncodeAccelerator::kPlatformFailureError); |
| 591 return; | 594 return; |
| 592 } | 595 } |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 891 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
| 889 init_retval == WEBRTC_VIDEO_CODEC_OK); | 892 init_retval == WEBRTC_VIDEO_CODEC_OK); |
| 890 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 893 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
| 891 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 894 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
| 892 profile, | 895 profile, |
| 893 media::VIDEO_CODEC_PROFILE_MAX + 1); | 896 media::VIDEO_CODEC_PROFILE_MAX + 1); |
| 894 } | 897 } |
| 895 } | 898 } |
| 896 | 899 |
| 897 } // namespace content | 900 } // namespace content |
| OLD | NEW |