Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / cast / sender / size_adaptable_video_encoder_base.cc
blob8c6b0464296fec07d87d675621cdf03c665ad44e
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
3 // found in the LICENSE file.
5 #include "media/cast/sender/size_adaptable_video_encoder_base.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "media/base/video_frame.h"
11 namespace media {
12 namespace cast {
14 SizeAdaptableVideoEncoderBase::SizeAdaptableVideoEncoderBase(
15 const scoped_refptr<CastEnvironment>& cast_environment,
16 const VideoSenderConfig& video_config,
17 const StatusChangeCallback& status_change_cb)
18 : cast_environment_(cast_environment),
19 video_config_(video_config),
20 status_change_cb_(status_change_cb),
21 frames_in_encoder_(0),
22 last_frame_id_(kStartFrameId),
23 weak_factory_(this) {
24 cast_environment_->PostTask(
25 CastEnvironment::MAIN,
26 FROM_HERE,
27 base::Bind(status_change_cb_, STATUS_INITIALIZED));
30 SizeAdaptableVideoEncoderBase::~SizeAdaptableVideoEncoderBase() {
31 DestroyEncoder();
34 bool SizeAdaptableVideoEncoderBase::EncodeVideoFrame(
35 const scoped_refptr<media::VideoFrame>& video_frame,
36 const base::TimeTicks& reference_time,
37 const FrameEncodedCallback& frame_encoded_callback) {
38 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
40 const gfx::Size frame_size = video_frame->visible_rect().size();
41 if (frame_size.IsEmpty()) {
42 DVLOG(1) << "Rejecting empty video frame.";
43 return false;
45 if (frames_in_encoder_ == kEncoderIsInitializing) {
46 VLOG(1) << "Dropping frame since encoder initialization is in-progress.";
47 return false;
49 if (frame_size != frame_size_ || !encoder_) {
50 VLOG(1) << "Dropping this frame, and future frames until a replacement "
51 "encoder is spun-up to handle size " << frame_size.ToString();
52 TrySpawningReplacementEncoder(frame_size);
53 return false;
56 const bool is_frame_accepted = encoder_->EncodeVideoFrame(
57 video_frame,
58 reference_time,
59 base::Bind(&SizeAdaptableVideoEncoderBase::OnEncodedVideoFrame,
60 weak_factory_.GetWeakPtr(),
61 frame_encoded_callback));
62 if (is_frame_accepted)
63 ++frames_in_encoder_;
64 return is_frame_accepted;
67 void SizeAdaptableVideoEncoderBase::SetBitRate(int new_bit_rate) {
68 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
69 video_config_.start_bitrate = new_bit_rate;
70 if (encoder_)
71 encoder_->SetBitRate(new_bit_rate);
74 void SizeAdaptableVideoEncoderBase::GenerateKeyFrame() {
75 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
76 if (encoder_)
77 encoder_->GenerateKeyFrame();
80 void SizeAdaptableVideoEncoderBase::LatestFrameIdToReference(uint32 frame_id) {
81 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
82 if (encoder_)
83 encoder_->LatestFrameIdToReference(frame_id);
86 scoped_ptr<VideoFrameFactory>
87 SizeAdaptableVideoEncoderBase::CreateVideoFrameFactory() {
88 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
89 return nullptr;
92 void SizeAdaptableVideoEncoderBase::EmitFrames() {
93 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
94 if (encoder_)
95 encoder_->EmitFrames();
98 StatusChangeCallback
99 SizeAdaptableVideoEncoderBase::CreateEncoderStatusChangeCallback() {
100 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
101 return base::Bind(&SizeAdaptableVideoEncoderBase::OnEncoderStatusChange,
102 weak_factory_.GetWeakPtr());
105 void SizeAdaptableVideoEncoderBase::OnEncoderReplaced(
106 VideoEncoder* replacement_encoder) {}
108 void SizeAdaptableVideoEncoderBase::DestroyEncoder() {
109 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
110 // The weak pointers are invalidated to prevent future calls back to |this|.
111 // This effectively cancels any of |encoder_|'s posted tasks that have not yet
112 // run.
113 weak_factory_.InvalidateWeakPtrs();
114 encoder_.reset();
117 void SizeAdaptableVideoEncoderBase::TrySpawningReplacementEncoder(
118 const gfx::Size& size_needed) {
119 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
121 // If prior frames are still encoding in the current encoder, let them finish
122 // first.
123 if (frames_in_encoder_ > 0) {
124 encoder_->EmitFrames();
125 // Check again, since EmitFrames() is a synchronous operation for some
126 // encoders.
127 if (frames_in_encoder_ > 0)
128 return;
131 if (frames_in_encoder_ == kEncoderIsInitializing)
132 return; // Already spawned.
134 DestroyEncoder();
135 frames_in_encoder_ = kEncoderIsInitializing;
136 OnEncoderStatusChange(STATUS_CODEC_REINIT_PENDING);
137 VLOG(1) << "Creating replacement video encoder (for frame size change from "
138 << frame_size_.ToString() << " to "
139 << size_needed.ToString() << ").";
140 frame_size_ = size_needed;
141 encoder_ = CreateEncoder().Pass();
142 DCHECK(encoder_);
145 void SizeAdaptableVideoEncoderBase::OnEncoderStatusChange(
146 OperationalStatus status) {
147 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
148 if (frames_in_encoder_ == kEncoderIsInitializing &&
149 status == STATUS_INITIALIZED) {
150 // Begin using the replacement encoder.
151 frames_in_encoder_ = 0;
152 OnEncoderReplaced(encoder_.get());
154 status_change_cb_.Run(status);
157 void SizeAdaptableVideoEncoderBase::OnEncodedVideoFrame(
158 const FrameEncodedCallback& frame_encoded_callback,
159 scoped_ptr<SenderEncodedFrame> encoded_frame) {
160 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
161 --frames_in_encoder_;
162 DCHECK_GE(frames_in_encoder_, 0);
163 last_frame_id_ = encoded_frame->frame_id;
164 frame_encoded_callback.Run(encoded_frame.Pass());
167 } // namespace cast
168 } // namespace media