Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: components/copresence/handlers/audio/audio_directive_handler.cc

Issue 461803003: Stop playing/recording when not needed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/copresence/handlers/audio/audio_directive_handler.cc
diff --git a/components/copresence/handlers/audio/audio_directive_handler.cc b/components/copresence/handlers/audio/audio_directive_handler.cc
index a5d3435c3c4864d71e83ef20d4416dccba1514cd..fcf1d8247c66c93a3cbe08e8d489b61f02eeba92 100644
--- a/components/copresence/handlers/audio/audio_directive_handler.cc
+++ b/components/copresence/handlers/audio/audio_directive_handler.cc
@@ -4,70 +4,88 @@
#include "components/copresence/handlers/audio/audio_directive_handler.h"
-#include <algorithm>
-
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "components/copresence/mediums/audio/audio_player.h"
#include "components/copresence/mediums/audio/audio_recorder.h"
#include "components/copresence/proto/data.pb.h"
#include "media/base/audio_bus.h"
+namespace {
+
+// UrlSafe is defined as:
+// '/' represented by a '_' and '+' represented by a '-'
+// TODO(rkc): Move this processing to the whispernet wrapper.
+std::string FromUrlSafe(std::string token) {
+ base::ReplaceChars(token, "-", "+", &token);
+ base::ReplaceChars(token, "_", "/", &token);
+ return token;
+}
+
+const int kSampleExpiryTimeMs = 60 * 60 * 1000; // 60 minutes.
+const int kMaxSamples = 10000;
+
+} // namespace
+
namespace copresence {
// Public methods.
AudioDirectiveHandler::AudioDirectiveHandler(
const AudioRecorder::DecodeSamplesCallback& decode_cb,
- const AudioDirectiveList::EncodeTokenCallback& encode_cb)
- : directive_list_inaudible_(
- encode_cb,
- base::Bind(&AudioDirectiveHandler::ExecuteNextTransmit,
- base::Unretained(this)),
- false),
- directive_list_audible_(
- encode_cb,
- base::Bind(&AudioDirectiveHandler::ExecuteNextTransmit,
- base::Unretained(this)),
- true),
- player_(NULL),
+ const AudioDirectiveHandler::EncodeTokenCallback& encode_cb)
+ : player_audible_(NULL),
+ player_inaudible_(NULL),
recorder_(NULL),
- decode_cb_(decode_cb) {
+ decode_cb_(decode_cb),
+ encode_cb_(encode_cb),
+ samples_cache_audible_(
+ base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs),
+ kMaxSamples),
+ samples_cache_inaudible_(
+ base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs),
+ kMaxSamples) {
}
AudioDirectiveHandler::~AudioDirectiveHandler() {
- if (player_)
- player_->Finalize();
+ if (player_audible_)
+ player_audible_->Finalize();
+ if (player_inaudible_)
+ player_inaudible_->Finalize();
if (recorder_)
recorder_->Finalize();
}
void AudioDirectiveHandler::Initialize() {
- player_ = new AudioPlayer();
- player_->Initialize();
+ player_audible_ = new AudioPlayer();
+ player_audible_->Initialize();
+
+ player_inaudible_ = new AudioPlayer();
+ player_inaudible_->Initialize();
recorder_ = new AudioRecorder(decode_cb_);
recorder_->Initialize();
}
void AudioDirectiveHandler::AddInstruction(const TokenInstruction& instruction,
+ const std::string& op_id,
base::TimeDelta ttl) {
switch (instruction.token_instruction_type()) {
case TRANSMIT:
DVLOG(2) << "Audio Transmit Directive received. Token: "
<< instruction.token_id()
<< " with TTL=" << ttl.InMilliseconds();
- // TODO(rkc): Fill in the op_id once we get it from the directive.
switch (instruction.medium()) {
case AUDIO_ULTRASOUND_PASSBAND:
- directive_list_inaudible_.AddTransmitDirective(
- instruction.token_id(), std::string(), ttl);
+ transmits_list_inaudible_.AddDirective(op_id, ttl);
+ HandleToken(instruction.token_id(), false);
break;
case AUDIO_AUDIBLE_DTMF:
- directive_list_audible_.AddTransmitDirective(
- instruction.token_id(), std::string(), ttl);
+ transmits_list_audible_.AddDirective(op_id, ttl);
+ HandleToken(instruction.token_id(), true);
break;
default:
NOTREACHED();
@@ -76,88 +94,128 @@ void AudioDirectiveHandler::AddInstruction(const TokenInstruction& instruction,
case RECEIVE:
DVLOG(2) << "Audio Receive Directive received. TTL="
<< ttl.InMilliseconds();
- // TODO(rkc): Fill in the op_id once we get it from the directive.
- switch (instruction.medium()) {
- case AUDIO_ULTRASOUND_PASSBAND:
- directive_list_inaudible_.AddReceiveDirective(std::string(), ttl);
- break;
- case AUDIO_AUDIBLE_DTMF:
- directive_list_audible_.AddReceiveDirective(std::string(), ttl);
- break;
- default:
- NOTREACHED();
- }
+ receives_list_.AddDirective(op_id, ttl);
break;
case UNKNOWN_TOKEN_INSTRUCTION_TYPE:
default:
LOG(WARNING) << "Unknown Audio Transmit Directive received.";
}
// ExecuteNextTransmit will be called by directive_list_ when Add is done.
- ExecuteNextReceive();
+ ProcessNextReceive();
}
-// Protected methods.
-
-void AudioDirectiveHandler::PlayAudio(
- const scoped_refptr<media::AudioBusRefCounted>& samples,
- base::TimeDelta duration) {
- player_->Play(samples);
- stop_playback_timer_.Start(
- FROM_HERE, duration, this, &AudioDirectiveHandler::StopPlayback);
-}
+void AudioDirectiveHandler::RemoveInstructions(const std::string& op_id) {
+ transmits_list_audible_.RemoveDirective(op_id);
+ transmits_list_inaudible_.RemoveDirective(op_id);
+ receives_list_.RemoveDirective(op_id);
-void AudioDirectiveHandler::RecordAudio(base::TimeDelta duration) {
- recorder_->Record();
- stop_recording_timer_.Start(
- FROM_HERE, duration, this, &AudioDirectiveHandler::StopRecording);
+ ProcessNextTransmit();
+ ProcessNextReceive();
}
// Private methods.
-void AudioDirectiveHandler::StopPlayback() {
- player_->Stop();
- DVLOG(2) << "Done playing audio.";
- ExecuteNextTransmit();
+void AudioDirectiveHandler::ProcessNextTransmit() {
+ // If we have an active directive for audible or inaudible audio, ensure that
+ // we are playing our respective token; if we do not have a directive, then
+ // make sure we aren't playing. This is duplicate code, but for just two
+ // elements, it has hard to make a case for processing a loop instead.
+
+ scoped_ptr<AudioDirective> audible_transmit(
+ transmits_list_audible_.GetActiveDirective());
+ if (audible_transmit && !player_audible_->IsPlaying()) {
+ DVLOG(3) << "Playing audible for op_id: " << audible_transmit->op_id;
+ player_audible_->Play(
+ samples_cache_audible_.GetValue(current_token_audible_));
+ stop_audible_playback_timer_.Start(
+ FROM_HERE,
+ audible_transmit->end_time - base::Time::Now(),
+ this,
+ &AudioDirectiveHandler::ProcessNextTransmit);
+ } else if (!audible_transmit && player_audible_->IsPlaying()) {
+ DVLOG(3) << "Stopping audible playback.";
+ current_token_audible_.clear();
+ stop_audible_playback_timer_.Stop();
+ player_audible_->Stop();
+ }
+
+ scoped_ptr<AudioDirective> inaudible_transmit(
+ transmits_list_inaudible_.GetActiveDirective());
+ if (inaudible_transmit && !player_inaudible_->IsPlaying()) {
+ DVLOG(3) << "Playing inaudible for op_id: " << inaudible_transmit->op_id;
+ player_inaudible_->Play(
+ samples_cache_inaudible_.GetValue(current_token_inaudible_));
+ stop_inaudible_playback_timer_.Start(
+ FROM_HERE,
+ inaudible_transmit->end_time - base::Time::Now(),
+ this,
+ &AudioDirectiveHandler::ProcessNextTransmit);
+ } else if (!inaudible_transmit && player_inaudible_->IsPlaying()) {
+ DVLOG(3) << "Stopping inaudible playback.";
+ current_token_inaudible_.clear();
+ stop_inaudible_playback_timer_.Stop();
+ player_inaudible_->Stop();
+ }
}
-void AudioDirectiveHandler::StopRecording() {
- recorder_->Stop();
- DVLOG(2) << "Done recording audio.";
- ExecuteNextReceive();
+void AudioDirectiveHandler::ProcessNextReceive() {
+ scoped_ptr<AudioDirective> receive(receives_list_.GetActiveDirective());
+
+ if (receive && !recorder_->IsRecording()) {
+ DVLOG(3) << "Recording for op_id: " << receive->op_id;
+ recorder_->Record();
+ stop_recording_timer_.Start(FROM_HERE,
+ receive->end_time - base::Time::Now(),
+ this,
+ &AudioDirectiveHandler::ProcessNextReceive);
+ } else if (!receive && recorder_->IsRecording()) {
+ DVLOG(3) << "Stopping Recording";
+ stop_recording_timer_.Stop();
+ recorder_->Stop();
+ }
}
-void AudioDirectiveHandler::ExecuteNextTransmit() {
- scoped_ptr<AudioDirective> audible_transmit(
- directive_list_audible_.GetNextTransmit());
- scoped_ptr<AudioDirective> inaudible_transmit(
- directive_list_inaudible_.GetNextTransmit());
+void AudioDirectiveHandler::HandleToken(const std::string token, bool audible) {
+ std::string valid_token = FromUrlSafe(token);
- if (inaudible_transmit) {
- PlayAudio(inaudible_transmit->samples,
- inaudible_transmit->end_time - base::Time::Now());
+ if (audible && samples_cache_audible_.HasKey(valid_token)) {
+ current_token_audible_ = token;
+ ProcessNextTransmit();
+ return;
}
- if (audible_transmit) {
- PlayAudio(audible_transmit->samples,
- audible_transmit->end_time - base::Time::Now());
+
+ if (!audible && samples_cache_inaudible_.HasKey(valid_token)) {
+ current_token_inaudible_ = token;
+ ProcessNextTransmit();
+ return;
}
+
+ encode_cb_.Run(valid_token,
+ audible,
+ base::Bind(&AudioDirectiveHandler::OnTokenEncoded,
+ base::Unretained(this)));
}
-void AudioDirectiveHandler::ExecuteNextReceive() {
- scoped_ptr<AudioDirective> audible_receive(
- directive_list_audible_.GetNextReceive());
- scoped_ptr<AudioDirective> inaudible_receive(
- directive_list_inaudible_.GetNextReceive());
-
- base::TimeDelta record_duration;
- if (inaudible_receive)
- record_duration = inaudible_receive->end_time - base::Time::Now();
- if (audible_receive) {
- record_duration = std::max(record_duration,
- audible_receive->end_time - base::Time::Now());
+void AudioDirectiveHandler::OnTokenEncoded(
+ const std::string& token,
+ bool audible,
+ const scoped_refptr<media::AudioBusRefCounted>& samples) {
+ DVLOG(3) << "Token: " << token << "[audible:" << audible << "] encoded.";
+ if (audible) {
+ samples_cache_audible_.Add(token, samples);
+ current_token_audible_ = token;
+ // Force process transmits to pick up the new token.
+ if (player_audible_->IsPlaying())
+ player_audible_->Stop();
+ } else {
+ samples_cache_inaudible_.Add(token, samples);
+ current_token_inaudible_ = token;
+ // Force process transmits to pick up the new token.
+ if (player_inaudible_->IsPlaying())
+ player_inaudible_->Stop();
}
- if (record_duration > base::TimeDelta::FromSeconds(0))
- RecordAudio(record_duration);
+ ProcessNextTransmit();
}
} // namespace copresence

Powered by Google App Engine
This is Rietveld 408576698