Skip to content

Commit

Permalink
Modifies AudioInputCallback::OnData and use media::AudioBus instead o…
Browse files Browse the repository at this point in the history
…f plain byte vector

BUG=375155
TEST=WebRTC and WebSpeech demos

Review URL: https://codereview.chromium.org/314713002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277794 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
henrika@chromium.org committed Jun 17, 2014
1 parent 29896ee commit 57a2e03
Show file tree
Hide file tree
Showing 46 changed files with 399 additions and 282 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
public:
MockAudioInputCallback() {}

MOCK_METHOD5(OnData, void(AudioInputStream* stream, const uint8* src,
uint32 size, uint32 hardware_delay_bytes,
double volume));
MOCK_METHOD4(OnData,
void(AudioInputStream* stream,
const media::AudioBus* src,
uint32 hardware_delay_bytes,
double volume));
MOCK_METHOD1(OnError, void(AudioInputStream* stream));

private:
Expand Down Expand Up @@ -238,7 +240,7 @@ class WebContentsAudioInputStreamTest : public testing::Test {
static_cast<AudioMirroringManager::MirroringDestination*>(NULL)))
.RetiresOnSaturation();

EXPECT_CALL(mock_input_callback_, OnData(NotNull(), NotNull(), _, _, _))
EXPECT_CALL(mock_input_callback_, OnData(NotNull(), NotNull(), _, _))
.WillRepeatedly(
InvokeWithoutArgs(&on_data_event_, &base::WaitableEvent::Signal));

Expand Down
14 changes: 7 additions & 7 deletions content/browser/renderer_host/media/audio_input_renderer_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_bus.h"

namespace content {

Expand Down Expand Up @@ -113,8 +114,7 @@ void AudioInputRendererHost::OnError(media::AudioInputController* controller,
}

void AudioInputRendererHost::OnData(media::AudioInputController* controller,
const uint8* data,
uint32 size) {
const media::AudioBus* data) {
NOTREACHED() << "Only low-latency mode is supported.";
}

Expand Down Expand Up @@ -292,8 +292,9 @@ void AudioInputRendererHost::OnCreateStream(
// Create a new AudioEntry structure.
scoped_ptr<AudioEntry> entry(new AudioEntry());

const uint32 segment_size = (sizeof(media::AudioInputBufferParameters) +
audio_params.GetBytesPerBuffer());
const uint32 segment_size =
(sizeof(media::AudioInputBufferParameters) +
media::AudioBus::CalculateMemorySize(audio_params));
entry->shared_memory_segment_count = config.shared_memory_count;

// Create the shared memory and share it with the renderer process
Expand All @@ -307,9 +308,8 @@ void AudioInputRendererHost::OnCreateStream(
return;
}

scoped_ptr<AudioInputSyncWriter> writer(
new AudioInputSyncWriter(&entry->shared_memory,
entry->shared_memory_segment_count));
scoped_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter(
&entry->shared_memory, entry->shared_memory_segment_count, audio_params));

if (!writer->Init()) {
SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ class CONTENT_EXPORT AudioInputRendererHost
virtual void OnError(media::AudioInputController* controller,
media::AudioInputController::ErrorCode error_code) OVERRIDE;
virtual void OnData(media::AudioInputController* controller,
const uint8* data,
uint32 size) OVERRIDE;
const media::AudioBus* data) OVERRIDE;
virtual void OnLog(media::AudioInputController* controller,
const std::string& message) OVERRIDE;

Expand Down
43 changes: 31 additions & 12 deletions content/browser/renderer_host/media/audio_input_sync_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,36 @@
#include "base/memory/shared_memory.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"

using media::AudioBus;

namespace content {

AudioInputSyncWriter::AudioInputSyncWriter(
base::SharedMemory* shared_memory,
int shared_memory_segment_count)
AudioInputSyncWriter::AudioInputSyncWriter(base::SharedMemory* shared_memory,
int shared_memory_segment_count,
const media::AudioParameters& params)
: shared_memory_(shared_memory),
shared_memory_segment_count_(shared_memory_segment_count),
current_segment_id_(0),
creation_time_(base::Time::Now()) {
creation_time_(base::Time::Now()),
audio_bus_memory_size_(AudioBus::CalculateMemorySize(params)) {
DCHECK_GT(shared_memory_segment_count, 0);
DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u);
shared_memory_segment_size_ =
shared_memory->requested_size() / shared_memory_segment_count;
DVLOG(1) << "SharedMemory::requested_size: "
<< shared_memory->requested_size();
DVLOG(1) << "shared_memory_segment_count: " << shared_memory_segment_count;

// Create vector of audio buses by wrapping existing blocks of memory.
uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
for (int i = 0; i < shared_memory_segment_count; ++i) {
media::AudioInputBuffer* buffer =
reinterpret_cast<media::AudioInputBuffer*>(ptr);
scoped_ptr<media::AudioBus> audio_bus =
media::AudioBus::WrapMemory(params, buffer->audio);
audio_buses_.push_back(audio_bus.release());
ptr += shared_memory_segment_size_;
}
}

AudioInputSyncWriter::~AudioInputSyncWriter() {}
Expand All @@ -31,10 +48,9 @@ void AudioInputSyncWriter::UpdateRecordedBytes(uint32 bytes) {
socket_->Send(&bytes, sizeof(bytes));
}

uint32 AudioInputSyncWriter::Write(const void* data,
uint32 size,
double volume,
bool key_pressed) {
void AudioInputSyncWriter::Write(const media::AudioBus* data,
double volume,
bool key_pressed) {
#if !defined(OS_ANDROID)
static const base::TimeDelta kLogDelayThreadhold =
base::TimeDelta::FromMilliseconds(500);
Expand All @@ -59,19 +75,22 @@ uint32 AudioInputSyncWriter::Write(const void* data,
last_write_time_ = base::Time::Now();
#endif

// Write audio parameters to shared memory.
uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
ptr += current_segment_id_ * shared_memory_segment_size_;
media::AudioInputBuffer* buffer =
reinterpret_cast<media::AudioInputBuffer*>(ptr);
buffer->params.volume = volume;
buffer->params.size = size;
buffer->params.size = audio_bus_memory_size_;
buffer->params.key_pressed = key_pressed;
memcpy(buffer->audio, data, size);

// Copy data from the native audio layer into shared memory using pre-
// allocated audio buses.
media::AudioBus* audio_bus = audio_buses_[current_segment_id_];
data->CopyTo(audio_bus);

if (++current_segment_id_ >= shared_memory_segment_count_)
current_segment_id_ = 0;

return size;
}

void AudioInputSyncWriter::Close() {
Expand Down
22 changes: 16 additions & 6 deletions content/browser/renderer_host/media/audio_input_sync_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_SYNC_WRITER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_SYNC_WRITER_H_

#include "base/memory/scoped_vector.h"
#include "base/process/process.h"
#include "base/sync_socket.h"
#include "base/time/time.h"
#include "media/audio/audio_input_controller.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
Expand All @@ -26,16 +29,16 @@ namespace content {
class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
public:
explicit AudioInputSyncWriter(base::SharedMemory* shared_memory,
int shared_memory_segment_count);
int shared_memory_segment_count,
const media::AudioParameters& params);

virtual ~AudioInputSyncWriter();

// media::AudioOutputController::SyncWriter implementation.
// media::AudioInputController::SyncWriter implementation.
virtual void UpdateRecordedBytes(uint32 bytes) OVERRIDE;
virtual uint32 Write(const void* data,
uint32 size,
double volume,
bool key_pressed) OVERRIDE;
virtual void Write(const media::AudioBus* data,
double volume,
bool key_pressed) OVERRIDE;
virtual void Close() OVERRIDE;

bool Init();
Expand Down Expand Up @@ -65,6 +68,13 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
// The time of the last Write call.
base::Time last_write_time_;

// Size in bytes of each audio bus.
const int audio_bus_memory_size_;

// Vector of audio buses allocated during construction and deleted in the
// destructor.
ScopedVector<media::AudioBus> audio_buses_;

DISALLOW_IMPLICIT_CONSTRUCTORS(AudioInputSyncWriter);
};

Expand Down
11 changes: 8 additions & 3 deletions content/browser/speech/speech_recognition_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class SpeechRecognitionBrowserTest :
size_t buffer_size,
bool fill_with_noise) {
DCHECK(controller.get());
const media::AudioParameters& audio_params = controller->audio_parameters();
scoped_ptr<uint8[]> audio_buffer(new uint8[buffer_size]);
if (fill_with_noise) {
for (size_t i = 0; i < buffer_size; ++i)
Expand All @@ -141,9 +142,13 @@ class SpeechRecognitionBrowserTest :
} else {
memset(audio_buffer.get(), 0, buffer_size);
}
controller->event_handler()->OnData(controller,
audio_buffer.get(),
buffer_size);

scoped_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(audio_params);
audio_bus->FromInterleaved(&audio_buffer.get()[0],
audio_bus->frames(),
audio_params.bits_per_sample() / 8);
controller->event_handler()->OnData(controller, audio_bus.get());
}

void FeedAudioController(int duration_ms, bool feed_with_noise) {
Expand Down
18 changes: 7 additions & 11 deletions content/browser/speech/speech_recognizer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class SpeechRecognizerImpl::OnDataConverter
const AudioParameters& output_params);
virtual ~OnDataConverter();

// Converts input |data| buffer into an AudioChunk where the input format
// Converts input audio |data| bus into an AudioChunk where the input format
// is given by |input_parameters_| and the output format by
// |output_parameters_|.
scoped_refptr<AudioChunk> Convert(const uint8* data, size_t size);
scoped_refptr<AudioChunk> Convert(const AudioBus* data);

private:
// media::AudioConverter::InputCallback implementation.
Expand Down Expand Up @@ -132,11 +132,10 @@ SpeechRecognizerImpl::OnDataConverter::~OnDataConverter() {
}

scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert(
const uint8* data, size_t size) {
CHECK_EQ(size, static_cast<size_t>(input_parameters_.GetBytesPerBuffer()));
const AudioBus* data) {
CHECK_EQ(data->frames(), input_parameters_.frames_per_buffer());

input_bus_->FromInterleaved(
data, input_bus_->frames(), input_parameters_.bits_per_sample() / 8);
data->CopyTo(input_bus_.get());

waiting_for_input_ = true;
audio_converter_.Convert(output_bus_.get());
Expand Down Expand Up @@ -272,13 +271,10 @@ void SpeechRecognizerImpl::OnError(AudioInputController* controller,
}

void SpeechRecognizerImpl::OnData(AudioInputController* controller,
const uint8* data, uint32 size) {
if (size == 0) // This could happen when audio capture stops and is normal.
return;

const AudioBus* data) {
// Convert audio from native format to fixed format used by WebSpeech.
FSMEventArgs event_args(EVENT_AUDIO_DATA);
event_args.audio_data = audio_converter_->Convert(data, size);
event_args.audio_data = audio_converter_->Convert(data);

BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&SpeechRecognizerImpl::DispatchEvent,
Expand Down
3 changes: 2 additions & 1 deletion content/browser/speech/speech_recognizer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "net/url_request/url_request_context_getter.h"

namespace media {
class AudioBus;
class AudioManager;
}

Expand Down Expand Up @@ -132,7 +133,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
virtual void OnError(media::AudioInputController* controller,
media::AudioInputController::ErrorCode error_code) OVERRIDE;
virtual void OnData(media::AudioInputController* controller,
const uint8* data, uint32 size) OVERRIDE;
const media::AudioBus* data) OVERRIDE;
virtual void OnLog(media::AudioInputController* controller,
const std::string& message) OVERRIDE {}

Expand Down
Loading

0 comments on commit 57a2e03

Please sign in to comment.