[M108 Migration][MM] Migrate AudioIO related patches 45/286445/14
authorKoyyani Maheswari <m.koyyani@samsung.com>
Thu, 5 Jan 2023 05:36:03 +0000 (11:06 +0530)
committerKoyyani Maheswari <m.koyyani@samsung.com>
Thu, 9 Feb 2023 11:53:24 +0000 (17:23 +0530)
This patch migrates patchs related to Audio IO.

Reference: https://review.tizen.org/gerrit/279518/

Change-Id: I766dcba9eefa6ff6d4ed0fe7be1ae7a254ce5c7b
Signed-off-by: Koyyani Maheswari <m.koyyani@samsung.com>
17 files changed:
media/audio/BUILD.gn
media/audio/audio_manager_base.cc
packaging/chromium-efl.spec
tizen_src/build/config/BUILD.gn
tizen_src/build/config/tizen_features.gni
tizen_src/build/gn_chromiumefl.sh
tizen_src/chromium_impl/media/audio/tizen/audio_manager_capi.cc
tizen_src/chromium_impl/media/audio/tizen/audio_manager_capi.h
tizen_src/chromium_impl/media/audio/tizen/capi_audio_input.cc
tizen_src/chromium_impl/media/audio/tizen/capi_audio_input.h
tizen_src/chromium_impl/media/audio/tizen/capi_audio_output.cc
tizen_src/chromium_impl/media/audio/tizen/capi_audio_output.h
tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.cc [new file with mode: 0644]
tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.h [new file with mode: 0644]
tizen_src/chromium_impl/media/audio/tizen/capi_util.cc
tizen_src/chromium_impl/media/audio/tizen/capi_util.h
tizen_src/chromium_impl/media/media_efl.gni

index f89a11c..eb449d9 100644 (file)
@@ -8,6 +8,10 @@ import("//media/media_options.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//tools/generate_stubs/rules.gni")
 
