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 |