Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / media / cast / cast_sender_impl.cc
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 LocalVideoFrameInput class posts all incoming video frames to the main
16 // cast thread for processing.
17 class LocalVideoFrameInput : public VideoFrameInput {
18  public:
19   LocalVideoFrameInput(scoped_refptr<CastEnvironment> cast_environment,
20                        base::WeakPtr<VideoSender> video_sender)
21       : cast_environment_(cast_environment), video_sender_(video_sender) {}
22
23   virtual void InsertRawVideoFrame(
24       const scoped_refptr<media::VideoFrame>& video_frame,
25       const base::TimeTicks& capture_time) OVERRIDE {
26     cast_environment_->PostTask(CastEnvironment::MAIN,
27                                 FROM_HERE,
28                                 base::Bind(&VideoSender::InsertRawVideoFrame,
29                                            video_sender_,
30                                            video_frame,
31                                            capture_time));
32   }
33
34  protected:
35   virtual ~LocalVideoFrameInput() {}
36
37  private:
38   friend class base::RefCountedThreadSafe<LocalVideoFrameInput>;
39
40   scoped_refptr<CastEnvironment> cast_environment_;
41   base::WeakPtr<VideoSender> video_sender_;
42
43   DISALLOW_COPY_AND_ASSIGN(LocalVideoFrameInput);
44 };
45
46 // The LocalAudioFrameInput class posts all incoming audio frames to the main
47 // cast thread for processing. Therefore frames can be inserted from any thread.
48 class LocalAudioFrameInput : public AudioFrameInput {
49  public:
50   LocalAudioFrameInput(scoped_refptr<CastEnvironment> cast_environment,
51                        base::WeakPtr<AudioSender> audio_sender)
52       : cast_environment_(cast_environment), audio_sender_(audio_sender) {}
53
54   virtual void InsertAudio(scoped_ptr<AudioBus> audio_bus,
55                            const base::TimeTicks& recorded_time) OVERRIDE {
56     cast_environment_->PostTask(CastEnvironment::MAIN,
57                                 FROM_HERE,
58                                 base::Bind(&AudioSender::InsertAudio,
59                                            audio_sender_,
60                                            base::Passed(&audio_bus),
61                                            recorded_time));
62   }
63
64  protected:
65   virtual ~LocalAudioFrameInput() {}
66
67  private:
68   friend class base::RefCountedThreadSafe<LocalAudioFrameInput>;
69
70   scoped_refptr<CastEnvironment> cast_environment_;
71   base::WeakPtr<AudioSender> audio_sender_;
72
73   DISALLOW_COPY_AND_ASSIGN(LocalAudioFrameInput);
74 };
75
76 scoped_ptr<CastSender> CastSender::Create(
77     scoped_refptr<CastEnvironment> cast_environment,
78     transport::CastTransportSender* const transport_sender) {
79   CHECK(cast_environment);
80   return scoped_ptr<CastSender>(
81       new CastSenderImpl(cast_environment, transport_sender));
82 }
83
84 CastSenderImpl::CastSenderImpl(
85     scoped_refptr<CastEnvironment> cast_environment,
86     transport::CastTransportSender* const transport_sender)
87     : cast_environment_(cast_environment),
88       transport_sender_(transport_sender),
89       weak_factory_(this) {
90   CHECK(cast_environment);
91 }
92
93 void CastSenderImpl::InitializeAudio(
94     const AudioSenderConfig& audio_config,
95     const CastInitializationCallback& cast_initialization_cb) {
96   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
97   CHECK(audio_config.use_external_encoder ||
98         cast_environment_->HasAudioThread());
99
100   VLOG(1) << "CastSenderImpl@" << this << "::InitializeAudio()";
101
102   audio_sender_.reset(
103       new AudioSender(cast_environment_, audio_config, transport_sender_));
104
105   const CastInitializationStatus status = audio_sender_->InitializationResult();
106   if (status == STATUS_AUDIO_INITIALIZED) {
107     ssrc_of_audio_sender_ = audio_config.incoming_feedback_ssrc;
108     audio_frame_input_ =
109         new LocalAudioFrameInput(cast_environment_, audio_sender_->AsWeakPtr());
110   }
111   cast_initialization_cb.Run(status);
112 }
113
114 void CastSenderImpl::InitializeVideo(
115     const VideoSenderConfig& video_config,
116     const CastInitializationCallback& cast_initialization_cb,
117     const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
118     const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
119   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
120   CHECK(video_config.use_external_encoder ||
121         cast_environment_->HasVideoThread());
122
123   VLOG(1) << "CastSenderImpl@" << this << "::InitializeVideo()";
124
125   video_sender_.reset(new VideoSender(cast_environment_,
126                                       video_config,
127                                       create_vea_cb,
128                                       create_video_encode_mem_cb,
129                                       transport_sender_));
130
131   const CastInitializationStatus status = video_sender_->InitializationResult();
132   if (status == STATUS_VIDEO_INITIALIZED) {
133     ssrc_of_video_sender_ = video_config.incoming_feedback_ssrc;
134     video_frame_input_ =
135         new LocalVideoFrameInput(cast_environment_, video_sender_->AsWeakPtr());
136   }
137   cast_initialization_cb.Run(status);
138 }
139
140 CastSenderImpl::~CastSenderImpl() {
141   VLOG(1) << "CastSenderImpl@" << this << "::~CastSenderImpl()";
142 }
143
144 // ReceivedPacket handle the incoming packets to the cast sender
145 // it's only expected to receive RTCP feedback packets from the remote cast
146 // receiver. The class verifies that that it is a RTCP packet and based on the
147 // SSRC of the incoming packet route the packet to the correct sender; audio or
148 // video.
149 //
150 // Definition of SSRC as defined in RFC 3550.
151 // Synchronization source (SSRC): The source of a stream of RTP
152 //    packets, identified by a 32-bit numeric SSRC identifier carried in
153 //    the RTP header so as not to be dependent upon the network address.
154 //    All packets from a synchronization source form part of the same
155 //    timing and sequence number space, so a receiver groups packets by
156 //    synchronization source for playback.  Examples of synchronization
157 //    sources include the sender of a stream of packets derived from a
158 //    signal source such as a microphone or a camera, or an RTP mixer
159 //    (see below).  A synchronization source may change its data format,
160 //    e.g., audio encoding, over time.  The SSRC identifier is a
161 //    randomly chosen value meant to be globally unique within a
162 //    particular RTP session (see Section 8).  A participant need not
163 //    use the same SSRC identifier for all the RTP sessions in a
164 //    multimedia session; the binding of the SSRC identifiers is
165 //    provided through RTCP (see Section 6.5.1).  If a participant
166 //    generates multiple streams in one RTP session, for example from
167 //    separate video cameras, each MUST be identified as a different
168 //    SSRC.
169 void CastSenderImpl::ReceivedPacket(scoped_ptr<Packet> packet) {
170   DCHECK(cast_environment_);
171   size_t length = packet->size();
172   const uint8_t* data = &packet->front();
173   if (!Rtcp::IsRtcpPacket(data, length)) {
174     VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
175             << "Received an invalid (non-RTCP?) packet in the cast sender.";
176     return;
177   }
178   uint32 ssrc_of_sender = Rtcp::GetSsrcOfSender(data, length);
179   if (ssrc_of_sender == ssrc_of_audio_sender_) {
180     if (!audio_sender_) {
181       NOTREACHED();
182       return;
183     }
184     cast_environment_->PostTask(CastEnvironment::MAIN,
185                                 FROM_HERE,
186                                 base::Bind(&AudioSender::IncomingRtcpPacket,
187                                            audio_sender_->AsWeakPtr(),
188                                            base::Passed(&packet)));
189   } else if (ssrc_of_sender == ssrc_of_video_sender_) {
190     if (!video_sender_) {
191       NOTREACHED();
192       return;
193     }
194     cast_environment_->PostTask(CastEnvironment::MAIN,
195                                 FROM_HERE,
196                                 base::Bind(&VideoSender::IncomingRtcpPacket,
197                                            video_sender_->AsWeakPtr(),
198                                            base::Passed(&packet)));
199   } else {
200     VLOG(1) << "CastSenderImpl@" << this << "::ReceivedPacket() -- "
201             << "Received a RTCP packet with a non matching sender SSRC "
202             << ssrc_of_sender;
203   }
204 }
205
206 scoped_refptr<AudioFrameInput> CastSenderImpl::audio_frame_input() {
207   return audio_frame_input_;
208 }
209
210 scoped_refptr<VideoFrameInput> CastSenderImpl::video_frame_input() {
211   return video_frame_input_;
212 }
213
214 transport::PacketReceiverCallback CastSenderImpl::packet_receiver() {
215   return base::Bind(&CastSenderImpl::ReceivedPacket,
216                     weak_factory_.GetWeakPtr());
217 }
218
219 }  // namespace cast
220 }  // namespace media