Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / audio / pulse / pulse_input.cc
index 54dfc1e..4a56d3a 100644 (file)
@@ -9,13 +9,15 @@
 #include "base/logging.h"
 #include "media/audio/pulse/audio_manager_pulse.h"
 #include "media/audio/pulse/pulse_util.h"
-#include "media/base/seekable_buffer.h"
 
 namespace media {
 
 using pulse::AutoPulseLock;
 using pulse::WaitForOperationCompletion;
 
+// Number of blocks of buffers used in the |fifo_|.
+const int kNumberOfBlocksBufferInFifo = 2;
+
 PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager,
                                              const std::string& device_name,
                                              const AudioParameters& params,
@@ -28,12 +30,16 @@ PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager,
       channels_(0),
       volume_(0.0),
       stream_started_(false),
+      fifo_(params.channels(),
+            params.frames_per_buffer(),
+            kNumberOfBlocksBufferInFifo),
       pa_mainloop_(mainloop),
       pa_context_(context),
       handle_(NULL),
       context_state_changed_(false) {
   DCHECK(mainloop);
   DCHECK(context);
+  CHECK(params_.IsValid());
 }
 
 PulseAudioInputStream::~PulseAudioInputStream() {
@@ -52,8 +58,6 @@ bool PulseAudioInputStream::Open() {
 
   DCHECK(handle_);
 
-  buffer_.reset(new media::SeekableBuffer(0, 2 * params_.GetBytesPerBuffer()));
-  audio_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]);
   return true;
 }
 
@@ -72,7 +76,7 @@ void PulseAudioInputStream::Start(AudioInputCallback* callback) {
 
   // Clean up the old buffer.
   pa_stream_drop(handle_);
-  buffer_->Clear();
+  fifo_.Clear();
 
   // Start the streaming.
   callback_ = callback;
@@ -105,6 +109,7 @@ void PulseAudioInputStream::Stop() {
   operation = pa_stream_cork(handle_, 1, &pulse::StreamSuccessCallback,
                              pa_mainloop_);
   WaitForOperationCompletion(pa_mainloop_, operation);
+  callback_ = NULL;
 }
 
 void PulseAudioInputStream::Close() {
@@ -114,7 +119,9 @@ void PulseAudioInputStream::Close() {
     if (handle_) {
       // Disable all the callbacks before disconnecting.
       pa_stream_set_state_callback(handle_, NULL, NULL);
-      pa_stream_flush(handle_, NULL, NULL);
+      pa_operation* operation = pa_stream_flush(
+          handle_, &pulse::StreamSuccessCallback, pa_mainloop_);
+      WaitForOperationCompletion(pa_mainloop_, operation);
 
       if (pa_stream_get_state(handle_) != PA_STREAM_UNCONNECTED)
         pa_stream_disconnect(handle_);
@@ -125,9 +132,6 @@ void PulseAudioInputStream::Close() {
     }
   }
 
-  if (callback_)
-    callback_->OnClose(this);
-
   // Signal to the manager that we're closed and can be removed.
   // This should be the last call in the function as it deletes "this".
   audio_manager_->ReleaseInputStream(this);
@@ -265,25 +269,33 @@ void PulseAudioInputStream::ReadData() {
     if (!data || length == 0)
       break;
 
-    buffer_->Append(reinterpret_cast<const uint8*>(data), length);
+    const int number_of_frames = length / params_.GetBytesPerFrame();
+    if (number_of_frames > fifo_.GetUnfilledFrames()) {
+      // Dynamically increase capacity to the FIFO to handle larger buffer got
+      // from Pulse.
+      const int increase_blocks_of_buffer = static_cast<int>(
+          (number_of_frames - fifo_.GetUnfilledFrames()) /
+              params_.frames_per_buffer()) + 1;
+      fifo_.IncreaseCapacity(increase_blocks_of_buffer);
+    }
+
+    fifo_.Push(data, number_of_frames, params_.bits_per_sample() / 8);
 
     // Checks if we still have data.
     pa_stream_drop(handle_);
   } while (pa_stream_readable_size(handle_) > 0);
 
-  int packet_size = params_.GetBytesPerBuffer();
-  while (buffer_->forward_bytes() >= packet_size) {
-    buffer_->Read(audio_data_buffer_.get(), packet_size);
-    callback_->OnData(this, audio_data_buffer_.get(), packet_size,
-                      hardware_delay, normalized_volume);
+  while (fifo_.available_blocks()) {
+    const AudioBus* audio_bus = fifo_.Consume();
 
-    if (buffer_->forward_bytes() < packet_size)
-      break;
+    // Compensate the audio delay caused by the FIFO.
+    hardware_delay += fifo_.GetAvailableFrames() * params_.GetBytesPerFrame();
+    callback_->OnData(this, audio_bus, hardware_delay, normalized_volume);
 
-    // TODO(xians): Remove once PPAPI is using circular buffers.
-    DVLOG(1) << "OnData is being called consecutively, sleep 5ms to "
-             << "wait until render consumes the data";
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
+    // Sleep 5ms to wait until render consumes the data in order to avoid
+    // back to back OnData() method.
+    if (fifo_.available_blocks())
+      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
   }
 
   pa_threaded_mainloop_signal(pa_mainloop_, 0);