Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / media / cast_session_delegate.cc
index 2562121..d5133b6 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "chrome/renderer/media/cast_transport_sender_ipc.h"
 #include "content/public/renderer/p2p_socket_client.h"
 #include "content/public/renderer/render_thread.h"
 #include "media/cast/cast_config.h"
@@ -20,73 +21,48 @@ using media::cast::CastEnvironment;
 using media::cast::CastSender;
 using media::cast::VideoSenderConfig;
 
-namespace {
-
-// This is a dummy class that does nothing. This is needed temporarily
-// to enable tests for cast.streaming extension APIs.
-// The real implementation of CastTransportSender is to use IPC to send
-// data to the browser process.
-// See crbug.com/327482 for more details.
-class DummyTransport : public media::cast::transport::CastTransportSender {
- public:
-  DummyTransport() {}
-  virtual ~DummyTransport() {}
-
-  // CastTransportSender implementations.
-  virtual void SetPacketReceiver(
-      scoped_refptr<
-        media::cast::transport::PacketReceiver> packet_receiver) OVERRIDE {}
-  virtual void InsertCodedAudioFrame(
-      const media::cast::transport::EncodedAudioFrame* audio_frame,
-      const base::TimeTicks& recorded_time) OVERRIDE {}
-  virtual void InsertCodedVideoFrame(
-      const media::cast::transport::EncodedVideoFrame* video_frame,
-      const base::TimeTicks& capture_time) OVERRIDE {}
-  virtual void SendRtcpFromRtpSender(
-      uint32 packet_type_flags,
-      const media::cast::transport::RtcpSenderInfo& sender_info,
-      const media::cast::transport::RtcpDlrrReportBlock& dlrr,
-      const media::cast::transport::RtcpSenderLogMessage& sender_log,
-      uint32 sending_ssrc,
-      const std::string& c_name) OVERRIDE {}
-  virtual void ResendPackets(
-      bool is_audio,
-      const media::cast::transport::MissingFramesAndPacketsMap& missing_packets)
-      OVERRIDE {}
-  virtual void RtpAudioStatistics(
-      const base::TimeTicks& now,
-      media::cast::transport::RtcpSenderInfo* sender_info) OVERRIDE {}
-  virtual void RtpVideoStatistics(
-      const base::TimeTicks& now,
-      media::cast::transport::RtcpSenderInfo* sender_info) OVERRIDE {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DummyTransport);
-};
-
-}  // namespace
-
 CastSessionDelegate::CastSessionDelegate()
     : audio_encode_thread_("CastAudioEncodeThread"),
       video_encode_thread_("CastVideoEncodeThread"),
-      audio_configured_(false),
-      video_configured_(false),
+      transport_configured_(false),
       io_message_loop_proxy_(
           content::RenderThread::Get()->GetIOMessageLoopProxy()) {
+  DCHECK(io_message_loop_proxy_);
 }
 
 CastSessionDelegate::~CastSessionDelegate() {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
 }
 
+void CastSessionDelegate::Initialize() {
+  if (cast_environment_)
+    return;  // Already initialized.
+
+  audio_encode_thread_.Start();
+  video_encode_thread_.Start();
+
+  // CastSender uses the renderer's IO thread as the main thread. This reduces
+  // thread hopping for incoming video frames and outgoing network packets.
+  // There's no need to decode so no thread assigned for decoding.
+  // Get default logging: All disabled.
+  cast_environment_ = new CastEnvironment(
+      scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
+      base::MessageLoopProxy::current(),
+      audio_encode_thread_.message_loop_proxy(),
+      NULL,
+      video_encode_thread_.message_loop_proxy(),
+      NULL,
+      base::MessageLoopProxy::current(),
+      media::cast::GetDefaultCastSenderLoggingConfig());
+}
+
 void CastSessionDelegate::StartAudio(
     const AudioSenderConfig& config,
     const FrameInputAvailableCallback& callback) {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
 
-  audio_configured_ = true;
-  audio_config_ = config;
-  frame_input_available_callbacks_.push_back(callback);
+  audio_config_.reset(new AudioSenderConfig(config));
+  video_frame_input_available_callback_ = callback;
   StartSendingInternal();
 }
 
