| Index: media/audio/cras/cras_unified.cc
|
| diff --git a/media/audio/cras/cras_unified.cc b/media/audio/cras/cras_unified.cc
|
| index 42d9222a356e7e19c01e3aac8cc5016de97c6177..25af3837ad66c75d3c64ef4fe02333dd3fb3319f 100644
|
| --- a/media/audio/cras/cras_unified.cc
|
| +++ b/media/audio/cras/cras_unified.cc
|
| @@ -20,6 +20,30 @@
|
| // 4) When finished Stop() is called, which is handled by stopping the stream.
|
| // 5) Finally Close() is called. It cleans up and notifies the audio manager,
|
| // which likely will destroy this object.
|
| +//
|
| +// For output-only streams, a unified stream is created with 0 input channels.
|
| +//
|
| +// Simplified data flow for unified streams:
|
| +//
|
| +// +-------------+ +------------------+
|
| +// | CRAS Server | | Chrome Client |
|
| +// +------+------+ Add Stream +---------+--------+
|
| +// |<----------------------------------|
|
| +// | |
|
| +// | buffer_frames captured to shm |
|
| +// |---------------------------------->|
|
| +// | | UnifiedCallback()
|
| +// | | ReadWriteAudio()
|
| +// | |
|
| +// | buffer_frames written to shm |
|
| +// |<----------------------------------|
|
| +// | |
|
| +// ... Repeats for each block. ...
|
| +// | |
|
| +// | |
|
| +// | Remove stream |
|
| +// |<----------------------------------|
|
| +// | |
|
| //
|
| // Simplified data flow for output only streams:
|
| //
|
| @@ -61,6 +85,18 @@
|
| stream_direction_(CRAS_STREAM_OUTPUT) {
|
| DCHECK(manager_);
|
| DCHECK(params_.channels() > 0);
|
| +
|
| + // Must have at least one input or output. If there are both they must be the
|
| + // same.
|
| + int input_channels = params_.input_channels();
|
| +
|
| + if (input_channels) {
|
| + // A unified stream for input and output.
|
| + DCHECK(params_.channels() == input_channels);
|
| + stream_direction_ = CRAS_STREAM_UNIFIED;
|
| + input_bus_ = AudioBus::Create(input_channels,
|
| + params_.frames_per_buffer());
|
| + }
|
|
|
| output_bus_ = AudioBus::Create(params);
|
| }
|
| @@ -289,11 +325,45 @@
|
| case CRAS_STREAM_INPUT:
|
| NOTREACHED() << "CrasUnifiedStream doesn't support input streams.";
|
| return 0;
|
| + case CRAS_STREAM_UNIFIED:
|
| + return ReadWriteAudio(frames, input_samples, output_samples,
|
| + input_ts, output_ts);
|
| default:
|
| break;
|
| }
|
|
|
| return 0;
|
| +}
|
| +
|
| +// Note these are run from a real time thread, so don't waste cycles here.
|
| +uint32 CrasUnifiedStream::ReadWriteAudio(size_t frames,
|
| + uint8* input_samples,
|
| + uint8* output_samples,
|
| + const timespec* input_ts,
|
| + const timespec* output_ts) {
|
| + DCHECK_EQ(frames, static_cast<size_t>(output_bus_->frames()));
|
| + DCHECK(source_callback_);
|
| +
|
| + uint32 bytes_per_sample = bytes_per_frame_ / params_.channels();
|
| + input_bus_->FromInterleaved(input_samples, frames, bytes_per_sample);
|
| +
|
| + // Determine latency and pass that on to the source. We have the capture time
|
| + // of the first input sample and the playback time of the next audio sample
|
| + // passed from the audio server, add them together for total latency.
|
| + uint32 total_delay_bytes;
|
| + timespec latency_ts = {0, 0};
|
| + cras_client_calc_capture_latency(input_ts, &latency_ts);
|
| + total_delay_bytes = GetBytesLatency(latency_ts);
|
| + cras_client_calc_playback_latency(output_ts, &latency_ts);
|
| + total_delay_bytes += GetBytesLatency(latency_ts);
|
| +
|
| + int frames_filled = source_callback_->OnMoreData(
|
| + output_bus_.get(),
|
| + AudioBuffersState(0, total_delay_bytes));
|
| +
|
| + output_bus_->ToInterleaved(frames_filled, bytes_per_sample, output_samples);
|
| +
|
| + return frames_filled;
|
| }
|
|
|
| uint32 CrasUnifiedStream::WriteAudio(size_t frames,
|
|
|