Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: content/renderer/media_recorder/video_track_recorder.cc

Issue 2804843002: Handle HW encoder errors in VideoTrackRecorder (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698