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 "DeviceInputTrack.h"
9 #include "MediaTrackGraphImpl.h"
16 #endif // LOG_INTERNAL
17 #define LOG_INTERNAL(level, msg, ...) \
18 MOZ_LOG(gMediaTrackGraphLog, LogLevel::level, (msg, ##__VA_ARGS__))
23 #define LOG(msg, ...) LOG_INTERNAL(Debug, msg, ##__VA_ARGS__)
28 #define LOGE(msg, ...) LOG_INTERNAL(Error, msg, ##__VA_ARGS__)
30 // This can only be called in graph thread since mGraph->CurrentDriver() is
32 #ifdef TRACK_GRAPH_LOG_INTERNAL
33 # undef TRACK_GRAPH_LOG_INTERNAL
34 #endif // TRACK_GRAPH_LOG_INTERNAL
35 #define TRACK_GRAPH_LOG_INTERNAL(level, msg, ...) \
36 LOG_INTERNAL(level, "(Graph %p, Driver %p) DeviceInputTrack %p, " msg, \
37 this->mGraph, this->mGraph->CurrentDriver(), this, \
40 #ifdef TRACK_GRAPH_LOG
41 # undef TRACK_GRAPH_LOG
42 #endif // TRACK_GRAPH_LOG
43 #define TRACK_GRAPH_LOG(msg, ...) \
44 TRACK_GRAPH_LOG_INTERNAL(Debug, msg, ##__VA_ARGS__)
46 #ifdef TRACK_GRAPH_LOGV
47 # undef TRACK_GRAPH_LOGV
48 #endif // TRACK_GRAPH_LOGV
49 #define TRACK_GRAPH_LOGV(msg, ...) \
50 TRACK_GRAPH_LOG_INTERNAL(Verbose, msg, ##__VA_ARGS__)
52 #ifdef TRACK_GRAPH_LOGE
53 # undef TRACK_GRAPH_LOGE
54 #endif // TRACK_GRAPH_LOGE
55 #define TRACK_GRAPH_LOGE(msg, ...) \
56 TRACK_GRAPH_LOG_INTERNAL(Error, msg, ##__VA_ARGS__)
58 #ifdef CONSUMER_GRAPH_LOG_INTERNAL
59 # undef CONSUMER_GRAPH_LOG_INTERNAL
60 #endif // CONSUMER_GRAPH_LOG_INTERNAL
61 #define CONSUMER_GRAPH_LOG_INTERNAL(level, msg, ...) \
63 level, "(Graph %p, Driver %p) DeviceInputConsumerTrack %p, " msg, \
64 this->mGraph, this->mGraph->CurrentDriver(), this, ##__VA_ARGS__)
66 #ifdef CONSUMER_GRAPH_LOGV
67 # undef CONSUMER_GRAPH_LOGV
68 #endif // CONSUMER_GRAPH_LOGV
69 #define CONSUMER_GRAPH_LOGV(msg, ...) \
70 CONSUMER_GRAPH_LOG_INTERNAL(Verbose, msg, ##__VA_ARGS__)
72 DeviceInputConsumerTrack::DeviceInputConsumerTrack(TrackRate aSampleRate
)
73 : ProcessedMediaTrack(aSampleRate
, MediaSegment::AUDIO
,
74 new AudioSegment()) {}
76 void DeviceInputConsumerTrack::ConnectDeviceInput(
77 CubebUtils::AudioDeviceID aId
, AudioDataListener
* aListener
,
78 const PrincipalHandle
& aPrincipal
) {
79 MOZ_ASSERT(NS_IsMainThread());
80 MOZ_ASSERT(GraphImpl());
81 MOZ_ASSERT(aListener
);
82 MOZ_ASSERT(!mListener
);
83 MOZ_ASSERT(!mDeviceInputTrack
);
84 MOZ_ASSERT(mDeviceId
.isNothing());
85 MOZ_ASSERT(!mDeviceInputTrack
,
86 "Must disconnect a device input before connecting a new one");
88 mListener
= aListener
;
89 mDeviceId
.emplace(aId
);
92 DeviceInputTrack::OpenAudio(GraphImpl(), aId
, aPrincipal
, this);
93 LOG("Open device %p (DeviceInputTrack %p) for consumer %p", aId
,
94 mDeviceInputTrack
.get(), this);
95 mPort
= AllocateInputPort(mDeviceInputTrack
.get());
98 void DeviceInputConsumerTrack::DisconnectDeviceInput() {
99 MOZ_ASSERT(NS_IsMainThread());
100 MOZ_ASSERT(GraphImpl());
103 MOZ_ASSERT(mDeviceId
.isNothing());
104 MOZ_ASSERT(!mDeviceInputTrack
);
109 MOZ_ASSERT(mDeviceInputTrack
);
110 MOZ_ASSERT(mDeviceId
.isSome());
112 LOG("Close device %p (DeviceInputTrack %p) for consumer %p ", *mDeviceId
,
113 mDeviceInputTrack
.get(), this);
115 DeviceInputTrack::CloseAudio(mDeviceInputTrack
.forget(), this);
117 mDeviceId
= Nothing();
120 Maybe
<CubebUtils::AudioDeviceID
> DeviceInputConsumerTrack::DeviceId() const {
121 MOZ_ASSERT(NS_IsMainThread());
125 NotNull
<AudioDataListener
*> DeviceInputConsumerTrack::GetAudioDataListener()
127 MOZ_ASSERT(NS_IsMainThread());
128 return WrapNotNull(mListener
.get());
131 bool DeviceInputConsumerTrack::ConnectToNativeDevice() const {
132 MOZ_ASSERT(NS_IsMainThread());
133 return mDeviceInputTrack
&& mDeviceInputTrack
->AsNativeInputTrack();
136 bool DeviceInputConsumerTrack::ConnectToNonNativeDevice() const {
137 MOZ_ASSERT(NS_IsMainThread());
138 return mDeviceInputTrack
&& mDeviceInputTrack
->AsNonNativeInputTrack();
141 void DeviceInputConsumerTrack::GetInputSourceData(AudioSegment
& aOutput
,
142 const MediaInputPort
* aPort
,
144 GraphTime aTo
) const {
145 MOZ_ASSERT(mGraph
->OnGraphThread());
146 MOZ_ASSERT(aOutput
.IsEmpty());
148 MediaTrack
* source
= aPort
->GetSource();
150 for (GraphTime t
= aFrom
; t
< aTo
; t
= next
) {
151 MediaInputPort::InputInterval interval
=
152 MediaInputPort::GetNextInputInterval(aPort
, t
);
153 interval
.mEnd
= std::min(interval
.mEnd
, aTo
);
155 const bool inputEnded
=
158 source
->GraphTimeToTrackTimeWithBlocking(interval
.mStart
);
160 TrackTime ticks
= interval
.mEnd
- interval
.mStart
;
161 next
= interval
.mEnd
;
163 if (interval
.mStart
>= interval
.mEnd
) {
168 aOutput
.AppendNullData(ticks
);
171 " ticks of null data from input port source (ended input)",
173 } else if (interval
.mInputIsBlocked
) {
174 aOutput
.AppendNullData(ticks
);
177 " ticks of null data from input port source (blocked input)",
179 } else if (source
->IsSuspended()) {
180 aOutput
.AppendNullData(ticks
);
183 " ticks of null data from input port source (source is suspended)",
187 source
->GraphTimeToTrackTimeWithBlocking(interval
.mStart
);
188 TrackTime end
= source
->GraphTimeToTrackTimeWithBlocking(interval
.mEnd
);
189 MOZ_ASSERT(source
->GetData
<AudioSegment
>()->GetDuration() >= end
);
190 aOutput
.AppendSlice(*source
->GetData
<AudioSegment
>(), start
, end
);
191 CONSUMER_GRAPH_LOGV("Getting %" PRId64
192 " ticks of real data from input port source %p",
193 end
- start
, source
);
199 NotNull
<RefPtr
<DeviceInputTrack
>> DeviceInputTrack::OpenAudio(
200 MediaTrackGraphImpl
* aGraph
, CubebUtils::AudioDeviceID aDeviceId
,
201 const PrincipalHandle
& aPrincipalHandle
,
202 DeviceInputConsumerTrack
* aConsumer
) {
203 MOZ_ASSERT(NS_IsMainThread());
204 MOZ_ASSERT(aConsumer
);
205 MOZ_ASSERT(aGraph
== aConsumer
->GraphImpl());
207 RefPtr
<DeviceInputTrack
> track
=
208 aGraph
->GetDeviceInputTrackMainThread(aDeviceId
);
210 MOZ_ASSERT(!track
->mConsumerTracks
.IsEmpty());
211 track
->AddDataListener(aConsumer
->GetAudioDataListener());
213 // Create a NativeInputTrack or NonNativeInputTrack, depending on whether
214 // the given graph already has a native device or not.
215 if (aGraph
->GetNativeInputTrackMainThread()) {
216 // A native device is already in use. This device will be a non-native
218 track
= new NonNativeInputTrack(aGraph
->GraphRate(), aDeviceId
,
221 // No native device is in use. This device will be the native device.
222 track
= new NativeInputTrack(aGraph
->GraphRate(), aDeviceId
,
225 LOG("Create %sNativeInputTrack %p in MTG %p for device %p",
226 (track
->AsNativeInputTrack() ? "" : "Non"), track
.get(), aGraph
,
228 aGraph
->AddTrack(track
);
229 // Add the listener before opening the device so the device passed to
230 // OpenAudioInput always has a non-zero input channel count.
231 track
->AddDataListener(aConsumer
->GetAudioDataListener());
232 aGraph
->OpenAudioInput(track
);
234 MOZ_ASSERT(track
->AsNativeInputTrack() || track
->AsNonNativeInputTrack());
235 MOZ_ASSERT(track
->mDeviceId
== aDeviceId
);
237 MOZ_ASSERT(!track
->mConsumerTracks
.Contains(aConsumer
));
238 track
->mConsumerTracks
.AppendElement(aConsumer
);
240 LOG("DeviceInputTrack %p (device %p: %snative) in MTG %p has %zu users now",
241 track
.get(), track
->mDeviceId
,
242 (track
->AsNativeInputTrack() ? "" : "non-"), aGraph
,
243 track
->mConsumerTracks
.Length());
244 if (track
->mConsumerTracks
.Length() > 1) {
245 track
->ReevaluateInputDevice();
248 return WrapNotNull(track
);
252 void DeviceInputTrack::CloseAudio(already_AddRefed
<DeviceInputTrack
> aTrack
,
253 DeviceInputConsumerTrack
* aConsumer
) {
254 MOZ_ASSERT(NS_IsMainThread());
256 RefPtr
<DeviceInputTrack
> track
= aTrack
;
259 track
->RemoveDataListener(aConsumer
->GetAudioDataListener());
260 DebugOnly
<bool> removed
= track
->mConsumerTracks
.RemoveElement(aConsumer
);
262 LOG("DeviceInputTrack %p (device %p) in MTG %p has %zu users now",
263 track
.get(), track
->mDeviceId
, track
->GraphImpl(),
264 track
->mConsumerTracks
.Length());
265 if (track
->mConsumerTracks
.IsEmpty()) {
266 track
->GraphImpl()->CloseAudioInput(track
);
269 track
->ReevaluateInputDevice();
273 const nsTArray
<RefPtr
<DeviceInputConsumerTrack
>>&
274 DeviceInputTrack::GetConsumerTracks() const {
275 MOZ_ASSERT(NS_IsMainThread());
276 return mConsumerTracks
;
279 DeviceInputTrack::DeviceInputTrack(TrackRate aSampleRate
,
280 CubebUtils::AudioDeviceID aDeviceId
,
281 const PrincipalHandle
& aPrincipalHandle
)
282 : ProcessedMediaTrack(aSampleRate
, MediaSegment::AUDIO
, new AudioSegment()),
283 mDeviceId(aDeviceId
),
284 mPrincipalHandle(aPrincipalHandle
) {}
286 uint32_t DeviceInputTrack::MaxRequestedInputChannels() const {
287 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
288 uint32_t maxInputChannels
= 0;
289 for (const auto& listener
: mListeners
) {
290 maxInputChannels
= std::max(maxInputChannels
,
291 listener
->RequestedInputChannelCount(mGraph
));
293 return maxInputChannels
;
296 bool DeviceInputTrack::HasVoiceInput() const {
297 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
298 for (const auto& listener
: mListeners
) {
299 if (listener
->IsVoiceInput(mGraph
)) {
306 void DeviceInputTrack::DeviceChanged(MediaTrackGraphImpl
* aGraph
) const {
307 MOZ_ASSERT(aGraph
->OnGraphThreadOrNotRunning());
308 MOZ_ASSERT(aGraph
== mGraph
,
309 "Receive device changed signal from another graph");
310 TRACK_GRAPH_LOG("DeviceChanged");
311 for (const auto& listener
: mListeners
) {
312 listener
->DeviceChanged(aGraph
);
316 void DeviceInputTrack::ReevaluateInputDevice() {
317 MOZ_ASSERT(NS_IsMainThread());
318 class Message
: public ControlMessage
{
320 explicit Message(MediaTrack
* aTrack
, CubebUtils::AudioDeviceID aDeviceId
)
321 : ControlMessage(aTrack
), mDeviceId(aDeviceId
) {}
322 void Run() override
{
323 TRACE("DeviceInputTrack::ReevaluateInputDevice ControlMessage");
324 mTrack
->GraphImpl()->ReevaluateInputDevice(mDeviceId
);
326 CubebUtils::AudioDeviceID mDeviceId
;
328 mGraph
->AppendMessage(MakeUnique
<Message
>(this, mDeviceId
));
331 void DeviceInputTrack::AddDataListener(AudioDataListener
* aListener
) {
332 MOZ_ASSERT(NS_IsMainThread());
334 class Message
: public ControlMessage
{
336 Message(DeviceInputTrack
* aInputTrack
, AudioDataListener
* aListener
)
337 : ControlMessage(nullptr),
338 mInputTrack(aInputTrack
),
339 mListener(aListener
) {}
340 void Run() override
{
341 TRACE("DeviceInputTrack::AddDataListener ControlMessage");
342 MOZ_ASSERT(!mInputTrack
->mListeners
.Contains(mListener
.get()),
343 "Don't add a listener twice.");
344 mInputTrack
->mListeners
.AppendElement(mListener
.get());
346 RefPtr
<DeviceInputTrack
> mInputTrack
;
347 RefPtr
<AudioDataListener
> mListener
;
350 mGraph
->AppendMessage(MakeUnique
<Message
>(this, aListener
));
353 void DeviceInputTrack::RemoveDataListener(AudioDataListener
* aListener
) {
354 MOZ_ASSERT(NS_IsMainThread());
356 class Message
: public ControlMessage
{
358 Message(DeviceInputTrack
* aInputTrack
, AudioDataListener
* aListener
)
359 : ControlMessage(nullptr),
360 mInputTrack(aInputTrack
),
361 mListener(aListener
) {}
362 void Run() override
{
363 TRACE("DeviceInputTrack::RemoveDataListener ControlMessage");
364 DebugOnly
<bool> wasPresent
=
365 mInputTrack
->mListeners
.RemoveElement(mListener
.get());
366 MOZ_ASSERT(wasPresent
, "Remove an unknown listener");
367 mListener
->Disconnect(mInputTrack
->GraphImpl());
369 RefPtr
<DeviceInputTrack
> mInputTrack
;
370 RefPtr
<AudioDataListener
> mListener
;
373 mGraph
->AppendMessage(MakeUnique
<Message
>(this, aListener
));
376 NativeInputTrack::NativeInputTrack(TrackRate aSampleRate
,
377 CubebUtils::AudioDeviceID aDeviceId
,
378 const PrincipalHandle
& aPrincipalHandle
)
379 : DeviceInputTrack(aSampleRate
, aDeviceId
, aPrincipalHandle
),
380 mIsBufferingAppended(false),
383 void NativeInputTrack::DestroyImpl() {
384 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
385 mPendingData
.Clear();
386 ProcessedMediaTrack::DestroyImpl();
389 void NativeInputTrack::ProcessInput(GraphTime aFrom
, GraphTime aTo
,
391 MOZ_ASSERT(mGraph
->OnGraphThread());
392 TRACE_COMMENT("NativeInputTrack::ProcessInput", "%p", this);
394 TRACK_GRAPH_LOGV("(Native) ProcessInput from %" PRId64
" to %" PRId64
395 ", needs %" PRId64
" frames",
396 aFrom
, aTo
, aTo
- aFrom
);
398 TrackTime from
= GraphTimeToTrackTime(aFrom
);
399 TrackTime to
= GraphTimeToTrackTime(aTo
);
404 MOZ_ASSERT_IF(!mIsBufferingAppended
, mPendingData
.IsEmpty());
406 TrackTime need
= to
- from
;
407 TrackTime dataNeed
= std::min(mPendingData
.GetDuration(), need
);
408 TrackTime silenceNeed
= std::max(need
- dataNeed
, (TrackTime
)0);
410 MOZ_ASSERT_IF(dataNeed
> 0, silenceNeed
== 0);
412 GetData
<AudioSegment
>()->AppendSlice(mPendingData
, 0, dataNeed
);
413 mPendingData
.RemoveLeading(dataNeed
);
414 GetData
<AudioSegment
>()->AppendNullData(silenceNeed
);
417 uint32_t NativeInputTrack::NumberOfChannels() const {
418 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
419 return mInputChannels
;
422 void NativeInputTrack::NotifyInputStopped(MediaTrackGraphImpl
* aGraph
) {
423 MOZ_ASSERT(aGraph
->OnGraphThreadOrNotRunning());
424 MOZ_ASSERT(aGraph
== mGraph
,
425 "Receive input stopped signal from another graph");
426 TRACK_GRAPH_LOG("(Native) NotifyInputStopped");
428 mIsBufferingAppended
= false;
429 mPendingData
.Clear();
432 void NativeInputTrack::NotifyInputData(MediaTrackGraphImpl
* aGraph
,
433 const AudioDataValue
* aBuffer
,
434 size_t aFrames
, TrackRate aRate
,
436 uint32_t aAlreadyBuffered
) {
437 MOZ_ASSERT(aGraph
->OnGraphThread());
438 MOZ_ASSERT(aGraph
== mGraph
, "Receive input data from another graph");
440 "NotifyInputData: frames=%zu, rate=%d, channel=%u, alreadyBuffered=%u",
441 aFrames
, aRate
, aChannels
, aAlreadyBuffered
);
443 if (!mIsBufferingAppended
) {
444 // First time we see live frames getting added. Use what's already buffered
445 // in the driver's scratch buffer as a starting point.
446 MOZ_ASSERT(mPendingData
.IsEmpty());
447 constexpr TrackTime buffering
= WEBAUDIO_BLOCK_SIZE
;
448 const TrackTime remaining
=
449 buffering
- static_cast<TrackTime
>(aAlreadyBuffered
);
450 mPendingData
.AppendNullData(remaining
);
451 mIsBufferingAppended
= true;
452 TRACK_GRAPH_LOG("Set mIsBufferingAppended by appending %" PRId64
" frames.",
456 MOZ_ASSERT(aChannels
);
457 if (!mInputChannels
) {
458 mInputChannels
= aChannels
;
460 mPendingData
.AppendFromInterleavedBuffer(aBuffer
, aFrames
, aChannels
,
464 NonNativeInputTrack::NonNativeInputTrack(
465 TrackRate aSampleRate
, CubebUtils::AudioDeviceID aDeviceId
,
466 const PrincipalHandle
& aPrincipalHandle
)
467 : DeviceInputTrack(aSampleRate
, aDeviceId
, aPrincipalHandle
),
468 mAudioSource(nullptr),
470 mGraphDriverThreadId(std::thread::id()) {}
472 void NonNativeInputTrack::DestroyImpl() {
473 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
475 mAudioSource
->Stop();
476 mAudioSource
= nullptr;
478 ProcessedMediaTrack::DestroyImpl();
481 void NonNativeInputTrack::ProcessInput(GraphTime aFrom
, GraphTime aTo
,
483 MOZ_ASSERT(mGraph
->OnGraphThread());
484 TRACE_COMMENT("NonNativeInputTrack::ProcessInput", "%p", this);
486 TRACK_GRAPH_LOGV("(NonNative) ProcessInput from %" PRId64
" to %" PRId64
487 ", needs %" PRId64
" frames",
488 aFrom
, aTo
, aTo
- aFrom
);
490 TrackTime from
= GraphTimeToTrackTime(aFrom
);
491 TrackTime to
= GraphTimeToTrackTime(aTo
);
496 TrackTime delta
= to
- from
;
498 GetData
<AudioSegment
>()->AppendNullData(delta
);
502 // GetAudioSegment only checks the given reader if DEBUG is defined.
503 AudioInputSource::Consumer consumer
=
505 // If we are on GraphRunner, we should always be on the same thread.
506 mGraph
->mGraphRunner
|| !CheckGraphDriverChanged()
507 ? AudioInputSource::Consumer::Same
508 : AudioInputSource::Consumer::Changed
;
510 AudioInputSource::Consumer::Same
;
513 AudioSegment data
= mAudioSource
->GetAudioSegment(delta
, consumer
);
514 MOZ_ASSERT(data
.GetDuration() == delta
);
515 GetData
<AudioSegment
>()->AppendFrom(&data
);
518 uint32_t NonNativeInputTrack::NumberOfChannels() const {
519 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
520 return mAudioSource
? mAudioSource
->mChannelCount
: 0;
523 void NonNativeInputTrack::StartAudio(
524 RefPtr
<AudioInputSource
>&& aAudioInputSource
) {
525 MOZ_ASSERT(mGraph
->OnGraphThread());
526 MOZ_ASSERT(aAudioInputSource
->mPrincipalHandle
== mPrincipalHandle
);
527 MOZ_ASSERT(aAudioInputSource
->mDeviceId
== mDeviceId
);
529 TRACK_GRAPH_LOG("StartAudio with source %p", aAudioInputSource
.get());
530 mAudioSource
= std::move(aAudioInputSource
);
531 mAudioSource
->Start();
534 void NonNativeInputTrack::StopAudio() {
535 MOZ_ASSERT(mGraph
->OnGraphThread());
537 TRACK_GRAPH_LOG("StopAudio from source %p", mAudioSource
.get());
541 mAudioSource
->Stop();
542 mAudioSource
= nullptr;
545 AudioInputType
NonNativeInputTrack::DevicePreference() const {
546 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
547 return mAudioSource
&& mAudioSource
->mIsVoice
? AudioInputType::Voice
548 : AudioInputType::Unknown
;
551 void NonNativeInputTrack::NotifyDeviceChanged(uint32_t aSourceId
) {
552 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
554 // No need to forward the notification if the audio input has been stopped or
555 // restarted by it users.
556 if (!mAudioSource
|| mAudioSource
->mId
!= aSourceId
) {
557 TRACK_GRAPH_LOG("(NonNative) NotifyDeviceChanged: No need to forward");
561 TRACK_GRAPH_LOG("(NonNative) NotifyDeviceChanged");
562 // Forward the notification.
563 DeviceInputTrack::DeviceChanged(mGraph
);
566 void NonNativeInputTrack::NotifyInputStopped(uint32_t aSourceId
) {
567 MOZ_ASSERT(mGraph
->OnGraphThreadOrNotRunning());
569 // No need to forward the notification if the audio input has been stopped or
570 // restarted by it users.
571 if (!mAudioSource
|| mAudioSource
->mId
!= aSourceId
) {
572 TRACK_GRAPH_LOG("(NonNative) NotifyInputStopped: No need to forward");
577 "(NonNative) NotifyInputStopped: audio unexpectedly stopped");
578 // Destory the underlying audio stream if it's stopped unexpectedly.
579 mAudioSource
->Stop();
582 AudioInputSource::Id
NonNativeInputTrack::GenerateSourceId() {
583 MOZ_ASSERT(mGraph
->OnGraphThread());
584 return mSourceIdNumber
++;
587 bool NonNativeInputTrack::CheckGraphDriverChanged() {
588 MOZ_ASSERT(mGraph
->CurrentDriver()->OnThread());
590 std::thread::id currentId
= std::this_thread::get_id();
591 if (mGraphDriverThreadId
== currentId
) {
594 mGraphDriverThreadId
= currentId
;
598 AudioInputSourceListener::AudioInputSourceListener(NonNativeInputTrack
* aOwner
)
601 void AudioInputSourceListener::AudioDeviceChanged(
602 AudioInputSource::Id aSourceId
) {
603 MOZ_ASSERT(NS_IsMainThread());
606 if (mOwner
->IsDestroyed()) {
607 LOG("NonNativeInputTrack %p has been destroyed. No need to forward the "
608 "audio device-changed notification",
613 class DeviceChangedMessage
: public ControlMessage
{
615 DeviceChangedMessage(NonNativeInputTrack
* aInputTrack
,
616 AudioInputSource::Id aSourceId
)
617 : ControlMessage(nullptr),
618 mInputTrack(aInputTrack
),
619 mSourceId(aSourceId
) {
620 MOZ_ASSERT(mInputTrack
);
622 void Run() override
{
623 TRACE("NonNativeInputTrack::AudioDeviceChanged ControlMessage");
624 mInputTrack
->NotifyDeviceChanged(mSourceId
);
626 RefPtr
<NonNativeInputTrack
> mInputTrack
;
627 AudioInputSource::Id mSourceId
;
630 MOZ_DIAGNOSTIC_ASSERT(mOwner
->GraphImpl());
631 mOwner
->GraphImpl()->AppendMessage(
632 MakeUnique
<DeviceChangedMessage
>(mOwner
.get(), aSourceId
));
635 void AudioInputSourceListener::AudioStateCallback(
636 AudioInputSource::Id aSourceId
,
637 AudioInputSource::EventListener::State aState
) {
638 MOZ_ASSERT(NS_IsMainThread());
642 aState
== AudioInputSource::EventListener::State::Started
? "started"
643 : aState
== AudioInputSource::EventListener::State::Stopped
? "stopped"
644 : aState
== AudioInputSource::EventListener::State::Drained
? "drained"
647 if (mOwner
->IsDestroyed()) {
648 LOG("NonNativeInputTrack %p has been destroyed. No need to forward the "
649 "audio state-changed(%s) notification",
650 mOwner
.get(), state
);
654 if (aState
== AudioInputSource::EventListener::State::Started
) {
655 LOG("We can ignore %s notification for NonNativeInputTrack %p", state
,
660 LOG("Notify audio stopped due to entering %s state", state
);
662 class InputStoppedMessage
: public ControlMessage
{
664 InputStoppedMessage(NonNativeInputTrack
* aInputTrack
,
665 AudioInputSource::Id aSourceId
)
666 : ControlMessage(nullptr),
667 mInputTrack(aInputTrack
),
668 mSourceId(aSourceId
) {
669 MOZ_ASSERT(mInputTrack
);
671 void Run() override
{
672 TRACE("NonNativeInputTrack::AudioStateCallback ControlMessage");
673 mInputTrack
->NotifyInputStopped(mSourceId
);
675 RefPtr
<NonNativeInputTrack
> mInputTrack
;
676 AudioInputSource::Id mSourceId
;
679 MOZ_DIAGNOSTIC_ASSERT(mOwner
->GraphImpl());
680 mOwner
->GraphImpl()->AppendMessage(
681 MakeUnique
<InputStoppedMessage
>(mOwner
.get(), aSourceId
));
687 #undef TRACK_GRAPH_LOG_INTERNAL
688 #undef TRACK_GRAPH_LOG
689 #undef TRACK_GRAPH_LOGV
690 #undef TRACK_GRAPH_LOGE
691 #undef CONSUMER_GRAPH_LOG_INTERNAL
692 #undef CONSUMER_GRAPH_LOGV
694 } // namespace mozilla