зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1191696. Part 1 - Handle the promise returned by DecodedStream::StartPlayback in MDSM. r=roc.
This commit is contained in:
Родитель
a58048f446
Коммит
64e94fc75e
|
@ -4,13 +4,13 @@
|
|||
* 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/. */
|
||||
|
||||
#include "DecodedStream.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "AudioSegment.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "MediaQueue.h"
|
||||
#include "DecodedStream.h"
|
||||
#include "MediaData.h"
|
||||
#include "MediaQueue.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "SharedBuffer.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -244,14 +244,15 @@ DecodedStream::~DecodedStream()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsRefPtr<GenericPromise>
|
||||
DecodedStream::StartPlayback(int64_t aStartTime, const MediaInfo& aInfo)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mStartTime.isNothing()) {
|
||||
mStartTime.emplace(aStartTime);
|
||||
mInfo = aInfo;
|
||||
}
|
||||
MOZ_ASSERT(mStartTime.isNothing(), "playback already started.");
|
||||
mStartTime.emplace(aStartTime);
|
||||
mInfo = aInfo;
|
||||
// TODO: fix me in next patches.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DecodedStream::StopPlayback()
|
||||
|
@ -680,12 +681,17 @@ DecodedStream::AdvanceTracks()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
DecodedStream::SendData()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mStartTime.isSome(), "Must be called after StartPlayback()");
|
||||
|
||||
// Nothing to do when the stream is finished.
|
||||
if (mData->mHaveSentFinish) {
|
||||
return;
|
||||
}
|
||||
|
||||
InitTracks();
|
||||
SendAudio(mVolume, mSameOrigin);
|
||||
SendVideo(mSameOrigin);
|
||||
|
@ -698,8 +704,6 @@ DecodedStream::SendData()
|
|||
mData->mHaveSentFinish = true;
|
||||
mData->mStream->Finish();
|
||||
}
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -53,7 +54,11 @@ public:
|
|||
|
||||
// Mimic MDSM::StartAudioThread.
|
||||
// Must be called before any calls to SendData().
|
||||
void StartPlayback(int64_t aStartTime, const MediaInfo& aInfo);
|
||||
//
|
||||
// Return a promise which will be resolved when the stream is finished
|
||||
// or rejected if any error.
|
||||
nsRefPtr<GenericPromise> StartPlayback(int64_t aStartTime,
|
||||
const MediaInfo& aInfo);
|
||||
// Mimic MDSM::StopAudioThread.
|
||||
void StopPlayback();
|
||||
|
||||
|
@ -71,8 +76,7 @@ public:
|
|||
bool IsFinished() const;
|
||||
bool HasConsumers() const;
|
||||
|
||||
// Return true if stream is finished.
|
||||
bool SendData();
|
||||
void SendData();
|
||||
|
||||
protected:
|
||||
virtual ~DecodedStream();
|
||||
|
|
|
@ -376,7 +376,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(!mAudioSink, "Should've been stopped in RunStateMachine()");
|
||||
|
||||
bool finished = mDecodedStream->SendData();
|
||||
mDecodedStream->SendData();
|
||||
|
||||
const auto clockTime = GetClock();
|
||||
while (true) {
|
||||
|
@ -392,12 +392,6 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// To be consistent with AudioSink, |mAudioCompleted| is not set
|
||||
// until all samples are drained.
|
||||
if (finished && AudioQueue().GetSize() == 0) {
|
||||
mAudioCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
|
||||
|
@ -1079,12 +1073,7 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
|
|||
MOZ_ASSERT(IsPlaying());
|
||||
|
||||
StartAudioThread();
|
||||
|
||||
// Tell DecodedStream to start playback with specified start time and media
|
||||
// info. This is consistent with how we create AudioSink in StartAudioThread().
|
||||
if (mAudioCaptured) {
|
||||
mDecodedStream->StartPlayback(GetMediaTime(), mInfo);
|
||||
}
|
||||
StartDecodedStream();
|
||||
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
}
|
||||
|
@ -1792,6 +1781,32 @@ MediaDecoderStateMachine::StartAudioThread()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::StopDecodedStream()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
mDecodedStream->StopPlayback();
|
||||
mDecodedStreamPromise.DisconnectIfExists();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::StartDecodedStream()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
// Tell DecodedStream to start playback with specified start time and media
|
||||
// info. This is consistent with how we create AudioSink in StartAudioThread().
|
||||
if (mAudioCaptured && !mDecodedStreamPromise.Exists()) {
|
||||
mDecodedStreamPromise.Begin(
|
||||
mDecodedStream->StartPlayback(GetMediaTime(), mInfo)->Then(
|
||||
OwnerThread(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnDecodedStreamFinish,
|
||||
&MediaDecoderStateMachine::OnDecodedStreamError));
|
||||
}
|
||||
}
|
||||
|
||||
int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
@ -2395,7 +2410,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
|||
// Stop audio sink after call to AudioEndTime() above, otherwise it will
|
||||
// return an incorrect value due to a null mAudioSink.
|
||||
StopAudioThread();
|
||||
mDecodedStream->StopPlayback();
|
||||
StopDecodedStream();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2425,7 +2440,7 @@ MediaDecoderStateMachine::Reset()
|
|||
// outside of the decoder monitor while we are clearing the queue and causes
|
||||
// crash for no samples to be popped.
|
||||
StopAudioThread();
|
||||
mDecodedStream->StopPlayback();
|
||||
StopDecodedStream();
|
||||
|
||||
mVideoFrameEndTime = -1;
|
||||
mDecodedVideoEndTime = -1;
|
||||
|
@ -3076,6 +3091,32 @@ void MediaDecoderStateMachine::OnAudioSinkError()
|
|||
DecodeError();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::OnDecodedStreamFinish()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(mAudioCaptured, "Audio should be captured.");
|
||||
|
||||
mDecodedStreamPromise.Complete();
|
||||
if (mInfo.HasAudio()) {
|
||||
mAudioCompleted = true;
|
||||
}
|
||||
// To notify PlaybackEnded as soon as possible.
|
||||
ScheduleStateMachine();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::OnDecodedStreamError()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(mAudioCaptured, "Audio should be captured.");
|
||||
|
||||
mDecodedStreamPromise.Complete();
|
||||
DecodeError();
|
||||
}
|
||||
|
||||
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
@ -3099,7 +3140,7 @@ void MediaDecoderStateMachine::DispatchAudioCaptured()
|
|||
// Start DecodedStream if we are already playing. Otherwise it will be
|
||||
// handled in MaybeStartPlayback().
|
||||
if (self->IsPlaying()) {
|
||||
self->mDecodedStream->StartPlayback(self->GetMediaTime(), self->mInfo);
|
||||
self->StartDecodedStream();
|
||||
}
|
||||
self->ScheduleStateMachine();
|
||||
}
|
||||
|
@ -3115,7 +3156,8 @@ void MediaDecoderStateMachine::DispatchAudioUncaptured()
|
|||
MOZ_ASSERT(self->OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
if (self->mAudioCaptured) {
|
||||
// Start again the audio sink
|
||||
self->StopDecodedStream();
|
||||
// Start again the audio sink.
|
||||
self->mAudioCaptured = false;
|
||||
if (self->IsPlaying()) {
|
||||
self->StartAudioThread();
|
||||
|
|
|
@ -518,6 +518,10 @@ protected:
|
|||
// one lock count. Called on the state machine thread.
|
||||
void StartAudioThread();
|
||||
|
||||
void StopDecodedStream();
|
||||
|
||||
void StartDecodedStream();
|
||||
|
||||
// Notification method invoked when mPlayState changes.
|
||||
void PlayStateChanged();
|
||||
|
||||
|
@ -670,6 +674,10 @@ private:
|
|||
// Rejected by the AudioSink to signal errors.
|
||||
void OnAudioSinkError();
|
||||
|
||||
void OnDecodedStreamFinish();
|
||||
|
||||
void OnDecodedStreamError();
|
||||
|
||||
// Return true if the video decoder's decode speed can not catch up the
|
||||
// play time.
|
||||
bool NeedToSkipToNextKeyframe();
|
||||
|
@ -1284,6 +1292,7 @@ private:
|
|||
nsRefPtr<MediaResource> mResource;
|
||||
|
||||
MozPromiseRequestHolder<GenericPromise> mAudioSinkPromise;
|
||||
MozPromiseRequestHolder<GenericPromise> mDecodedStreamPromise;
|
||||
|
||||
MediaEventListener mAudioQueueListener;
|
||||
MediaEventListener mVideoQueueListener;
|
||||
|
|
Загрузка…
Ссылка в новой задаче