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

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: 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 21 matching lines...) Expand all
32 extern "C" { 32 extern "C" {
33 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide 33 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
34 // backwards compatibility for legacy applications using the library. 34 // backwards compatibility for legacy applications using the library.
35 #define VPX_CODEC_DISABLE_COMPAT 1 35 #define VPX_CODEC_DISABLE_COMPAT 1
36 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" 36 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
37 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" 37 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
38 } 38 }
39 39
40 using media::VideoFrame; 40 using media::VideoFrame;
41 using media::VideoFrameMetadata; 41 using media::VideoFrameMetadata;
42 using video_track_recorder::kVEAEncoderMinResolutionWidth;
43 using video_track_recorder::kVEAEncoderMinResolutionHeight;
42 44
43 namespace content { 45 namespace content {
44 46
45 namespace { 47 namespace {
46 48
47 const int kVEAEncoderMinResolutionWidth = 640;
48 const int kVEAEncoderMinResolutionHeight = 480;
49 const int kVEAEncoderOutputBufferCount = 4; 49 const int kVEAEncoderOutputBufferCount = 4;
50 50
51 static struct { 51 static struct {
52 VideoTrackRecorder::CodecId codec_id; 52 VideoTrackRecorder::CodecId codec_id;
53 media::VideoCodecProfile min_profile; 53 media::VideoCodecProfile min_profile;
54 media::VideoCodecProfile max_profile; 54 media::VideoCodecProfile max_profile;
55 } const kSupportedVideoCodecIdToProfile[] = { 55 } const kSupportedVideoCodecIdToProfile[] = {
56 {VideoTrackRecorder::CodecId::VP8, 56 {VideoTrackRecorder::CodecId::VP8,
57 media::VP8PROFILE_MIN, 57 media::VP8PROFILE_MIN,
58 media::VP8PROFILE_MAX}, 58 media::VP8PROFILE_MAX},
59 {VideoTrackRecorder::CodecId::VP9, 59 {VideoTrackRecorder::CodecId::VP9,
60 media::VP9PROFILE_MIN, 60 media::VP9PROFILE_MIN,
61 media::VP9PROFILE_MAX}, 61 media::VP9PROFILE_MAX},
62 {VideoTrackRecorder::CodecId::H264, 62 {VideoTrackRecorder::CodecId::H264,
63 media::H264PROFILE_MIN, 63 media::H264PROFILE_MIN,
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 DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth);
408 DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight);
409
410 encoding_task_runner_->PostTask(
411 FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner,
412 this, size));
403 } 413 }
404 414
405 VEAEncoder::~VEAEncoder() { 415 VEAEncoder::~VEAEncoder() {
406 encoding_task_runner_->PostTask( 416 encoding_task_runner_->PostTask(
407 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy, 417 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy,
408 base::Unretained(video_encoder_.release()))); 418 base::Unretained(video_encoder_.release())));
409 } 419 }
410 420
411 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/, 421 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/,
412 const gfx::Size& input_coded_size, 422 const gfx::Size& input_coded_size,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 const scoped_refptr<VideoFrame>& frame, 488 const scoped_refptr<VideoFrame>& frame,
479 base::TimeTicks capture_timestamp) { 489 base::TimeTicks capture_timestamp) {
480 DVLOG(3) << __FUNCTION__; 490 DVLOG(3) << __FUNCTION__;
481 DCHECK(encoding_task_runner_->BelongsToCurrentThread()); 491 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
482 492
483 if (input_size_ != frame->visible_rect().size() && video_encoder_) { 493 if (input_size_ != frame->visible_rect().size() && video_encoder_) {
484 video_encoder_->Destroy(); 494 video_encoder_->Destroy();
485 video_encoder_.reset(); 495 video_encoder_.reset();
486 } 496 }
487 497
488 if (!video_encoder_) { 498 if (!video_encoder_)
489 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); 499 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
490 first_frame_.reset(
491 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
492 frame, capture_timestamp));
493 }
494 500
495 if (error_notified_) { 501 if (error_notified_) {
496 DVLOG(3) << "An error occurred in VEA encoder"; 502 DVLOG(3) << "An error occurred in VEA encoder";
497 return; 503 return;
498 } 504 }
499 505
500 // Drop frames if there is no output buffers available. 506 // Drop frames if there is no output buffers available.
501 if (output_buffers_.empty()) { 507 if (output_buffers_.empty()) {
502 // TODO(emircan): Investigate if resetting encoder would help. 508 // TODO(emircan): Investigate if resetting encoder would help.
503 DVLOG(3) << "Dropped frame."; 509 DVLOG(3) << "Might drop frame.";
510 last_frame_.reset(
511 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
512 frame, capture_timestamp));
504 return; 513 return;
505 } 514 }
506 515
507 // If first frame hasn't been encoded, do it first. 516 // If first frame hasn't been encoded, do it first.
508 if (first_frame_) { 517 if (last_frame_) {
509 std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release()); 518 std::unique_ptr<VideoFrameAndTimestamp> last_frame(last_frame_.release());
510 EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second); 519 EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second);
511 } 520 }
512 521
513 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. 522 // 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. 523 // In that case, the encoder expects more frames before returning result.
515 // Therefore, a copy is necessary to release the current frame. 524 // Therefore, a copy is necessary to release the current frame.
516 scoped_refptr<media::VideoFrame> video_frame = frame; 525 scoped_refptr<media::VideoFrame> video_frame = frame;
517 if (vea_requested_input_size_ != input_size_ || 526 if (vea_requested_input_size_ != input_size_ ||
518 input_size_.width() < kVEAEncoderMinResolutionWidth || 527 input_size_.width() < kVEAEncoderMinResolutionWidth ||
519 input_size_.height() < kVEAEncoderMinResolutionHeight) { 528 input_size_.height() < kVEAEncoderMinResolutionHeight) {
520 // Create SharedMemory backed input buffers as necessary. These SharedMemory 529 // Create SharedMemory backed input buffers as necessary. These SharedMemory
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 } 938 }
930 #endif //#if BUILDFLAG(RTC_USE_H264) 939 #endif //#if BUILDFLAG(RTC_USE_H264)
931 940
932 } // anonymous namespace 941 } // anonymous namespace
933 942
934 VideoTrackRecorder::VideoTrackRecorder( 943 VideoTrackRecorder::VideoTrackRecorder(
935 CodecId codec, 944 CodecId codec,
936 const blink::WebMediaStreamTrack& track, 945 const blink::WebMediaStreamTrack& track,
937 const OnEncodedVideoCB& on_encoded_video_callback, 946 const OnEncodedVideoCB& on_encoded_video_callback,
938 int32_t bits_per_second) 947 int32_t bits_per_second)
939 : track_(track) { 948 : track_(track),
949 paused_before_init_(false),
950 weak_ptr_factory_(this) {
940 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 951 DCHECK(main_render_thread_checker_.CalledOnValidThread());
941 DCHECK(!track_.isNull()); 952 DCHECK(!track_.isNull());
942 DCHECK(track_.getTrackData()); 953 DCHECK(track_.getTrackData());
943 954
955 initialize_encoder_callback_ = base::Bind(
956 &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(),
957 codec, on_encoded_video_callback, bits_per_second);
958
959 // InitializeEncoder() will be called on Render Main thread.
960 MediaStreamVideoSink::ConnectToTrack(
961 track_, media::BindToCurrentLoop(initialize_encoder_callback_), false);
962 }
963
964 VideoTrackRecorder::~VideoTrackRecorder() {
965 DCHECK(main_render_thread_checker_.CalledOnValidThread());
966 MediaStreamVideoSink::DisconnectFromTrack();
967 track_.reset();
968 }
969
970 void VideoTrackRecorder::Pause() {
971 DCHECK(main_render_thread_checker_.CalledOnValidThread());
972 if (encoder_)
973 encoder_->SetPaused(true);
974 else
975 paused_before_init_ = true;
976 }
977
978 void VideoTrackRecorder::Resume() {
979 DCHECK(main_render_thread_checker_.CalledOnValidThread());
980 if (encoder_)
981 encoder_->SetPaused(false);
982 else
983 paused_before_init_ = false;
984 }
985
986 void VideoTrackRecorder::OnVideoFrameForTesting(
987 const scoped_refptr<media::VideoFrame>& frame,
988 base::TimeTicks timestamp) {
989 DVLOG(3) << __FUNCTION__;
990
991 if (!encoder_) {
992 DCHECK(!initialize_encoder_callback_.is_null());
993 initialize_encoder_callback_.Run(frame, timestamp);
994 }
995
996 encoder_->StartFrameEncode(frame, timestamp);
997 }
998
999 void VideoTrackRecorder::InitializeEncoder(
1000 CodecId codec,
1001 const OnEncodedVideoCB& on_encoded_video_callback,
1002 int32_t bits_per_second,
1003 const scoped_refptr<media::VideoFrame>& frame,
1004 base::TimeTicks capture_time) {
1005 DVLOG(3) << __FUNCTION__ << frame->visible_rect().size().ToString();
1006 DCHECK(main_render_thread_checker_.CalledOnValidThread());
1007
1008 MediaStreamVideoSink::DisconnectFromTrack();
1009
1010 const gfx::Size& input_size = frame->visible_rect().size();
944 const auto& vea_supported_profile = CodecIdToVEAProfile(codec); 1011 const auto& vea_supported_profile = CodecIdToVEAProfile(codec);
945 // TODO(emircan): Prioritize software based encoders in lower resolutions. 1012 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN &&
946 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) { 1013 input_size.width() >= kVEAEncoderMinResolutionWidth &&
1014 input_size.height() >= kVEAEncoderMinResolutionHeight) {
947 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, 1015 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
948 vea_supported_profile); 1016 vea_supported_profile, input_size);
949 } else { 1017 } else {
950 switch (codec) { 1018 switch (codec) {
951 #if BUILDFLAG(RTC_USE_H264) 1019 #if BUILDFLAG(RTC_USE_H264)
952 case CodecId::H264: 1020 case CodecId::H264:
953 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second); 1021 encoder_ =
1022 new H264Encoder(on_encoded_video_callback, bits_per_second);
954 break; 1023 break;
955 #endif 1024 #endif
956 case CodecId::VP8: 1025 case CodecId::VP8:
957 case CodecId::VP9: 1026 case CodecId::VP9:
958 encoder_ = new VpxEncoder(codec == CodecId::VP9, 1027 encoder_ = new VpxEncoder(codec == CodecId::VP9,
959 on_encoded_video_callback, bits_per_second); 1028 on_encoded_video_callback, bits_per_second);
960 break; 1029 break;
961 default: 1030 default:
962 NOTREACHED() << "Unsupported codec"; 1031 NOTREACHED() << "Unsupported codec";
963 } 1032 }
964 } 1033 }
965 1034
1035 if (paused_before_init_)
1036 encoder_->SetPaused(paused_before_init_);
1037
966 // StartFrameEncode() will be called on Render IO thread. 1038 // StartFrameEncode() will be called on Render IO thread.
967 MediaStreamVideoSink::ConnectToTrack( 1039 MediaStreamVideoSink::ConnectToTrack(
968 track_, 1040 track_,
969 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), 1041 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_),
970 false); 1042 false);
971 } 1043 }
972 1044
973 VideoTrackRecorder::~VideoTrackRecorder() {
974 DCHECK(main_render_thread_checker_.CalledOnValidThread());
975 MediaStreamVideoSink::DisconnectFromTrack();
976 track_.reset();
977 }
978
979 void VideoTrackRecorder::Pause() {
980 DCHECK(main_render_thread_checker_.CalledOnValidThread());
981 DCHECK(encoder_);
982 encoder_->SetPaused(true);
983 }
984
985 void VideoTrackRecorder::Resume() {
986 DCHECK(main_render_thread_checker_.CalledOnValidThread());
987 DCHECK(encoder_);
988 encoder_->SetPaused(false);
989 }
990
991 void VideoTrackRecorder::OnVideoFrameForTesting(
992 const scoped_refptr<media::VideoFrame>& frame,
993 base::TimeTicks timestamp) {
994 encoder_->StartFrameEncode(frame, timestamp);
995 }
996
997 } // namespace content 1045 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698