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