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 "media/cast/cast_receiver_impl.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop.h" 11 12 namespace media { 13 namespace cast { 14 15 // The video and audio receivers should only be called from the main thread. 16 // LocalFrameReciever posts tasks to the main thread, making the cast interface 17 // thread safe. 18 class LocalFrameReceiver : public FrameReceiver { 19 public: 20 LocalFrameReceiver(scoped_refptr<CastEnvironment> cast_environment, 21 AudioReceiver* audio_receiver, 22 VideoReceiver* video_receiver) 23 : cast_environment_(cast_environment), 24 audio_receiver_(audio_receiver), 25 video_receiver_(video_receiver) {} 26 27 virtual void GetRawVideoFrame( 28 const VideoFrameDecodedCallback& callback) OVERRIDE { 29 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 30 base::Bind(&VideoReceiver::GetRawVideoFrame, 31 video_receiver_->AsWeakPtr(), callback)); 32 } 33 34 virtual void GetEncodedVideoFrame( 35 const VideoFrameEncodedCallback& callback) OVERRIDE { 36 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 37 base::Bind(&VideoReceiver::GetEncodedVideoFrame, 38 video_receiver_->AsWeakPtr(), callback)); 39 } 40 41 virtual void GetRawAudioFrame( 42 int number_of_10ms_blocks, 43 int desired_frequency, 44 const AudioFrameDecodedCallback& callback) OVERRIDE { 45 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, base::Bind( 46 &AudioReceiver::GetRawAudioFrame, audio_receiver_->AsWeakPtr(), 47 number_of_10ms_blocks, desired_frequency, callback)); 48 } 49 50 virtual void GetCodedAudioFrame( 51 const AudioFrameEncodedCallback& callback) OVERRIDE { 52 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 53 base::Bind(&AudioReceiver::GetEncodedAudioFrame, 54 audio_receiver_->AsWeakPtr(), callback)); 55 } 56 57 protected: 58 virtual ~LocalFrameReceiver() {} 59 60 private: 61 friend class base::RefCountedThreadSafe<LocalFrameReceiver>; 62 63 scoped_refptr<CastEnvironment> cast_environment_; 64 AudioReceiver* audio_receiver_; 65 VideoReceiver* video_receiver_; 66 }; 67 68 // The video and audio receivers should only be called from the main thread. 69 class LocalPacketReceiver : public PacketReceiver { 70 public: 71 LocalPacketReceiver(scoped_refptr<CastEnvironment> cast_environment, 72 AudioReceiver* audio_receiver, 73 VideoReceiver* video_receiver, 74 uint32 ssrc_of_audio_sender, 75 uint32 ssrc_of_video_sender) 76 : cast_environment_(cast_environment), 77 audio_receiver_(audio_receiver), 78 video_receiver_(video_receiver), 79 ssrc_of_audio_sender_(ssrc_of_audio_sender), 80 ssrc_of_video_sender_(ssrc_of_video_sender) {} 81 82 virtual void ReceivedPacket(const uint8* packet, 83 size_t length, 84 const base::Closure callback) OVERRIDE { 85 if (length < kMinLengthOfRtcp) { 86 // No action; just log and call the callback informing that we are done 87 // with the packet. 88 VLOG(1) << "Received a packet which is too short " << length; 89 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 90 return; 91 } 92 uint32 ssrc_of_sender; 93 if (!Rtcp::IsRtcpPacket(packet, length)) { 94 if (length < kMinLengthOfRtp) { 95 // No action; just log and call the callback informing that we are done 96 // with the packet. 97 VLOG(1) << "Received a RTP packet which is too short " << length; 98 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 99 return; 100 } 101 ssrc_of_sender = RtpReceiver::GetSsrcOfSender(packet, length); 102 } else { 103 ssrc_of_sender = Rtcp::GetSsrcOfSender(packet, length); 104 } 105 if (ssrc_of_sender == ssrc_of_audio_sender_) { 106 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 107 base::Bind(&AudioReceiver::IncomingPacket, 108 audio_receiver_->AsWeakPtr(), packet, length, callback)); 109 } else if (ssrc_of_sender == ssrc_of_video_sender_) { 110 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 111 base::Bind(&VideoReceiver::IncomingPacket, 112 video_receiver_->AsWeakPtr(), packet, length, callback)); 113 } else { 114 // No action; just log and call the callback informing that we are done 115 // with the packet. 116 VLOG(1) << "Received a packet with a non matching sender SSRC " 117 << ssrc_of_sender; 118 119 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 120 } 121 } 122 123 protected: 124 virtual ~LocalPacketReceiver() {} 125 126 private: 127 friend class base::RefCountedThreadSafe<LocalPacketReceiver>; 128 129 scoped_refptr<CastEnvironment> cast_environment_; 130 AudioReceiver* audio_receiver_; 131 VideoReceiver* video_receiver_; 132 const uint32 ssrc_of_audio_sender_; 133 const uint32 ssrc_of_video_sender_; 134 }; 135 136 CastReceiver* CastReceiver::CreateCastReceiver( 137 scoped_refptr<CastEnvironment> cast_environment, 138 const AudioReceiverConfig& audio_config, 139 const VideoReceiverConfig& video_config, 140 PacketSender* const packet_sender) { 141 return new CastReceiverImpl(cast_environment, 142 audio_config, 143 video_config, 144 packet_sender); 145 } 146 147 CastReceiverImpl::CastReceiverImpl( 148 scoped_refptr<CastEnvironment> cast_environment, 149 const AudioReceiverConfig& audio_config, 150 const VideoReceiverConfig& video_config, 151 PacketSender* const packet_sender) 152 : pacer_(cast_environment, packet_sender), 153 audio_receiver_(cast_environment, audio_config, &pacer_), 154 video_receiver_(cast_environment, video_config, &pacer_), 155 frame_receiver_(new LocalFrameReceiver(cast_environment, 156 &audio_receiver_, 157 &video_receiver_)), 158 packet_receiver_(new LocalPacketReceiver(cast_environment, 159 &audio_receiver_, 160 &video_receiver_, 161 audio_config.incoming_ssrc, 162 video_config.incoming_ssrc)) {} 163 164 CastReceiverImpl::~CastReceiverImpl() {} 165 166 scoped_refptr<PacketReceiver> CastReceiverImpl::packet_receiver() { 167 return packet_receiver_; 168 } 169 170 scoped_refptr<FrameReceiver> CastReceiverImpl::frame_receiver() { 171 return frame_receiver_; 172 } 173 174 } // namespace cast 175 } // namespace media 176