Bug 1324629. Part 1 - remove audio callback. r?kaku
MozReview-Commit-ID: DbWwSNpYXLo
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -33,36 +33,30 @@ MediaDecoderReaderWrapper::ReadMetadata(
MOZ_ASSERT(!mShutdown);
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
&MediaDecoderReader::AsyncReadMetadata)
->Then(mOwnerThread, __func__, this,
&MediaDecoderReaderWrapper::OnMetadataRead,
&MediaDecoderReaderWrapper::OnMetadataNotRead);
}
-void
+RefPtr<MediaDecoderReaderWrapper::MediaDataPromise>
MediaDecoderReaderWrapper::RequestAudioData()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
- auto p = InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
- &MediaDecoderReader::RequestAudioData);
-
- RefPtr<MediaDecoderReaderWrapper> self = this;
- mAudioDataRequest.Begin(p->Then(mOwnerThread, __func__,
- [self] (MediaData* aAudioSample) {
- self->mAudioDataRequest.Complete();
- aAudioSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
- self->mAudioCallback.Notify(AsVariant(aAudioSample));
- },
- [self] (const MediaResult& aError) {
- self->mAudioDataRequest.Complete();
- self->mAudioCallback.Notify(AsVariant(aError));
- }));
+ int64_t startTime = StartTime().ToMicroseconds();
+ return InvokeAsync(mReader->OwnerThread(), mReader.get(),
+ __func__, &MediaDecoderReader::RequestAudioData)
+ ->Then(mOwnerThread, __func__,
+ [startTime] (MediaData* aAudio) {
+ aAudio->AdjustForStartTime(startTime);
+ },
+ [] (const MediaResult& aError) {});
}
void
MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
media::TimeUnit aTimeThreshold)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(!mShutdown);
@@ -88,23 +82,16 @@ MediaDecoderReaderWrapper::RequestVideoD
},
[self] (const MediaResult& aError) {
self->mVideoDataRequest.Complete();
self->mVideoCallback.Notify(AsVariant(aError));
}));
}
bool
-MediaDecoderReaderWrapper::IsRequestingAudioData() const
-{
- MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- return mAudioDataRequest.Exists();
-}
-
-bool
MediaDecoderReaderWrapper::IsRequestingVideoData() const
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
return mVideoDataRequest.Exists();
}
bool
MediaDecoderReaderWrapper::IsWaitingAudioData() const
@@ -176,17 +163,16 @@ MediaDecoderReaderWrapper::ReleaseResour
}
void
MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (aTracks.contains(TrackInfo::kAudioTrack)) {
- mAudioDataRequest.DisconnectIfExists();
mAudioWaitRequest.DisconnectIfExists();
}
if (aTracks.contains(TrackInfo::kVideoTrack)) {
mVideoDataRequest.DisconnectIfExists();
mVideoWaitRequest.DisconnectIfExists();
}
@@ -196,17 +182,16 @@ MediaDecoderReaderWrapper::ResetDecode(T
aTracks);
mReader->OwnerThread()->Dispatch(r.forget());
}
RefPtr<ShutdownPromise>
MediaDecoderReaderWrapper::Shutdown()
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- MOZ_ASSERT(!mAudioDataRequest.Exists());
MOZ_ASSERT(!mVideoDataRequest.Exists());
mShutdown = true;
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
&MediaDecoderReader::Shutdown);
}
void
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -33,41 +33,38 @@ class MediaDecoderReaderWrapper {
typedef MediaDecoderReader::MetadataPromise MetadataPromise;
typedef MediaDecoderReader::MediaDataPromise MediaDataPromise;
typedef MediaDecoderReader::SeekPromise SeekPromise;
typedef MediaDecoderReader::WaitForDataPromise WaitForDataPromise;
typedef MediaDecoderReader::TrackSet TrackSet;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReaderWrapper);
private:
- MediaCallbackExc<AudioCallbackData> mAudioCallback;
MediaCallbackExc<VideoCallbackData> mVideoCallback;
MediaCallbackExc<WaitCallbackData> mAudioWaitCallback;
MediaCallbackExc<WaitCallbackData> mVideoWaitCallback;
public:
MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
MediaDecoderReader* aReader);
media::TimeUnit StartTime() const;
RefPtr<MetadataPromise> ReadMetadata();
- decltype(mAudioCallback)& AudioCallback() { return mAudioCallback; }
decltype(mVideoCallback)& VideoCallback() { return mVideoCallback; }
decltype(mAudioWaitCallback)& AudioWaitCallback() { return mAudioWaitCallback; }
decltype(mVideoWaitCallback)& VideoWaitCallback() { return mVideoWaitCallback; }
// NOTE: please set callbacks before requesting audio/video data!
- void RequestAudioData();
+ RefPtr<MediaDataPromise> RequestAudioData();
void RequestVideoData(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);
// NOTE: please set callbacks before invoking WaitForData()!
void WaitForData(MediaData::Type aType);
- bool IsRequestingAudioData() const;
bool IsRequestingVideoData() const;
bool IsWaitingAudioData() const;
bool IsWaitingVideoData() const;
RefPtr<SeekPromise> Seek(const SeekTarget& aTarget);
RefPtr<ShutdownPromise> Shutdown();
void ReleaseResources();
@@ -119,17 +116,16 @@ private:
MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
const RefPtr<AbstractThread> mOwnerThread;
const RefPtr<MediaDecoderReader> mReader;
bool mShutdown = false;
Maybe<media::TimeUnit> mStartTime;
- MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest;
MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
};
} // namespace mozilla
#endif // MediaDecoderReaderWrapper_h_
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1059,19 +1059,19 @@ private:
mSeekRequest.Complete();
MOZ_ASSERT(NS_FAILED(aError), "Cancels should also disconnect mSeekRequest");
mMaster->DecodeError(aError);
}
void RequestAudioData()
{
MOZ_ASSERT(!mDoneAudioSeeking);
- MOZ_ASSERT(!Reader()->IsRequestingAudioData());
+ MOZ_ASSERT(!mMaster->IsRequestingAudioData());
MOZ_ASSERT(!Reader()->IsWaitingAudioData());
- Reader()->RequestAudioData();
+ mMaster->RequestAudioData();
}
void RequestVideoData()
{
MOZ_ASSERT(!mDoneVideoSeeking);
MOZ_ASSERT(!Reader()->IsRequestingVideoData());
MOZ_ASSERT(!Reader()->IsWaitingVideoData());
Reader()->RequestVideoData(false, media::TimeUnit());
@@ -2132,17 +2132,17 @@ BufferingState::Step()
return;
}
} else if (mMaster->OutOfDecodedAudio() || mMaster->OutOfDecodedVideo()) {
MOZ_ASSERT(Reader()->IsWaitForDataSupported(),
"Don't yet have a strategy for non-heuristic + non-WaitForData");
mMaster->DispatchDecodeTasksIfNeeded();
MOZ_ASSERT(mMaster->mMinimizePreroll ||
!mMaster->OutOfDecodedAudio() ||
- Reader()->IsRequestingAudioData() ||
+ mMaster->IsRequestingAudioData() ||
Reader()->IsWaitingAudioData());
MOZ_ASSERT(mMaster->mMinimizePreroll ||
!mMaster->OutOfDecodedVideo() ||
Reader()->IsRequestingVideoData() ||
Reader()->IsWaitingVideoData());
SLOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
"mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
mMaster->OutOfDecodedAudio(), mMaster->AudioRequestStatus(),
@@ -2182,16 +2182,17 @@ ShutdownState::Enter()
master->mCDMProxyPromise.DisconnectIfExists();
if (master->IsPlaying()) {
master->StopPlayback();
}
// To break the cycle-reference between MediaDecoderReaderWrapper and MDSM.
master->CancelMediaDecoderReaderWrapperCallback();
+ master->mAudioDataRequest.DisconnectIfExists();
master->Reset();
master->mMediaSink->Shutdown();
// Prevent dangling pointers by disconnecting the listeners.
master->mAudioQueueListener.Disconnect();
master->mVideoQueueListener.Disconnect();
@@ -2516,16 +2517,18 @@ MediaDecoderStateMachine::NeedToDecodeAu
}
void
MediaDecoderStateMachine::OnAudioDecoded(MediaData* aAudio)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aAudio);
+ mAudioDataRequest.Complete();
+
// audio->GetEndTime() is not always mono-increasing in chained ogg.
mDecodedAudioEndTime = std::max(aAudio->GetEndTime(), mDecodedAudioEndTime);
SAMPLE_LOG("OnAudioDecoded [%lld,%lld]", aAudio->mTime, aAudio->GetEndTime());
mStateObj->HandleAudioDecoded(aAudio);
}
@@ -2564,23 +2567,29 @@ void
MediaDecoderStateMachine::OnVideoPopped(const RefPtr<MediaData>& aSample)
{
MOZ_ASSERT(OnTaskQueue());
mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
DispatchVideoDecodeTaskIfNeeded();
}
void
+MediaDecoderStateMachine::OnAudioNotDecoded(const MediaResult& aError)
+{
+ MOZ_ASSERT(OnTaskQueue());
+ mAudioDataRequest.Complete();
+ OnNotDecoded(MediaData::AUDIO_DATA, aError);
+}
+
+void
MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
-
SAMPLE_LOG("OnNotDecoded (aType=%u, aError=%u)", aType, aError.Code());
-
mStateObj->HandleNotDecoded(aType, aError);
}
void
MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideo,
TimeStamp aDecodeStartTime)
{
MOZ_ASSERT(OnTaskQueue());
@@ -2691,25 +2700,16 @@ nsresult MediaDecoderStateMachine::Init(
return NS_OK;
}
void
MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
{
MOZ_ASSERT(OnTaskQueue());
- mAudioCallback = mReader->AudioCallback().Connect(
- mTaskQueue, [this] (AudioCallbackData aData) {
- if (aData.is<MediaData*>()) {
- OnAudioDecoded(aData.as<MediaData*>());
- } else {
- OnNotDecoded(MediaData::AUDIO_DATA, aData.as<MediaResult>());
- }
- });
-
mVideoCallback = mReader->VideoCallback().Connect(
mTaskQueue, [this] (VideoCallbackData aData) {
typedef Tuple<MediaData*, TimeStamp> Type;
if (aData.is<Type>()) {
auto&& v = aData.as<Type>();
OnVideoDecoded(Get<0>(v), Get<1>(v));
} else {
OnNotDecoded(MediaData::VIDEO_DATA, aData.as<MediaResult>());
@@ -2734,17 +2734,16 @@ MediaDecoderStateMachine::SetMediaDecode
}
});
}
void
MediaDecoderStateMachine::CancelMediaDecoderReaderWrapperCallback()
{
MOZ_ASSERT(OnTaskQueue());
- mAudioCallback.Disconnect();
mVideoCallback.Disconnect();
mAudioWaitCallback.Disconnect();
mVideoWaitCallback.Disconnect();
}
void MediaDecoderStateMachine::StopPlayback()
{
MOZ_ASSERT(OnTaskQueue());
@@ -3066,34 +3065,37 @@ MediaDecoderStateMachine::EnsureAudioDec
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING) {
return;
}
if (!IsAudioDecoding() ||
- mReader->IsRequestingAudioData() ||
+ IsRequestingAudioData() ||
mReader->IsWaitingAudioData()) {
return;
}
RequestAudioData();
}
void
MediaDecoderStateMachine::RequestAudioData()
{
MOZ_ASSERT(OnTaskQueue());
- MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
-
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
- mReader->RequestAudioData();
+ mAudioDataRequest.Begin(
+ mReader->RequestAudioData()->Then(
+ OwnerThread(), __func__, this,
+ &MediaDecoderStateMachine::OnAudioDecoded,
+ &MediaDecoderStateMachine::OnAudioNotDecoded)
+ );
}
void
MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded()
{
MOZ_ASSERT(OnTaskQueue());
if (!IsShutdown() && NeedToDecodeVideo()) {
EnsureVideoDecodeTaskQueued();
@@ -3373,16 +3375,17 @@ MediaDecoderStateMachine::Reset(TrackSet
mVideoCompleted = false;
VideoQueue().Reset();
}
if (aTracks.contains(TrackInfo::kAudioTrack)) {
mDecodedAudioEndTime = 0;
mAudioCompleted = false;
AudioQueue().Reset();
+ mAudioDataRequest.DisconnectIfExists();
}
mPlaybackOffset = 0;
mReader->ResetDecode(aTracks);
}
int64_t
@@ -3775,17 +3778,17 @@ MediaDecoderStateMachine::OnMediaNotSeek
{
return mReader->OnMediaNotSeekable();
}
const char*
MediaDecoderStateMachine::AudioRequestStatus() const
{
MOZ_ASSERT(OnTaskQueue());
- if (mReader->IsRequestingAudioData()) {
+ if (IsRequestingAudioData()) {
MOZ_DIAGNOSTIC_ASSERT(!mReader->IsWaitingAudioData());
return "pending";
} else if (mReader->IsWaitingAudioData()) {
return "waiting";
}
return "idle";
}
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -324,16 +324,17 @@ private:
bool IsShutdown() const;
// Returns true if we're currently playing. The decoder monitor must
// be held.
bool IsPlaying() const;
void OnAudioDecoded(MediaData* aAudio);
void OnVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStartTime);
+ void OnAudioNotDecoded(const MediaResult& aError);
void OnNotDecoded(MediaData::Type aType, const MediaResult& aError);
void OnAudioWaited(MediaData::Type aType);
void OnVideoWaited(MediaData::Type aType);
void OnNotWaited(const WaitForDataRejectValue& aRejection);
// Resets all state related to decoding and playback, emptying all buffers
// and aborting all pending operations on the decode task queue.
void Reset(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack,
@@ -469,16 +470,18 @@ protected:
// Start a task to decode audio.
// The decoder monitor must be held.
void RequestAudioData();
// Start a task to decode video.
// The decoder monitor must be held.
void RequestVideoData();
+ bool IsRequestingAudioData() const { return mAudioDataRequest.Exists(); }
+
// Re-evaluates the state and determines whether we need to dispatch
// events to run the decode, or if not whether we should set the reader
// to idle mode. This is threadsafe, and can be called from any thread.
// The decoder monitor must be held.
void DispatchDecodeTasksIfNeeded();
// Returns the "media time". This is the absolute time which the media
// playback has reached. i.e. this returns values in the range
@@ -649,21 +652,23 @@ private:
{
MOZ_ASSERT(OnTaskQueue());
return GetAmpleVideoFrames() / 2;
}
// Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
// should exist at any given moment.
- MediaEventListener mAudioCallback;
MediaEventListener mVideoCallback;
MediaEventListener mAudioWaitCallback;
MediaEventListener mVideoWaitCallback;
+ using MediaDataPromise = MediaDecoderReader::MediaDataPromise;
+ MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
+
const char* AudioRequestStatus() const;
const char* VideoRequestStatus() const;
void OnSuspendTimerResolved();
void OnSuspendTimerRejected();
// True if we shouldn't play our audio (but still write it to any capturing
// streams). When this is true, the audio thread will never start again after