1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file. 4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/cast/audio_receiver/audio_receiver.h" 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/bind.h" 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/logging.h" 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "crypto/encryptor.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "crypto/symmetric_key.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/cast/audio_receiver/audio_decoder.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/cast/framer/framer.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/cast/rtcp/rtcp.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/cast/rtp_receiver/rtp_receiver.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Max time we wait until an audio frame is due to be played out is released. 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const int64 kMaxAudioFrameWaitMs = 20; 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const int64 kMinSchedulingDelayMs = 1; 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace media { 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace cast { 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)DecodedAudioCallbackData::DecodedAudioCallbackData() 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : number_of_10ms_blocks(0), 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) desired_frequency(0), 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback() {} 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)DecodedAudioCallbackData::~DecodedAudioCallbackData() {} 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Local implementation of RtpData (defined in rtp_rtcp_defines.h). 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Used to pass payload data into the audio receiver. 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class LocalRtpAudioData : public RtpData { 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) explicit LocalRtpAudioData(AudioReceiver* audio_receiver) 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : audio_receiver_(audio_receiver) {} 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnReceivedPayloadData( 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint8* payload_data, 408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t payload_size, 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const RtpCastHeader* rtp_header) OVERRIDE { 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_receiver_->IncomingParsedRtpPacket(payload_data, payload_size, 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *rtp_header); 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioReceiver* audio_receiver_; 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Local implementation of RtpPayloadFeedback (defined in rtp_defines.h) 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Used to convey cast-specific feedback from receiver to sender. 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class LocalRtpAudioFeedback : public RtpPayloadFeedback { 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit LocalRtpAudioFeedback(AudioReceiver* audio_receiver) 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : audio_receiver_(audio_receiver) { 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void CastFeedback(const RtcpCastMessage& cast_message) OVERRIDE { 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_receiver_->CastFeedback(cast_message); 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioReceiver* audio_receiver_; 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class LocalRtpReceiverStatistics : public RtpReceiverStatistics { 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit LocalRtpReceiverStatistics(RtpReceiver* rtp_receiver) 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : rtp_receiver_(rtp_receiver) { 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void GetStatistics(uint8* fraction_lost, 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32* cumulative_lost, // 24 bits valid. 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32* extended_high_sequence_number, 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32* jitter) OVERRIDE { 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rtp_receiver_->GetStatistics(fraction_lost, 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) cumulative_lost, 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) extended_high_sequence_number, 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) jitter); 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RtpReceiver* rtp_receiver_; 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment, 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const AudioReceiverConfig& audio_config, 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PacedPacketSender* const packet_sender) 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : cast_environment_(cast_environment), 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) codec_(audio_config.codec), 91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) frequency_(audio_config.frequency), 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_buffer_(), 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_decoder_(), 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) time_offset_(), 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) weak_factory_(this) { 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) target_delay_delta_ = 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms); 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) incoming_payload_callback_.reset(new LocalRtpAudioData(this)); 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this)); 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (audio_config.use_external_decoder) { 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_buffer_.reset(new Framer(cast_environment->Clock(), 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) incoming_payload_feedback_.get(), 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_config.incoming_ssrc, 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) true, 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 0)); 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_decoder_.reset(new AudioDecoder(cast_environment, 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_config, 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) incoming_payload_feedback_.get())); 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (audio_config.aes_iv_mask.size() == kAesKeySize && 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_config.aes_key.size() == kAesKeySize) { 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) iv_mask_ = audio_config.aes_iv_mask; 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) crypto::SymmetricKey* key = crypto::SymmetricKey::Import( 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) crypto::SymmetricKey::AES, audio_config.aes_key); 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) decryptor_.reset(new crypto::Encryptor()); 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) decryptor_->Init(key, crypto::Encryptor::CTR, std::string()); 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (audio_config.aes_iv_mask.size() != 0 || 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_config.aes_key.size() != 0) { 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(false) << "Invalid crypto configuration"; 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(), 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &audio_config, 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NULL, 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) incoming_payload_callback_.get())); 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rtp_audio_receiver_statistics_.reset( 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) new LocalRtpReceiverStatistics(rtp_receiver_.get())); 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta rtcp_interval_delta = 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval); 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtcp_.reset(new Rtcp(cast_environment, 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NULL, 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) packet_sender, 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NULL, 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rtp_audio_receiver_statistics_.get(), 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_config.rtcp_mode, 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rtcp_interval_delta, 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_config.feedback_ssrc, 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_config.incoming_ssrc, 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_config.rtcp_c_name)); 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)AudioReceiver::~AudioReceiver() {} 144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AudioReceiver::InitializeTimers() { 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScheduleNextRtcpReport(); 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScheduleNextCastMessage(); 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::IncomingParsedRtpPacket(const uint8* payload_data, 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t payload_size, 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const RtpCastHeader& rtp_header) { 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cast_environment_->Logging()->InsertPacketEvent(kPacketReceived, 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtp_header.webrtc.header.timestamp, rtp_header.frame_id, 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtp_header.packet_id, rtp_header.max_packet_id, payload_size); 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(pwestin): update this as video to refresh over time. 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (time_first_incoming_packet_.is_null()) { 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitializeTimers(); 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp; 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) time_first_incoming_packet_ = cast_environment_->Clock()->NowTicks(); 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (audio_decoder_) { 168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!audio_buffer_) << "Invalid internal state"; 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string plaintext(reinterpret_cast<const char*>(payload_data), 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) payload_size); 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (decryptor_) { 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) plaintext.clear(); 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!decryptor_->SetCounter(GetAesNonce(rtp_header.frame_id, iv_mask_))) { 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED() << "Failed to set counter"; 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!decryptor_->Decrypt(base::StringPiece(reinterpret_cast<const char*>( 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) payload_data), payload_size), &plaintext)) { 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Decryption error"; 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_decoder_->IncomingParsedRtpPacket( 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(), 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtp_header); 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!queued_decoded_callbacks_.empty()) { 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DecodedAudioCallbackData decoded_data = queued_decoded_callbacks_.front(); 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) queued_decoded_callbacks_.pop_front(); 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cast_environment_->PostTask(CastEnvironment::AUDIO_DECODER, FROM_HERE, 190d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::Bind(&AudioReceiver::DecodeAudioFrameThread, 191d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::Unretained(this), 192d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) decoded_data.number_of_10ms_blocks, 193d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) decoded_data.desired_frequency, 194d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) decoded_data.callback)); 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(audio_buffer_) << "Invalid internal state"; 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(!audio_decoder_) << "Invalid internal state"; 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool complete = audio_buffer_->InsertPacket(payload_data, payload_size, 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rtp_header); 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!complete) return; // Audio frame not complete; wait for more packets. 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (queued_encoded_callbacks_.empty()) return; 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AudioFrameEncodedCallback callback = queued_encoded_callbacks_.front(); 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) queued_encoded_callbacks_.pop_front(); 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&AudioReceiver::GetEncodedAudioFrame, 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_factory_.GetWeakPtr(), callback)); 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::GetRawAudioFrame(int number_of_10ms_blocks, 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int desired_frequency, const AudioFrameDecodedCallback& callback) { 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(audio_decoder_) << "Invalid function call in this configuration"; 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(pwestin): we can skip this function by posting direct to the decoder. 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostTask(CastEnvironment::AUDIO_DECODER, FROM_HERE, 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&AudioReceiver::DecodeAudioFrameThread, 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Unretained(this), 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) number_of_10ms_blocks, 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) desired_frequency, 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) callback)); 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::DecodeAudioFrameThread( 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int number_of_10ms_blocks, 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int desired_frequency, 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const AudioFrameDecodedCallback callback) { 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_DECODER)); 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(mikhal): Allow the application to allocate this memory. 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<PcmAudioFrame> audio_frame(new PcmAudioFrame()); 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 rtp_timestamp = 0; 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!audio_decoder_->GetRawAudioFrame(number_of_10ms_blocks, 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) desired_frequency, 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_frame.get(), 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &rtp_timestamp)) { 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DecodedAudioCallbackData callback_data; 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback_data.number_of_10ms_blocks = number_of_10ms_blocks; 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback_data.desired_frequency = desired_frequency; 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback_data.callback = callback; 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) queued_decoded_callbacks_.push_back(callback_data); 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&AudioReceiver::ReturnDecodedFrameWithPlayoutDelay, 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Unretained(this), base::Passed(&audio_frame), rtp_timestamp, 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback)); 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AudioReceiver::ReturnDecodedFrameWithPlayoutDelay( 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<PcmAudioFrame> audio_frame, uint32 rtp_timestamp, 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const AudioFrameDecodedCallback callback) { 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cast_environment_->Logging()->InsertFrameEvent(kAudioFrameDecoded, 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rtp_timestamp, kFrameIdUnknown); 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks playout_time = GetPlayoutTime(now, rtp_timestamp); 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cast_environment_->Logging()->InsertFrameEventWithDelay(kAudioPlayoutDelay, 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtp_timestamp, kFrameIdUnknown, playout_time - now); 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Frame is ready - Send back to the caller. 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(callback, base::Passed(&audio_frame), playout_time)); 270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AudioReceiver::PlayoutTimeout() { 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 2740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (queued_encoded_callbacks_.empty()) { 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Already released by incoming packet. 2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 rtp_timestamp = 0; 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool next_frame = false; 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &rtp_timestamp, &next_frame)) { 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We have no audio frames. Wait for new packet(s). 2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Since the application can post multiple AudioFrameEncodedCallback and 2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // we only check the next frame to play out we might have multiple timeout 2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // events firing after each other; however this should be a rare event. 2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) VLOG(1) << "Failed to retrieved a complete frame at this point in time"; 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (decryptor_ && !DecryptAudioFrame(&encoded_frame)) { 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Logging already done. 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (PostEncodedAudioFrame(queued_encoded_callbacks_.front(), rtp_timestamp, 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) next_frame, &encoded_frame)) { 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Call succeed remove callback from list. 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) queued_encoded_callbacks_.pop_front(); 3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AudioReceiver::GetEncodedAudioFrame( 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const AudioFrameEncodedCallback& callback) { 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32 rtp_timestamp = 0; 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool next_frame = false; 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<EncodedAudioFrame> encoded_frame(new EncodedAudioFrame()); 3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!audio_buffer_->GetEncodedAudioFrame(encoded_frame.get(), 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &rtp_timestamp, &next_frame)) { 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We have no audio frames. Wait for new packet(s). 3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Wait for more audio packets in frame"; 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) queued_encoded_callbacks_.push_back(callback); 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (decryptor_ && !DecryptAudioFrame(&encoded_frame)) { 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Logging already done. 323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) queued_encoded_callbacks_.push_back(callback); 324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!PostEncodedAudioFrame(callback, rtp_timestamp, next_frame, 3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &encoded_frame)) { 3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We have an audio frame; however we are missing packets and we have time 3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // to wait for new packet(s). 3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) queued_encoded_callbacks_.push_back(callback); 3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool AudioReceiver::PostEncodedAudioFrame( 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const AudioFrameEncodedCallback& callback, 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32 rtp_timestamp, 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool next_frame, 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<EncodedAudioFrame>* encoded_frame) { 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 3400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(audio_buffer_) << "Invalid function call in this configuration"; 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeTicks playout_time = GetPlayoutTime(now, rtp_timestamp); 3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta time_until_playout = playout_time - now; 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta min_wait_delta = 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxAudioFrameWaitMs); 3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!next_frame && (time_until_playout > min_wait_delta)) { 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta time_until_release = time_until_playout - min_wait_delta; 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&AudioReceiver::PlayoutTimeout, weak_factory_.GetWeakPtr()), 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) time_until_release); 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Wait until time to playout:" 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << time_until_release.InMilliseconds(); 3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (*encoded_frame)->codec = codec_; 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) audio_buffer_->ReleaseFrame((*encoded_frame)->frame_id); 3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, 3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(callback, base::Passed(encoded_frame), playout_time)); 3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void AudioReceiver::IncomingPacket(const uint8* packet, size_t length, 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::Closure callback) { 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool rtcp_packet = Rtcp::IsRtcpPacket(packet, length); 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!rtcp_packet) { 370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rtp_receiver_->ReceivedPacket(packet, length); 371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) rtcp_->IncomingRtcpPacket(packet, length); 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback); 375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 377d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::CastFeedback(const RtcpCastMessage& cast_message) { 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(pwestin): add logging. 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtcp_->SendRtcpFromRtpReceiver(&cast_message, NULL); 380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)base::TimeTicks AudioReceiver::GetPlayoutTime(base::TimeTicks now, 383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 rtp_timestamp) { 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Senders time in ms when this frame was recorded. 386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note: the senders clock and our local clock might not be synced. 387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeTicks rtp_timestamp_in_ticks; 3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (time_offset_ == base::TimeDelta()) { 389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (rtcp_->RtpTimestampInSenderTime(frequency_, 3901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) first_incoming_rtp_timestamp_, 391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &rtp_timestamp_in_ticks)) { 3921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) time_offset_ = time_first_incoming_packet_ - rtp_timestamp_in_ticks; 393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We have not received any RTCP to sync the stream play it out as soon as 395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // possible. 3961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32 rtp_timestamp_diff = rtp_timestamp - first_incoming_rtp_timestamp_; 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int frequency_khz = frequency_ / 1000; 399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta rtp_time_diff_delta = 400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta::FromMilliseconds(rtp_timestamp_diff / frequency_khz); 4011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::TimeDelta time_diff_delta = now - time_first_incoming_packet_; 4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 403d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) return now + std::max(rtp_time_diff_delta - time_diff_delta, 404d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) base::TimeDelta()); 405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 407d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) // This can fail if we have not received any RTCP packets in a long time. 408d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) return rtcp_->RtpTimestampInSenderTime(frequency_, rtp_timestamp, 409d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) &rtp_timestamp_in_ticks) ? 410d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) rtp_timestamp_in_ticks + time_offset_ + target_delay_delta_ : 411d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles) now; 412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool AudioReceiver::DecryptAudioFrame( 415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<EncodedAudioFrame>* audio_frame) { 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(decryptor_) << "Invalid state"; 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!decryptor_->SetCounter(GetAesNonce((*audio_frame)->frame_id, 419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) iv_mask_))) { 420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED() << "Failed to set counter"; 421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string decrypted_audio_data; 424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!decryptor_->Decrypt((*audio_frame)->data, &decrypted_audio_data)) { 425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Decryption error"; 426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Give up on this frame, release it from jitter buffer. 427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) audio_buffer_->ReleaseFrame((*audio_frame)->frame_id); 428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (*audio_frame)->data.swap(decrypted_audio_data); 431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::ScheduleNextRtcpReport() { 435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TimeDelta time_to_send = rtcp_->TimeToSendNextRtcpReport() - 4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->Clock()->NowTicks(); 438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) time_to_send = std::max(time_to_send, 440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(&AudioReceiver::SendNextRtcpReport, 444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) weak_factory_.GetWeakPtr()), time_to_send); 445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void AudioReceiver::SendNextRtcpReport() { 448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(pwestin): add logging. 450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rtcp_->SendRtcpFromRtpReceiver(NULL, NULL); 451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ScheduleNextRtcpReport(); 452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Cast messages should be sent within a maximum interval. Schedule a call 4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// if not triggered elsewhere, e.g. by the cast message_builder. 4560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void AudioReceiver::ScheduleNextCastMessage() { 457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks send_time; 4590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (audio_buffer_) { 4600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) audio_buffer_->TimeToSendNextCastMessage(&send_time); 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (audio_decoder_) { 462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_decoder_->TimeToSendNextCastMessage(&send_time); 463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 4650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeDelta time_to_send = send_time - 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cast_environment_->Clock()->NowTicks(); 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) time_to_send = std::max(time_to_send, 469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&AudioReceiver::SendNextCastMessage, 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_factory_.GetWeakPtr()), time_to_send); 4730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void AudioReceiver::SendNextCastMessage() { 476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (audio_buffer_) { 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Will only send a message if it is time. 480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_buffer_->SendCastMessage(); 481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (audio_decoder_) { 483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Will only send a message if it is time. 484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) audio_decoder_->SendCastMessage(); 485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 4860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleNextCastMessage(); 4870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace cast 490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace media 491