audio_directive_list.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 "components/copresence/handlers/audio/audio_directive_list.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/strings/string_util.h" 10#include "media/base/audio_bus.h" 11 12namespace { 13 14// UrlSafe is defined as: 15// '/' represented by a '_' and '+' represented by a '-' 16// TODO(rkc): Move this processing to the whispernet wrapper. 17std::string FromUrlSafe(std::string token) { 18 base::ReplaceChars(token, "-", "+", &token); 19 base::ReplaceChars(token, "_", "/", &token); 20 return token; 21} 22 23const int kSampleExpiryTimeMs = 60 * 60 * 1000; // 60 minutes. 24const int kMaxSamples = 10000; 25 26} // namespace 27 28namespace copresence { 29 30// Public methods. 31 32AudioDirective::AudioDirective() { 33} 34 35AudioDirective::AudioDirective(const std::string& token, 36 const std::string& op_id, 37 base::Time end_time) 38 : token(token), op_id(op_id), end_time(end_time) { 39} 40 41AudioDirective::AudioDirective( 42 const std::string& token, 43 const std::string& op_id, 44 base::Time end_time, 45 const scoped_refptr<media::AudioBusRefCounted>& samples) 46 : token(token), op_id(op_id), end_time(end_time), samples(samples) { 47} 48 49AudioDirective::~AudioDirective() { 50} 51 52AudioDirectiveList::AudioDirectiveList( 53 const EncodeTokenCallback& encode_token_callback, 54 const base::Closure& token_added_callback) 55 : encode_token_callback_(encode_token_callback), 56 token_added_callback_(token_added_callback), 57 samples_cache_(base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs), 58 kMaxSamples) { 59} 60 61AudioDirectiveList::~AudioDirectiveList() { 62} 63 64void AudioDirectiveList::AddTransmitDirective(const std::string& token, 65 const std::string& op_id, 66 base::TimeDelta ttl) { 67 std::string valid_token = FromUrlSafe(token); 68 base::Time end_time = base::Time::Now() + ttl; 69 70 if (samples_cache_.HasKey(valid_token)) { 71 active_transmit_tokens_.push(AudioDirective( 72 valid_token, op_id, end_time, samples_cache_.GetValue(valid_token))); 73 return; 74 } 75 76 // If an encode request for this token has been sent, don't send it again. 77 if (pending_transmit_tokens_.find(valid_token) != 78 pending_transmit_tokens_.end()) { 79 return; 80 } 81 82 pending_transmit_tokens_[valid_token] = 83 AudioDirective(valid_token, op_id, end_time); 84 // All whispernet callbacks will be cleared before we are destructed, so 85 // unretained is safe to use here. 86 encode_token_callback_.Run( 87 valid_token, 88 base::Bind(&AudioDirectiveList::OnTokenEncoded, base::Unretained(this))); 89} 90 91void AudioDirectiveList::AddReceiveDirective(const std::string& op_id, 92 base::TimeDelta ttl) { 93 active_receive_tokens_.push( 94 AudioDirective(std::string(), op_id, base::Time::Now() + ttl)); 95} 96 97scoped_ptr<AudioDirective> AudioDirectiveList::GetNextTransmit() { 98 return GetNextFromList(&active_transmit_tokens_); 99} 100 101scoped_ptr<AudioDirective> AudioDirectiveList::GetNextReceive() { 102 return GetNextFromList(&active_receive_tokens_); 103} 104 105scoped_ptr<AudioDirective> AudioDirectiveList::GetNextFromList( 106 AudioDirectiveQueue* list) { 107 CHECK(list); 108 109 // Checks if we have any valid tokens at all (since the top of the list is 110 // always pointing to the token with the latest expiry time). If we don't 111 // have any valid tokens left, clear the list. 112 if (!list->empty() && list->top().end_time < base::Time::Now()) { 113 while (!list->empty()) 114 list->pop(); 115 } 116 117 if (list->empty()) 118 return make_scoped_ptr<AudioDirective>(NULL); 119 120 return make_scoped_ptr(new AudioDirective(list->top())); 121} 122 123void AudioDirectiveList::OnTokenEncoded( 124 const std::string& token, 125 const scoped_refptr<media::AudioBusRefCounted>& samples) { 126 // We shouldn't re-encode a token if it's already in the cache. 127 DCHECK(!samples_cache_.HasKey(token)); 128 DVLOG(3) << "Token: " << token << " encoded."; 129 samples_cache_.Add(token, samples); 130 131 // Copy the samples into their corresponding directive object and move 132 // that object into the active queue. 133 std::map<std::string, AudioDirective>::iterator it = 134 pending_transmit_tokens_.find(token); 135 136 it->second.samples = samples; 137 active_transmit_tokens_.push(it->second); 138 pending_transmit_tokens_.erase(it); 139 140 if (!token_added_callback_.is_null()) 141 token_added_callback_.Run(); 142} 143 144} // namespace copresence 145