зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1221587: Base update of the MSG API for full-duplex r=padenot
--HG-- extra : commitid : Kf1JpZKH7LH
This commit is contained in:
Родитель
3121c632b9
Коммит
6d7d97d7bc
|
@ -885,6 +885,23 @@ AudioCallbackDriver::DataCallback(AudioDataValue* aBuffer, long aFrames)
|
||||||
|
|
||||||
mBuffer.BufferFilled();
|
mBuffer.BufferFilled();
|
||||||
|
|
||||||
|
// Callback any observers for the AEC speaker data. Note that one
|
||||||
|
// (maybe) of these will be full-duplex, the others will get their input
|
||||||
|
// data off separate cubeb callbacks. Take care with how stuff is
|
||||||
|
// removed/added to this list and TSAN issues, but input and output will
|
||||||
|
// use separate callback methods.
|
||||||
|
mGraphImpl->NotifySpeakerData(aOutputBuffer, static_cast<size_t>(aFrames),
|
||||||
|
ChannelCount);
|
||||||
|
|
||||||
|
// Process mic data if any/needed -- after inserting far-end data for AEC!
|
||||||
|
if (aInputBuffer) {
|
||||||
|
if (mAudioInput) { // for this specific input-only or full-duplex stream
|
||||||
|
mAudioInput->NotifyInputData(mGraphImpl, aInputBuffer,
|
||||||
|
static_cast<size_t>(aFrames),
|
||||||
|
ChannelCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool switching = false;
|
bool switching = false;
|
||||||
{
|
{
|
||||||
MonitorAutoLock mon(mGraphImpl->GetMonitor());
|
MonitorAutoLock mon(mGraphImpl->GetMonitor());
|
||||||
|
|
|
@ -196,6 +196,16 @@ public:
|
||||||
|
|
||||||
virtual bool OnThread() = 0;
|
virtual bool OnThread() = 0;
|
||||||
|
|
||||||
|
// XXX Thread-safety! Do these via commands to avoid TSAN issues
|
||||||
|
// and crashes!!!
|
||||||
|
virtual void SetInputListener(MediaStreamListener *aListener) {
|
||||||
|
mAudioInput = aListener;
|
||||||
|
}
|
||||||
|
// XXX do we need the param? probably no
|
||||||
|
virtual void RemoveInputListener(MediaStreamListener *aListener) {
|
||||||
|
mAudioInput = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GraphTime StateComputedTime() const;
|
GraphTime StateComputedTime() const;
|
||||||
|
|
||||||
|
@ -226,6 +236,9 @@ protected:
|
||||||
// This must be access with the monitor.
|
// This must be access with the monitor.
|
||||||
WaitState mWaitState;
|
WaitState mWaitState;
|
||||||
|
|
||||||
|
// Callback for mic data, if any
|
||||||
|
RefPtr<MediaStreamListener> mAudioInput;
|
||||||
|
|
||||||
// This is used on the main thread (during initialization), and the graph
|
// This is used on the main thread (during initialization), and the graph
|
||||||
// thread. No monitor needed because we know the graph thread does not run
|
// thread. No monitor needed because we know the graph thread does not run
|
||||||
// during the initialization.
|
// during the initialization.
|
||||||
|
@ -488,6 +501,8 @@ private:
|
||||||
* This is synchronized by the Graph's monitor.
|
* This is synchronized by the Graph's monitor.
|
||||||
* */
|
* */
|
||||||
bool mStarted;
|
bool mStarted;
|
||||||
|
/* Listener for mic input, if any. */
|
||||||
|
RefPtr<MediaStreamListener> mAudioInput;
|
||||||
|
|
||||||
struct AutoInCallback
|
struct AutoInCallback
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#ifdef MOZ_WEBRTC
|
#ifdef MOZ_WEBRTC
|
||||||
#include "AudioOutputObserver.h"
|
#include "AudioOutputObserver.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "mtransport/runnable_utils.h"
|
||||||
|
|
||||||
#include "webaudio/blink/HRTFDatabaseLoader.h"
|
#include "webaudio/blink/HRTFDatabaseLoader.h"
|
||||||
|
|
||||||
|
@ -922,6 +923,85 @@ MediaStreamGraphImpl::PlayVideo(MediaStream* aStream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaStreamGraphImpl::OpenAudioInputImpl(char *aName, MediaStreamListener *aListener)
|
||||||
|
{
|
||||||
|
if (CurrentDriver()->AsAudioCallbackDriver()) {
|
||||||
|
CurrentDriver()->SetInputListener(aListener);
|
||||||
|
} else {
|
||||||
|
// XXX Switch to callback driver
|
||||||
|
}
|
||||||
|
mAudioInputs.AppendElement(aListener); // always monitor speaker data
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
MediaStreamGraphImpl::OpenAudioInput(char *aName, MediaStreamListener *aListener)
|
||||||
|
{
|
||||||
|
// XXX So, so, so annoying. Can't AppendMessage except on Mainthread
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
NS_DispatchToMainThread(WrapRunnable(this,
|
||||||
|
&MediaStreamGraphImpl::OpenAudioInput,
|
||||||
|
aName, aListener)); // XXX Fix! string need to copied
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
class Message : public ControlMessage {
|
||||||
|
public:
|
||||||
|
Message(MediaStreamGraphImpl *aGraph, char *aName, MediaStreamListener *aListener) :
|
||||||
|
ControlMessage(nullptr), mGraph(aGraph), mName(aName), mListener(aListener) {}
|
||||||
|
virtual void Run()
|
||||||
|
{
|
||||||
|
mGraph->OpenAudioInputImpl(mName, mListener);
|
||||||
|
}
|
||||||
|
MediaStreamGraphImpl *mGraph;
|
||||||
|
char *mName; // XXX needs to copy
|
||||||
|
MediaStreamListener *mListener;
|
||||||
|
};
|
||||||
|
this->AppendMessage(new Message(this, aName, aListener));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaStreamGraphImpl::CloseAudioInputImpl(MediaStreamListener *aListener)
|
||||||
|
{
|
||||||
|
CurrentDriver()->RemoveInputListener(aListener);
|
||||||
|
mAudioInputs.RemoveElement(aListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaStreamGraphImpl::CloseAudioInput(MediaStreamListener *aListener)
|
||||||
|
{
|
||||||
|
// XXX So, so, so annoying. Can't AppendMessage except on Mainthread
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
NS_DispatchToMainThread(WrapRunnable(this,
|
||||||
|
&MediaStreamGraphImpl::CloseAudioInput,
|
||||||
|
aListener));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
class Message : public ControlMessage {
|
||||||
|
public:
|
||||||
|
Message(MediaStreamGraphImpl *aGraph, MediaStreamListener *aListener) :
|
||||||
|
ControlMessage(nullptr), mGraph(aGraph), mListener(aListener) {}
|
||||||
|
virtual void Run()
|
||||||
|
{
|
||||||
|
mGraph->CloseAudioInputImpl(mListener);
|
||||||
|
}
|
||||||
|
MediaStreamGraphImpl *mGraph;
|
||||||
|
MediaStreamListener *mListener;
|
||||||
|
};
|
||||||
|
this->AppendMessage(new Message(this, aListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// All AudioInput listeners get the same speaker data (at least for now).
|
||||||
|
void
|
||||||
|
MediaStreamGraph::NotifySpeakerData(AudioDataValue* aBuffer, size_t aFrames,
|
||||||
|
uint32_t aChannels)
|
||||||
|
{
|
||||||
|
for (auto& listener : mAudioInputs) {
|
||||||
|
listener->NotifySpeakerData(this, aBuffer, aFrames, aChannels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MediaStreamGraphImpl::ShouldUpdateMainThread()
|
MediaStreamGraphImpl::ShouldUpdateMainThread()
|
||||||
{
|
{
|
||||||
|
|
|
@ -181,6 +181,23 @@ public:
|
||||||
* are also notified of atomically to MediaStreamListeners.
|
* are also notified of atomically to MediaStreamListeners.
|
||||||
*/
|
*/
|
||||||
virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) {}
|
virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) {}
|
||||||
|
|
||||||
|
/* These are for cubeb audio input & output streams: */
|
||||||
|
/**
|
||||||
|
* Output data to speakers, for use as the "far-end" data for echo
|
||||||
|
* cancellation. This is not guaranteed to be in any particular size
|
||||||
|
* chunks.
|
||||||
|
*/
|
||||||
|
virtual void NotifySpeakerData(MediaStreamGraph* aGraph,
|
||||||
|
AudioDataValue* aBuffer, size_t aFrames,
|
||||||
|
uint32_t aChannels) {}
|
||||||
|
/**
|
||||||
|
* Input data from a microphone (or other audio source. This is not
|
||||||
|
* guaranteed to be in any particular size chunks.
|
||||||
|
*/
|
||||||
|
virtual void NotifyInputData(MediaStreamGraph* aGraph,
|
||||||
|
AudioDataValue* aBuffer, size_t aFrames,
|
||||||
|
uint32_t aChannels) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1175,6 +1192,11 @@ public:
|
||||||
// Idempotent
|
// Idempotent
|
||||||
static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
|
static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
|
||||||
|
|
||||||
|
virtual nsresult OpenAudioInput(char *aName, MediaStreamListener *aListener) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
virtual void CloseAudioInput(MediaStreamListener *aListener) {}
|
||||||
|
|
||||||
// Control API.
|
// Control API.
|
||||||
/**
|
/**
|
||||||
* Create a stream that a media decoder (or some other source of
|
* Create a stream that a media decoder (or some other source of
|
||||||
|
@ -1254,6 +1276,13 @@ public:
|
||||||
already_AddRefed<MediaInputPort> ConnectToCaptureStream(
|
already_AddRefed<MediaInputPort> ConnectToCaptureStream(
|
||||||
uint64_t aWindowId, MediaStream* aMediaStream);
|
uint64_t aWindowId, MediaStream* aMediaStream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data going to the speakers from the GraphDriver's DataCallback
|
||||||
|
* to notify any listeners (for echo cancellation).
|
||||||
|
*/
|
||||||
|
void NotifySpeakerData(AudioDataValue* aBuffer, size_t aFrames,
|
||||||
|
uint32_t aChannels);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit MediaStreamGraph(TrackRate aSampleRate)
|
explicit MediaStreamGraph(TrackRate aSampleRate)
|
||||||
: mSampleRate(aSampleRate)
|
: mSampleRate(aSampleRate)
|
||||||
|
@ -1274,6 +1303,8 @@ protected:
|
||||||
* at construction.
|
* at construction.
|
||||||
*/
|
*/
|
||||||
TrackRate mSampleRate;
|
TrackRate mSampleRate;
|
||||||
|
|
||||||
|
nsTArray<RefPtr<MediaStreamListener>> mAudioInputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -350,6 +350,11 @@ public:
|
||||||
* at the current buffer end point. The StreamBuffer's tracks must be
|
* at the current buffer end point. The StreamBuffer's tracks must be
|
||||||
* explicitly set to finished by the caller.
|
* explicitly set to finished by the caller.
|
||||||
*/
|
*/
|
||||||
|
void OpenAudioInputImpl(char *aName, MediaStreamListener *aListener);
|
||||||
|
virtual nsresult OpenAudioInput(char *aName, MediaStreamListener *aListener) override;
|
||||||
|
void CloseAudioInputImpl(MediaStreamListener *aListener);
|
||||||
|
virtual void CloseAudioInput(MediaStreamListener *aListener) override;
|
||||||
|
|
||||||
void FinishStream(MediaStream* aStream);
|
void FinishStream(MediaStream* aStream);
|
||||||
/**
|
/**
|
||||||
* Compute how much stream data we would like to buffer for aStream.
|
* Compute how much stream data we would like to buffer for aStream.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче