1// Copyright 2014 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. 4 5#include "media/cast/video_sender/video_encoder_impl.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/callback.h" 10#include "base/logging.h" 11#include "base/message_loop/message_loop.h" 12#include "media/base/video_frame.h" 13#include "media/cast/cast_defines.h" 14#include "media/cast/video_sender/codecs/vp8/vp8_encoder.h" 15#include "media/cast/video_sender/fake_software_video_encoder.h" 16 17namespace media { 18namespace cast { 19 20namespace { 21 22typedef base::Callback<void(Vp8Encoder*)> PassEncoderCallback; 23 24void InitializeEncoderOnEncoderThread( 25 const scoped_refptr<CastEnvironment>& environment, 26 SoftwareVideoEncoder* encoder) { 27 DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO)); 28 encoder->Initialize(); 29} 30 31void EncodeVideoFrameOnEncoderThread( 32 scoped_refptr<CastEnvironment> environment, 33 SoftwareVideoEncoder* encoder, 34 const scoped_refptr<media::VideoFrame>& video_frame, 35 const base::TimeTicks& capture_time, 36 const VideoEncoderImpl::CodecDynamicConfig& dynamic_config, 37 const VideoEncoderImpl::FrameEncodedCallback& frame_encoded_callback) { 38 DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO)); 39 if (dynamic_config.key_frame_requested) { 40 encoder->GenerateKeyFrame(); 41 } 42 encoder->LatestFrameIdToReference( 43 dynamic_config.latest_frame_id_to_reference); 44 encoder->UpdateRates(dynamic_config.bit_rate); 45 46 scoped_ptr<transport::EncodedFrame> encoded_frame( 47 new transport::EncodedFrame()); 48 if (!encoder->Encode(video_frame, encoded_frame.get())) { 49 VLOG(1) << "Encoding failed"; 50 return; 51 } 52 if (encoded_frame->data.empty()) { 53 VLOG(1) << "Encoding resulted in an empty frame"; 54 return; 55 } 56 encoded_frame->rtp_timestamp = transport::GetVideoRtpTimestamp(capture_time); 57 encoded_frame->reference_time = capture_time; 58 59 environment->PostTask( 60 CastEnvironment::MAIN, 61 FROM_HERE, 62 base::Bind( 63 frame_encoded_callback, base::Passed(&encoded_frame))); 64} 65} // namespace 66 67VideoEncoderImpl::VideoEncoderImpl( 68 scoped_refptr<CastEnvironment> cast_environment, 69 const VideoSenderConfig& video_config, 70 int max_unacked_frames) 71 : video_config_(video_config), 72 cast_environment_(cast_environment) { 73 if (video_config.codec == transport::kVp8) { 74 encoder_.reset(new Vp8Encoder(video_config, max_unacked_frames)); 75 cast_environment_->PostTask(CastEnvironment::VIDEO, 76 FROM_HERE, 77 base::Bind(&InitializeEncoderOnEncoderThread, 78 cast_environment, 79 encoder_.get())); 80#ifndef OFFICIAL_BUILD 81 } else if (video_config.codec == transport::kFakeSoftwareVideo) { 82 encoder_.reset(new FakeSoftwareVideoEncoder(video_config)); 83#endif 84 } else { 85 DCHECK(false) << "Invalid config"; // Codec not supported. 86 } 87 88 dynamic_config_.key_frame_requested = false; 89 dynamic_config_.latest_frame_id_to_reference = kStartFrameId; 90 dynamic_config_.bit_rate = video_config.start_bitrate; 91} 92 93VideoEncoderImpl::~VideoEncoderImpl() { 94 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 95 if (encoder_) { 96 cast_environment_->PostTask( 97 CastEnvironment::VIDEO, 98 FROM_HERE, 99 base::Bind(&base::DeletePointer<SoftwareVideoEncoder>, 100 encoder_.release())); 101 } 102} 103 104bool VideoEncoderImpl::EncodeVideoFrame( 105 const scoped_refptr<media::VideoFrame>& video_frame, 106 const base::TimeTicks& capture_time, 107 const FrameEncodedCallback& frame_encoded_callback) { 108 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 109 cast_environment_->PostTask(CastEnvironment::VIDEO, 110 FROM_HERE, 111 base::Bind(&EncodeVideoFrameOnEncoderThread, 112 cast_environment_, 113 encoder_.get(), 114 video_frame, 115 capture_time, 116 dynamic_config_, 117 frame_encoded_callback)); 118 119 dynamic_config_.key_frame_requested = false; 120 return true; 121} 122 123// Inform the encoder about the new target bit rate. 124void VideoEncoderImpl::SetBitRate(int new_bit_rate) { 125 dynamic_config_.bit_rate = new_bit_rate; 126} 127 128// Inform the encoder to encode the next frame as a key frame. 129void VideoEncoderImpl::GenerateKeyFrame() { 130 dynamic_config_.key_frame_requested = true; 131} 132 133// Inform the encoder to only reference frames older or equal to frame_id; 134void VideoEncoderImpl::LatestFrameIdToReference(uint32 frame_id) { 135 dynamic_config_.latest_frame_id_to_reference = frame_id; 136} 137 138} // namespace cast 139} // namespace media 140