Home | History | Annotate | Download | only in cast
      1 // Copyright 2013 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/cast_sender_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "media/base/video_frame.h"
     12 
     13 namespace media {
     14 namespace cast {
     15 
     16 // The LocalVideoFrameInput class posts all incoming video frames to the main
     17 // cast thread for processing.
     18 class LocalVideoFrameInput : public VideoFrameInput {
     19  public:
     20   LocalVideoFrameInput(scoped_refptr<CastEnvironment> cast_environment,
     21                        base::WeakPtr<VideoSender> video_sender)
     22       : cast_environment_(cast_environment), video_sender_(video_sender) {}
     23 
     24   virtual void InsertRawVideoFrame(
     25       const scoped_refptr<media::VideoFrame>& video_frame,
     26       const base::TimeTicks& capture_time) OVERRIDE {
     27     cast_environment_->PostTask(CastEnvironment::MAIN,
     28                                 FROM_HERE,
     29                                 base::Bind(&VideoSender::InsertRawVideoFrame,
     30                                            video_sender_,
     31                                            video_frame,
     32                                            capture_time));
     33   }
     34 
     35  protected:
     36   virtual ~LocalVideoFrameInput() {}
     37 
     38  private:
     39   friend class base::RefCountedThreadSafe<LocalVideoFrameInput>;
     40 
     41   scoped_refptr<CastEnvironment> cast_environment_;
     42   base::WeakPtr<VideoSender> video_sender_;
     43 
     44   DISALLOW_COPY_AND_ASSIGN(LocalVideoFrameInput);
     45 };
     46 
     47 // The LocalAudioFrameInput class posts all incoming audio frames to the main
     48 // cast thread for processing. Therefore frames can be inserted from any thread.
     49 class LocalAudioFrameInput : public AudioFrameInput {
     50  public:
     51   LocalAudioFrameInput(scoped_refptr<CastEnvironment> cast_environment,
     52                        base::WeakPtr<AudioSender> audio_sender)
     53       : cast_environment_(cast_environment), audio_sender_(audio_sender) {}
     54 
     55   virtual void InsertAudio(scoped_ptr<AudioBus> audio_bus,
     56                            const base::TimeTicks& recorded_time) OVERRIDE {
     57     cast_environment_->PostTask(CastEnvironment::MAIN,
     58                                 FROM_HERE,
     59                                 base::Bind(&AudioSender::InsertAudio,
     60                                            audio_sender_,
     61                                            base::Passed(&audio_bus),
     62                                            recorded_time));
     63   }
     64 
     65  protected:
     66   virtual ~LocalAudioFrameInput() {}
     67 
     68  private:
     69   friend class base::RefCountedThreadSafe<LocalAudioFrameInput>;
     70 
     71   scoped_refptr<CastEnvironment> cast_environment_;
     72   base::WeakPtr<AudioSender> audio_sender_;
     73 
     74   DISALLOW_COPY_AND_ASSIGN(LocalAudioFrameInput);
     75 };
     76 
     77 scoped_ptr<CastSender> CastSender::Create(
     78     scoped_refptr<CastEnvironment> cast_environment,
     79     CastTransportSender* const transport_sender) {
     80   CHECK(cast_environment.get());
     81   return scoped_ptr<CastSender>(
     82       new CastSenderImpl(cast_environment, transport_sender));
     83 }
     84 
     85 CastSenderImpl::CastSenderImpl(
     86     scoped_refptr<CastEnvironment> cast_environment,
     87     CastTransportSender* const transport_sender)
     88     : cast_environment_(cast_environment),
     89       transport_sender_(transport_sender),
     90       weak_factory_(this) {
     91   CHECK(cast_environment.get());
     92 }
     93 
     94 void CastSenderImpl::InitializeAudio(
     95     const AudioSenderConfig& audio_config,
     96     const CastInitializationCallback& cast_initialization_cb) {
     97   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
     98   CHECK(audio_config.use_external_encoder ||
     99         cast_environment_->HasAudioThread());
    100 
    101   VLOG(1) << "CastSenderImpl@" << this << "::InitializeAudio()";
    102 
    103   audio_sender_.reset(
    104       new AudioSender(cast_environment_, audio_config, transport_sender_));
    105 
    106   const CastInitializationStatus status = audio_sender_->InitializationResult();
    107   if (status == STATUS_AUDIO_INITIALIZED) {
    108     audio_frame_input_ =
    109         new LocalAudioFrameInput(cast_environment_, audio_sender_->AsWeakPtr());
    110   }
    111   cast_initialization_cb.Run(status);
    112   if (video_sender_) {
    113     DCHECK(audio_sender_->GetTargetPlayoutDelay() ==
    114            video_sender_->GetTargetPlayoutDelay());
    115   }
    116 }
    117 
    118 void CastSenderImpl::InitializeVideo(
    119     const VideoSenderConfig& video_config,
    120     const CastInitializationCallback& cast_initialization_cb,
    121     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
    122     const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
    123   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
    124   CHECK(video_config.use_external_encoder ||
    125         cast_environment_->HasVideoThread());
    126 
    127   VLOG(1) << "CastSenderImpl@" << this << "::InitializeVideo()";
    128 
    129   video_sender_.reset(new VideoSender(
    130       cast_environment_,
    131       video_config,
    132       base::Bind(&CastSenderImpl::OnVideoInitialized,
    133                  weak_factory_.GetWeakPtr(), cast_initialization_cb),
    134       create_vea_cb,
    135       create_video_encode_mem_cb,
    136       transport_sender_,
    137       base::Bind(&CastSenderImpl::SetTargetPlayoutDelay,
    138                  weak_factory_.GetWeakPtr())));
    139   if (audio_sender_) {
    140     DCHECK(audio_sender_->GetTargetPlayoutDelay() ==
    141            video_sender_->GetTargetPlayoutDelay());
    142   }
    143 }
    144 
    145 CastSenderImpl::~CastSenderImpl() {
    146   VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
    147 }
    148 
    149 scoped_refptr<AudioFrameInput> CastSenderImpl::audio_frame_input() {
    150   return audio_frame_input_;
    151 }
    152 
    153 scoped_refptr<VideoFrameInput> CastSenderImpl::video_frame_input() {
    154   return video_frame_input_;
    155 }
    156 
    157 void CastSenderImpl::SetTargetPlayoutDelay(
    158     base::TimeDelta new_target_playout_delay) {
    159   VLOG(1) << "CastSenderImpl@" << this << "::SetTargetPlayoutDelay("
    160           << new_target_playout_delay.InMilliseconds() << " ms)";
    161   if (audio_sender_) {
    162     audio_sender_->SetTargetPlayoutDelay(new_target_playout_delay);
    163   }
    164   if (video_sender_) {
    165     video_sender_->SetTargetPlayoutDelay(new_target_playout_delay);
    166   }
    167 }
    168 
    169 void CastSenderImpl::OnVideoInitialized(
    170     const CastInitializationCallback& initialization_cb,
    171     media::cast::CastInitializationStatus result) {
    172   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
    173   video_frame_input_ =
    174       new LocalVideoFrameInput(cast_environment_, video_sender_->AsWeakPtr());
    175   initialization_cb.Run(result);
    176 }
    177 
    178 }  // namespace cast
    179 }  // namespace media
    180