cast_sender_impl.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 11namespace media { 12namespace cast { 13 14// The LocalFrameInput class posts all incoming frames; audio and video to the 15// main cast thread for processing. 16// This make the cast sender interface thread safe. 17class LocalFrameInput : public FrameInput { 18 public: 19 LocalFrameInput(scoped_refptr<CastEnvironment> cast_environment, 20 base::WeakPtr<AudioSender> audio_sender, 21 base::WeakPtr<VideoSender> video_sender) 22 : cast_environment_(cast_environment), 23 audio_sender_(audio_sender), 24 video_sender_(video_sender) {} 25 26 virtual void InsertRawVideoFrame(const I420VideoFrame* video_frame, 27 const base::TimeTicks& capture_time, 28 const base::Closure callback) OVERRIDE { 29 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 30 base::Bind(&VideoSender::InsertRawVideoFrame, video_sender_, 31 video_frame, capture_time, callback)); 32 } 33 34 virtual void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame, 35 const base::TimeTicks& capture_time, 36 const base::Closure callback) OVERRIDE { 37 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 38 base::Bind(&VideoSender::InsertCodedVideoFrame, video_sender_, 39 video_frame, capture_time, callback)); 40 } 41 42 virtual void InsertRawAudioFrame(const PcmAudioFrame* audio_frame, 43 const base::TimeTicks& recorded_time, 44 const base::Closure callback) OVERRIDE { 45 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 46 base::Bind(&AudioSender::InsertRawAudioFrame, audio_sender_, 47 audio_frame, recorded_time, callback)); 48 } 49 50 virtual void InsertCodedAudioFrame(const EncodedAudioFrame* audio_frame, 51 const base::TimeTicks& recorded_time, 52 const base::Closure callback) OVERRIDE { 53 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 54 base::Bind(&AudioSender::InsertCodedAudioFrame, audio_sender_, 55 audio_frame, recorded_time, callback)); 56 } 57 58 protected: 59 virtual ~LocalFrameInput() {} 60 61 private: 62 friend class base::RefCountedThreadSafe<LocalFrameInput>; 63 64 scoped_refptr<CastEnvironment> cast_environment_; 65 base::WeakPtr<AudioSender> audio_sender_; 66 base::WeakPtr<VideoSender> video_sender_; 67}; 68 69// LocalCastSenderPacketReceiver handle the incoming packets to the cast sender 70// it's only expected to receive RTCP feedback packets from the remote cast 71// receiver. The class verifies that that it is a RTCP packet and based on the 72// SSRC of the incoming packet route the packet to the correct sender; audio or 73// video. 74// 75// Definition of SSRC as defined in RFC 3550. 76// Synchronization source (SSRC): The source of a stream of RTP 77// packets, identified by a 32-bit numeric SSRC identifier carried in 78// the RTP header so as not to be dependent upon the network address. 79// All packets from a synchronization source form part of the same 80// timing and sequence number space, so a receiver groups packets by 81// synchronization source for playback. Examples of synchronization 82// sources include the sender of a stream of packets derived from a 83// signal source such as a microphone or a camera, or an RTP mixer 84// (see below). A synchronization source may change its data format, 85// e.g., audio encoding, over time. The SSRC identifier is a 86// randomly chosen value meant to be globally unique within a 87// particular RTP session (see Section 8). A participant need not 88// use the same SSRC identifier for all the RTP sessions in a 89// multimedia session; the binding of the SSRC identifiers is 90// provided through RTCP (see Section 6.5.1). If a participant 91// generates multiple streams in one RTP session, for example from 92// separate video cameras, each MUST be identified as a different 93// SSRC. 94 95class LocalCastSenderPacketReceiver : public PacketReceiver { 96 public: 97 LocalCastSenderPacketReceiver(scoped_refptr<CastEnvironment> cast_environment, 98 base::WeakPtr<AudioSender> audio_sender, 99 base::WeakPtr<VideoSender> video_sender, 100 uint32 ssrc_of_audio_sender, 101 uint32 ssrc_of_video_sender) 102 : cast_environment_(cast_environment), 103 audio_sender_(audio_sender), 104 video_sender_(video_sender), 105 ssrc_of_audio_sender_(ssrc_of_audio_sender), 106 ssrc_of_video_sender_(ssrc_of_video_sender) {} 107 108 virtual void ReceivedPacket(const uint8* packet, 109 int length, 110 const base::Closure callback) OVERRIDE { 111 if (!Rtcp::IsRtcpPacket(packet, length)) { 112 // We should have no incoming RTP packets. 113 // No action; just log and call the callback informing that we are done 114 // with the packet. 115 VLOG(1) << "Unexpectedly received a RTP packet in the cast sender"; 116 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 117 return; 118 } 119 uint32 ssrc_of_sender = Rtcp::GetSsrcOfSender(packet, length); 120 if (ssrc_of_sender == ssrc_of_audio_sender_) { 121 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 122 base::Bind(&AudioSender::IncomingRtcpPacket, audio_sender_, 123 packet, length, callback)); 124 } else if (ssrc_of_sender == ssrc_of_video_sender_) { 125 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 126 base::Bind(&VideoSender::IncomingRtcpPacket, video_sender_, 127 packet, length, callback)); 128 } else { 129 // No action; just log and call the callback informing that we are done 130 // with the packet. 131 VLOG(1) << "Received a RTCP packet with a non matching sender SSRC " 132 << ssrc_of_sender; 133 134 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 135 } 136 } 137 138 protected: 139 virtual ~LocalCastSenderPacketReceiver() {} 140 141 private: 142 friend class base::RefCountedThreadSafe<LocalCastSenderPacketReceiver>; 143 144 scoped_refptr<CastEnvironment> cast_environment_; 145 base::WeakPtr<AudioSender> audio_sender_; 146 base::WeakPtr<VideoSender> video_sender_; 147 const uint32 ssrc_of_audio_sender_; 148 const uint32 ssrc_of_video_sender_; 149}; 150 151CastSender* CastSender::CreateCastSender( 152 scoped_refptr<CastEnvironment> cast_environment, 153 const AudioSenderConfig& audio_config, 154 const VideoSenderConfig& video_config, 155 VideoEncoderController* const video_encoder_controller, 156 PacketSender* const packet_sender) { 157 return new CastSenderImpl(cast_environment, 158 audio_config, 159 video_config, 160 video_encoder_controller, 161 packet_sender); 162} 163 164CastSenderImpl::CastSenderImpl( 165 scoped_refptr<CastEnvironment> cast_environment, 166 const AudioSenderConfig& audio_config, 167 const VideoSenderConfig& video_config, 168 VideoEncoderController* const video_encoder_controller, 169 PacketSender* const packet_sender) 170 : pacer_(cast_environment, packet_sender), 171 audio_sender_(cast_environment, audio_config, &pacer_), 172 video_sender_(cast_environment, video_config, video_encoder_controller, 173 &pacer_), 174 frame_input_(new LocalFrameInput(cast_environment, 175 audio_sender_.AsWeakPtr(), 176 video_sender_.AsWeakPtr())), 177 packet_receiver_(new LocalCastSenderPacketReceiver(cast_environment, 178 audio_sender_.AsWeakPtr(), video_sender_.AsWeakPtr(), 179 audio_config.incoming_feedback_ssrc, 180 video_config.incoming_feedback_ssrc)) {} 181 182CastSenderImpl::~CastSenderImpl() {} 183 184scoped_refptr<FrameInput> CastSenderImpl::frame_input() { 185 return frame_input_; 186} 187 188scoped_refptr<PacketReceiver> CastSenderImpl::packet_receiver() { 189 return packet_receiver_; 190} 191 192} // namespace cast 193} // namespace media 194