Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / cast / cast_sender_impl.cc
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