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"
5
6 #include "base/bind.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"
11
12 namespace media {
13 namespace cast {
14
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 {
19 public:
LocalFrameInput(scoped_refptr<CastEnvironment> cast_environment,base::WeakPtr<AudioSender> audio_sender,base::WeakPtr<VideoSender> video_sender)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) {}
26
InsertRawVideoFrame(const scoped_refptr<media::VideoFrame> & video_frame,const base::TimeTicks & capture_time)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));
33 }
34
InsertCodedVideoFrame(const EncodedVideoFrame * video_frame,const base::TimeTicks & capture_time,const base::Closure callback)35 virtual void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame,
36 const base::TimeTicks& capture_time,
37 const base::Closure callback) OVERRIDE {
38 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
39 base::Bind(&VideoSender::InsertCodedVideoFrame, video_sender_,
40 video_frame, capture_time, callback));
41 }
42
InsertAudio(const AudioBus * audio_bus,const base::TimeTicks & recorded_time,const base::Closure & done_callback)43 virtual void InsertAudio(const AudioBus* audio_bus,
44 const base::TimeTicks& recorded_time,
45 const base::Closure& done_callback) OVERRIDE {
46 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
47 base::Bind(&AudioSender::InsertAudio, audio_sender_,
48 audio_bus, recorded_time, done_callback));
49 }
50
InsertCodedAudioFrame(const EncodedAudioFrame * audio_frame,const base::TimeTicks & recorded_time,const base::Closure callback)51 virtual void InsertCodedAudioFrame(const EncodedAudioFrame* audio_frame,
52 const base::TimeTicks& recorded_time,
53 const base::Closure callback) OVERRIDE {
54 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
55 base::Bind(&AudioSender::InsertCodedAudioFrame, audio_sender_,
56 audio_frame, recorded_time, callback));
57 }
58
59 protected:
~LocalFrameInput()60 virtual ~LocalFrameInput() {}
61
62 private:
63 friend class base::RefCountedThreadSafe<LocalFrameInput>;
64
65 scoped_refptr<CastEnvironment> cast_environment_;
66 base::WeakPtr<AudioSender> audio_sender_;
67 base::WeakPtr<VideoSender> video_sender_;
68 };
69
70 // LocalCastSenderPacketReceiver handle the incoming packets to the cast sender
71 // it's only expected to receive RTCP feedback packets from the remote cast
72 // receiver. The class verifies that that it is a RTCP packet and based on the
73 // SSRC of the incoming packet route the packet to the correct sender; audio or
74 // video.
75 //
76 // Definition of SSRC as defined in RFC 3550.
77 // Synchronization source (SSRC): The source of a stream of RTP
78 // packets, identified by a 32-bit numeric SSRC identifier carried in
79 // the RTP header so as not to be dependent upon the network address.
80 // All packets from a synchronization source form part of the same
81 // timing and sequence number space, so a receiver groups packets by
82 // synchronization source for playback. Examples of synchronization
83 // sources include the sender of a stream of packets derived from a
84 // signal source such as a microphone or a camera, or an RTP mixer
85 // (see below). A synchronization source may change its data format,
86 // e.g., audio encoding, over time. The SSRC identifier is a
87 // randomly chosen value meant to be globally unique within a
88 // particular RTP session (see Section 8). A participant need not
89 // use the same SSRC identifier for all the RTP sessions in a
90 // multimedia session; the binding of the SSRC identifiers is
91 // provided through RTCP (see Section 6.5.1). If a participant
92 // generates multiple streams in one RTP session, for example from
93 // separate video cameras, each MUST be identified as a different
94 // SSRC.
95
96 class LocalCastSenderPacketReceiver : public PacketReceiver {
97 public:
LocalCastSenderPacketReceiver(scoped_refptr<CastEnvironment> cast_environment,base::WeakPtr<AudioSender> audio_sender,base::WeakPtr<VideoSender> video_sender,uint32 ssrc_of_audio_sender,uint32 ssrc_of_video_sender)98 LocalCastSenderPacketReceiver(scoped_refptr<CastEnvironment> cast_environment,
99 base::WeakPtr<AudioSender> audio_sender,
100 base::WeakPtr<VideoSender> video_sender,
101 uint32 ssrc_of_audio_sender,
102 uint32 ssrc_of_video_sender)
103 : cast_environment_(cast_environment),
104 audio_sender_(audio_sender),
105 video_sender_(video_sender),
106 ssrc_of_audio_sender_(ssrc_of_audio_sender),
107 ssrc_of_video_sender_(ssrc_of_video_sender) {}
108
ReceivedPacket(const uint8 * packet,size_t length,const base::Closure callback)109 virtual void ReceivedPacket(const uint8* packet,
110 size_t length,
111 const base::Closure callback) OVERRIDE {
112 if (!Rtcp::IsRtcpPacket(packet, length)) {
113 // We should have no incoming RTP packets.
114 // No action; just log and call the callback informing that we are done
115 // with the packet.
116 VLOG(1) << "Unexpectedly received a RTP packet in the cast sender";
117 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
118 return;
119 }
120 uint32 ssrc_of_sender = Rtcp::GetSsrcOfSender(packet, length);
121 if (ssrc_of_sender == ssrc_of_audio_sender_) {
122 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
123 base::Bind(&AudioSender::IncomingRtcpPacket, audio_sender_,
124 packet, length, callback));
125 } else if (ssrc_of_sender == ssrc_of_video_sender_) {
126 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
127 base::Bind(&VideoSender::IncomingRtcpPacket, video_sender_,
128 packet, length, callback));
129 } else {
130 // No action; just log and call the callback informing that we are done
131 // with the packet.
132 VLOG(1) << "Received a RTCP packet with a non matching sender SSRC "
133 << ssrc_of_sender;
134
135 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
136 }
137 }
138
139 protected:
~LocalCastSenderPacketReceiver()140 virtual ~LocalCastSenderPacketReceiver() {}
141
142 private:
143 friend class base::RefCountedThreadSafe<LocalCastSenderPacketReceiver>;
144
145 scoped_refptr<CastEnvironment> cast_environment_;
146 base::WeakPtr<AudioSender> audio_sender_;
147 base::WeakPtr<VideoSender> video_sender_;
148 const uint32 ssrc_of_audio_sender_;
149 const uint32 ssrc_of_video_sender_;
150 };
151
CreateCastSender(scoped_refptr<CastEnvironment> cast_environment,const AudioSenderConfig & audio_config,const VideoSenderConfig & video_config,VideoEncoderController * const video_encoder_controller,PacketSender * const packet_sender)152 CastSender* CastSender::CreateCastSender(
153 scoped_refptr<CastEnvironment> cast_environment,
154 const AudioSenderConfig& audio_config,
155 const VideoSenderConfig& video_config,
156 VideoEncoderController* const video_encoder_controller,
157 PacketSender* const packet_sender) {
158 return new CastSenderImpl(cast_environment,
159 audio_config,
160 video_config,
161 video_encoder_controller,
162 packet_sender);
163 }
164
CastSenderImpl(scoped_refptr<CastEnvironment> cast_environment,const AudioSenderConfig & audio_config,const VideoSenderConfig & video_config,VideoEncoderController * const video_encoder_controller,PacketSender * const packet_sender)165 CastSenderImpl::CastSenderImpl(
166 scoped_refptr<CastEnvironment> cast_environment,
167 const AudioSenderConfig& audio_config,
168 const VideoSenderConfig& video_config,
169 VideoEncoderController* const video_encoder_controller,
170 PacketSender* const packet_sender)
171 : pacer_(cast_environment, packet_sender),
172 audio_sender_(cast_environment, audio_config, &pacer_),
173 video_sender_(cast_environment, video_config, video_encoder_controller,
174 &pacer_),
175 frame_input_(new LocalFrameInput(cast_environment,
176 audio_sender_.AsWeakPtr(),
177 video_sender_.AsWeakPtr())),
178 packet_receiver_(new LocalCastSenderPacketReceiver(cast_environment,
179 audio_sender_.AsWeakPtr(), video_sender_.AsWeakPtr(),
180 audio_config.incoming_feedback_ssrc,
181 video_config.incoming_feedback_ssrc)) {}
182
~CastSenderImpl()183 CastSenderImpl::~CastSenderImpl() {}
184
frame_input()185 scoped_refptr<FrameInput> CastSenderImpl::frame_input() {
186 return frame_input_;
187 }
188
packet_receiver()189 scoped_refptr<PacketReceiver> CastSenderImpl::packet_receiver() {
190 return packet_receiver_;
191 }
192
193 } // namespace cast
194 } // namespace media
195