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