Chromium Code Reviews| 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 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 } | 406 } |
| 407 | 407 |
| 408 // Class encapsulating VideoEncodeAccelerator interactions. | 408 // Class encapsulating VideoEncodeAccelerator interactions. |
| 409 // This class is created and destroyed in its owner thread. All other methods | 409 // This class is created and destroyed in its owner thread. All other methods |
| 410 // operate on the task runner pointed by GpuFactories. | 410 // operate on the task runner pointed by GpuFactories. |
| 411 class VEAEncoder final : public VideoTrackRecorder::Encoder, | 411 class VEAEncoder final : public VideoTrackRecorder::Encoder, |
| 412 public media::VideoEncodeAccelerator::Client { | 412 public media::VideoEncodeAccelerator::Client { |
| 413 public: | 413 public: |
| 414 VEAEncoder( | 414 VEAEncoder( |
| 415 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, | 415 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| 416 const VideoTrackRecorder::OnErrorCB& on_error_callback, | |
| 416 int32_t bits_per_second, | 417 int32_t bits_per_second, |
| 417 media::VideoCodecProfile codec, | 418 media::VideoCodecProfile codec, |
| 418 const gfx::Size& size); | 419 const gfx::Size& size); |
| 419 | 420 |
| 420 // media::VideoEncodeAccelerator::Client implementation. | 421 // media::VideoEncodeAccelerator::Client implementation. |
| 421 void RequireBitstreamBuffers(unsigned int input_count, | 422 void RequireBitstreamBuffers(unsigned int input_count, |
| 422 const gfx::Size& input_coded_size, | 423 const gfx::Size& input_coded_size, |
| 423 size_t output_buffer_size) override; | 424 size_t output_buffer_size) override; |
| 424 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 425 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 425 size_t payload_size, | 426 size_t payload_size, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; | 466 std::unique_ptr<VideoFrameAndTimestamp> last_frame_; |
| 466 | 467 |
| 467 // Size used to initialize encoder. | 468 // Size used to initialize encoder. |
| 468 gfx::Size input_visible_size_; | 469 gfx::Size input_visible_size_; |
| 469 | 470 |
| 470 // Coded size that encoder requests as input. | 471 // Coded size that encoder requests as input. |
| 471 gfx::Size vea_requested_input_coded_size_; | 472 gfx::Size vea_requested_input_coded_size_; |
| 472 | 473 |
| 473 // Frames and corresponding timestamps in encode as FIFO. | 474 // Frames and corresponding timestamps in encode as FIFO. |
| 474 std::queue<VideoParamsAndTimestamp> frames_in_encode_; | 475 std::queue<VideoParamsAndTimestamp> frames_in_encode_; |
| 476 | |
| 477 // This callback can be exercised on any thread. | |
| 478 const VideoTrackRecorder::OnErrorCB on_error_callback_; | |
| 475 }; | 479 }; |
| 476 | 480 |
| 477 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. | 481 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. |
| 478 class VpxEncoder final : public VideoTrackRecorder::Encoder { | 482 class VpxEncoder final : public VideoTrackRecorder::Encoder { |
| 479 public: | 483 public: |
| 480 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, | 484 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
| 481 ScopedVpxCodecCtxPtr encoder); | 485 ScopedVpxCodecCtxPtr encoder); |
| 482 | 486 |
| 483 VpxEncoder( | 487 VpxEncoder( |
| 484 bool use_vp9, | 488 bool use_vp9, |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 // |encoding_thread_|. | 585 // |encoding_thread_|. |
| 582 base::TimeTicks first_frame_timestamp_; | 586 base::TimeTicks first_frame_timestamp_; |
| 583 | 587 |
| 584 DISALLOW_COPY_AND_ASSIGN(H264Encoder); | 588 DISALLOW_COPY_AND_ASSIGN(H264Encoder); |
| 585 }; | 589 }; |
| 586 | 590 |
| 587 #endif // #if BUILDFLAG(RTC_USE_H264) | 591 #endif // #if BUILDFLAG(RTC_USE_H264) |
| 588 | 592 |
| 589 VEAEncoder::VEAEncoder( | 593 VEAEncoder::VEAEncoder( |
| 590 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, | 594 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| 595 const VideoTrackRecorder::OnErrorCB& on_error_callback, | |
| 591 int32_t bits_per_second, | 596 int32_t bits_per_second, |
| 592 media::VideoCodecProfile codec, | 597 media::VideoCodecProfile codec, |
| 593 const gfx::Size& size) | 598 const gfx::Size& size) |
| 594 : Encoder(on_encoded_video_callback, | 599 : Encoder(on_encoded_video_callback, |
| 595 bits_per_second > 0 ? bits_per_second | 600 bits_per_second > 0 ? bits_per_second |
| 596 : size.GetArea() * kVEADefaultBitratePerPixel, | 601 : size.GetArea() * kVEADefaultBitratePerPixel, |
| 597 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), | 602 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), |
| 598 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), | 603 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), |
| 599 codec_(codec), | 604 codec_(codec), |
| 600 error_notified_(false) { | 605 error_notified_(false), |
| 606 on_error_callback_(on_error_callback) { | |
| 601 DCHECK(gpu_factories_); | 607 DCHECK(gpu_factories_); |
| 602 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); | 608 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); |
| 603 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); | 609 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); |
| 604 | 610 |
| 605 encoding_task_runner_->PostTask( | 611 encoding_task_runner_->PostTask( |
| 606 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, | 612 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, |
| 607 this, size)); | 613 this, size)); |
| 608 } | 614 } |
| 609 | 615 |
| 610 VEAEncoder::~VEAEncoder() { | 616 VEAEncoder::~VEAEncoder() { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 663 origin_task_runner_->PostTask( | 669 origin_task_runner_->PostTask( |
| 664 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_, | 670 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_, |
| 665 front_frame.first, base::Passed(&data), nullptr, | 671 front_frame.first, base::Passed(&data), nullptr, |
| 666 front_frame.second, keyframe)); | 672 front_frame.second, keyframe)); |
| 667 UseOutputBitstreamBufferId(bitstream_buffer_id); | 673 UseOutputBitstreamBufferId(bitstream_buffer_id); |
| 668 } | 674 } |
| 669 | 675 |
| 670 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) { | 676 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) { |
| 671 DVLOG(3) << __func__; | 677 DVLOG(3) << __func__; |
| 672 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 678 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 673 | 679 on_error_callback_.Run(false /* allow_vea_encoder */); |
| 674 // TODO(emircan): Notify the owner via a callback. | |
| 675 error_notified_ = true; | 680 error_notified_ = true; |
| 676 } | 681 } |
| 677 | 682 |
| 678 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) { | 683 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) { |
| 679 DVLOG(3) << __func__; | 684 DVLOG(3) << __func__; |
| 680 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); | 685 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); |
| 681 | 686 |
| 682 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( | 687 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer( |
| 683 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(), | 688 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(), |
| 684 output_buffers_[bitstream_buffer_id]->mapped_size())); | 689 output_buffers_[bitstream_buffer_id]->mapped_size())); |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1240 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1245 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1241 DCHECK(!track_.isNull()); | 1246 DCHECK(!track_.isNull()); |
| 1242 DCHECK(track_.getTrackData()); | 1247 DCHECK(track_.getTrackData()); |
| 1243 | 1248 |
| 1244 initialize_encoder_callback_ = base::Bind( | 1249 initialize_encoder_callback_ = base::Bind( |
| 1245 &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(), | 1250 &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(), |
| 1246 codec, on_encoded_video_callback, bits_per_second); | 1251 codec, on_encoded_video_callback, bits_per_second); |
| 1247 | 1252 |
| 1248 // InitializeEncoder() will be called on Render Main thread. | 1253 // InitializeEncoder() will be called on Render Main thread. |
| 1249 MediaStreamVideoSink::ConnectToTrack( | 1254 MediaStreamVideoSink::ConnectToTrack( |
| 1250 track_, media::BindToCurrentLoop(initialize_encoder_callback_), false); | 1255 track_, |
| 1256 media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, | |
| 1257 true /* allow_vea_encoder */)), | |
| 1258 false); | |
| 1251 } | 1259 } |
| 1252 | 1260 |
| 1253 VideoTrackRecorder::~VideoTrackRecorder() { | 1261 VideoTrackRecorder::~VideoTrackRecorder() { |
| 1254 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1262 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1255 MediaStreamVideoSink::DisconnectFromTrack(); | 1263 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1256 track_.reset(); | 1264 track_.reset(); |
| 1257 } | 1265 } |
| 1258 | 1266 |
| 1259 void VideoTrackRecorder::Pause() { | 1267 void VideoTrackRecorder::Pause() { |
| 1260 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1268 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1272 paused_before_init_ = false; | 1280 paused_before_init_ = false; |
| 1273 } | 1281 } |
| 1274 | 1282 |
| 1275 void VideoTrackRecorder::OnVideoFrameForTesting( | 1283 void VideoTrackRecorder::OnVideoFrameForTesting( |
| 1276 const scoped_refptr<media::VideoFrame>& frame, | 1284 const scoped_refptr<media::VideoFrame>& frame, |
| 1277 base::TimeTicks timestamp) { | 1285 base::TimeTicks timestamp) { |
| 1278 DVLOG(3) << __func__; | 1286 DVLOG(3) << __func__; |
| 1279 | 1287 |
| 1280 if (!encoder_) { | 1288 if (!encoder_) { |
| 1281 DCHECK(!initialize_encoder_callback_.is_null()); | 1289 DCHECK(!initialize_encoder_callback_.is_null()); |
| 1282 initialize_encoder_callback_.Run(frame, timestamp); | 1290 initialize_encoder_callback_.Run(true /* allow_vea_encoder */, frame, |
| 1291 timestamp); | |
| 1283 } | 1292 } |
| 1284 | 1293 |
| 1285 encoder_->StartFrameEncode(frame, timestamp); | 1294 encoder_->StartFrameEncode(frame, timestamp); |
| 1286 } | 1295 } |
| 1287 | 1296 |
| 1288 void VideoTrackRecorder::InitializeEncoder( | 1297 void VideoTrackRecorder::InitializeEncoder( |
| 1289 CodecId codec, | 1298 CodecId codec, |
| 1290 const OnEncodedVideoCB& on_encoded_video_callback, | 1299 const OnEncodedVideoCB& on_encoded_video_callback, |
| 1291 int32_t bits_per_second, | 1300 int32_t bits_per_second, |
| 1301 bool allow_vea_encoder, | |
| 1292 const scoped_refptr<media::VideoFrame>& frame, | 1302 const scoped_refptr<media::VideoFrame>& frame, |
| 1293 base::TimeTicks capture_time) { | 1303 base::TimeTicks capture_time) { |
| 1294 DVLOG(3) << __func__ << frame->visible_rect().size().ToString(); | 1304 DVLOG(3) << __func__ << frame->visible_rect().size().ToString(); |
| 1295 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 1305 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 1296 | 1306 |
| 1297 // Avoid reinitializing |encoder_| when there are multiple frames sent to the | 1307 // Avoid reinitializing |encoder_| when there are multiple frames sent to the |
| 1298 // sink to initialize, https://crbug.com/698441. | 1308 // sink to initialize, https://crbug.com/698441. |
| 1299 if (encoder_) | 1309 if (encoder_) |
| 1300 return; | 1310 return; |
| 1301 | 1311 |
| 1302 MediaStreamVideoSink::DisconnectFromTrack(); | 1312 MediaStreamVideoSink::DisconnectFromTrack(); |
| 1303 | 1313 |
| 1304 const gfx::Size& input_size = frame->visible_rect().size(); | 1314 const gfx::Size& input_size = frame->visible_rect().size(); |
| 1305 const auto& vea_supported_profile = | 1315 const auto& vea_supported_profile = |
| 1306 GetCodecEnumerator()->CodecIdToVEAProfile(codec); | 1316 GetCodecEnumerator()->CodecIdToVEAProfile(codec); |
| 1307 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && | 1317 if (allow_vea_encoder && |
| 1318 vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && | |
| 1308 input_size.width() >= kVEAEncoderMinResolutionWidth && | 1319 input_size.width() >= kVEAEncoderMinResolutionWidth && |
| 1309 input_size.height() >= kVEAEncoderMinResolutionHeight) { | 1320 input_size.height() >= kVEAEncoderMinResolutionHeight) { |
| 1310 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, | 1321 encoder_ = new VEAEncoder( |
| 1311 vea_supported_profile, input_size); | 1322 on_encoded_video_callback, |
| 1323 media::BindToCurrentLoop(base::Bind(&VideoTrackRecorder::OnError, | |
| 1324 weak_ptr_factory_.GetWeakPtr())), | |
| 1325 bits_per_second, vea_supported_profile, input_size); | |
| 1312 } else { | 1326 } else { |
| 1313 switch (codec) { | 1327 switch (codec) { |
| 1314 #if BUILDFLAG(RTC_USE_H264) | 1328 #if BUILDFLAG(RTC_USE_H264) |
| 1315 case CodecId::H264: | 1329 case CodecId::H264: |
| 1316 encoder_ = | 1330 encoder_ = |
| 1317 new H264Encoder(on_encoded_video_callback, bits_per_second); | 1331 new H264Encoder(on_encoded_video_callback, bits_per_second); |
| 1318 break; | 1332 break; |
| 1319 #endif | 1333 #endif |
| 1320 case CodecId::VP8: | 1334 case CodecId::VP8: |
| 1321 case CodecId::VP9: | 1335 case CodecId::VP9: |
| 1322 encoder_ = new VpxEncoder(codec == CodecId::VP9, | 1336 encoder_ = new VpxEncoder(codec == CodecId::VP9, |
| 1323 on_encoded_video_callback, bits_per_second); | 1337 on_encoded_video_callback, bits_per_second); |
| 1324 break; | 1338 break; |
| 1325 default: | 1339 default: |
| 1326 NOTREACHED() << "Unsupported codec " << static_cast<int>(codec); | 1340 NOTREACHED() << "Unsupported codec " << static_cast<int>(codec); |
| 1327 } | 1341 } |
| 1328 } | 1342 } |
| 1329 | 1343 |
| 1330 if (paused_before_init_) | 1344 if (paused_before_init_) |
| 1331 encoder_->SetPaused(paused_before_init_); | 1345 encoder_->SetPaused(paused_before_init_); |
| 1332 | 1346 |
| 1333 // StartFrameEncode() will be called on Render IO thread. | 1347 // StartFrameEncode() will be called on Render IO thread. |
| 1334 MediaStreamVideoSink::ConnectToTrack( | 1348 MediaStreamVideoSink::ConnectToTrack( |
| 1335 track_, | 1349 track_, |
| 1336 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), | 1350 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| 1337 false); | 1351 false); |
| 1338 } | 1352 } |
| 1339 | 1353 |
| 1354 void VideoTrackRecorder::OnError(bool allow_vea_encoder) { | |
| 1355 DVLOG(3) << __func__; | |
| 1356 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | |
| 1357 | |
| 1358 // InitializeEncoder() will be called to reinitialize encoder on Render Main | |
| 1359 // thread. | |
| 1360 MediaStreamVideoSink::DisconnectFromTrack(); | |
| 1361 encoder_ = nullptr; | |
| 1362 MediaStreamVideoSink::ConnectToTrack( | |
| 1363 track_, | |
| 1364 media::BindToCurrentLoop( | |
| 1365 base::Bind(initialize_encoder_callback_, allow_vea_encoder)), | |
|
mcasas
2017/04/05 21:44:33
...and here
s|allow_vea_encoder|false /*allow_vea
emircan
2017/04/05 21:52:55
Done.
| |
| 1366 false); | |
| 1367 } | |
| 1368 | |
| 1340 bool VideoTrackRecorder::CanEncodeAlphaChannelForTesting() { | 1369 bool VideoTrackRecorder::CanEncodeAlphaChannelForTesting() { |
| 1341 DCHECK(encoder_); | 1370 DCHECK(encoder_); |
| 1342 return encoder_->CanEncodeAlphaChannel(); | 1371 return encoder_->CanEncodeAlphaChannel(); |
| 1343 } | 1372 } |
| 1344 | 1373 |
| 1345 } // namespace content | 1374 } // namespace content |
| OLD | NEW |