1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/cras/cras_unified.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/cras/audio_manager_cras.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace media {
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Overview of operation:
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 1) An object of CrasUnifiedStream is created by the AudioManager
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// factory: audio_man->MakeAudioStream().
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 2) Next some thread will call Open(), at that point a client is created and
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// configured for the correct format and sample rate.
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 3) Then Start(source) is called and a stream is added to the CRAS client
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// which will create its own thread that periodically calls the source for more
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data as buffers are being consumed.
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 4) When finished Stop() is called, which is handled by stopping the stream.
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5) Finally Close() is called. It cleans up and notifies the audio manager,
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// which likely will destroy this object.
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// For output-only streams, a unified stream is created with 0 input channels.
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Simplified data flow for unified streams:
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   +-------------+                  +------------------+
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   | CRAS Server |                  | Chrome Client    |
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   +------+------+    Add Stream    +---------+--------+
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |  buffer_frames captured to shm    |
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |---------------------------------->|
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |  UnifiedCallback()
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |  ReadWriteAudio()
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |  buffer_frames written to shm     |
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//         ...  Repeats for each block.        ...
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |  Remove stream                    |
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Simplified data flow for output only streams:
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   +-------------+                  +------------------+
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   | CRAS Server |                  | Chrome Client    |
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   +------+------+    Add Stream    +---------+--------+
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          | Near out of samples, request more |
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |---------------------------------->|
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |  UnifiedCallback()
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |  WriteAudio()
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |  buffer_frames written to shm     |
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//         ...  Repeats for each block.        ...
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |  Remove stream                    |
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |<----------------------------------|
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//          |                                   |
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// For Unified streams the Chrome client is notified whenever buffer_frames have
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// been captured.  For Output streams the client is notified a few milliseconds
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// before the hardware buffer underruns and fills the buffer with another block
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// of audio.
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CrasUnifiedStream::CrasUnifiedStream(const AudioParameters& params,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     AudioManagerCras* manager)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : client_(NULL),
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_id_(0),
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params_(params),
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bytes_per_frame_(0),
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      is_playing_(false),
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      volume_(1.0),
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      manager_(manager),
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      source_callback_(NULL),
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_direction_(CRAS_STREAM_OUTPUT) {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(manager_);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(params_.channels()  > 0);
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Must have at least one input or output.  If there are both they must be the
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // same.
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int input_channels = params_.input_channels();
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (input_channels) {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // A unified stream for input and output.
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(params_.channels() == input_channels);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_direction_ = CRAS_STREAM_UNIFIED;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    input_bus_ = AudioBus::Create(input_channels,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  params_.frames_per_buffer());
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  output_bus_ = AudioBus::Create(params);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CrasUnifiedStream::~CrasUnifiedStream() {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!is_playing_);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CrasUnifiedStream::Open() {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Sanity check input values.
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (params_.sample_rate() <= 0) {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Unsupported audio frequency.";
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (AudioManagerCras::BitsToFormat(params_.bits_per_sample()) ==
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SND_PCM_FORMAT_UNKNOWN) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Unsupported pcm format";
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create the client and connect to the CRAS server.
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cras_client_create(&client_)) {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Couldn't create CRAS client.\n";
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_ = NULL;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cras_client_connect(client_)) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Couldn't connect CRAS client.\n";
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_client_destroy(client_);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_ = NULL;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Then start running the client.
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cras_client_run_thread(client_)) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Couldn't run CRAS client.\n";
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_client_destroy(client_);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_ = NULL;
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::Close() {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (client_) {
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_client_stop(client_);
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_client_destroy(client_);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_ = NULL;
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Signal to the manager that we're closed and can be removed.
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Should be last call in the method as it deletes "this".
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  manager_->ReleaseOutputStream(this);
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::Start(AudioSourceCallback* callback) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(callback);
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Channel map to CRAS_CHANNEL, values in the same order of
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // corresponding source in Chromium defined Channels.
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  static const int kChannelMap[] = {
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_FL,
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_FR,
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_FC,
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_LFE,
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_RL,
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_RR,
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_FLC,
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_FRC,
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_RC,
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_SL,
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    CRAS_CH_SR
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  };
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  source_callback_ = callback;
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only start if we can enter the playing state.
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_playing_)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Prepare |audio_format| and |stream_params| for the stream we
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // will create.
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_audio_format* audio_format = cras_audio_format_create(
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AudioManagerCras::BitsToFormat(params_.bits_per_sample()),
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params_.sample_rate(),
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params_.channels());
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!audio_format) {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Error setting up audio parameters.";
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback->OnError(this);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Initialize channel layout to all -1 to indicate that none of
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // the channels is set in the layout.
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int8 layout[CRAS_CH_MAX] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Converts to CRAS defined channels. ChannelOrder will return -1
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // for channels that does not present in params_.channel_layout().
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kChannelMap); ++i)
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    layout[kChannelMap[i]] = ChannelOrder(params_.channel_layout(),
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                          static_cast<Channels>(i));
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (cras_audio_format_set_channel_layout(audio_format, layout)) {
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    LOG(WARNING) << "Error setting channel layout.";
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    callback->OnError(this);
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_stream_params* stream_params = cras_client_unified_params_create(
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_direction_,
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params_.frames_per_buffer(),
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CRAS_STREAM_TYPE_DEFAULT,
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      0,
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this,
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CrasUnifiedStream::UnifiedCallback,
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CrasUnifiedStream::StreamError,
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      audio_format);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!stream_params) {
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Error setting up stream parameters.";
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback->OnError(this);
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_audio_format_destroy(audio_format);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Before starting the stream, save the number of bytes in a frame for use in
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the callback.
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Adding the stream will start the audio callbacks requesting data.
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cras_client_add_stream(client_, &stream_id_, stream_params) < 0) {
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Failed to add the stream";
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback->OnError(this);
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_audio_format_destroy(audio_format);
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cras_client_stream_params_destroy(stream_params);
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set initial volume.
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_set_stream_volume(client_, stream_id_, volume_);
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Done with config params.
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_audio_format_destroy(audio_format);
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_stream_params_destroy(stream_params);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  is_playing_ = true;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::Stop() {
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!client_)
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Removing the stream from the client stops audio.
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_rm_stream(client_, stream_id_);
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  is_playing_ = false;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::SetVolume(double volume) {
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!client_)
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  volume_ = static_cast<float>(volume);
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_set_stream_volume(client_, stream_id_, volume_);
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::GetVolume(double* volume) {
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *volume = volume_;
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 CrasUnifiedStream::GetBytesLatency(
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const struct timespec& latency_ts) {
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32 latency_usec;
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Treat negative latency (if we are too slow to render) as 0.
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (latency_ts.tv_sec < 0 || latency_ts.tv_nsec < 0) {
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    latency_usec = 0;
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    latency_usec = (latency_ts.tv_sec * base::Time::kMicrosecondsPerSecond) +
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        latency_ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  double frames_latency =
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      latency_usec * params_.sample_rate() / base::Time::kMicrosecondsPerSecond;
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return static_cast<unsigned int>(frames_latency * bytes_per_frame_);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Static callback asking for samples.
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int CrasUnifiedStream::UnifiedCallback(cras_client* client,
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       cras_stream_id_t stream_id,
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       uint8* input_samples,
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       uint8* output_samples,
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       unsigned int frames,
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       const timespec* input_ts,
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       const timespec* output_ts,
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       void* arg) {
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrasUnifiedStream* me = static_cast<CrasUnifiedStream*>(arg);
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return me->DispatchCallback(frames,
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              input_samples,
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              output_samples,
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              input_ts,
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              output_ts);
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Static callback for stream errors.
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int CrasUnifiedStream::StreamError(cras_client* client,
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   cras_stream_id_t stream_id,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   int err,
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   void* arg) {
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CrasUnifiedStream* me = static_cast<CrasUnifiedStream*>(arg);
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  me->NotifyStreamError(err);
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Calls the appropriate rendering function for this type of stream.
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 CrasUnifiedStream::DispatchCallback(size_t frames,
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           uint8* input_samples,
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           uint8* output_samples,
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           const timespec* input_ts,
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           const timespec* output_ts) {
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (stream_direction_) {
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case CRAS_STREAM_OUTPUT:
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return WriteAudio(frames, output_samples, output_ts);
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case CRAS_STREAM_INPUT:
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "CrasUnifiedStream doesn't support input streams.";
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 0;
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case CRAS_STREAM_UNIFIED:
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ReadWriteAudio(frames, input_samples, output_samples,
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            input_ts, output_ts);
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note these are run from a real time thread, so don't waste cycles here.
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 CrasUnifiedStream::ReadWriteAudio(size_t frames,
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         uint8* input_samples,
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         uint8* output_samples,
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         const timespec* input_ts,
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         const timespec* output_ts) {
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(frames, static_cast<size_t>(output_bus_->frames()));
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(source_callback_);
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32 bytes_per_sample = bytes_per_frame_ / params_.channels();
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  input_bus_->FromInterleaved(input_samples, frames, bytes_per_sample);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine latency and pass that on to the source.  We have the capture time
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // of the first input sample and the playback time of the next audio sample
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // passed from the audio server, add them together for total latency.
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32 total_delay_bytes;
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  timespec latency_ts  = {0, 0};
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_calc_capture_latency(input_ts, &latency_ts);
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  total_delay_bytes = GetBytesLatency(latency_ts);
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_calc_playback_latency(output_ts, &latency_ts);
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  total_delay_bytes += GetBytesLatency(latency_ts);
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int frames_filled = source_callback_->OnMoreData(
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      output_bus_.get(),
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AudioBuffersState(0, total_delay_bytes));
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  output_bus_->ToInterleaved(frames_filled, bytes_per_sample, output_samples);
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return frames_filled;
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 CrasUnifiedStream::WriteAudio(size_t frames,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     uint8* buffer,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     const timespec* sample_ts) {
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(frames, static_cast<size_t>(output_bus_->frames()));
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine latency and pass that on to the source.
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  timespec latency_ts  = {0, 0};
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cras_client_calc_playback_latency(sample_ts, &latency_ts);
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int frames_filled = source_callback_->OnMoreData(
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      output_bus_.get(), AudioBuffersState(0, GetBytesLatency(latency_ts)));
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Note: If this ever changes to output raw float the data must be clipped and
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // sanitized since it may come from an untrusted source such as NaCl.
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  output_bus_->ToInterleaved(
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frames_filled, bytes_per_frame_ / params_.channels(), buffer);
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return frames_filled;
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CrasUnifiedStream::NotifyStreamError(int err) {
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This will remove the stream from the client.
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (source_callback_)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    source_callback_->OnError(this);
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace media
396