blob: 06842f3bd02d0b7f1876a88d3afd001ca148e087 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/renderer/media/cast_transport_ipc.h"
#include <memory>
#include <utility>
#include "base/callback.h"
#include "base/containers/id_map.h"
#include "chrome/common/cast_messages.h"
#include "chrome/renderer/media/cast_ipc_dispatcher.h"
#include "ipc/ipc_channel_proxy.h"
#include "media/cast/cast_sender.h"
CastTransportIPC::CastTransportIPC(
const net::IPEndPoint& local_end_point,
const net::IPEndPoint& remote_end_point,
std::unique_ptr<base::DictionaryValue> options,
media::cast::PacketReceiverCallback packet_callback,
media::cast::CastTransportStatusCallback status_callback,
BulkRawEventsCallback raw_events_cb)
: channel_id_(-1),
packet_callback_(std::move(packet_callback)),
status_callback_(std::move(status_callback)),
raw_events_callback_(std::move(raw_events_cb)) {
if (CastIPCDispatcher::Get()) {
// TODO(miu): CastIPCDispatcher should be provided as a ctor argument.
channel_id_ = CastIPCDispatcher::Get()->AddSender(this);
Send(new CastHostMsg_New(channel_id_, local_end_point, remote_end_point,
*options));
}
}
CastTransportIPC::~CastTransportIPC() {
Send(new CastHostMsg_Delete(channel_id_));
if (CastIPCDispatcher::Get()) {
CastIPCDispatcher::Get()->RemoveSender(channel_id_);
}
}
void CastTransportIPC::InitializeStream(
const media::cast::CastTransportRtpConfig& config,
std::unique_ptr<media::cast::RtcpObserver> rtcp_observer) {
if (rtcp_observer) {
DCHECK(clients_.find(config.ssrc) == clients_.end());
clients_[config.ssrc] = std::move(rtcp_observer);
}
Send(new CastHostMsg_InitializeStream(channel_id_, config));
}
void CastTransportIPC::InsertFrame(uint32_t ssrc,
const media::cast::EncodedFrame& frame) {
Send(new CastHostMsg_InsertFrame(channel_id_, ssrc, frame));
}
void CastTransportIPC::SendSenderReport(
uint32_t ssrc,
base::TimeTicks current_time,
media::cast::RtpTimeTicks current_time_as_rtp_timestamp) {
Send(new CastHostMsg_SendSenderReport(channel_id_, ssrc, current_time,
current_time_as_rtp_timestamp));
}
void CastTransportIPC::CancelSendingFrames(
uint32_t ssrc,
const std::vector<media::cast::FrameId>& frame_ids) {
Send(new CastHostMsg_CancelSendingFrames(channel_id_, ssrc, frame_ids));
}
void CastTransportIPC::ResendFrameForKickstart(uint32_t ssrc,
media::cast::FrameId frame_id) {
Send(new CastHostMsg_ResendFrameForKickstart(channel_id_, ssrc, frame_id));
}
void CastTransportIPC::AddValidRtpReceiver(uint32_t rtp_sender_ssrc,
uint32_t rtp_receiver_ssrc) {
Send(new CastHostMsg_AddValidRtpReceiver(channel_id_, rtp_sender_ssrc,
rtp_receiver_ssrc));
}
void CastTransportIPC::InitializeRtpReceiverRtcpBuilder(
uint32_t rtp_receiver_ssrc,
const media::cast::RtcpTimeData& time_data) {
Send(new CastHostMsg_InitializeRtpReceiverRtcpBuilder(
channel_id_, rtp_receiver_ssrc, time_data));
}
void CastTransportIPC::AddCastFeedback(
const media::cast::RtcpCastMessage& cast_message,
base::TimeDelta target_delay) {
Send(
new CastHostMsg_AddCastFeedback(channel_id_, cast_message, target_delay));
}
void CastTransportIPC::AddPli(const media::cast::RtcpPliMessage& pli_message) {
Send(new CastHostMsg_AddPli(channel_id_, pli_message));
}
void CastTransportIPC::AddRtcpEvents(
const media::cast::ReceiverRtcpEventSubscriber::RtcpEvents& rtcp_events) {
Send(new CastHostMsg_AddRtcpEvents(channel_id_, rtcp_events));
}
void CastTransportIPC::AddRtpReceiverReport(
const media::cast::RtcpReportBlock& rtp_receiver_report_block) {
Send(new CastHostMsg_AddRtpReceiverReport(channel_id_,
rtp_receiver_report_block));
}
void CastTransportIPC::SendRtcpFromRtpReceiver() {
Send(new CastHostMsg_SendRtcpFromRtpReceiver(channel_id_));
}
void CastTransportIPC::OnNotifyStatusChange(
media::cast::CastTransportStatus status) {
status_callback_.Run(status);
}
void CastTransportIPC::OnRawEvents(
const std::vector<media::cast::PacketEvent>& packet_events,
const std::vector<media::cast::FrameEvent>& frame_events) {
// Note: Casting away const to avoid having to copy all the data elements. As
// the only consumer of this data in the IPC message, mutating the inputs
// should be acceptable. Just nod and blame the interface we were given here.
std::unique_ptr<std::vector<media::cast::FrameEvent>> taken_frame_events(
new std::vector<media::cast::FrameEvent>());
taken_frame_events->swap(
const_cast<std::vector<media::cast::FrameEvent>&>(frame_events));
std::unique_ptr<std::vector<media::cast::PacketEvent>> taken_packet_events(
new std::vector<media::cast::PacketEvent>());
taken_packet_events->swap(
const_cast<std::vector<media::cast::PacketEvent>&>(packet_events));
raw_events_callback_.Run(std::move(taken_frame_events),
std::move(taken_packet_events));
}
void CastTransportIPC::OnRtt(uint32_t rtp_sender_ssrc, base::TimeDelta rtt) {
auto it = clients_.find(rtp_sender_ssrc);
if (it == clients_.end()) {
LOG(ERROR) << "Received RTT report for unknown SSRC: " << rtp_sender_ssrc;
return;
}
it->second->OnReceivedRtt(rtt);
}
void CastTransportIPC::OnRtcpCastMessage(
uint32_t rtp_sender_ssrc,
const media::cast::RtcpCastMessage& cast_message) {
auto it = clients_.find(rtp_sender_ssrc);
if (it == clients_.end()) {
LOG(ERROR) << "Received cast message for unknown SSRC: " << rtp_sender_ssrc;
return;
}
it->second->OnReceivedCastMessage(cast_message);
}
void CastTransportIPC::OnReceivedPli(uint32_t rtp_sender_ssrc) {
auto it = clients_.find(rtp_sender_ssrc);
if (it == clients_.end()) {
LOG(ERROR) << "Received picture loss indicator for unknown SSRC: "
<< rtp_sender_ssrc;
return;
}
it->second->OnReceivedPli();
}
void CastTransportIPC::OnReceivedPacket(const media::cast::Packet& packet) {
if (!packet_callback_.is_null()) {
// TODO(hubbe): Perhaps an non-ownership-transferring cb here?
std::unique_ptr<media::cast::Packet> packet_copy(
new media::cast::Packet(packet));
packet_callback_.Run(std::move(packet_copy));
} else {
DVLOG(1) << "CastIPCDispatcher::OnReceivedPacket no packet callback yet.";
}
}
void CastTransportIPC::Send(IPC::Message* message) {
if (CastIPCDispatcher::Get() && channel_id_ != -1) {
CastIPCDispatcher::Get()->Send(message);
} else {
delete message;
}
}