+if (tizen_audio_io) {
+  import("//tizen_src/chromium_impl/media/media_efl.gni")
+}
+
 # When libpulse is not directly linked, use stubs to allow for dlopening of the
 # binary.
 if (use_pulseaudio && !link_pulseaudio) {
@@ -161,6 +165,11 @@ source_set("audio") {
     "//media:subcomponent_config",
   ]
 
+  if (tizen_audio_io) {
+    configs += external_media_efl_audio_io_config
+    sources += external_media_efl_audio_io_sources
+  }
+
   if (is_mac) {
     sources += [
       "mac/audio_auhal_mac.cc",
@@ -259,7 +268,7 @@ source_set("audio") {
     ]
   }
 
-  if (is_linux || is_chromeos || is_tizen) {
+  if (is_linux || is_chromeos || !tizen_audio_io) {
     sources += [ "linux/audio_manager_linux.cc" ]
   }
 
index c7e11c8..fcec918 100644 (file)
@@ -458,6 +458,15 @@ void AudioManagerBase::GetAudioOutputDeviceNames(
 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
   CHECK(GetTaskRunner()->BelongsToCurrentThread());
   DCHECK(stream);
+#if defined(TIZEN_MULTIMEDIA_USE_CAPI_AUDIO_IO)
+  // It is possible that audio device creation on tizen could fail. In such
+  // case |num_output_streams_| could be 0.
+  if (!num_output_streams_) {
+    delete stream;
+    return;
+  }
+#endif
+
   CHECK_GT(num_output_streams_, 0);
   // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
   // For example, pass the ownership to AudioManager so it can delete the
@@ -469,8 +478,14 @@ void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
   CHECK(GetTaskRunner()->BelongsToCurrentThread());
   DCHECK(stream);
+#if defined(TIZEN_MULTIMEDIA_USE_CAPI_AUDIO_IO)
+  // It is possible that audio device creation on tizen could fail. In such
+  // case, checking against return value of erase would be fatal.
+  input_streams_.erase(stream);
+#else
   // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
   CHECK_EQ(1u, input_streams_.erase(stream));
+#endif
   delete stream;
 }
 
index d5b0dac..3820106 100644 (file)
@@ -143,6 +143,7 @@ BuildRequires: pkgconfig(xtst)
 %endif
 
 %if "%{?tizen_profile_name}" == "tv"
+BuildRequires: pkgconfig(capi-media-sound-manager)
 BuildRequires: pkgconfig(capi-stt-wrapper-tv)
 BuildRequires: pkgconfig(vd-win-util)
 %endif
index fd06c45..68fb742 100644 (file)
@@ -54,6 +54,9 @@ config("tizen_feature_flags") {
     if (tizen_multimedia) {
       defines += [ "TIZEN_MULTIMEDIA" ]
     }
+    if (tizen_audio_io) {
+      defines += [ "TIZEN_MULTIMEDIA_USE_CAPI_AUDIO_IO" ]
+    }
     if (tizen_autofill_support) {
       defines += [ "TIZEN_AUTOFILL_SUPPORT" ]
     }
index f8df89b..85f5827 100644 (file)
@@ -49,6 +49,7 @@ declare_args() {
   tizen_multimedia_support = false
   tizen_multimedia = false
   tizen_tbm_support = false
+  tizen_audio_io = false
   tizen_web_speech_recognition = false
 
   tizen_autofill_support = false
index 275bef8..078276d 100755 (executable)
@@ -221,6 +221,7 @@ add_tizen_flags() {
   #            FIXME: http://165.213.149.170/jira/browse/TWF-610
   ADDITIONAL_GN_PARAMETERS+="tizen_multimedia=true
                              proprietary_codecs=true
+                             tizen_audio_io=true
                              tizen_web_speech_recognition=true
                              tizen_tbm_support=true
                             "
index 2f9fd1a..08fd7c5 100644 (file)
 #include "base/logging.h"
 #include "base/nix/xdg_util.h"
 #include "base/stl_util.h"
-#include "media/audio/audio_parameters.h"
 #include "media/audio/pulse/pulse_output.h"
 #include "media/audio/tizen/capi_audio_input.h"
 #include "media/audio/tizen/capi_audio_output.h"
+#include "media/audio/tizen/capi_usb_audio_input_stream.h"
 #include "media/audio/tizen/capi_util.h"
+#include "media/base/audio_parameters.h"
 #include "media/base/channel_layout.h"
 #include "media/base/limits.h"
 
-namespace {
-
-const int kMaxOutputStreams = 50;
-const int kDefaultSampleRate = 44100;
-const int kDefaultOutputBufferSize = 512;
-const int kDefaultInputBufferSize = 1024;
-const int kBitsPerSample = 16;
+namespace media {
 
+std::unique_ptr<AudioManager> CreateAudioManager(
+    std::unique_ptr<AudioThread> audio_thread,
+    AudioLogFactory* audio_log_factory) {
+  return std::make_unique<AudioManagerCapi>(std::move(audio_thread),
+                                            audio_log_factory);
 }
 
-namespace media{
-
-AudioManager* AudioManagerCapi::Create(AudioLogFactory* audio_log_factory) {
-  return new AudioManagerCapi(audio_log_factory);
-}
-
-AudioManagerCapi::AudioManagerCapi(AudioLogFactory* audio_log_factory)
-    : AudioManagerBase(audio_log_factory),
-      native_input_sample_rate_(kDefaultSampleRate) {
+AudioManagerCapi::AudioManagerCapi(std::unique_ptr<AudioThread> audio_thread,
+                                   AudioLogFactory* audio_log_factory)
+    : AudioManagerBase(std::move(audio_thread), audio_log_factory) {
   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
 }
 
@@ -55,17 +49,31 @@ bool AudioManagerCapi::HasAudioInputDevices() {
   return !devices.empty();
 }
 
-void AudioManagerCapi::ShowAudioInputSettings() {
-  NOTIMPLEMENTED();
-}
-
 void AudioManagerCapi::GetAudioDeviceNames(
-    bool input, media::AudioDeviceNames* device_names) const {
+    bool input,
+    media::AudioDeviceNames* device_names) const {
   DCHECK(device_names != NULL);
   DCHECK(device_names->empty());
-  device_names->push_front(
-      AudioDeviceName(AudioManager::GetDefaultDeviceName(),
-                      AudioManagerBase::kDefaultDeviceId));
+  auto mask = input ? SOUND_DEVICE_IO_DIRECTION_IN_MASK
+                    : SOUND_DEVICE_IO_DIRECTION_OUT_MASK;
+
+  sound_device_list_h list;
+  int ret = sound_manager_get_device_list(mask, &list);
+#if !BUILDFLAG(IS_TIZEN_TV)
+  if (ret == SOUND_MANAGER_ERROR_NO_DATA) {
+    LOG(INFO) << "No audio " << (input ? "in" : "out") << " device available.";
+    device_names->push_front(AudioDeviceName::CreateDefault());
+    return;
+  }
+#endif
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "Failed to get device list. Err:" << ret
+               << ". Creating only the default device";
+    device_names->push_front(AudioDeviceName::CreateDefault());
+    return;
+  }
+
+  device_names->push_front(AudioDeviceName::CreateDefault());
 }
 
 void AudioManagerCapi::GetAudioInputDeviceNames(
@@ -80,54 +88,94 @@ void AudioManagerCapi::GetAudioOutputDeviceNames(
 
 AudioParameters AudioManagerCapi::GetInputStreamParameters(
     const std::string& device_id) {
-  int buffer_size = media::GetAudioInputBufferSize(NULL);
+  return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                         media::ChannelLayoutConfig::Stereo(),
+                         kDefaultSampleRate, kDefaultInputBufferSize);
+}
+
+AudioOutputStream* AudioManagerCapi::MakeAudioOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return MakeOutputStream(params, device_id);
+}
 
-  if (buffer_size <= 0)
-    buffer_size = kDefaultInputBufferSize;
+AudioInputStream* AudioManagerCapi::MakeAudioInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return MakeInputStream(params, device_id);
+}
+
+void AudioManagerCapi::ReleaseOutputStream(AudioOutputStream* stream) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  AudioManagerBase::ReleaseOutputStream(stream);
+}
 
-  return AudioParameters(
-      AudioParameters::AUDIO_PCM_LOW_LATENCY,
-      CHANNEL_LAYOUT_STEREO,
-      kDefaultSampleRate,
-      kBitsPerSample,
-      buffer_size);
+void AudioManagerCapi::ReleaseInputStream(AudioInputStream* stream) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  AudioManagerBase::ReleaseInputStream(stream);
 }
 
+const char* AudioManagerCapi::GetName() {
+  return "Tizen";
+}
+
+// FIXME: Use the audio format in all below APIs.
 AudioOutputStream* AudioManagerCapi::MakeLinearOutputStream(
-    const AudioParameters& params) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+    const AudioParameters& params,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   return MakeOutputStream(params, std::string());
 }
 
 AudioOutputStream* AudioManagerCapi::MakeLowLatencyOutputStream(
     const AudioParameters& params,
-    const std::string& device_id) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return MakeOutputStream(params, device_id);
+}
+
+AudioOutputStream* AudioManagerCapi::MakeBitstreamOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   return MakeOutputStream(params, device_id);
 }
 
 AudioInputStream* AudioManagerCapi::MakeLinearInputStream(
-    const AudioParameters& params, const std::string& device_id) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   return MakeInputStream(params, device_id);
 }
 
 AudioInputStream* AudioManagerCapi::MakeLowLatencyInputStream(
-    const AudioParameters& params, const std::string& device_id) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   return MakeInputStream(params, device_id);
 }
 
+void AudioManagerCapi::ShutdownOnAudioThread() {
+  AudioManagerBase::ShutdownOnAudioThread();
+}
+
 AudioParameters AudioManagerCapi::GetPreferredOutputStreamParameters(
     const std::string& output_device_id,
     const AudioParameters& input_params) {
-  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+  ChannelLayoutConfig channel_layout_config = ChannelLayoutConfig::Stereo();
+  SampleFormat sample_format = kDefaultSampleFormat;
   int frame_per_buffer = kDefaultOutputBufferSize;
-  int bits_per_sample = kBitsPerSample;
   int sample_rate = kDefaultSampleRate;
-
+  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
   if (input_params.IsValid()) {
-    bits_per_sample = input_params.bits_per_sample();
     channel_layout = input_params.channel_layout();
     frame_per_buffer = input_params.frames_per_buffer();
     sample_rate = input_params.sample_rate();
@@ -142,34 +190,26 @@ AudioParameters AudioManagerCapi::GetPreferredOutputStreamParameters(
       LOG(WARNING) << "but channel_layout is OK. Use it for fail-safe routine";
       channel_layout = input_params.channel_layout();
     }
-    if (input_params.bits_per_sample() > 0 &&
-        input_params.bits_per_sample() <= media::limits::kMaxBitsPerSample) {
-      LOG(WARNING) << "but bits_per_sample is OK. Use it for fail-safe routine";
-      bits_per_sample = input_params.bits_per_sample();
-    }
 
-    sample_rate = media::GetAudioOutputSampleRate(NULL,
-                                                  sample_rate,
-                                                  channel_layout,
-                                                  bits_per_sample);
+    sample_rate = media::GetAudioOutputSampleRate(
+        NULL, sample_rate, channel_layout, sample_format);
     if (!sample_rate)
       sample_rate = kDefaultSampleRate;
   }
 
-  int capi_buffer_size =
-      media::GetAudioOutputBufferSize(NULL,
-                                      sample_rate,
-                                      channel_layout,
-                                      bits_per_sample);
+  int capi_buffer_size = media::GetAudioOutputBufferSize(
+      NULL, sample_rate, channel_layout, sample_format);
 
   if (capi_buffer_size) {
-    if (input_params.GetBytesPerFrame() != 0) {
+    // Should use actual format value.
+    if (input_params.GetBytesPerFrame(sample_format) != 0) {
       frame_per_buffer =
-          capi_buffer_size / input_params.GetBytesPerFrame();
+          capi_buffer_size / input_params.GetBytesPerFrame(sample_format);
     } else {
       int channel_count = channel_layout == CHANNEL_LAYOUT_STEREO ? 2 : 1;
       frame_per_buffer =
-          capi_buffer_size / (bits_per_sample / 8 * channel_count);
+          capi_buffer_size /
+          (SampleFormatToBytesPerChannel(sample_format) * channel_count);
     }
   }
 
@@ -180,20 +220,19 @@ AudioParameters AudioManagerCapi::GetPreferredOutputStreamParameters(
   }
 
   return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                         channel_layout,
-                         sample_rate,
-                         bits_per_sample,
-                         frame_per_buffer);
+                         channel_layout_config, sample_rate, frame_per_buffer);
 }
 
 AudioOutputStream* AudioManagerCapi::MakeOutputStream(
-    const AudioParameters& params, const std::string& input_device_id) {
+    const AudioParameters& params,
+    const std::string& input_device_id) {
   return new CapiAudioOutputStream(params, this);
 }
 
 AudioInputStream* AudioManagerCapi::MakeInputStream(
-    const AudioParameters& params, const std::string& device_id) {
-  return new CapiAudioInputStream(this, device_id, params);
+    const AudioParameters& params,
+    const std::string& device_id) {
+  return new CapiUsbAudioInputStream(this, device_id, params);
 }
 
 }  // namespace media
