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 #include "media/cast/cast_sender_impl.h"
7 #include "base/callback.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/base/video_frame.h"
15 // The LocalFrameInput class posts all incoming frames; audio and video to the
16 // main cast thread for processing.
17 // This make the cast sender interface thread safe.
18 class LocalFrameInput
: public FrameInput
{
20 LocalFrameInput(scoped_refptr
<CastEnvironment
> cast_environment
,
21 base::WeakPtr
<AudioSender
> audio_sender
,
22 base::WeakPtr
<VideoSender
> video_sender
)
23 : cast_environment_(cast_environment
),
24 audio_sender_(audio_sender
),
25 video_sender_(video_sender
) {}
27 virtual void InsertRawVideoFrame(
28 const scoped_refptr
<media::VideoFrame
>& video_frame
,
29 const base::TimeTicks
& capture_time
) OVERRIDE
{
30 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
31 base::Bind(&VideoSender::InsertRawVideoFrame
, video_sender_
,
32 video_frame
, capture_time
));
35 virtual void InsertAudio(const AudioBus
* audio_bus
,
36 const base::TimeTicks
& recorded_time
,
37 const base::Closure
& done_callback
) OVERRIDE
{
38 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
39 base::Bind(&AudioSender::InsertAudio
, audio_sender_
,
40 audio_bus
, recorded_time
, done_callback
));
43 virtual void InsertCodedAudioFrame(
44 const transport::EncodedAudioFrame
* audio_frame
,
45 const base::TimeTicks
& recorded_time
,
46 const base::Closure callback
) OVERRIDE
{
47 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
48 base::Bind(&AudioSender::InsertCodedAudioFrame
, audio_sender_
,
49 audio_frame
, recorded_time
, callback
));
53 virtual ~LocalFrameInput() {}
56 friend class base::RefCountedThreadSafe
<LocalFrameInput
>;
58 scoped_refptr
<CastEnvironment
> cast_environment_
;
59 base::WeakPtr
<AudioSender
> audio_sender_
;
60 base::WeakPtr
<VideoSender
> video_sender_
;
63 // LocalCastSenderPacketReceiver handle the incoming packets to the cast sender
64 // it's only expected to receive RTCP feedback packets from the remote cast
65 // receiver. The class verifies that that it is a RTCP packet and based on the
66 // SSRC of the incoming packet route the packet to the correct sender; audio or
69 // Definition of SSRC as defined in RFC 3550.
70 // Synchronization source (SSRC): The source of a stream of RTP
71 // packets, identified by a 32-bit numeric SSRC identifier carried in
72 // the RTP header so as not to be dependent upon the network address.
73 // All packets from a synchronization source form part of the same
74 // timing and sequence number space, so a receiver groups packets by
75 // synchronization source for playback. Examples of synchronization
76 // sources include the sender of a stream of packets derived from a
77 // signal source such as a microphone or a camera, or an RTP mixer
78 // (see below). A synchronization source may change its data format,
79 // e.g., audio encoding, over time. The SSRC identifier is a
80 // randomly chosen value meant to be globally unique within a
81 // particular RTP session (see Section 8). A participant need not
82 // use the same SSRC identifier for all the RTP sessions in a
83 // multimedia session; the binding of the SSRC identifiers is
84 // provided through RTCP (see Section 6.5.1). If a participant
85 // generates multiple streams in one RTP session, for example from
86 // separate video cameras, each MUST be identified as a different
89 class LocalCastSenderPacketReceiver
: public transport::PacketReceiver
{
91 LocalCastSenderPacketReceiver(scoped_refptr
<CastEnvironment
> cast_environment
,
92 base::WeakPtr
<AudioSender
> audio_sender
,
93 base::WeakPtr
<VideoSender
> video_sender
,
94 uint32 ssrc_of_audio_sender
,
95 uint32 ssrc_of_video_sender
)
96 : cast_environment_(cast_environment
),
97 audio_sender_(audio_sender
),
98 video_sender_(video_sender
),
99 ssrc_of_audio_sender_(ssrc_of_audio_sender
),
100 ssrc_of_video_sender_(ssrc_of_video_sender
) {}
102 virtual void ReceivedPacket(const uint8
* packet
,
104 const base::Closure callback
) OVERRIDE
{
105 if (!Rtcp::IsRtcpPacket(packet
, length
)) {
106 // We should have no incoming RTP packets.
107 // No action; just log and call the callback informing that we are done
109 VLOG(1) << "Unexpectedly received a RTP packet in the cast sender";
110 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
, callback
);
113 uint32 ssrc_of_sender
= Rtcp::GetSsrcOfSender(packet
, length
);
114 if (ssrc_of_sender
== ssrc_of_audio_sender_
) {
115 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
116 base::Bind(&AudioSender::IncomingRtcpPacket
, audio_sender_
,
117 packet
, length
, callback
));
118 } else if (ssrc_of_sender
== ssrc_of_video_sender_
) {
119 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
120 base::Bind(&VideoSender::IncomingRtcpPacket
, video_sender_
,
121 packet
, length
, callback
));
123 // No action; just log and call the callback informing that we are done
125 VLOG(1) << "Received a RTCP packet with a non matching sender SSRC "
128 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
, callback
);
133 virtual ~LocalCastSenderPacketReceiver() {}
136 friend class base::RefCountedThreadSafe
<LocalCastSenderPacketReceiver
>;
138 scoped_refptr
<CastEnvironment
> cast_environment_
;
139 base::WeakPtr
<AudioSender
> audio_sender_
;
140 base::WeakPtr
<VideoSender
> video_sender_
;
141 const uint32 ssrc_of_audio_sender_
;
142 const uint32 ssrc_of_video_sender_
;
145 CastSender
* CastSender::CreateCastSender(
146 scoped_refptr
<CastEnvironment
> cast_environment
,
147 const AudioSenderConfig
& audio_config
,
148 const VideoSenderConfig
& video_config
,
149 const scoped_refptr
<GpuVideoAcceleratorFactories
>& gpu_factories
,
150 PacketSender
* const packet_sender
) {
151 return new CastSenderImpl(cast_environment
, audio_config
, video_config
,
152 gpu_factories
, packet_sender
);
155 CastSenderImpl::CastSenderImpl(
156 scoped_refptr
<CastEnvironment
> cast_environment
,
157 const AudioSenderConfig
& audio_config
,
158 const VideoSenderConfig
& video_config
,
159 const scoped_refptr
<GpuVideoAcceleratorFactories
>& gpu_factories
,
160 PacketSender
* const packet_sender
)
161 : pacer_(cast_environment
->Clock(), packet_sender
,
162 cast_environment
->GetMessageTaskRunnerForThread(
163 CastEnvironment::TRANSPORT
)),
164 audio_sender_(cast_environment
, audio_config
, &pacer_
),
165 video_sender_(cast_environment
, video_config
, gpu_factories
, &pacer_
),
166 frame_input_(new LocalFrameInput(cast_environment
,
167 audio_sender_
.AsWeakPtr(),
168 video_sender_
.AsWeakPtr())),
169 packet_receiver_(new LocalCastSenderPacketReceiver(cast_environment
,
170 audio_sender_
.AsWeakPtr(), video_sender_
.AsWeakPtr(),
171 audio_config
.incoming_feedback_ssrc
,
172 video_config
.incoming_feedback_ssrc
)) {}
174 CastSenderImpl::~CastSenderImpl() {}
176 scoped_refptr
<FrameInput
> CastSenderImpl::frame_input() {
180 scoped_refptr
<transport::PacketReceiver
> CastSenderImpl::packet_receiver() {
181 return packet_receiver_
;