mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 1754495 - Don't use the audio clock to determine if an AudioStream is low on decoded audio. r=alwu
The old technique was slightly misleading. It was counting the audio already sent to the device, in the decoded audio duration. But in fact, there's nothing that can be done about this, the audio is going to be played regardless of what happens. If the audio latency is high enough, this would return a number that's high, but not a lot of audio would be sitting in Firefox's buffer, ready to service the audio callbacks. It's best to only consider the decoded audio (processed + unprocessed) here, since the goal of this is to determine whether more audio needs to be decoded. It also saves a `cubeb_stream_get_position` IPC call if using AudioIPC (soon to be all platforms). Differential Revision: https://phabricator.services.mozilla.com/D138318
This commit is contained in:
parent
a0a0df247c
commit
b37e1d497b
@ -2904,10 +2904,8 @@ already_AddRefed<MediaSink> MediaDecoderStateMachine::CreateMediaSink() {
|
||||
TimeUnit MediaDecoderStateMachine::GetDecodedAudioDuration() const {
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
if (mMediaSink->IsStarted()) {
|
||||
// mDecodedAudioEndTime might be smaller than GetClock() when there is
|
||||
// overlap between 2 adjacent audio samples or when we are playing
|
||||
// a chained ogg file.
|
||||
return std::max(mDecodedAudioEndTime - GetClock(), TimeUnit::Zero());
|
||||
return mMediaSink->UnplayedDuration(TrackInfo::kAudioTrack) +
|
||||
TimeUnit::FromMicroseconds(AudioQueue().Duration());
|
||||
}
|
||||
// MediaSink not started. All audio samples are in the queue.
|
||||
return TimeUnit::FromMicroseconds(AudioQueue().Duration());
|
||||
|
@ -115,6 +115,10 @@ bool AudioSink::HasUnplayedFrames() {
|
||||
(mAudioStream && mAudioStream->GetPositionInFrames() + 1 < mWritten);
|
||||
}
|
||||
|
||||
TimeUnit AudioSink::UnplayedDuration() const {
|
||||
return TimeUnit::FromMicroseconds(AudioQueuedInRingBufferMS());
|
||||
}
|
||||
|
||||
void AudioSink::Shutdown() {
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
|
@ -54,10 +54,13 @@ class AudioSink : private AudioStream::DataSource {
|
||||
media::TimeUnit GetPosition();
|
||||
media::TimeUnit GetEndTime() const;
|
||||
|
||||
// Check whether we've pushed more frames to the audio hardware than it has
|
||||
// played.
|
||||
// Check whether we've pushed more frames to the audio stream than it
|
||||
// has played.
|
||||
bool HasUnplayedFrames();
|
||||
|
||||
// The duration of the buffered frames.
|
||||
media::TimeUnit UnplayedDuration() const;
|
||||
|
||||
// Shut down the AudioSink's resources.
|
||||
void Shutdown();
|
||||
|
||||
|
@ -80,6 +80,11 @@ bool AudioSinkWrapper::HasUnplayedFrames(TrackType aType) const {
|
||||
return mAudioSink ? mAudioSink->HasUnplayedFrames() : false;
|
||||
}
|
||||
|
||||
media::TimeUnit AudioSinkWrapper::UnplayedDuration(TrackType aType) const {
|
||||
AssertOwnerThread();
|
||||
return mAudioSink ? mAudioSink->UnplayedDuration() : media::TimeUnit::Zero();
|
||||
}
|
||||
|
||||
void AudioSinkWrapper::SetVolume(double aVolume) {
|
||||
AssertOwnerThread();
|
||||
mParams.mVolume = aVolume;
|
||||
|
@ -66,6 +66,7 @@ class AudioSinkWrapper : public MediaSink {
|
||||
media::TimeUnit GetEndTime(TrackType aType) const override;
|
||||
media::TimeUnit GetPosition(TimeStamp* aTimeStamp = nullptr) const override;
|
||||
bool HasUnplayedFrames(TrackType aType) const override;
|
||||
media::TimeUnit UnplayedDuration(TrackType aType) const override;
|
||||
|
||||
void SetVolume(double aVolume) override;
|
||||
void SetStreamName(const nsAString& aStreamName) override;
|
||||
|
@ -46,10 +46,15 @@ class DecodedStream : public MediaSink {
|
||||
media::TimeUnit GetEndTime(TrackType aType) const override;
|
||||
media::TimeUnit GetPosition(TimeStamp* aTimeStamp = nullptr) const override;
|
||||
bool HasUnplayedFrames(TrackType aType) const override {
|
||||
// TODO: implement this.
|
||||
// TODO: bug 1755026
|
||||
return false;
|
||||
}
|
||||
|
||||
media::TimeUnit UnplayedDuration(TrackType aType) const override {
|
||||
// TODO: bug 1755026
|
||||
return media::TimeUnit::Zero();
|
||||
}
|
||||
|
||||
void SetVolume(double aVolume) override;
|
||||
void SetPlaybackRate(double aPlaybackRate) override;
|
||||
void SetPreservesPitch(bool aPreservesPitch) override;
|
||||
|
@ -67,6 +67,10 @@ class MediaSink {
|
||||
// Can be called in any state.
|
||||
virtual bool HasUnplayedFrames(TrackType aType) const = 0;
|
||||
|
||||
// Return the duration of data consumed but not played yet.
|
||||
// Can be called in any state.
|
||||
virtual media::TimeUnit UnplayedDuration(TrackType aType) const = 0;
|
||||
|
||||
// Set volume of the audio track.
|
||||
// Do nothing if this sink has no audio track.
|
||||
// Can be called in any state.
|
||||
|
@ -128,6 +128,14 @@ bool VideoSink::HasUnplayedFrames(TrackType aType) const {
|
||||
return mAudioSink->HasUnplayedFrames(aType);
|
||||
}
|
||||
|
||||
media::TimeUnit VideoSink::UnplayedDuration(TrackType aType) const {
|
||||
AssertOwnerThread();
|
||||
MOZ_ASSERT(aType == TrackInfo::kAudioTrack,
|
||||
"Not implemented for non audio tracks.");
|
||||
|
||||
return mAudioSink->UnplayedDuration(aType);
|
||||
}
|
||||
|
||||
void VideoSink::SetPlaybackRate(double aPlaybackRate) {
|
||||
AssertOwnerThread();
|
||||
|
||||
|
@ -39,6 +39,7 @@ class VideoSink : public MediaSink {
|
||||
media::TimeUnit GetPosition(TimeStamp* aTimeStamp = nullptr) const override;
|
||||
|
||||
bool HasUnplayedFrames(TrackType aType) const override;
|
||||
media::TimeUnit UnplayedDuration(TrackType aType) const override;
|
||||
|
||||
void SetPlaybackRate(double aPlaybackRate) override;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user