| 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/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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |