Skip to content

Commit

Permalink
ChromeOS: enable pinning stream output routing for webapp request
Browse files Browse the repository at this point in the history
Changes:
This CL is extracted from https://codereview.chromium.org/2516813002/, dealing with 666202 only. Support pinning stream for output, the behavior reverts to default if pin_device_ is NO_DEVICE.

The mirror bug of 658048 exists, that is selecting 'Headphone', it will still route to internal speaker, unless headphone is activated by system selection.

BUG=666202
TEST=manual test and expect the results: "The drop down for audio input and output from a web page should show a list of available devices plus "default".  Choosing one from a web page will route only that page's audio to/from the selected device."

CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel

Review-Url: https://codereview.chromium.org/2651073004
Cr-Commit-Position: refs/heads/master@{#446539}
  • Loading branch information
warx authored and Commit bot committed Jan 27, 2017
1 parent 827b0c2 commit 03d77dd
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 32 deletions.
23 changes: 15 additions & 8 deletions media/audio/cras/audio_manager_cras.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void AudioManagerCras::GetAudioDeviceNamesImpl(bool is_input,
if (is_input && mic_positions_.size() > 1)
AddBeamformingDevices(device_names);
else
device_names->push_back(media::AudioDeviceName::CreateDefault());
device_names->push_back(AudioDeviceName::CreateDefault());

if (base::FeatureList::IsEnabled(features::kEnumerateAudioDevices)) {
chromeos::AudioDeviceList devices;
Expand Down Expand Up @@ -236,17 +236,17 @@ AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
const AudioParameters& params,
const LogCallback& log_callback) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
return MakeOutputStream(params);
// Pinning stream is not supported for MakeLinearOutputStream.
return MakeOutputStream(params, AudioDeviceDescription::kDefaultDeviceId);
}

AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
const AudioParameters& params,
const std::string& device_id,
const LogCallback& log_callback) {
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
// TODO(dgreid): Open the correct input device for unified IO.
return MakeOutputStream(params);
return MakeOutputStream(params, device_id);
}

AudioInputStream* AudioManagerCras::MakeLinearInputStream(
Expand All @@ -268,8 +268,6 @@ AudioInputStream* AudioManagerCras::MakeLowLatencyInputStream(
AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) {
// TODO(tommi): Support |output_device_id|.
DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
int sample_rate = kDefaultSampleRate;
int buffer_size = kMinimumOutputBufferSize;
Expand All @@ -292,8 +290,9 @@ AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
}

AudioOutputStream* AudioManagerCras::MakeOutputStream(
const AudioParameters& params) {
return new CrasUnifiedStream(params, this);
const AudioParameters& params,
const std::string& device_id) {
return new CrasUnifiedStream(params, this, device_id);
}

AudioInputStream* AudioManagerCras::MakeInputStream(
Expand All @@ -316,4 +315,12 @@ snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) {
}
}

bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
AudioDeviceNames device_names;
GetAudioDeviceNamesImpl(is_input, &device_names);
DCHECK(!device_names.empty());
const AudioDeviceName& device_name = device_names.front();
return device_name.unique_id == device_id;
}

} // namespace media
7 changes: 6 additions & 1 deletion media/audio/cras/audio_manager_cras.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {

static snd_pcm_format_t BitsToFormat(int bits_per_sample);

// Checks if |device_id| corresponds to the default device.
// Set |is_input| to true for capture devices, false for output.
bool IsDefault(const std::string& device_id, bool is_input);

protected:
~AudioManagerCras() override;

Expand All @@ -61,7 +65,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {

private:
// Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
AudioOutputStream* MakeOutputStream(const AudioParameters& params);
AudioOutputStream* MakeOutputStream(const AudioParameters& params,
const std::string& device_id);

// Called by MakeLinearInputStream and MakeLowLatencyInputStream.
AudioInputStream* MakeInputStream(const AudioParameters& params,
Expand Down
11 changes: 1 addition & 10 deletions media/audio/cras/cras_input.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_manager.h"
#include "media/audio/cras/audio_manager_cras.h"

namespace media {
Expand All @@ -36,7 +35,7 @@ CrasInputStream::CrasInputStream(const AudioParameters& params,
mute_done_(false) {
DCHECK(audio_manager_);
audio_bus_ = AudioBus::Create(params_);
if (!IsDefault(device_id)) {
if (!audio_manager_->IsDefault(device_id, true)) {
uint64_t cras_node_id;
base::StringToUint64(device_id, &cras_node_id);
pin_device_ = dev_index_of(cras_node_id);
Expand Down Expand Up @@ -355,14 +354,6 @@ bool CrasInputStream::IsMuted() {
return false;
}

bool CrasInputStream::IsDefault(const std::string& device_id) const {
AudioDeviceNames device_names;
audio_manager_->GetAudioInputDeviceNames(&device_names);
DCHECK(!device_names.empty());
AudioDeviceName device_name = device_names.front();
return device_name.unique_id == device_id;
}

double CrasInputStream::GetVolumeRatioFromDecibels(double dB) const {
return pow(10, dB / 20.0);
}
Expand Down
3 changes: 0 additions & 3 deletions media/audio/cras/cras_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ class MEDIA_EXPORT CrasInputStream : public AgcAudioStream<AudioInputStream> {
bool IsMuted() override;

private:
// Checks if |device_id| corresponds to 'Default' choice.
bool IsDefault(const std::string& device_id) const;

// Handles requests to get samples from the provided buffer. This will be
// called by the audio server when it has samples ready.
static int SamplesReady(cras_client* client,
Expand Down
28 changes: 22 additions & 6 deletions media/audio/cras/cras_unified.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,24 @@

#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "media/audio/cras/audio_manager_cras.h"

namespace media {

namespace {

int GetDevicePin(AudioManagerCras* manager, const std::string& device_id) {
if (!manager->IsDefault(device_id, false)) {
uint64_t cras_node_id;
base::StringToUint64(device_id, &cras_node_id);
return dev_index_of(cras_node_id);
}
return NO_DEVICE;
}

} // namespace

// Overview of operation:
// 1) An object of CrasUnifiedStream is created by the AudioManager
// factory: audio_man->MakeAudioStream().
Expand Down Expand Up @@ -52,7 +66,8 @@ namespace media {
// of audio.

CrasUnifiedStream::CrasUnifiedStream(const AudioParameters& params,
AudioManagerCras* manager)
AudioManagerCras* manager,
const std::string& device_id)
: client_(NULL),
stream_id_(0),
params_(params),
Expand All @@ -61,11 +76,11 @@ CrasUnifiedStream::CrasUnifiedStream(const AudioParameters& params,
volume_(1.0),
manager_(manager),
source_callback_(NULL),
stream_direction_(CRAS_STREAM_OUTPUT) {
output_bus_(AudioBus::Create(params)),
stream_direction_(CRAS_STREAM_OUTPUT),
pin_device_(GetDevicePin(manager, device_id)) {
DCHECK(manager_);
DCHECK_GT(params_.channels(), 0);

output_bus_ = AudioBus::Create(params);
}

CrasUnifiedStream::~CrasUnifiedStream() {
Expand Down Expand Up @@ -196,8 +211,9 @@ void CrasUnifiedStream::Start(AudioSourceCallback* callback) {
bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format);

// Adding the stream will start the audio callbacks requesting data.
if (cras_client_add_stream(client_, &stream_id_, stream_params) < 0) {
LOG(WARNING) << "Failed to add the stream";
if (cras_client_add_pinned_stream(client_, pin_device_, &stream_id_,
stream_params)) {
LOG(WARNING) << "Failed to add the stream.";
callback->OnError(this);
cras_audio_format_destroy(audio_format);
cras_client_stream_params_destroy(stream_params);
Expand Down
7 changes: 6 additions & 1 deletion media/audio/cras/cras_unified.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class MEDIA_EXPORT CrasUnifiedStream : public AudioOutputStream {
public:
// The ctor takes all the usual parameters, plus |manager| which is the
// audio manager who is creating this object.
CrasUnifiedStream(const AudioParameters& params, AudioManagerCras* manager);
CrasUnifiedStream(const AudioParameters& params,
AudioManagerCras* manager,
const std::string& device_id);

// The dtor is typically called by the AudioManager only and it is usually
// triggered by calling AudioUnifiedStream::Close().
Expand Down Expand Up @@ -111,6 +113,9 @@ class MEDIA_EXPORT CrasUnifiedStream : public AudioOutputStream {
// Direciton of the stream.
CRAS_STREAM_DIRECTION stream_direction_;

// Index of the CRAS device to stream output to.
const int pin_device_;

DISALLOW_COPY_AND_ASSIGN(CrasUnifiedStream);
};

Expand Down
10 changes: 7 additions & 3 deletions media/audio/cras/cras_unified_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/cras/audio_manager_cras.h"
#include "media/audio/fake_audio_log_factory.h"
#include "media/audio/mock_audio_source_callback.h"
Expand Down Expand Up @@ -72,7 +73,8 @@ class CrasUnifiedStreamTest : public testing::Test {
int32_t samples_per_packet) {
AudioParameters params(kTestFormat, layout, kTestSampleRate,
kTestBitsPerSample, samples_per_packet);
return new CrasUnifiedStream(params, mock_manager_.get());
return new CrasUnifiedStream(params, mock_manager_.get(),
AudioDeviceDescription::kDefaultDeviceId);
}

MockAudioManagerCras& mock_manager() {
Expand Down Expand Up @@ -121,14 +123,16 @@ TEST_F(CrasUnifiedStreamTest, ConstructedState) {
AudioParameters bad_bps_params(kTestFormat, kTestChannelLayout,
kTestSampleRate, kTestBitsPerSample - 1,
kTestFramesPerPacket);
test_stream = new CrasUnifiedStream(bad_bps_params, mock_manager_.get());
test_stream = new CrasUnifiedStream(bad_bps_params, mock_manager_.get(),
AudioDeviceDescription::kDefaultDeviceId);
EXPECT_FALSE(test_stream->Open());
test_stream->Close();

// Bad sample rate.
AudioParameters bad_rate_params(kTestFormat, kTestChannelLayout,
0, kTestBitsPerSample, kTestFramesPerPacket);
test_stream = new CrasUnifiedStream(bad_rate_params, mock_manager_.get());
test_stream = new CrasUnifiedStream(bad_rate_params, mock_manager_.get(),
AudioDeviceDescription::kDefaultDeviceId);
EXPECT_FALSE(test_stream->Open());
test_stream->Close();
}
Expand Down

0 comments on commit 03d77dd

Please sign in to comment.