Index: media/cast/sender/size_adaptable_video_encoder_base.cc |
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.cc b/media/cast/sender/size_adaptable_video_encoder_base.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a9a46b8283f431f0724fa7efcd0543d43dc76beb |
--- /dev/null |
+++ b/media/cast/sender/size_adaptable_video_encoder_base.cc |
@@ -0,0 +1,162 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/cast/sender/size_adaptable_video_encoder_base.h" |
+ |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "media/base/video_frame.h" |
+ |
+namespace media { |
+namespace cast { |
+ |
+SizeAdaptableVideoEncoderBase::SizeAdaptableVideoEncoderBase( |
+ const scoped_refptr<CastEnvironment>& cast_environment, |
+ const VideoSenderConfig& video_config, |
+ const StatusChangeCallback& status_change_cb) |
+ : cast_environment_(cast_environment), |
+ video_config_(video_config), |
+ status_change_cb_(status_change_cb), |
+ frames_in_encoder_(0), |
+ last_frame_id_(kStartFrameId), |
+ weak_factory_(this) { |
+ cast_environment_->PostTask( |
+ CastEnvironment::MAIN, |
+ FROM_HERE, |
+ base::Bind(status_change_cb_, STATUS_INITIALIZED)); |
+} |
+ |
+SizeAdaptableVideoEncoderBase::~SizeAdaptableVideoEncoderBase() { |
+ weak_factory_.InvalidateWeakPtrs(); |
hubbe
2015/02/11 00:47:54
This is kind of weird.
Why invalidate weak pointer
miu
2015/02/11 02:14:23
Done. Consolidated into DestroyCurrentEncoder(),
|
+ DestroyCurrentEncoder(); |
+} |
+ |
+bool SizeAdaptableVideoEncoderBase::EncodeVideoFrame( |
+ const scoped_refptr<media::VideoFrame>& video_frame, |
+ const base::TimeTicks& reference_time, |
+ const FrameEncodedCallback& frame_encoded_callback) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ |
+ const gfx::Size frame_size = video_frame->visible_rect().size(); |
+ if (frame_size.IsEmpty()) { |
+ DVLOG(1) << "Rejecting empty video frame."; |
+ return false; |
+ } |
+ if (frame_size != current_encoder_frame_size_ || !current_encoder_) { |
+ VLOG(1) << "Dropping frame (of size " << frame_size.ToString() |
+ << ") until a replacement encoder is spun-up. Current encoder " |
+ "handles frames of size " |
+ << current_encoder_frame_size_.ToString() << '.'; |
+ MaybeSpawnReplacementEncoder(frame_size); |
+ return false; |
+ } |
+ |
+ const bool is_frame_accepted = current_encoder_->EncodeVideoFrame( |
+ video_frame, |
+ reference_time, |
+ base::Bind(&SizeAdaptableVideoEncoderBase::OnEncodedVideoFrame, |
+ weak_factory_.GetWeakPtr(), |
+ frame_encoded_callback)); |
+ if (is_frame_accepted) |
+ ++frames_in_encoder_; |
+ return is_frame_accepted; |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::SetBitRate(int new_bit_rate) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ video_config_.start_bitrate = new_bit_rate; |
+ if (current_encoder_) |
+ current_encoder_->SetBitRate(new_bit_rate); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::GenerateKeyFrame() { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ if (current_encoder_) |
+ current_encoder_->GenerateKeyFrame(); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::LatestFrameIdToReference(uint32 frame_id) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ if (current_encoder_) |
+ current_encoder_->LatestFrameIdToReference(frame_id); |
+} |
+ |
+scoped_ptr<VideoFrameFactory> |
+ SizeAdaptableVideoEncoderBase::CreateVideoFrameFactory() { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ return nullptr; |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::EmitFrames() { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ if (current_encoder_) |
+ current_encoder_->EmitFrames(); |
+} |
+ |
+StatusChangeCallback |
+ SizeAdaptableVideoEncoderBase::CreateEncoderStatusChangeCallback() { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ return base::Bind(&SizeAdaptableVideoEncoderBase::OnEncoderStatusChange, |
+ weak_factory_.GetWeakPtr()); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::OnEncoderReplaced( |
+ VideoEncoder* replacement_encoder) {} |
+ |
+void SizeAdaptableVideoEncoderBase::DestroyCurrentEncoder() { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ current_encoder_.reset(); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::MaybeSpawnReplacementEncoder( |
hubbe
2015/02/11 00:47:54
I don't like "Maybe"
I think "Try" or "" would be
miu
2015/02/11 02:14:23
Done.
|
+ const gfx::Size& size_needed) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ |
+ // If prior frames are still encoding in the current encoder, let them finish |
+ // first. |
+ if (frames_in_encoder_ > 0) { |
+ current_encoder_->EmitFrames(); |
+ return; |
+ } |
+ |
+ if (next_encoder_.get()) |
+ return; // Already spawned. |
+ |
+ // Prevent future callbacks from |current_encoder_| and destroy it. |
+ weak_factory_.InvalidateWeakPtrs(); |
+ DestroyCurrentEncoder(); |
+ |
+ OnEncoderStatusChange(STATUS_CODEC_REINIT_PENDING); |
+ next_encoder_frame_size_ = size_needed; |
+ VLOG(1) << "Creating replacement video encoder (for frame size change from " |
+ << current_encoder_frame_size_.ToString() << " to " |
+ << next_encoder_frame_size_.ToString() << ")."; |
+ next_encoder_ = CreateReplacementEncoder().Pass(); |
+ DCHECK(next_encoder_.get()); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::OnEncoderStatusChange( |
+ OperationalStatus status) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ if (next_encoder_.get() && status == STATUS_INITIALIZED) { |
+ // Begin using the replacement encoder. |
+ current_encoder_ = next_encoder_.Pass(); |
+ current_encoder_frame_size_ = next_encoder_frame_size_; |
+ OnEncoderReplaced(current_encoder_.get()); |
+ } |
+ status_change_cb_.Run(status); |
+} |
+ |
+void SizeAdaptableVideoEncoderBase::OnEncodedVideoFrame( |
+ const FrameEncodedCallback& frame_encoded_callback, |
+ scoped_ptr<EncodedFrame> encoded_frame) { |
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
+ --frames_in_encoder_; |
+ DCHECK_GE(frames_in_encoder_, 0); |
+ last_frame_id_ = encoded_frame->frame_id; |
+ frame_encoded_callback.Run(encoded_frame.Pass()); |
+} |
+ |
+} // namespace cast |
+} // namespace media |