Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / media / cast_session_delegate.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_session_delegate.h"
6
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "chrome/renderer/media/cast_transport_sender_ipc.h"
10 #include "content/public/renderer/p2p_socket_client.h"
11 #include "content/public/renderer/render_thread.h"
12 #include "media/cast/cast_config.h"
13 #include "media/cast/cast_environment.h"
14 #include "media/cast/cast_sender.h"
15 #include "media/cast/logging/logging_defines.h"
16 #include "media/cast/transport/cast_transport_config.h"
17 #include "media/cast/transport/cast_transport_sender.h"
18
19 using media::cast::AudioSenderConfig;
20 using media::cast::CastEnvironment;
21 using media::cast::CastSender;
22 using media::cast::VideoSenderConfig;
23
24 CastSessionDelegate::CastSessionDelegate()
25     : audio_encode_thread_("CastAudioEncodeThread"),
26       video_encode_thread_("CastVideoEncodeThread"),
27       transport_configured_(false),
28       io_message_loop_proxy_(
29           content::RenderThread::Get()->GetIOMessageLoopProxy()) {
30   DCHECK(io_message_loop_proxy_);
31 }
32
33 CastSessionDelegate::~CastSessionDelegate() {
34   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
35 }
36
37 void CastSessionDelegate::Initialize() {
38   if (cast_environment_)
39     return;  // Already initialized.
40
41   audio_encode_thread_.Start();
42   video_encode_thread_.Start();
43
44   // CastSender uses the renderer's IO thread as the main thread. This reduces
45   // thread hopping for incoming video frames and outgoing network packets.
46   // There's no need to decode so no thread assigned for decoding.
47   // Get default logging: All disabled.
48   cast_environment_ = new CastEnvironment(
49       scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
50       base::MessageLoopProxy::current(),
51       audio_encode_thread_.message_loop_proxy(),
52       NULL,
53       video_encode_thread_.message_loop_proxy(),
54       NULL,
55       base::MessageLoopProxy::current(),
56       media::cast::GetDefaultCastSenderLoggingConfig());
57 }
58
59 void CastSessionDelegate::StartAudio(
60     const AudioSenderConfig& config,
61     const FrameInputAvailableCallback& callback) {
62   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
63
64   audio_config_.reset(new AudioSenderConfig(config));
65   video_frame_input_available_callback_ = callback;
66   StartSendingInternal();
67 }
68
69 void CastSessionDelegate::StartVideo(
70     const VideoSenderConfig& config,
71     const FrameInputAvailableCallback& callback) {
72   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
73   audio_frame_input_available_callback_ = callback;
74
75   video_config_.reset(new VideoSenderConfig(config));
76   StartSendingInternal();
77 }
78
79 void CastSessionDelegate::StartUDP(
80     const net::IPEndPoint& local_endpoint,
81     const net::IPEndPoint& remote_endpoint) {
82   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
83   transport_configured_ = true;
84   local_endpoint_ = local_endpoint;
85   remote_endpoint_ = remote_endpoint;
86   StartSendingInternal();
87 }
88
89 void CastSessionDelegate::StatusNotificationCB(
90     media::cast::transport::CastTransportStatus unused_status) {
91   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
92   // TODO(hubbe): Call javascript UDPTransport error function.
93 }
94
95 void CastSessionDelegate::StartSendingInternal() {
96   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
97
98   // No transport, wait.
99   if (!transport_configured_)
100     return;
101
102   // No audio or video, wait.
103   if (!audio_config_ && !video_config_)
104     return;
105
106   Initialize();
107
108   media::cast::transport::CastTransportConfig config;
109
110   // TODO(hubbe): set config.aes_key and config.aes_iv_mask.
111   config.local_endpoint = local_endpoint_;
112   config.receiver_endpoint = remote_endpoint_;
113   if (audio_config_) {
114     config.audio_ssrc = audio_config_->sender_ssrc;
115     config.audio_codec = audio_config_->codec;
116     config.audio_rtp_config = audio_config_->rtp_config;
117     config.audio_frequency = audio_config_->frequency;
118     config.audio_channels = audio_config_->channels;
119   }
120   if (video_config_) {
121     config.video_ssrc = video_config_->sender_ssrc;
122     config.video_codec = video_config_->codec;
123     config.video_rtp_config = video_config_->rtp_config;
124   }
125
126   cast_transport_.reset(new CastTransportSenderIPC(
127       config,
128       base::Bind(&CastSessionDelegate::StatusNotificationCB,
129                  base::Unretained(this))));
130
131   cast_sender_.reset(CastSender::CreateCastSender(
132       cast_environment_,
133       audio_config_.get(),
134       video_config_.get(),
135       NULL,  // GPU.
136       base::Bind(&CastSessionDelegate::InitializationResult,
137                  base::Unretained(this)),
138       cast_transport_.get()));
139   cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver());
140 }
141
142 void CastSessionDelegate::InitializationResult(
143     media::cast::CastInitializationStatus result) const {
144   DCHECK(cast_sender_);
145
146   // TODO(pwestin): handle the error codes.
147   if (result == media::cast::STATUS_INITIALIZED) {
148     if (!audio_frame_input_available_callback_.is_null()) {
149       audio_frame_input_available_callback_.Run(cast_sender_->frame_input());
150     }
151     if (!video_frame_input_available_callback_.is_null()) {
152       video_frame_input_available_callback_.Run(cast_sender_->frame_input());
153     }
154   }
155 }