summaryrefslogtreecommitdiffstats
path: root/dom/media/gtest/MockCubeb.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/gtest/MockCubeb.h')
-rw-r--r--dom/media/gtest/MockCubeb.h184
1 files changed, 129 insertions, 55 deletions
diff --git a/dom/media/gtest/MockCubeb.h b/dom/media/gtest/MockCubeb.h
index ed6342a779..15689a4a4e 100644
--- a/dom/media/gtest/MockCubeb.h
+++ b/dom/media/gtest/MockCubeb.h
@@ -11,12 +11,15 @@
#include "MediaEventSource.h"
#include "mozilla/DataMutex.h"
#include "mozilla/MozPromise.h"
+#include "mozilla/Result.h"
+#include "mozilla/ResultVariant.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "nsTArray.h"
#include <thread>
#include <atomic>
#include <chrono>
+#include <utility>
namespace mozilla {
const uint32_t MAX_OUTPUT_CHANNELS = 2;
@@ -68,6 +71,8 @@ struct cubeb_ops {
// Keep those and the struct definition in sync with cubeb.h and
// cubeb-internal.h
void cubeb_mock_destroy(cubeb* context);
+static int cubeb_mock_get_supported_input_processing_params(
+ cubeb* context, cubeb_input_processing_params* params);
static int cubeb_mock_enumerate_devices(cubeb* context, cubeb_device_type type,
cubeb_device_collection* out);
@@ -101,6 +106,9 @@ static int cubeb_mock_stream_set_volume(cubeb_stream* stream, float volume);
static int cubeb_mock_stream_set_name(cubeb_stream* stream,
char const* stream_name);
+static int cubeb_mock_stream_set_input_processing_params(
+ cubeb_stream* stream, cubeb_input_processing_params);
+
static int cubeb_mock_stream_register_device_changed_callback(
cubeb_stream* stream,
cubeb_device_changed_callback device_changed_callback);
@@ -122,7 +130,7 @@ cubeb_ops const mock_ops = {
/*.get_min_latency =*/cubeb_mock_get_min_latency,
/*.get_preferred_sample_rate =*/cubeb_mock_get_preferred_sample_rate,
/*.get_supported_input_processing_params =*/
- NULL,
+ cubeb_mock_get_supported_input_processing_params,
/*.enumerate_devices =*/cubeb_mock_enumerate_devices,
/*.device_collection_destroy =*/cubeb_mock_device_collection_destroy,
/*.destroy =*/cubeb_mock_destroy,
@@ -139,7 +147,7 @@ cubeb_ops const mock_ops = {
/*.stream_set_input_mute =*/NULL,
/*.stream_set_input_processing_params =*/
- NULL,
+ cubeb_mock_stream_set_input_processing_params,
/*.stream_device_destroy =*/NULL,
/*.stream_register_device_changed_callback =*/
cubeb_mock_stream_register_device_changed_callback,
@@ -160,7 +168,7 @@ class MockCubebStream {
void* mUserPtr;
public:
- enum class KeepProcessing { No, Yes };
+ enum class KeepProcessing { No, Yes, InvalidState };
enum class RunningMode { Automatic, Manual };
MockCubebStream(cubeb* aContext, char const* aStreamName,
@@ -175,50 +183,56 @@ class MockCubebStream {
~MockCubebStream();
- int Start();
- int Stop();
- uint64_t Position();
- void Destroy();
- int SetName(char const* aName);
+ int Start() MOZ_EXCLUDES(mMutex);
+ int Stop() MOZ_EXCLUDES(mMutex);
+ uint64_t Position() MOZ_EXCLUDES(mMutex);
+ void Destroy() MOZ_EXCLUDES(mMutex);
+ int SetName(char const* aName) MOZ_EXCLUDES(mMutex);
int RegisterDeviceChangedCallback(
- cubeb_device_changed_callback aDeviceChangedCallback);
+ cubeb_device_changed_callback aDeviceChangedCallback)
+ MOZ_EXCLUDES(mMutex);
+ int SetInputProcessingParams(cubeb_input_processing_params aParams);
- cubeb_stream* AsCubebStream();
+ cubeb_stream* AsCubebStream() MOZ_EXCLUDES(mMutex);
static MockCubebStream* AsMock(cubeb_stream* aStream);
- char const* StreamName() const { return mName.get(); }
+ char const* StreamName() const MOZ_EXCLUDES(mMutex) {
+ MutexAutoLock l(mMutex);
+ return mName.get();
+ }
cubeb_devid GetInputDeviceID() const;
cubeb_devid GetOutputDeviceID() const;
- uint32_t InputChannels() const;
- uint32_t OutputChannels() const;
- uint32_t SampleRate() const;
- uint32_t InputFrequency() const;
+ uint32_t InputChannels() const MOZ_EXCLUDES(mMutex);
+ uint32_t OutputChannels() const MOZ_EXCLUDES(mMutex);
+ uint32_t SampleRate() const MOZ_EXCLUDES(mMutex);
+ uint32_t InputFrequency() const MOZ_EXCLUDES(mMutex);
+ Maybe<cubeb_state> State() const MOZ_EXCLUDES(mMutex);
- void SetDriftFactor(float aDriftFactor);
- void ForceError();
- void ForceDeviceChanged();
- void Thaw();
+ void SetDriftFactor(float aDriftFactor) MOZ_EXCLUDES(mMutex);
+ void ForceError() MOZ_EXCLUDES(mMutex);
+ void ForceDeviceChanged() MOZ_EXCLUDES(mMutex);
+ void Thaw() MOZ_EXCLUDES(mMutex);
// For RunningMode::Manual, drive this MockCubebStream forward.
- KeepProcessing ManualDataCallback(long aNrFrames);
+ KeepProcessing ManualDataCallback(long aNrFrames) MOZ_EXCLUDES(mMutex);
// For RunningMode::Manual, notify the client of a DeviceChanged event
// synchronously.
- void NotifyDeviceChangedNow();
+ void NotifyDeviceChangedNow() MOZ_EXCLUDES(mMutex);
// Enable input recording for this driver. This is best called before
// the thread is running, but is safe to call whenever.
- void SetOutputRecordingEnabled(bool aEnabled);
+ void SetOutputRecordingEnabled(bool aEnabled) MOZ_EXCLUDES(mMutex);
// Enable input recording for this driver. This is best called before
// the thread is running, but is safe to call whenever.
- void SetInputRecordingEnabled(bool aEnabled);
+ void SetInputRecordingEnabled(bool aEnabled) MOZ_EXCLUDES(mMutex);
// Get the recorded output from this stream. This doesn't copy, and therefore
// only works once.
- nsTArray<AudioDataValue>&& TakeRecordedOutput();
+ nsTArray<AudioDataValue>&& TakeRecordedOutput() MOZ_EXCLUDES(mMutex);
// Get the recorded input from this stream. This doesn't copy, and therefore
// only works once.
- nsTArray<AudioDataValue>&& TakeRecordedInput();
+ nsTArray<AudioDataValue>&& TakeRecordedInput() MOZ_EXCLUDES(mMutex);
MediaEventSource<nsCString>& NameSetEvent();
MediaEventSource<cubeb_state>& StateEvent();
@@ -232,7 +246,13 @@ class MockCubebStream {
MediaEventSource<void>& DeviceChangeForcedEvent();
private:
- KeepProcessing Process(long aNrFrames);
+ cubeb_stream* AsCubebStreamLocked() MOZ_REQUIRES(mMutex);
+ static MockCubebStream* AsMockLocked(cubeb_stream* aStream);
+ uint32_t InputChannelsLocked() const MOZ_REQUIRES(mMutex);
+ uint32_t OutputChannelsLocked() const MOZ_REQUIRES(mMutex);
+ uint32_t SampleRateLocked() const MOZ_REQUIRES(mMutex);
+ uint32_t InputFrequencyLocked() const MOZ_REQUIRES(mMutex);
+ KeepProcessing Process(long aNrFrames) MOZ_REQUIRES(mMutex);
KeepProcessing Process10Ms();
public:
@@ -242,52 +262,58 @@ class MockCubebStream {
SmartMockCubebStream* const mSelf;
private:
- void NotifyState(cubeb_state aState);
- void NotifyDeviceChanged();
+ void NotifyState(cubeb_state aState) MOZ_REQUIRES(mMutex);
+ void NotifyDeviceChanged() MOZ_EXCLUDES(mMutex);
static constexpr long kMaxNrFrames = 1920;
+ // Mutex guarding most members to ensure state is in sync.
+ mutable Mutex mMutex{"MockCubebStream::mMutex"};
// Monitor used to block start until mFrozenStart is false.
- Monitor mFrozenStartMonitor MOZ_UNANNOTATED;
+ Monitor mFrozenStartMonitor MOZ_ACQUIRED_BEFORE(mMutex);
// Whether this stream should wait for an explicit start request before
- // starting. Protected by FrozenStartMonitor.
- bool mFrozenStart;
+ // starting.
+ bool mFrozenStart MOZ_GUARDED_BY(mFrozenStartMonitor);
+ // The stream's most recently issued state change, if any has occurred.
// Used to abort a frozen start if cubeb_stream_start() is called currently
// with a blocked cubeb_stream_start() call.
- std::atomic_bool mStreamStop{true};
+ Maybe<cubeb_state> mState MOZ_GUARDED_BY(mMutex);
// Whether or not the output-side of this stream (what is written from the
// callback output buffer) is recorded in an internal buffer. The data is then
// available via `GetRecordedOutput`.
- std::atomic_bool mOutputRecordingEnabled{false};
+ bool mOutputRecordingEnabled MOZ_GUARDED_BY(mMutex) = false;
// Whether or not the input-side of this stream (what is written from the
// callback input buffer) is recorded in an internal buffer. The data is then
// available via `TakeRecordedInput`.
- std::atomic_bool mInputRecordingEnabled{false};
+ bool mInputRecordingEnabled MOZ_GUARDED_BY(mMutex) = false;
// The audio buffer used on data callback.
- AudioDataValue mOutputBuffer[MAX_OUTPUT_CHANNELS * kMaxNrFrames] = {};
- AudioDataValue mInputBuffer[MAX_INPUT_CHANNELS * kMaxNrFrames] = {};
+ AudioDataValue mOutputBuffer[MAX_OUTPUT_CHANNELS *
+ kMaxNrFrames] MOZ_GUARDED_BY(mMutex) = {};
+ AudioDataValue mInputBuffer[MAX_INPUT_CHANNELS * kMaxNrFrames] MOZ_GUARDED_BY(
+ mMutex) = {};
// The audio callback
- cubeb_data_callback mDataCallback = nullptr;
+ const cubeb_data_callback mDataCallback = nullptr;
// The stream state callback
- cubeb_state_callback mStateCallback = nullptr;
+ const cubeb_state_callback mStateCallback = nullptr;
// The device changed callback
- cubeb_device_changed_callback mDeviceChangedCallback = nullptr;
+ cubeb_device_changed_callback mDeviceChangedCallback MOZ_GUARDED_BY(mMutex) =
+ nullptr;
// A name for this stream
- nsCString mName;
+ nsCString mName MOZ_GUARDED_BY(mMutex);
// The stream params
- cubeb_stream_params mOutputParams = {};
- cubeb_stream_params mInputParams = {};
+ cubeb_stream_params mOutputParams MOZ_GUARDED_BY(mMutex) = {};
+ cubeb_stream_params mInputParams MOZ_GUARDED_BY(mMutex) = {};
/* Device IDs */
- cubeb_devid mInputDeviceID;
- cubeb_devid mOutputDeviceID;
-
- std::atomic<float> mDriftFactor{1.0};
- std::atomic_bool mFastMode{false};
- std::atomic_bool mForceErrorState{false};
- std::atomic_bool mForceDeviceChanged{false};
- std::atomic_bool mDestroyed{false};
- std::atomic<uint64_t> mPosition{0};
- AudioGenerator<AudioDataValue> mAudioGenerator;
- AudioVerifier<AudioDataValue> mAudioVerifier;
+ const cubeb_devid mInputDeviceID;
+ const cubeb_devid mOutputDeviceID;
+
+ float mDriftFactor MOZ_GUARDED_BY(mMutex) = 1.0;
+ bool mFastMode MOZ_GUARDED_BY(mMutex) = false;
+ bool mForceErrorState MOZ_GUARDED_BY(mMutex) = false;
+ bool mForceDeviceChanged MOZ_GUARDED_BY(mMutex) = false;
+ bool mDestroyed MOZ_GUARDED_BY(mMutex) = false;
+ uint64_t mPosition MOZ_GUARDED_BY(mMutex) = 0;
+ AudioGenerator<AudioDataValue> mAudioGenerator MOZ_GUARDED_BY(mMutex);
+ AudioVerifier<AudioDataValue> mAudioVerifier MOZ_GUARDED_BY(mMutex);
MediaEventProducer<nsCString> mNameSetEvent;
MediaEventProducer<cubeb_state> mStateEvent;
@@ -299,12 +325,29 @@ class MockCubebStream {
MediaEventProducer<void> mDeviceChangedForcedEvent;
// The recorded data, copied from the output_buffer of the callback.
// Interleaved.
- nsTArray<AudioDataValue> mRecordedOutput;
+ nsTArray<AudioDataValue> mRecordedOutput MOZ_GUARDED_BY(mMutex);
// The recorded data, copied from the input buffer of the callback.
// Interleaved.
- nsTArray<AudioDataValue> mRecordedInput;
+ nsTArray<AudioDataValue> mRecordedInput MOZ_GUARDED_BY(mMutex);
};
+inline std::ostream& operator<<(std::ostream& aStream,
+ const MockCubebStream::KeepProcessing& aVal) {
+ switch (aVal) {
+ case MockCubebStream::KeepProcessing::Yes:
+ aStream << "KeepProcessing::Yes";
+ return aStream;
+ case MockCubebStream::KeepProcessing::No:
+ aStream << "KeepProcessing::No";
+ return aStream;
+ case MockCubebStream::KeepProcessing::InvalidState:
+ aStream << "KeepProcessing::InvalidState";
+ return aStream;
+ }
+ aStream << "KeepProcessing(invalid " << static_cast<uint32_t>(aVal) << ")";
+ return aStream;
+}
+
class SmartMockCubebStream
: public MockCubebStream,
public SupportsThreadSafeWeakPtr<SmartMockCubebStream> {
@@ -362,6 +405,16 @@ class MockCubeb {
cubeb_device_type aDevType,
cubeb_device_collection_changed_callback aCallback, void* aUserPtr);
+ Result<cubeb_input_processing_params, int> SupportedInputProcessingParams()
+ const;
+ void SetSupportedInputProcessingParams(cubeb_input_processing_params aParams,
+ int aRv);
+ // Set the rv to be returned when SetInputProcessingParams for any stream of
+ // this context would apply the params to the stream, i.e. after passing the
+ // supported-params check.
+ void SetInputProcessingApplyRv(int aRv);
+ int InputProcessingApplyRv() const;
+
// Control API
// Add an input or output device to this backend. This calls the device
@@ -455,6 +508,10 @@ class MockCubeb {
// notification via a system callback. If not, Gecko is expected to re-query
// the list every time.
bool mSupportsDeviceCollectionChangedCallback = true;
+ std::pair<cubeb_input_processing_params, int>
+ mSupportedInputProcessingParams = std::make_pair(
+ CUBEB_INPUT_PROCESSING_PARAM_NONE, CUBEB_ERROR_NOT_SUPPORTED);
+ int mInputProcessingParamsApplyRv = CUBEB_OK;
const RunningMode mRunningMode;
Atomic<bool> mStreamInitErrorState;
// Whether new MockCubebStreams should be frozen on start.
@@ -502,6 +559,18 @@ int cubeb_mock_register_device_collection_changed(
devtype, callback, user_ptr);
}
+int cubeb_mock_get_supported_input_processing_params(
+ cubeb* context, cubeb_input_processing_params* params) {
+ Result<cubeb_input_processing_params, int> res =
+ MockCubeb::AsMock(context)->SupportedInputProcessingParams();
+ if (res.isErr()) {
+ *params = CUBEB_INPUT_PROCESSING_PARAM_NONE;
+ return res.unwrapErr();
+ }
+ *params = res.unwrap();
+ return CUBEB_OK;
+}
+
int cubeb_mock_stream_init(
cubeb* context, cubeb_stream** stream, char const* stream_name,
cubeb_devid input_device, cubeb_stream_params* input_stream_params,
@@ -562,6 +631,11 @@ int cubeb_mock_stream_register_device_changed_callback(
device_changed_callback);
}
+static int cubeb_mock_stream_set_input_processing_params(
+ cubeb_stream* stream, cubeb_input_processing_params params) {
+ return MockCubebStream::AsMock(stream)->SetInputProcessingParams(params);
+}
+
int cubeb_mock_get_min_latency(cubeb* context, cubeb_stream_params params,
uint32_t* latency_ms) {
*latency_ms = 10;