| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_recorder/video_track_recorder.h" | 5 #include "content/renderer/media_recorder/video_track_recorder.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 // Shared memory buffers for output with the VEA as FIFO. | 454 // Shared memory buffers for output with the VEA as FIFO. |
| 455 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_; | 455 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_; |
| 456 | 456 |
| 457 // Tracks error status. | 457 // Tracks error status. |
| 458 bool error_notified_; | 458 bool error_notified_; |
| 459 | 459 |
| 460 // Tracks the last frame that we delay the encode. | 460 // Tracks the last frame that we delay the encode. |
| 461 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; | 461 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; |
| 462 | 462 |
| 463 // Size used to initialize encoder. | 463 // Size used to initialize encoder. |
| 464 gfx::Size input_size_; | 464 gfx::Size input_visible_size_; |
| 465 | 465 |
| 466 // Coded size that encoder requests as input. | 466 // Coded size that encoder requests as input. |
| 467 gfx::Size vea_requested_input_size_; | 467 gfx::Size vea_requested_input_coded_size_; |
| 468 | 468 |
| 469 // Frames and corresponding timestamps in encode as FIFO. | 469 // Frames and corresponding timestamps in encode as FIFO. |
| 470 std::queue<VideoParamsAndTimestamp> frames_in_encode_; | 470 std::queue<VideoParamsAndTimestamp> frames_in_encode_; |
| 471 }; | 471 }; |
| 472 | 472 |
| 473 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. | 473 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. |
| 474 class VpxEncoder final : public VideoTrackRecorder::Encoder { | 474 class VpxEncoder final : public VideoTrackRecorder::Encoder { |
| 475 public: | 475 public: |
| 476 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, | 476 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
| 477 ScopedVpxCodecCtxPtr encoder); | 477 ScopedVpxCodecCtxPtr encoder); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 base::Unretained(this), &release_waiter)); | 592 base::Unretained(this), &release_waiter)); |
| 593 release_waiter.Wait(); | 593 release_waiter.Wait(); |
| 594 } | 594 } |
| 595 | 595 |
| 596 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/, | 596 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/, |
| 597 const gfx::Size& input_coded_size, | 597 const gfx::Size& input_coded_size, |
| 598 size_t output_buffer_size) { | 598 size_t output_buffer_size) { |
| 599 DVLOG(3) << __func__; | 599 DVLOG(3) << __func__; |
| 600 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 600 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 601 | 601 |
| 602 vea_requested_input_size_ = input_coded_size; | 602 vea_requested_input_coded_size_ = input_coded_size; |
| 603 output_buffers_.clear(); | 603 output_buffers_.clear(); |
| 604 std::queue<std::unique_ptr<base::SharedMemory>>().swap(input_buffers_); | 604 std::queue<std::unique_ptr<base::SharedMemory>>().swap(input_buffers_); |
| 605 | 605 |
| 606 for (int i = 0; i < kVEAEncoderOutputBufferCount; ++i) { | 606 for (int i = 0; i < kVEAEncoderOutputBufferCount; ++i) { |
| 607 std::unique_ptr<base::SharedMemory> shm = | 607 std::unique_ptr<base::SharedMemory> shm = |
| 608 gpu_factories_->CreateSharedMemory(output_buffer_size); | 608 gpu_factories_->CreateSharedMemory(output_buffer_size); |
| 609 if (shm) | 609 if (shm) |
| 610 output_buffers_.push_back(base::WrapUnique(shm.release())); | 610 output_buffers_.push_back(base::WrapUnique(shm.release())); |
| 611 } | 611 } |
| 612 | 612 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 658 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 659 input_buffers_.push(std::move(shm)); | 659 input_buffers_.push(std::move(shm)); |
| 660 } | 660 } |
| 661 | 661 |
| 662 void VEAEncoder::EncodeOnEncodingTaskRunner( | 662 void VEAEncoder::EncodeOnEncodingTaskRunner( |
| 663 scoped_refptr<VideoFrame> frame, | 663 scoped_refptr<VideoFrame> frame, |
| 664 base::TimeTicks capture_timestamp) { | 664 base::TimeTicks capture_timestamp) { |
| 665 DVLOG(3) << __func__; | 665 DVLOG(3) << __func__; |
| 666 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 666 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 667 | 667 |
| 668 if (input_size_ != frame->visible_rect().size() && video_encoder_) | 668 if (input_visible_size_ != frame->visible_rect().size() && video_encoder_) |
| 669 video_encoder_.reset(); | 669 video_encoder_.reset(); |
| 670 | 670 |
| 671 if (!video_encoder_) | 671 if (!video_encoder_) |
| 672 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); | 672 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); |
| 673 | 673 |
| 674 if (error_notified_) { | 674 if (error_notified_) { |
| 675 DVLOG(3) << "An error occurred in VEA encoder"; | 675 DVLOG(3) << "An error occurred in VEA encoder"; |
| 676 return; | 676 return; |
| 677 } | 677 } |
| 678 | 678 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 692 EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second); | 692 EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second); |
| 693 } | 693 } |
| 694 | 694 |
| 695 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. | 695 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. |
| 696 // In that case, the encoder expects more frames before returning result. | 696 // In that case, the encoder expects more frames before returning result. |
| 697 // Therefore, a copy is necessary to release the current frame. | 697 // Therefore, a copy is necessary to release the current frame. |
| 698 // Only STORAGE_SHMEM backed frames can be shared with GPU process, therefore | 698 // Only STORAGE_SHMEM backed frames can be shared with GPU process, therefore |
| 699 // a copy is required for other storage types. | 699 // a copy is required for other storage types. |
| 700 scoped_refptr<media::VideoFrame> video_frame = frame; | 700 scoped_refptr<media::VideoFrame> video_frame = frame; |
| 701 if (video_frame->storage_type() != VideoFrame::STORAGE_SHMEM || | 701 if (video_frame->storage_type() != VideoFrame::STORAGE_SHMEM || |
| 702 vea_requested_input_size_ != input_size_ || | 702 vea_requested_input_coded_size_ != frame->coded_size() || |
| 703 input_size_.width() < kVEAEncoderMinResolutionWidth || | 703 input_visible_size_.width() < kVEAEncoderMinResolutionWidth || |
| 704 input_size_.height() < kVEAEncoderMinResolutionHeight) { | 704 input_visible_size_.height() < kVEAEncoderMinResolutionHeight) { |
| 705 // Create SharedMemory backed input buffers as necessary. These SharedMemory | 705 // Create SharedMemory backed input buffers as necessary. These SharedMemory |
| 706 // instances will be shared with GPU process. | 706 // instances will be shared with GPU process. |
| 707 std::unique_ptr<base::SharedMemory> input_buffer; | 707 std::unique_ptr<base::SharedMemory> input_buffer; |
| 708 const size_t desired_mapped_size = media::VideoFrame::AllocationSize( | 708 const size_t desired_mapped_size = media::VideoFrame::AllocationSize( |
| 709 media::PIXEL_FORMAT_I420, vea_requested_input_size_); | 709 media::PIXEL_FORMAT_I420, vea_requested_input_coded_size_); |
| 710 if (input_buffers_.empty()) { | 710 if (input_buffers_.empty()) { |
| 711 input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size); | 711 input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size); |
| 712 } else { | 712 } else { |
| 713 do { | 713 do { |
| 714 input_buffer = std::move(input_buffers_.front()); | 714 input_buffer = std::move(input_buffers_.front()); |
| 715 input_buffers_.pop(); | 715 input_buffers_.pop(); |
| 716 } while (!input_buffers_.empty() && | 716 } while (!input_buffers_.empty() && |
| 717 input_buffer->mapped_size() < desired_mapped_size); | 717 input_buffer->mapped_size() < desired_mapped_size); |
| 718 if (!input_buffer || input_buffer->mapped_size() < desired_mapped_size) | 718 if (!input_buffer || input_buffer->mapped_size() < desired_mapped_size) |
| 719 return; | 719 return; |
| 720 } | 720 } |
| 721 | 721 |
| 722 video_frame = media::VideoFrame::WrapExternalSharedMemory( | 722 video_frame = media::VideoFrame::WrapExternalSharedMemory( |
| 723 media::PIXEL_FORMAT_I420, vea_requested_input_size_, | 723 media::PIXEL_FORMAT_I420, vea_requested_input_coded_size_, |
| 724 gfx::Rect(input_size_), input_size_, | 724 gfx::Rect(input_visible_size_), input_visible_size_, |
| 725 reinterpret_cast<uint8_t*>(input_buffer->memory()), | 725 reinterpret_cast<uint8_t*>(input_buffer->memory()), |
| 726 input_buffer->mapped_size(), input_buffer->handle(), 0, | 726 input_buffer->mapped_size(), input_buffer->handle(), 0, |
| 727 frame->timestamp()); | 727 frame->timestamp()); |
| 728 video_frame->AddDestructionObserver(media::BindToCurrentLoop( | 728 video_frame->AddDestructionObserver(media::BindToCurrentLoop( |
| 729 base::Bind(&VEAEncoder::FrameFinished, this, | 729 base::Bind(&VEAEncoder::FrameFinished, this, |
| 730 base::Passed(std::move(input_buffer))))); | 730 base::Passed(std::move(input_buffer))))); |
| 731 libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane), | 731 libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane), |
| 732 frame->stride(media::VideoFrame::kYPlane), | 732 frame->stride(media::VideoFrame::kYPlane), |
| 733 frame->visible_data(media::VideoFrame::kUPlane), | 733 frame->visible_data(media::VideoFrame::kUPlane), |
| 734 frame->stride(media::VideoFrame::kUPlane), | 734 frame->stride(media::VideoFrame::kUPlane), |
| 735 frame->visible_data(media::VideoFrame::kVPlane), | 735 frame->visible_data(media::VideoFrame::kVPlane), |
| 736 frame->stride(media::VideoFrame::kVPlane), | 736 frame->stride(media::VideoFrame::kVPlane), |
| 737 video_frame->visible_data(media::VideoFrame::kYPlane), | 737 video_frame->visible_data(media::VideoFrame::kYPlane), |
| 738 video_frame->stride(media::VideoFrame::kYPlane), | 738 video_frame->stride(media::VideoFrame::kYPlane), |
| 739 video_frame->visible_data(media::VideoFrame::kUPlane), | 739 video_frame->visible_data(media::VideoFrame::kUPlane), |
| 740 video_frame->stride(media::VideoFrame::kUPlane), | 740 video_frame->stride(media::VideoFrame::kUPlane), |
| 741 video_frame->visible_data(media::VideoFrame::kVPlane), | 741 video_frame->visible_data(media::VideoFrame::kVPlane), |
| 742 video_frame->stride(media::VideoFrame::kVPlane), | 742 video_frame->stride(media::VideoFrame::kVPlane), |
| 743 input_size_.width(), input_size_.height()); | 743 input_visible_size_.width(), input_visible_size_.height()); |
| 744 } | 744 } |
| 745 frames_in_encode_.push(std::make_pair( | 745 frames_in_encode_.push(std::make_pair( |
| 746 media::WebmMuxer::VideoParameters(frame), capture_timestamp)); | 746 media::WebmMuxer::VideoParameters(frame), capture_timestamp)); |
| 747 | 747 |
| 748 video_encoder_->Encode(video_frame, false); | 748 video_encoder_->Encode(video_frame, false); |
| 749 } | 749 } |
| 750 | 750 |
| 751 void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) { | 751 void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) { |
| 752 DVLOG(3) << __func__; | 752 DVLOG(3) << __func__; |
| 753 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 753 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 754 DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread()); | 754 DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 755 DCHECK_GT(bits_per_second_, 0); | 755 DCHECK_GT(bits_per_second_, 0); |
| 756 | 756 |
| 757 input_size_ = size; | 757 input_visible_size_ = size; |
| 758 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator(); | 758 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator(); |
| 759 if (!video_encoder_ || | 759 if (!video_encoder_ || |
| 760 !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_size_, codec_, | 760 !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_visible_size_, |
| 761 bits_per_second_, this)) { | 761 codec_, bits_per_second_, this)) { |
| 762 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 762 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
| 763 } | 763 } |
| 764 } | 764 } |
| 765 | 765 |
| 766 void VEAEncoder::DestroyOnEncodingTaskRunner( | 766 void VEAEncoder::DestroyOnEncodingTaskRunner( |
| 767 base::WaitableEvent* async_waiter) { | 767 base::WaitableEvent* async_waiter) { |
| 768 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 768 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 769 video_encoder_.reset(); | 769 video_encoder_.reset(); |
| 770 async_waiter->Signal(); | 770 async_waiter->Signal(); |
| 771 } | 771 } |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 encoder_->SetPaused(paused_before_init_); | 1235 encoder_->SetPaused(paused_before_init_); |
| 1236 | 1236 |
| 1237 // StartFrameEncode() will be called on Render IO thread. | 1237 // StartFrameEncode() will be called on Render IO thread. |
| 1238 MediaStreamVideoSink::ConnectToTrack( | 1238 MediaStreamVideoSink::ConnectToTrack( |
| 1239 track_, | 1239 track_, |
| 1240 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), | 1240 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| 1241 false); | 1241 false); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 } // namespace content | 1244 } // namespace content |
| OLD | NEW |