зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1238038 - Add a base type of MediaTrack for different devices r=padenot
Separate common interfaces that will be used for NonNativeInputTrack class, from NativeInputTrack, into a base class: DeviceInputTrack, where the NonNativeInputTrack will be implemented in the next patch. Differential Revision: https://phabricator.services.mozilla.com/D137782
This commit is contained in:
Родитель
e24a32d029
Коммит
086c0af18e
|
@ -33,7 +33,7 @@ namespace mozilla {
|
|||
# undef TRACK_GRAPH_LOG_INTERNAL
|
||||
#endif // TRACK_GRAPH_LOG_INTERNAL
|
||||
#define TRACK_GRAPH_LOG_INTERNAL(level, msg, ...) \
|
||||
LOG_INTERNAL(level, "(Graph %p, Driver %p) NativeInputTrack %p, " msg, \
|
||||
LOG_INTERNAL(level, "(Graph %p, Driver %p) DeviceInputTrack %p, " msg, \
|
||||
this->mGraph, this->mGraph->CurrentDriver(), this, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
|
@ -50,12 +50,12 @@ namespace mozilla {
|
|||
TRACK_GRAPH_LOG_INTERNAL(Verbose, msg, ##__VA_ARGS__)
|
||||
|
||||
/* static */
|
||||
Result<RefPtr<NativeInputTrack>, nsresult> NativeInputTrack::OpenAudio(
|
||||
Result<RefPtr<DeviceInputTrack>, nsresult> DeviceInputTrack::OpenAudio(
|
||||
MediaTrackGraphImpl* aGraph, CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle, AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<NativeInputTrack> track = aGraph->GetNativeInputTrack();
|
||||
RefPtr<DeviceInputTrack> track = aGraph->GetNativeInputTrack();
|
||||
if (!track) {
|
||||
track =
|
||||
new NativeInputTrack(aGraph->GraphRate(), aDeviceId, aPrincipalHandle);
|
||||
|
@ -77,7 +77,7 @@ Result<RefPtr<NativeInputTrack>, nsresult> NativeInputTrack::OpenAudio(
|
|||
MOZ_ASSERT(track->mDeviceId == aDeviceId);
|
||||
|
||||
track->mUserCount += 1;
|
||||
LOG("NativeInputTrack %p (device %p) in MTG %p has %d users now", track.get(),
|
||||
LOG("DeviceInputTrack %p (device %p) in MTG %p has %d users now", track.get(),
|
||||
track->mDeviceId, aGraph, track->mUserCount);
|
||||
if (track->mUserCount > 1) {
|
||||
track->ReevaluateInputDevice();
|
||||
|
@ -87,7 +87,7 @@ Result<RefPtr<NativeInputTrack>, nsresult> NativeInputTrack::OpenAudio(
|
|||
}
|
||||
|
||||
/* static */
|
||||
void NativeInputTrack::CloseAudio(RefPtr<NativeInputTrack>&& aTrack,
|
||||
void DeviceInputTrack::CloseAudio(RefPtr<DeviceInputTrack>&& aTrack,
|
||||
AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aTrack);
|
||||
|
@ -95,7 +95,7 @@ void NativeInputTrack::CloseAudio(RefPtr<NativeInputTrack>&& aTrack,
|
|||
|
||||
aTrack->RemoveDataListener(aListener);
|
||||
aTrack->mUserCount -= 1;
|
||||
LOG("NativeInputTrack %p (device %p) in MTG %p has %d users now",
|
||||
LOG("DeviceInputTrack %p (device %p) in MTG %p has %d users now",
|
||||
aTrack.get(), aTrack->mDeviceId, aTrack->GraphImpl(), aTrack->mUserCount);
|
||||
if (aTrack->mUserCount == 0) {
|
||||
aTrack->GraphImpl()->CloseAudioInput(aTrack);
|
||||
|
@ -105,16 +105,111 @@ void NativeInputTrack::CloseAudio(RefPtr<NativeInputTrack>&& aTrack,
|
|||
}
|
||||
}
|
||||
|
||||
NativeInputTrack::NativeInputTrack(TrackRate aSampleRate,
|
||||
DeviceInputTrack::DeviceInputTrack(TrackRate aSampleRate,
|
||||
CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle)
|
||||
: ProcessedMediaTrack(aSampleRate, MediaSegment::AUDIO, new AudioSegment()),
|
||||
mDeviceId(aDeviceId),
|
||||
mPrincipalHandle(aPrincipalHandle),
|
||||
mIsBufferingAppended(false),
|
||||
mInputChannels(0),
|
||||
mUserCount(0) {}
|
||||
|
||||
uint32_t DeviceInputTrack::MaxRequestedInputChannels() const {
|
||||
MOZ_ASSERT(mGraph->OnGraphThreadOrNotRunning());
|
||||
uint32_t maxInputChannels = 0;
|
||||
for (const auto& listener : mListeners) {
|
||||
maxInputChannels = std::max(maxInputChannels,
|
||||
listener->RequestedInputChannelCount(mGraph));
|
||||
}
|
||||
return maxInputChannels;
|
||||
}
|
||||
|
||||
bool DeviceInputTrack::HasVoiceInput() const {
|
||||
MOZ_ASSERT(mGraph->OnGraphThreadOrNotRunning());
|
||||
for (const auto& listener : mListeners) {
|
||||
if (listener->IsVoiceInput(mGraph)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceInputTrack::DeviceChanged(MediaTrackGraphImpl* aGraph) const {
|
||||
MOZ_ASSERT(aGraph->OnGraphThreadOrNotRunning());
|
||||
MOZ_ASSERT(aGraph == mGraph,
|
||||
"Receive device changed signal from another graph");
|
||||
TRACK_GRAPH_LOG("DeviceChanged");
|
||||
for (const auto& listener : mListeners) {
|
||||
listener->DeviceChanged(aGraph);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceInputTrack::ReevaluateInputDevice() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
explicit Message(MediaTrackGraphImpl* aGraph)
|
||||
: ControlMessage(nullptr), mGraph(aGraph) {}
|
||||
void Run() override {
|
||||
TRACE("DeviceInputTrack::ReevaluateInputDevice ControlMessage");
|
||||
mGraph->ReevaluateInputDevice();
|
||||
}
|
||||
MediaTrackGraphImpl* mGraph;
|
||||
};
|
||||
mGraph->AppendMessage(MakeUnique<Message>(mGraph));
|
||||
}
|
||||
|
||||
void DeviceInputTrack::AddDataListener(AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(DeviceInputTrack* aInputTrack, AudioDataListener* aListener)
|
||||
: ControlMessage(nullptr),
|
||||
mInputTrack(aInputTrack),
|
||||
mListener(aListener) {}
|
||||
void Run() override {
|
||||
TRACE("DeviceInputTrack::AddDataListener ControlMessage");
|
||||
MOZ_ASSERT(!mInputTrack->mListeners.Contains(mListener.get()),
|
||||
"Don't add a listener twice.");
|
||||
mInputTrack->mListeners.AppendElement(mListener.get());
|
||||
}
|
||||
RefPtr<DeviceInputTrack> mInputTrack;
|
||||
RefPtr<AudioDataListener> mListener;
|
||||
};
|
||||
|
||||
mGraph->AppendMessage(MakeUnique<Message>(this, aListener));
|
||||
}
|
||||
|
||||
void DeviceInputTrack::RemoveDataListener(AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(DeviceInputTrack* aInputTrack, AudioDataListener* aListener)
|
||||
: ControlMessage(nullptr),
|
||||
mInputTrack(aInputTrack),
|
||||
mListener(aListener) {}
|
||||
void Run() override {
|
||||
TRACE("DeviceInputTrack::RemoveDataListener ControlMessage");
|
||||
DebugOnly<bool> wasPresent =
|
||||
mInputTrack->mListeners.RemoveElement(mListener.get());
|
||||
MOZ_ASSERT(wasPresent, "Remove an unknown listener");
|
||||
mListener->Disconnect(mInputTrack->GraphImpl());
|
||||
}
|
||||
RefPtr<DeviceInputTrack> mInputTrack;
|
||||
RefPtr<AudioDataListener> mListener;
|
||||
};
|
||||
|
||||
mGraph->AppendMessage(MakeUnique<Message>(this, aListener));
|
||||
}
|
||||
|
||||
NativeInputTrack::NativeInputTrack(TrackRate aSampleRate,
|
||||
CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle)
|
||||
: DeviceInputTrack(aSampleRate, aDeviceId, aPrincipalHandle),
|
||||
mIsBufferingAppended(false),
|
||||
mInputChannels(0) {}
|
||||
|
||||
void NativeInputTrack::DestroyImpl() {
|
||||
MOZ_ASSERT(mGraph->OnGraphThreadOrNotRunning());
|
||||
mPendingData.Clear();
|
||||
|
@ -126,7 +221,7 @@ void NativeInputTrack::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
|||
MOZ_ASSERT(mGraph->OnGraphThread());
|
||||
TRACE_COMMENT("NativeInputTrack::ProcessInput", "%p", this);
|
||||
|
||||
TRACK_GRAPH_LOGV("ProcessInput from %" PRId64 " to %" PRId64
|
||||
TRACK_GRAPH_LOGV("(Native) ProcessInput from %" PRId64 " to %" PRId64
|
||||
", needs %" PRId64 " frames",
|
||||
aFrom, aTo, aTo - aFrom);
|
||||
|
||||
|
@ -158,7 +253,7 @@ void NativeInputTrack::NotifyInputStopped(MediaTrackGraphImpl* aGraph) {
|
|||
MOZ_ASSERT(aGraph->OnGraphThreadOrNotRunning());
|
||||
MOZ_ASSERT(aGraph == mGraph,
|
||||
"Receive input stopped signal from another graph");
|
||||
TRACK_GRAPH_LOG("NotifyInputStopped");
|
||||
TRACK_GRAPH_LOG("(Native) NotifyInputStopped");
|
||||
mInputChannels = 0;
|
||||
mIsBufferingAppended = false;
|
||||
mPendingData.Clear();
|
||||
|
@ -196,96 +291,6 @@ void NativeInputTrack::NotifyInputData(MediaTrackGraphImpl* aGraph,
|
|||
mPrincipalHandle);
|
||||
}
|
||||
|
||||
void NativeInputTrack::DeviceChanged(MediaTrackGraphImpl* aGraph) {
|
||||
MOZ_ASSERT(aGraph->OnGraphThreadOrNotRunning());
|
||||
MOZ_ASSERT(aGraph == mGraph,
|
||||
"Receive device changed signal from another graph");
|
||||
TRACK_GRAPH_LOG("DeviceChanged");
|
||||
for (auto& listener : mDataUsers) {
|
||||
listener->DeviceChanged(aGraph);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t NativeInputTrack::MaxRequestedInputChannels() const {
|
||||
MOZ_ASSERT(mGraph->OnGraphThreadOrNotRunning());
|
||||
uint32_t maxInputChannels = 0;
|
||||
for (const auto& listener : mDataUsers) {
|
||||
maxInputChannels = std::max(maxInputChannels,
|
||||
listener->RequestedInputChannelCount(mGraph));
|
||||
}
|
||||
return maxInputChannels;
|
||||
}
|
||||
|
||||
bool NativeInputTrack::HasVoiceInput() const {
|
||||
MOZ_ASSERT(mGraph->OnGraphThreadOrNotRunning());
|
||||
for (const auto& listener : mDataUsers) {
|
||||
if (listener->IsVoiceInput(mGraph)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeInputTrack::ReevaluateInputDevice() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
explicit Message(MediaTrackGraphImpl* aGraph)
|
||||
: ControlMessage(nullptr), mGraph(aGraph) {}
|
||||
void Run() override {
|
||||
TRACE("NativeInputTrack::ReevaluateInputDevice ControlMessage");
|
||||
mGraph->ReevaluateInputDevice();
|
||||
}
|
||||
MediaTrackGraphImpl* mGraph;
|
||||
};
|
||||
mGraph->AppendMessage(MakeUnique<Message>(mGraph));
|
||||
}
|
||||
|
||||
void NativeInputTrack::AddDataListener(AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(NativeInputTrack* aInputTrack, AudioDataListener* aListener)
|
||||
: ControlMessage(nullptr),
|
||||
mInputTrack(aInputTrack),
|
||||
mListener(aListener) {}
|
||||
void Run() override {
|
||||
TRACE("NativeInputTrack::AddDataListener ControlMessage");
|
||||
MOZ_ASSERT(!mInputTrack->mDataUsers.Contains(mListener.get()),
|
||||
"Don't add a listener twice.");
|
||||
mInputTrack->mDataUsers.AppendElement(mListener.get());
|
||||
}
|
||||
RefPtr<NativeInputTrack> mInputTrack;
|
||||
RefPtr<AudioDataListener> mListener;
|
||||
};
|
||||
|
||||
mGraph->AppendMessage(MakeUnique<Message>(this, aListener));
|
||||
}
|
||||
|
||||
void NativeInputTrack::RemoveDataListener(AudioDataListener* aListener) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(NativeInputTrack* aInputTrack, AudioDataListener* aListener)
|
||||
: ControlMessage(nullptr),
|
||||
mInputTrack(aInputTrack),
|
||||
mListener(aListener) {}
|
||||
void Run() override {
|
||||
TRACE("NativeInputTrack::RemoveDataListener ControlMessage");
|
||||
DebugOnly<bool> wasPresent =
|
||||
mInputTrack->mDataUsers.RemoveElement(mListener.get());
|
||||
MOZ_ASSERT(wasPresent, "Remove an unknown listener");
|
||||
mListener->Disconnect(mInputTrack->GraphImpl());
|
||||
}
|
||||
RefPtr<NativeInputTrack> mInputTrack;
|
||||
RefPtr<AudioDataListener> mListener;
|
||||
};
|
||||
|
||||
mGraph->AppendMessage(MakeUnique<Message>(this, aListener));
|
||||
}
|
||||
|
||||
#undef LOG_INTERNAL
|
||||
#undef LOG
|
||||
#undef LOGE
|
||||
|
|
|
@ -12,15 +12,18 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
// MediaTrack subclass storing the raw audio data from microphone.
|
||||
class NativeInputTrack : public ProcessedMediaTrack {
|
||||
class NativeInputTrack;
|
||||
|
||||
class DeviceInputTrack : public ProcessedMediaTrack {
|
||||
public:
|
||||
// Main Thread APIs:
|
||||
// The following two APIs can create and destroy a NativeInputTrack reference
|
||||
// on main thread, then open and close the paired audio device accordingly on
|
||||
// the graph thread. The user who wants to read the audio input from a certain
|
||||
// device should use these APIs to obtain a NativeInputTrack reference and
|
||||
// return the reference when the user no longer needs the audio data.
|
||||
// The following two APIs can create and destroy a DeviceInputTrack reference
|
||||
// on main thread, then open and close the underlying audio device accordingly
|
||||
// on the graph thread. The user who wants to read the audio input from a
|
||||
// certain device should use these APIs to obtain a DeviceInputTrack reference
|
||||
// and release the reference when the user no longer needs the audio data.
|
||||
//
|
||||
// Currently, all the DeviceInputTrack is NativeInputTrack.
|
||||
//
|
||||
// There is only one NativeInputTrack per MediaTrackGraph and it will be
|
||||
// created when the first user who requests the audio data. Once the
|
||||
|
@ -35,82 +38,96 @@ class NativeInputTrack : public ProcessedMediaTrack {
|
|||
//
|
||||
// Example:
|
||||
// // On main thread
|
||||
// RefPtr<NativeInputTrack> track = NativeInputTrack::OpenAudio(...);
|
||||
// RefPtr<DeviceInputTrack> track = DeviceInputTrack::OpenAudio(...);
|
||||
// ...
|
||||
// // On graph thread
|
||||
// AudioSegmen* data = track->GetData<AudioSegment>();
|
||||
// ...
|
||||
// // On main thread
|
||||
// NativeInputTrack::CloseAudio(std::move(track), ...);
|
||||
// DeviceInputTrack::CloseAudio(std::move(track), ...);
|
||||
//
|
||||
// Returns a reference of NativeInputTrack, storing the input audio data from
|
||||
// Returns a reference of DeviceInputTrack, storing the input audio data from
|
||||
// the given device, in the given MediaTrackGraph, if the MediaTrackGraph has
|
||||
// no audio input device, or the given device is the same as the one currently
|
||||
// running in the MediaTrackGraph. Otherwise, return an error. The paired
|
||||
// audio device will be opened accordingly in the successful case. The
|
||||
// NativeInputTrack will access its user's audio settings via the attached
|
||||
// DeviceInputTrack will access its user's audio settings via the attached
|
||||
// AudioDataListener when it needs.
|
||||
static Result<RefPtr<NativeInputTrack>, nsresult> OpenAudio(
|
||||
static Result<RefPtr<DeviceInputTrack>, nsresult> OpenAudio(
|
||||
MediaTrackGraphImpl* aGraph, CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle, AudioDataListener* aListener);
|
||||
// Destroy the NativeInputTrack reference obtained by the above API. The
|
||||
// Destroy the DeviceInputTrack reference obtained by the above API. The
|
||||
// paired audio device will be closed accordingly.
|
||||
static void CloseAudio(RefPtr<NativeInputTrack>&& aTrack,
|
||||
static void CloseAudio(RefPtr<DeviceInputTrack>&& aTrack,
|
||||
AudioDataListener* aListener);
|
||||
|
||||
// Graph Thread APIs, for ProcessedMediaTrack
|
||||
// Graph thread APIs:
|
||||
// Query audio settings from its users.
|
||||
uint32_t MaxRequestedInputChannels() const;
|
||||
bool HasVoiceInput() const;
|
||||
// Deliver notification to its users.
|
||||
void DeviceChanged(MediaTrackGraphImpl* aGraph) const;
|
||||
|
||||
// Any thread:
|
||||
DeviceInputTrack* AsDeviceInputTrack() override { return this; }
|
||||
virtual NativeInputTrack* AsNativeInputTrack() { return nullptr; }
|
||||
|
||||
// Any thread:
|
||||
const CubebUtils::AudioDeviceID mDeviceId;
|
||||
const PrincipalHandle mPrincipalHandle;
|
||||
|
||||
protected:
|
||||
DeviceInputTrack(TrackRate aSampleRate, CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle);
|
||||
~DeviceInputTrack() = default;
|
||||
|
||||
private:
|
||||
// Main thread APIs:
|
||||
void ReevaluateInputDevice();
|
||||
void AddDataListener(AudioDataListener* aListener);
|
||||
void RemoveDataListener(AudioDataListener* aListener);
|
||||
|
||||
// Only accessed on the main thread.
|
||||
// When this becomes zero, this DeviceInputTrack is no longer needed.
|
||||
int32_t mUserCount = 0;
|
||||
|
||||
// Only accessed on the graph thread.
|
||||
nsTArray<RefPtr<AudioDataListener>> mListeners;
|
||||
};
|
||||
|
||||
class NativeInputTrack final : public DeviceInputTrack {
|
||||
public:
|
||||
// Do not call this directly. This can only be called in DeviceInputTrack or
|
||||
// tests.
|
||||
NativeInputTrack(TrackRate aSampleRate, CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle);
|
||||
|
||||
// Graph Thread APIs, for ProcessedMediaTrack.
|
||||
void DestroyImpl() override;
|
||||
void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override;
|
||||
uint32_t NumberOfChannels() const override;
|
||||
|
||||
// Graph thread APIs: Redirect calls from GraphDriver to mDataUsers
|
||||
void DeviceChanged(MediaTrackGraphImpl* aGraph);
|
||||
|
||||
// Graph thread APIs: Get input audio data and event from graph
|
||||
// Graph thread APIs: Get input audio data and event from graph.
|
||||
void NotifyInputStopped(MediaTrackGraphImpl* aGraph);
|
||||
void NotifyInputData(MediaTrackGraphImpl* aGraph,
|
||||
const AudioDataValue* aBuffer, size_t aFrames,
|
||||
TrackRate aRate, uint32_t aChannels,
|
||||
uint32_t aAlreadyBuffered);
|
||||
|
||||
// Graph thread APIs
|
||||
uint32_t MaxRequestedInputChannels() const;
|
||||
bool HasVoiceInput() const;
|
||||
|
||||
// Any thread
|
||||
NativeInputTrack* AsNativeInputTrack() override { return this; }
|
||||
|
||||
// Any thread
|
||||
const CubebUtils::AudioDeviceID mDeviceId;
|
||||
const PrincipalHandle mPrincipalHandle;
|
||||
|
||||
private:
|
||||
NativeInputTrack(TrackRate aSampleRate, CubebUtils::AudioDeviceID aDeviceId,
|
||||
const PrincipalHandle& aPrincipalHandle);
|
||||
~NativeInputTrack() = default;
|
||||
|
||||
// Main thread APIs
|
||||
void ReevaluateInputDevice();
|
||||
void AddDataListener(AudioDataListener* aListener);
|
||||
void RemoveDataListener(AudioDataListener* aListener);
|
||||
|
||||
// Graph thread only members:
|
||||
// Indicate whether we append extra frames in mPendingData. The extra number
|
||||
// of frames is in [0, WEBAUDIO_BLOCK_SIZE] range.
|
||||
bool mIsBufferingAppended;
|
||||
|
||||
// Queue the audio input data coming from NotifyInputData. Used in graph
|
||||
// thread only.
|
||||
bool mIsBufferingAppended = false;
|
||||
// Queue the audio input data coming from NotifyInputData.
|
||||
AudioSegment mPendingData;
|
||||
|
||||
// Only accessed on the graph thread.
|
||||
// The input channel count for the audio data.
|
||||
uint32_t mInputChannels = 0;
|
||||
|
||||
// Only accessed on the main thread.
|
||||
// When this becomes zero, this NativeInputTrack is no longer needed.
|
||||
int32_t mUserCount = 0;
|
||||
|
||||
// Only accessed on the graph thread.
|
||||
nsTArray<RefPtr<AudioDataListener>> mDataUsers;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -682,11 +682,12 @@ void MediaTrackGraphImpl::OpenAudioInputImpl(NativeInputTrack* aTrack) {
|
|||
SwitchAtNextIteration(driver);
|
||||
}
|
||||
|
||||
void MediaTrackGraphImpl::OpenAudioInput(NativeInputTrack* aTrack) {
|
||||
void MediaTrackGraphImpl::OpenAudioInput(DeviceInputTrack* aTrack) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aTrack);
|
||||
MOZ_ASSERT(aTrack->AsNativeInputTrack());
|
||||
|
||||
LOG(LogLevel::Debug, ("%p OpenInput: NativeInputTrack %p for device %p", this,
|
||||
LOG(LogLevel::Debug, ("%p OpenInput: DeviceInputTrack %p for device %p", this,
|
||||
aTrack, aTrack->mDeviceId));
|
||||
|
||||
class Message : public ControlMessage {
|
||||
|
@ -702,10 +703,10 @@ void MediaTrackGraphImpl::OpenAudioInput(NativeInputTrack* aTrack) {
|
|||
};
|
||||
|
||||
MOZ_ASSERT(!mNativeInputTrackOnMain);
|
||||
mNativeInputTrackOnMain = aTrack;
|
||||
mNativeInputTrackOnMain = aTrack->AsNativeInputTrack();
|
||||
|
||||
// XXX Check not destroyed!
|
||||
this->AppendMessage(MakeUnique<Message>(this, aTrack));
|
||||
this->AppendMessage(MakeUnique<Message>(this, aTrack->AsNativeInputTrack()));
|
||||
}
|
||||
|
||||
void MediaTrackGraphImpl::CloseAudioInputImpl(CubebUtils::AudioDeviceID aID) {
|
||||
|
@ -782,8 +783,11 @@ void MediaTrackGraphImpl::UnregisterAudioOutput(MediaTrack* aTrack,
|
|||
});
|
||||
}
|
||||
|
||||
void MediaTrackGraphImpl::CloseAudioInput(NativeInputTrack* aTrack) {
|
||||
void MediaTrackGraphImpl::CloseAudioInput(DeviceInputTrack* aTrack) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aTrack);
|
||||
MOZ_ASSERT(aTrack->AsNativeInputTrack());
|
||||
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
Message(MediaTrackGraphImpl* aGraph, CubebUtils::AudioDeviceID aID)
|
||||
|
|
|
@ -97,7 +97,7 @@ class MediaTrack;
|
|||
class MediaTrackGraph;
|
||||
class MediaTrackGraphImpl;
|
||||
class MediaTrackListener;
|
||||
class NativeInputTrack;
|
||||
class DeviceInputTrack;
|
||||
class ProcessedMediaTrack;
|
||||
class SourceMediaTrack;
|
||||
|
||||
|
@ -359,7 +359,7 @@ class MediaTrack : public mozilla::LinkedListElement<MediaTrack> {
|
|||
virtual ForwardedInputTrack* AsForwardedInputTrack() { return nullptr; }
|
||||
virtual CrossGraphTransmitter* AsCrossGraphTransmitter() { return nullptr; }
|
||||
virtual CrossGraphReceiver* AsCrossGraphReceiver() { return nullptr; }
|
||||
virtual NativeInputTrack* AsNativeInputTrack() { return nullptr; }
|
||||
virtual DeviceInputTrack* AsDeviceInputTrack() { return nullptr; }
|
||||
|
||||
// These Impl methods perform the core functionality of the control methods
|
||||
// above, on the media graph thread.
|
||||
|
@ -1031,8 +1031,8 @@ class MediaTrackGraph {
|
|||
// Idempotent
|
||||
void ForceShutDown();
|
||||
|
||||
virtual void OpenAudioInput(NativeInputTrack* aTrack) = 0;
|
||||
virtual void CloseAudioInput(NativeInputTrack* aTrack) = 0;
|
||||
virtual void OpenAudioInput(DeviceInputTrack* aTrack) = 0;
|
||||
virtual void CloseAudioInput(DeviceInputTrack* aTrack) = 0;
|
||||
|
||||
// Control API.
|
||||
/**
|
||||
|
|
|
@ -411,7 +411,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
void OpenAudioInputImpl(NativeInputTrack* aTrack);
|
||||
/* Called on the main thread when something requests audio from an input
|
||||
* audio device aID. */
|
||||
virtual void OpenAudioInput(NativeInputTrack* aTrack) override;
|
||||
virtual void OpenAudioInput(DeviceInputTrack* aTrack) override;
|
||||
|
||||
/* Runs off a message on the graph when input audio from aID is not needed
|
||||
* anymore, for a particular track. It can be that other tracks still need
|
||||
|
@ -420,7 +420,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
/* Called on the main thread when input audio from aID is not needed
|
||||
* anymore, for a particular track. It can be that other tracks still need
|
||||
* audio from this audio input device. */
|
||||
virtual void CloseAudioInput(NativeInputTrack* aTrack) override;
|
||||
virtual void CloseAudioInput(DeviceInputTrack* aTrack) override;
|
||||
|
||||
/* Add or remove an audio output for this track. All tracks that have an
|
||||
* audio output are mixed and written to a single audio output stream. */
|
||||
|
|
|
@ -84,10 +84,12 @@ TEST_F(TestDeviceInputTrack, NativeInputTrackData) {
|
|||
const PrincipalHandle testPrincipal =
|
||||
MakePrincipalHandle(nsContentUtils::GetSystemPrincipal());
|
||||
|
||||
auto r = NativeInputTrack::OpenAudio(mGraph.get(), deviceId, testPrincipal,
|
||||
nullptr);
|
||||
ASSERT_TRUE(r.isOk());
|
||||
RefPtr<NativeInputTrack> track = r.unwrap();
|
||||
// Setup: Create a NativeInputTrack and add it to mGraph
|
||||
RefPtr<NativeInputTrack> track =
|
||||
new NativeInputTrack(mGraph->GraphRate(), deviceId, testPrincipal);
|
||||
mGraph->AddTrack(track);
|
||||
|
||||
// Main test below:
|
||||
|
||||
generator.GenerateInterleaved(buffer.Elements(), nrFrames);
|
||||
track->NotifyInputData(mGraph.get(), buffer.Elements(), nrFrames, mRate,
|
||||
|
@ -123,7 +125,9 @@ TEST_F(TestDeviceInputTrack, NativeInputTrackData) {
|
|||
EXPECT_EQ(chunk.mPrincipalHandle, testPrincipal);
|
||||
}
|
||||
|
||||
NativeInputTrack::CloseAudio(std::move(track), nullptr);
|
||||
// Tear down: Destroy the NativeInputTrack and remove it from mGraph.
|
||||
track->Destroy();
|
||||
mGraph->RemoveTrackGraphThread(track);
|
||||
}
|
||||
|
||||
TEST_F(TestDeviceInputTrack, OpenTwiceWithoutCloseFirst) {
|
||||
|
@ -136,7 +140,8 @@ TEST_F(TestDeviceInputTrack, OpenTwiceWithoutCloseFirst) {
|
|||
auto r1 = NativeInputTrack::OpenAudio(mGraph.get(), deviceId1, testPrincipal,
|
||||
nullptr);
|
||||
ASSERT_TRUE(r1.isOk());
|
||||
RefPtr<NativeInputTrack> track1 = r1.unwrap();
|
||||
RefPtr<NativeInputTrack> track1 = r1.unwrap()->AsNativeInputTrack();
|
||||
ASSERT_TRUE(track1);
|
||||
|
||||
auto r2 = NativeInputTrack::OpenAudio(mGraph.get(), deviceId2, testPrincipal,
|
||||
nullptr);
|
||||
|
|
|
@ -1332,12 +1332,13 @@ nsresult AudioProcessingTrack::ConnectDeviceInput(
|
|||
mInputListener = aListener;
|
||||
mDeviceId.emplace(aId);
|
||||
|
||||
auto r = NativeInputTrack::OpenAudio(GraphImpl(), aId, aPrincipal,
|
||||
auto r = DeviceInputTrack::OpenAudio(GraphImpl(), aId, aPrincipal,
|
||||
mInputListener.get());
|
||||
if (r.isErr()) {
|
||||
NS_WARNING("Failed to open audio device.");
|
||||
return r.unwrapErr();
|
||||
}
|
||||
|
||||
mDeviceInputTrack = r.unwrap();
|
||||
MOZ_ASSERT(mDeviceInputTrack);
|
||||
LOG("Open device %p (InputTrack=%p) for Mic source %p", aId,
|
||||
|
@ -1354,10 +1355,11 @@ void AudioProcessingTrack::DisconnectDeviceInput() {
|
|||
}
|
||||
MOZ_ASSERT(mPort);
|
||||
MOZ_ASSERT(mDeviceId.isSome());
|
||||
MOZ_ASSERT(mDeviceInputTrack);
|
||||
LOG("Close device %p (InputTrack=%p) for Mic source %p ", *mDeviceId,
|
||||
mDeviceInputTrack.get(), this);
|
||||
mPort->Destroy();
|
||||
NativeInputTrack::CloseAudio(std::move(mDeviceInputTrack),
|
||||
DeviceInputTrack::CloseAudio(std::move(mDeviceInputTrack),
|
||||
mInputListener.get());
|
||||
mInputListener = nullptr;
|
||||
mDeviceId = Nothing();
|
||||
|
|
|
@ -228,7 +228,7 @@ class AudioProcessingTrack : public ProcessedMediaTrack {
|
|||
|
||||
// Only accessed on the main thread. This is the track producing raw audio
|
||||
// input data. Graph thread should MediaInputPort::GetSource() to get this
|
||||
RefPtr<NativeInputTrack> mDeviceInputTrack;
|
||||
RefPtr<DeviceInputTrack> mDeviceInputTrack;
|
||||
|
||||
// Only accessed on the main thread. Used for bookkeeping on main thread, such
|
||||
// that DisconnectDeviceInput can be idempotent.
|
||||
|
|
Загрузка…
Ссылка в новой задаче