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.
5 #include "media/cast/cast_sender_impl.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"
16 // The LocalVideoFrameInput class posts all incoming video frames to the main
17 // cast thread for processing.
18 class LocalVideoFrameInput
: public VideoFrameInput
{
20 LocalVideoFrameInput(scoped_refptr
<CastEnvironment
> cast_environment
,
21 base::WeakPtr
<VideoSender
> video_sender
)
22 : cast_environment_(cast_environment
), video_sender_(video_sender
) {}
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
,
29 base::Bind(&VideoSender::InsertRawVideoFrame
,
36 virtual ~LocalVideoFrameInput() {}
39 friend class base::RefCountedThreadSafe
<LocalVideoFrameInput
>;
41 scoped_refptr
<CastEnvironment
> cast_environment_
;
42 base::WeakPtr
<VideoSender
> video_sender_
;
44 DISALLOW_COPY_AND_ASSIGN(LocalVideoFrameInput
);
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
{
51 LocalAudioFrameInput(scoped_refptr
<CastEnvironment
> cast_environment
,
52 base::WeakPtr
<AudioSender
> audio_sender
)
53 : cast_environment_(cast_environment
), audio_sender_(audio_sender
) {}
55 virtual void InsertAudio(scoped_ptr
<AudioBus
> audio_bus
,
56 const base::TimeTicks
& recorded_time
) OVERRIDE
{
57 cast_environment_
->PostTask(CastEnvironment::MAIN
,
59 base::Bind(&AudioSender::InsertAudio
,
61 base::Passed(&audio_bus
),
66 virtual ~LocalAudioFrameInput() {}
69 friend class base::RefCountedThreadSafe
<LocalAudioFrameInput
>;
71 scoped_refptr
<CastEnvironment
> cast_environment_
;
72 base::WeakPtr
<AudioSender
> audio_sender_
;
74 DISALLOW_COPY_AND_ASSIGN(LocalAudioFrameInput
);
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
));
85 CastSenderImpl::CastSenderImpl(
86 scoped_refptr
<CastEnvironment
> cast_environment
,
87 CastTransportSender
* const transport_sender
)
88 : cast_environment_(cast_environment
),
89 transport_sender_(transport_sender
),
91 CHECK(cast_environment
.get());
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());
101 VLOG(1) << "CastSenderImpl@" << this << "::InitializeAudio()";
104 new AudioSender(cast_environment_
, audio_config
, transport_sender_
));
106 const CastInitializationStatus status
= audio_sender_
->InitializationResult();
107 if (status
== STATUS_AUDIO_INITIALIZED
) {
108 ssrc_of_audio_sender_
= audio_config
.incoming_feedback_ssrc
;
110 new LocalAudioFrameInput(cast_environment_
, audio_sender_
->AsWeakPtr());
112 cast_initialization_cb
.Run(status
);
114 DCHECK(audio_sender_
->GetTargetPlayoutDelay() ==
115 video_sender_
->GetTargetPlayoutDelay());
119 void CastSenderImpl::InitializeVideo(
120 const VideoSenderConfig
& video_config
,
121 const CastInitializationCallback
& cast_initialization_cb
,
122 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
123 const CreateVideoEncodeMemoryCallback
& create_video_encode_mem_cb
) {
124 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
125 CHECK(video_config
.use_external_encoder
||
126 cast_environment_
->HasVideoThread());
128 VLOG(1) << "CastSenderImpl@" << this << "::InitializeVideo()";
130 video_sender_
.reset(new VideoSender(cast_environment_
,
133 create_video_encode_mem_cb
,
136 const CastInitializationStatus status
= video_sender_
->InitializationResult();
137 if (status
== STATUS_VIDEO_INITIALIZED
) {
138 ssrc_of_video_sender_
= video_config
.incoming_feedback_ssrc
;
140 new LocalVideoFrameInput(cast_environment_
, video_sender_
->AsWeakPtr());
142 cast_initialization_cb
.Run(status
);
144 DCHECK(audio_sender_
->GetTargetPlayoutDelay() ==
145 video_sender_
->GetTargetPlayoutDelay());
149 CastSenderImpl::~CastSenderImpl() {
150 VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
153 scoped_refptr
<AudioFrameInput
> CastSenderImpl::audio_frame_input() {
154 return audio_frame_input_
;
157 scoped_refptr
<VideoFrameInput
> CastSenderImpl::video_frame_input() {
158 return video_frame_input_
;
161 void CastSenderImpl::SetTargetPlayoutDelay(
162 base::TimeDelta new_target_playout_delay
) {
163 VLOG(1) << "CastSenderImpl@" << this << "::SetTargetPlayoutDelay("
164 << new_target_playout_delay
.InMilliseconds() << " ms)";
166 audio_sender_
->SetTargetPlayoutDelay(new_target_playout_delay
);
169 video_sender_
->SetTargetPlayoutDelay(new_target_playout_delay
);