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.
5 #include "media/cast/cast_receiver_impl.h"
8 #include "base/callback.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
15 // The callback should not be used, as the receiver is using the external
16 // transport. Implementation is required as the pacer is common to sender and
18 static void DoNothingCastTransportStatus(transport::CastTransportStatus status)
20 NOTREACHED() << "Internal transport used in CastReceiver";
22 // The video and audio receivers should only be called from the main thread.
23 // LocalFrameReciever posts tasks to the main thread, making the cast interface
25 class LocalFrameReceiver : public FrameReceiver {
27 LocalFrameReceiver(scoped_refptr<CastEnvironment> cast_environment,
28 AudioReceiver* audio_receiver,
29 VideoReceiver* video_receiver)
30 : cast_environment_(cast_environment),
31 audio_receiver_(audio_receiver),
32 video_receiver_(video_receiver) {}
34 virtual void GetRawVideoFrame(
35 const VideoFrameDecodedCallback& callback) OVERRIDE {
36 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
37 base::Bind(&VideoReceiver::GetRawVideoFrame,
38 video_receiver_->AsWeakPtr(), callback));
41 virtual void GetEncodedVideoFrame(
42 const VideoFrameEncodedCallback& callback) OVERRIDE {
43 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
44 base::Bind(&VideoReceiver::GetEncodedVideoFrame,
45 video_receiver_->AsWeakPtr(), callback));
48 virtual void GetRawAudioFrame(
49 int number_of_10ms_blocks,
50 int desired_frequency,
51 const AudioFrameDecodedCallback& callback) OVERRIDE {
52 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, base::Bind(
53 &AudioReceiver::GetRawAudioFrame, audio_receiver_->AsWeakPtr(),
54 number_of_10ms_blocks, desired_frequency, callback));
57 virtual void GetCodedAudioFrame(
58 const AudioFrameEncodedCallback& callback) OVERRIDE {
59 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
60 base::Bind(&AudioReceiver::GetEncodedAudioFrame,
61 audio_receiver_->AsWeakPtr(), callback));
65 virtual ~LocalFrameReceiver() {}
68 friend class base::RefCountedThreadSafe<LocalFrameReceiver>;
70 scoped_refptr<CastEnvironment> cast_environment_;
71 AudioReceiver* audio_receiver_;
72 VideoReceiver* video_receiver_;
75 // The video and audio receivers should only be called from the main thread.
76 class LocalPacketReceiver : public transport::PacketReceiver {
78 LocalPacketReceiver(scoped_refptr<CastEnvironment> cast_environment,
79 AudioReceiver* audio_receiver,
80 VideoReceiver* video_receiver,
81 uint32 ssrc_of_audio_sender,
82 uint32 ssrc_of_video_sender)
83 : cast_environment_(cast_environment),
84 audio_receiver_(audio_receiver),
85 video_receiver_(video_receiver),
86 ssrc_of_audio_sender_(ssrc_of_audio_sender),
87 ssrc_of_video_sender_(ssrc_of_video_sender) {}
89 virtual void ReceivedPacket(const uint8* packet,
91 const base::Closure callback) OVERRIDE {
92 if (length < kMinLengthOfRtcp) {
93 // No action; just log and call the callback informing that we are done
95 VLOG(1) << "Received a packet which is too short " << length;
96 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
99 uint32 ssrc_of_sender;
100 if (!Rtcp::IsRtcpPacket(packet, length)) {
101 if (length < kMinLengthOfRtp) {
102 // No action; just log and call the callback informing that we are done
104 VLOG(1) << "Received a RTP packet which is too short " << length;
105 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
108 ssrc_of_sender = RtpReceiver::GetSsrcOfSender(packet, length);
110 ssrc_of_sender = Rtcp::GetSsrcOfSender(packet, length);
112 if (ssrc_of_sender == ssrc_of_audio_sender_) {
113 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
114 base::Bind(&AudioReceiver::IncomingPacket,
115 audio_receiver_->AsWeakPtr(), packet, length, callback));
116 } else if (ssrc_of_sender == ssrc_of_video_sender_) {
117 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
118 base::Bind(&VideoReceiver::IncomingPacket,
119 video_receiver_->AsWeakPtr(), packet, length, callback));
121 // No action; just log and call the callback informing that we are done
123 VLOG(1) << "Received a packet with a non matching sender SSRC "
126 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
131 virtual ~LocalPacketReceiver() {}
134 friend class base::RefCountedThreadSafe<LocalPacketReceiver>;
136 scoped_refptr<CastEnvironment> cast_environment_;
137 AudioReceiver* audio_receiver_;
138 VideoReceiver* video_receiver_;
139 const uint32 ssrc_of_audio_sender_;
140 const uint32 ssrc_of_video_sender_;
143 CastReceiver* CastReceiver::CreateCastReceiver(
144 scoped_refptr<CastEnvironment> cast_environment,
145 const AudioReceiverConfig& audio_config,
146 const VideoReceiverConfig& video_config,
147 transport::PacketSender* const packet_sender) {
148 return new CastReceiverImpl(cast_environment,
154 CastReceiverImpl::CastReceiverImpl(
155 scoped_refptr<CastEnvironment> cast_environment,
156 const AudioReceiverConfig& audio_config,
157 const VideoReceiverConfig& video_config,
158 transport::PacketSender* const packet_sender)
159 : pacer_(cast_environment->Clock(), NULL, packet_sender,
160 cast_environment->GetMessageTaskRunnerForThread(
161 CastEnvironment::TRANSPORT),
162 base::Bind(&DoNothingCastTransportStatus)),
163 audio_receiver_(cast_environment, audio_config, &pacer_),
164 video_receiver_(cast_environment, video_config, &pacer_),
165 frame_receiver_(new LocalFrameReceiver(cast_environment,
168 packet_receiver_(new LocalPacketReceiver(cast_environment,
171 audio_config.incoming_ssrc,
172 video_config.incoming_ssrc)) {}
174 CastReceiverImpl::~CastReceiverImpl() {}
176 scoped_refptr<transport::PacketReceiver> CastReceiverImpl::packet_receiver() {
177 return packet_receiver_;
180 scoped_refptr<FrameReceiver> CastReceiverImpl::frame_receiver() {
181 return frame_receiver_;