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/. */
7 #include "CubebInputStream.h"
9 #include "AudioSampleFormat.h"
10 #include "mozilla/Logging.h"
14 extern mozilla::LazyLogModule gMediaTrackGraphLog
;
18 #endif // LOG_INTERNAL
19 #define LOG_INTERNAL(level, msg, ...) \
20 MOZ_LOG(gMediaTrackGraphLog, LogLevel::level, (msg, ##__VA_ARGS__))
25 #define LOG(msg, ...) LOG_INTERNAL(Debug, msg, ##__VA_ARGS__)
30 #define LOGE(msg, ...) LOG_INTERNAL(Error, msg, ##__VA_ARGS__)
32 #define InvokeCubebWithLog(func, ...) \
35 _retval = InvokeCubeb(func, ##__VA_ARGS__); \
36 if (_retval == CUBEB_OK) { \
37 LOG("CubebInputStream %p: %s for stream %p was successful", this, #func, \
40 LOGE("CubebInputStream %p: %s for stream %p was failed. Error %d", this, \
41 #func, mStream.get(), _retval); \
46 static cubeb_stream_params
CreateStreamInitParams(uint32_t aChannels
,
49 cubeb_stream_params params
;
50 params
.format
= CubebUtils::ToCubebFormat
<AUDIO_OUTPUT_FORMAT
>::value
;
52 params
.channels
= aChannels
;
53 params
.layout
= CUBEB_LAYOUT_UNDEFINED
;
54 params
.prefs
= CubebUtils::GetDefaultStreamPrefs(CUBEB_DEVICE_TYPE_INPUT
);
57 params
.prefs
|= static_cast<cubeb_stream_prefs
>(CUBEB_STREAM_PREF_VOICE
);
63 void CubebInputStream::CubebDestroyPolicy::operator()(
64 cubeb_stream
* aStream
) const {
65 int r
= cubeb_stream_register_device_changed_callback(aStream
, nullptr);
67 LOG("Unregister device changed callback for %p successfully", aStream
);
69 LOGE("Fail to unregister device changed callback for %p. Error %d", aStream
,
72 cubeb_stream_destroy(aStream
);
76 UniquePtr
<CubebInputStream
> CubebInputStream::Create(cubeb_devid aDeviceId
,
80 Listener
* aListener
) {
82 LOGE("No available listener");
86 cubeb
* context
= CubebUtils::GetCubebContext();
88 LOGE("No valid cubeb context");
89 CubebUtils::ReportCubebStreamInitFailure(CubebUtils::GetFirstStream());
93 cubeb_stream_params params
=
94 CreateStreamInitParams(aChannels
, aRate
, aIsVoice
);
95 uint32_t latencyFrames
= CubebUtils::GetCubebMTGLatencyInFrames(¶ms
);
97 cubeb_stream
* cubebStream
= nullptr;
99 RefPtr
<Listener
> listener(aListener
);
100 if (int r
= CubebUtils::CubebStreamInit(
101 context
, &cubebStream
, "input-only stream", aDeviceId
, ¶ms
,
102 nullptr, nullptr, latencyFrames
, DataCallback_s
, StateCallback_s
,
105 CubebUtils::ReportCubebStreamInitFailure(CubebUtils::GetFirstStream());
106 LOGE("Fail to create a cubeb stream. Error %d", r
);
110 UniquePtr
<cubeb_stream
, CubebDestroyPolicy
> inputStream(cubebStream
);
112 LOG("Create a cubeb stream %p successfully", inputStream
.get());
114 UniquePtr
<CubebInputStream
> stream(
115 new CubebInputStream(listener
.forget(), std::move(inputStream
)));
120 CubebInputStream::CubebInputStream(
121 already_AddRefed
<Listener
>&& aListener
,
122 UniquePtr
<cubeb_stream
, CubebDestroyPolicy
>&& aStream
)
123 : mListener(aListener
), mStream(std::move(aStream
)) {
124 MOZ_ASSERT(mListener
);
128 void CubebInputStream::Init() {
129 // cubeb_stream_register_device_changed_callback is only supported on macOS
130 // platform and MockCubebfor now.
131 InvokeCubebWithLog(cubeb_stream_register_device_changed_callback
,
132 CubebInputStream::DeviceChangedCallback_s
);
135 int CubebInputStream::Start() { return InvokeCubebWithLog(cubeb_stream_start
); }
137 int CubebInputStream::Stop() { return InvokeCubebWithLog(cubeb_stream_stop
); }
139 int CubebInputStream::Latency(uint32_t* aLatencyFrames
) {
140 return InvokeCubebWithLog(cubeb_stream_get_input_latency
, aLatencyFrames
);
143 template <typename Function
, typename
... Args
>
144 int CubebInputStream::InvokeCubeb(Function aFunction
, Args
&&... aArgs
) {
146 return aFunction(mStream
.get(), std::forward
<Args
>(aArgs
)...);
150 long CubebInputStream::DataCallback_s(cubeb_stream
* aStream
, void* aUser
,
151 const void* aInputBuffer
,
152 void* aOutputBuffer
, long aFrames
) {
154 MOZ_ASSERT(aInputBuffer
);
155 MOZ_ASSERT(!aOutputBuffer
);
156 return static_cast<Listener
*>(aUser
)->DataCallback(aInputBuffer
, aFrames
);
160 void CubebInputStream::StateCallback_s(cubeb_stream
* aStream
, void* aUser
,
161 cubeb_state aState
) {
163 static_cast<Listener
*>(aUser
)->StateCallback(aState
);
167 void CubebInputStream::DeviceChangedCallback_s(void* aUser
) {
169 static_cast<Listener
*>(aUser
)->DeviceChangedCallback();
176 } // namespace mozilla