Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / media / cast / receiver / cast_receiver_impl.cc
blob8265211c71cd5d431fd61078bbf79b07e038d6bc
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.
5 #include "media/cast/receiver/cast_receiver_impl.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "media/cast/receiver/audio_decoder.h"
14 #include "media/cast/receiver/video_decoder.h"
16 namespace media {
17 namespace cast {
19 scoped_ptr<CastReceiver> CastReceiver::Create(
20 scoped_refptr<CastEnvironment> cast_environment,
21 const FrameReceiverConfig& audio_config,
22 const FrameReceiverConfig& video_config,
23 PacketSender* const packet_sender) {
24 return scoped_ptr<CastReceiver>(new CastReceiverImpl(
25 cast_environment, audio_config, video_config, packet_sender));
28 CastReceiverImpl::CastReceiverImpl(
29 scoped_refptr<CastEnvironment> cast_environment,
30 const FrameReceiverConfig& audio_config,
31 const FrameReceiverConfig& video_config,
32 PacketSender* const packet_sender)
33 : cast_environment_(cast_environment),
34 pacer_(kTargetBurstSize,
35 kMaxBurstSize,
36 cast_environment->Clock(),
37 cast_environment->Logging(),
38 packet_sender,
39 cast_environment->GetTaskRunner(CastEnvironment::MAIN)),
40 audio_receiver_(cast_environment, audio_config, AUDIO_EVENT, &pacer_),
41 video_receiver_(cast_environment, video_config, VIDEO_EVENT, &pacer_),
42 ssrc_of_audio_sender_(audio_config.incoming_ssrc),
43 ssrc_of_video_sender_(video_config.incoming_ssrc),
44 num_audio_channels_(audio_config.channels),
45 audio_sampling_rate_(audio_config.frequency),
46 audio_codec_(audio_config.codec),
47 video_codec_(video_config.codec) {}
49 CastReceiverImpl::~CastReceiverImpl() {}
51 void CastReceiverImpl::DispatchReceivedPacket(scoped_ptr<Packet> packet) {
52 const uint8_t* const data = &packet->front();
53 const size_t length = packet->size();
55 uint32 ssrc_of_sender;
56 if (Rtcp::IsRtcpPacket(data, length)) {
57 ssrc_of_sender = Rtcp::GetSsrcOfSender(data, length);
58 } else if (!FrameReceiver::ParseSenderSsrc(data, length, &ssrc_of_sender)) {
59 VLOG(1) << "Invalid RTP packet.";
60 return;
63 base::WeakPtr<FrameReceiver> target;
64 if (ssrc_of_sender == ssrc_of_video_sender_) {
65 target = video_receiver_.AsWeakPtr();
66 } else if (ssrc_of_sender == ssrc_of_audio_sender_) {
67 target = audio_receiver_.AsWeakPtr();
68 } else {
69 VLOG(1) << "Dropping packet with a non matching sender SSRC: "
70 << ssrc_of_sender;
71 return;
73 cast_environment_->PostTask(
74 CastEnvironment::MAIN,
75 FROM_HERE,
76 base::Bind(base::IgnoreResult(&FrameReceiver::ProcessPacket),
77 target,
78 base::Passed(&packet)));
81 PacketReceiverCallback CastReceiverImpl::packet_receiver() {
82 return base::Bind(&CastReceiverImpl::DispatchReceivedPacket,
83 // TODO(miu): This code structure is dangerous, since the
84 // callback could be stored and then invoked after
85 // destruction of |this|.
86 base::Unretained(this));
89 void CastReceiverImpl::RequestDecodedAudioFrame(
90 const AudioFrameDecodedCallback& callback) {
91 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
92 DCHECK(!callback.is_null());
93 audio_receiver_.RequestEncodedFrame(base::Bind(
94 &CastReceiverImpl::DecodeEncodedAudioFrame,
95 // Note: Use of Unretained is safe since this Closure is guaranteed to be
96 // invoked or discarded by |audio_receiver_| before destruction of |this|.
97 base::Unretained(this),
98 callback));
101 void CastReceiverImpl::RequestEncodedAudioFrame(
102 const ReceiveEncodedFrameCallback& callback) {
103 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
104 audio_receiver_.RequestEncodedFrame(callback);
107 void CastReceiverImpl::RequestDecodedVideoFrame(
108 const VideoFrameDecodedCallback& callback) {
109 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
110 DCHECK(!callback.is_null());
111 video_receiver_.RequestEncodedFrame(base::Bind(
112 &CastReceiverImpl::DecodeEncodedVideoFrame,
113 // Note: Use of Unretained is safe since this Closure is guaranteed to be
114 // invoked or discarded by |video_receiver_| before destruction of |this|.
115 base::Unretained(this),
116 callback));
119 void CastReceiverImpl::RequestEncodedVideoFrame(
120 const ReceiveEncodedFrameCallback& callback) {
121 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
122 video_receiver_.RequestEncodedFrame(callback);
125 void CastReceiverImpl::DecodeEncodedAudioFrame(
126 const AudioFrameDecodedCallback& callback,
127 scoped_ptr<EncodedFrame> encoded_frame) {
128 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
129 if (!encoded_frame) {
130 callback.Run(make_scoped_ptr<AudioBus>(NULL), base::TimeTicks(), false);
131 return;
134 if (!audio_decoder_) {
135 audio_decoder_.reset(new AudioDecoder(cast_environment_,
136 num_audio_channels_,
137 audio_sampling_rate_,
138 audio_codec_));
140 const uint32 frame_id = encoded_frame->frame_id;
141 const uint32 rtp_timestamp = encoded_frame->rtp_timestamp;
142 const base::TimeTicks playout_time = encoded_frame->reference_time;
143 audio_decoder_->DecodeFrame(
144 encoded_frame.Pass(),
145 base::Bind(&CastReceiverImpl::EmitDecodedAudioFrame,
146 cast_environment_,
147 callback,
148 frame_id,
149 rtp_timestamp,
150 playout_time));
153 void CastReceiverImpl::DecodeEncodedVideoFrame(
154 const VideoFrameDecodedCallback& callback,
155 scoped_ptr<EncodedFrame> encoded_frame) {
156 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
157 if (!encoded_frame) {
158 callback.Run(
159 make_scoped_refptr<VideoFrame>(NULL), base::TimeTicks(), false);
160 return;
163 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
164 TRACE_EVENT_INSTANT2(
165 "cast_perf_test", "PullEncodedVideoFrame",
166 TRACE_EVENT_SCOPE_THREAD,
167 "rtp_timestamp", encoded_frame->rtp_timestamp,
168 "render_time", encoded_frame->reference_time.ToInternalValue());
170 if (!video_decoder_)
171 video_decoder_.reset(new VideoDecoder(cast_environment_, video_codec_));
172 const uint32 frame_id = encoded_frame->frame_id;
173 const uint32 rtp_timestamp = encoded_frame->rtp_timestamp;
174 const base::TimeTicks playout_time = encoded_frame->reference_time;
175 video_decoder_->DecodeFrame(
176 encoded_frame.Pass(),
177 base::Bind(&CastReceiverImpl::EmitDecodedVideoFrame,
178 cast_environment_,
179 callback,
180 frame_id,
181 rtp_timestamp,
182 playout_time));
185 // static
186 void CastReceiverImpl::EmitDecodedAudioFrame(
187 const scoped_refptr<CastEnvironment>& cast_environment,
188 const AudioFrameDecodedCallback& callback,
189 uint32 frame_id,
190 uint32 rtp_timestamp,
191 const base::TimeTicks& playout_time,
192 scoped_ptr<AudioBus> audio_bus,
193 bool is_continuous) {
194 DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN));
195 if (audio_bus.get()) {
196 const base::TimeTicks now = cast_environment->Clock()->NowTicks();
197 cast_environment->Logging()->InsertFrameEvent(
198 now, FRAME_DECODED, AUDIO_EVENT, rtp_timestamp, frame_id);
199 cast_environment->Logging()->InsertFrameEventWithDelay(
200 now, FRAME_PLAYOUT, AUDIO_EVENT, rtp_timestamp, frame_id,
201 playout_time - now);
203 callback.Run(audio_bus.Pass(), playout_time, is_continuous);
206 // static
207 void CastReceiverImpl::EmitDecodedVideoFrame(
208 const scoped_refptr<CastEnvironment>& cast_environment,
209 const VideoFrameDecodedCallback& callback,
210 uint32 frame_id,
211 uint32 rtp_timestamp,
212 const base::TimeTicks& playout_time,
213 const scoped_refptr<VideoFrame>& video_frame,
214 bool is_continuous) {
215 DCHECK(cast_environment->CurrentlyOn(CastEnvironment::MAIN));
216 if (video_frame.get()) {
217 const base::TimeTicks now = cast_environment->Clock()->NowTicks();
218 cast_environment->Logging()->InsertFrameEvent(
219 now, FRAME_DECODED, VIDEO_EVENT, rtp_timestamp, frame_id);
220 cast_environment->Logging()->InsertFrameEventWithDelay(
221 now, FRAME_PLAYOUT, VIDEO_EVENT, rtp_timestamp, frame_id,
222 playout_time - now);
224 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
225 TRACE_EVENT_INSTANT1(
226 "cast_perf_test", "FrameDecoded",
227 TRACE_EVENT_SCOPE_THREAD,
228 "rtp_timestamp", rtp_timestamp);
230 callback.Run(video_frame, playout_time, is_continuous);
233 } // namespace cast
234 } // namespace media