index 82f7e45..dfe2513 100644 (file)
@@ -5,48 +5,69 @@
 #ifndef MEDIA_AUDIO_TIZEN_AUDIO_MANAGER_CAPI_H_
 #define MEDIA_AUDIO_TIZEN_AUDIO_MANAGER_CAPI_H_
 
+#include <memory>
 #include <string>
 
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "build/build_config.h"
 #include "media/audio/audio_manager_base.h"
 
 namespace media {
 
+class MuteableAudioOutputStream;
+
 class MEDIA_EXPORT AudioManagerCapi : public AudioManagerBase {
  public:
-  explicit AudioManagerCapi(AudioLogFactory* audio_log_factory);
-  AudioManagerCapi(const AudioManagerCapi&) = delete;
-  AudioManagerCapi& operator=(const AudioManagerCapi&) = delete;
+  explicit AudioManagerCapi(std::unique_ptr<AudioThread> audio_thread,
+                            AudioLogFactory* audio_log_factory);
   ~AudioManagerCapi() override;
 
   AudioManagerCapi(const AudioManagerCapi&) = delete;
   AudioManagerCapi& operator=(const AudioManagerCapi&) = delete;
 
-  static AudioManager* Create(AudioLogFactory* audio_log_factory);
-
   // Implementation of AudioManager.
   bool HasAudioOutputDevices() override;
   bool HasAudioInputDevices() override;
-  void ShowAudioInputSettings() override;
   void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
   void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
   AudioParameters GetInputStreamParameters(
       const std::string& device_id) override;
+
+  AudioOutputStream* MakeAudioOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeAudioInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  void ReleaseOutputStream(AudioOutputStream* stream) override;
+  void ReleaseInputStream(AudioInputStream* stream) override;
+  const char* GetName() override;
   // Implementation of AudioManagerBase.
   AudioOutputStream* MakeLinearOutputStream(
-      const AudioParameters& params) override;
+      const AudioParameters& params,
+      const LogCallback& log_callback) override;
   AudioOutputStream* MakeLowLatencyOutputStream(
       const AudioParameters& params,
-      const std::string& device_id) override;
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioOutputStream* MakeBitstreamOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
   AudioInputStream* MakeLinearInputStream(
       const AudioParameters& params,
-      const std::string& device_id) override;
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
   AudioInputStream* MakeLowLatencyInputStream(
       const AudioParameters& params,
-      const std::string& device_id) override;
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
 
  protected:
+  void ShutdownOnAudioThread() override;
   AudioParameters GetPreferredOutputStreamParameters(
       const std::string& output_device_id,
       const AudioParameters& input_params) override;
@@ -62,8 +83,6 @@ class MEDIA_EXPORT AudioManagerCapi : public AudioManagerBase {
   // Called by MakeLinearInputStream and MakeLowLatencyInputStream.
   AudioInputStream* MakeInputStream(const AudioParameters& params,
                                     const std::string& device_id);
-
-  int native_input_sample_rate_;
 };
 
 }  // namespace media
