sndio_input.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/audio/sndio/sndio_input.h"
  5. #include <stddef.h>
  6. #include "base/bind.h"
  7. #include "base/logging.h"
  8. #include "base/macros.h"
  9. #include "base/message_loop/message_loop.h"
  10. #include "media/audio/openbsd/audio_manager_openbsd.h"
  11. #include "media/audio/audio_manager.h"
  12. namespace media {
  13. void sndio_in_onmove(void *arg, int delta) {
  14. NOTIMPLEMENTED();
  15. SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
  16. self->hw_delay_ = delta - self->params_.GetBytesPerFrame();
  17. }
  18. void *sndio_in_threadstart(void *arg) {
  19. NOTIMPLEMENTED();
  20. SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
  21. self->ReadAudio();
  22. return NULL;
  23. }
  24. SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* audio_manager,
  25. const std::string& device_name,
  26. const AudioParameters& params)
  27. : audio_manager_(audio_manager),
  28. device_name_(device_name),
  29. params_(params),
  30. bytes_per_buffer_(params.frames_per_buffer() *
  31. (params.channels() * params.bits_per_sample()) /
  32. 8),
  33. buffer_duration_(base::TimeDelta::FromMicroseconds(
  34. params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
  35. static_cast<float>(params.sample_rate()))),
  36. callback_(NULL),
  37. device_handle_(NULL),
  38. read_callback_behind_schedule_(false),
  39. audio_bus_(AudioBus::Create(params)) {
  40. }
  41. SndioAudioInputStream::~SndioAudioInputStream() {}
  42. bool SndioAudioInputStream::Open() {
  43. struct sio_par par;
  44. int sig;
  45. if (device_handle_)
  46. return false; // Already open.
  47. if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR &&
  48. params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
  49. LOG(WARNING) << "Unsupported audio format.";
  50. return false;
  51. }
  52. sio_initpar(&par);
  53. par.rate = params_.sample_rate();
  54. par.pchan = params_.channels();
  55. par.bits = params_.bits_per_sample();
  56. par.bps = par.bits / 8;
  57. par.sig = sig = par.bits != 8 ? 1 : 0;
  58. par.le = SIO_LE_NATIVE;
  59. par.appbufsz = params_.frames_per_buffer();
  60. sndio_rec_bufsz_ = par.bufsz;
  61. sndio_rec_bufsize_ = par.round * par.bps * par.rchan;
  62. device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0);
  63. if (device_handle_ == NULL) {
  64. LOG(ERROR) << "Couldn't open audio device.";
  65. return false;
  66. }
  67. if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) {
  68. LOG(ERROR) << "Couldn't set audio parameters.";
  69. goto bad_close;
  70. }
  71. if (par.rate != (unsigned int)params_.sample_rate() ||
  72. par.pchan != (unsigned int)params_.channels() ||
  73. par.bits != (unsigned int)params_.bits_per_sample() ||
  74. par.sig != (unsigned int)sig ||
  75. (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
  76. (par.bits != par.bps * 8)) {
  77. LOG(ERROR) << "Unsupported audio parameters.";
  78. goto bad_close;
  79. }
  80. sio_onmove(device_handle_, sndio_in_onmove, this);
  81. audio_buffer_.reset(new uint8_t[bytes_per_buffer_]);
  82. return true;
  83. bad_close:
  84. sio_close(device_handle_);
  85. return false;
  86. }
  87. void SndioAudioInputStream::Start(AudioInputCallback* callback) {
  88. DCHECK(!callback_ && callback);
  89. callback_ = callback;
  90. StartAgc();
  91. // We start reading data half |buffer_duration_| later than when the
  92. // buffer might have got filled, to accommodate some delays in the audio
  93. // driver. This could also give us a smooth read sequence going forward.
  94. base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
  95. next_read_time_ = base::TimeTicks::Now() + delay;
  96. if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0)
  97. LOG(ERROR) << "Failed to create real-time thread.";
  98. }
  99. void SndioAudioInputStream::ReadAudio() {
  100. NOTIMPLEMENTED();
  101. DCHECK(callback_);
  102. int num_buffers = sndio_rec_bufsize_ / params_.frames_per_buffer();
  103. double normalized_volume = 0.0;
  104. // Update the AGC volume level once every second. Note that, |volume| is
  105. // also updated each time SetVolume() is called through IPC by the
  106. // render-side AGC.
  107. GetAgcVolume(&normalized_volume);
  108. while (num_buffers--) {
  109. int frames_read = sio_read(device_handle_, audio_buffer_.get(),
  110. params_.frames_per_buffer());
  111. if (frames_read == params_.frames_per_buffer()) {
  112. audio_bus_->FromInterleaved(audio_buffer_.get(),
  113. audio_bus_->frames(),
  114. params_.bits_per_sample() / 8);
  115. callback_->OnData(
  116. this, audio_bus_.get(), hw_delay_, normalized_volume);
  117. } else {
  118. LOG(WARNING) << "sio_read() returning less than expected frames: "
  119. << frames_read << " vs. " << params_.frames_per_buffer()
  120. << ". Dropping this buffer.";
  121. }
  122. }
  123. }
  124. void SndioAudioInputStream::Stop() {
  125. if (!device_handle_ || !callback_)
  126. return;
  127. StopAgc();
  128. pthread_join(thread_, NULL);
  129. sio_stop(device_handle_);
  130. callback_ = NULL;
  131. }
  132. void SndioAudioInputStream::Close() {
  133. if (device_handle_) {
  134. sio_close(device_handle_);
  135. audio_buffer_.reset();
  136. device_handle_ = NULL;
  137. }
  138. audio_manager_->ReleaseInputStream(this);
  139. }
  140. double SndioAudioInputStream::GetMaxVolume() {
  141. return static_cast<double>(SIO_MAXVOL);
  142. }
  143. void SndioAudioInputStream::SetVolume(double volume) {
  144. NOTIMPLEMENTED();
  145. }
  146. double SndioAudioInputStream::GetVolume() {
  147. long current_volume = 0;
  148. return static_cast<double>(current_volume);
  149. }
  150. bool SndioAudioInputStream::IsMuted() {
  151. return false;
  152. }
  153. } // namespace media