tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CubebInputStream.cpp (6681B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CubebInputStream.h"
      8 
      9 #include "AudioSampleFormat.h"
     10 #include "mozilla/Logging.h"
     11 
     12 namespace mozilla {
     13 
     14 extern mozilla::LazyLogModule gMediaTrackGraphLog;
     15 
     16 #ifdef LOG_INTERNAL
     17 #  undef LOG_INTERNAL
     18 #endif  // LOG_INTERNAL
     19 #define LOG_INTERNAL(level, msg, ...) \
     20  MOZ_LOG(gMediaTrackGraphLog, LogLevel::level, (msg, ##__VA_ARGS__))
     21 
     22 #ifdef LOG
     23 #  undef LOG
     24 #endif  // LOG
     25 #define LOG(msg, ...) LOG_INTERNAL(Debug, msg, ##__VA_ARGS__)
     26 
     27 #ifdef LOGE
     28 #  undef LOGE
     29 #endif  // LOGE
     30 #define LOGE(msg, ...) LOG_INTERNAL(Error, msg, ##__VA_ARGS__)
     31 
     32 #define InvokeCubebWithLog(func, ...)                                          \
     33  ({                                                                           \
     34    int _retval;                                                               \
     35    _retval = InvokeCubeb(func, ##__VA_ARGS__);                                \
     36    if (_retval == CUBEB_OK) {                                                 \
     37      LOG("CubebInputStream %p: %s for stream %p was successful", this, #func, \
     38          mStream.get());                                                      \
     39    } else {                                                                   \
     40      LOGE("CubebInputStream %p: %s for stream %p was failed. Error %d", this, \
     41           #func, mStream.get(), _retval);                                     \
     42    }                                                                          \
     43    _retval;                                                                   \
     44  })
     45 
     46 static cubeb_stream_params CreateStreamInitParams(uint32_t aChannels,
     47                                                  uint32_t aRate,
     48                                                  bool aIsVoice) {
     49  cubeb_stream_params params;
     50  params.format = CubebUtils::ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value;
     51  params.rate = aRate;
     52  params.channels = aChannels;
     53  params.layout = CUBEB_LAYOUT_UNDEFINED;
     54  params.prefs = CubebUtils::GetDefaultStreamPrefs(CUBEB_DEVICE_TYPE_INPUT);
     55  params.input_params = CUBEB_INPUT_PROCESSING_PARAM_NONE;
     56 
     57  if (aIsVoice) {
     58    params.prefs |= static_cast<cubeb_stream_prefs>(CUBEB_STREAM_PREF_VOICE);
     59  }
     60 
     61  return params;
     62 }
     63 
     64 void CubebInputStream::CubebDestroyPolicy::operator()(
     65    cubeb_stream* aStream) const {
     66  int r = cubeb_stream_register_device_changed_callback(aStream, nullptr);
     67  if (r == CUBEB_OK) {
     68    LOG("Unregister device changed callback for %p successfully", aStream);
     69  } else {
     70    LOGE("Fail to unregister device changed callback for %p. Error %d", aStream,
     71         r);
     72  }
     73  cubeb_stream_destroy(aStream);
     74 }
     75 
     76 /* static */
     77 UniquePtr<CubebInputStream> CubebInputStream::Create(cubeb_devid aDeviceId,
     78                                                     uint32_t aChannels,
     79                                                     uint32_t aRate,
     80                                                     bool aIsVoice,
     81                                                     Listener* aListener) {
     82  if (!aListener) {
     83    LOGE("No available listener");
     84    return nullptr;
     85  }
     86 
     87  RefPtr<CubebUtils::CubebHandle> handle = CubebUtils::GetCubeb();
     88  if (!handle) {
     89    LOGE("No valid cubeb context");
     90    CubebUtils::ReportCubebStreamInitFailure(CubebUtils::GetFirstStream());
     91    return nullptr;
     92  }
     93 
     94  cubeb_stream_params params =
     95      CreateStreamInitParams(aChannels, aRate, aIsVoice);
     96  uint32_t latencyFrames = CubebUtils::GetCubebMTGLatencyInFrames(&params);
     97 
     98  cubeb_stream* cubebStream = nullptr;
     99 
    100  RefPtr<Listener> listener(aListener);
    101  if (int r = CubebUtils::CubebStreamInit(
    102          handle->Context(), &cubebStream, "input-only stream", aDeviceId,
    103          &params, nullptr, nullptr, latencyFrames, DataCallback_s,
    104          StateCallback_s, listener.get());
    105      r != CUBEB_OK) {
    106    CubebUtils::ReportCubebStreamInitFailure(CubebUtils::GetFirstStream());
    107    LOGE("Fail to create a cubeb stream. Error %d", r);
    108    return nullptr;
    109  }
    110 
    111  UniquePtr<cubeb_stream, CubebDestroyPolicy> inputStream(cubebStream);
    112 
    113  LOG("Create a cubeb stream %p successfully", inputStream.get());
    114 
    115  UniquePtr<CubebInputStream> stream(new CubebInputStream(
    116      listener.forget(), handle.forget(), std::move(inputStream)));
    117  stream->Init();
    118  return stream;
    119 }
    120 
    121 CubebInputStream::CubebInputStream(
    122    already_AddRefed<Listener>&& aListener,
    123    already_AddRefed<CubebUtils::CubebHandle>&& aCubeb,
    124    UniquePtr<cubeb_stream, CubebDestroyPolicy>&& aStream)
    125    : mListener(aListener), mCubeb(aCubeb), mStream(std::move(aStream)) {
    126  MOZ_ASSERT(mListener);
    127  MOZ_ASSERT(mStream);
    128 }
    129 
    130 void CubebInputStream::Init() {
    131  // cubeb_stream_register_device_changed_callback is only supported on macOS
    132  // platform and MockCubeb for now.
    133  InvokeCubebWithLog(cubeb_stream_register_device_changed_callback,
    134                     CubebInputStream::DeviceChangedCallback_s);
    135 }
    136 
    137 int CubebInputStream::Start() { return InvokeCubebWithLog(cubeb_stream_start); }
    138 
    139 int CubebInputStream::Stop() { return InvokeCubebWithLog(cubeb_stream_stop); }
    140 
    141 int CubebInputStream::SetProcessingParams(
    142    cubeb_input_processing_params aParams) {
    143  return InvokeCubebWithLog(cubeb_stream_set_input_processing_params, aParams);
    144 }
    145 
    146 int CubebInputStream::Latency(uint32_t* aLatencyFrames) {
    147  return InvokeCubebWithLog(cubeb_stream_get_input_latency, aLatencyFrames);
    148 }
    149 
    150 template <typename Function, typename... Args>
    151 int CubebInputStream::InvokeCubeb(Function aFunction, Args&&... aArgs) {
    152  MOZ_ASSERT(mStream);
    153  return aFunction(mStream.get(), std::forward<Args>(aArgs)...);
    154 }
    155 
    156 /* static */
    157 long CubebInputStream::DataCallback_s(cubeb_stream* aStream, void* aUser,
    158                                      const void* aInputBuffer,
    159                                      void* aOutputBuffer, long aFrames) {
    160  MOZ_ASSERT(aUser);
    161  MOZ_ASSERT(aInputBuffer);
    162  MOZ_ASSERT(!aOutputBuffer);
    163  return static_cast<Listener*>(aUser)->DataCallback(aInputBuffer, aFrames);
    164 }
    165 
    166 /* static */
    167 void CubebInputStream::StateCallback_s(cubeb_stream* aStream, void* aUser,
    168                                       cubeb_state aState) {
    169  MOZ_ASSERT(aUser);
    170  static_cast<Listener*>(aUser)->StateCallback(aState);
    171 }
    172 
    173 /* static */
    174 void CubebInputStream::DeviceChangedCallback_s(void* aUser) {
    175  MOZ_ASSERT(aUser);
    176  static_cast<Listener*>(aUser)->DeviceChangedCallback();
    177 }
    178 
    179 #undef LOG_INTERNAL
    180 #undef LOG
    181 #undef LOGE
    182 
    183 }  // namespace mozilla