index a3b51ce..ed06c7f 100644 (file)
@@ -9,8 +9,10 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
 #include "media/audio/tizen/audio_manager_capi.h"
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "content/public/browser/browser_thread.h"
+#endif
 
 namespace media {
 
@@ -18,92 +20,42 @@ namespace media {
 const int kNumberOfBlocksBufferInFifo = 2;
 
 CapiAudioInputStream::CapiAudioInputStream(AudioManagerCapi* audio_manager,
-                                           const std::string& device_name,
                                            const AudioParameters& params)
     : audio_manager_(audio_manager),
       callback_(NULL),
-      device_name_(device_name),
       params_(params),
       volume_(1.0f),
       state_(media::kIsClosed),
       audio_worker_("AudioInput"),
-      device_(NULL),
       fifo_(params.channels(),
             params.frames_per_buffer(),
-            kNumberOfBlocksBufferInFifo) {
-}
+            kNumberOfBlocksBufferInFifo) {}
 
-CapiAudioInputStream::~CapiAudioInputStream() {
-  DCHECK(!device_);
-}
+CapiAudioInputStream::~CapiAudioInputStream() {}
 
-//static
-void CapiAudioInputStream::AudioStreamReadCB(audio_in_h handle,
-                                             size_t nbytes,
-                                             void* user_data) {
-  CapiAudioInputStream* is = static_cast<CapiAudioInputStream*>(user_data);
-  is->ReadAudioData();
-}
-
-bool CapiAudioInputStream::Open() {
+AudioInputStream::OpenOutcome CapiAudioInputStream::Open() {
   DCHECK(state_ == media::kIsClosed);
-
-  if (AUDIO_IO_ERROR_NONE !=
-          audio_in_create(params_.sample_rate(), AUDIO_CHANNEL_STEREO,
-                          AUDIO_SAMPLE_TYPE_S16_LE, &device_)) {
-    LOG(ERROR) << "Fail to create audio input";
-    if (callback_)
-      callback_->OnError(this);
-    return false;
-  }
-
-  state_ = media::kIsOpened;
-  return true;
+  return OpenMic() ? AudioInputStream::OpenOutcome::kSuccess
+                   : AudioInputStream::OpenOutcome::kFailed;
 }
 
 void CapiAudioInputStream::Start(AudioInputCallback* callback) {
   DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
-  DCHECK(device_);
   callback_ = callback;
 
   if (state_ != media::kIsOpened) {
     LOG(ERROR) << "Device is not opened";
     if (callback_)
-      callback_->OnError(this);
+      callback_->OnError();
     return;
   }
-
-  if (AUDIO_IO_ERROR_NONE !=
-      audio_in_set_stream_cb(device_, &AudioStreamReadCB, this)) {
-    LOG(ERROR) << "Cannot get the required buffer size for audio input.";
-    if (callback_)
-      callback_->OnError(this);
-    return;
-  }
-
-  audio_worker_.Start();
-  StartAgc();
-
-  if (AUDIO_IO_ERROR_NONE != audio_in_prepare(device_)) {
-    LOG(ERROR) << "Cannot prepare audio input";
-    if (callback_)
-      callback_->OnError(this);
-    return;
-  }
-
-  state_ = media::kIsStarted;
+  StartMic();
 }
 
 void CapiAudioInputStream::Stop() {
-  DCHECK(device_);
   DCHECK(state_ == media::kIsStarted);
 
-  if (AUDIO_IO_ERROR_NONE != audio_in_unprepare(device_))
-    LOG(WARNING) << "Cannot unprepare audio input";
-
-  if (AUDIO_IO_ERROR_NONE != audio_in_unset_stream_cb(device_))
-    LOG(WARNING) << "Cannot unset audio input cb";
-
+  StopMic();
   StopAgc();
   callback_ = NULL;
 
@@ -117,12 +69,7 @@ void CapiAudioInputStream::Close() {
   if (state_ != media::kIsStopped)
     CapiAudioInputStream::Stop();
 
-  state_ = media::kIsClosed;
-
-  if (AUDIO_IO_ERROR_NONE != audio_in_destroy(device_))
-    LOG(WARNING) << "Cannot destroy audio input";
-
-  device_ = NULL;
+  CloseMic(true);
 
   // 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".
@@ -152,61 +99,21 @@ bool CapiAudioInputStream::IsMuted() {
   return volume_ ? false : true;
 }
 
-void CapiAudioInputStream::OnAudioIOData(const AudioBus* audio_bus,
-                                         uint32_t hardware_delay_bytes,
-                                         double normalized_volume) {
-  if (callback_)
-    callback_->OnData(this,audio_bus, hardware_delay_bytes, normalized_volume);
+void CapiAudioInputStream::SetOutputDeviceForAec(
+    const std::string& output_device_id) {
+  NOTIMPLEMENTED();
 }
 
-void CapiAudioInputStream::ReadAudioData() {
-  unsigned int bytes_read = 0;
-  const void* loc_buff = NULL;
-
-  if (AUDIO_IO_ERROR_NONE !=
-      audio_in_peek(device_, &loc_buff, &bytes_read)) {
-    LOG(ERROR) << "audio_in_peek() failed";
-    if (callback_)
-      callback_->OnError(this);
-    return;
-  }
-
-  int number_of_frames = bytes_read / params_.GetBytesPerFrame();
-  if (number_of_frames > fifo_.GetUnfilledFrames()) {
-    int increase_blocks_of_buffer =
-        (number_of_frames - fifo_.GetUnfilledFrames()) /
-            params_.frames_per_buffer() + 1;
-    fifo_.IncreaseCapacity(increase_blocks_of_buffer);
-  }
-
-  fifo_.Push(loc_buff, number_of_frames, params_.bits_per_sample() / 8);
-
-  if (AUDIO_IO_ERROR_NONE != audio_in_drop(device_)) {
-    LOG(ERROR) << "audio_in_drop() failed";
-    if (callback_)
-      callback_->OnError(this);
+void CapiAudioInputStream::OnAudioIOData(std::unique_ptr<AudioBus> audio_bus,
+                                         double hardware_delay_seconds,
+                                         double normalized_volume) {
+  if (!callback_)
     return;
-  }
-  double normalized_volume = 0.0;
-  GetAgcVolume(&normalized_volume);
 
-  uint32_t hardware_delay_bytes =
-      params_.GetBytesPerSecond() *
-      static_cast<int>(params_.GetBufferDuration().InSeconds() * 2) *
-      params_.channels();
-
-  while (fifo_.available_blocks()) {
-    const AudioBus* audio_bus = fifo_.Consume();
-    hardware_delay_bytes +=
-        (fifo_.GetAvailableFrames() * params_.GetBytesPerFrame());
-
-    // To reduce latency run client CB from dedicated thread
-    if (callback_)
-      audio_worker_.message_loop()->PostTask(
-          FROM_HERE, base::BindOnce(&CapiAudioInputStream::OnAudioIOData,
-                                    base::Unretained(this), audio_bus,
-                                    hardware_delay_bytes, normalized_volume));
-  }
+  callback_->OnData(
+      audio_bus.get(),
+      base::TimeTicks::Now() - base::Seconds(hardware_delay_seconds),
+      normalized_volume);
 }
 
 }  // namespace media
index 7fa0fac..bc9bd4b 100644 (file)
 #include "media/audio/agc_audio_stream.h"
 #include "media/audio/audio_device_name.h"
 #include "media/audio/audio_io.h"
-#include "media/audio/audio_parameters.h"
 #include "media/audio/tizen/capi_util.h"
 #include "media/base/audio_block_fifo.h"
+#include "media/base/audio_parameters.h"
 
 namespace media {
 
 class AudioManagerCapi;
 
-class CapiAudioInputStream final : public AgcAudioStream<AudioInputStream> {
+class CapiAudioInputStream : public AgcAudioStream<AudioInputStream> {
  public:
   CapiAudioInputStream(AudioManagerCapi* audio_manager,
-                       const std::string& device_name,
                        const AudioParameters& params);
-  CapiAudioInputStream(const CapiAudioInputStream&) = delete;
-  CapiAudioInputStream& operator=(const CapiAudioInputStream&) = delete;
+
   ~CapiAudioInputStream() override;
 
   CapiAudioInputStream(const CapiAudioInputStream&) = delete;
   CapiAudioInputStream& operator=(const CapiAudioInputStream&) = delete;
 
-  bool Open() override;
+  // Implementation of AudioInputStream.
+  AudioInputStream::OpenOutcome Open() override;
   void Start(AudioInputCallback* callback) override;
   void Stop() override;
   void Close() override;
   double GetMaxVolume() override;
   void SetVolume(double volume) override;
   double GetVolume() override;
-  bool IsMuted();
-  void OnAudioIOData(const AudioBus* audio_bus,
-                     uint32_t hardware_delay_bytes,
-                     double normalized_volume);
+  bool IsMuted() override;
+  void SetOutputDeviceForAec(const std::string& output_device_id) override;
 
- private:
-  static void AudioStreamReadCB(audio_in_h handle,
-                                size_t nbytes,
-                                void* user_data);
-  void ReadAudioData();
+ protected:
+  virtual bool OpenMic() = 0;
+  virtual void StartMic() = 0;
+  virtual void StopMic() = 0;
+  virtual void CloseMic(bool success) = 0;
+  void OnAudioIOData(std::unique_ptr<AudioBus> audio_bus,
+                     double hardware_delay_seconds,
+                     double normalized_volume);
 
-  AudioManagerCapi* audio_manager_;
   AudioInputCallback* callback_;
-  std::string device_name_;
   AudioParameters params_;
-  double volume_;
   media::InternalState state_;
   base::Thread audio_worker_;
-  audio_in_h device_;
-
   // Holds the data from the OS.
   AudioBlockFifo fifo_;
+
+ private:
+  AudioManagerCapi* audio_manager_;
+  double volume_;
 };
 
 }  // namespace media
index 48e1e26..45a5e05 100644 (file)
@@ -7,26 +7,44 @@
 #include <audio_io.h>
 
 #include "base/bind.h"
-#include "base/single_thread_task_runner.h"
+#include "base/logging.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/time/default_tick_clock.h"
 #include "media/audio/audio_manager_base.h"
-#include "media/audio/audio_parameters.h"
+#include "media/base/audio_parameters.h"
 
 namespace {
 
-const int kBitsPerByte = 8;
-
-static void OnAudioIOInterrupted(audio_io_interrupted_code_e code, void* data) {
-  media::CapiAudioOutputStream* self =
-      static_cast<media::CapiAudioOutputStream*>(data);
-  LOG(WARNING) << "Play interrupted: audio_io_interrupted_code_e : " << code;
-  if (self)
-    self->HandleError();
+#define ENUM_CASE(x) \
+  case x:            \
+    return #x;       \
+    break
+
+const char* GetString(audio_io_error_e error) {
+  switch (error) {
+    ENUM_CASE(AUDIO_IO_ERROR_INVALID_PARAMETER);
+    ENUM_CASE(AUDIO_IO_ERROR_INVALID_BUFFER);
+    ENUM_CASE(AUDIO_IO_ERROR_SOUND_POLICY);
+    ENUM_CASE(AUDIO_IO_ERROR_INVALID_STATE);
+    ENUM_CASE(AUDIO_IO_ERROR_NONE);
+  };
+  NOTREACHED() << "Invalid FlushErrorCode! (code=" << error << ")";
+  return "";
 }
+#undef ENUM_CASE
 
-}
+}  // namespace
 
 namespace media {
 
+// static
+void CapiAudioOutputStream::AudioStreamWriteCB(audio_out_h handle,
+                                               size_t nbytes,
+                                               void* user_data) {
+  CapiAudioOutputStream* os = static_cast<CapiAudioOutputStream*>(user_data);
+  os->WriteAudioData(nbytes);
+}
+
 CapiAudioOutputStream::CapiAudioOutputStream(const AudioParameters& params,
                                              AudioManagerBase* manager)
     : params_(params),
@@ -47,15 +65,7 @@ CapiAudioOutputStream::~CapiAudioOutputStream() {}
 void CapiAudioOutputStream::HandleError() {
   if (source_callback_ == NULL)
     return;
-  source_callback_->OnError(this);
-}
-
-//static
-void CapiAudioOutputStream::AudioStreamWriteCB(audio_out_h handle,
-                                               size_t nbytes,
-                                               void* user_data) {
-  CapiAudioOutputStream* os = static_cast<CapiAudioOutputStream*>(user_data);
-  os->WriteAudioData(nbytes);
+  source_callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
 }
 
 bool CapiAudioOutputStream::Open() {
@@ -63,25 +73,15 @@ bool CapiAudioOutputStream::Open() {
   DCHECK(state_ == media::kIsClosed);
 
   if (AUDIO_IO_ERROR_NONE !=
-          audio_out_create(params_.sample_rate(),
-                           ToCapiAudioEnum(params_.channel_layout()),
-                           ToCapiBPSEnum(params_.bits_per_sample()),
-                           SOUND_TYPE_MEDIA,
-                           &audio_out_)) {
+      audio_out_create_new(
+          params_.sample_rate(), ToCapiAudioEnum(params_.channel_layout()),
+          ToCapiSampleType(kDefaultSampleFormat), &audio_out_)) {
     LOG(ERROR) << "Fail to create audio output";
     return false;
   }
 
-  if (AUDIO_IO_ERROR_NONE !=
-          audio_out_set_interrupted_cb(
-              audio_out_,
-              OnAudioIOInterrupted,
-              this)) {
-    LOG(ERROR) << "Fail to audio_out_set_interrupted_cb";
-    HandleError();
-  }
-
-  buffer_ = (char*) malloc(sizeof(char) * params_.GetBytesPerBuffer());
+  buffer_ = (char*)malloc(sizeof(char) *
+                          params_.GetBytesPerBuffer(kDefaultSampleFormat));
   if (!buffer_) {
     LOG(ERROR) << "Memory allocation for |buffer_| Failed";
     return false;
@@ -139,7 +139,6 @@ void CapiAudioOutputStream::Close() {
 
   state_ = media::kIsClosed;
 
-  audio_out_unset_interrupted_cb(audio_out_);  // always success
   audio_out_destroy(audio_out_);  // always success
   audio_out_ = NULL;
   free(buffer_);
@@ -157,20 +156,28 @@ void CapiAudioOutputStream::GetVolume(double* volume) {
   *volume = volume_;
 }
 
+void CapiAudioOutputStream::Flush() {
+  DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
+  if (state_ != media::kIsStarted)
+    return;
+
+  int flush_status = audio_out_flush(audio_out_);
+  if (flush_status != AUDIO_IO_ERROR_NONE) {
+    LOG(ERROR) << "Flush Error Code "
+               << GetString(static_cast<audio_io_error_e>(flush_status));
+  }
+}
+
 void CapiAudioOutputStream::WriteAudioData(size_t nbytes) {
   int bytes_remaining = nbytes;
-  size_t bytes_to_fill = params_.GetBytesPerBuffer();
 
-  int channel_count = params_.channel_layout() == CHANNEL_LAYOUT_STEREO ? 2 : 1;
+  size_t bytes_to_fill = params_.GetBytesPerBuffer(kDefaultSampleFormat);
 
   while (bytes_remaining > 0) {
     int frames_filled = 0;
     if (source_callback_) {
       frames_filled = source_callback_->OnMoreData(
-          audio_bus_.get(),
-          static_cast<int>(params_.GetBufferDuration().InSeconds() *
-                           channel_count),
-          0);
+          base::TimeDelta(), base::TimeTicks::Now(), 0, audio_bus_.get());
     }
 
     memset(buffer_, 0, bytes_to_fill);
@@ -182,16 +189,15 @@ void CapiAudioOutputStream::WriteAudioData(size_t nbytes) {
     }
 
     audio_bus_->Scale(volume_);
-    audio_bus_->ToInterleaved(audio_bus_->frames(),
-                              params_.bits_per_sample() / kBitsPerByte, buffer_);
+    audio_bus_->ToInterleaved<media::SignedInt16SampleTypeTraits>(
+        audio_bus_->frames(), reinterpret_cast<int16_t*>(buffer_));
 
-    int bytes_written =
-        audio_out_write(audio_out_, buffer_, bytes_to_fill);
+    int bytes_written = audio_out_write(audio_out_, buffer_, bytes_to_fill);
 
     if (bytes_written < 0) {
       if (source_callback_) {
         LOG(ERROR) << "FAILED: audio_out_write";
-        source_callback_->OnError(this);
+        source_callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
         continue;
       }
     }
index 6b7c4bd..e8c0f0e 100644 (file)
@@ -13,8 +13,8 @@
 
 #include "base/threading/thread.h"
 #include "media/audio/audio_io.h"
-#include "media/audio/audio_parameters.h"
 #include "media/audio/tizen/capi_util.h"
+#include "media/base/audio_parameters.h"
 
 namespace media {
 
@@ -24,8 +24,7 @@ class CapiAudioOutputStream : public AudioOutputStream {
  public:
   CapiAudioOutputStream(const AudioParameters& params,
                         AudioManagerBase* manager);
-  CapiAudioOutputStream(const CapiAudioOutputStream&) = delete;
-  CapiAudioOutputStream& operator=(const CapiAudioOutputStream&) = delete;
+
   ~CapiAudioOutputStream() override;
 
   CapiAudioOutputStream(const CapiAudioOutputStream&) = delete;
@@ -37,6 +36,7 @@ class CapiAudioOutputStream : public AudioOutputStream {
   void Stop() override;
   void SetVolume(double volume) override;
   void GetVolume(double* volume) override;
+  void Flush() override;
   void HandleError();
 
  private:
diff --git a/tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.cc b/tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.cc
new file mode 100644 (file)
index 0000000..d045f9c
--- /dev/null
@@ -0,0 +1,298 @@
+// Copyright (c) 202020 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/tizen/capi_usb_audio_input_stream.h"
+
+#include <audio_io.h>
+#include <sys/types.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "media/audio/tizen/audio_manager_capi.h"
+
+#include <sound_manager_internal.h>
+namespace media {
+
+CapiUsbAudioInputStream::CapiUsbAudioInputStream(
+    AudioManagerCapi* audio_manager,
+    const std::string& device_name,
+    const AudioParameters& params)
+    : CapiAudioInputStream(audio_manager, params) {
+  device_ = nullptr;
+  device_name_ = device_name;
+#if BUILDFLAG(IS_TIZEN_TV)
+  device_added_for_stream_routing_ = false;
+  device_list_ = nullptr;
+  sound_device_ = nullptr;
+  stream_info_ = nullptr;
+#endif
+}
+
+CapiUsbAudioInputStream::~CapiUsbAudioInputStream() {
+#if !BUILDFLAG(IS_TIZEN_TV)
+  DCHECK(!device_);
+#endif
+}
+
+// static
+void CapiUsbAudioInputStream::AudioStreamReadCB(audio_in_h handle,
+                                                size_t nbytes,
+                                                void* user_data) {
+  CapiUsbAudioInputStream* inputStream =
+      static_cast<CapiUsbAudioInputStream*>(user_data);
+  if (inputStream)
+    inputStream->ReadAudioData();
+}
+
+bool CapiUsbAudioInputStream::OpenMic() {
+  int ret;
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  // TODO(Girish): Register stream focus changed callback and take action
+  // accordingly.
+
+  ret = sound_manager_get_device_list(SOUND_DEVICE_IO_DIRECTION_IN_MASK,
+                                      &device_list_);
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "sound_manager_get_device_list falied. Err:" << ret;
+    CloseMic(false);
+    return false;
+  }
+
+  int device_id = std::stoi(device_name_, nullptr, 0);
+  sound_device_h device;
+  sound_device_type_e device_type;
+  sound_stream_type_e stream_type = SOUND_STREAM_TYPE_MEDIA_EXTERNAL_ONLY;
+
+  while (!sound_manager_get_next_device(device_list_, &device)) {
+    int id;
+
+    if (sound_manager_get_device_id(device, &id)) {
+      LOG(ERROR) << "Failed to get device ID";
+      continue;
+    }
+
+    if (sound_manager_get_device_type(device, &device_type)) {
+      LOG(ERROR) << "Failed to get device TYPE";
+      continue;
+    }
+
+    if (device_id == id) {
+      sound_device_ = device;
+      if (device_type == SOUND_DEVICE_BUILTIN_MIC) {
+        stream_type = SOUND_STREAM_TYPE_MEDIA;
+        sound_manager_set_stream_preemptive_device(
+            stream_type, SOUND_DEVICE_IO_DIRECTION_IN, device_id);
+      }
+      break;
+    }
+  }
+
+  if (sound_device_ == nullptr) {
+    LOG(ERROR) << "Sound device with the mentioned ID does not exist";
+    CloseMic(false);
+    return false;
+  }
+
+  stream_info_ = nullptr;
+
+  ret = sound_manager_create_stream_information(stream_type, nullptr, nullptr,
+                                                &stream_info_);
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "sound_manager_create_stream_information failed. Err:" << ret;
+    CloseMic(false);
+    return false;
+  }
+
+  if (device_type != SOUND_DEVICE_BUILTIN_MIC) {
+    ret = sound_manager_add_device_for_stream_routing(stream_info_,
+                                                      sound_device_);
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+      LOG(ERROR) << "sound_manager_add_device_for_stream_routing failed. Err:"
+                 << ret;
+      CloseMic(false);
+      return false;
+    }
+
+    device_added_for_stream_routing_ = true;
+    ret = sound_manager_apply_stream_routing(stream_info_);
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+      LOG(ERROR) << "sound_manager_apply_stream_routing failed. Err:" << ret;
+      CloseMic(false);
+      return false;
+    }
+  }
+#endif
+
+  ret = audio_in_create(params_.sample_rate(), AUDIO_CHANNEL_STEREO,
+                        AUDIO_SAMPLE_TYPE_S16_LE, &device_);
+  if (ret != AUDIO_IO_ERROR_NONE) {
+    LOG(ERROR) << "audio_in_create failed. Err:" << ret;
+    CloseMic(false);
+    return false;
+  }
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  ret = audio_in_set_sound_stream_info(device_, stream_info_);
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LOG(ERROR) << "audio_in_set_sound_stream_info failed. Err:" << ret;
+    CloseMic(false);
+    return false;
+  }
+#endif
+
+  state_ = media::kIsOpened;
+  return true;
+}
+
+void CapiUsbAudioInputStream::StartMic() {
+  DCHECK(device_);
+
+  int ret = audio_in_set_stream_cb(device_, &AudioStreamReadCB, this);
+  if (ret != AUDIO_IO_ERROR_NONE) {
+    LOG(ERROR) << "audio_in_set_stream_cb failed. Err:" << ret;
+    if (callback_)
+      callback_->OnError();
+    return;
+  }
+
+  audio_worker_.Start();
+  StartAgc();
+
+  ret = audio_in_prepare(device_);
+  if (ret != AUDIO_IO_ERROR_NONE) {
+    LOG(ERROR) << "Cannot prepare audio input. Err:" << ret;
+    if (callback_)
+      callback_->OnError();
+    return;
+  }
+
+  state_ = media::kIsStarted;
+}
+
+void CapiUsbAudioInputStream::StopMic() {
+  DCHECK(device_);
+
+  if (AUDIO_IO_ERROR_NONE != audio_in_unprepare(device_))
+    LOG(WARNING) << "Cannot unprepare audio input";
+
+  if (AUDIO_IO_ERROR_NONE != audio_in_unset_stream_cb(device_))
+    LOG(WARNING) << "Cannot unset audio input cb";
+}
+
+void CapiUsbAudioInputStream::CloseMic(bool success) {
+  state_ = media::kIsClosed;
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  sound_device_type_e device_type;
+  sound_manager_get_device_type(sound_device_, &device_type);
+
+  if (device_type == SOUND_DEVICE_BUILTIN_MIC) {
+    sound_manager_set_stream_preemptive_device(
+        SOUND_STREAM_TYPE_MEDIA, SOUND_DEVICE_IO_DIRECTION_IN,
+        SOUND_MANAGER_STREAM_NO_PREEMPTIVE_DEVICE);
+  }
+
+  if (device_added_for_stream_routing_) {
+    int ret = sound_manager_remove_device_for_stream_routing(stream_info_,
+                                                             sound_device_);
+    if (ret != SOUND_MANAGER_ERROR_NONE)
+      LOG(ERROR)
+          << "sound_manager_remove_device_for_stream_routing failed. Err:"
+          << ret;
+
+    device_added_for_stream_routing_ = false;
+  }
+  sound_device_ = nullptr;
+
+  if (device_list_) {
+    int ret = sound_manager_free_device_list(device_list_);
+    if (ret != SOUND_MANAGER_ERROR_NONE)
+      LOG(ERROR) << "sound_manager_free_device_list failed. Err:" << ret;
+
+    device_list_ = nullptr;
+  }
+
+  if (stream_info_) {
+    int ret = sound_manager_destroy_stream_information(stream_info_);
+    if (ret != SOUND_MANAGER_ERROR_NONE)
+      LOG(ERROR) << "sound_manager_destroy_stream_information failed. Err:"
+                 << ret;
+
+    stream_info_ = nullptr;
+  }
+#endif
+
+  if (device_) {
+    int ret = audio_in_destroy(device_);
+    if (ret != AUDIO_IO_ERROR_NONE)
+      LOG(WARNING) << "audio_in_destroy failed. Err:" << ret;
+
+    device_ = nullptr;
+  }
+
+  if (!success && callback_)
+    callback_->OnError();
+}
+
+void CapiUsbAudioInputStream::ReadAudioData() {
+  unsigned int bytes_read = 0;
+  const void* loc_buff = nullptr;
+
+  if (AUDIO_IO_ERROR_NONE != audio_in_peek(device_, &loc_buff, &bytes_read)) {
+    LOG(ERROR) << "audio_in_peek() failed";
+    if (callback_)
+      callback_->OnError();
+    return;
+  }
+
+  int number_of_frames =
+      bytes_read / params_.GetBytesPerFrame(kDefaultSampleFormat);
+  if (number_of_frames > fifo_.GetUnfilledFrames()) {
+    int increase_blocks_of_buffer =
+        (number_of_frames - fifo_.GetUnfilledFrames()) /
+            params_.frames_per_buffer() +
+        1;
+    fifo_.IncreaseCapacity(increase_blocks_of_buffer);
+  }
+
+  fifo_.Push(loc_buff, number_of_frames,
+             SampleFormatToBytesPerChannel(kDefaultSampleFormat));
+
+  double normalized_volume = 0.0;
+  GetAgcVolume(&normalized_volume);
+
+  double hardware_delay_seconds =
+      static_cast<double>(params_.GetBufferDuration().InSeconds() * 2) *
+      params_.channels();
+
+  while (fifo_.available_blocks()) {
+    const AudioBus* audio_bus = fifo_.Consume();
+
+    hardware_delay_seconds +=
+        static_cast<double>(fifo_.GetAvailableFrames()) / params_.sample_rate();
+
+    // To reduce latency run client CB from dedicated thread
+    if (callback_) {
+      // Need to copy data out if it runs in different thread
+      std::unique_ptr<AudioBus> audio_bus_copy =
+          AudioBus::Create(audio_bus->channels(), audio_bus->frames());
+      audio_bus->CopyTo(audio_bus_copy.get());
+      audio_worker_.task_runner()->PostTask(
+          FROM_HERE,
+          base::BindOnce(&CapiUsbAudioInputStream::OnAudioIOData,
+                         base::Unretained(this), std::move(audio_bus_copy),
+                         hardware_delay_seconds, normalized_volume));
+    }
+  }
+
+  if (AUDIO_IO_ERROR_NONE != audio_in_drop(device_)) {
+    LOG(ERROR) << "audio_in_drop() failed";
+    if (callback_)
+      callback_->OnError();
+    return;
+  }
+}
+
+}  // namespace media
diff --git a/tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.h b/tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.h
new file mode 100644 (file)
index 0000000..ab19405
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (c) 2014 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_AUDIO_TIZEN_CAPI_USB_AUDIO_INPUT_STREAM_H_
+#define MEDIA_AUDIO_TIZEN_CAPI_USB_AUDIO_INPUT_STREAM_H_
+
+#include <audio_io.h>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "media/audio/agc_audio_stream.h"
+#include "media/audio/audio_debug_recording_helper.h"
+#include "media/audio/audio_device_name.h"
+#include "media/audio/tizen/capi_audio_input.h"
+#include "media/audio/tizen/capi_util.h"
+#include "media/base/audio_block_fifo.h"
+#include "media/base/audio_parameters.h"
+namespace media {
+
+class CapiUsbAudioInputStream final : public CapiAudioInputStream {
+ public:
+  CapiUsbAudioInputStream(AudioManagerCapi* audio_manager,
+                          const std::string& device_name,
+                          const AudioParameters& params);
+
+  ~CapiUsbAudioInputStream() override;
+
+  CapiUsbAudioInputStream(const CapiUsbAudioInputStream&) = delete;
+  CapiUsbAudioInputStream& operator=(const CapiUsbAudioInputStream&) = delete;
+
+  // Implementation of AudioInputStream.
+ protected:
+  bool OpenMic() override;
+  void StartMic() override;
+  void StopMic() override;
+  void CloseMic(bool success) override;
+
+ private:
+  static void AudioStreamReadCB(audio_in_h handle,
+                                size_t nbytes,
+                                void* user_data);
+
+  void ReadAudioData();
+
+  audio_in_h device_;
+  std::string device_name_;
+#if BUILDFLAG(IS_TIZEN_TV)
+  bool device_added_for_stream_routing_;
+  sound_device_list_h device_list_;
+  sound_device_h sound_device_;
+  sound_stream_info_h stream_info_;
+#endif
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_TIZEN_CAPI_USB_AUDIO_INPUT_STREAM
index f070936..f0bac70 100644 (file)
@@ -4,17 +4,9 @@
 
 #include "media/audio/tizen/capi_util.h"
 
-#include <audio_io.h>
-
 #include "base/logging.h"
 #include "base/time/time.h"
 
-namespace {
-
-const int kDefaultSampleRate = 44100;
-const int kDefaultBitsPerSec = 8;
-}
-
 namespace media {
 
 audio_channel_e ToCapiAudioEnum(media::ChannelLayout e) {
@@ -24,10 +16,9 @@ audio_channel_e ToCapiAudioEnum(media::ChannelLayout e) {
   return AUDIO_CHANNEL_MONO;
 }
 
-audio_sample_type_e ToCapiBPSEnum(int bits_per_sec) {
-  if (bits_per_sec == kDefaultBitsPerSec) {
+audio_sample_type_e ToCapiSampleType(SampleFormat sample_format) {
+  if (sample_format == kSampleFormatU8)
     return AUDIO_SAMPLE_TYPE_U8;
-  }
   return AUDIO_SAMPLE_TYPE_S16_LE;
 }
 
@@ -46,10 +37,8 @@ int GetAudioInputBufferSize(audio_in_h audio_in) {
     }
   } else {
     // create |audio_in| locally to get buffer size.
-    err = audio_in_create(kDefaultSampleRate,
-                          AUDIO_CHANNEL_STEREO,
-                          AUDIO_SAMPLE_TYPE_S16_LE,
-                          &audio_in);
+    err = audio_in_create(kDefaultSampleRate, AUDIO_CHANNEL_STEREO,
+                          AUDIO_SAMPLE_TYPE_S16_LE, &audio_in);
     if (AUDIO_IO_ERROR_NONE != err) {
       LOG(ERROR) << "audio_in_create() failed, Error code " << err;
       return 0;
@@ -57,8 +46,7 @@ int GetAudioInputBufferSize(audio_in_h audio_in) {
     local_audio_handle = true;
   }
 
-  if (AUDIO_IO_ERROR_NONE ==
-          audio_in_prepare(audio_in)) {
+  if (AUDIO_IO_ERROR_NONE == audio_in_prepare(audio_in)) {
     audio_in_get_buffer_size(audio_in, &buffer_size);
     audio_in_unprepare(audio_in);
   }
@@ -72,7 +60,7 @@ int GetAudioInputBufferSize(audio_in_h audio_in) {
 int GetAudioOutputBufferSize(audio_out_h audio_out,
                              int sample_rate,
                              media::ChannelLayout channel_layout,
-                             int bit_per_sample) {
+                             SampleFormat sample_format) {
   int buffer_size = 0;
   bool local_audio_handle = false;
   int err = AUDIO_IO_ERROR_NONE;
@@ -87,20 +75,16 @@ int GetAudioOutputBufferSize(audio_out_h audio_out,
     }
   } else {
     // create |audio_out| locally to get buffer size.
-    err = audio_out_create(sample_rate,
-                           ToCapiAudioEnum(channel_layout),
-                           ToCapiBPSEnum(bit_per_sample),
-                           SOUND_TYPE_MEDIA,
-                           &audio_out);
+    err = audio_out_create_new(sample_rate, ToCapiAudioEnum(channel_layout),
+                               ToCapiSampleType(sample_format), &audio_out);
     if (AUDIO_IO_ERROR_NONE != err) {
-      LOG(ERROR) << "audio_out_create() failed, Error code " << err;
+      LOG(ERROR) << "audio_out_create_new() failed, Error code " << err;
       return 0;
     }
     local_audio_handle = true;
   }
 
-  if (AUDIO_IO_ERROR_NONE ==
-          audio_out_prepare(audio_out)) {
+  if (AUDIO_IO_ERROR_NONE == audio_out_prepare(audio_out)) {
     audio_out_get_buffer_size(audio_out, &buffer_size);
     audio_out_unprepare(audio_out);
   }
@@ -114,16 +98,13 @@ int GetAudioOutputBufferSize(audio_out_h audio_out,
 int GetAudioOutputSampleRate(audio_out_h audio_out,
                              int sample_rate,
                              media::ChannelLayout channel_layout,
-                             int bit_per_sample) {
+                             SampleFormat sample_format) {
   int err = AUDIO_IO_ERROR_NONE;
 
-  //If NULL try to create audio handle with passed sample rate.
+  // If NULL try to create audio handle with passed sample rate.
   if (audio_out == NULL) {
-    err = audio_out_create(sample_rate,
-                           ToCapiAudioEnum(channel_layout),
-                           ToCapiBPSEnum(bit_per_sample),
-                           SOUND_TYPE_MEDIA,
-                           &audio_out);
+    err = audio_out_create_new(sample_rate, ToCapiAudioEnum(channel_layout),
+                               ToCapiSampleType(sample_format), &audio_out);
 
     if (AUDIO_IO_ERROR_NONE == err) {
       audio_out_destroy(audio_out);
@@ -132,9 +113,9 @@ int GetAudioOutputSampleRate(audio_out_h audio_out,
     return 0;
   }
 
-  //If not NULL get samplerate of passed audio_out handle.
+  // If not NULL get samplerate of passed audio_out handle.
   if (AUDIO_IO_ERROR_NONE !=
-          audio_out_get_sample_rate(audio_out, &sample_rate)) {
+      audio_out_get_sample_rate(audio_out, &sample_rate)) {
     return 0;
   }
 
@@ -143,7 +124,7 @@ int GetAudioOutputSampleRate(audio_out_h audio_out,
 
 int LatencyInBytes(int latency_milli, int sample_rate, int bytes_per_frame) {
   return latency_milli * sample_rate * bytes_per_frame /
-      base::Time::kMillisecondsPerSecond;
+         base::Time::kMillisecondsPerSecond;
 }
 
 int GetAudioInLatencyInBytes(audio_in_h audio_in, int bytes_per_frame) {
@@ -152,8 +133,8 @@ int GetAudioInLatencyInBytes(audio_in_h audio_in, int bytes_per_frame) {
   static int latency_milli = 0;
   static int sample_rate = 0;
 
-  if (sample_rate == 0 && AUDIO_IO_ERROR_NONE !=
-          audio_in_get_sample_rate(audio_in, &sample_rate))
+  if (sample_rate == 0 &&
+      AUDIO_IO_ERROR_NONE != audio_in_get_sample_rate(audio_in, &sample_rate))
     return 0;
 
   return LatencyInBytes(latency_milli, sample_rate, bytes_per_frame);
@@ -165,8 +146,8 @@ int GetAudioOutLatencyInBytes(audio_out_h audio_out, int bytes_per_frame) {
   static int latency_milli = 0;
   static int sample_rate = 0;
 
-  if (sample_rate == 0 && AUDIO_IO_ERROR_NONE !=
-          audio_out_get_sample_rate(audio_out, &sample_rate))
+  if (sample_rate == 0 &&
+      AUDIO_IO_ERROR_NONE != audio_out_get_sample_rate(audio_out, &sample_rate))
     return 0;
 
   return LatencyInBytes(latency_milli, sample_rate, bytes_per_frame);
index a7078f8..a852077 100644 (file)
@@ -5,17 +5,26 @@
 // Utils to use tizen Core API for audio output/input.
 // (tizen capi-media-audio-io.)
 
-
 #ifndef MEDIA_AUDIO_TIZEN_CAPI_UTIL_H_
 #define MEDIA_AUDIO_TIZEN_CAPI_UTIL_H_
 
 #include <audio_io.h>
-#include <sound_manager.h>
 
-#include "media/audio/audio_parameters.h"
+#include "media/base/audio_parameters.h"
 
 namespace media {
 
+const int kMaxOutputStreams = 50;
+const int kDefaultSampleRate = 44100;
+const int kDefaultOutputBufferSize = 512;
+const int kDefaultInputBufferSize = 1024;
+const int kBitsPerSample = 16;
+const SampleFormat kDefaultSampleFormat = kSampleFormatS16;
+#if BUILDFLAG(IS_TIZEN_TV)
+const int kBtMinReadSize = 720;
+const int kBtSampleRate = 16000;
+#endif
+
 enum InternalState {
   kInError = 0,
   kIsOpened,
@@ -26,19 +35,19 @@ enum InternalState {
 
 audio_channel_e ToCapiAudioEnum(media::ChannelLayout e);
 
-audio_sample_type_e ToCapiBPSEnum(int bitPerSecond);
+audio_sample_type_e ToCapiSampleType(SampleFormat sample_format);
 
 int GetAudioInputBufferSize(audio_in_h audio_in);
 
 int GetAudioOutputBufferSize(audio_out_h audio_out,
                              int sample_rate,
                              media::ChannelLayout channel_layout,
-                             int bit_per_sample);
+                             SampleFormat sample_format);
 
 int GetAudioOutputSampleRate(audio_out_h audio_out,
                              int sample_rate,
                              media::ChannelLayout channel_layout,
-                             int bit_per_sample);
+                             SampleFormat sample_format);
 
 int LatencyInBytes(int latency_milli, int sample_rate, int bytes_per_frame);
 
index ff1ba71..7edc247 100644 (file)
@@ -4,6 +4,8 @@
 
 import("//tizen_src/build/config/tizen_features.gni")
 
+external_media_efl_audio_io_config = []
+external_media_efl_audio_io_sources = []
 external_media_efl_deps = []
 external_media_efl_sources = []
 external_exclude_media_efl_sources = []
@@ -127,3 +129,23 @@ if (tizen_multimedia) {
     "//tizen_src/chromium_impl/media/base/tizen/media_player_bridge_capi.h",
   ]
 }
+
+if (tizen_audio_io) {
+  external_media_efl_audio_io_config += [
+    "//tizen_src/build:capi-media-audio-io",
+    "//tizen_src/build:libcapi-media-audio-io",
+  ]
+
+  external_media_efl_audio_io_sources += [
+    "//tizen_src/chromium_impl/media/audio/tizen/audio_manager_capi.cc",
+    "//tizen_src/chromium_impl/media/audio/tizen/audio_manager_capi.h",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_audio_input.cc",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_audio_input.h",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_audio_output.cc",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_audio_output.h",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.cc",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_usb_audio_input_stream.h",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_util.cc",
+    "//tizen_src/chromium_impl/media/audio/tizen/capi_util.h",
+  ]
+}