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

Unified Diff: media/cast/sender/size_adaptable_video_encoder_base.cc

Issue 906403006: [Cast] Size-Adaptable platform video encoders. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed hubbe's comments. Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/cast/sender/size_adaptable_video_encoder_base.h ('k') | media/cast/sender/video_encoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..96c65a0d505968c669784e13a8f78af897aa716a
--- /dev/null
+++ b/media/cast/sender/size_adaptable_video_encoder_base.cc
@@ -0,0 +1,168 @@
+// 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() {
+ DestroyEncoder();
+}
+
+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 (frames_in_encoder_ == kEncoderIsInitializing) {
+ VLOG(1) << "Dropping frame since encoder initialization is in-progress.";
+ return false;
+ }
+ if (frame_size != frame_size_ || !encoder_) {
+ VLOG(1) << "Dropping this frame, and future frames until a replacement "
+ "encoder is spun-up to handle size " << frame_size.ToString();
+ TrySpawningReplacementEncoder(frame_size);
+ return false;
+ }
+
+ const bool is_frame_accepted = 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 (encoder_)
+ encoder_->SetBitRate(new_bit_rate);
+}
+
+void SizeAdaptableVideoEncoderBase::GenerateKeyFrame() {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ if (encoder_)
+ encoder_->GenerateKeyFrame();
+}
+
+void SizeAdaptableVideoEncoderBase::LatestFrameIdToReference(uint32 frame_id) {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ if (encoder_)
+ 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 (encoder_)
+ 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::DestroyEncoder() {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ // The weak pointers are invalidated to prevent future calls back to |this|.
+ // This effectively cancels any of |encoder_|'s posted tasks that have not yet
+ // run.
+ weak_factory_.InvalidateWeakPtrs();
+ encoder_.reset();
+}
+
+void SizeAdaptableVideoEncoderBase::TrySpawningReplacementEncoder(
+ 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) {
+ encoder_->EmitFrames();
+ // Check again, since EmitFrames() is a synchronous operation for some
+ // encoders.
+ if (frames_in_encoder_ > 0)
+ return;
+ }
+
+ if (frames_in_encoder_ == kEncoderIsInitializing)
+ return; // Already spawned.
+
+ DestroyEncoder();
+ frames_in_encoder_ = kEncoderIsInitializing;
+ OnEncoderStatusChange(STATUS_CODEC_REINIT_PENDING);
+ VLOG(1) << "Creating replacement video encoder (for frame size change from "
+ << frame_size_.ToString() << " to "
+ << size_needed.ToString() << ").";
+ frame_size_ = size_needed;
+ encoder_ = CreateEncoder().Pass();
+ DCHECK(encoder_);
+}
+
+void SizeAdaptableVideoEncoderBase::OnEncoderStatusChange(
+ OperationalStatus status) {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+ if (frames_in_encoder_ == kEncoderIsInitializing &&
+ status == STATUS_INITIALIZED) {
+ // Begin using the replacement encoder.
+ frames_in_encoder_ = 0;
+ OnEncoderReplaced(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
« no previous file with comments | « media/cast/sender/size_adaptable_video_encoder_base.h ('k') | media/cast/sender/video_encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698