| 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 29 matching lines...) Expand all Loading... |
| 40 // backwards compatibility for legacy applications using the library. | 40 // backwards compatibility for legacy applications using the library. |
| 41 #define VPX_CODEC_DISABLE_COMPAT 1 | 41 #define VPX_CODEC_DISABLE_COMPAT 1 |
| 42 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" | 42 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" |
| 43 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" | 43 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" |
| 44 } | 44 } |
| 45 | 45 |
| 46 using media::VideoFrame; | 46 using media::VideoFrame; |
| 47 using media::VideoFrameMetadata; | 47 using media::VideoFrameMetadata; |
| 48 using video_track_recorder::kVEAEncoderMinResolutionWidth; | 48 using video_track_recorder::kVEAEncoderMinResolutionWidth; |
| 49 using video_track_recorder::kVEAEncoderMinResolutionHeight; | 49 using video_track_recorder::kVEAEncoderMinResolutionHeight; |
| 50 using video_track_recorder::kVEAEncoderMinResolutionWidthAndroid; |
| 51 using video_track_recorder::kVEAEncoderMinResolutionHeightAndroid; |
| 50 | 52 |
| 51 namespace content { | 53 namespace content { |
| 52 | 54 |
| 53 namespace { | 55 namespace { |
| 54 | 56 |
| 55 // HW encoders expect a nonzero bitrate, so |kVEADefaultBitratePerPixel| is used | 57 // HW encoders expect a nonzero bitrate, so |kVEADefaultBitratePerPixel| is used |
| 56 // to estimate bits per second for ~30 fps with ~1/16 compression rate. | 58 // to estimate bits per second for ~30 fps with ~1/16 compression rate. |
| 57 const int kVEADefaultBitratePerPixel = 2; | 59 const int kVEADefaultBitratePerPixel = 2; |
| 58 // Number of output buffers used to copy the encoded data coming from HW | 60 // Number of output buffers used to copy the encoded data coming from HW |
| 59 // encoders. | 61 // encoders. |
| 60 const int kVEAEncoderOutputBufferCount = 4; | 62 const int kVEAEncoderOutputBufferCount = 4; |
| 61 | 63 |
| 62 using CodecId = VideoTrackRecorder::CodecId; | 64 using CodecId = VideoTrackRecorder::CodecId; |
| 63 | 65 |
| 64 static const struct { | 66 static const struct { |
| 65 CodecId codec_id; | 67 CodecId codec_id; |
| 66 media::VideoCodecProfile min_profile; | 68 media::VideoCodecProfile min_profile; |
| 67 media::VideoCodecProfile max_profile; | 69 media::VideoCodecProfile max_profile; |
| 68 } kPreferredCodecIdAndVEAProfiles[] = { | 70 } kPreferredCodecIdAndVEAProfiles[] = { |
| 69 {CodecId::VP8, media::VP8PROFILE_MIN, media::VP8PROFILE_MAX}, | 71 {CodecId::VP8, media::VP8PROFILE_MIN, media::VP8PROFILE_MAX}, |
| 70 {CodecId::VP9, media::VP9PROFILE_MIN, media::VP9PROFILE_MAX}, | 72 {CodecId::VP9, media::VP9PROFILE_MIN, media::VP9PROFILE_MAX}, |
| 71 #if BUILDFLAG(RTC_USE_H264) | 73 #if BUILDFLAG(RTC_USE_H264) || defined(OS_ANDROID) |
| 72 {CodecId::H264, media::H264PROFILE_MIN, media::H264PROFILE_MAX} | 74 {CodecId::H264, media::H264PROFILE_MIN, media::H264PROFILE_MAX} |
| 73 #endif | 75 #endif |
| 74 }; | 76 }; |
| 75 | 77 |
| 76 static_assert(arraysize(kPreferredCodecIdAndVEAProfiles) == | 78 static_assert(arraysize(kPreferredCodecIdAndVEAProfiles) == |
| 77 static_cast<int>(CodecId::LAST), | 79 static_cast<int>(CodecId::LAST), |
| 78 "|kPreferredCodecIdAndVEAProfiles| should consider all CodecIds"); | 80 "|kPreferredCodecIdAndVEAProfiles| should consider all CodecIds"); |
| 79 | 81 |
| 80 // Class to encapsulate the enumeration of CodecIds/VideoCodecProfiles supported | 82 // Class to encapsulate the enumeration of CodecIds/VideoCodecProfiles supported |
| 81 // by the VEA underlying platform. Provides methods to query the preferred | 83 // by the VEA underlying platform. Provides methods to query the preferred |
| (...skipping 22 matching lines...) Expand all Loading... |
| 104 static CodecEnumerator* enumerator = new CodecEnumerator(); | 106 static CodecEnumerator* enumerator = new CodecEnumerator(); |
| 105 return enumerator; | 107 return enumerator; |
| 106 } | 108 } |
| 107 | 109 |
| 108 CodecEnumerator::CodecEnumerator() { | 110 CodecEnumerator::CodecEnumerator() { |
| 109 #if defined(OS_CHROMEOS) | 111 #if defined(OS_CHROMEOS) |
| 110 // See https://crbug.com/616659. | 112 // See https://crbug.com/616659. |
| 111 return; | 113 return; |
| 112 #endif | 114 #endif |
| 113 | 115 |
| 114 #if defined(OS_ANDROID) | |
| 115 // See https://crbug.com/653864. | |
| 116 return; | |
| 117 #endif | |
| 118 | |
| 119 content::RenderThreadImpl* const render_thread_impl = | 116 content::RenderThreadImpl* const render_thread_impl = |
| 120 content::RenderThreadImpl::current(); | 117 content::RenderThreadImpl::current(); |
| 121 if (!render_thread_impl) { | 118 if (!render_thread_impl) { |
| 122 DVLOG(2) << "Couldn't access the render thread"; | 119 DVLOG(2) << "Couldn't access the render thread"; |
| 123 return; | 120 return; |
| 124 } | 121 } |
| 125 | 122 |
| 126 media::GpuVideoAcceleratorFactories* const gpu_factories = | 123 media::GpuVideoAcceleratorFactories* const gpu_factories = |
| 127 render_thread_impl->GetGpuFactories(); | 124 render_thread_impl->GetGpuFactories(); |
| 128 if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { | 125 if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 151 return codec_id_to_profile_.begin()->first; | 148 return codec_id_to_profile_.begin()->first; |
| 152 } | 149 } |
| 153 | 150 |
| 154 media::VideoCodecProfile CodecEnumerator::CodecIdToVEAProfile(CodecId codec) { | 151 media::VideoCodecProfile CodecEnumerator::CodecIdToVEAProfile(CodecId codec) { |
| 155 const auto profile = codec_id_to_profile_.find(codec); | 152 const auto profile = codec_id_to_profile_.find(codec); |
| 156 return profile == codec_id_to_profile_.end() | 153 return profile == codec_id_to_profile_.end() |
| 157 ? media::VIDEO_CODEC_PROFILE_UNKNOWN | 154 ? media::VIDEO_CODEC_PROFILE_UNKNOWN |
| 158 : profile->second; | 155 : profile->second; |
| 159 } | 156 } |
| 160 | 157 |
| 158 bool IsFrameSizeBiggerThanVEAEncoderMinResolution(const gfx::Size& input_size) { |
| 159 #if !defined(OS_ANDROID) |
| 160 if (input_size.width() >= input_size.height()) { |
| 161 return input_size.width() >= kVEAEncoderMinResolutionWidth && |
| 162 input_size.height() >= kVEAEncoderMinResolutionHeight; |
| 163 } else { |
| 164 return input_size.height() >= kVEAEncoderMinResolutionWidth && |
| 165 input_size.width() >= kVEAEncoderMinResolutionHeight; |
| 166 } |
| 167 #else |
| 168 return input_size.width() >= kVEAEncoderMinResolutionWidthAndroid && |
| 169 input_size.height() >= kVEAEncoderMinResolutionHeightAndroid; |
| 170 #endif |
| 171 } |
| 172 |
| 161 } // anonymous namespace | 173 } // anonymous namespace |
| 162 | 174 |
| 163 // Base class to describe a generic Encoder, encapsulating all actual encoder | 175 // Base class to describe a generic Encoder, encapsulating all actual encoder |
| 164 // (re)configurations, encoding and delivery of received frames. This class is | 176 // (re)configurations, encoding and delivery of received frames. This class is |
| 165 // ref-counted to allow the MediaStreamVideoTrack to hold a reference to it (via | 177 // ref-counted to allow the MediaStreamVideoTrack to hold a reference to it (via |
| 166 // the callback that MediaStreamVideoSink passes along) and to jump back and | 178 // the callback that MediaStreamVideoSink passes along) and to jump back and |
| 167 // forth to an internal encoder thread. Moreover, this class: | 179 // forth to an internal encoder thread. Moreover, this class: |
| 168 // - is created on its parent's thread (usually the main Render thread), | 180 // - is created on its parent's thread (usually the main Render thread), |
| 169 // that is, |main_task_runner_|. | 181 // that is, |main_task_runner_|. |
| 170 // - receives VideoFrames on |origin_task_runner_| and runs OnEncodedVideoCB on | 182 // - receives VideoFrames on |origin_task_runner_| and runs OnEncodedVideoCB on |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 media::VideoCodecProfile codec, | 604 media::VideoCodecProfile codec, |
| 593 const gfx::Size& size) | 605 const gfx::Size& size) |
| 594 : Encoder(on_encoded_video_callback, | 606 : Encoder(on_encoded_video_callback, |
| 595 bits_per_second > 0 ? bits_per_second | 607 bits_per_second > 0 ? bits_per_second |
| 596 : size.GetArea() * kVEADefaultBitratePerPixel, | 608 : size.GetArea() * kVEADefaultBitratePerPixel, |
| 597 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), | 609 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), |
| 598 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), | 610 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), |
| 599 codec_(codec), | 611 codec_(codec), |
| 600 error_notified_(false) { | 612 error_notified_(false) { |
| 601 DCHECK(gpu_factories_); | 613 DCHECK(gpu_factories_); |
| 602 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); | |
| 603 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); | |
| 604 | 614 |
| 605 encoding_task_runner_->PostTask( | 615 encoding_task_runner_->PostTask( |
| 606 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, | 616 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, |
| 607 this, size)); | 617 this, size)); |
| 608 } | 618 } |
| 609 | 619 |
| 610 VEAEncoder::~VEAEncoder() { | 620 VEAEncoder::~VEAEncoder() { |
| 611 base::WaitableEvent release_waiter( | 621 base::WaitableEvent release_waiter( |
| 612 base::WaitableEvent::ResetPolicy::MANUAL, | 622 base::WaitableEvent::ResetPolicy::MANUAL, |
| 613 base::WaitableEvent::InitialState::NOT_SIGNALED); | 623 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 } | 734 } |
| 725 | 735 |
| 726 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. | 736 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. |
| 727 // In that case, the encoder expects more frames before returning result. | 737 // In that case, the encoder expects more frames before returning result. |
| 728 // Therefore, a copy is necessary to release the current frame. | 738 // Therefore, a copy is necessary to release the current frame. |
| 729 // Only STORAGE_SHMEM backed frames can be shared with GPU process, therefore | 739 // Only STORAGE_SHMEM backed frames can be shared with GPU process, therefore |
| 730 // a copy is required for other storage types. | 740 // a copy is required for other storage types. |
| 731 scoped_refptr<media::VideoFrame> video_frame = frame; | 741 scoped_refptr<media::VideoFrame> video_frame = frame; |
| 732 if (video_frame->storage_type() != VideoFrame::STORAGE_SHMEM || | 742 if (video_frame->storage_type() != VideoFrame::STORAGE_SHMEM || |
| 733 vea_requested_input_coded_size_ != frame->coded_size() || | 743 vea_requested_input_coded_size_ != frame->coded_size() || |
| 734 input_visible_size_.width() < kVEAEncoderMinResolutionWidth || | 744 !IsFrameSizeBiggerThanVEAEncoderMinResolution(input_visible_size_)) { |
| 735 input_visible_size_.height() < kVEAEncoderMinResolutionHeight) { | |
| 736 // Create SharedMemory backed input buffers as necessary. These SharedMemory | 745 // Create SharedMemory backed input buffers as necessary. These SharedMemory |
| 737 // instances will be shared with GPU process. | 746 // instances will be shared with GPU process. |
| 738 std::unique_ptr<base::SharedMemory> input_buffer; | 747 std::unique_ptr<base::SharedMemory> input_buffer; |
| 739 const size_t desired_mapped_size = media::VideoFrame::AllocationSize( | 748 const size_t desired_mapped_size = media::VideoFrame::AllocationSize( |
| 740 media::PIXEL_FORMAT_I420, vea_requested_input_coded_size_); | 749 media::PIXEL_FORMAT_I420, vea_requested_input_coded_size_); |
| 741 if (input_buffers_.empty()) { | 750 if (input_buffers_.empty()) { |
| 742 input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size); | 751 input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size); |
| 743 } else { | 752 } else { |
| 744 do { | 753 do { |
| 745 input_buffer = std::move(input_buffers_.front()); | 754 input_buffer = std::move(input_buffers_.front()); |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 // sink to initialize, https://crbug.com/698441. | 1307 // sink to initialize, https://crbug.com/698441. |
| 1299 if (encoder_) | 1308 if (encoder_) |
| 1300 return; | 1309 return; |
| 1301 | 1310 |
| 1302 MediaStreamVideoSink::DisconnectFromTrack(); | 1311 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1303 | 1312 |
| 1304 const gfx::Size& input_size = frame->visible_rect().size(); | 1313 const gfx::Size& input_size = frame->visible_rect().size(); |
| 1305 const auto& vea_supported_profile = | 1314 const auto& vea_supported_profile = |
| 1306 GetCodecEnumerator()->CodecIdToVEAProfile(codec); | 1315 GetCodecEnumerator()->CodecIdToVEAProfile(codec); |
| 1307 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && | 1316 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && |
| 1308 input_size.width() >= kVEAEncoderMinResolutionWidth && | 1317 IsFrameSizeBiggerThanVEAEncoderMinResolution(input_size)) { |
| 1309 input_size.height() >= kVEAEncoderMinResolutionHeight) { | |
| 1310 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, | 1318 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, |
| 1311 vea_supported_profile, input_size); | 1319 vea_supported_profile, input_size); |
| 1312 } else { | 1320 } else { |
| 1313 switch (codec) { | 1321 switch (codec) { |
| 1314 #if BUILDFLAG(RTC_USE_H264) | 1322 #if BUILDFLAG(RTC_USE_H264) |
| 1315 case CodecId::H264: | 1323 case CodecId::H264: |
| 1316 encoder_ = | 1324 encoder_ = |
| 1317 new H264Encoder(on_encoded_video_callback, bits_per_second); | 1325 new H264Encoder(on_encoded_video_callback, bits_per_second); |
| 1318 break; | 1326 break; |
| 1319 #endif | 1327 #endif |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1336 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), | 1344 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| 1337 false); | 1345 false); |
| 1338 } | 1346 } |
| 1339 | 1347 |
| 1340 bool VideoTrackRecorder::CanEncodeAlphaChannelForTesting() { | 1348 bool VideoTrackRecorder::CanEncodeAlphaChannelForTesting() { |
| 1341 DCHECK(encoder_); | 1349 DCHECK(encoder_); |
| 1342 return encoder_->CanEncodeAlphaChannel(); | 1350 return encoder_->CanEncodeAlphaChannel(); |
| 1343 } | 1351 } |
| 1344 | 1352 |
| 1345 } // namespace content | 1353 } // namespace content |
| OLD | NEW |