Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / media / cast_rtp_stream.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
5 #include "chrome/renderer/media/cast_rtp_stream.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "chrome/renderer/media/cast_session.h"
11 #include "chrome/renderer/media/cast_udp_transport.h"
12 #include "content/public/renderer/media_stream_audio_sink.h"
13 #include "content/public/renderer/media_stream_video_sink.h"
14 #include "media/base/audio_bus.h"
15 #include "media/cast/cast_config.h"
16 #include "media/cast/cast_defines.h"
17 #include "media/cast/cast_sender.h"
18 #include "media/cast/transport/cast_transport_config.h"
19 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
20
21 using media::cast::AudioSenderConfig;
22 using media::cast::VideoSenderConfig;
23
24 namespace {
25 const char kCodecNameOpus[] = "OPUS";
26 const char kCodecNameVp8[] = "VP8";
27
28 CastRtpPayloadParams DefaultOpusPayload() {
29   CastRtpPayloadParams payload;
30   payload.ssrc = 1;
31   payload.feedback_ssrc = 1;
32   payload.payload_type = 127;
33   payload.codec_name = kCodecNameOpus;
34   payload.clock_rate = 48000;
35   payload.channels = 2;
36   payload.min_bitrate = payload.max_bitrate =
37       media::cast::kDefaultAudioEncoderBitrate;
38   return payload;
39 }
40
41 CastRtpPayloadParams DefaultVp8Payload() {
42   CastRtpPayloadParams payload;
43   payload.ssrc = 11;
44   payload.feedback_ssrc = 12;
45   payload.payload_type = 96;
46   payload.codec_name = kCodecNameVp8;
47   payload.clock_rate = 90000;
48   payload.width = 1280;
49   payload.height = 720;
50   payload.min_bitrate = 50 * 1000;
51   payload.max_bitrate = 2000 * 1000;
52   return payload;
53 }
54
55 std::vector<CastRtpParams> SupportedAudioParams() {
56   // TODO(hclam): Fill in more codecs here.
57   std::vector<CastRtpParams> supported_params;
58   supported_params.push_back(CastRtpParams(DefaultOpusPayload()));
59   return supported_params;
60 }
61
62 std::vector<CastRtpParams> SupportedVideoParams() {
63   // TODO(hclam): Fill in H264 here.
64   std::vector<CastRtpParams> supported_params;
65   supported_params.push_back(CastRtpParams(DefaultVp8Payload()));
66   return supported_params;
67 }
68
69 bool ToAudioSenderConfig(const CastRtpParams& params,
70                          AudioSenderConfig* config) {
71   config->sender_ssrc = params.payload.ssrc;
72   config->incoming_feedback_ssrc = params.payload.feedback_ssrc;
73   config->rtp_payload_type = params.payload.payload_type;
74   config->use_external_encoder = false;
75   config->frequency = params.payload.clock_rate;
76   config->channels = params.payload.channels;
77   config->bitrate = params.payload.max_bitrate;
78   config->codec = media::cast::transport::kPcm16;
79   if (params.payload.codec_name == kCodecNameOpus)
80     config->codec = media::cast::transport::kOpus;
81   else
82     return false;
83   return true;
84 }
85
86 bool ToVideoSenderConfig(const CastRtpParams& params,
87                          VideoSenderConfig* config) {
88   config->sender_ssrc = params.payload.ssrc;
89   config->incoming_feedback_ssrc = params.payload.feedback_ssrc;
90   config->rtp_payload_type = params.payload.payload_type;
91   config->use_external_encoder = false;
92   config->width = params.payload.width;
93   config->height = params.payload.height;
94   config->min_bitrate = config->start_bitrate = params.payload.min_bitrate;
95   config->max_bitrate = params.payload.max_bitrate;
96   if (params.payload.codec_name == kCodecNameVp8)
97     config->codec = media::cast::transport::kVp8;
98   else
99     return false;
100   return true;
101 }
102
103 void DeleteAudioBus(scoped_ptr<media::AudioBus> audio_bus) {
104   // Do nothing as |audio_bus| will be deleted.
105 }
106
107 }  // namespace
108
109 // This class receives MediaStreamTrack events and video frames from a
110 // MediaStreamTrack. Video frames are submitted to media::cast::FrameInput.
111 //
112 // Threading: Video frames are received on the render thread.
113 class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
114                       public content::MediaStreamVideoSink {
115  public:
116   explicit CastVideoSink(const blink::WebMediaStreamTrack& track)
117       : track_(track), sink_added_(false) {
118   }
119
120   virtual ~CastVideoSink() {
121     if (sink_added_)
122       RemoveFromVideoTrack(this, track_);
123   }
124
125   // content::MediaStreamVideoSink implementation.
126   virtual void OnVideoFrame(
127       const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
128     // TODO(hclam): Pass in the accurate capture time to have good
129     // audio/video sync.
130     frame_input_->InsertRawVideoFrame(frame,
131                                       base::TimeTicks::Now());
132   }
133
134   // Attach this sink to MediaStreamTrack. This method call must
135   // be made on the render thread. Incoming data can then be
136   // passed to media::cast::FrameInput on any thread.
137   void AddToTrack(
138       const scoped_refptr<media::cast::FrameInput>& frame_input) {
139     DCHECK(!sink_added_);
140     frame_input_ = frame_input;
141     AddToVideoTrack(this, track_);
142     sink_added_ = true;
143   }
144
145  private:
146   blink::WebMediaStreamTrack track_;
147   scoped_refptr<media::cast::FrameInput> frame_input_;
148   bool sink_added_;
149
150   DISALLOW_COPY_AND_ASSIGN(CastVideoSink);
151 };
152
153 // Receives audio data from a MediaStreamTrack. Data is submitted to
154 // media::cast::FrameInput.
155 //
156 // Threading: Audio frames are received on the real-time audio thread.
157 class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>,
158                       public content::MediaStreamAudioSink {
159  public:
160   explicit CastAudioSink(const blink::WebMediaStreamTrack& track)
161       : track_(track), sink_added_(false) {
162   }
163
164   virtual ~CastAudioSink() {
165     if (sink_added_)
166       RemoveFromAudioTrack(this, track_);
167   }
168
169   // content::MediaStreamAudioSink implementation.
170   virtual void OnData(const int16* audio_data,
171                       int sample_rate,
172                       int number_of_channels,
173                       int number_of_frames) OVERRIDE {
174     scoped_ptr<media::AudioBus> audio_bus(
175         media::AudioBus::Create(number_of_channels,
176                                 number_of_frames));
177     audio_bus->FromInterleaved(audio_data, number_of_frames, 2);
178
179     // TODO(hclam): Pass in the accurate capture time to have good
180     // audio/video sync.
181     media::AudioBus* audio_bus_ptr = audio_bus.get();
182     frame_input_->InsertAudio(
183         audio_bus_ptr,
184         base::TimeTicks::Now(),
185         base::Bind(&DeleteAudioBus, base::Passed(&audio_bus)));
186   }
187
188   virtual void OnSetFormat(
189       const media::AudioParameters& params) OVERRIDE{
190     NOTIMPLEMENTED();
191   }
192
193   // See CastVideoSink for details.
194   void AddToTrack(
195       const scoped_refptr<media::cast::FrameInput>& frame_input) {
196     DCHECK(!sink_added_);
197     frame_input_ = frame_input;
198     AddToAudioTrack(this, track_);
199     sink_added_ = true;
200   }
201
202  private:
203   blink::WebMediaStreamTrack track_;
204   scoped_refptr<media::cast::FrameInput> frame_input_;
205   bool sink_added_;
206
207   DISALLOW_COPY_AND_ASSIGN(CastAudioSink);
208 };
209
210 CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params)
211   : payload(payload_params) {
212 }
213
214 CastCodecSpecificParams::CastCodecSpecificParams() {
215 }
216
217 CastCodecSpecificParams::~CastCodecSpecificParams() {
218 }
219
220 CastRtpPayloadParams::CastRtpPayloadParams()
221     : payload_type(0),
222       ssrc(0),
223       feedback_ssrc(0),
224       clock_rate(0),
225       max_bitrate(0),
226       min_bitrate(0),
227       channels(0),
228       width(0),
229       height(0) {
230 }
231
232 CastRtpPayloadParams::~CastRtpPayloadParams() {
233 }
234
235 CastRtpParams::CastRtpParams() {
236 }
237
238 CastRtpParams::~CastRtpParams() {
239 }
240
241 CastRtpStream::CastRtpStream(
242     const blink::WebMediaStreamTrack& track,
243     const scoped_refptr<CastSession>& session)
244     : track_(track),
245       cast_session_(session) {
246 }
247
248 CastRtpStream::~CastRtpStream() {
249 }
250
251 std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() {
252   if (IsAudio())
253     return SupportedAudioParams();
254   else
255     return SupportedVideoParams();
256 }
257
258 CastRtpParams CastRtpStream::GetParams() {
259   return params_;
260 }
261
262 void CastRtpStream::Start(const CastRtpParams& params) {
263   if (IsAudio()) {
264     AudioSenderConfig config;
265     if (!ToAudioSenderConfig(params, &config)) {
266       DVLOG(1) << "Invalid parameters for audio.";
267     }
268     audio_sink_.reset(new CastAudioSink(track_));
269     cast_session_->StartAudio(
270         config,
271         base::Bind(&CastAudioSink::AddToTrack,
272                    audio_sink_->AsWeakPtr()));
273   } else {
274     VideoSenderConfig config;
275     if (!ToVideoSenderConfig(params, &config)) {
276       DVLOG(1) << "Invalid parameters for video.";
277     }
278     video_sink_.reset(new CastVideoSink(track_));
279     cast_session_->StartVideo(
280         config,
281         base::Bind(&CastVideoSink::AddToTrack,
282                    video_sink_->AsWeakPtr()));
283   }
284 }
285
286 void CastRtpStream::Stop() {
287   audio_sink_.reset();
288   video_sink_.reset();
289 }
290
291 bool CastRtpStream::IsAudio() const {
292   return track_.source().type() == blink::WebMediaStreamSource::TypeAudio;
293 }