View | Details | Raw Unified | Return to bug 238869 | Differences between
and this patch

Collapse All | Expand All

(-)b/www/chromium/files/sndio_input.cc (-26 / +100 lines)
Lines 12-31 Link Here
12
#include "base/message_loop/message_loop.h"
12
#include "base/message_loop/message_loop.h"
13
#include "media/audio/openbsd/audio_manager_openbsd.h"
13
#include "media/audio/openbsd/audio_manager_openbsd.h"
14
#include "media/audio/audio_manager.h"
14
#include "media/audio/audio_manager.h"
15
#include "media/base/audio_timestamp_helper.h"
15
16
16
namespace media {
17
namespace media {
17
18
18
static const SampleFormat kSampleFormat = kSampleFormatS16;
19
static const SampleFormat kSampleFormat = kSampleFormatS16;
19
20
21
// Number of blocks of buffers used in the |fifo_|.
22
const int kNumberOfBlocksBufferInFifo = 2;
23
20
void sndio_in_onmove(void *arg, int delta) {
24
void sndio_in_onmove(void *arg, int delta) {
21
  NOTIMPLEMENTED();
22
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
25
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
23
26
24
  self->hw_delay_ = delta - self->params_.GetBytesPerFrame(kSampleFormat);
27
  self->hw_delay_ = delta;
28
}
29
30
void sndio_in_onvol(void *arg, unsigned int volume) {
31
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
32
  pthread_mutex_lock(&(self->mutex));
33
  self->vol = volume;
34
  pthread_mutex_unlock(&(self->mutex));
25
}
35
}
26
36
27
void *sndio_in_threadstart(void *arg) {
37
void *sndio_in_threadstart(void *arg) {
28
  NOTIMPLEMENTED();
29
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
38
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
30
39
31
  self->ReadAudio();
40
  self->ReadAudio();
Lines 45-54 SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* audio_manager, Link Here
45
      callback_(NULL),
54
      callback_(NULL),
46
      device_handle_(NULL),
55
      device_handle_(NULL),
47
      read_callback_behind_schedule_(false),
56
      read_callback_behind_schedule_(false),
48
      audio_bus_(AudioBus::Create(params)) {
57
      state(kClosed),
58
      mutex(PTHREAD_MUTEX_INITIALIZER),
59
      fifo_(params.channels(),
60
            params.frames_per_buffer(),
61
            kNumberOfBlocksBufferInFifo) {
49
}
62
}
50
63
51
SndioAudioInputStream::~SndioAudioInputStream() {}
64
SndioAudioInputStream::~SndioAudioInputStream() {
65
  if (state != kClosed)
66
    Close();
67
}
52
68
53
bool SndioAudioInputStream::Open() {
69
bool SndioAudioInputStream::Open() {
54
  struct sio_par par;
70
  struct sio_par par;
Lines 59-79 bool SndioAudioInputStream::Open() { Link Here
59
75
60
  if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR &&
76
  if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR &&
61
      params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
77
      params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
62
    LOG(WARNING) << "Unsupported audio format.";
78
    LOG(ERROR) << "Unsupported audio format.";
63
    return false;
79
    return false;
64
  }
80
  }
65
81
66
  sio_initpar(&par);
67
  par.rate = params_.sample_rate();
68
  par.pchan = params_.channels();
69
  par.bits = SampleFormatToBytesPerChannel(kSampleFormat);
70
  par.bps = par.bits / 8;
71
  par.sig = sig = par.bits != 8 ? 1 : 0;
72
  par.le = SIO_LE_NATIVE;
73
  par.appbufsz = params_.frames_per_buffer();
74
  sndio_rec_bufsz_ = par.bufsz;
75
  sndio_rec_bufsize_ = par.round * par.bps * par.rchan;
76
77
  device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0);
82
  device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0);
78
83
79
  if (device_handle_ == NULL) {
84
  if (device_handle_ == NULL) {
Lines 81-94 bool SndioAudioInputStream::Open() { Link Here
81
    return false;
86
    return false;
82
  }
87
  }
83
88
89
  sio_initpar(&par);
90
91
  par.rate = params_.sample_rate();
92
  par.rchan = params_.channels();
93
  par.bps = SampleFormatToBytesPerChannel(kSampleFormat);
94
  par.bits = par.bps * 8;
95
  par.sig = sig = par.bits != 8 ? 1 : 0;
96
  par.le = SIO_LE_NATIVE;
97
  par.appbufsz = 10 * params_.channels() * par.bps * params_.frames_per_buffer();
98
84
  if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) {
99
  if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) {
85
    LOG(ERROR) << "Couldn't set audio parameters.";
100
    LOG(ERROR) << "Couldn't set audio parameters.";
86
    goto bad_close;
101
    goto bad_close;
87
  }
102
  }
88
103
89
  if (par.rate  != (unsigned int)params_.sample_rate() ||
104
  if (par.rate  != (unsigned int)params_.sample_rate() ||
90
      par.pchan != (unsigned int)params_.channels() ||
105
      par.rchan != (unsigned int)params_.channels() ||
91
      par.bits  != (unsigned int)SampleFormatToBytesPerChannel(kSampleFormat) ||
106
      par.bps   != (unsigned int)SampleFormatToBytesPerChannel(kSampleFormat) ||
92
      par.sig   != (unsigned int)sig ||
107
      par.sig   != (unsigned int)sig ||
93
      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
108
      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
94
      (par.bits != par.bps * 8)) {
109
      (par.bits != par.bps * 8)) {
Lines 96-102 bool SndioAudioInputStream::Open() { Link Here
96
    goto bad_close;
111
    goto bad_close;
97
  }
112
  }
98
  sio_onmove(device_handle_, sndio_in_onmove, this);
113
  sio_onmove(device_handle_, sndio_in_onmove, this);
114
  sio_onvol(device_handle_, sndio_in_onvol, this);
115
116
  vol = SIO_MAXVOL;
117
118
  if (!sio_start(device_handle_)) {
119
    LOG(ERROR) << "Couldn't start device.";
120
    goto bad_close;
121
  }
99
122
123
  state = kStopped;
100
  audio_buffer_.reset(new uint8_t[bytes_per_buffer_]);
124
  audio_buffer_.reset(new uint8_t[bytes_per_buffer_]);
101
125
102
  return true;
126
  return true;
Lines 110-141 void SndioAudioInputStream::Start(AudioInputCallback* callback) { Link Here
110
  callback_ = callback;
134
  callback_ = callback;
111
  StartAgc();
135
  StartAgc();
112
136
137
  state = kRunning;
113
  // We start reading data half |buffer_duration_| later than when the
138
  // We start reading data half |buffer_duration_| later than when the
114
  // buffer might have got filled, to accommodate some delays in the audio
139
  // buffer might have got filled, to accommodate some delays in the audio
115
  // driver. This could also give us a smooth read sequence going forward.
140
  // driver. This could also give us a smooth read sequence going forward.
116
  base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
141
  base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
117
  next_read_time_ = base::TimeTicks::Now() + delay;
142
  next_read_time_ = base::TimeTicks::Now() + delay;
118
  if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0)
143
144
  if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0) {
119
    LOG(ERROR) << "Failed to create real-time thread.";
145
    LOG(ERROR) << "Failed to create real-time thread.";
146
    sio_stop(device_handle_);
147
    state = kStopped;
148
  }
120
}
149
}
121
150
122
void SndioAudioInputStream::ReadAudio() {
151
void SndioAudioInputStream::ReadAudio() {
123
  NOTIMPLEMENTED();
152
  DCHECK(callback_);
153
154
  double normalized_volume = 1.0;
155
  void* data = audio_buffer_.get();
156
  int number_of_bytes = 0;
157
  int number_of_frames = 0;
158
  int bpc = SampleFormatToBytesPerChannel(kSampleFormat);
159
  const AudioBus* audio_bus;
160
  base::TimeTicks capture_time = base::TimeTicks::Now();
161
162
  while (state == kRunning) {
163
    normalized_volume = GetVolume()/SIO_MAXVOL;
164
165
    capture_time = base::TimeTicks::Now() - base::TimeDelta::FromMicroseconds(hw_delay_ * base::Time::kMicrosecondsPerSecond / static_cast<float>(params_.sample_rate()));
166
167
    number_of_bytes = sio_read(device_handle_, data, bytes_per_buffer_);
168
    number_of_frames = number_of_bytes/(bpc * params_.channels());
169
170
    fifo_.Push(data, number_of_frames, bpc);
171
172
    while (fifo_.available_blocks()) {
173
      audio_bus = fifo_.Consume();
174
175
      callback_->OnData(audio_bus, capture_time, normalized_volume);
176
177
      // Move the capture time forward for each vended block.
178
      capture_time += AudioTimestampHelper::FramesToTime(audio_bus->frames(),
179
                                                         params_.sample_rate());
180
    }
181
  }
124
}
182
}
125
183
126
void SndioAudioInputStream::Stop() {
184
void SndioAudioInputStream::Stop() {
185
186
  if (state == kStopped)
187
    return;
188
127
  if (!device_handle_ || !callback_)
189
  if (!device_handle_ || !callback_)
128
    return;
190
    return;
129
191
130
  StopAgc();
192
  StopAgc();
131
193
194
  state = kStopWait;
132
  pthread_join(thread_, NULL);
195
  pthread_join(thread_, NULL);
133
  sio_stop(device_handle_);
196
  sio_stop(device_handle_);
134
197
  state = kStopped;
198
  fifo_.Clear();
135
  callback_ = NULL;
199
  callback_ = NULL;
136
}
200
}
137
201
138
void SndioAudioInputStream::Close() {
202
void SndioAudioInputStream::Close() {
203
  if (state == kClosed)
204
    return;
205
206
  if (state == kRunning)
207
    Stop();
208
209
  state = kClosed;
210
139
  if (device_handle_) {
211
  if (device_handle_) {
140
    sio_close(device_handle_);
212
    sio_close(device_handle_);
141
    audio_buffer_.reset();
213
    audio_buffer_.reset();
Lines 149-161 double SndioAudioInputStream::GetMaxVolume() { Link Here
149
  return static_cast<double>(SIO_MAXVOL);
221
  return static_cast<double>(SIO_MAXVOL);
150
}
222
}
151
223
152
void SndioAudioInputStream::SetVolume(double volume) {
224
void SndioAudioInputStream::SetVolume(double v) {
153
  NOTIMPLEMENTED();
225
  pthread_mutex_lock(&mutex);
226
  int res = sio_setvol(device_handle_, v);
227
  vol = v;
228
  pthread_mutex_unlock(&mutex);
154
}
229
}
155
230
156
double SndioAudioInputStream::GetVolume() {
231
double SndioAudioInputStream::GetVolume() {
157
  long current_volume = 0;
232
  return vol;
158
  return static_cast<double>(current_volume);
159
}
233
}
160
234
161
bool SndioAudioInputStream::IsMuted() {
235
bool SndioAudioInputStream::IsMuted() {
(-)b/www/chromium/files/sndio_input.h (-1 / +17 lines)
Lines 17-22 Link Here
17
#include "media/audio/audio_io.h"
17
#include "media/audio/audio_io.h"
18
#include "media/audio/audio_device_description.h"
18
#include "media/audio/audio_device_description.h"
19
#include "media/base/audio_parameters.h"
19
#include "media/base/audio_parameters.h"
20
#include "media/base/audio_block_fifo.h"
20
21
21
namespace media {
22
namespace media {
22
23
Lines 67-72 class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> { Link Here
67
  friend void *sndio_in_threadstart(void *arg);
68
  friend void *sndio_in_threadstart(void *arg);
68
69
69
 private:
70
 private:
71
  enum StreamState {
72
    kClosed,            // Not opened yet
73
    kStopped,           // Device opened, but not started yet
74
    kRunning,           // Started, device playing
75
    kStopWait           // Stopping, waiting for the real-time thread to exit
76
  };
77
70
  // Logs the error and invokes any registered callbacks.
78
  // Logs the error and invokes any registered callbacks.
71
  void HandleError(const char* method, int error);
79
  void HandleError(const char* method, int error);
72
80
Lines 92-105 class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> { Link Here
92
  struct sio_hdl* device_handle_;  // Handle to the SNDIO PCM recording device.
100
  struct sio_hdl* device_handle_;  // Handle to the SNDIO PCM recording device.
93
  std::unique_ptr<uint8_t[]> audio_buffer_;  // Buffer used for reading audio data.
101
  std::unique_ptr<uint8_t[]> audio_buffer_;  // Buffer used for reading audio data.
94
  bool read_callback_behind_schedule_;
102
  bool read_callback_behind_schedule_;
95
  std::unique_ptr<AudioBus> audio_bus_;
103
  // Current state of the stream
104
  enum StreamState state;
96
105
97
  int hw_delay_;
106
  int hw_delay_;
98
  int sndio_rec_bufsize_;
107
  int sndio_rec_bufsize_;
99
  int sndio_rec_bufsz_;
108
  int sndio_rec_bufsz_;
109
  // Current volume in the 0..SIO_MAXVOL range
110
  int vol;
100
111
101
  // High priority thread running RealTimeThread()
112
  // High priority thread running RealTimeThread()
102
  pthread_t thread_;
113
  pthread_t thread_;
114
  // Protects vol, volpending and hw_delay
115
  pthread_mutex_t mutex;
116
117
  // Holds the data from the OS.
118
  AudioBlockFifo fifo_;
103
119
104
  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
120
  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
105
};
121
};

Return to bug 238869