Chromium Code Reviews| Index: content/renderer/media/video_track_recorder.cc |
| diff --git a/content/renderer/media/video_track_recorder.cc b/content/renderer/media/video_track_recorder.cc |
| index d65e238e8795e5d07b6ffcba163d6c135fb684c0..5e9b22e6466537e779b5a2b8a63b5886343a077e 100644 |
| --- a/content/renderer/media/video_track_recorder.cc |
| +++ b/content/renderer/media/video_track_recorder.cc |
| @@ -71,13 +71,15 @@ media::VideoCodecProfile CodecIdToVEAProfile( |
| #if defined(OS_CHROMEOS) |
| return media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| #endif // defined(OS_CHROMEOS) |
| - content::RenderThreadImpl* render_thread_impl = |
| + content::RenderThreadImpl* const render_thread_impl = |
| content::RenderThreadImpl::current(); |
| - if (!render_thread_impl) |
| + if (!render_thread_impl) { |
| + DVLOG(3) << "Couldn't access the render thread"; |
| return media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| + } |
| - media::GpuVideoAcceleratorFactories* gpu_factories = |
| - content::RenderThreadImpl::current()->GetGpuFactories(); |
| + media::GpuVideoAcceleratorFactories* const gpu_factories = |
| + render_thread_impl->GetGpuFactories(); |
| if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { |
| DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories"; |
| return media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| @@ -250,7 +252,8 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder, |
| VEAEncoder( |
| const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| int32_t bits_per_second, |
| - media::VideoCodecProfile codec); |
| + media::VideoCodecProfile codec, |
| + const gfx::Size& size); |
| // media::VideoEncodeAccelerator::Client implementation. |
| void RequireBitstreamBuffers(unsigned int input_count, |
| @@ -291,8 +294,8 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder, |
| // Tracks error status. |
| bool error_notified_; |
| - // Tracks the first frame to encode. |
| - std::unique_ptr<VideoFrameAndTimestamp> first_frame_; |
| + // Tracks the last frame that we delay the encode. |
| + std::unique_ptr<VideoFrameAndTimestamp> last_frame_; |
| // Size used to initialize encoder. |
| gfx::Size input_size_; |
| @@ -392,7 +395,8 @@ class H264Encoder final : public VideoTrackRecorder::Encoder { |
| VEAEncoder::VEAEncoder( |
| const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| int32_t bits_per_second, |
| - media::VideoCodecProfile codec) |
| + media::VideoCodecProfile codec, |
| + const gfx::Size& size) |
| : Encoder(on_encoded_video_callback, |
| bits_per_second, |
| RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), |
| @@ -400,6 +404,10 @@ VEAEncoder::VEAEncoder( |
| codec_(codec), |
| error_notified_(false) { |
| DCHECK(gpu_factories_); |
| + |
|
mcasas
2016/07/08 22:59:27
DCHECK_GE(size.width(), kVEAEncoderMinResolutionWi
emircan
2016/07/12 01:00:35
Done.
|
| + encoding_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, |
| + this, size)); |
| } |
| VEAEncoder::~VEAEncoder() { |
| @@ -485,12 +493,8 @@ void VEAEncoder::EncodeOnEncodingTaskRunner( |
| video_encoder_.reset(); |
| } |
| - if (!video_encoder_) { |
| + if (!video_encoder_) |
| ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); |
| - first_frame_.reset( |
| - new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>( |
| - frame, capture_timestamp)); |
| - } |
| if (error_notified_) { |
| DVLOG(3) << "An error occurred in VEA encoder"; |
| @@ -500,14 +504,17 @@ void VEAEncoder::EncodeOnEncodingTaskRunner( |
| // Drop frames if there is no output buffers available. |
| if (output_buffers_.empty()) { |
| // TODO(emircan): Investigate if resetting encoder would help. |
| - DVLOG(3) << "Dropped frame."; |
| + DVLOG(3) << "Might drop frame."; |
| + last_frame_.reset( |
| + new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>( |
| + frame, capture_timestamp)); |
| return; |
| } |
| // If first frame hasn't been encoded, do it first. |
| - if (first_frame_) { |
| - std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release()); |
| - EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second); |
| + if (last_frame_) { |
| + std::unique_ptr<VideoFrameAndTimestamp> last_frame(last_frame_.release()); |
| + EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second); |
| } |
| // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. |
| @@ -936,37 +943,23 @@ VideoTrackRecorder::VideoTrackRecorder( |
| const blink::WebMediaStreamTrack& track, |
| const OnEncodedVideoCB& on_encoded_video_callback, |
| int32_t bits_per_second) |
| - : track_(track) { |
| + : track_(track), |
| + codec_(codec), |
| + on_encoded_video_callback_(on_encoded_video_callback), |
| + bits_per_second_(bits_per_second), |
| + paused_before_init_(false), |
| + weak_ptr_factory_(this) { |
| DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| DCHECK(!track_.isNull()); |
| DCHECK(track_.getTrackData()); |
| - const auto& vea_supported_profile = CodecIdToVEAProfile(codec); |
| - // TODO(emircan): Prioritize software based encoders in lower resolutions. |
| - if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) { |
| - encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, |
| - vea_supported_profile); |
| - } else { |
| - switch (codec) { |
| -#if BUILDFLAG(RTC_USE_H264) |
| - case CodecId::H264: |
| - encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second); |
| - break; |
| -#endif |
| - case CodecId::VP8: |
| - case CodecId::VP9: |
| - encoder_ = new VpxEncoder(codec == CodecId::VP9, |
| - on_encoded_video_callback, bits_per_second); |
| - break; |
| - default: |
| - NOTREACHED() << "Unsupported codec"; |
| - } |
| - } |
| - |
| - // StartFrameEncode() will be called on Render IO thread. |
| + // InitializeEncoder() will be called on Render Main thread. |
| + // It is safe to use Unretained, because the class gets disconnected from |
| + // track in dtor. |
| MediaStreamVideoSink::ConnectToTrack( |
| track_, |
| - base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| + media::BindToCurrentLoop(base::Bind( |
| + &VideoTrackRecorder::InitializeEncoder, base::Unretained(this))), |
| false); |
| } |
| @@ -978,20 +971,73 @@ VideoTrackRecorder::~VideoTrackRecorder() { |
| void VideoTrackRecorder::Pause() { |
| DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| - DCHECK(encoder_); |
| - encoder_->SetPaused(true); |
| + if (encoder_) |
| + encoder_->SetPaused(true); |
| + else |
| + paused_before_init_ = true; |
| } |
| void VideoTrackRecorder::Resume() { |
| DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| - DCHECK(encoder_); |
| - encoder_->SetPaused(false); |
| + if (encoder_) |
| + encoder_->SetPaused(false); |
| + else |
| + paused_before_init_ = false; |
| } |
| void VideoTrackRecorder::OnVideoFrameForTesting( |
| const scoped_refptr<media::VideoFrame>& frame, |
| base::TimeTicks timestamp) { |
| + DVLOG(3) << __FUNCTION__; |
| + |
| + if (!encoder_) |
| + InitializeEncoder(frame, timestamp); |
| + |
| encoder_->StartFrameEncode(frame, timestamp); |
| } |
| + |
| +void VideoTrackRecorder::InitializeEncoder( |
| + const scoped_refptr<media::VideoFrame>& frame, |
| + base::TimeTicks capture_time) { |
| + DVLOG(3) << __FUNCTION__ << frame->visible_rect().size().ToString(); |
| + DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| + |
| + MediaStreamVideoSink::DisconnectFromTrack(); |
| + |
| + const gfx::Size& input_size = frame->visible_rect().size(); |
| + const auto& vea_supported_profile = CodecIdToVEAProfile(codec_); |
| + if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && |
| + input_size.width() >= kVEAEncoderMinResolutionWidth && |
| + input_size.height() >= kVEAEncoderMinResolutionHeight) { |
| + encoder_ = new VEAEncoder(on_encoded_video_callback_, bits_per_second_, |
| + vea_supported_profile, input_size); |
| + } else { |
| + switch (codec_) { |
| +#if BUILDFLAG(RTC_USE_H264) |
| + case CodecId::H264: |
| + encoder_ = |
| + new H264Encoder(on_encoded_video_callback_, bits_per_second_); |
| + break; |
| +#endif |
| + case CodecId::VP8: |
| + case CodecId::VP9: |
| + encoder_ = new VpxEncoder(codec_ == CodecId::VP9, |
| + on_encoded_video_callback_, bits_per_second_); |
| + break; |
| + default: |
| + NOTREACHED() << "Unsupported codec"; |
| + } |
| + } |
| + |
| + if (paused_before_init_) |
| + encoder_->SetPaused(paused_before_init_); |
| + |
| + // StartFrameEncode() will be called on Render IO thread. |
| + MediaStreamVideoSink::ConnectToTrack( |
| + track_, |
| + base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), |
| + false); |
| +} |
| + |
| } // namespace content |