diff options
Diffstat (limited to 'chromium/media/cast/cast_receiver_impl.cc')
-rw-r--r-- | chromium/media/cast/cast_receiver_impl.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/chromium/media/cast/cast_receiver_impl.cc b/chromium/media/cast/cast_receiver_impl.cc new file mode 100644 index 00000000000..e2c004fe963 --- /dev/null +++ b/chromium/media/cast/cast_receiver_impl.cc @@ -0,0 +1,175 @@ +// Copyright 2013 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 "media/cast/cast_receiver_impl.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" + +namespace media { +namespace cast { + +// The video and audio receivers should only be called from the main thread. +// LocalFrameReciever posts tasks to the main thread, making the cast interface +// thread safe. +class LocalFrameReceiver : public FrameReceiver { + public: + LocalFrameReceiver(scoped_refptr<CastEnvironment> cast_environment, + AudioReceiver* audio_receiver, + VideoReceiver* video_receiver) + : cast_environment_(cast_environment), + audio_receiver_(audio_receiver), + video_receiver_(video_receiver) {} + + virtual void GetRawVideoFrame( + const VideoFrameDecodedCallback& callback) OVERRIDE { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&VideoReceiver::GetRawVideoFrame, + video_receiver_->AsWeakPtr(), callback)); + } + + virtual void GetEncodedVideoFrame( + const VideoFrameEncodedCallback& callback) OVERRIDE { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&VideoReceiver::GetEncodedVideoFrame, + video_receiver_->AsWeakPtr(), callback)); + } + + virtual void GetRawAudioFrame( + int number_of_10ms_blocks, + int desired_frequency, + const AudioFrameDecodedCallback& callback) OVERRIDE { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, base::Bind( + &AudioReceiver::GetRawAudioFrame, audio_receiver_->AsWeakPtr(), + number_of_10ms_blocks, desired_frequency, callback)); + } + + virtual void GetCodedAudioFrame( + const AudioFrameEncodedCallback& callback) OVERRIDE { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&AudioReceiver::GetEncodedAudioFrame, + audio_receiver_->AsWeakPtr(), callback)); + } + + protected: + virtual ~LocalFrameReceiver() {} + + private: + friend class base::RefCountedThreadSafe<LocalFrameReceiver>; + + scoped_refptr<CastEnvironment> cast_environment_; + AudioReceiver* audio_receiver_; + VideoReceiver* video_receiver_; +}; + +// The video and audio receivers should only be called from the main thread. +class LocalPacketReceiver : public PacketReceiver { + public: + LocalPacketReceiver(scoped_refptr<CastEnvironment> cast_environment, + AudioReceiver* audio_receiver, + VideoReceiver* video_receiver, + uint32 ssrc_of_audio_sender, + uint32 ssrc_of_video_sender) + : cast_environment_(cast_environment), + audio_receiver_(audio_receiver), + video_receiver_(video_receiver), + ssrc_of_audio_sender_(ssrc_of_audio_sender), + ssrc_of_video_sender_(ssrc_of_video_sender) {} + + virtual void ReceivedPacket(const uint8* packet, + size_t length, + const base::Closure callback) OVERRIDE { + if (length < kMinLengthOfRtcp) { + // No action; just log and call the callback informing that we are done + // with the packet. + VLOG(1) << "Received a packet which is too short " << length; + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); + return; + } + uint32 ssrc_of_sender; + if (!Rtcp::IsRtcpPacket(packet, length)) { + if (length < kMinLengthOfRtp) { + // No action; just log and call the callback informing that we are done + // with the packet. + VLOG(1) << "Received a RTP packet which is too short " << length; + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); + return; + } + ssrc_of_sender = RtpReceiver::GetSsrcOfSender(packet, length); + } else { + ssrc_of_sender = Rtcp::GetSsrcOfSender(packet, length); + } + if (ssrc_of_sender == ssrc_of_audio_sender_) { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&AudioReceiver::IncomingPacket, + audio_receiver_->AsWeakPtr(), packet, length, callback)); + } else if (ssrc_of_sender == ssrc_of_video_sender_) { + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, + base::Bind(&VideoReceiver::IncomingPacket, + video_receiver_->AsWeakPtr(), packet, length, callback)); + } else { + // No action; just log and call the callback informing that we are done + // with the packet. + VLOG(1) << "Received a packet with a non matching sender SSRC " + << ssrc_of_sender; + + cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); + } + } + + protected: + virtual ~LocalPacketReceiver() {} + + private: + friend class base::RefCountedThreadSafe<LocalPacketReceiver>; + + scoped_refptr<CastEnvironment> cast_environment_; + AudioReceiver* audio_receiver_; + VideoReceiver* video_receiver_; + const uint32 ssrc_of_audio_sender_; + const uint32 ssrc_of_video_sender_; +}; + +CastReceiver* CastReceiver::CreateCastReceiver( + scoped_refptr<CastEnvironment> cast_environment, + const AudioReceiverConfig& audio_config, + const VideoReceiverConfig& video_config, + PacketSender* const packet_sender) { + return new CastReceiverImpl(cast_environment, + audio_config, + video_config, + packet_sender); +} + +CastReceiverImpl::CastReceiverImpl( + scoped_refptr<CastEnvironment> cast_environment, + const AudioReceiverConfig& audio_config, + const VideoReceiverConfig& video_config, + PacketSender* const packet_sender) + : pacer_(cast_environment, packet_sender), + audio_receiver_(cast_environment, audio_config, &pacer_), + video_receiver_(cast_environment, video_config, &pacer_), + frame_receiver_(new LocalFrameReceiver(cast_environment, + &audio_receiver_, + &video_receiver_)), + packet_receiver_(new LocalPacketReceiver(cast_environment, + &audio_receiver_, + &video_receiver_, + audio_config.incoming_ssrc, + video_config.incoming_ssrc)) {} + +CastReceiverImpl::~CastReceiverImpl() {} + +scoped_refptr<PacketReceiver> CastReceiverImpl::packet_receiver() { + return packet_receiver_; +} + +scoped_refptr<FrameReceiver> CastReceiverImpl::frame_receiver() { + return frame_receiver_; +} + +} // namespace cast +} // namespace media |