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"
12 #include "media/cast/sender/video_frame_factory.h"
17 // The LocalVideoFrameInput class posts all incoming video frames to the main
18 // cast thread for processing.
19 class LocalVideoFrameInput
: public VideoFrameInput
{
21 LocalVideoFrameInput(scoped_refptr
<CastEnvironment
> cast_environment
,
22 base::WeakPtr
<VideoSender
> video_sender
,
23 scoped_ptr
<VideoFrameFactory
> video_frame_factory
)
24 : cast_environment_(cast_environment
),
25 video_sender_(video_sender
),
26 video_frame_factory_(video_frame_factory
.Pass()) {}
28 void InsertRawVideoFrame(const scoped_refptr
<media::VideoFrame
>& video_frame
,
29 const base::TimeTicks
& capture_time
) override
{
30 cast_environment_
->PostTask(CastEnvironment::MAIN
,
32 base::Bind(&VideoSender::InsertRawVideoFrame
,
38 scoped_refptr
<VideoFrame
> CreateOptimizedFrame(
39 base::TimeDelta timestamp
) override
{
40 DCHECK(video_frame_factory_
.get());
41 return video_frame_factory_
->CreateFrame(timestamp
);
44 bool SupportsCreateOptimizedFrame() const override
{
45 return video_frame_factory_
.get() != nullptr;
49 ~LocalVideoFrameInput() override
{}
52 friend class base::RefCountedThreadSafe
<LocalVideoFrameInput
>;
54 scoped_refptr
<CastEnvironment
> cast_environment_
;
55 base::WeakPtr
<VideoSender
> video_sender_
;
56 scoped_ptr
<VideoFrameFactory
> video_frame_factory_
;
58 DISALLOW_COPY_AND_ASSIGN(LocalVideoFrameInput
);
61 // The LocalAudioFrameInput class posts all incoming audio frames to the main
62 // cast thread for processing. Therefore frames can be inserted from any thread.
63 class LocalAudioFrameInput
: public AudioFrameInput
{
65 LocalAudioFrameInput(scoped_refptr
<CastEnvironment
> cast_environment
,
66 base::WeakPtr
<AudioSender
> audio_sender
)
67 : cast_environment_(cast_environment
), audio_sender_(audio_sender
) {}
69 void InsertAudio(scoped_ptr
<AudioBus
> audio_bus
,
70 const base::TimeTicks
& recorded_time
) override
{
71 cast_environment_
->PostTask(CastEnvironment::MAIN
,
73 base::Bind(&AudioSender::InsertAudio
,
75 base::Passed(&audio_bus
),
80 ~LocalAudioFrameInput() override
{}
83 friend class base::RefCountedThreadSafe
<LocalAudioFrameInput
>;
85 scoped_refptr
<CastEnvironment
> cast_environment_
;
86 base::WeakPtr
<AudioSender
> audio_sender_
;
88 DISALLOW_COPY_AND_ASSIGN(LocalAudioFrameInput
);
91 scoped_ptr
<CastSender
> CastSender::Create(
92 scoped_refptr
<CastEnvironment
> cast_environment
,
93 CastTransportSender
* const transport_sender
) {
94 CHECK(cast_environment
.get());
95 return scoped_ptr
<CastSender
>(
96 new CastSenderImpl(cast_environment
, transport_sender
));
99 CastSenderImpl::CastSenderImpl(
100 scoped_refptr
<CastEnvironment
> cast_environment
,
101 CastTransportSender
* const transport_sender
)
102 : cast_environment_(cast_environment
),
103 transport_sender_(transport_sender
),
104 weak_factory_(this) {
105 CHECK(cast_environment
.get());
108 void CastSenderImpl::InitializeAudio(
109 const AudioSenderConfig
& audio_config
,
110 const CastInitializationCallback
& cast_initialization_cb
) {
111 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
112 CHECK(audio_config
.use_external_encoder
||
113 cast_environment_
->HasAudioThread());
115 VLOG(1) << "CastSenderImpl@" << this << "::InitializeAudio()";
118 new AudioSender(cast_environment_
, audio_config
, transport_sender_
));
120 const CastInitializationStatus status
= audio_sender_
->InitializationResult();
121 if (status
== STATUS_AUDIO_INITIALIZED
) {
123 new LocalAudioFrameInput(cast_environment_
, audio_sender_
->AsWeakPtr());
125 cast_initialization_cb
.Run(status
);
127 DCHECK(audio_sender_
->GetTargetPlayoutDelay() ==
128 video_sender_
->GetTargetPlayoutDelay());
132 void CastSenderImpl::InitializeVideo(
133 const VideoSenderConfig
& video_config
,
134 const CastInitializationCallback
& cast_initialization_cb
,
135 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
136 const CreateVideoEncodeMemoryCallback
& create_video_encode_mem_cb
) {
137 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
139 VLOG(1) << "CastSenderImpl@" << this << "::InitializeVideo()";
141 video_sender_
.reset(new VideoSender(
144 base::Bind(&CastSenderImpl::OnVideoInitialized
,
145 weak_factory_
.GetWeakPtr(), cast_initialization_cb
),
147 create_video_encode_mem_cb
,
149 base::Bind(&CastSenderImpl::SetTargetPlayoutDelay
,
150 weak_factory_
.GetWeakPtr())));
152 DCHECK(audio_sender_
->GetTargetPlayoutDelay() ==
153 video_sender_
->GetTargetPlayoutDelay());
157 CastSenderImpl::~CastSenderImpl() {
158 VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
161 scoped_refptr
<AudioFrameInput
> CastSenderImpl::audio_frame_input() {
162 return audio_frame_input_
;
165 scoped_refptr
<VideoFrameInput
> CastSenderImpl::video_frame_input() {
166 return video_frame_input_
;
169 void CastSenderImpl::SetTargetPlayoutDelay(
170 base::TimeDelta new_target_playout_delay
) {
171 VLOG(1) << "CastSenderImpl@" << this << "::SetTargetPlayoutDelay("
172 << new_target_playout_delay
.InMilliseconds() << " ms)";
174 audio_sender_
->SetTargetPlayoutDelay(new_target_playout_delay
);
177 video_sender_
->SetTargetPlayoutDelay(new_target_playout_delay
);
181 void CastSenderImpl::OnVideoInitialized(
182 const CastInitializationCallback
& initialization_cb
,
183 media::cast::CastInitializationStatus result
) {
184 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
185 if (result
== STATUS_VIDEO_INITIALIZED
) {
187 new LocalVideoFrameInput(cast_environment_
, video_sender_
->AsWeakPtr(),
188 video_sender_
->CreateVideoFrameFactory());
190 initialization_cb
.Run(result
);