| 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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 } | 403 } |
| 404 | 404 |
| 405 // Class encapsulating VideoEncodeAccelerator interactions. | 405 // Class encapsulating VideoEncodeAccelerator interactions. |
| 406 // This class is created and destroyed in its owner thread. All other methods | 406 // This class is created and destroyed in its owner thread. All other methods |
| 407 // operate on the task runner pointed by GpuFactories. | 407 // operate on the task runner pointed by GpuFactories. |
| 408 class VEAEncoder final : public VideoTrackRecorder::Encoder, | 408 class VEAEncoder final : public VideoTrackRecorder::Encoder, |
| 409 public media::VideoEncodeAccelerator::Client { | 409 public media::VideoEncodeAccelerator::Client { |
| 410 public: | 410 public: |
| 411 VEAEncoder( | 411 VEAEncoder( |
| 412 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, | 412 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| 413 const VideoTrackRecorder::OnErrorCB& on_error_callback, |
| 413 int32_t bits_per_second, | 414 int32_t bits_per_second, |
| 414 media::VideoCodecProfile codec, | 415 media::VideoCodecProfile codec, |
| 415 const gfx::Size& size); | 416 const gfx::Size& size); |
| 416 | 417 |
| 417 // media::VideoEncodeAccelerator::Client implementation. | 418 // media::VideoEncodeAccelerator::Client implementation. |
| 418 void RequireBitstreamBuffers(unsigned int input_count, | 419 void RequireBitstreamBuffers(unsigned int input_count, |
| 419 const gfx::Size& input_coded_size, | 420 const gfx::Size& input_coded_size, |
| 420 size_t output_buffer_size) override; | 421 size_t output_buffer_size) override; |
| 421 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 422 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 422 size_t payload_size, | 423 size_t payload_size, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; | 462 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; |
| 462 | 463 |
| 463 // Size used to initialize encoder. | 464 // Size used to initialize encoder. |
| 464 gfx::Size input_visible_size_; | 465 gfx::Size input_visible_size_; |
| 465 | 466 |
| 466 // Coded size that encoder requests as input. | 467 // Coded size that encoder requests as input. |
| 467 gfx::Size vea_requested_input_coded_size_; | 468 gfx::Size vea_requested_input_coded_size_; |
| 468 | 469 |
| 469 // Frames and corresponding timestamps in encode as FIFO. | 470 // Frames and corresponding timestamps in encode as FIFO. |
| 470 std::queue<VideoParamsAndTimestamp> frames_in_encode_; | 471 std::queue<VideoParamsAndTimestamp> frames_in_encode_; |
| 472 |
| 473 // This callback can be exercised on any thread. |
| 474 const VideoTrackRecorder::OnErrorCB on_error_callback_; |
| 471 }; | 475 }; |
| 472 | 476 |
| 473 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. | 477 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. |
| 474 class VpxEncoder final : public VideoTrackRecorder::Encoder { | 478 class VpxEncoder final : public VideoTrackRecorder::Encoder { |
| 475 public: | 479 public: |
| 476 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, | 480 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
| 477 ScopedVpxCodecCtxPtr encoder); | 481 ScopedVpxCodecCtxPtr encoder); |
| 478 | 482 |
| 479 VpxEncoder( | 483 VpxEncoder( |
| 480 bool use_vp9, | 484 bool use_vp9, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 // |encoding_thread_|. | 554 // |encoding_thread_|. |
| 551 base::TimeTicks first_frame_timestamp_; | 555 base::TimeTicks first_frame_timestamp_; |
| 552 | 556 |
| 553 DISALLOW_COPY_AND_ASSIGN(H264Encoder); | 557 DISALLOW_COPY_AND_ASSIGN(H264Encoder); |
| 554 }; | 558 }; |
| 555 | 559 |
| 556 #endif // #if BUILDFLAG(RTC_USE_H264) | 560 #endif // #if BUILDFLAG(RTC_USE_H264) |
| 557 | 561 |
| 558 VEAEncoder::VEAEncoder( | 562 VEAEncoder::VEAEncoder( |
| 559 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, | 563 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| 564 const VideoTrackRecorder::OnErrorCB& on_error_callback, |
| 560 int32_t bits_per_second, | 565 int32_t bits_per_second, |
| 561 media::VideoCodecProfile codec, | 566 media::VideoCodecProfile codec, |
| 562 const gfx::Size& size) | 567 const gfx::Size& size) |
| 563 : Encoder(on_encoded_video_callback, | 568 : Encoder(on_encoded_video_callback, |
| 564 bits_per_second > 0 ? bits_per_second | 569 bits_per_second > 0 ? bits_per_second |
| 565 : size.GetArea() * kVEADefaultBitratePerPixel, | 570 : size.GetArea() * kVEADefaultBitratePerPixel, |
| 566 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), | 571 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), |
| 567 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), | 572 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), |
| 568 codec_(codec), | 573 codec_(codec), |
| 569 error_notified_(false) { | 574 error_notified_(false), |
| 575 on_error_callback_(on_error_callback) { |
| 570 DCHECK(gpu_factories_); | 576 DCHECK(gpu_factories_); |
| 571 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); | 577 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); |
| 572 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); | 578 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); |
| 573 | 579 |
| 574 encoding_task_runner_->PostTask( | 580 encoding_task_runner_->PostTask( |
| 575 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, | 581 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, |
| 576 this, size)); | 582 this, size)); |
| 577 } | 583 } |
| 578 | 584 |
| 579 VEAEncoder::~VEAEncoder() { | 585 VEAEncoder::~VEAEncoder() { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 origin_task_runner_->PostTask( | 638 origin_task_runner_->PostTask( |
| 633 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_, | 639 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_, |
| 634 front_frame.first, base::Passed(&data), | 640 front_frame.first, base::Passed(&data), |
| 635 front_frame.second, keyframe)); | 641 front_frame.second, keyframe)); |
| 636 UseOutputBitstreamBufferId(bitstream_buffer_id); | 642 UseOutputBitstreamBufferId(bitstream_buffer_id); |
| 637 } | 643 } |
| 638 | 644 |
| 639 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) { | 645 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) { |
| 640 DVLOG(3) << __func__; | 646 DVLOG(3) << __func__; |
| 641 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 647 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 642 | 648 on_error_callback_.Run(); |
| 643 // TODO(emircan): Notify the owner via a callback. | |
| 644 error_notified_ = true; | 649 error_notified_ = true; |
| 645 } | 650 } |
| 646 | 651 |
| 647 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) { | 652 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) { |
| 648 DVLOG(3) << __func__; | 653 DVLOG(3) << __func__; |
| 649 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 654 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 650 | 655 |
| 651 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( | 656 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( |
| 652 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(), | 657 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(), |
| 653 output_buffers_[bitstream_buffer_id]->mapped_size())); | 658 output_buffers_[bitstream_buffer_id]->mapped_size())); |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1154 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1150 DCHECK(!track_.isNull()); | 1155 DCHECK(!track_.isNull()); |
| 1151 DCHECK(track_.getTrackData()); | 1156 DCHECK(track_.getTrackData()); |
| 1152 | 1157 |
| 1153 initialize_encoder_callback_ = base::Bind( | 1158 initialize_encoder_callback_ = base::Bind( |
| 1154 &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(), | 1159 &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(), |
| 1155 codec, on_encoded_video_callback, bits_per_second); | 1160 codec, on_encoded_video_callback, bits_per_second); |
| 1156 | 1161 |
| 1157 // InitializeEncoder() will be called on Render Main thread. | 1162 // InitializeEncoder() will be called on Render Main thread. |
| 1158 MediaStreamVideoSink::ConnectToTrack( | 1163 MediaStreamVideoSink::ConnectToTrack( |
| 1159 track_, media::BindToCurrentLoop(initialize_encoder_callback_), false); | 1164 track_, |
| 1165 media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, |
| 1166 true /* allow_vea_encoder */)), |
| 1167 false); |
| 1160 } | 1168 } |
| 1161 | 1169 |
| 1162 VideoTrackRecorder::~VideoTrackRecorder() { | 1170 VideoTrackRecorder::~VideoTrackRecorder() { |
| 1163 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1171 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1164 MediaStreamVideoSink::DisconnectFromTrack(); | 1172 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1165 track_.reset(); | 1173 track_.reset(); |
| 1166 } | 1174 } |
| 1167 | 1175 |
| 1168 void VideoTrackRecorder::Pause() { | 1176 void VideoTrackRecorder::Pause() { |
| 1169 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1177 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1181 paused_before_init_ = false; | 1189 paused_before_init_ = false; |
| 1182 } | 1190 } |
| 1183 | 1191 |
| 1184 void VideoTrackRecorder::OnVideoFrameForTesting( | 1192 void VideoTrackRecorder::OnVideoFrameForTesting( |
| 1185 const scoped_refptr<media::VideoFrame>& frame, | 1193 const scoped_refptr<media::VideoFrame>& frame, |
| 1186 base::TimeTicks timestamp) { | 1194 base::TimeTicks timestamp) { |
| 1187 DVLOG(3) << __func__; | 1195 DVLOG(3) << __func__; |
| 1188 | 1196 |
| 1189 if (!encoder_) { | 1197 if (!encoder_) { |
| 1190 DCHECK(!initialize_encoder_callback_.is_null()); | 1198 DCHECK(!initialize_encoder_callback_.is_null()); |
| 1191 initialize_encoder_callback_.Run(frame, timestamp); | 1199 initialize_encoder_callback_.Run(true /* allow_vea_encoder */, frame, |
| 1200 timestamp); |
| 1192 } | 1201 } |
| 1193 | 1202 |
| 1194 encoder_->StartFrameEncode(frame, timestamp); | 1203 encoder_->StartFrameEncode(frame, timestamp); |
| 1195 } | 1204 } |
| 1196 | 1205 |
| 1197 void VideoTrackRecorder::InitializeEncoder( | 1206 void VideoTrackRecorder::InitializeEncoder( |
| 1198 CodecId codec, | 1207 CodecId codec, |
| 1199 const OnEncodedVideoCB& on_encoded_video_callback, | 1208 const OnEncodedVideoCB& on_encoded_video_callback, |
| 1200 int32_t bits_per_second, | 1209 int32_t bits_per_second, |
| 1210 bool allow_vea_encoder, |
| 1201 const scoped_refptr<media::VideoFrame>& frame, | 1211 const scoped_refptr<media::VideoFrame>& frame, |
| 1202 base::TimeTicks capture_time) { | 1212 base::TimeTicks capture_time) { |
| 1203 DVLOG(3) << __func__ << frame->visible_rect().size().ToString(); | 1213 DVLOG(3) << __func__ << frame->visible_rect().size().ToString(); |
| 1204 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1214 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1205 | 1215 |
| 1206 MediaStreamVideoSink::DisconnectFromTrack(); | 1216 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1207 | 1217 |
| 1208 const gfx::Size& input_size = frame->visible_rect().size(); | 1218 const gfx::Size& input_size = frame->visible_rect().size(); |
| 1209 const auto& vea_supported_profile = | 1219 const auto& vea_supported_profile = |
| 1210 GetCodecEnumerator()->CodecIdToVEAProfile(codec); | 1220 GetCodecEnumerator()->CodecIdToVEAProfile(codec); |
| 1211 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && | 1221 if (allow_vea_encoder && |
| 1222 vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && |
| 1212 input_size.width() >= kVEAEncoderMinResolutionWidth && | 1223 input_size.width() >= kVEAEncoderMinResolutionWidth && |
| 1213 input_size.height() >= kVEAEncoderMinResolutionHeight) { | 1224 input_size.height() >= kVEAEncoderMinResolutionHeight) { |
| 1214 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, | 1225 encoder_ = new VEAEncoder( |
| 1215 vea_supported_profile, input_size); | 1226 on_encoded_video_callback, |
| 1227 media::BindToCurrentLoop(base::Bind(&VideoTrackRecorder::OnError, |
| 1228 weak_ptr_factory_.GetWeakPtr())), |
| 1229 bits_per_second, vea_supported_profile, input_size); |
| 1216 } else { | 1230 } else { |
| 1217 switch (codec) { | 1231 switch (codec) { |
| 1218 #if BUILDFLAG(RTC_USE_H264) | 1232 #if BUILDFLAG(RTC_USE_H264) |
| 1219 case CodecId::H264: | 1233 case CodecId::H264: |
| 1220 encoder_ = | 1234 encoder_ = |
| 1221 new H264Encoder(on_encoded_video_callback, bits_per_second); | 1235 new H264Encoder(on_encoded_video_callback, bits_per_second); |
| 1222 break; | 1236 break; |
| 1223 #endif | 1237 #endif |
| 1224 case CodecId::VP8: | 1238 case CodecId::VP8: |
| 1225 case CodecId::VP9: | 1239 case CodecId::VP9: |
| 1226 encoder_ = new VpxEncoder(codec == CodecId::VP9, | 1240 encoder_ = new VpxEncoder(codec == CodecId::VP9, |
| 1227 on_encoded_video_callback, bits_per_second); | 1241 on_encoded_video_callback, bits_per_second); |
| 1228 break; | 1242 break; |
| 1229 default: | 1243 default: |
| 1230 NOTREACHED() << "Unsupported codec " << static_cast<int>(codec); | 1244 NOTREACHED() << "Unsupported codec " << static_cast<int>(codec); |
| 1231 } | 1245 } |
| 1232 } | 1246 } |
| 1233 | 1247 |
| 1234 if (paused_before_init_) | 1248 if (paused_before_init_) |
| 1235 encoder_->SetPaused(paused_before_init_); | 1249 encoder_->SetPaused(paused_before_init_); |
| 1236 | 1250 |
| 1237 // StartFrameEncode() will be called on Render IO thread. | 1251 // StartFrameEncode() will be called on Render IO thread. |
| 1238 MediaStreamVideoSink::ConnectToTrack( | 1252 MediaStreamVideoSink::ConnectToTrack( |
| 1239 track_, | 1253 track_, |
| 1240 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), | 1254 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| 1241 false); | 1255 false); |
| 1242 } | 1256 } |
| 1243 | 1257 |
| 1258 void VideoTrackRecorder::OnError() { |
| 1259 DVLOG(3) << __func__; |
| 1260 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1261 |
| 1262 // InitializeEncoder() will be called to reinitialize encoder on Render Main |
| 1263 // thread. |
| 1264 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1265 encoder_ = nullptr; |
| 1266 MediaStreamVideoSink::ConnectToTrack( |
| 1267 track_, |
| 1268 media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, |
| 1269 false /*allow_vea_encoder*/)), |
| 1270 false); |
| 1271 } |
| 1272 |
| 1244 } // namespace content | 1273 } // namespace content |
| OLD | NEW |