@@ -94,49 +70,86 @@ void CastSessionDelegate::StartVideo(
     const VideoSenderConfig& config,
     const FrameInputAvailableCallback& callback) {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+  audio_frame_input_available_callback_ = callback;
+
+  video_config_.reset(new VideoSenderConfig(config));
+  StartSendingInternal();
+}
 
-  video_configured_ = true;
-  video_config_ = config;
-  frame_input_available_callbacks_.push_back(callback);
+void CastSessionDelegate::StartUDP(
+    const net::IPEndPoint& local_endpoint,
+    const net::IPEndPoint& remote_endpoint) {
+  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+  transport_configured_ = true;
+  local_endpoint_ = local_endpoint;
+  remote_endpoint_ = remote_endpoint;
   StartSendingInternal();
 }
 
+void CastSessionDelegate::StatusNotificationCB(
+    media::cast::transport::CastTransportStatus unused_status) {
+  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
+  // TODO(hubbe): Call javascript UDPTransport error function.
+}
+
 void CastSessionDelegate::StartSendingInternal() {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
 
-  if (cast_environment_)
+  // No transport, wait.
+  if (!transport_configured_)
     return;
-  if (!audio_configured_ || !video_configured_)
+
+  // No audio or video, wait.
+  if (!audio_config_ && !video_config_)
     return;
 
-  cast_transport_.reset(new DummyTransport());
-  audio_encode_thread_.Start();
-  video_encode_thread_.Start();
+  Initialize();
 
-  // CastSender uses the renderer's IO thread as the main thread. This reduces
-  // thread hopping for incoming video frames and outgoing network packets.
-  // There's no need to decode so no thread assigned for decoding.
-  // Get default logging: All disabled.
-  cast_environment_ = new CastEnvironment(
-      scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
-      base::MessageLoopProxy::current(),
-      audio_encode_thread_.message_loop_proxy(),
-      NULL,
-      video_encode_thread_.message_loop_proxy(),
-      NULL,
-      base::MessageLoopProxy::current(),
-      media::cast::GetDefaultCastSenderLoggingConfig());
+  media::cast::transport::CastTransportConfig config;
+
+  // TODO(hubbe): set config.aes_key and config.aes_iv_mask.
+  config.local_endpoint = local_endpoint_;
+  config.receiver_endpoint = remote_endpoint_;
+  if (audio_config_) {
+    config.audio_ssrc = audio_config_->sender_ssrc;
+    config.audio_codec = audio_config_->codec;
+    config.audio_rtp_config = audio_config_->rtp_config;
+    config.audio_frequency = audio_config_->frequency;
+    config.audio_channels = audio_config_->channels;
+  }
+  if (video_config_) {
+    config.video_ssrc = video_config_->sender_ssrc;
+    config.video_codec = video_config_->codec;
+    config.video_rtp_config = video_config_->rtp_config;
+  }
+
+  cast_transport_.reset(new CastTransportSenderIPC(
+      config,
+      base::Bind(&CastSessionDelegate::StatusNotificationCB,
+                 base::Unretained(this))));
 
   cast_sender_.reset(CastSender::CreateCastSender(
       cast_environment_,
-      audio_config_,
-      video_config_,
-      NULL,
+      audio_config_.get(),
+      video_config_.get(),
+      NULL,  // GPU.
+      base::Bind(&CastSessionDelegate::InitializationResult,
+                 base::Unretained(this)),
       cast_transport_.get()));
+  cast_transport_->SetPacketReceiver(cast_sender_->packet_receiver());
+}
 
-  for (size_t i = 0; i < frame_input_available_callbacks_.size(); ++i) {
-    frame_input_available_callbacks_[i].Run(
-        cast_sender_->frame_input());
+void CastSessionDelegate::InitializationResult(
+    media::cast::CastInitializationStatus result) const {
+  DCHECK(cast_sender_);
+
+  // TODO(pwestin): handle the error codes.
+  if (result == media::cast::STATUS_INITIALIZED) {
+    if (!audio_frame_input_available_callback_.is_null()) {
+      audio_frame_input_available_callback_.Run(cast_sender_->frame_input());
+    }
+    if (!video_frame_input_available_callback_.is_null()) {
+      video_frame_input_available_callback_.Run(cast_sender_->frame_input());
+    }
   }
-  frame_input_available_callbacks_.clear();
 }