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

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

Issue 2000003002: Initialize based on frame sizes in VideoTrackRecorder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mrgpu2
Patch Set: Drop first frames. Created 4 years, 5 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/video_track_recorder.h" 5 #include "content/renderer/media/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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 media::H264PROFILE_MAX}}; 64 media::H264PROFILE_MAX}};
65 65
66 // Returns the corresponding codec profile from VEA supported codecs. If no 66 // Returns the corresponding codec profile from VEA supported codecs. If no
67 // profile is found, returns VIDEO_CODEC_PROFILE_UNKNOWN. 67 // profile is found, returns VIDEO_CODEC_PROFILE_UNKNOWN.
68 media::VideoCodecProfile CodecIdToVEAProfile( 68 media::VideoCodecProfile CodecIdToVEAProfile(
69 content::VideoTrackRecorder::CodecId codec) { 69 content::VideoTrackRecorder::CodecId codec) {
70 // See https://crbug.com/616659. 70 // See https://crbug.com/616659.
71 #if defined(OS_CHROMEOS) 71 #if defined(OS_CHROMEOS)
72 return media::VIDEO_CODEC_PROFILE_UNKNOWN; 72 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
73 #endif // defined(OS_CHROMEOS) 73 #endif // defined(OS_CHROMEOS)
74 content::RenderThreadImpl* render_thread_impl = 74 content::RenderThreadImpl* const render_thread_impl =
75 content::RenderThreadImpl::current(); 75 content::RenderThreadImpl::current();
76 if (!render_thread_impl) 76 if (!render_thread_impl) {
77 DVLOG(3) << "Couldn't access the render thread";
77 return media::VIDEO_CODEC_PROFILE_UNKNOWN; 78 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
79 }
78 80
79 media::GpuVideoAcceleratorFactories* gpu_factories = 81 media::GpuVideoAcceleratorFactories* const gpu_factories =
80 content::RenderThreadImpl::current()->GetGpuFactories(); 82 render_thread_impl->GetGpuFactories();
81 if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { 83 if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
82 DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories"; 84 DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories";
83 return media::VIDEO_CODEC_PROFILE_UNKNOWN; 85 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
84 } 86 }
85 87
86 const media::VideoEncodeAccelerator::SupportedProfiles& vea_profiles = 88 const media::VideoEncodeAccelerator::SupportedProfiles& vea_profiles =
87 gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles(); 89 gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
88 for (const auto& vea_profile : vea_profiles) { 90 for (const auto& vea_profile : vea_profiles) {
89 for (const auto& supported_profile : kSupportedVideoCodecIdToProfile) { 91 for (const auto& supported_profile : kSupportedVideoCodecIdToProfile) {
90 if (codec == supported_profile.codec_id && 92 if (codec == supported_profile.codec_id &&
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 245
244 // Class encapsulating VideoEncodeAccelerator interactions. 246 // Class encapsulating VideoEncodeAccelerator interactions.
245 // This class is created and destroyed in its owner thread. All other methods 247 // This class is created and destroyed in its owner thread. All other methods
246 // operate on the task runner pointed by GpuFactories. 248 // operate on the task runner pointed by GpuFactories.
247 class VEAEncoder final : public VideoTrackRecorder::Encoder, 249 class VEAEncoder final : public VideoTrackRecorder::Encoder,
248 public media::VideoEncodeAccelerator::Client { 250 public media::VideoEncodeAccelerator::Client {
249 public: 251 public:
250 VEAEncoder( 252 VEAEncoder(
251 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, 253 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
252 int32_t bits_per_second, 254 int32_t bits_per_second,
253 media::VideoCodecProfile codec); 255 media::VideoCodecProfile codec,
256 const gfx::Size& size);
254 257
255 // media::VideoEncodeAccelerator::Client implementation. 258 // media::VideoEncodeAccelerator::Client implementation.
256 void RequireBitstreamBuffers(unsigned int input_count, 259 void RequireBitstreamBuffers(unsigned int input_count,
257 const gfx::Size& input_coded_size, 260 const gfx::Size& input_coded_size,
258 size_t output_buffer_size) override; 261 size_t output_buffer_size) override;
259 void BitstreamBufferReady(int32_t bitstream_buffer_id, 262 void BitstreamBufferReady(int32_t bitstream_buffer_id,
260 size_t payload_size, 263 size_t payload_size,
261 bool key_frame, 264 bool key_frame,
262 base::TimeDelta timestamp) override; 265 base::TimeDelta timestamp) override;
263 void NotifyError(media::VideoEncodeAccelerator::Error error) override; 266 void NotifyError(media::VideoEncodeAccelerator::Error error) override;
(...skipping 20 matching lines...) Expand all
284 287
285 // Shared memory buffers for output with the VEA. 288 // Shared memory buffers for output with the VEA.
286 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_; 289 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_;
287 290
288 // Shared memory buffers for output with the VEA as FIFO. 291 // Shared memory buffers for output with the VEA as FIFO.
289 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_; 292 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_;
290 293
291 // Tracks error status. 294 // Tracks error status.
292 bool error_notified_; 295 bool error_notified_;
293 296
294 // Tracks the first frame to encode. 297 // Tracks the last frame that we delay the encode.
295 std::unique_ptr<VideoFrameAndTimestamp> first_frame_; 298 std::unique_ptr<VideoFrameAndTimestamp> last_frame_;
296 299
297 // Size used to initialize encoder. 300 // Size used to initialize encoder.
298 gfx::Size input_size_; 301 gfx::Size input_size_;
299 302
300 // Coded size that encoder requests as input. 303 // Coded size that encoder requests as input.
301 gfx::Size vea_requested_input_size_; 304 gfx::Size vea_requested_input_size_;
302 305
303 // Frames and corresponding timestamps in encode as FIFO. 306 // Frames and corresponding timestamps in encode as FIFO.
304 std::queue<VideoFrameAndTimestamp> frames_in_encode_; 307 std::queue<VideoFrameAndTimestamp> frames_in_encode_;
305 }; 308 };
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 base::TimeTicks first_frame_timestamp_; 388 base::TimeTicks first_frame_timestamp_;
386 389
387 DISALLOW_COPY_AND_ASSIGN(H264Encoder); 390 DISALLOW_COPY_AND_ASSIGN(H264Encoder);
388 }; 391 };
389 392
390 #endif // #if BUILDFLAG(RTC_USE_H264) 393 #endif // #if BUILDFLAG(RTC_USE_H264)
391 394
392 VEAEncoder::VEAEncoder( 395 VEAEncoder::VEAEncoder(
393 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, 396 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
394 int32_t bits_per_second, 397 int32_t bits_per_second,
395 media::VideoCodecProfile codec) 398 media::VideoCodecProfile codec,
399 const gfx::Size& size)
396 : Encoder(on_encoded_video_callback, 400 : Encoder(on_encoded_video_callback,
397 bits_per_second, 401 bits_per_second,
398 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), 402 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()),
399 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), 403 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
400 codec_(codec), 404 codec_(codec),
401 error_notified_(false) { 405 error_notified_(false) {
402 DCHECK(gpu_factories_); 406 DCHECK(gpu_factories_);
407
mcasas 2016/07/08 22:59:27 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWi
emircan 2016/07/12 01:00:35 Done.
408 encoding_task_runner_->PostTask(
409 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner,
410 this, size));
403 } 411 }
404 412
405 VEAEncoder::~VEAEncoder() { 413 VEAEncoder::~VEAEncoder() {
406 encoding_task_runner_->PostTask( 414 encoding_task_runner_->PostTask(
407 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy, 415 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy,
408 base::Unretained(video_encoder_.release()))); 416 base::Unretained(video_encoder_.release())));
409 } 417 }
410 418
411 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/, 419 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/,
412 const gfx::Size& input_coded_size, 420 const gfx::Size& input_coded_size,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 const scoped_refptr<VideoFrame>& frame, 486 const scoped_refptr<VideoFrame>& frame,
479 base::TimeTicks capture_timestamp) { 487 base::TimeTicks capture_timestamp) {
480 DVLOG(3) << __FUNCTION__; 488 DVLOG(3) << __FUNCTION__;
481 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); 489 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
482 490
483 if (input_size_ != frame->visible_rect().size() && video_encoder_) { 491 if (input_size_ != frame->visible_rect().size() && video_encoder_) {
484 video_encoder_->Destroy(); 492 video_encoder_->Destroy();
485 video_encoder_.reset(); 493 video_encoder_.reset();
486 } 494 }
487 495
488 if (!video_encoder_) { 496 if (!video_encoder_)
489 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); 497 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
490 first_frame_.reset(
491 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
492 frame, capture_timestamp));
493 }
494 498
495 if (error_notified_) { 499 if (error_notified_) {
496 DVLOG(3) << "An error occurred in VEA encoder"; 500 DVLOG(3) << "An error occurred in VEA encoder";
497 return; 501 return;
498 } 502 }
499 503
500 // Drop frames if there is no output buffers available. 504 // Drop frames if there is no output buffers available.
501 if (output_buffers_.empty()) { 505 if (output_buffers_.empty()) {
502 // TODO(emircan): Investigate if resetting encoder would help. 506 // TODO(emircan): Investigate if resetting encoder would help.
503 DVLOG(3) << "Dropped frame."; 507 DVLOG(3) << "Might drop frame.";
508 last_frame_.reset(
509 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
510 frame, capture_timestamp));
504 return; 511 return;
505 } 512 }
506 513
507 // If first frame hasn't been encoded, do it first. 514 // If first frame hasn't been encoded, do it first.
508 if (first_frame_) { 515 if (last_frame_) {
509 std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release()); 516 std::unique_ptr<VideoFrameAndTimestamp> last_frame(last_frame_.release());
510 EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second); 517 EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second);
511 } 518 }
512 519
513 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. 520 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac.
514 // In that case, the encoder expects more frames before returning result. 521 // In that case, the encoder expects more frames before returning result.
515 // Therefore, a copy is necessary to release the current frame. 522 // Therefore, a copy is necessary to release the current frame.
516 scoped_refptr<media::VideoFrame> video_frame = frame; 523 scoped_refptr<media::VideoFrame> video_frame = frame;
517 if (vea_requested_input_size_ != input_size_ || 524 if (vea_requested_input_size_ != input_size_ ||
518 input_size_.width() < kVEAEncoderMinResolutionWidth || 525 input_size_.width() < kVEAEncoderMinResolutionWidth ||
519 input_size_.height() < kVEAEncoderMinResolutionHeight) { 526 input_size_.height() < kVEAEncoderMinResolutionHeight) {
520 // Create SharedMemory backed input buffers as necessary. These SharedMemory 527 // Create SharedMemory backed input buffers as necessary. These SharedMemory
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 } 936 }
930 #endif //#if BUILDFLAG(RTC_USE_H264) 937 #endif //#if BUILDFLAG(RTC_USE_H264)
931 938
932 } // anonymous namespace 939 } // anonymous namespace
933 940
934 VideoTrackRecorder::VideoTrackRecorder( 941 VideoTrackRecorder::VideoTrackRecorder(
935 CodecId codec, 942 CodecId codec,
936 const blink::WebMediaStreamTrack& track, 943 const blink::WebMediaStreamTrack& track,
937 const OnEncodedVideoCB& on_encoded_video_callback, 944 const OnEncodedVideoCB& on_encoded_video_callback,
938 int32_t bits_per_second) 945 int32_t bits_per_second)
939 : track_(track) { 946 : track_(track),
947 codec_(codec),
948 on_encoded_video_callback_(on_encoded_video_callback),
949 bits_per_second_(bits_per_second),
950 paused_before_init_(false),
951 weak_ptr_factory_(this) {
940 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 952 DCHECK(main_render_thread_checker_.CalledOnValidThread());
941 DCHECK(!track_.isNull()); 953 DCHECK(!track_.isNull());
942 DCHECK(track_.getTrackData()); 954 DCHECK(track_.getTrackData());
943 955
944 const auto& vea_supported_profile = CodecIdToVEAProfile(codec); 956 // InitializeEncoder() will be called on Render Main thread.
945 // TODO(emircan): Prioritize software based encoders in lower resolutions. 957 // It is safe to use Unretained, because the class gets disconnected from
946 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) { 958 // track in dtor.
947 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
948 vea_supported_profile);
949 } else {
950 switch (codec) {
951 #if BUILDFLAG(RTC_USE_H264)
952 case CodecId::H264:
953 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
954 break;
955 #endif
956 case CodecId::VP8:
957 case CodecId::VP9:
958 encoder_ = new VpxEncoder(codec == CodecId::VP9,
959 on_encoded_video_callback, bits_per_second);
960 break;
961 default:
962 NOTREACHED() << "Unsupported codec";
963 }
964 }
965
966 // StartFrameEncode() will be called on Render IO thread.
967 MediaStreamVideoSink::ConnectToTrack( 959 MediaStreamVideoSink::ConnectToTrack(
968 track_, 960 track_,
969 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), 961 media::BindToCurrentLoop(base::Bind(
962 &VideoTrackRecorder::InitializeEncoder, base::Unretained(this))),
970 false); 963 false);
971 } 964 }
972 965
973 VideoTrackRecorder::~VideoTrackRecorder() { 966 VideoTrackRecorder::~VideoTrackRecorder() {
974 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 967 DCHECK(main_render_thread_checker_.CalledOnValidThread());
975 MediaStreamVideoSink::DisconnectFromTrack(); 968 MediaStreamVideoSink::DisconnectFromTrack();
976 track_.reset(); 969 track_.reset();
977 } 970 }
978 971
979 void VideoTrackRecorder::Pause() { 972 void VideoTrackRecorder::Pause() {
980 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 973 DCHECK(main_render_thread_checker_.CalledOnValidThread());
981 DCHECK(encoder_); 974 if (encoder_)
982 encoder_->SetPaused(true); 975 encoder_->SetPaused(true);
976 else
977 paused_before_init_ = true;
983 } 978 }
984 979
985 void VideoTrackRecorder::Resume() { 980 void VideoTrackRecorder::Resume() {
986 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 981 DCHECK(main_render_thread_checker_.CalledOnValidThread());
987 DCHECK(encoder_); 982 if (encoder_)
988 encoder_->SetPaused(false); 983 encoder_->SetPaused(false);
984 else
985 paused_before_init_ = false;
989 } 986 }
990 987
991 void VideoTrackRecorder::OnVideoFrameForTesting( 988 void VideoTrackRecorder::OnVideoFrameForTesting(
992 const scoped_refptr<media::VideoFrame>& frame, 989 const scoped_refptr<media::VideoFrame>& frame,
993 base::TimeTicks timestamp) { 990 base::TimeTicks timestamp) {
991 DVLOG(3) << __FUNCTION__;
992
993 if (!encoder_)
994 InitializeEncoder(frame, timestamp);
995
994 encoder_->StartFrameEncode(frame, timestamp); 996 encoder_->StartFrameEncode(frame, timestamp);
995 } 997 }
996 998
999
1000 void VideoTrackRecorder::InitializeEncoder(
1001 const scoped_refptr<media::VideoFrame>& frame,
1002 base::TimeTicks capture_time) {
1003 DVLOG(3) << __FUNCTION__ << frame->visible_rect().size().ToString();
1004 DCHECK(main_render_thread_checker_.CalledOnValidThread());
1005
1006 MediaStreamVideoSink::DisconnectFromTrack();
1007
1008 const gfx::Size& input_size = frame->visible_rect().size();
1009 const auto& vea_supported_profile = CodecIdToVEAProfile(codec_);
1010 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN &&
1011 input_size.width() >= kVEAEncoderMinResolutionWidth &&
1012 input_size.height() >= kVEAEncoderMinResolutionHeight) {
1013 encoder_ = new VEAEncoder(on_encoded_video_callback_, bits_per_second_,
1014 vea_supported_profile, input_size);
1015 } else {
1016 switch (codec_) {
1017 #if BUILDFLAG(RTC_USE_H264)
1018 case CodecId::H264:
1019 encoder_ =
1020 new H264Encoder(on_encoded_video_callback_, bits_per_second_);
1021 break;
1022 #endif
1023 case CodecId::VP8:
1024 case CodecId::VP9:
1025 encoder_ = new VpxEncoder(codec_ == CodecId::VP9,
1026 on_encoded_video_callback_, bits_per_second_);
1027 break;
1028 default:
1029 NOTREACHED() << "Unsupported codec";
1030 }
1031 }
1032
1033 if (paused_before_init_)
1034 encoder_->SetPaused(paused_before_init_);
1035
1036 // StartFrameEncode() will be called on Render IO thread.
1037 MediaStreamVideoSink::ConnectToTrack(
1038 track_,
1039 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_),
1040 false);
1041 }
1042
997 } // namespace content 1043 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698