1 // Copyright 2014 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/receiver/cast_receiver_impl.h"
6 
7 #include <stddef.h>
8 
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/callback_helpers.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/trace_event/trace_event.h"
17 #include "media/cast/net/rtcp/rtcp_utility.h"
18 #include "media/cast/receiver/audio_decoder.h"
19 #include "media/cast/receiver/video_decoder.h"
20 
21 namespace media {
22 namespace cast {
23 
Create(scoped_refptr<CastEnvironment> cast_environment,const FrameReceiverConfig & audio_config,const FrameReceiverConfig & video_config,CastTransport * const transport)24 std::unique_ptr<CastReceiver> CastReceiver::Create(
25     scoped_refptr<CastEnvironment> cast_environment,
26     const FrameReceiverConfig& audio_config,
27     const FrameReceiverConfig& video_config,
28     CastTransport* const transport) {
29   return std::unique_ptr<CastReceiver>(new CastReceiverImpl(
30       cast_environment, audio_config, video_config, transport));
31 }
32 
CastReceiverImpl(scoped_refptr<CastEnvironment> cast_environment,const FrameReceiverConfig & audio_config,const FrameReceiverConfig & video_config,CastTransport * const transport)33 CastReceiverImpl::CastReceiverImpl(
34     scoped_refptr<CastEnvironment> cast_environment,
35     const FrameReceiverConfig& audio_config,
36     const FrameReceiverConfig& video_config,
37     CastTransport* const transport)
38     : cast_environment_(cast_environment),
39       audio_receiver_(cast_environment, audio_config, AUDIO_EVENT, transport),
40       video_receiver_(cast_environment, video_config, VIDEO_EVENT, transport),
41       ssrc_of_audio_sender_(audio_config.sender_ssrc),
42       ssrc_of_video_sender_(video_config.sender_ssrc),
43       num_audio_channels_(audio_config.channels),
44       audio_sampling_rate_(audio_config.rtp_timebase),
45       audio_codec_(audio_config.codec),
46       video_codec_(video_config.codec) {}
47 
48 CastReceiverImpl::~CastReceiverImpl() = default;
49 
ReceivePacket(std::unique_ptr<Packet> packet)50 void CastReceiverImpl::ReceivePacket(std::unique_ptr<Packet> packet) {
51   const uint8_t* const data = &packet->front();
52   const size_t length = packet->size();
53 
54   uint32_t ssrc_of_sender;
55   if (IsRtcpPacket(data, length)) {
56     ssrc_of_sender = GetSsrcOfSender(data, length);
57   } else if (!RtpParser::ParseSsrc(data, length, &ssrc_of_sender)) {
58     VLOG(1) << "Invalid RTP packet.";
59     return;
60   }
61 
62   base::WeakPtr<FrameReceiver> target;
63   if (ssrc_of_sender == ssrc_of_video_sender_) {
64     target = video_receiver_.AsWeakPtr();
65   } else if (ssrc_of_sender == ssrc_of_audio_sender_) {
66     target = audio_receiver_.AsWeakPtr();
67   } else {
68     VLOG(1) << "Dropping packet with a non matching sender SSRC: "
69             << ssrc_of_sender;
70     return;
71   }
72   cast_environment_->PostTask(
73       CastEnvironment::MAIN, FROM_HERE,
74       base::BindOnce(base::IgnoreResult(&FrameReceiver::ProcessPacket), target,
75                      std::move(packet)));
76 }
77 
RequestDecodedAudioFrame(const AudioFrameDecodedCallback & callback)78 void CastReceiverImpl::RequestDecodedAudioFrame(
79     const AudioFrameDecodedCallback& callback) {
80   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
81   DCHECK(!callback.is_null());
82   audio_receiver_.RequestEncodedFrame(base::BindOnce(
83       &CastReceiverImpl::DecodeEncodedAudioFrame,
84       // Note: Use of Unretained is safe since this Closure is guaranteed to be
85       // invoked or discarded by |audio_receiver_| before destruction of |this|.
86       base::Unretained(this), callback));
87 }
88 
RequestDecodedVideoFrame(const VideoFrameDecodedCallback & callback)89 void CastReceiverImpl::RequestDecodedVideoFrame(
90     const VideoFrameDecodedCallback& callback) {
91   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
92   DCHECK(!callback.is_null());
93   video_receiver_.RequestEncodedFrame(base::BindOnce(
94       &CastReceiverImpl::DecodeEncodedVideoFrame,
95       // Note: Use of Unretained is safe since this Closure is guaranteed to be
96       // invoked or discarded by |video_receiver_| before destruction of |this|.
97       base::Unretained(this), callback));
98 }
99 
DecodeEncodedAudioFrame(const AudioFrameDecodedCallback & callback,std::unique_ptr<EncodedFrame> encoded_frame)100 void CastReceiverImpl::DecodeEncodedAudioFrame(
101     const AudioFrameDecodedCallback& callback,
102     std::unique_ptr<EncodedFrame> encoded_frame) {
103   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
104   if (!encoded_frame) {
105     callback.Run(base::WrapUnique<AudioBus>(nullptr), base::TimeTicks(), false);
106     return;
107   }
108 
109   if (!audio_decoder_) {
110     audio_decoder_ =
111         std::make_unique<AudioDecoder>(cast_environment_, num_audio_channels_,
112                                        audio_sampling_rate_, audio_codec_);
113   }
114   const FrameId frame_id = encoded_frame->frame_id;
115   const RtpTimeTicks rtp_timestamp = encoded_frame->rtp_timestamp;
116   const base::TimeTicks playout_time = encoded_frame->reference_time;
117   audio_decoder_->DecodeFrame(
118       std::move(encoded_frame),
119       base::BindOnce(&CastReceiverImpl::EmitDecodedAudioFrame,
120                      cast_environment_, callback, frame_id, rtp_timestamp,
121                      playout_time));
122 }
123 
DecodeEncodedVideoFrame(const VideoFrameDecodedCallback & callback,std::unique_ptr<EncodedFrame> encoded_frame)124 void CastReceiverImpl::DecodeEncodedVideoFrame(
125     const VideoFrameDecodedCallback& callback,
126     std::unique_ptr<EncodedFrame> encoded_frame) {
127   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
128   if (!encoded_frame) {
129     callback.Run(base::WrapRefCounted<VideoFrame>(nullptr), base::TimeTicks(),
130                  false);
131     return;
132   }
133 
134   // Used by chrome/browser/media/cast_mirroring_performance_browsertest.cc
135   TRACE_EVENT_INSTANT1("cast_perf_test", "PullEncodedVideoFrame",
136                        TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp",
137                        encoded_frame->rtp_timestamp.lower_32_bits());
138 
139   if (!video_decoder_) {
140     video_decoder_ =
141         std::make_unique<VideoDecoder>(cast_environment_, video_codec_);
142   }
143   const FrameId frame_id = encoded_frame->frame_id;
144   const RtpTimeTicks rtp_timestamp = encoded_frame->rtp_timestamp;
145   const base::TimeTicks playout_time = encoded_frame->reference_time;
146   video_decoder_->DecodeFrame(
147       std::move(encoded_frame),
148       base::BindRepeating(&CastReceiverImpl::EmitDecodedVideoFrame,
149                           cast_environment_, callback, frame_id, rtp_timestamp,
150                           playout_time));
151 }
152 
153 // static
EmitDecodedAudioFrame(const scoped_refptr<CastEnvironment> & cast_environment,const AudioFrameDecodedCallback & callback,FrameId frame_id,RtpTimeTicks rtp_timestamp,const base::TimeTicks & playout_time,std::unique_ptr<AudioBus> audio_bus,bool is_continuous)154 void CastReceiverImpl::EmitDecodedAudioFrame(
155     const scoped_refptr<CastEnvironment>& cast_environment,
156     const AudioFrameDecodedCallback& callback,
157     FrameId frame_id,
158     RtpTimeTicks rtp_timestamp,
159     const base::TimeTicks& playout_time,
160     std::unique_ptr<AudioBus> audio_bus,
161     bool is_continuous) {
162   DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN));
163 
164   if (audio_bus.get()) {
165     // TODO(miu): This is reporting incorrect timestamp and delay.
166     // http://crbug.com/547251
167     std::unique_ptr<FrameEvent> playout_event(new FrameEvent());
168     playout_event->timestamp = cast_environment->Clock()->NowTicks();
169     playout_event->type = FRAME_PLAYOUT;
170     playout_event->media_type = AUDIO_EVENT;
171     playout_event->rtp_timestamp = rtp_timestamp;
172     playout_event->frame_id = frame_id;
173     playout_event->delay_delta = playout_time - playout_event->timestamp;
174     cast_environment->logger()->DispatchFrameEvent(std::move(playout_event));
175   }
176 
177   callback.Run(std::move(audio_bus), playout_time, is_continuous);
178 }
179 
180 // static
EmitDecodedVideoFrame(const scoped_refptr<CastEnvironment> & cast_environment,const VideoFrameDecodedCallback & callback,FrameId frame_id,RtpTimeTicks rtp_timestamp,const base::TimeTicks & playout_time,scoped_refptr<VideoFrame> video_frame,bool is_continuous)181 void CastReceiverImpl::EmitDecodedVideoFrame(
182     const scoped_refptr<CastEnvironment>& cast_environment,
183     const VideoFrameDecodedCallback& callback,
184     FrameId frame_id,
185     RtpTimeTicks rtp_timestamp,
186     const base::TimeTicks& playout_time,
187     scoped_refptr<VideoFrame> video_frame,
188     bool is_continuous) {
189   DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN));
190 
191   if (video_frame) {
192     // TODO(miu): This is reporting incorrect timestamp and delay.
193     // http://crbug.com/547251
194     std::unique_ptr<FrameEvent> playout_event(new FrameEvent());
195     playout_event->timestamp = cast_environment->Clock()->NowTicks();
196     playout_event->type = FRAME_PLAYOUT;
197     playout_event->media_type = VIDEO_EVENT;
198     playout_event->rtp_timestamp = rtp_timestamp;
199     playout_event->frame_id = frame_id;
200     playout_event->delay_delta = playout_time - playout_event->timestamp;
201     cast_environment->logger()->DispatchFrameEvent(std::move(playout_event));
202 
203     // Used by chrome/browser/media/cast_mirroring_performance_browsertest.cc
204     TRACE_EVENT_INSTANT2("cast_perf_test", "VideoFrameDecoded",
205                          TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp",
206                          rtp_timestamp.lower_32_bits(), "playout_time",
207                          (playout_time - base::TimeTicks()).InMicroseconds());
208   }
209 
210   callback.Run(std::move(video_frame), playout_time, is_continuous);
211 }
212 
213 }  // namespace cast
214 }  // namespace media
215