2013-12-11 09:03:30 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2017-03-22 09:55:59 +03:00
|
|
|
#ifndef AudioSink_h__
|
|
|
|
#define AudioSink_h__
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
#include "AudioStream.h"
|
2015-08-26 05:30:56 +03:00
|
|
|
#include "MediaEventSource.h"
|
2016-04-27 14:01:13 +03:00
|
|
|
#include "MediaQueue.h"
|
2015-07-23 14:58:30 +03:00
|
|
|
#include "MediaInfo.h"
|
2017-03-22 09:48:00 +03:00
|
|
|
#include "MediaSink.h"
|
2015-07-23 14:58:30 +03:00
|
|
|
|
2013-12-11 09:03:30 +04:00
|
|
|
#include "mozilla/dom/AudioChannelBinding.h"
|
2015-07-09 17:58:24 +03:00
|
|
|
#include "mozilla/Atomics.h"
|
2015-07-28 06:52:05 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2015-07-22 04:54:06 +03:00
|
|
|
#include "mozilla/MozPromise.h"
|
2016-04-25 17:13:01 +03:00
|
|
|
#include "mozilla/Monitor.h"
|
2017-03-22 09:48:00 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
#include "nsISupportsImpl.h"
|
2013-12-11 09:03:30 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
2015-08-26 05:30:56 +03:00
|
|
|
|
2016-04-11 14:16:17 +03:00
|
|
|
class AudioConverter;
|
|
|
|
|
2015-08-18 06:55:01 +03:00
|
|
|
namespace media {
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2017-03-22 09:55:59 +03:00
|
|
|
class AudioSink : private AudioStream::DataSource {
|
2017-03-22 09:48:00 +03:00
|
|
|
using PlaybackParams = MediaSink::PlaybackParams;
|
|
|
|
|
2013-12-11 09:03:30 +04:00
|
|
|
public:
|
2017-03-22 09:55:59 +03:00
|
|
|
AudioSink(AbstractThread* aThread,
|
|
|
|
MediaQueue<AudioData>& aAudioQueue,
|
2017-03-27 06:37:17 +03:00
|
|
|
TimeUnit aStartTime,
|
2017-03-22 09:55:59 +03:00
|
|
|
const AudioInfo& aInfo,
|
|
|
|
dom::AudioChannel aChannel);
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2017-03-22 10:13:10 +03:00
|
|
|
~AudioSink();
|
|
|
|
|
2017-03-22 09:55:59 +03:00
|
|
|
// Return a promise which will be resolved when AudioSink
|
2015-08-18 06:55:01 +03:00
|
|
|
// finishes playing, or rejected if any error.
|
2017-03-22 09:48:00 +03:00
|
|
|
RefPtr<GenericPromise> Init(const PlaybackParams& aParams);
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2015-07-24 09:24:42 +03:00
|
|
|
/*
|
2016-01-12 16:48:25 +03:00
|
|
|
* All public functions are not thread-safe.
|
|
|
|
* Called on the task queue of MDSM only.
|
2015-07-24 09:24:42 +03:00
|
|
|
*/
|
2017-03-27 06:37:17 +03:00
|
|
|
TimeUnit GetPosition();
|
|
|
|
TimeUnit GetEndTime() const;
|
2015-07-16 05:13:27 +03:00
|
|
|
|
2015-02-27 00:37:03 +03:00
|
|
|
// Check whether we've pushed more frames to the audio hardware than it has
|
|
|
|
// played.
|
2017-03-22 09:48:00 +03:00
|
|
|
bool HasUnplayedFrames();
|
2015-02-27 00:37:03 +03:00
|
|
|
|
2017-03-22 09:55:59 +03:00
|
|
|
// Shut down the AudioSink's resources.
|
2017-03-22 09:48:00 +03:00
|
|
|
void Shutdown();
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2017-03-22 09:48:00 +03:00
|
|
|
void SetVolume(double aVolume);
|
|
|
|
void SetPlaybackRate(double aPlaybackRate);
|
|
|
|
void SetPreservesPitch(bool aPreservesPitch);
|
|
|
|
void SetPlaying(bool aPlaying);
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2016-05-12 09:18:53 +03:00
|
|
|
MediaEventSource<bool>& AudibleEvent() {
|
|
|
|
return mAudibleEvent;
|
|
|
|
}
|
|
|
|
|
2013-12-11 09:03:30 +04:00
|
|
|
private:
|
2016-01-12 16:48:25 +03:00
|
|
|
// Allocate and initialize mAudioStream. Returns NS_OK on success.
|
|
|
|
nsresult InitializeAudioStream(const PlaybackParams& aParams);
|
2015-07-28 06:49:59 +03:00
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
// Interface of AudioStream::DataSource.
|
|
|
|
// Called on the callback thread of cubeb.
|
|
|
|
UniquePtr<AudioStream::Chunk> PopFrames(uint32_t aFrames) override;
|
|
|
|
bool Ended() const override;
|
|
|
|
void Drained() override;
|
2015-07-28 06:49:59 +03:00
|
|
|
|
2016-05-12 09:18:53 +03:00
|
|
|
void CheckIsAudible(const AudioData* aData);
|
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
// The audio stream resource. Used on the task queue of MDSM only.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AudioStream> mAudioStream;
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2017-03-27 06:37:17 +03:00
|
|
|
// The presentation time of the first audio frame that was played.
|
|
|
|
// We can add this to the audio stream position to determine
|
2016-01-12 16:48:25 +03:00
|
|
|
// the current audio time.
|
2017-03-27 06:37:17 +03:00
|
|
|
const TimeUnit mStartTime;
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2014-10-30 23:10:00 +03:00
|
|
|
// Keep the last good position returned from the audio stream. Used to ensure
|
|
|
|
// position returned by GetPosition() is mono-increasing in spite of audio
|
2016-01-12 16:48:25 +03:00
|
|
|
// stream error. Used on the task queue of MDSM only.
|
2017-03-27 06:37:17 +03:00
|
|
|
TimeUnit mLastGoodPosition;
|
2014-10-30 23:10:00 +03:00
|
|
|
|
2015-07-16 05:13:27 +03:00
|
|
|
const AudioInfo mInfo;
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2015-08-18 06:55:01 +03:00
|
|
|
const dom::AudioChannel mChannel;
|
2013-12-11 09:03:30 +04:00
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
// Used on the task queue of MDSM only.
|
2013-12-11 09:03:30 +04:00
|
|
|
bool mPlaying;
|
2015-07-22 04:54:06 +03:00
|
|
|
|
|
|
|
MozPromiseHolder<GenericPromise> mEndPromise;
|
2015-08-06 05:16:49 +03:00
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
/*
|
|
|
|
* Members to implement AudioStream::DataSource.
|
|
|
|
* Used on the callback thread of cubeb.
|
|
|
|
*/
|
|
|
|
// The AudioData at which AudioStream::DataSource is reading.
|
|
|
|
RefPtr<AudioData> mCurrentData;
|
2016-04-25 17:13:01 +03:00
|
|
|
|
|
|
|
// Monitor protecting access to mCursor and mWritten.
|
|
|
|
// mCursor is created/destroyed on the cubeb thread, while we must also
|
|
|
|
// ensure that mWritten and mCursor::Available() get modified simultaneously.
|
|
|
|
// (written on cubeb thread, and read on MDSM task queue).
|
|
|
|
mutable Monitor mMonitor;
|
2016-04-11 14:16:17 +03:00
|
|
|
// Keep track of the read position of mCurrentData.
|
2016-01-18 06:24:06 +03:00
|
|
|
UniquePtr<AudioBufferCursor> mCursor;
|
2016-04-25 17:13:01 +03:00
|
|
|
|
|
|
|
// PCM frames written to the stream so far.
|
|
|
|
int64_t mWritten;
|
|
|
|
|
2016-01-12 16:48:25 +03:00
|
|
|
// True if there is any error in processing audio data like overflow.
|
2016-04-13 10:17:54 +03:00
|
|
|
Atomic<bool> mErrored;
|
2016-03-22 10:55:51 +03:00
|
|
|
|
|
|
|
// Set on the callback thread of cubeb once the stream has drained.
|
|
|
|
Atomic<bool> mPlaybackComplete;
|
2016-04-11 14:16:17 +03:00
|
|
|
|
2016-04-13 10:17:54 +03:00
|
|
|
const RefPtr<AbstractThread> mOwnerThread;
|
|
|
|
|
|
|
|
// Audio Processing objects and methods
|
2017-03-22 06:59:54 +03:00
|
|
|
void OnAudioPopped(const RefPtr<AudioData>& aSample);
|
|
|
|
void OnAudioPushed(const RefPtr<AudioData>& aSample);
|
2016-04-13 10:17:54 +03:00
|
|
|
void NotifyAudioNeeded();
|
2016-04-14 08:44:02 +03:00
|
|
|
// Drain the converter and add the output to the processed audio queue.
|
|
|
|
// A maximum of aMaxFrames will be added.
|
|
|
|
uint32_t DrainConverter(uint32_t aMaxFrames = UINT32_MAX);
|
2016-04-13 10:17:54 +03:00
|
|
|
already_AddRefed<AudioData> CreateAudioFromBuffer(AlignedAudioBuffer&& aBuffer,
|
|
|
|
AudioData* aReference);
|
|
|
|
// Add data to the processsed queue, update mProcessedQueueLength and
|
|
|
|
// return the number of frames added.
|
|
|
|
uint32_t PushProcessedAudio(AudioData* aData);
|
2016-04-11 14:16:17 +03:00
|
|
|
UniquePtr<AudioConverter> mConverter;
|
2016-04-13 10:17:54 +03:00
|
|
|
MediaQueue<AudioData> mProcessedQueue;
|
|
|
|
// Length in microseconds of the ProcessedQueue
|
|
|
|
Atomic<int32_t> mProcessedQueueLength;
|
|
|
|
MediaEventListener mAudioQueueListener;
|
|
|
|
MediaEventListener mAudioQueueFinishListener;
|
|
|
|
MediaEventListener mProcessedQueueListener;
|
2017-03-22 09:48:00 +03:00
|
|
|
// Number of frames processed from mAudioQueue. Used to determine gaps in
|
2016-04-13 10:17:54 +03:00
|
|
|
// the input stream. It indicates the time in frames since playback started
|
|
|
|
// at the current input framerate.
|
|
|
|
int64_t mFramesParsed;
|
2016-04-14 08:44:02 +03:00
|
|
|
Maybe<RefPtr<AudioData>> mLastProcessedPacket;
|
2017-03-27 06:37:17 +03:00
|
|
|
TimeUnit mLastEndTime;
|
2016-04-13 10:17:54 +03:00
|
|
|
// Never modifed after construction.
|
|
|
|
uint32_t mOutputRate;
|
|
|
|
uint32_t mOutputChannels;
|
2016-05-12 09:18:53 +03:00
|
|
|
|
|
|
|
// True when audio is producing audible sound, false when audio is silent.
|
|
|
|
bool mIsAudioDataAudible;
|
|
|
|
|
|
|
|
MediaEventProducer<bool> mAudibleEvent;
|
2017-03-22 09:48:00 +03:00
|
|
|
|
|
|
|
MediaQueue<AudioData>& mAudioQueue;
|
2013-12-11 09:03:30 +04:00
|
|
|
};
|
|
|
|
|
2015-08-18 06:55:01 +03:00
|
|
|
} // namespace media
|
2013-12-11 09:03:30 +04:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2017-03-22 09:55:59 +03:00
|
|
|
#endif // AudioSink_h__
|