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/audio_receiver/audio_receiver.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_piece.h"
11 #include "media/cast/audio_receiver/audio_decoder.h"
12 #include "media/cast/framer/framer.h"
13 #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
14 #include "media/cast/rtcp/rtcp.h"
15 #include "media/cast/rtp_receiver/rtp_receiver.h"
16 #include "media/cast/transport/cast_transport_defines.h"
20 using media::cast::kMaxIpPacketSize
;
21 using media::cast::kRtcpCastLogHeaderSize
;
22 using media::cast::kRtcpReceiverEventLogSize
;
24 // Max time we wait until an audio frame is due to be played out is released.
25 static const int64 kMaxAudioFrameWaitMs
= 20;
26 static const int64 kMinSchedulingDelayMs
= 1;
28 // This is an upper bound on number of events that can fit into a single RTCP
30 static const int64 kMaxEventSubscriberEntries
=
31 (kMaxIpPacketSize
- kRtcpCastLogHeaderSize
) / kRtcpReceiverEventLogSize
;
38 DecodedAudioCallbackData::DecodedAudioCallbackData()
39 : number_of_10ms_blocks(0), desired_frequency(0), callback() {}
41 DecodedAudioCallbackData::~DecodedAudioCallbackData() {}
43 // Local implementation of RtpData (defined in rtp_rtcp_defines.h).
44 // Used to pass payload data into the audio receiver.
45 class LocalRtpAudioData
: public RtpData
{
47 explicit LocalRtpAudioData(AudioReceiver
* audio_receiver
)
48 : audio_receiver_(audio_receiver
) {}
50 virtual void OnReceivedPayloadData(const uint8
* payload_data
,
52 const RtpCastHeader
* rtp_header
) OVERRIDE
{
53 audio_receiver_
->IncomingParsedRtpPacket(payload_data
, payload_size
,
58 AudioReceiver
* audio_receiver_
;
61 // Local implementation of RtpPayloadFeedback (defined in rtp_defines.h)
62 // Used to convey cast-specific feedback from receiver to sender.
63 class LocalRtpAudioFeedback
: public RtpPayloadFeedback
{
65 explicit LocalRtpAudioFeedback(AudioReceiver
* audio_receiver
)
66 : audio_receiver_(audio_receiver
) {}
68 virtual void CastFeedback(const RtcpCastMessage
& cast_message
) OVERRIDE
{
69 audio_receiver_
->CastFeedback(cast_message
);
73 AudioReceiver
* audio_receiver_
;
76 class LocalRtpReceiverStatistics
: public RtpReceiverStatistics
{
78 explicit LocalRtpReceiverStatistics(RtpReceiver
* rtp_receiver
)
79 : rtp_receiver_(rtp_receiver
) {}
81 virtual void GetStatistics(uint8
* fraction_lost
,
82 uint32
* cumulative_lost
, // 24 bits valid.
83 uint32
* extended_high_sequence_number
,
84 uint32
* jitter
) OVERRIDE
{
85 rtp_receiver_
->GetStatistics(fraction_lost
, cumulative_lost
,
86 extended_high_sequence_number
, jitter
);
90 RtpReceiver
* rtp_receiver_
;
93 AudioReceiver::AudioReceiver(scoped_refptr
<CastEnvironment
> cast_environment
,
94 const AudioReceiverConfig
& audio_config
,
95 transport::PacedPacketSender
* const packet_sender
)
96 : cast_environment_(cast_environment
),
98 kMaxEventSubscriberEntries
,
99 ReceiverRtcpEventSubscriber::kAudioEventSubscriber
),
100 codec_(audio_config
.codec
),
101 frequency_(audio_config
.frequency
),
105 weak_factory_(this) {
106 target_delay_delta_
=
107 base::TimeDelta::FromMilliseconds(audio_config
.rtp_max_delay_ms
);
108 incoming_payload_callback_
.reset(new LocalRtpAudioData(this));
109 incoming_payload_feedback_
.reset(new LocalRtpAudioFeedback(this));
110 if (audio_config
.use_external_decoder
) {
111 audio_buffer_
.reset(new Framer(cast_environment
->Clock(),
112 incoming_payload_feedback_
.get(),
113 audio_config
.incoming_ssrc
, true, 0));
115 audio_decoder_
.reset(new AudioDecoder(cast_environment
, audio_config
,
116 incoming_payload_feedback_
.get()));
118 decryptor_
.Initialize(audio_config
.aes_key
, audio_config
.aes_iv_mask
);
119 rtp_receiver_
.reset(new RtpReceiver(cast_environment
->Clock(),
122 incoming_payload_callback_
.get()));
123 rtp_audio_receiver_statistics_
.reset(
124 new LocalRtpReceiverStatistics(rtp_receiver_
.get()));
125 base::TimeDelta rtcp_interval_delta
=
126 base::TimeDelta::FromMilliseconds(audio_config
.rtcp_interval
);
127 rtcp_
.reset(new Rtcp(cast_environment
, NULL
, NULL
, packet_sender
, NULL
,
128 rtp_audio_receiver_statistics_
.get(),
129 audio_config
.rtcp_mode
, rtcp_interval_delta
,
130 audio_config
.feedback_ssrc
, audio_config
.incoming_ssrc
,
131 audio_config
.rtcp_c_name
));
132 cast_environment_
->Logging()->AddRawEventSubscriber(&event_subscriber_
);
135 AudioReceiver::~AudioReceiver() {
136 cast_environment_
->Logging()->RemoveRawEventSubscriber(&event_subscriber_
);
139 void AudioReceiver::InitializeTimers() {
140 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
141 ScheduleNextRtcpReport();
142 ScheduleNextCastMessage();
145 void AudioReceiver::IncomingParsedRtpPacket(const uint8
* payload_data
,
147 const RtpCastHeader
& rtp_header
) {
148 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
149 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
151 cast_environment_
->Logging()->InsertPacketEvent(
152 now
, kAudioPacketReceived
, rtp_header
.webrtc
.header
.timestamp
,
153 rtp_header
.frame_id
, rtp_header
.packet_id
, rtp_header
.max_packet_id
,
156 // TODO(pwestin): update this as video to refresh over time.
157 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
158 if (time_first_incoming_packet_
.is_null()) {
160 first_incoming_rtp_timestamp_
= rtp_header
.webrtc
.header
.timestamp
;
161 time_first_incoming_packet_
= now
;
164 if (audio_decoder_
) {
165 DCHECK(!audio_buffer_
) << "Invalid internal state";
166 std::string plaintext
;
167 if (decryptor_
.initialized()) {
168 if (!decryptor_
.Decrypt(
170 base::StringPiece(reinterpret_cast<const char*>(payload_data
),
175 plaintext
.append(reinterpret_cast<const char*>(payload_data
),
178 audio_decoder_
->IncomingParsedRtpPacket(
179 reinterpret_cast<const uint8
*>(plaintext
.data()), plaintext
.size(),
181 if (!queued_decoded_callbacks_
.empty()) {
182 DecodedAudioCallbackData decoded_data
= queued_decoded_callbacks_
.front();
183 queued_decoded_callbacks_
.pop_front();
184 cast_environment_
->PostTask(
185 CastEnvironment::AUDIO_DECODER
, FROM_HERE
,
186 base::Bind(&AudioReceiver::DecodeAudioFrameThread
,
187 base::Unretained(this), decoded_data
.number_of_10ms_blocks
,
188 decoded_data
.desired_frequency
, decoded_data
.callback
));
193 DCHECK(audio_buffer_
) << "Invalid internal state";
194 DCHECK(!audio_decoder_
) << "Invalid internal state";
196 bool duplicate
= false;
197 bool complete
= audio_buffer_
->InsertPacket(payload_data
, payload_size
,
198 rtp_header
, &duplicate
);
200 cast_environment_
->Logging()->InsertPacketEvent(
201 now
, kDuplicatePacketReceived
, rtp_header
.webrtc
.header
.timestamp
,
202 rtp_header
.frame_id
, rtp_header
.packet_id
, rtp_header
.max_packet_id
,
204 // Duplicate packets are ignored.
207 if (!complete
) return; // Audio frame not complete; wait for more packets.
208 if (queued_encoded_callbacks_
.empty()) return;
209 AudioFrameEncodedCallback callback
= queued_encoded_callbacks_
.front();
210 queued_encoded_callbacks_
.pop_front();
211 cast_environment_
->PostTask(CastEnvironment::MAIN
, FROM_HERE
,
212 base::Bind(&AudioReceiver::GetEncodedAudioFrame
,
213 weak_factory_
.GetWeakPtr(), callback
));
216 void AudioReceiver::GetRawAudioFrame(
217 int number_of_10ms_blocks
, int desired_frequency
,
218 const AudioFrameDecodedCallback
& callback
) {
219 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
220 DCHECK(audio_decoder_
) << "Invalid function call in this configuration";
221 // TODO(pwestin): we can skip this function by posting direct to the decoder.
222 cast_environment_
->PostTask(
223 CastEnvironment::AUDIO_DECODER
, FROM_HERE
,
224 base::Bind(&AudioReceiver::DecodeAudioFrameThread
, base::Unretained(this),
225 number_of_10ms_blocks
, desired_frequency
, callback
));
228 void AudioReceiver::DecodeAudioFrameThread(
229 int number_of_10ms_blocks
, int desired_frequency
,
230 const AudioFrameDecodedCallback callback
) {
231 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::AUDIO_DECODER
));
232 // TODO(mikhal): Allow the application to allocate this memory.
233 scoped_ptr
<PcmAudioFrame
> audio_frame(new PcmAudioFrame());
235 uint32 rtp_timestamp
= 0;
236 if (!audio_decoder_
->GetRawAudioFrame(number_of_10ms_blocks
,
237 desired_frequency
, audio_frame
.get(),
239 DecodedAudioCallbackData callback_data
;
240 callback_data
.number_of_10ms_blocks
= number_of_10ms_blocks
;
241 callback_data
.desired_frequency
= desired_frequency
;
242 callback_data
.callback
= callback
;
243 queued_decoded_callbacks_
.push_back(callback_data
);
247 cast_environment_
->PostTask(
248 CastEnvironment::MAIN
, FROM_HERE
,
249 base::Bind(&AudioReceiver::ReturnDecodedFrameWithPlayoutDelay
,
250 base::Unretained(this), base::Passed(&audio_frame
),
251 rtp_timestamp
, callback
));
254 void AudioReceiver::ReturnDecodedFrameWithPlayoutDelay(
255 scoped_ptr
<PcmAudioFrame
> audio_frame
, uint32 rtp_timestamp
,
256 const AudioFrameDecodedCallback callback
) {
257 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
258 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
259 cast_environment_
->Logging()->InsertFrameEvent(
260 now
, kAudioFrameDecoded
, rtp_timestamp
, kFrameIdUnknown
);
262 base::TimeTicks playout_time
= GetPlayoutTime(now
, rtp_timestamp
);
264 cast_environment_
->Logging()->InsertFrameEventWithDelay(
265 now
, kAudioPlayoutDelay
, rtp_timestamp
, kFrameIdUnknown
,
268 // Frame is ready - Send back to the caller.
269 cast_environment_
->PostTask(
270 CastEnvironment::MAIN
, FROM_HERE
,
271 base::Bind(callback
, base::Passed(&audio_frame
), playout_time
));
274 void AudioReceiver::PlayoutTimeout() {
275 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
276 DCHECK(audio_buffer_
) << "Invalid function call in this configuration";
277 if (queued_encoded_callbacks_
.empty()) {
278 // Already released by incoming packet.
281 bool next_frame
= false;
282 scoped_ptr
<transport::EncodedAudioFrame
> encoded_frame(
283 new transport::EncodedAudioFrame());
285 if (!audio_buffer_
->GetEncodedAudioFrame(encoded_frame
.get(), &next_frame
)) {
286 // We have no audio frames. Wait for new packet(s).
287 // Since the application can post multiple AudioFrameEncodedCallback and
288 // we only check the next frame to play out we might have multiple timeout
289 // events firing after each other; however this should be a rare event.
290 VLOG(1) << "Failed to retrieved a complete frame at this point in time";
294 if (decryptor_
.initialized() && !DecryptAudioFrame(&encoded_frame
)) {
295 // Logging already done.
299 if (PostEncodedAudioFrame(
300 queued_encoded_callbacks_
.front(), next_frame
, &encoded_frame
)) {
301 // Call succeed remove callback from list.
302 queued_encoded_callbacks_
.pop_front();
306 void AudioReceiver::GetEncodedAudioFrame(
307 const AudioFrameEncodedCallback
& callback
) {
308 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
309 DCHECK(audio_buffer_
) << "Invalid function call in this configuration";
311 bool next_frame
= false;
312 scoped_ptr
<transport::EncodedAudioFrame
> encoded_frame(
313 new transport::EncodedAudioFrame());
315 if (!audio_buffer_
->GetEncodedAudioFrame(encoded_frame
.get(), &next_frame
)) {
316 // We have no audio frames. Wait for new packet(s).
317 VLOG(1) << "Wait for more audio packets in frame";
318 queued_encoded_callbacks_
.push_back(callback
);
321 if (decryptor_
.initialized() && !DecryptAudioFrame(&encoded_frame
)) {
322 // Logging already done.
323 queued_encoded_callbacks_
.push_back(callback
);
326 if (!PostEncodedAudioFrame(callback
, next_frame
, &encoded_frame
)) {
327 // We have an audio frame; however we are missing packets and we have time
328 // to wait for new packet(s).
329 queued_encoded_callbacks_
.push_back(callback
);
333 bool AudioReceiver::PostEncodedAudioFrame(
334 const AudioFrameEncodedCallback
& callback
,
336 scoped_ptr
<transport::EncodedAudioFrame
>* encoded_frame
) {
337 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
338 DCHECK(audio_buffer_
) << "Invalid function call in this configuration";
339 DCHECK(encoded_frame
) << "Invalid encoded_frame";
341 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
342 base::TimeTicks playout_time
=
343 GetPlayoutTime(now
, (*encoded_frame
)->rtp_timestamp
);
344 base::TimeDelta time_until_playout
= playout_time
- now
;
345 base::TimeDelta min_wait_delta
=
346 base::TimeDelta::FromMilliseconds(kMaxAudioFrameWaitMs
);
348 if (!next_frame
&& (time_until_playout
> min_wait_delta
)) {
349 base::TimeDelta time_until_release
= time_until_playout
- min_wait_delta
;
350 cast_environment_
->PostDelayedTask(
351 CastEnvironment::MAIN
, FROM_HERE
,
352 base::Bind(&AudioReceiver::PlayoutTimeout
, weak_factory_
.GetWeakPtr()),
354 VLOG(1) << "Wait until time to playout:"
355 << time_until_release
.InMilliseconds();
358 (*encoded_frame
)->codec
= codec_
;
359 audio_buffer_
->ReleaseFrame((*encoded_frame
)->frame_id
);
361 cast_environment_
->PostTask(
362 CastEnvironment::MAIN
, FROM_HERE
,
363 base::Bind(callback
, base::Passed(encoded_frame
), playout_time
));
367 void AudioReceiver::IncomingPacket(scoped_ptr
<Packet
> packet
) {
368 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
369 bool rtcp_packet
= Rtcp::IsRtcpPacket(&packet
->front(), packet
->size());
371 rtp_receiver_
->ReceivedPacket(&packet
->front(), packet
->size());
373 rtcp_
->IncomingRtcpPacket(&packet
->front(), packet
->size());
377 void AudioReceiver::CastFeedback(const RtcpCastMessage
& cast_message
) {
378 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
379 cast_environment_
->Logging()->InsertGenericEvent(now
, kAudioAckSent
,
380 cast_message
.ack_frame_id_
);
382 rtcp_
->SendRtcpFromRtpReceiver(&cast_message
, &event_subscriber_
);
385 base::TimeTicks
AudioReceiver::GetPlayoutTime(base::TimeTicks now
,
386 uint32 rtp_timestamp
) {
387 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
388 // Senders time in ms when this frame was recorded.
389 // Note: the senders clock and our local clock might not be synced.
390 base::TimeTicks rtp_timestamp_in_ticks
;
391 base::TimeTicks playout_time
;
392 if (time_offset_
== base::TimeDelta()) {
393 if (rtcp_
->RtpTimestampInSenderTime(frequency_
,
394 first_incoming_rtp_timestamp_
,
395 &rtp_timestamp_in_ticks
)) {
396 time_offset_
= time_first_incoming_packet_
- rtp_timestamp_in_ticks
;
398 // We have not received any RTCP to sync the stream play it out as soon as
400 uint32 rtp_timestamp_diff
= rtp_timestamp
- first_incoming_rtp_timestamp_
;
402 int frequency_khz
= frequency_
/ 1000;
403 base::TimeDelta rtp_time_diff_delta
=
404 base::TimeDelta::FromMilliseconds(rtp_timestamp_diff
/ frequency_khz
);
405 base::TimeDelta time_diff_delta
= now
- time_first_incoming_packet_
;
407 playout_time
= now
+ std::max(rtp_time_diff_delta
- time_diff_delta
,
411 if (playout_time
.is_null()) {
412 // This can fail if we have not received any RTCP packets in a long time.
413 if (rtcp_
->RtpTimestampInSenderTime(frequency_
, rtp_timestamp
,
414 &rtp_timestamp_in_ticks
)) {
416 rtp_timestamp_in_ticks
+ time_offset_
+ target_delay_delta_
;
421 // Don't allow the playout time to go backwards.
422 if (last_playout_time_
> playout_time
) playout_time
= last_playout_time_
;
423 last_playout_time_
= playout_time
;
427 bool AudioReceiver::DecryptAudioFrame(
428 scoped_ptr
<transport::EncodedAudioFrame
>* audio_frame
) {
429 if (!decryptor_
.initialized())
432 std::string decrypted_audio_data
;
433 if (!decryptor_
.Decrypt((*audio_frame
)->frame_id
,
434 (*audio_frame
)->data
,
435 &decrypted_audio_data
)) {
436 // Give up on this frame, release it from the jitter buffer.
437 audio_buffer_
->ReleaseFrame((*audio_frame
)->frame_id
);
440 (*audio_frame
)->data
.swap(decrypted_audio_data
);
444 void AudioReceiver::ScheduleNextRtcpReport() {
445 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
446 base::TimeDelta time_to_send
= rtcp_
->TimeToSendNextRtcpReport() -
447 cast_environment_
->Clock()->NowTicks();
449 time_to_send
= std::max(
450 time_to_send
, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs
));
452 cast_environment_
->PostDelayedTask(
453 CastEnvironment::MAIN
, FROM_HERE
,
454 base::Bind(&AudioReceiver::SendNextRtcpReport
,
455 weak_factory_
.GetWeakPtr()),
459 void AudioReceiver::SendNextRtcpReport() {
460 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
461 // TODO(pwestin): add logging.
462 rtcp_
->SendRtcpFromRtpReceiver(NULL
, NULL
);
463 ScheduleNextRtcpReport();
466 // Cast messages should be sent within a maximum interval. Schedule a call
467 // if not triggered elsewhere, e.g. by the cast message_builder.
468 void AudioReceiver::ScheduleNextCastMessage() {
469 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
470 base::TimeTicks send_time
;
472 audio_buffer_
->TimeToSendNextCastMessage(&send_time
);
473 } else if (audio_decoder_
) {
474 audio_decoder_
->TimeToSendNextCastMessage(&send_time
);
478 base::TimeDelta time_to_send
=
479 send_time
- cast_environment_
->Clock()->NowTicks();
480 time_to_send
= std::max(
481 time_to_send
, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs
));
482 cast_environment_
->PostDelayedTask(
483 CastEnvironment::MAIN
, FROM_HERE
,
484 base::Bind(&AudioReceiver::SendNextCastMessage
,
485 weak_factory_
.GetWeakPtr()),
489 void AudioReceiver::SendNextCastMessage() {
490 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
493 // Will only send a message if it is time.
494 audio_buffer_
->SendCastMessage();
496 if (audio_decoder_
) {
497 // Will only send a message if it is time.
498 audio_decoder_
->SendCastMessage();
500 ScheduleNextCastMessage();